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

Commit f81c1d16 authored by Wale Ogunwale's avatar Wale Ogunwale
Browse files

Fixed some activity visiblility issues in picture-in-picutre mode

- Previously when don't re-launch an activity due to configuration
change if the activity is currently pausing. And, once the pause is
complete we destroy the activity. This logic is based on the assumption
that all activities are fullscreen and pausing is the same as stopping
which means the activity is no longer visible and can be destoried.
This assumption is not true in multi-window mode where you can have
visible activities in the paused state.
We now relaunch the activity once it is done pausing.

- Previously we set the return type of the top task in a stack to home
if the previously focused stack is home while add the task to the stack.
This logic is based on the assumption that the focus stack is the front
stack which isn't true for pinned stack. This causes an activity behind
the top translucent activity in the pinned stack to be marked as invisible
and stopped since the top task is over the home task so we should be
showing the home task behind it and not other tasks in the stack.
We now set the return to task type to application type for task added to
the pinned stack.

Bug: 26273032
Change-Id: I0ffac81f46c57e2d0d900db3417381f059aee7ea
parent f2c4be29
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -592,6 +592,14 @@ public class ActivityManager {
        public static boolean isAlwaysOnTop(int stackId) {
            return stackId == PINNED_STACK_ID;
        }

        /**
         * Returns true if the top task in the task is allowed to return home when finished and
         * there are other tasks in the stack.
         */
        public static boolean allowTopTaskToReturnHome(int stackId) {
            return stackId != PINNED_STACK_ID;
        }
    }

    /**
+8 −6
Original line number Diff line number Diff line
@@ -171,7 +171,9 @@ final class ActivityRecord {
    boolean stopped;        // is activity pause finished?
    boolean delayedResume;  // not yet resumed because of stopped app switches?
    boolean finishing;      // activity in pending finish list?
    boolean configDestroy;  // need to destroy due to config change?
    boolean deferRelaunchUntilPaused;   // relaunch of activity is being deferred until pause is
                                        // completed
    boolean preserveWindowOnDeferredRelaunch; // activity windows are preserved on deferred relaunch
    int configChangeFlags;  // which config values have changed
    boolean keysPaused;     // has key dispatching been paused for it?
    int launchMode;         // the launch mode activity attribute.
@@ -184,9 +186,9 @@ final class ActivityRecord {
    boolean immersive;      // immersive mode (don't interrupt if possible)
    boolean forceNewConfig; // force re-create with new config next time
    int launchCount;        // count of launches since last state
    long lastLaunchTime;    // time of last lauch of this activity
    long lastLaunchTime;    // time of last launch of this activity
    boolean isVrActivity;   // is the activity running in VR mode?
    ArrayList<ActivityContainer> mChildContainers = new ArrayList<ActivityContainer>();
    ArrayList<ActivityContainer> mChildContainers = new ArrayList<>();

    String stringName;      // for caching of toString().

@@ -341,8 +343,8 @@ final class ActivityRecord {
                    else TimeUtils.formatDuration(lastVisibleTime, now, pw);
                    pw.println();
        }
        if (configDestroy || configChangeFlags != 0) {
            pw.print(prefix); pw.print("configDestroy="); pw.print(configDestroy);
        if (deferRelaunchUntilPaused || configChangeFlags != 0) {
            pw.print(prefix); pw.print("deferRelaunchUntilPaused="); pw.print(deferRelaunchUntilPaused);
                    pw.print(" configChangeFlags=");
                    pw.println(Integer.toHexString(configChangeFlags));
        }
@@ -551,7 +553,7 @@ final class ActivityRecord {
        stopped = false;
        delayedResume = false;
        finishing = false;
        configDestroy = false;
        deferRelaunchUntilPaused = false;
        keysPaused = false;
        inHistory = false;
        visible = false;
+27 −31
Original line number Diff line number Diff line
@@ -1088,7 +1088,7 @@ final class ActivityStack {
            if (r.finishing) {
                r.clearOptionsLocked();
            } else {
                if (r.configDestroy) {
                if (r.deferRelaunchUntilPaused) {
                    destroyActivityLocked(r, true, "stop-config");
                    mStackSupervisor.resumeFocusedStackTopActivityLocked();
                } else {
@@ -1114,14 +1114,11 @@ final class ActivityStack {
                    if (DEBUG_SWITCH || DEBUG_PAUSE) Slog.v(TAG_PAUSE,
                            "Complete pause, no longer waiting: " + prev);
                }
                if (prev.configDestroy) {
                    // The previous is being paused because the configuration
                    // is changing, which means it is actually stopping...
                    // To juggle the fact that we are also starting a new
                    // instance right now, we need to first completely stop
                    // the current instance before starting the new one.
                    if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Destroying after pause: " + prev);
                    destroyActivityLocked(prev, true, "pause-config");
                if (prev.deferRelaunchUntilPaused) {
                    // Complete the deferred relaunch that was waiting for pause to complete.
                    if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Re-launching after pause: " + prev);
                    relaunchActivityLocked(prev, prev.configChangeFlags, false,
                            prev.preserveWindowOnDeferredRelaunch);
                } else if (wasStopping) {
                    // We are also stopping, the stop request must have gone soon after the pause.
                    // We can't clobber it, because the stop confirmation will not be handled.
@@ -2318,11 +2315,12 @@ final class ActivityStack {
            ActivityStack lastStack = mStackSupervisor.getLastStack();
            final boolean fromHome = lastStack.isHomeStack();
            if (!isHomeStack() && (fromHome || topTask() != task)) {
                task.setTaskToReturnTo(fromHome
                        ? lastStack.topTask() == null
                                ? HOME_ACTIVITY_TYPE
                                : lastStack.topTask().taskType
                        : APPLICATION_ACTIVITY_TYPE);
                int returnToType = APPLICATION_ACTIVITY_TYPE;
                if (fromHome && StackId.allowTopTaskToReturnHome(mStackId)) {
                    returnToType = lastStack.topTask() == null
                            ? HOME_ACTIVITY_TYPE : lastStack.topTask().taskType;
                }
                task.setTaskToReturnTo(returnToType);
            }
        } else {
            task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
@@ -2972,7 +2970,7 @@ final class ActivityStack {
                r.stopped = true;
                if (DEBUG_STATES) Slog.v(TAG_STATES, "Stop failed; moving to STOPPED: " + r);
                r.state = ActivityState.STOPPED;
                if (r.configDestroy) {
                if (r.deferRelaunchUntilPaused) {
                    destroyActivityLocked(r, true, "stop-except");
                }
            }
@@ -3403,7 +3401,7 @@ final class ActivityStack {
        }
        mService.resetFocusedActivityIfNeededLocked(r);

        r.configDestroy = false;
        r.deferRelaunchUntilPaused = false;
        r.frozenBeforeDestroy = false;

        if (setState) {
@@ -4175,38 +4173,33 @@ final class ActivityStack {
            r.configChangeFlags |= changes;
            r.startFreezingScreenLocked(r.app, globalChanges);
            r.forceNewConfig = false;
            preserveWindow &= isResizeOnlyChange(changes);
            if (r.app == null || r.app.thread == null) {
                if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
                        "Config is destroying non-running " + r);
                destroyActivityLocked(r, true, "config");
            } else if (r.state == ActivityState.PAUSING) {
                // A little annoying: we are waiting for this activity to
                // finish pausing.  Let's not do anything now, but just
                // flag that it needs to be restarted when done pausing.
                // A little annoying: we are waiting for this activity to finish pausing. Let's not
                // do anything now, but just flag that it needs to be restarted when done pausing.
                if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
                        "Config is skipping already pausing " + r);
                r.configDestroy = true;
                r.deferRelaunchUntilPaused = true;
                r.preserveWindowOnDeferredRelaunch = preserveWindow;
                return true;
            } else if (r.state == ActivityState.RESUMED) {
                // Try to optimize this case: the configuration is changing
                // and we need to restart the top, resumed activity.
                // Instead of doing the normal handshaking, just say
                // Try to optimize this case: the configuration is changing and we need to restart
                // the top, resumed activity. Instead of doing the normal handshaking, just say
                // "restart!".
                if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
                        "Config is relaunching resumed " + r);
                relaunchActivityLocked(r, r.configChangeFlags, true,
                        preserveWindow && isResizeOnlyChange(changes));
                r.configChangeFlags = 0;
                relaunchActivityLocked(r, r.configChangeFlags, true, preserveWindow);
            } else {
                if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
                        "Config is relaunching non-resumed " + r);
                relaunchActivityLocked(r, r.configChangeFlags, false,
                        preserveWindow && isResizeOnlyChange(changes));
                r.configChangeFlags = 0;
                relaunchActivityLocked(r, r.configChangeFlags, false, preserveWindow);
            }

            // All done...  tell the caller we weren't able to keep this
            // activity around.
            // All done...  tell the caller we weren't able to keep this activity around.
            return false;
        }

@@ -4298,6 +4291,7 @@ final class ActivityStack {
    private void relaunchActivityLocked(
            ActivityRecord r, int changes, boolean andResume, boolean preserveWindow) {
        if (mService.mSuppressResizeConfigChanges && preserveWindow) {
            r.configChangeFlags = 0;
            return;
        }

@@ -4341,6 +4335,8 @@ final class ActivityStack {
            mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
            r.state = ActivityState.PAUSED;
        }

        r.configChangeFlags = 0;
    }

    boolean willActivityBeVisibleLocked(IBinder token) {
+3 −3
Original line number Diff line number Diff line
@@ -2722,7 +2722,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
        for (int activityNdx = mStoppingActivities.size() - 1; activityNdx >= 0; --activityNdx) {
            ActivityRecord s = mStoppingActivities.get(activityNdx);
            final boolean waitingVisible = mWaitingVisibleActivities.contains(s);
            if (DEBUG_ALL) Slog.v(TAG, "Stopping " + s + ": nowVisible=" + nowVisible
            if (DEBUG_STATES) Slog.v(TAG, "Stopping " + s + ": nowVisible=" + nowVisible
                    + " waitingVisible=" + waitingVisible + " finishing=" + s.finishing);
            if (waitingVisible && nowVisible) {
                mWaitingVisibleActivities.remove(s);
@@ -2732,12 +2732,12 @@ public final class ActivityStackSupervisor implements DisplayListener {
                    // so get rid of it.  Otherwise, we need to go through the
                    // normal flow and hide it once we determine that it is
                    // hidden by the activities in front of it.
                    if (DEBUG_ALL) Slog.v(TAG, "Before stopping, can hide: " + s);
                    if (DEBUG_STATES) Slog.v(TAG, "Before stopping, can hide: " + s);
                    mWindowManager.setAppVisibility(s.appToken, false);
                }
            }
            if ((!waitingVisible || mService.isSleepingOrShuttingDown()) && remove) {
                if (DEBUG_ALL) Slog.v(TAG, "Ready to stop: " + s);
                if (DEBUG_STATES) Slog.v(TAG, "Ready to stop: " + s);
                if (stops == null) {
                    stops = new ArrayList<>();
                }