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

Commit 3b23239d authored by Wale Ogunwale's avatar Wale Ogunwale
Browse files

Fixed bugs with starting windows when displayng forcedResized activity

- Added ActivityOption to mark a starting activity as a taskOverlay
activity. That is the activity will always be the top activity of the
task and doesn't cause the task to be moved to the front when it is added.
- Only set the starting window state of the ActivityRecord to shown if
window manager actually showed the starting window for the activity.
Avoids incorrectly trying to remove starting window for an activity that
didn't show any.
- When starting additional activity in a task, transfer the starting
window from the top most activity with a starting window. It is possible
the top most window does have a starting window like in the case of the
forcedResized activity.
- Only ensure visiblity of an activity we are starting in a task whose top
activity is a task overlay. They need to start in the visible-paused state
and not the resumed state which just causes extra churn in the system.
- Always add additional starting activities in a task with an overlay
activity below the overlay activity.

Bug: 28751186
Change-Id: I3624a4313ae9c406d42c67a3537f67ad685791af
parent c4033e7c
Loading
Loading
Loading
Loading
+12 −12
Original line number Diff line number Diff line
@@ -161,10 +161,10 @@ public class ActivityOptions {
    private static final String KEY_LAUNCH_TASK_ID = "android.activity.launchTaskId";

    /**
     * See {@link #setAvoidMoveToFront}.
     * See {@link #setTaskOverlay}.
     * @hide
     */
    private static final String KEY_DONT_MOVE_TO_FRONT = "android.activity.dontMoveToFront";
    private static final String KEY_TASK_OVERLAY = "android.activity.taskOverlay";

    /**
     * Where the docked stack should be positioned.
@@ -239,7 +239,7 @@ public class ActivityOptions {
    private int mLaunchStackId = INVALID_STACK_ID;
    private int mLaunchTaskId = -1;
    private int mDockCreateMode = DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
    private boolean mAvoidMoveToFront;
    private boolean mTaskOverlay;
    private AppTransitionAnimationSpec mAnimSpecs[];

    /**
@@ -782,7 +782,7 @@ public class ActivityOptions {
        }
        mLaunchStackId = opts.getInt(KEY_LAUNCH_STACK_ID, INVALID_STACK_ID);
        mLaunchTaskId = opts.getInt(KEY_LAUNCH_TASK_ID, -1);
        mAvoidMoveToFront = opts.getBoolean(KEY_DONT_MOVE_TO_FRONT, false);
        mTaskOverlay = opts.getBoolean(KEY_TASK_OVERLAY, false);
        mDockCreateMode = opts.getInt(KEY_DOCK_CREATE_MODE, DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT);
        if (opts.containsKey(KEY_ANIM_SPECS)) {
            Parcelable[] specs = opts.getParcelableArray(KEY_ANIM_SPECS);
@@ -961,20 +961,20 @@ public class ActivityOptions {
    }

    /**
     * Set's whether the task should be moved to the front. This is different from
     * {@link #getLaunchTaskBehind()} as we don't want to have an animation at all when launching
     * an activity that shouldn't be moved to the front.
     * 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 and doesn't cause the task to be moved
     * to the front when it is added.
     * @hide
     */
    public void setAvoidMoveToFront(boolean avoidMoveToFront) {
        mAvoidMoveToFront = avoidMoveToFront;
    public void setTaskOverlay(boolean taskOverlay) {
        mTaskOverlay = taskOverlay;
    }

    /**
     * @hide
     */
    public boolean getAvoidMoveToFront() {
        return mAvoidMoveToFront;
    public boolean getTaskOverlay() {
        return mTaskOverlay;
    }

    /** @hide */
@@ -1130,7 +1130,7 @@ public class ActivityOptions {
        }
        b.putInt(KEY_LAUNCH_STACK_ID, mLaunchStackId);
        b.putInt(KEY_LAUNCH_TASK_ID, mLaunchTaskId);
        b.putBoolean(KEY_DONT_MOVE_TO_FRONT, mAvoidMoveToFront);
        b.putBoolean(KEY_TASK_OVERLAY, mTaskOverlay);
        b.putInt(KEY_DOCK_CREATE_MODE, mDockCreateMode);
        if (mAnimSpecs != null) {
            b.putParcelableArray(KEY_ANIM_SPECS, mAnimSpecs);
+6 −1
Original line number Diff line number Diff line
@@ -163,7 +163,12 @@ interface IWindowManager
            IAppTransitionAnimationSpecsFuture specsFuture, IRemoteCallback startedCallback,
            boolean scaleUp);
    void executeAppTransition();
    void setAppStartingWindow(IBinder token, String pkg, int theme,

    /**
     * Called to set the starting window for the input token and returns true if the starting
     * window was set for the token.
     */
    boolean setAppStartingWindow(IBinder token, String pkg, int theme,
            in CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes,
            int icon, int logo, int windowFlags, IBinder transferFrom, boolean createIfNeeded);
    void setAppVisibility(IBinder token, boolean visible);
+1 −1
Original line number Diff line number Diff line
@@ -111,7 +111,7 @@ public class ForcedResizableInfoActivityController {
            Intent intent = new Intent(mContext, ForcedResizableInfoActivity.class);
            ActivityOptions options = ActivityOptions.makeBasic();
            options.setLaunchTaskId(mPendingTaskIds.valueAt(i));
            options.setAvoidMoveToFront(true);
            options.setTaskOverlay(true);
            mContext.startActivity(intent, options.toBundle());
        }
        mPendingTaskIds.clear();
+12 −0
Original line number Diff line number Diff line
@@ -202,6 +202,7 @@ final class ActivityRecord {
    static final int STARTING_WINDOW_SHOWN = 1;
    static final int STARTING_WINDOW_REMOVED = 2;
    int mStartingWindowState = STARTING_WINDOW_NOT_SHOWN;
    boolean mTaskOverlay = false; // Task is always on-top of other activities in the task.

    boolean mUpdateTaskThumbnailWhenHidden;
    ActivityContainer mInitialActivityContainer;
@@ -1390,6 +1391,17 @@ final class ActivityRecord {
        pendingVoiceInteractionStart = false;
    }

    void showStartingWindow(ActivityRecord prev, boolean createIfNeeded) {
        final CompatibilityInfo compatInfo =
                service.compatibilityInfoForPackageLocked(info.applicationInfo);
        final boolean shown = service.mWindowManager.setAppStartingWindow(
                appToken, packageName, theme, compatInfo, nonLocalizedLabel, labelRes, icon,
                logo, windowFlags, prev != null ? prev.appToken : null, createIfNeeded);
        if (shown) {
            mStartingWindowState = STARTING_WINDOW_SHOWN;
        }
    }

    void saveToXml(XmlSerializer out) throws IOException, XmlPullParserException {
        out.attribute(null, ATTR_ID, String.valueOf(createTime));
        out.attribute(null, ATTR_LAUNCHEDFROMUID, String.valueOf(launchedFromUid));
+4 −22
Original line number Diff line number Diff line
@@ -2459,12 +2459,7 @@ final class ActivityStack {
                    next.hasBeenLaunched = true;
                } else  if (SHOW_APP_STARTING_PREVIEW && lastStack != null &&
                        mStackSupervisor.isFrontStack(lastStack)) {
                    mWindowManager.setAppStartingWindow(
                            next.appToken, next.packageName, next.theme,
                            mService.compatibilityInfoForPackageLocked(next.info.applicationInfo),
                            next.nonLocalizedLabel, next.labelRes, next.icon, next.logo,
                            next.windowFlags, null, true);
                    next.mStartingWindowState = STARTING_WINDOW_SHOWN;
                    next.showStartingWindow(null, true);
                }
                mStackSupervisor.startSpecificActivityLocked(next, true, false);
                if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
@@ -2490,14 +2485,7 @@ final class ActivityStack {
                next.hasBeenLaunched = true;
            } else {
                if (SHOW_APP_STARTING_PREVIEW) {
                    mWindowManager.setAppStartingWindow(
                            next.appToken, next.packageName, next.theme,
                            mService.compatibilityInfoForPackageLocked(
                                    next.info.applicationInfo),
                            next.nonLocalizedLabel,
                            next.labelRes, next.icon, next.logo, next.windowFlags,
                            null, true);
                    next.mStartingWindowState = STARTING_WINDOW_SHOWN;
                    next.showStartingWindow(null, true);
                }
                if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Restarting: " + next);
            }
@@ -2712,7 +2700,7 @@ final class ActivityStack {
                // "has the same starting icon" as the next one.  This allows the
                // window manager to keep the previous window it had previously
                // created, if it still had one.
                ActivityRecord prev = mResumedActivity;
                ActivityRecord prev = r.task.topRunningActivityWithStartingWindowLocked();
                if (prev != null) {
                    // We don't want to reuse the previous starting preview if:
                    // (1) The current activity is in a different task.
@@ -2724,13 +2712,7 @@ final class ActivityStack {
                        prev = null;
                    }
                }
                mWindowManager.setAppStartingWindow(
                        r.appToken, r.packageName, r.theme,
                        mService.compatibilityInfoForPackageLocked(
                                r.info.applicationInfo), r.nonLocalizedLabel,
                        r.labelRes, r.icon, r.logo, r.windowFlags,
                        prev != null ? prev.appToken : null, showStartingIcon);
                r.mStartingWindowState = STARTING_WINDOW_SHOWN;
                r.showStartingWindow(prev, showStartingIcon);
            }
        } else {
            // If this is the first activity, don't do any fancy animations,
Loading