Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d070775c authored by Winson Chung's avatar Winson Chung
Browse files

Add activity options flag to force launching an activity in a new task

- This is to work around issues where the caller (ie. RemoteViews) is
  launching a provided pending intent that is immutable and still needs
  to ensure that it is launched in a separate task.

Bug: 112508020
Test: Launch an immutable pending intent from a widget and ensure it
      launches in a new task as expected

Change-Id: I70c318674da15a78418548ee719cb1257f899ac6
parent 1780672b
Loading
Loading
Loading
Loading
+28 −0
Original line number Diff line number Diff line
@@ -194,6 +194,13 @@ public class ActivityOptions {
     */
    private static final String KEY_LAUNCH_TASK_ID = "android.activity.launchTaskId";

    /**
     * See {@link #setPendingIntentLaunchFlags(int)}
     * @hide
     */
    private static final String KEY_PENDING_INTENT_LAUNCH_FLAGS =
            "android.activity.pendingIntentLaunchFlags";

    /**
     * See {@link #setTaskOverlay}.
     * @hide
@@ -309,6 +316,7 @@ public class ActivityOptions {
    @WindowConfiguration.ActivityType
    private int mLaunchActivityType = ACTIVITY_TYPE_UNDEFINED;
    private int mLaunchTaskId = -1;
    private int mPendingIntentLaunchFlags;
    private int mSplitScreenCreateMode = SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT;
    private boolean mLockTaskMode = false;
    private boolean mDisallowEnterPictureInPictureWhileLaunching;
@@ -932,6 +940,7 @@ public class ActivityOptions {
        mLaunchWindowingMode = opts.getInt(KEY_LAUNCH_WINDOWING_MODE, WINDOWING_MODE_UNDEFINED);
        mLaunchActivityType = opts.getInt(KEY_LAUNCH_ACTIVITY_TYPE, ACTIVITY_TYPE_UNDEFINED);
        mLaunchTaskId = opts.getInt(KEY_LAUNCH_TASK_ID, -1);
        mPendingIntentLaunchFlags = opts.getInt(KEY_PENDING_INTENT_LAUNCH_FLAGS, 0);
        mTaskOverlay = opts.getBoolean(KEY_TASK_OVERLAY, false);
        mTaskOverlayCanResume = opts.getBoolean(KEY_TASK_OVERLAY_CAN_RESUME, false);
        mAvoidMoveToFront = opts.getBoolean(KEY_AVOID_MOVE_TO_FRONT, false);
@@ -1232,6 +1241,22 @@ public class ActivityOptions {
        return mLaunchTaskId;
    }

    /**
     * Specifies intent flags to be applied for any activity started from a PendingIntent.
     *
     * @hide
     */
    public void setPendingIntentLaunchFlags(@android.content.Intent.Flags int flags) {
        mPendingIntentLaunchFlags = flags;
    }

    /**
     * @hide
     */
    public int getPendingIntentLaunchFlags() {
        return mPendingIntentLaunchFlags;
    }

    /**
     * Set's whether the activity launched with this option should be a task overlay. That is the
     * activity will always be the top activity of the task.  If {@param canResume} is true, then
@@ -1463,6 +1488,9 @@ public class ActivityOptions {
        if (mLaunchTaskId != -1) {
            b.putInt(KEY_LAUNCH_TASK_ID, mLaunchTaskId);
        }
        if (mPendingIntentLaunchFlags != 0) {
            b.putInt(KEY_PENDING_INTENT_LAUNCH_FLAGS, mPendingIntentLaunchFlags);
        }
        if (mTaskOverlay) {
            b.putBoolean(KEY_TASK_OVERLAY, mTaskOverlay);
        }
+11 −4
Original line number Diff line number Diff line
@@ -368,10 +368,12 @@ public class RemoteViews implements Parcelable, Filter {
                // TODO: Unregister this handler if PendingIntent.FLAG_ONE_SHOT?
                Context context = view.getContext();
                ActivityOptions opts = getActivityOptions(context);
                // The NEW_TASK flags are applied through the activity options and not as a part of
                // the call to startIntentSender() to ensure that they are consistently applied to
                // both mutable and immutable PendingIntents.
                context.startIntentSender(
                        pendingIntent.getIntentSender(), fillInIntent,
                        Intent.FLAG_ACTIVITY_NEW_TASK,
                        Intent.FLAG_ACTIVITY_NEW_TASK, 0, opts.toBundle());
                        0, 0, 0, opts.toBundle());
            } catch (IntentSender.SendIntentException e) {
                android.util.Log.e(LOG_TAG, "Cannot send pending intent: ", e);
                return false;
@@ -399,10 +401,15 @@ public class RemoteViews implements Parcelable, Filter {
                windowAnimationStyle.recycle();

                if (enterAnimationId != 0) {
                    return ActivityOptions.makeCustomAnimation(context, enterAnimationId, 0);
                    final ActivityOptions opts = ActivityOptions.makeCustomAnimation(context,
                            enterAnimationId, 0);
                    opts.setPendingIntentLaunchFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    return opts;
                }
            }
            return ActivityOptions.makeBasic();
            final ActivityOptions opts = ActivityOptions.makeBasic();
            opts.setPendingIntentLaunchFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            return opts;
        }
    }

+9 −2
Original line number Diff line number Diff line
@@ -288,12 +288,19 @@ public final class PendingIntentRecord extends IIntentSender.Stub {
                resolvedType = key.requestResolvedType;
            }

            // Apply any launch flags from the ActivityOptions. This is to ensure that the caller
            // can specify a consistent launch mode even if the PendingIntent is immutable
            final ActivityOptions opts = ActivityOptions.fromBundle(options);
            if (opts != null) {
                finalIntent.addFlags(opts.getPendingIntentLaunchFlags());
            }

            // Extract options before clearing calling identity
            mergedOptions = key.options;
            if (mergedOptions == null) {
                mergedOptions = SafeActivityOptions.fromBundle(options);
                mergedOptions = new SafeActivityOptions(opts);
            } else {
                mergedOptions.setCallerOptions(ActivityOptions.fromBundle(options));
                mergedOptions.setCallerOptions(opts);
            }

            if (whitelistDuration != null) {