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

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

Clean up activity/stack associations.

The stack currently holds a reference to resuming and pausing
activities. These are usually cleaned up when the activity ends or
the task is reparented. However, it is possible for an activity to
lose its reference to its task in other areas (such as
ActivityStarter), which can lead to the stack not being updated
correctly.

This changelist adds a method to the ActivityStack to disassociate
the stack from an ActivityRecord. In addition to places where this is
called when an activity ends, this method is invoked on the children
of a task when the task is reparented. The task member variable of
ActivityRecord is also now surrounded by a setter/getter, with the
setter always invoking the dissociation logic on a previous stack.

Test: bit FrameworksServicesTests:com.android.server.am.ActivityRecordTests
Change-Id: Iffeccdb6f011958896271673946acfed28856f53
Fixes: 36387417
parent 21a5edcc
Loading
Loading
Loading
Loading
+35 −25
Original line number Diff line number Diff line
@@ -2872,7 +2872,7 @@ public class ActivityManagerService extends IActivityManager.Stub
        mTempConfig.setToDefaults();
        mTempConfig.setLocales(LocaleList.getDefault());
        mConfigurationSeq = mTempConfig.seq = 1;
        mStackSupervisor = new ActivityStackSupervisor(this);
        mStackSupervisor = createStackSupervisor();
        mStackSupervisor.onConfigurationChanged(mTempConfig);
        mKeyguardController = mStackSupervisor.mKeyguardController;
        mCompatModePackages = new CompatModePackages(this, systemDir, mHandler);
@@ -2920,6 +2920,10 @@ public class ActivityManagerService extends IActivityManager.Stub
        Watchdog.getInstance().addThread(mHandler);
    }
    protected ActivityStackSupervisor createStackSupervisor() {
        return new ActivityStackSupervisor(this, mHandler.getLooper());
    }
    public void setSystemServiceManager(SystemServiceManager mgr) {
        mSystemServiceManager = mgr;
    }
