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

Commit da7d338b authored by Riddle Hsu's avatar Riddle Hsu Committed by android-build-merger
Browse files

Merge "Add support to preload recents activity in background" into qt-r1-dev

am: 6a6d1c38

Change-Id: I07938eed9e9b08ae36601e8086510219198041db
parents 9e89ef2a 6a6d1c38
Loading
Loading
Loading
Loading
+8 −14
Original line number Original line Diff line number Diff line
@@ -3162,7 +3162,7 @@ final class ActivityRecord extends ConfigurationContainer {


    boolean ensureActivityConfiguration(int globalChanges, boolean preserveWindow) {
    boolean ensureActivityConfiguration(int globalChanges, boolean preserveWindow) {
        return ensureActivityConfiguration(globalChanges, preserveWindow,
        return ensureActivityConfiguration(globalChanges, preserveWindow,
                false /* ignoreStopState */);
                false /* ignoreVisibility */);
    }
    }


    /**
    /**
@@ -3172,15 +3172,15 @@ final class ActivityRecord extends ConfigurationContainer {
     * @param globalChanges The changes to the global configuration.
     * @param globalChanges The changes to the global configuration.
     * @param preserveWindow If the activity window should be preserved on screen if the activity
     * @param preserveWindow If the activity window should be preserved on screen if the activity
     *                       is relaunched.
     *                       is relaunched.
     * @param ignoreStopState If we should try to relaunch the activity even if it is in the stopped
     * @param ignoreVisibility If we should try to relaunch the activity even if it is invisible
     *                        state. This is useful for the case where we know the activity will be
     *                         (stopped state). This is useful for the case where we know the
     *                        visible soon and we want to ensure its configuration before we make it
     *                         activity will be visible soon and we want to ensure its configuration
     *                        visible.
     *                         before we make it visible.
     * @return False if the activity was relaunched and true if it wasn't relaunched because we
     * @return False if the activity was relaunched and true if it wasn't relaunched because we
     *         can't or the app handles the specific configuration that is changing.
     *         can't or the app handles the specific configuration that is changing.
     */
     */
    boolean ensureActivityConfiguration(int globalChanges, boolean preserveWindow,
    boolean ensureActivityConfiguration(int globalChanges, boolean preserveWindow,
            boolean ignoreStopState) {
            boolean ignoreVisibility) {
        final ActivityStack stack = getActivityStack();
        final ActivityStack stack = getActivityStack();
        if (stack.mConfigWillChange) {
        if (stack.mConfigWillChange) {
            if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
            if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
@@ -3196,15 +3196,9 @@ final class ActivityRecord extends ConfigurationContainer {
            return true;
            return true;
        }
        }


        if (!ignoreStopState && (mState == STOPPING || mState == STOPPED)) {
        if (!ignoreVisibility && (mState == STOPPING || mState == STOPPED || !shouldBeVisible())) {
            if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
            if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
                    "Skipping config check stopped or stopping: " + this);
                    "Skipping config check invisible: " + this);
            return true;
        }

        if (!shouldBeVisible()) {
            if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
                    "Skipping config check invisible stack: " + this);
            return true;
            return true;
        }
        }


+8 −5
Original line number Original line Diff line number Diff line
@@ -1880,8 +1880,7 @@ class ActivityStack extends ConfigurationContainer {
        mRootActivityContainer.ensureActivitiesVisible(resuming, 0, !PRESERVE_WINDOWS);
        mRootActivityContainer.ensureActivitiesVisible(resuming, 0, !PRESERVE_WINDOWS);
    }
    }


    private void addToStopping(ActivityRecord r, boolean scheduleIdle, boolean idleDelayed,
    void addToStopping(ActivityRecord r, boolean scheduleIdle, boolean idleDelayed, String reason) {
            String reason) {
        if (!mStackSupervisor.mStoppingActivities.contains(r)) {
        if (!mStackSupervisor.mStoppingActivities.contains(r)) {
            EventLog.writeEvent(EventLogTags.AM_ADD_TO_STOPPING, r.mUserId,
            EventLog.writeEvent(EventLogTags.AM_ADD_TO_STOPPING, r.mUserId,
                    System.identityHashCode(r), r.shortComponentName, reason);
                    System.identityHashCode(r), r.shortComponentName, reason);
@@ -2176,7 +2175,7 @@ class ActivityStack extends ConfigurationContainer {
                        // sure it matches the current configuration.
                        // sure it matches the current configuration.
                        if (r != starting && notifyClients) {
                        if (r != starting && notifyClients) {
                            r.ensureActivityConfiguration(0 /* globalChanges */, preserveWindows,
                            r.ensureActivityConfiguration(0 /* globalChanges */, preserveWindows,
                                    true /* ignoreStopState */);
                                    true /* ignoreVisibility */);
                        }
                        }


                        if (!r.attachedToProcess()) {
                        if (!r.attachedToProcess()) {
@@ -3138,8 +3137,10 @@ class ActivityStack extends ConfigurationContainer {
            boolean newTask, boolean keepCurTransition, ActivityOptions options) {
            boolean newTask, boolean keepCurTransition, ActivityOptions options) {
        TaskRecord rTask = r.getTaskRecord();
        TaskRecord rTask = r.getTaskRecord();
        final int taskId = rTask.taskId;
        final int taskId = rTask.taskId;
        final boolean allowMoveToFront = options == null || !options.getAvoidMoveToFront();
        // mLaunchTaskBehind tasks get placed at the back of the task stack.
        // mLaunchTaskBehind tasks get placed at the back of the task stack.
        if (!r.mLaunchTaskBehind && (taskForIdLocked(taskId) == null || newTask)) {
        if (!r.mLaunchTaskBehind && allowMoveToFront
                && (taskForIdLocked(taskId) == null || newTask)) {
            // Last activity in task had been removed or ActivityManagerService is reusing task.
            // Last activity in task had been removed or ActivityManagerService is reusing task.
            // Insert or replace.
            // Insert or replace.
            // Might not even be in.
            // Might not even be in.
@@ -3198,7 +3199,9 @@ class ActivityStack extends ConfigurationContainer {


        task.setFrontOfTask();
        task.setFrontOfTask();


        if (!isHomeOrRecentsStack() || numActivities() > 0) {
        // The transition animation and starting window are not needed if {@code allowMoveToFront}
        // is false, because the activity won't be visible.
        if ((!isHomeOrRecentsStack() || numActivities() > 0) && allowMoveToFront) {
            final DisplayContent dc = getDisplay().mDisplayContent;
            final DisplayContent dc = getDisplay().mDisplayContent;
            if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,
            if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,
                    "Prepare open transition: starting " + r);
                    "Prepare open transition: starting " + r);
+2 −2
Original line number Original line Diff line number Diff line
@@ -2307,12 +2307,12 @@ class ActivityStarter {
        // isLockTaskModeViolation fails below.
        // isLockTaskModeViolation fails below.


        if (mReuseTask == null) {
        if (mReuseTask == null) {
            final boolean toTop = !mLaunchTaskBehind && !mAvoidMoveToFront;
            final TaskRecord task = mTargetStack.createTaskRecord(
            final TaskRecord task = mTargetStack.createTaskRecord(
                    mSupervisor.getNextTaskIdForUserLocked(mStartActivity.mUserId),
                    mSupervisor.getNextTaskIdForUserLocked(mStartActivity.mUserId),
                    mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info,
                    mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info,
                    mNewTaskIntent != null ? mNewTaskIntent : mIntent, mVoiceSession,
                    mNewTaskIntent != null ? mNewTaskIntent : mIntent, mVoiceSession,
                    mVoiceInteractor, !mLaunchTaskBehind /* toTop */, mStartActivity, mSourceRecord,
                    mVoiceInteractor, toTop, mStartActivity, mSourceRecord, mOptions);
                    mOptions);
            addOrReparentStartingActivity(task, "setTaskFromReuseOrCreateNewTask - mReuseTask");
            addOrReparentStartingActivity(task, "setTaskFromReuseOrCreateNewTask - mReuseTask");
            updateBounds(mStartActivity.getTaskRecord(), mLaunchParams.mBounds);
            updateBounds(mStartActivity.getTaskRecord(), mLaunchParams.mBounds);


+15 −5
Original line number Original line Diff line number Diff line
@@ -1451,9 +1451,15 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
                .execute();
                .execute();
    }
    }


    /**
     * Start the recents activity to perform the recents animation.
     *
     * @param intent The intent to start the recents activity.
     * @param recentsAnimationRunner Pass {@code null} to only preload the activity.
     */
    @Override
    @Override
    public void startRecentsActivity(Intent intent, IAssistDataReceiver assistDataReceiver,
    public void startRecentsActivity(Intent intent, @Deprecated IAssistDataReceiver unused,
            IRecentsAnimationRunner recentsAnimationRunner) {
            @Nullable IRecentsAnimationRunner recentsAnimationRunner) {
        enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "startRecentsActivity()");
        enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "startRecentsActivity()");
        final int callingPid = Binder.getCallingPid();
        final int callingPid = Binder.getCallingPid();
        final long origId = Binder.clearCallingIdentity();
        final long origId = Binder.clearCallingIdentity();
@@ -1464,9 +1470,13 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {


                // Start a new recents animation
                // Start a new recents animation
                final RecentsAnimation anim = new RecentsAnimation(this, mStackSupervisor,
                final RecentsAnimation anim = new RecentsAnimation(this, mStackSupervisor,
                        getActivityStartController(), mWindowManager, callingPid);
                        getActivityStartController(), mWindowManager, intent, recentsComponent,
                anim.startRecentsActivity(intent, recentsAnimationRunner, recentsComponent,
                        recentsUid, callingPid);
                        recentsUid, assistDataReceiver);
                if (recentsAnimationRunner == null) {
                    anim.preloadRecentsActivity();
                } else {
                    anim.startRecentsActivity(recentsAnimationRunner);
                }
            }
            }
        } finally {
        } finally {
            Binder.restoreCallingIdentity(origId);
            Binder.restoreCallingIdentity(origId);
+98 −33
Original line number Original line Diff line number Diff line
@@ -34,7 +34,6 @@ import static com.android.server.wm.RecentsAnimationController.REORDER_MOVE_TO_T
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_RECENTS_ANIMATIONS;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_RECENTS_ANIMATIONS;


import android.app.ActivityOptions;
import android.app.ActivityOptions;
import android.app.IAssistDataReceiver;
import android.content.ComponentName;
import android.content.ComponentName;
import android.content.Intent;
import android.content.Intent;
import android.os.RemoteException;
import android.os.RemoteException;
@@ -58,7 +57,12 @@ class RecentsAnimation implements RecentsAnimationCallbacks,
    private final ActivityStartController mActivityStartController;
    private final ActivityStartController mActivityStartController;
    private final WindowManagerService mWindowManager;
    private final WindowManagerService mWindowManager;
    private final ActivityDisplay mDefaultDisplay;
    private final ActivityDisplay mDefaultDisplay;
    private final Intent mTargetIntent;
    private final ComponentName mRecentsComponent;
    private final int mRecentsUid;
    private final int mCallingPid;
    private final int mCallingPid;
    private final int mUserId;
    private final int mTargetActivityType;


    /**
    /**
     * The activity which has been launched behind. We need to remember the activity because the
     * The activity which has been launched behind. We need to remember the activity because the
@@ -66,27 +70,90 @@ class RecentsAnimation implements RecentsAnimationCallbacks,
     * for the exact activity.
     * for the exact activity.
     */
     */
    private ActivityRecord mLaunchedTargetActivity;
    private ActivityRecord mLaunchedTargetActivity;
    private int mTargetActivityType;


    // The stack to restore the target stack behind when the animation is finished
    // The stack to restore the target stack behind when the animation is finished
    private ActivityStack mRestoreTargetBehindStack;
    private ActivityStack mRestoreTargetBehindStack;


    RecentsAnimation(ActivityTaskManagerService atm, ActivityStackSupervisor stackSupervisor,
    RecentsAnimation(ActivityTaskManagerService atm, ActivityStackSupervisor stackSupervisor,
            ActivityStartController activityStartController, WindowManagerService wm,
            ActivityStartController activityStartController, WindowManagerService wm,
            int callingPid) {
            Intent targetIntent, ComponentName recentsComponent, int recentsUid, int callingPid) {
        mService = atm;
        mService = atm;
        mStackSupervisor = stackSupervisor;
        mStackSupervisor = stackSupervisor;
        mDefaultDisplay = mService.mRootActivityContainer.getDefaultDisplay();
        mDefaultDisplay = mService.mRootActivityContainer.getDefaultDisplay();
        mActivityStartController = activityStartController;
        mActivityStartController = activityStartController;
        mWindowManager = wm;
        mWindowManager = wm;
        mTargetIntent = targetIntent;
        mRecentsComponent = recentsComponent;
        mRecentsUid = recentsUid;
        mCallingPid = callingPid;
        mCallingPid = callingPid;
        mUserId = atm.getCurrentUserId();
        mTargetActivityType = targetIntent.getComponent() != null
                && recentsComponent.equals(targetIntent.getComponent())
                        ? ACTIVITY_TYPE_RECENTS
                        : ACTIVITY_TYPE_HOME;
    }

    /**
     * Starts the recents activity in background without animation if the record doesn't exist or
     * the client isn't launched. If the recents activity is already alive, ensure its configuration
     * is updated to the current one.
     */
    void preloadRecentsActivity() {
        if (DEBUG) Slog.d(TAG, "Preload recents with " + mTargetIntent);
        ActivityStack targetStack = mDefaultDisplay.getStack(WINDOWING_MODE_UNDEFINED,
                mTargetActivityType);
        ActivityRecord targetActivity = getTargetActivity(targetStack);
        if (targetActivity != null) {
            if (targetActivity.visible || targetActivity.isTopRunningActivity()) {
                // The activity is ready.
                return;
            }
            if (targetActivity.attachedToProcess()) {
                // The activity may be relaunched if it cannot handle the current configuration
                // changes. The activity will be paused state if it is relaunched, otherwise it
                // keeps the original stopped state.
                targetActivity.ensureActivityConfiguration(0 /* globalChanges */,
                        false /* preserveWindow */, true /* ignoreVisibility */);
                if (DEBUG) Slog.d(TAG, "Updated config=" + targetActivity.getConfiguration());
            }
        } else {
            // Create the activity record. Because the activity is invisible, this doesn't really
            // start the client.
            startRecentsActivityInBackground("preloadRecents");
            targetStack = mDefaultDisplay.getStack(WINDOWING_MODE_UNDEFINED, mTargetActivityType);
            targetActivity = getTargetActivity(targetStack);
            if (targetActivity == null) {
                Slog.w(TAG, "Cannot start " + mTargetIntent);
                return;
            }
        }

        if (!targetActivity.attachedToProcess()) {
            if (DEBUG) Slog.d(TAG, "Real start recents");
            mStackSupervisor.startSpecificActivityLocked(targetActivity, false /* andResume */,
                    false /* checkConfig */);
            // Make sure the activity won't be involved in transition.
            if (targetActivity.mAppWindowToken != null) {
                targetActivity.mAppWindowToken.getDisplayContent().mUnknownAppVisibilityController
                        .appRemovedOrHidden(targetActivity.mAppWindowToken);
            }
        }
        }


    void startRecentsActivity(Intent intent, IRecentsAnimationRunner recentsAnimationRunner,
        // Invisible activity should be stopped. If the recents activity is alive and its doesn't
            ComponentName recentsComponent, int recentsUid,
        // need to relaunch by current configuration, then it may be already in stopped state.
            @Deprecated IAssistDataReceiver assistDataReceiver) {
        if (!targetActivity.isState(ActivityStack.ActivityState.STOPPING,
        if (DEBUG) Slog.d(TAG, "startRecentsActivity(): intent=" + intent
                ActivityStack.ActivityState.STOPPED)) {
                + " assistDataReceiver=" + assistDataReceiver);
            // Add to stopping instead of stop immediately. So the client has the chance to perform
            // traversal in non-stopped state (ViewRootImpl.mStopped) that would initialize more
            // things (e.g. the measure can be done earlier). The actual stop will be performed when
            // it reports idle.
            targetStack.addToStopping(targetActivity, true /* scheduleIdle */,
                    true /* idleDelayed */, "preloadRecents");
        }
    }

    void startRecentsActivity(IRecentsAnimationRunner recentsAnimationRunner) {
        if (DEBUG) Slog.d(TAG, "startRecentsActivity(): intent=" + mTargetIntent);
        Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "RecentsAnimation#startRecentsActivity");
        Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "RecentsAnimation#startRecentsActivity");


        // TODO(multi-display) currently only support recents animation in default display.
        // TODO(multi-display) currently only support recents animation in default display.
@@ -100,15 +167,9 @@ class RecentsAnimation implements RecentsAnimationCallbacks,
        }
        }


        // If the activity is associated with the recents stack, then try and get that first
        // If the activity is associated with the recents stack, then try and get that first
        final int userId = mService.getCurrentUserId();
        mTargetActivityType = intent.getComponent() != null
                && recentsComponent.equals(intent.getComponent())
                        ? ACTIVITY_TYPE_RECENTS
                        : ACTIVITY_TYPE_HOME;
        ActivityStack targetStack = mDefaultDisplay.getStack(WINDOWING_MODE_UNDEFINED,
        ActivityStack targetStack = mDefaultDisplay.getStack(WINDOWING_MODE_UNDEFINED,
                mTargetActivityType);
                mTargetActivityType);
        ActivityRecord targetActivity = getTargetActivity(targetStack, intent.getComponent(),
        ActivityRecord targetActivity = getTargetActivity(targetStack);
                userId);
        final boolean hasExistingActivity = targetActivity != null;
        final boolean hasExistingActivity = targetActivity != null;
        if (hasExistingActivity) {
        if (hasExistingActivity) {
            final ActivityDisplay display = targetActivity.getDisplay();
            final ActivityDisplay display = targetActivity.getDisplay();
@@ -127,7 +188,7 @@ class RecentsAnimation implements RecentsAnimationCallbacks,
                    true /* forceSend */, targetActivity);
                    true /* forceSend */, targetActivity);
        }
        }


        mStackSupervisor.getActivityMetricsLogger().notifyActivityLaunching(intent);
        mStackSupervisor.getActivityMetricsLogger().notifyActivityLaunching(mTargetIntent);


        mService.mH.post(() -> mService.mAmInternal.setRunningRemoteAnimation(mCallingPid, true));
        mService.mH.post(() -> mService.mAmInternal.setRunningRemoteAnimation(mCallingPid, true));


@@ -148,23 +209,12 @@ class RecentsAnimation implements RecentsAnimationCallbacks,
                }
                }
            } else {
            } else {
                // No recents activity, create the new recents activity bottom most
                // No recents activity, create the new recents activity bottom most
                ActivityOptions options = ActivityOptions.makeBasic();
                startRecentsActivityInBackground("startRecentsActivity_noTargetActivity");
                options.setLaunchActivityType(mTargetActivityType);
                options.setAvoidMoveToFront();
                intent.addFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_NO_ANIMATION);

                mActivityStartController
                        .obtainStarter(intent, "startRecentsActivity_noTargetActivity")
                        .setCallingUid(recentsUid)
                        .setCallingPackage(recentsComponent.getPackageName())
                        .setActivityOptions(SafeActivityOptions.fromBundle(options.toBundle()))
                        .setMayWait(userId)
                        .execute();


                // Move the recents activity into place for the animation
                // Move the recents activity into place for the animation
                targetStack = mDefaultDisplay.getStack(WINDOWING_MODE_UNDEFINED,
                targetStack = mDefaultDisplay.getStack(WINDOWING_MODE_UNDEFINED,
                        mTargetActivityType);
                        mTargetActivityType);
                targetActivity = getTargetActivity(targetStack, intent.getComponent(), userId);
                targetActivity = getTargetActivity(targetStack);
                mDefaultDisplay.moveStackBehindBottomMostVisibleStack(targetStack);
                mDefaultDisplay.moveStackBehindBottomMostVisibleStack(targetStack);
                if (DEBUG) {
                if (DEBUG) {
                    Slog.d(TAG, "Moved stack=" + targetStack + " behind stack="
                    Slog.d(TAG, "Moved stack=" + targetStack + " behind stack="
@@ -176,7 +226,7 @@ class RecentsAnimation implements RecentsAnimationCallbacks,


                // TODO: Maybe wait for app to draw in this particular case?
                // TODO: Maybe wait for app to draw in this particular case?


                if (DEBUG) Slog.d(TAG, "Started intent=" + intent);
                if (DEBUG) Slog.d(TAG, "Started intent=" + mTargetIntent);
            }
            }


            // Mark the target activity as launch-behind to bump its visibility for the
            // Mark the target activity as launch-behind to bump its visibility for the
@@ -383,6 +433,21 @@ class RecentsAnimation implements RecentsAnimationCallbacks,
        }
        }
    }
    }


    private void startRecentsActivityInBackground(String reason) {
        final ActivityOptions options = ActivityOptions.makeBasic();
        options.setLaunchActivityType(mTargetActivityType);
        options.setAvoidMoveToFront();
        mTargetIntent.addFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_NO_ANIMATION);

        mActivityStartController
                .obtainStarter(mTargetIntent, reason)
                .setCallingUid(mRecentsUid)
                .setCallingPackage(mRecentsComponent.getPackageName())
                .setActivityOptions(new SafeActivityOptions(options))
                .setMayWait(mUserId)
                .execute();
    }

    /**
    /**
     * Called only when the animation should be canceled prior to starting.
     * Called only when the animation should be canceled prior to starting.
     */
     */
@@ -412,15 +477,15 @@ class RecentsAnimation implements RecentsAnimationCallbacks,
     * @return the top activity in the {@param targetStack} matching the {@param component}, or just
     * @return the top activity in the {@param targetStack} matching the {@param component}, or just
     * the top activity of the top task if no task matches the component.
     * the top activity of the top task if no task matches the component.
     */
     */
    private ActivityRecord getTargetActivity(ActivityStack targetStack, ComponentName component,
    private ActivityRecord getTargetActivity(ActivityStack targetStack) {
            int userId) {
        if (targetStack == null) {
        if (targetStack == null) {
            return null;
            return null;
        }
        }


        for (int i = targetStack.getChildCount() - 1; i >= 0; i--) {
        for (int i = targetStack.getChildCount() - 1; i >= 0; i--) {
            final TaskRecord task = targetStack.getChildAt(i);
            final TaskRecord task = targetStack.getChildAt(i);
            if (task.userId == userId && task.getBaseIntent().getComponent().equals(component)) {
            if (task.userId == mUserId
                    && task.getBaseIntent().getComponent().equals(mTargetIntent.getComponent())) {
                return task.getTopActivity();
                return task.getTopActivity();
            }
            }
        }
        }
Loading