Loading services/core/java/com/android/server/wm/ActivityRecord.java +8 −14 Original line number Diff line number Diff line Loading @@ -3160,7 +3160,7 @@ final class ActivityRecord extends ConfigurationContainer { boolean ensureActivityConfiguration(int globalChanges, boolean preserveWindow) { return ensureActivityConfiguration(globalChanges, preserveWindow, false /* ignoreStopState */); false /* ignoreVisibility */); } /** Loading @@ -3170,15 +3170,15 @@ final class ActivityRecord extends ConfigurationContainer { * @param globalChanges The changes to the global configuration. * @param preserveWindow If the activity window should be preserved on screen if the activity * is relaunched. * @param ignoreStopState If we should try to relaunch the activity even if it is in the stopped * state. This is useful for the case where we know the activity will be * visible soon and we want to ensure its configuration before we make it * visible. * @param ignoreVisibility If we should try to relaunch the activity even if it is invisible * (stopped state). This is useful for the case where we know the * activity will be visible soon and we want to ensure its configuration * before we make it visible. * @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. */ boolean ensureActivityConfiguration(int globalChanges, boolean preserveWindow, boolean ignoreStopState) { boolean ignoreVisibility) { final ActivityStack stack = getActivityStack(); if (stack.mConfigWillChange) { if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, Loading @@ -3194,15 +3194,9 @@ final class ActivityRecord extends ConfigurationContainer { return true; } if (!ignoreStopState && (mState == STOPPING || mState == STOPPED)) { if (!ignoreVisibility && (mState == STOPPING || mState == STOPPED || !shouldBeVisible())) { if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, "Skipping config check stopped or stopping: " + this); return true; } if (!shouldBeVisible()) { if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, "Skipping config check invisible stack: " + this); "Skipping config check invisible: " + this); return true; } Loading services/core/java/com/android/server/wm/ActivityStack.java +8 −5 Original line number Diff line number Diff line Loading @@ -1880,8 +1880,7 @@ class ActivityStack extends ConfigurationContainer { mRootActivityContainer.ensureActivitiesVisible(resuming, 0, !PRESERVE_WINDOWS); } private void addToStopping(ActivityRecord r, boolean scheduleIdle, boolean idleDelayed, String reason) { void addToStopping(ActivityRecord r, boolean scheduleIdle, boolean idleDelayed, String reason) { if (!mStackSupervisor.mStoppingActivities.contains(r)) { EventLog.writeEvent(EventLogTags.AM_ADD_TO_STOPPING, r.mUserId, System.identityHashCode(r), r.shortComponentName, reason); Loading Loading @@ -2176,7 +2175,7 @@ class ActivityStack extends ConfigurationContainer { // sure it matches the current configuration. if (r != starting && notifyClients) { r.ensureActivityConfiguration(0 /* globalChanges */, preserveWindows, true /* ignoreStopState */); true /* ignoreVisibility */); } if (!r.attachedToProcess()) { Loading Loading @@ -3145,8 +3144,10 @@ class ActivityStack extends ConfigurationContainer { boolean newTask, boolean keepCurTransition, ActivityOptions options) { TaskRecord rTask = r.getTaskRecord(); final int taskId = rTask.taskId; final boolean allowMoveToFront = options == null || !options.getAvoidMoveToFront(); // 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. // Insert or replace. // Might not even be in. Loading Loading @@ -3205,7 +3206,9 @@ class ActivityStack extends ConfigurationContainer { 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; if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare open transition: starting " + r); Loading services/core/java/com/android/server/wm/ActivityStarter.java +2 −2 Original line number Diff line number Diff line Loading @@ -2307,12 +2307,12 @@ class ActivityStarter { // isLockTaskModeViolation fails below. if (mReuseTask == null) { final boolean toTop = !mLaunchTaskBehind && !mAvoidMoveToFront; final TaskRecord task = mTargetStack.createTaskRecord( mSupervisor.getNextTaskIdForUserLocked(mStartActivity.mUserId), mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info, mNewTaskIntent != null ? mNewTaskIntent : mIntent, mVoiceSession, mVoiceInteractor, !mLaunchTaskBehind /* toTop */, mStartActivity, mSourceRecord, mOptions); mVoiceInteractor, toTop, mStartActivity, mSourceRecord, mOptions); addOrReparentStartingActivity(task, "setTaskFromReuseOrCreateNewTask - mReuseTask"); updateBounds(mStartActivity.getTaskRecord(), mLaunchParams.mBounds); Loading services/core/java/com/android/server/wm/ActivityTaskManagerService.java +15 −5 Original line number Diff line number Diff line Loading @@ -1447,9 +1447,15 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { .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 public void startRecentsActivity(Intent intent, IAssistDataReceiver assistDataReceiver, IRecentsAnimationRunner recentsAnimationRunner) { public void startRecentsActivity(Intent intent, @Deprecated IAssistDataReceiver unused, @Nullable IRecentsAnimationRunner recentsAnimationRunner) { enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "startRecentsActivity()"); final int callingPid = Binder.getCallingPid(); final long origId = Binder.clearCallingIdentity(); Loading @@ -1460,9 +1466,13 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { // Start a new recents animation final RecentsAnimation anim = new RecentsAnimation(this, mStackSupervisor, getActivityStartController(), mWindowManager, callingPid); anim.startRecentsActivity(intent, recentsAnimationRunner, recentsComponent, recentsUid, assistDataReceiver); getActivityStartController(), mWindowManager, intent, recentsComponent, recentsUid, callingPid); if (recentsAnimationRunner == null) { anim.preloadRecentsActivity(); } else { anim.startRecentsActivity(recentsAnimationRunner); } } } finally { Binder.restoreCallingIdentity(origId); Loading services/core/java/com/android/server/wm/RecentsAnimation.java +98 −33 Original line number Diff line number Diff line Loading @@ -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 android.app.ActivityOptions; import android.app.IAssistDataReceiver; import android.content.ComponentName; import android.content.Intent; import android.os.RemoteException; Loading @@ -58,7 +57,12 @@ class RecentsAnimation implements RecentsAnimationCallbacks, private final ActivityStartController mActivityStartController; private final WindowManagerService mWindowManager; private final ActivityDisplay mDefaultDisplay; private final Intent mTargetIntent; private final ComponentName mRecentsComponent; private final int mRecentsUid; 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 Loading @@ -66,27 +70,90 @@ class RecentsAnimation implements RecentsAnimationCallbacks, * for the exact activity. */ private ActivityRecord mLaunchedTargetActivity; private int mTargetActivityType; // The stack to restore the target stack behind when the animation is finished private ActivityStack mRestoreTargetBehindStack; RecentsAnimation(ActivityTaskManagerService atm, ActivityStackSupervisor stackSupervisor, ActivityStartController activityStartController, WindowManagerService wm, int callingPid) { Intent targetIntent, ComponentName recentsComponent, int recentsUid, int callingPid) { mService = atm; mStackSupervisor = stackSupervisor; mDefaultDisplay = mService.mRootActivityContainer.getDefaultDisplay(); mActivityStartController = activityStartController; mWindowManager = wm; mTargetIntent = targetIntent; mRecentsComponent = recentsComponent; mRecentsUid = recentsUid; 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, ComponentName recentsComponent, int recentsUid, @Deprecated IAssistDataReceiver assistDataReceiver) { if (DEBUG) Slog.d(TAG, "startRecentsActivity(): intent=" + intent + " assistDataReceiver=" + assistDataReceiver); // Invisible activity should be stopped. If the recents activity is alive and its doesn't // need to relaunch by current configuration, then it may be already in stopped state. if (!targetActivity.isState(ActivityStack.ActivityState.STOPPING, ActivityStack.ActivityState.STOPPED)) { // 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"); // TODO(multi-display) currently only support recents animation in default display. Loading @@ -100,15 +167,9 @@ class RecentsAnimation implements RecentsAnimationCallbacks, } // 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, mTargetActivityType); ActivityRecord targetActivity = getTargetActivity(targetStack, intent.getComponent(), userId); ActivityRecord targetActivity = getTargetActivity(targetStack); final boolean hasExistingActivity = targetActivity != null; if (hasExistingActivity) { final ActivityDisplay display = targetActivity.getDisplay(); Loading @@ -127,7 +188,7 @@ class RecentsAnimation implements RecentsAnimationCallbacks, true /* forceSend */, targetActivity); } mStackSupervisor.getActivityMetricsLogger().notifyActivityLaunching(intent); mStackSupervisor.getActivityMetricsLogger().notifyActivityLaunching(mTargetIntent); mService.mH.post(() -> mService.mAmInternal.setRunningRemoteAnimation(mCallingPid, true)); Loading @@ -148,23 +209,12 @@ class RecentsAnimation implements RecentsAnimationCallbacks, } } else { // No recents activity, create the new recents activity bottom most ActivityOptions options = ActivityOptions.makeBasic(); 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(); startRecentsActivityInBackground("startRecentsActivity_noTargetActivity"); // Move the recents activity into place for the animation targetStack = mDefaultDisplay.getStack(WINDOWING_MODE_UNDEFINED, mTargetActivityType); targetActivity = getTargetActivity(targetStack, intent.getComponent(), userId); targetActivity = getTargetActivity(targetStack); mDefaultDisplay.moveStackBehindBottomMostVisibleStack(targetStack); if (DEBUG) { Slog.d(TAG, "Moved stack=" + targetStack + " behind stack=" Loading @@ -176,7 +226,7 @@ class RecentsAnimation implements RecentsAnimationCallbacks, // 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 Loading Loading @@ -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. */ Loading Loading @@ -412,15 +477,15 @@ class RecentsAnimation implements RecentsAnimationCallbacks, * @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. */ private ActivityRecord getTargetActivity(ActivityStack targetStack, ComponentName component, int userId) { private ActivityRecord getTargetActivity(ActivityStack targetStack) { if (targetStack == null) { return null; } for (int i = targetStack.getChildCount() - 1; i >= 0; 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(); } } Loading Loading
services/core/java/com/android/server/wm/ActivityRecord.java +8 −14 Original line number Diff line number Diff line Loading @@ -3160,7 +3160,7 @@ final class ActivityRecord extends ConfigurationContainer { boolean ensureActivityConfiguration(int globalChanges, boolean preserveWindow) { return ensureActivityConfiguration(globalChanges, preserveWindow, false /* ignoreStopState */); false /* ignoreVisibility */); } /** Loading @@ -3170,15 +3170,15 @@ final class ActivityRecord extends ConfigurationContainer { * @param globalChanges The changes to the global configuration. * @param preserveWindow If the activity window should be preserved on screen if the activity * is relaunched. * @param ignoreStopState If we should try to relaunch the activity even if it is in the stopped * state. This is useful for the case where we know the activity will be * visible soon and we want to ensure its configuration before we make it * visible. * @param ignoreVisibility If we should try to relaunch the activity even if it is invisible * (stopped state). This is useful for the case where we know the * activity will be visible soon and we want to ensure its configuration * before we make it visible. * @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. */ boolean ensureActivityConfiguration(int globalChanges, boolean preserveWindow, boolean ignoreStopState) { boolean ignoreVisibility) { final ActivityStack stack = getActivityStack(); if (stack.mConfigWillChange) { if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, Loading @@ -3194,15 +3194,9 @@ final class ActivityRecord extends ConfigurationContainer { return true; } if (!ignoreStopState && (mState == STOPPING || mState == STOPPED)) { if (!ignoreVisibility && (mState == STOPPING || mState == STOPPED || !shouldBeVisible())) { if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, "Skipping config check stopped or stopping: " + this); return true; } if (!shouldBeVisible()) { if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, "Skipping config check invisible stack: " + this); "Skipping config check invisible: " + this); return true; } Loading
services/core/java/com/android/server/wm/ActivityStack.java +8 −5 Original line number Diff line number Diff line Loading @@ -1880,8 +1880,7 @@ class ActivityStack extends ConfigurationContainer { mRootActivityContainer.ensureActivitiesVisible(resuming, 0, !PRESERVE_WINDOWS); } private void addToStopping(ActivityRecord r, boolean scheduleIdle, boolean idleDelayed, String reason) { void addToStopping(ActivityRecord r, boolean scheduleIdle, boolean idleDelayed, String reason) { if (!mStackSupervisor.mStoppingActivities.contains(r)) { EventLog.writeEvent(EventLogTags.AM_ADD_TO_STOPPING, r.mUserId, System.identityHashCode(r), r.shortComponentName, reason); Loading Loading @@ -2176,7 +2175,7 @@ class ActivityStack extends ConfigurationContainer { // sure it matches the current configuration. if (r != starting && notifyClients) { r.ensureActivityConfiguration(0 /* globalChanges */, preserveWindows, true /* ignoreStopState */); true /* ignoreVisibility */); } if (!r.attachedToProcess()) { Loading Loading @@ -3145,8 +3144,10 @@ class ActivityStack extends ConfigurationContainer { boolean newTask, boolean keepCurTransition, ActivityOptions options) { TaskRecord rTask = r.getTaskRecord(); final int taskId = rTask.taskId; final boolean allowMoveToFront = options == null || !options.getAvoidMoveToFront(); // 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. // Insert or replace. // Might not even be in. Loading Loading @@ -3205,7 +3206,9 @@ class ActivityStack extends ConfigurationContainer { 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; if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare open transition: starting " + r); Loading
services/core/java/com/android/server/wm/ActivityStarter.java +2 −2 Original line number Diff line number Diff line Loading @@ -2307,12 +2307,12 @@ class ActivityStarter { // isLockTaskModeViolation fails below. if (mReuseTask == null) { final boolean toTop = !mLaunchTaskBehind && !mAvoidMoveToFront; final TaskRecord task = mTargetStack.createTaskRecord( mSupervisor.getNextTaskIdForUserLocked(mStartActivity.mUserId), mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info, mNewTaskIntent != null ? mNewTaskIntent : mIntent, mVoiceSession, mVoiceInteractor, !mLaunchTaskBehind /* toTop */, mStartActivity, mSourceRecord, mOptions); mVoiceInteractor, toTop, mStartActivity, mSourceRecord, mOptions); addOrReparentStartingActivity(task, "setTaskFromReuseOrCreateNewTask - mReuseTask"); updateBounds(mStartActivity.getTaskRecord(), mLaunchParams.mBounds); Loading
services/core/java/com/android/server/wm/ActivityTaskManagerService.java +15 −5 Original line number Diff line number Diff line Loading @@ -1447,9 +1447,15 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { .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 public void startRecentsActivity(Intent intent, IAssistDataReceiver assistDataReceiver, IRecentsAnimationRunner recentsAnimationRunner) { public void startRecentsActivity(Intent intent, @Deprecated IAssistDataReceiver unused, @Nullable IRecentsAnimationRunner recentsAnimationRunner) { enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "startRecentsActivity()"); final int callingPid = Binder.getCallingPid(); final long origId = Binder.clearCallingIdentity(); Loading @@ -1460,9 +1466,13 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { // Start a new recents animation final RecentsAnimation anim = new RecentsAnimation(this, mStackSupervisor, getActivityStartController(), mWindowManager, callingPid); anim.startRecentsActivity(intent, recentsAnimationRunner, recentsComponent, recentsUid, assistDataReceiver); getActivityStartController(), mWindowManager, intent, recentsComponent, recentsUid, callingPid); if (recentsAnimationRunner == null) { anim.preloadRecentsActivity(); } else { anim.startRecentsActivity(recentsAnimationRunner); } } } finally { Binder.restoreCallingIdentity(origId); Loading
services/core/java/com/android/server/wm/RecentsAnimation.java +98 −33 Original line number Diff line number Diff line Loading @@ -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 android.app.ActivityOptions; import android.app.IAssistDataReceiver; import android.content.ComponentName; import android.content.Intent; import android.os.RemoteException; Loading @@ -58,7 +57,12 @@ class RecentsAnimation implements RecentsAnimationCallbacks, private final ActivityStartController mActivityStartController; private final WindowManagerService mWindowManager; private final ActivityDisplay mDefaultDisplay; private final Intent mTargetIntent; private final ComponentName mRecentsComponent; private final int mRecentsUid; 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 Loading @@ -66,27 +70,90 @@ class RecentsAnimation implements RecentsAnimationCallbacks, * for the exact activity. */ private ActivityRecord mLaunchedTargetActivity; private int mTargetActivityType; // The stack to restore the target stack behind when the animation is finished private ActivityStack mRestoreTargetBehindStack; RecentsAnimation(ActivityTaskManagerService atm, ActivityStackSupervisor stackSupervisor, ActivityStartController activityStartController, WindowManagerService wm, int callingPid) { Intent targetIntent, ComponentName recentsComponent, int recentsUid, int callingPid) { mService = atm; mStackSupervisor = stackSupervisor; mDefaultDisplay = mService.mRootActivityContainer.getDefaultDisplay(); mActivityStartController = activityStartController; mWindowManager = wm; mTargetIntent = targetIntent; mRecentsComponent = recentsComponent; mRecentsUid = recentsUid; 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, ComponentName recentsComponent, int recentsUid, @Deprecated IAssistDataReceiver assistDataReceiver) { if (DEBUG) Slog.d(TAG, "startRecentsActivity(): intent=" + intent + " assistDataReceiver=" + assistDataReceiver); // Invisible activity should be stopped. If the recents activity is alive and its doesn't // need to relaunch by current configuration, then it may be already in stopped state. if (!targetActivity.isState(ActivityStack.ActivityState.STOPPING, ActivityStack.ActivityState.STOPPED)) { // 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"); // TODO(multi-display) currently only support recents animation in default display. Loading @@ -100,15 +167,9 @@ class RecentsAnimation implements RecentsAnimationCallbacks, } // 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, mTargetActivityType); ActivityRecord targetActivity = getTargetActivity(targetStack, intent.getComponent(), userId); ActivityRecord targetActivity = getTargetActivity(targetStack); final boolean hasExistingActivity = targetActivity != null; if (hasExistingActivity) { final ActivityDisplay display = targetActivity.getDisplay(); Loading @@ -127,7 +188,7 @@ class RecentsAnimation implements RecentsAnimationCallbacks, true /* forceSend */, targetActivity); } mStackSupervisor.getActivityMetricsLogger().notifyActivityLaunching(intent); mStackSupervisor.getActivityMetricsLogger().notifyActivityLaunching(mTargetIntent); mService.mH.post(() -> mService.mAmInternal.setRunningRemoteAnimation(mCallingPid, true)); Loading @@ -148,23 +209,12 @@ class RecentsAnimation implements RecentsAnimationCallbacks, } } else { // No recents activity, create the new recents activity bottom most ActivityOptions options = ActivityOptions.makeBasic(); 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(); startRecentsActivityInBackground("startRecentsActivity_noTargetActivity"); // Move the recents activity into place for the animation targetStack = mDefaultDisplay.getStack(WINDOWING_MODE_UNDEFINED, mTargetActivityType); targetActivity = getTargetActivity(targetStack, intent.getComponent(), userId); targetActivity = getTargetActivity(targetStack); mDefaultDisplay.moveStackBehindBottomMostVisibleStack(targetStack); if (DEBUG) { Slog.d(TAG, "Moved stack=" + targetStack + " behind stack=" Loading @@ -176,7 +226,7 @@ class RecentsAnimation implements RecentsAnimationCallbacks, // 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 Loading Loading @@ -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. */ Loading Loading @@ -412,15 +477,15 @@ class RecentsAnimation implements RecentsAnimationCallbacks, * @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. */ private ActivityRecord getTargetActivity(ActivityStack targetStack, ComponentName component, int userId) { private ActivityRecord getTargetActivity(ActivityStack targetStack) { if (targetStack == null) { return null; } for (int i = targetStack.getChildCount() - 1; i >= 0; 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(); } } Loading