@@ -3174,7 +3178,8 @@ public class ActivityManagerService extends IActivityManager.Stub
     * {@link ActivityStack#setResumedActivityLocked} when an activity is resumed.
     */
    void setResumedActivityUncheckLocked(ActivityRecord r, String reason) {
        if (r.task.isApplicationTask()) {
        final TaskRecord task = r.getTask();
        if (task.isApplicationTask()) {
            if (mCurAppTimeTracker != r.appTimeTracker) {
                // We are switching app tracking.  Complete the current one.
                if (mCurAppTimeTracker != null) {
@@ -3197,17 +3202,18 @@ public class ActivityManagerService extends IActivityManager.Stub
        // TODO: VI Maybe r.task.voiceInteractor || r.voiceInteractor != null
        // TODO: Probably not, because we don't want to resume voice on switching
        // back to this activity
        if (r.task.voiceInteractor != null) {
            startRunningVoiceLocked(r.task.voiceSession, r.info.applicationInfo.uid);
        if (task.voiceInteractor != null) {
            startRunningVoiceLocked(task.voiceSession, r.info.applicationInfo.uid);
        } else {
            finishRunningVoiceLocked();
            if (mLastResumedActivity != null) {
                final IVoiceInteractionSession session;
                if (mLastResumedActivity.task != null
                        && mLastResumedActivity.task.voiceSession != null) {
                    session = mLastResumedActivity.task.voiceSession;
                final TaskRecord lastResumedActivityTask = mLastResumedActivity.getTask();
                if (lastResumedActivityTask != null
                        && lastResumedActivityTask.voiceSession != null) {
                    session = lastResumedActivityTask.voiceSession;
                } else {
                    session = mLastResumedActivity.voiceSession;
                }
@@ -3340,7 +3346,7 @@ public class ActivityManagerService extends IActivityManager.Stub
    final void showAskCompatModeDialogLocked(ActivityRecord r) {
        Message msg = Message.obtain();
        msg.what = SHOW_COMPAT_MODE_DIALOG_UI_MSG;
        msg.obj = r.task.askedCompatMode ? null : r;
        msg.obj = r.getTask().askedCompatMode ? null : r;
        mUiHandler.sendMessage(msg);
    }
@@ -4746,7 +4752,7 @@ public class ActivityManagerService extends IActivityManager.Stub
            if (ActivityRecord.forTokenLocked(callingActivity) != activity) {
                throw new SecurityException("Only focused activity can call startVoiceInteraction");
            }
            if (mRunningVoice != null || activity.task.voiceSession != null
            if (mRunningVoice != null || activity.getTask().voiceSession != null
                    || activity.voiceSession != null) {
                Slog.w(TAG, "Already in a voice interaction, cannot start new voice interaction");
                return;
@@ -5056,7 +5062,7 @@ public class ActivityManagerService extends IActivityManager.Stub
                return true;
            }
            // Keep track of the root activity of the task before we finish it
            TaskRecord tr = r.task;
            TaskRecord tr = r.getTask();
            ActivityRecord rootR = tr.getRootActivity();
            if (rootR == null) {
                Slog.w(TAG, "Finishing task with all activities already finished");
@@ -5193,7 +5199,7 @@ public class ActivityManagerService extends IActivityManager.Stub
                // Do not allow task to finish if last task in lockTask mode. Launchable priv-apps
                // can finish.
                final TaskRecord task = r.task;
                final TaskRecord task = r.getTask();
                if (task.mLockTaskAuth != LOCK_TASK_AUTH_LAUNCHABLE_PRIV &&
                        mStackSupervisor.isLastLockedTask(task) && task.getRootActivity() == r) {
                    mStackSupervisor.showLockTaskToast();
@@ -7857,7 +7863,7 @@ public class ActivityManagerService extends IActivityManager.Stub
                    return false;
                }
                // An activity is consider to be in multi-window mode if its task isn't fullscreen.
                return !r.task.mFullscreen;
                return !r.getTask().mFullscreen;
            }
        } finally {
            Binder.restoreCallingIdentity(origId);
@@ -9950,8 +9956,9 @@ public class ActivityManagerService extends IActivityManager.Stub
            ActivityRecord r = ActivityRecord.isInStackLocked(token);
            if (r != null) {
                r.setTaskDescription(td);
                r.task.updateTaskDescription();
                mTaskChangeNotificationController.notifyTaskDescriptionChanged(r.task.taskId, td);
                final TaskRecord task = r.getTask();
                task.updateTaskDescription();
                mTaskChangeNotificationController.notifyTaskDescriptionChanged(task.taskId, td);
            }
        }
    }
@@ -10401,8 +10408,8 @@ public class ActivityManagerService extends IActivityManager.Stub
                }
                if (DEBUG_STACK) Slog.d(TAG_STACK, "exitFreeformMode: " + r);
                r.task.reparent(FULLSCREEN_WORKSPACE_STACK_ID, ON_TOP, REPARENT_KEEP_STACK_AT_FRONT,
                        ANIMATE, !DEFER_RESUME, "exitFreeformMode");
                r.getTask().reparent(FULLSCREEN_WORKSPACE_STACK_ID, ON_TOP,
                        REPARENT_KEEP_STACK_AT_FRONT, ANIMATE, !DEFER_RESUME, "exitFreeformMode");
            } finally {
                Binder.restoreCallingIdentity(ident);
            }
@@ -10783,7 +10790,7 @@ public class ActivityManagerService extends IActivityManager.Stub
            if (r == null) {
                return;
            }
            final TaskRecord task = r.task;
            final TaskRecord task = r.getTask();
            if (task != null) {
                startLockTaskModeLocked(task);
            }
@@ -10882,7 +10889,7 @@ public class ActivityManagerService extends IActivityManager.Stub
            if (r == null) {
                return;
            }
            mStackSupervisor.showLockTaskEscapeMessageLocked(r.task);
            mStackSupervisor.showLockTaskEscapeMessageLocked(r.getTask());
        }
    }
@@ -13137,9 +13144,10 @@ public class ActivityManagerService extends IActivityManager.Stub
                if (r == null) {
                    return false;
                }
                int index = r.task.mActivities.lastIndexOf(r);
                final TaskRecord task = r.getTask();
                int index = task.mActivities.lastIndexOf(r);
                if (index > 0) {
                    ActivityRecord under = r.task.mActivities.get(index - 1);
                    ActivityRecord under = task.mActivities.get(index - 1);
                    under.returningOptions = ActivityOptions.fromBundle(options);
                }
                final boolean translucentChanged = r.changeWindowTranslucency(false);
@@ -13426,7 +13434,7 @@ public class ActivityManagerService extends IActivityManager.Stub
            if (r == null) {
                throw new IllegalArgumentException();
            }
            return r.task.getTopActivity() == r;
            return r.getTask().getTopActivity() == r;
        }
    }
@@ -15952,8 +15960,9 @@ public class ActivityManagerService extends IActivityManager.Stub
            }
            needSep = true;
            synchronized (this) {
                if (lastTask != r.task) {
                    lastTask = r.task;
                final TaskRecord task = r.getTask();
                if (lastTask != task) {
                    lastTask = task;
                    pw.print("TASK "); pw.print(lastTask.affinity);
                            pw.print(" id="); pw.print(lastTask.taskId);
                            pw.print(" userId="); pw.println(lastTask.userId);
@@ -20582,8 +20591,9 @@ public class ActivityManagerService extends IActivityManager.Stub
                    app.cached = false;
                    app.empty = false;
                    foregroundActivities = true;
                    if (r.task != null && minLayer > 0) {
                        final int layer = r.task.mLayerRank;
                    final TaskRecord task = r.getTask();
                    if (task != null && minLayer > 0) {
                        final int layer = task.mLayerRank;
                        if (layer >= 0 && minLayer > layer) {
                            minLayer = layer;
                        }
+42 −3
Original line number Diff line number Diff line
@@ -229,7 +229,7 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
    private int theme;              // resource identifier of activity's theme.
    private int realTheme;          // actual theme resource we will use, never 0.
    private int windowFlags;        // custom window flags for preview window.
    TaskRecord task;        // the task this is in.
    private TaskRecord task;        // the task this is in.
    private long createTime = System.currentTimeMillis();
    long displayStartTime;  // when we started launching this activity
    long fullyDrawnStartTime; // when we started launching this activity
@@ -656,9 +656,48 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo

    @Override
    protected ConfigurationContainer getParent() {
        return getTask();
    }

    TaskRecord getTask() {
        return task;
    }

    /**
     * Sets reference to the {@link TaskRecord} the {@link ActivityRecord} will treat as its parent.
     * Note that this does not actually add the {@link ActivityRecord} as a {@link TaskRecord}
     * children. However, this method will clean up references to this {@link ActivityRecord} in
     * {@link ActivityStack}.
     * @param task The new parent {@link TaskRecord}.
     */
    void setTask(TaskRecord task) {
        setTask(task, false /*reparenting*/);
    }

    /**
     * This method should only be called by {@link TaskRecord#removeActivity(ActivityRecord)}.
     */
    void setTask(TaskRecord task, boolean reparenting) {
        // Do nothing if the {@link TaskRecord} is the same as the current {@link getTask}.
        if (task != null && task == getTask()) {
            return;
        }

        final ActivityStack stack = getStack();

        // If the new {@link TaskRecord} is from a different {@link ActivityStack}, remove this
        // {@link ActivityRecord} from its current {@link ActivityStack}.
        if (!reparenting && stack != null && (task == null || stack != task.getStack())) {
            stack.onActivityRemovedFromStack(this);
        }

        this.task = task;

        if (!reparenting) {
            onParentChanged();
        }
    }

    static class Token extends IApplicationToken.Stub {
        private final WeakReference<ActivityRecord> weakActivity;

@@ -895,8 +934,8 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
        // Must reparent first in window manager
        mWindowContainerController.reparent(newTask.getWindowContainerController(), position);

        // Remove the activity from the old task and add it to the new task
        prevTask.removeActivity(this);
        // Remove the activity from the old task and add it to the new task.
        prevTask.removeActivity(this, true /*reparenting*/);

        newTask.addActivityAtIndex(position, this);
    }
+91 −65

File changed.

Preview size limit exceeded, changes collapsed.

+35 −26
Original line number Diff line number Diff line
@@ -164,6 +164,7 @@ import android.view.Display;
import android.view.InputEvent;
import android.view.Surface;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.content.ReferrerIntent;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -173,6 +174,7 @@ import com.android.internal.util.ArrayUtils;
import com.android.internal.widget.LockPatternUtils;
import com.android.server.LocalServices;
import com.android.server.am.ActivityStack.ActivityState;
import com.android.server.wm.StackWindowController;
import com.android.server.wm.WindowManagerService;

import java.io.FileDescriptor;
@@ -549,9 +551,9 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
        }
    }

    public ActivityStackSupervisor(ActivityManagerService service) {
    public ActivityStackSupervisor(ActivityManagerService service, Looper looper) {
        mService = service;
        mHandler = new ActivityStackSupervisorHandler(mService.mHandler.getLooper());
        mHandler = new ActivityStackSupervisorHandler(looper);
        mActivityMetricsLogger = new ActivityMetricsLogger(this, mService.mContext);
        mKeyguardController = new KeyguardController(service, this);
    }
@@ -718,7 +720,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
        }

        if (prev != null) {
            prev.task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
            prev.getTask().setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
        }

        mHomeStack.moveHomeStackTaskToTop();
@@ -1310,7 +1312,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
        mService.updateLruProcessLocked(app, true, null);
        mService.updateOomAdjLocked();

        final TaskRecord task = r.task;
        final TaskRecord task = r.getTask();
        if (task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE ||
                task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE_PRIV) {
            setLockTaskModeLocked(task, LOCK_TASK_MODE_LOCKED, "mLockTaskAuth==LAUNCHABLE", false);
@@ -2614,7 +2616,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
                }

                for (int k = 0; k < proc.activities.size(); k++) {
                    TaskRecord otherTask = proc.activities.get(k).task;
                    TaskRecord otherTask = proc.activities.get(k).getTask();
                    if (tr.taskId != otherTask.taskId && otherTask.inRecents) {
                        // Don't kill process(es) that has an activity in a different task that is
                        // also in recents.
@@ -2829,7 +2831,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
        final PinnedActivityStack stack = getStack(PINNED_STACK_ID, CREATE_IF_NEEDED, ON_TOP);

        try {
            final TaskRecord task = r.task;
            final TaskRecord task = r.getTask();

            if (r == task.getStack().getVisibleBehindActivity()) {
                // An activity can't be pinned and visible behind at the same time. Go ahead and
@@ -2902,7 +2904,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
            return false;
        }

        final TaskRecord task = r.task;
        final TaskRecord task = r.getTask();
        final ActivityStack stack = r.getStack();
        if (stack == null) {
            Slog.w(TAG, "moveActivityStackToFront: invalid task or stack: r="
@@ -3195,7 +3197,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D

    // Called when WindowManager has finished animating the launchingBehind activity to the back.
    private void handleLaunchTaskBehindCompleteLocked(ActivityRecord r) {
        final TaskRecord task = r.task;
        final TaskRecord task = r.getTask();
        final ActivityStack stack = task.getStack();

        r.mLaunchTaskBehind = false;
@@ -3208,7 +3210,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
        // task has been shown briefly
        final ActivityRecord top = stack.topActivity();
        if (top != null) {
            top.task.touchActiveTime();
            top.getTask().touchActiveTime();
        }
    }

@@ -3307,17 +3309,19 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
                if (DEBUG_RELEASE) Slog.d(TAG_RELEASE, "Not releasing in-use activity: " + r);
                continue;
            }
            if (r.task != null) {
                if (DEBUG_RELEASE) Slog.d(TAG_RELEASE, "Collecting release task " + r.task

            final TaskRecord task = r.getTask();
            if (task != null) {
                if (DEBUG_RELEASE) Slog.d(TAG_RELEASE, "Collecting release task " + task
                        + " from " + r);
                if (firstTask == null) {
                    firstTask = r.task;
                } else if (firstTask != r.task) {
                    firstTask = task;
                } else if (firstTask != task) {
                    if (tasks == null) {
                        tasks = new ArraySet<>();
                        tasks.add(firstTask);
                    }
                    tasks.add(r.task);
                    tasks.add(task);
                }
            }
        }
@@ -3656,8 +3660,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
                pw.println(header2);
                header2 = null;
            }
            if (lastTask != r.task) {
                lastTask = r.task;
            if (lastTask != r.getTask()) {
                lastTask = r.getTask();
                pw.print(prefix);
                pw.print(full ? "* " : "  ");
                pw.println(lastTask);
@@ -4072,7 +4076,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
            }
        }
        final ActivityRecord r = topRunningActivityLocked();
        final TaskRecord task = r != null ? r.task : null;
        final TaskRecord task = r != null ? r.getTask() : null;
        if (mLockTaskModeTasks.isEmpty() && task != null
                && task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE) {
            // This task must have just been authorized.
@@ -4365,7 +4369,15 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
            synchronized (mService) {
                mStackId = stackId;
                mActivityDisplay = activityDisplay;
                switch (mStackId) {
                mIdString = "ActivtyContainer{" + mStackId + "}";

                createStack(stackId, onTop);
                if (DEBUG_STACK) Slog.d(TAG_STACK, "Creating " + this);
            }
        }

        protected void createStack(int stackId, boolean onTop) {
            switch (stackId) {
                case PINNED_STACK_ID:
                    new PinnedActivityStack(this, mRecentTasks, onTop);
                    break;
@@ -4373,9 +4385,6 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
                    new ActivityStack(this, mRecentTasks, onTop);
                    break;
            }
                mIdString = "ActivtyContainer{" + mStackId + "}";
                if (DEBUG_STACK) Slog.d(TAG_STACK, "Creating " + this);
            }
        }

        /**
@@ -4901,7 +4910,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D

            mService.mActivityStarter.postStartActivityProcessing(task.getTopActivity(),
                    ActivityManager.START_TASK_TO_FRONT,
                    sourceRecord != null ? sourceRecord.task.getStackId() : INVALID_STACK_ID,
                    sourceRecord != null ? sourceRecord.getTask().getStackId() : INVALID_STACK_ID,
                    sourceRecord, task.getStack());
            return ActivityManager.START_TASK_TO_FRONT;
        }
+2 −2
Original line number Diff line number Diff line
@@ -188,10 +188,10 @@ class ActivityStartInterceptor {
        }

        ActivityRecord homeActivityRecord = mSupervisor.getHomeActivity();
        if (homeActivityRecord != null && homeActivityRecord.task != null) {
        if (homeActivityRecord != null && homeActivityRecord.getTask() != null) {
            // Showing credential confirmation activity in home task to avoid stopping multi-windowed
            // mode after showing the full-screen credential confirmation activity.
            mActivityOptions.setLaunchTaskId(homeActivityRecord.task.taskId);
            mActivityOptions.setLaunchTaskId(homeActivityRecord.getTask().taskId);
        }

        final UserInfo parent = mUserManager.getProfileParent(mUserId);
Loading