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

Commit c4ab62a4 authored by Bryce Lee's avatar Bryce Lee
Browse files

Couple mResumedActivity to Activity lifecycle.

mResumedActivity is a cached reference to the currently resumed
activity in a stack. Previously, this value was set on demand at
various points in the code. This can lead to discord with the
ActivityRecord if the activity updates state without the containing
ActivityStack being directly aware of the change.

This changelist addresses the issue by placing mResumedActivity
behind an accessor. A callback path has been added from
ActivityRecord to the ActivityStack, signaling when the activity's
state has changed. The stack can then update the state accordingly.

Test: atest FrameworksServicesTests:com.android.server.am.ActivityStackTests#testResumedActivity
Bug: 66344012
Fixes: 74118620
Change-Id: If950fd4c41f044ec67722ccc5b1d631cead70bce
parent 999e97f4
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -3364,7 +3364,8 @@ public class ActivityManagerService extends IActivityManager.Stub
    /**
     * Update AMS states when an activity is resumed. This should only be called by
     * {@link ActivityStack#setResumedActivityLocked} when an activity is resumed.
     * {@link ActivityStack#onActivityStateChanged(ActivityRecord, ActivityState, String)} when an
     * activity is resumed.
     */
    @GuardedBy("this")
    void setResumedActivityUncheckLocked(ActivityRecord r, String reason) {
+7 −3
Original line number Diff line number Diff line
@@ -1636,7 +1636,11 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo

        mRecentTransitions.add(new StateTransition(prev, state, reason));

        mState = state;
        final TaskRecord parent = getTask();

        if (parent != null) {
            parent.onActivityStateChanged(this, state, reason);
        }

        if (isState(DESTROYING, DESTROYED)) {
            makeFinishingLocked();
@@ -2111,7 +2115,7 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
        if (mStackSupervisor.mActivitiesWaitingForVisibleActivity.contains(this) || stopped) {
            final ActivityStack stack = mStackSupervisor.getFocusedStack();
            // Try to use the one which is closest to top.
            ActivityRecord r = stack.mResumedActivity;
            ActivityRecord r = stack.getResumedActivity();
            if (r == null) {
                r = stack.mPausingActivity;
            }
@@ -2208,7 +2212,7 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
            return false;
        }
        final ActivityStack stack = getStack();
        if (stack == null || this == stack.mResumedActivity || this == stack.mPausingActivity
        if (stack == null || this == stack.getResumedActivity() || this == stack.mPausingActivity
                || !haveState || !stopped) {
            // We're not ready for this kind of thing.
            return false;
+43 −17
Original line number Diff line number Diff line
@@ -472,6 +472,28 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
        return mWindowContainerController;
    }

    /**
     * This should be called when an activity in a child task changes state. This should only
     * be called from
     * {@link TaskRecord#onActivityStateChanged(ActivityRecord, ActivityState, String)}.
     * @param record The {@link ActivityRecord} whose state has changed.
     * @param state The new state.
     * @param reason The reason for the change.
     */
    void onActivityStateChanged(ActivityRecord record, ActivityState state, String reason) {
        if (record == mResumedActivity && state != RESUMED) {
            clearResumedActivity(reason + " - onActivityStateChanged");
        }

        if (state == RESUMED) {
            if (DEBUG_STACK) Slog.v(TAG_STACK, "set resumed activity to:" + record + " reason:"
                    + reason);
            mResumedActivity = record;
            mService.setResumedActivityUncheckLocked(record, reason);
            mStackSupervisor.mRecentTasks.add(record.getTask());
        }
    }

    @Override
    public void onConfigurationChanged(Configuration newParentConfig) {
        final int prevWindowingMode = getWindowingMode();
@@ -1226,7 +1248,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
    void minimalResumeActivityLocked(ActivityRecord r) {
        if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to RESUMED: " + r + " (starting new instance)"
                + " callers=" + Debug.getCallers(5));
        setResumedActivityLocked(r, "minimalResumeActivityLocked");
        r.setState(RESUMED, "minimalResumeActivityLocked");
        r.completeResumeLocked();
        setLaunchTime(r);
        if (DEBUG_SAVED_STATE) Slog.i(TAG_SAVED_STATE,
@@ -1451,7 +1473,6 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai

        if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to PAUSING: " + prev);
        else if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Start pausing: " + prev);
        mResumedActivity = null;
        mPausingActivity = prev;
        mLastPausedActivity = prev;
        mLastNoHistoryActivity = (prev.intent.getFlags() & Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
@@ -2279,13 +2300,21 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
        return result;
    }

    void setResumedActivityLocked(ActivityRecord r, String reason) {
        // TODO: move mResumedActivity to stack supervisor,
        // there should only be 1 global copy of resumed activity.
        mResumedActivity = r;
        r.setState(RESUMED, "setResumedActivityLocked");
        mService.setResumedActivityUncheckLocked(r, reason);
        mStackSupervisor.mRecentTasks.add(r.getTask());
    /**
     * Returns the currently resumed activity.
     */
    protected ActivityRecord getResumedActivity() {
        return mResumedActivity;
    }

    /**
     * Clears reference to currently resumed activity.
     */
    private void clearResumedActivity(String reason) {
        if (DEBUG_STACK) Slog.d(TAG_STACK, "clearResumedActivity: " + mResumedActivity + " reason:"
                + reason);

        mResumedActivity = null;
    }

    @GuardedBy("mService")
@@ -2574,7 +2603,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
                if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to RESUMED: " + next
                        + " (in existing)");

                setResumedActivityLocked(next, "resumeTopActivityInnerLocked");
                next.setState(RESUMED, "resumeTopActivityInnerLocked");

                mService.updateLruProcessLocked(next.app, true, null);
                updateLRUListLocked(next);
@@ -2676,7 +2705,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
                            + lastState + ": " + next);
                    next.setState(lastState, "resumeTopActivityInnerLocked");
                    if (lastStack != null) {
                        lastStack.mResumedActivity = lastResumedActivity;
                        lastResumedActivity.setState(RESUMED, "resumeTopActivityInnerLocked");
                    }
                    Slog.i(TAG, "Restarting because process died: " + next);
                    if (!next.hasBeenLaunched) {
@@ -3776,9 +3805,6 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
        mStackSupervisor.mStoppingActivities.remove(r);
        mStackSupervisor.mGoingToSleepActivities.remove(r);
        mStackSupervisor.mActivitiesWaitingForVisibleActivity.remove(r);
        if (mResumedActivity == r) {
            mResumedActivity = null;
        }
        final ActivityState prevState = r.getState();
        if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to FINISHING: " + r);

@@ -3991,7 +4017,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
     */
    void onActivityRemovedFromStack(ActivityRecord r) {
        if (mResumedActivity == r) {
            mResumedActivity = null;
            clearResumedActivity("onActivityRemovedFromStack");
        }
        if (mPausingActivity == r) {
            mPausingActivity = null;
@@ -5181,7 +5207,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
                        + " other stack to this stack mResumedActivity=" + mResumedActivity
                        + " other mResumedActivity=" + topRunningActivity);
            }
            mResumedActivity = topRunningActivity;
            topRunningActivity.setState(RESUMED, "positionChildAt");
        }

        // The task might have already been running and its visibility needs to be synchronized with
@@ -5226,7 +5252,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
        // so that we don't resume the same activity again in the new stack.
        // Apps may depend on onResume()/onPause() being called in pairs.
        if (setResume) {
            mResumedActivity = r;
            r.setState(RESUMED, "moveToFrontAndResumeStateIfNeeded");
            updateLRUListLocked(r);
        }
        // If the activity was previously pausing, then ensure we transfer that as well
+11 −10
Original line number Diff line number Diff line
@@ -930,7 +930,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
        if (stack == null) {
            return null;
        }
        ActivityRecord resumedActivity = stack.mResumedActivity;
        ActivityRecord resumedActivity = stack.getResumedActivity();
        if (resumedActivity == null || resumedActivity.app == null) {
            resumedActivity = stack.mPausingActivity;
            if (resumedActivity == null || resumedActivity.app == null) {
@@ -985,7 +985,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
                if (!isFocusedStack(stack) || stack.numActivities() == 0) {
                    continue;
                }
                final ActivityRecord resumedActivity = stack.mResumedActivity;
                final ActivityRecord resumedActivity = stack.getResumedActivity();
                if (resumedActivity == null || !resumedActivity.idle) {
                    if (DEBUG_STATES) Slog.d(TAG_STATES, "allResumedActivitiesIdle: stack="
                             + stack.mStackId + " " + resumedActivity + " not idle");
@@ -1004,7 +1004,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
            for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
                final ActivityStack stack = display.getChildAt(stackNdx);
                if (isFocusedStack(stack)) {
                    final ActivityRecord r = stack.mResumedActivity;
                    final ActivityRecord r = stack.getResumedActivity();
                    if (r != null && !r.isState(RESUMED)) {
                        return false;
                    }
@@ -1025,7 +1025,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
            final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
            for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
                final ActivityStack stack = display.getChildAt(stackNdx);
                final ActivityRecord r = stack.mResumedActivity;
                final ActivityRecord r = stack.getResumedActivity();
                if (r != null) {
                    if (!r.nowVisible || mActivitiesWaitingForVisibleActivity.contains(r)) {
                        return false;
@@ -1051,9 +1051,9 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
            final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
            for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
                final ActivityStack stack = display.getChildAt(stackNdx);
                if (!isFocusedStack(stack) && stack.mResumedActivity != null) {
                if (!isFocusedStack(stack) && stack.getResumedActivity() != null) {
                    if (DEBUG_STATES) Slog.d(TAG_STATES, "pauseBackStacks: stack=" + stack +
                            " mResumedActivity=" + stack.mResumedActivity);
                            " mResumedActivity=" + stack.getResumedActivity());
                    someActivityPaused |= stack.startPausingLocked(userLeaving, false, resuming,
                            dontWait);
                }
@@ -2063,8 +2063,9 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
            for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
                final ActivityStack stack = display.getChildAt(stackNdx);
                if (isFocusedStack(stack)) {
                    if (stack.mResumedActivity != null) {
                        fgApp = stack.mResumedActivity.app;
                    final ActivityRecord resumedActivity = stack.getResumedActivity();
                    if (resumedActivity != null) {
                        fgApp = resumedActivity.app;
                    } else if (stack.mPausingActivity != null) {
                        fgApp = stack.mPausingActivity.app;
                    }
@@ -3734,7 +3735,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
                                + " state=" + state);
                    }
                } else {
                    final ActivityRecord resumed = stack.mResumedActivity;
                    final ActivityRecord resumed = stack.getResumedActivity();
                    if (resumed != null && resumed == r) Slog.e(TAG,
                            "validateTop...: back stack has resumed activity r=" + r
                            + " state=" + state);
@@ -3884,7 +3885,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
                    printed = true;
                    needSep = false;
                }
                pr = printThisActivity(pw, stack.mResumedActivity, dumpPackage, needSep,
                pr = printThisActivity(pw, stack.getResumedActivity(), dumpPackage, needSep,
                        "    mResumedActivity: ");
                if (pr) {
                    printed = true;
+2 −2
Original line number Diff line number Diff line
@@ -820,8 +820,8 @@ class ActivityStarter {

        // If we are starting an activity that is not from the same uid as the currently resumed
        // one, check whether app switches are allowed.
        if (voiceSession == null && (stack.mResumedActivity == null
                || stack.mResumedActivity.info.applicationInfo.uid != realCallingUid)) {
        if (voiceSession == null && (stack.getResumedActivity() == null
                || stack.getResumedActivity().info.applicationInfo.uid != realCallingUid)) {
            if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid,
                    realCallingPid, realCallingUid, "Activity start")) {
                mController.addPendingActivityLaunch(new PendingActivityLaunch(r,
Loading