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

Commit 93eddc6f authored by Android Build Merger (Role)'s avatar Android Build Merger (Role) Committed by Android (Google) Code Review
Browse files

Merge "Merge "Add support to preload recents activity in background" into...

Merge "Merge "Add support to preload recents activity in background" into qt-r1-dev am: 6a6d1c38 am: da7d338b"
parents 4932db2a 799700f6
Loading
Loading
Loading
Loading
+8 −14
Original line number Original line Diff line number Diff line
@@ -3160,7 +3160,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 */);
    }
    }


    /**
    /**
@@ -3170,15 +3170,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,
@@ -3194,15 +3194,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()) {
@@ -3145,8 +3144,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.
@@ -3205,7 +3206,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
@@ -1447,9 +1447,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();
@@ -1460,9 +1466,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