Move activity timeouts to ActivityRecord (81/n)
Reduces reliance on ActivityStack
Also:
- Removed AS#mWindowManager and use mWmService instead
- Renames AS#mService to mAtmService
- Removed AS#mLruActivities which was only used for logging
Change-Id: I61ade9104b9be65b69f68f3055ad2c226d364202
Test: Existing tests pass.
Bug: 80414790
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index b09e19f..cffcfef 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -379,6 +379,27 @@
@VisibleForTesting static final int Z_BOOST_BASE = 800570000;
static final int INVALID_PID = -1;
+ // How long we wait until giving up on the last activity to pause. This
+ // is short because it directly impacts the responsiveness of starting the
+ // next activity.
+ private static final int PAUSE_TIMEOUT = 500;
+
+ // Ticks during which we check progress while waiting for an app to launch.
+ private static final int LAUNCH_TICK = 500;
+
+ // How long we wait for the activity to tell us it has stopped before
+ // giving up. This is a good amount of time because we really need this
+ // from the application in order to get its saved state. Once the stop
+ // is complete we may start destroying client resources triggering
+ // crashes if the UI thread was hung. We put this timeout one second behind
+ // the ANR timeout so these situations will generate ANR instead of
+ // Surface lost or other errors.
+ private static final int STOP_TIMEOUT = 11 * 1000;
+
+ // How long we wait until giving up on an activity telling us it has
+ // finished destroying itself.
+ private static final int DESTROY_TIMEOUT = 10 * 1000;
+
final ActivityTaskManagerService mAtmService;
final ActivityInfo info; // activity info provided by developer in AndroidManifest
// Non-null only for application tokens.
@@ -681,6 +702,55 @@
// Token for targeting this activity for assist purposes.
final Binder assistToken = new Binder();
+ private final Runnable mPauseTimeoutRunnable = new Runnable() {
+ @Override
+ public void run() {
+ // We don't at this point know if the activity is fullscreen,
+ // so we need to be conservative and assume it isn't.
+ Slog.w(TAG, "Activity pause timeout for " + ActivityRecord.this);
+ synchronized (mAtmService.mGlobalLock) {
+ if (hasProcess()) {
+ mAtmService.logAppTooSlow(app, pauseTime, "pausing " + ActivityRecord.this);
+ }
+ activityPaused(true);
+ }
+ }
+ };
+
+ private final Runnable mLaunchTickRunnable = new Runnable() {
+ @Override
+ public void run() {
+ synchronized (mAtmService.mGlobalLock) {
+ if (continueLaunchTicking()) {
+ mAtmService.logAppTooSlow(
+ app, launchTickTime, "launching " + ActivityRecord.this);
+ }
+ }
+ }
+ };
+
+ private final Runnable mDestroyTimeoutRunnable = new Runnable() {
+ @Override
+ public void run() {
+ synchronized (mAtmService.mGlobalLock) {
+ Slog.w(TAG, "Activity destroy timeout for " + ActivityRecord.this);
+ destroyed("destroyTimeout");
+ }
+ }
+ };
+
+ private final Runnable mStopTimeoutRunnable = new Runnable() {
+ @Override
+ public void run() {
+ synchronized (mAtmService.mGlobalLock) {
+ Slog.w(TAG, "Activity stop timeout for " + ActivityRecord.this);
+ if (isInHistory()) {
+ activityStopped(null /*icicle*/, null /*persistentState*/, null /*description*/);
+ }
+ }
+ }
+ };
+
private static String startingWindowStateToString(int state) {
switch (state) {
case STARTING_WINDOW_NOT_SHOWN:
@@ -2684,11 +2754,6 @@
EventLogTags.writeWmDestroyActivity(mUserId, System.identityHashCode(this),
task.mTaskId, shortComponentName, reason);
- final ActivityStack stack = getActivityStack();
- if (hasProcess() && !stack.inLruList(this)) {
- Slog.w(TAG, "Activity " + this + " being finished, but not in LRU list");
- }
-
boolean removedFromHistory = false;
cleanUp(false /* cleanServices */, false /* setState */);
@@ -2735,7 +2800,7 @@
}
setState(DESTROYING,
"destroyActivityLocked. finishing and not skipping destroy");
- stack.scheduleDestroyTimeoutForActivity(this);
+ mAtmService.mH.postDelayed(mDestroyTimeoutRunnable, DESTROY_TIMEOUT);
} else {
if (DEBUG_STATES) {
Slog.v(TAG_STATES, "Moving to DESTROYED: " + this + " (destroy skipped)");
@@ -2785,8 +2850,7 @@
}
takeFromHistory();
- final ActivityStack stack = getActivityStack();
- stack.removeTimeoutsForActivity(this);
+ removeTimeouts();
if (DEBUG_STATES) {
Slog.v(TAG_STATES, "Moving to DESTROYED: " + this + " (removed from history)");
}
@@ -2814,7 +2878,7 @@
* AND finished.
*/
void destroyed(String reason) {
- getActivityStack().removeDestroyTimeoutForActivity(this);
+ removeDestroyTimeout();
if (DEBUG_CONTAINERS) Slog.d(TAG_CONTAINERS, "activityDestroyedLocked: r=" + this);
@@ -2872,7 +2936,7 @@
}
// Get rid of any pending idle timeouts.
- stack.removeTimeoutsForActivity(this);
+ removeTimeouts();
// Clean-up activities are no longer relaunching (e.g. app process died). Notify window
// manager so it can update its bookkeeping.
clearRelaunching();
@@ -4737,6 +4801,73 @@
}
}
+ void activityPaused(boolean timeout) {
+ if (DEBUG_PAUSE) Slog.v(TAG_PAUSE,
+ "Activity paused: token=" + appToken + ", timeout=" + timeout);
+
+ final ActivityStack stack = getStack();
+
+ if (stack != null) {
+ removePauseTimeout();
+
+ if (stack.mPausingActivity == this) {
+ if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to PAUSED: " + this
+ + (timeout ? " (due to timeout)" : " (pause complete)"));
+ mAtmService.deferWindowLayout();
+ try {
+ stack.completePauseLocked(true /* resumeNext */, null /* resumingActivity */);
+ } finally {
+ mAtmService.continueWindowLayout();
+ }
+ return;
+ } else {
+ EventLogTags.writeWmFailedToPause(mUserId, System.identityHashCode(this),
+ shortComponentName, stack.mPausingActivity != null
+ ? stack.mPausingActivity.shortComponentName : "(none)");
+ if (isState(PAUSING)) {
+ setState(PAUSED, "activityPausedLocked");
+ if (finishing) {
+ if (DEBUG_PAUSE) Slog.v(TAG,
+ "Executing finish of failed to pause activity: " + this);
+ completeFinishing("activityPausedLocked");
+ }
+ }
+ }
+ }
+
+ mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
+ }
+
+ /**
+ * Schedule a pause timeout in case the app doesn't respond. We don't give it much time because
+ * this directly impacts the responsiveness seen by the user.
+ */
+ void schedulePauseTimeout() {
+ pauseTime = SystemClock.uptimeMillis();
+ mAtmService.mH.postDelayed(mPauseTimeoutRunnable, PAUSE_TIMEOUT);
+ if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Waiting for pause to complete...");
+ }
+
+ private void removePauseTimeout() {
+ mAtmService.mH.removeCallbacks(mPauseTimeoutRunnable);
+ }
+
+ private void removeDestroyTimeout() {
+ mAtmService.mH.removeCallbacks(mDestroyTimeoutRunnable);
+ }
+
+ private void removeStopTimeout() {
+ mAtmService.mH.removeCallbacks(mStopTimeoutRunnable);
+ }
+
+ void removeTimeouts() {
+ mStackSupervisor.removeIdleTimeoutForActivity(this);
+ removePauseTimeout();
+ removeStopTimeout();
+ removeDestroyTimeout();
+ finishLaunchTickingLocked();
+ }
+
void stopIfPossible() {
if (DEBUG_SWITCH) Slog.d(TAG_SWITCH, "Stopping: " + this);
final ActivityStack stack = getActivityStack();
@@ -4783,7 +4914,7 @@
if (stack.shouldSleepOrShutDownActivities()) {
setSleeping(true);
}
- stack.scheduleStopTimeoutForActivity(this);
+ mAtmService.mH.postDelayed(mStopTimeoutRunnable, STOP_TIMEOUT);
} catch (Exception e) {
// Maybe just ignore exceptions here... if the process has crashed, our death
// notification will clean things up.
@@ -4798,13 +4929,13 @@
}
}
- final void activityStoppedLocked(Bundle newIcicle, PersistableBundle newPersistentState,
+ void activityStopped(Bundle newIcicle, PersistableBundle newPersistentState,
CharSequence description) {
final ActivityStack stack = getActivityStack();
final boolean isStopping = mState == STOPPING;
if (!isStopping && mState != RESTARTING_PROCESS) {
Slog.i(TAG, "Activity reported stop, but no longer stopping: " + this);
- stack.removeStopTimeoutForActivity(this);
+ removeStopTimeout();
return;
}
if (newPersistentState != null) {
@@ -4822,7 +4953,7 @@
if (DEBUG_SAVED_STATE) Slog.i(TAG_SAVED_STATE, "Saving icicle of " + this + ": " + mIcicle);
if (!stopped) {
if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to STOPPED: " + this + " (stop complete)");
- stack.removeStopTimeoutForActivity(this);
+ removeStopTimeout();
stopped = true;
if (isStopping) {
setState(STOPPED, "activityStoppedLocked");
@@ -4877,11 +5008,11 @@
}
if (launchTickTime == 0) {
launchTickTime = SystemClock.uptimeMillis();
- continueLaunchTickingLocked();
+ continueLaunchTicking();
}
}
- boolean continueLaunchTickingLocked() {
+ private boolean continueLaunchTicking() {
if (launchTickTime == 0) {
return false;
}
@@ -4892,10 +5023,14 @@
}
stack.removeLaunchTickMessages();
- stack.scheduleLaunchTickForActivity(this);
+ mAtmService.mH.postDelayed(mLaunchTickRunnable, LAUNCH_TICK);
return true;
}
+ void removeLaunchTickRunnable() {
+ mAtmService.mH.removeCallbacks(mLaunchTickRunnable);
+ }
+
void finishLaunchTickingLocked() {
launchTickTime = 0;
final ActivityStack stack = getActivityStack();
@@ -7017,10 +7152,7 @@
newIntents = null;
mAtmService.getAppWarningsLocked().onResumeActivity(this);
} else {
- final ActivityStack stack = getActivityStack();
- if (stack != null) {
- stack.removePauseTimeoutForActivity(this);
- }
+ removePauseTimeout();
setState(PAUSED, "relaunchActivityLocked");
}
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index 7935dba..37ceb73 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -192,7 +192,7 @@
private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStack" : TAG_ATM;
static final String TAG_ADD_REMOVE = TAG + POSTFIX_ADD_REMOVE;
private static final String TAG_APP = TAG + POSTFIX_APP;
- private static final String TAG_CLEANUP = TAG + POSTFIX_CLEANUP;
+ static final String TAG_CLEANUP = TAG + POSTFIX_CLEANUP;
private static final String TAG_PAUSE = TAG + POSTFIX_PAUSE;
private static final String TAG_RELEASE = TAG + POSTFIX_RELEASE;
private static final String TAG_RESULTS = TAG + POSTFIX_RESULTS;
@@ -204,27 +204,6 @@
private static final String TAG_USER_LEAVING = TAG + POSTFIX_USER_LEAVING;
static final String TAG_VISIBILITY = TAG + POSTFIX_VISIBILITY;
- // Ticks during which we check progress while waiting for an app to launch.
- private static final int LAUNCH_TICK = 500;
-
- // How long we wait until giving up on the last activity to pause. This
- // is short because it directly impacts the responsiveness of starting the
- // next activity.
- private static final int PAUSE_TIMEOUT = 500;
-
- // How long we wait for the activity to tell us it has stopped before
- // giving up. This is a good amount of time because we really need this
- // from the application in order to get its saved state. Once the stop
- // is complete we may start destroying client resources triggering
- // crashes if the UI thread was hung. We put this timeout one second behind
- // the ANR timeout so these situations will generate ANR instead of
- // Surface lost or other errors.
- private static final int STOP_TIMEOUT = 11 * 1000;
-
- // How long we wait until giving up on an activity telling us it has
- // finished destroying itself.
- private static final int DESTROY_TIMEOUT = 10 * 1000;
-
// Set to false to disable the preview that is shown while a new activity
// is being started.
private static final boolean SHOW_APP_STARTING_PREVIEW = true;
@@ -270,15 +249,7 @@
RESTARTING_PROCESS
}
- final ActivityTaskManagerService mService;
- final WindowManagerService mWindowManager;
-
- /**
- * List of running activities, sorted by recent usage.
- * The first entry in the list is the least recently used.
- * It contains HistoryRecord objects.
- */
- private final ArrayList<ActivityRecord> mLruActivities = new ArrayList<>();
+ final ActivityTaskManagerService mAtmService;
/**
* When we are in the process of pausing an activity, before starting the
@@ -418,21 +389,7 @@
private boolean mTopActivityOccludesKeyguard;
private ActivityRecord mTopDismissingKeyguardActivity;
- private static final int PAUSE_TIMEOUT_MSG = FIRST_ACTIVITY_STACK_MSG + 1;
- private static final int DESTROY_TIMEOUT_MSG = FIRST_ACTIVITY_STACK_MSG + 2;
- private static final int LAUNCH_TICK_MSG = FIRST_ACTIVITY_STACK_MSG + 3;
- private static final int STOP_TIMEOUT_MSG = FIRST_ACTIVITY_STACK_MSG + 4;
- private static final int DESTROY_ACTIVITIES_MSG = FIRST_ACTIVITY_STACK_MSG + 5;
- private static final int TRANSLUCENT_TIMEOUT_MSG = FIRST_ACTIVITY_STACK_MSG + 6;
-
- private static class ScheduleDestroyArgs {
- final WindowProcessController mOwner;
- final String mReason;
- ScheduleDestroyArgs(WindowProcessController owner, String reason) {
- mOwner = owner;
- mReason = reason;
- }
- }
+ private static final int TRANSLUCENT_TIMEOUT_MSG = FIRST_ACTIVITY_STACK_MSG + 1;
private final Handler mHandler;
@@ -445,57 +402,8 @@
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
- case PAUSE_TIMEOUT_MSG: {
- ActivityRecord r = (ActivityRecord)msg.obj;
- // We don't at this point know if the activity is fullscreen,
- // so we need to be conservative and assume it isn't.
- Slog.w(TAG, "Activity pause timeout for " + r);
- synchronized (mService.mGlobalLock) {
- if (r.hasProcess()) {
- mService.logAppTooSlow(r.app, r.pauseTime, "pausing " + r);
- }
- activityPausedLocked(r.appToken, true);
- }
- } break;
- case LAUNCH_TICK_MSG: {
- ActivityRecord r = (ActivityRecord)msg.obj;
- synchronized (mService.mGlobalLock) {
- if (r.continueLaunchTickingLocked()) {
- mService.logAppTooSlow(r.app, r.launchTickTime, "launching " + r);
- }
- }
- } break;
- case DESTROY_TIMEOUT_MSG: {
- ActivityRecord r = (ActivityRecord)msg.obj;
- // We don't at this point know if the activity is fullscreen,
- // so we need to be conservative and assume it isn't.
- Slog.w(TAG, "Activity destroy timeout for " + r);
- synchronized (mService.mGlobalLock) {
- if (r != null) {
- r.destroyed("destroyTimeout");
- }
- }
- } break;
- case STOP_TIMEOUT_MSG: {
- ActivityRecord r = (ActivityRecord)msg.obj;
- // We don't at this point know if the activity is fullscreen,
- // so we need to be conservative and assume it isn't.
- Slog.w(TAG, "Activity stop timeout for " + r);
- synchronized (mService.mGlobalLock) {
- if (r.isInHistory()) {
- r.activityStoppedLocked(null /* icicle */,
- null /* persistentState */, null /* description */);
- }
- }
- } break;
- case DESTROY_ACTIVITIES_MSG: {
- ScheduleDestroyArgs args = (ScheduleDestroyArgs)msg.obj;
- synchronized (mService.mGlobalLock) {
- destroyActivities(args.mOwner, args.mReason);
- }
- } break;
case TRANSLUCENT_TIMEOUT_MSG: {
- synchronized (mService.mGlobalLock) {
+ synchronized (mAtmService.mGlobalLock) {
notifyActivityDrawnLocked(null);
}
} break;
@@ -737,12 +645,11 @@
com.android.internal.R.dimen.docked_stack_minimize_thickness);
EventLogTags.writeWmStackCreated(stackId);
mStackSupervisor = supervisor;
- mService = supervisor.mService;
- mRootActivityContainer = mService.mRootActivityContainer;
+ mAtmService = supervisor.mService;
+ mRootActivityContainer = mAtmService.mRootActivityContainer;
mHandler = new ActivityStackHandler(supervisor.mLooper);
- mWindowManager = mService.mWindowManager;
mRemoteToken = new RemoteToken(this);
- mCurrentUser = mService.mAmInternal.getCurrentUserId();
+ mCurrentUser = mAtmService.mAmInternal.getCurrentUserId();
// Set display id before setting activity and window type to make sure it won't affect
// stacks on a wrong display.
mDisplayId = display.mDisplayId;
@@ -767,7 +674,7 @@
+ reason);
setResumedActivity(record, reason + " - onActivityStateChanged");
if (record == mRootActivityContainer.getTopResumedActivity()) {
- mService.setResumedActivityUncheckLocked(record, reason);
+ mAtmService.setResumedActivityUncheckLocked(record, reason);
}
mStackSupervisor.mRecentTasks.add(record.getTask());
}
@@ -922,7 +829,7 @@
*/
void setWindowingMode(int preferredWindowingMode, boolean animate, boolean showRecents,
boolean enteringSplitScreenMode, boolean deferEnsuringVisibility, boolean creating) {
- mWindowManager.inSurfaceTransaction(() -> setWindowingModeInSurfaceTransaction(
+ mWmService.inSurfaceTransaction(() -> setWindowingModeInSurfaceTransaction(
preferredWindowingMode, animate, showRecents, enteringSplitScreenMode,
deferEnsuringVisibility, creating));
}
@@ -970,7 +877,7 @@
// Looks like we can't launch in split screen mode or the stack we are launching
// doesn't support split-screen mode, go ahead an dismiss split-screen and display a
// warning toast about it.
- mService.getTaskChangeNotificationController().notifyActivityDismissingDockedStack();
+ mAtmService.getTaskChangeNotificationController().notifyActivityDismissingDockedStack();
final ActivityStack primarySplitStack = display.getSplitScreenPrimaryStack();
primarySplitStack.setWindowingModeInSurfaceTransaction(WINDOWING_MODE_UNDEFINED,
false /* animate */, false /* showRecents */,
@@ -1004,11 +911,11 @@
// Inform the user that they are starting an app that may not work correctly in
// multi-window mode.
final String packageName = topActivity.info.applicationInfo.packageName;
- mService.getTaskChangeNotificationController().notifyActivityForcedResizable(
+ mAtmService.getTaskChangeNotificationController().notifyActivityForcedResizable(
topTask.mTaskId, FORCED_RESIZEABLE_REASON_SPLIT_SCREEN, packageName);
}
- mService.deferWindowLayout();
+ mAtmService.deferWindowLayout();
try {
if (!animate && topActivity != null) {
mStackSupervisor.mNoAnimActivities.add(topActivity);
@@ -1063,16 +970,16 @@
// task, and from the tests
// TODO (b/78247419): Fix the rotation animation from fullscreen to minimized mode
final boolean isRecentsComponentHome =
- mService.getRecentTasks().isRecentsComponentHomeActivity(mCurrentUser);
+ mAtmService.getRecentTasks().isRecentsComponentHomeActivity(mCurrentUser);
final ActivityStack recentStack = display.getOrCreateStack(
WINDOWING_MODE_SPLIT_SCREEN_SECONDARY,
isRecentsComponentHome ? ACTIVITY_TYPE_HOME : ACTIVITY_TYPE_RECENTS,
true /* onTop */);
recentStack.moveToFront("setWindowingMode");
// If task moved to docked stack - show recents if needed.
- mService.mWindowManager.showRecentApps();
+ mWmService.showRecentApps();
}
- mService.continueWindowLayout();
+ mAtmService.continueWindowLayout();
}
if (!deferEnsuringVisibility) {
@@ -1240,18 +1147,6 @@
return display != null && display.isSingleTaskInstance();
}
- /** @return {@code true} if LRU list contained the specified activity. */
- final boolean inLruList(ActivityRecord activity) {
- return mLruActivities.contains(activity);
- }
-
- /** @return {@code true} if the given activity was contained in LRU list. */
- final boolean updateLruList(ActivityRecord r) {
- final boolean contained = mLruActivities.remove(r);
- mLruActivities.add(r);
- return contained;
- }
-
final boolean isHomeOrRecentsStack() {
return isActivityTypeHome() || isActivityTypeRecents();
}
@@ -1375,7 +1270,7 @@
private void clearLaunchTime(ActivityRecord r) {
// Make sure that there is no activity waiting for this to launch.
if (!mStackSupervisor.mWaitingActivityLaunched.isEmpty()) {
- mStackSupervisor.removeTimeoutsForActivityLocked(r);
+ mStackSupervisor.removeIdleTimeoutForActivity(r);
mStackSupervisor.scheduleIdleTimeoutLocked(r);
}
}
@@ -1385,7 +1280,7 @@
forAllActivities((Consumer<ActivityRecord>) (r) -> r.setSleeping(false));
if (mPausingActivity != null) {
Slog.d(TAG, "awakeFromSleepingLocked: previously pausing activity didn't pause");
- activityPausedLocked(mPausingActivity.appToken, true);
+ mPausingActivity.activityPaused(true);
}
}
@@ -1520,7 +1415,7 @@
prev.getTask().touchActiveTime();
clearLaunchTime(prev);
- mService.updateCpuStats();
+ mAtmService.updateCpuStats();
boolean pauseImmediately = false;
if (resuming != null && (resuming.info.flags & FLAG_RESUME_WHILE_PAUSING) != 0) {
@@ -1541,7 +1436,7 @@
EventLogTags.writeWmPauseActivity(prev.mUserId, System.identityHashCode(prev),
prev.shortComponentName, "userLeaving=" + userLeaving);
- mService.getLifecycleManager().scheduleTransaction(prev.app.getThread(),
+ mAtmService.getLifecycleManager().scheduleTransaction(prev.app.getThread(),
prev.appToken, PauseActivityItem.obtain(prev.finishing, userLeaving,
prev.configChangeFlags, pauseImmediately));
} catch (Exception e) {
@@ -1559,7 +1454,7 @@
// If we are not going to sleep, we want to ensure the device is
// awake until the next activity is started.
- if (!uiSleeping && !mService.isSleepingOrShuttingDownLocked()) {
+ if (!uiSleeping && !mAtmService.isSleepingOrShuttingDownLocked()) {
mStackSupervisor.acquireLaunchWakelock();
}
@@ -1581,7 +1476,7 @@
return false;
} else {
- schedulePauseTimeoutForActivity(prev);
+ prev.schedulePauseTimeout();
return true;
}
@@ -1596,41 +1491,6 @@
}
}
- final void activityPausedLocked(IBinder token, boolean timeout) {
- if (DEBUG_PAUSE) Slog.v(TAG_PAUSE,
- "Activity paused: token=" + token + ", timeout=" + timeout);
-
- final ActivityRecord r = isInStackLocked(token);
-
- if (r != null) {
- mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
- if (mPausingActivity == r) {
- if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to PAUSED: " + r
- + (timeout ? " (due to timeout)" : " (pause complete)"));
- mService.deferWindowLayout();
- try {
- completePauseLocked(true /* resumeNext */, null /* resumingActivity */);
- } finally {
- mService.continueWindowLayout();
- }
- return;
- } else {
- EventLogTags.writeWmFailedToPause(r.mUserId, System.identityHashCode(r),
- r.shortComponentName, mPausingActivity != null
- ? mPausingActivity.shortComponentName : "(none)");
- if (r.isState(PAUSING)) {
- r.setState(PAUSED, "activityPausedLocked");
- if (r.finishing) {
- if (DEBUG_PAUSE) Slog.v(TAG,
- "Executing finish of failed to pause activity: " + r);
- r.completeFinishing("activityPausedLocked");
- }
- }
- }
- }
- mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
- }
-
@VisibleForTesting
void completePauseLocked(boolean resumeNext, ActivityRecord resuming) {
ActivityRecord prev = mPausingActivity;
@@ -1702,10 +1562,10 @@
if (diff > 0) {
final Runnable r = PooledLambda.obtainRunnable(
ActivityManagerInternal::updateForegroundTimeIfOnBattery,
- mService.mAmInternal, prev.info.packageName,
+ mAtmService.mAmInternal, prev.info.packageName,
prev.info.applicationInfo.uid,
diff);
- mService.mH.post(r);
+ mAtmService.mH.post(r);
}
}
prev.cpuTimeAtResume = 0; // reset it
@@ -1716,7 +1576,7 @@
// task stack changes, because its positioning may depend on it.
if (mStackSupervisor.mAppVisibilitiesChangedSinceLastPause
|| (getDisplay() != null && getDisplay().hasPinnedStack())) {
- mService.getTaskChangeNotificationController().notifyTaskStackChanged();
+ mAtmService.getTaskChangeNotificationController().notifyTaskStackChanged();
mStackSupervisor.mAppVisibilitiesChangedSinceLastPause = false;
}
@@ -1839,7 +1699,7 @@
if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
if (activityType == ACTIVITY_TYPE_HOME
|| (activityType == ACTIVITY_TYPE_ASSISTANT
- && mWindowManager.getRecentsAnimationController() != null)) {
+ && mWmService.getRecentsAnimationController() != null)) {
break;
}
}
@@ -2085,7 +1945,7 @@
mHandler.removeMessages(TRANSLUCENT_TIMEOUT_MSG);
if (waitingActivity != null) {
- mWindowManager.setWindowOpaqueLocked(waitingActivity.appToken, false);
+ mWmService.setWindowOpaqueLocked(waitingActivity.appToken, false);
if (waitingActivity.attachedToProcess()) {
try {
waitingActivity.app.getThread().scheduleTranslucentConversionComplete(
@@ -2182,7 +2042,7 @@
@GuardedBy("mService")
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
- if (!mService.isBooting() && !mService.isBooted()) {
+ if (!mAtmService.isBooting() && !mAtmService.isBooted()) {
// Not ready yet!
return false;
}
@@ -2237,7 +2097,7 @@
// If the current top activity may be able to occlude keyguard but the occluded state
// has not been set, update visibility and check again if we should continue to resume.
boolean nothingToResume = true;
- if (!mService.mShuttingDown) {
+ if (!mAtmService.mShuttingDown) {
final boolean canShowWhenLocked = !mTopActivityOccludesKeyguard
&& next.canShowWhenLocked();
final boolean mayDismissKeyguard = mTopDismissingKeyguardActivity != next
@@ -2262,7 +2122,7 @@
// Make sure that the user who owns this activity is started. If not,
// we will just leave it as is because someone should be bringing
// another user's activities to the top of the stack.
- if (!mService.mAmInternal.hasStartedUserState(next.mUserId)) {
+ if (!mAtmService.mAmInternal.hasStartedUserState(next.mUserId)) {
Slog.w(TAG, "Skipping resume of top activity " + next
+ ": user " + next.mUserId + " is stopped");
return false;
@@ -2322,7 +2182,7 @@
// activity isn't running, we can start the process earlier to save the time to wait
// for the current activity to be paused.
final boolean isTop = this == display.getFocusedStack();
- mService.startProcessAsync(next, false /* knownToBeDead */, isTop,
+ mAtmService.startProcessAsync(next, false /* knownToBeDead */, isTop,
isTop ? "pre-top-activity" : "pre-activity");
}
if (lastResumed != null) {
@@ -2379,7 +2239,7 @@
// Launching this app's activity, make sure the app is no longer
// considered stopped.
try {
- mService.getPackageManager().setPackageStoppedState(
+ mAtmService.getPackageManager().setPackageStoppedState(
next.packageName, false, next.mUserId); /* TODO: Verify if correct userid */
} catch (RemoteException e1) {
} catch (IllegalArgumentException e) {
@@ -2465,7 +2325,7 @@
lastFocusedStack == null ? null : lastFocusedStack.mResumedActivity;
final ActivityState lastState = next.getState();
- mService.updateCpuStats();
+ mAtmService.updateCpuStats();
if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to RESUMED: " + next
+ " (in existing)");
@@ -2474,7 +2334,6 @@
next.app.updateProcessInfo(false /* updateServiceConnectionActivities */,
true /* activityChange */, true /* updateOomAdj */);
- updateLruList(next);
// Have the window manager re-evaluate the orientation of
// the screen based on the new activity order.
@@ -2543,13 +2402,13 @@
next.getTask().mTaskId, next.shortComponentName);
next.sleeping = false;
- mService.getAppWarningsLocked().onResumeActivity(next);
- next.app.setPendingUiCleanAndForceProcessStateUpTo(mService.mTopProcessState);
+ mAtmService.getAppWarningsLocked().onResumeActivity(next);
+ next.app.setPendingUiCleanAndForceProcessStateUpTo(mAtmService.mTopProcessState);
next.clearOptionsLocked();
transaction.setLifecycleStateRequest(
ResumeActivityItem.obtain(next.app.getReportedProcState(),
dc.isNextTransitionForward()));
- mService.getLifecycleManager().scheduleTransaction(transaction);
+ mAtmService.getLifecycleManager().scheduleTransaction(transaction);
if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Resumed "
+ next);
@@ -2861,7 +2720,7 @@
// Set focused app directly because if the next focused activity is already resumed
// (e.g. the next top activity is on a different display), there won't have activity
// state change to update it.
- mService.setResumedActivityUncheckLocked(stack.mResumedActivity, reason);
+ mAtmService.setResumedActivityUncheckLocked(stack.mResumedActivity, reason);
}
return stack;
}
@@ -2892,7 +2751,7 @@
if (activityBelow != null) {
if (activityBelow.isState(STARTED, RESUMED, PAUSING, PAUSED)) {
if (!activityBelow.isActivityTypeHome()
- || mService.mHomeProcess != activityBelow.app) {
+ || mAtmService.mHomeProcess != activityBelow.app) {
Slog.w(TAG, " Force finishing activity "
+ activityBelow.intent.getComponent().flattenToShortString());
activityBelow.finishIfPossible(reason, false /* oomAdj */);
@@ -3023,7 +2882,7 @@
// TODO: There is a dup. of this block of code in ActivityTaskManagerService.finishActivity
// We should consolidate.
- IActivityController controller = mService.mController;
+ IActivityController controller = mAtmService.mController;
if (controller != null) {
ActivityRecord next = topRunningActivity(srec.appToken, INVALID_TASK_ID);
if (next != null) {
@@ -3032,7 +2891,7 @@
try {
resumeOK = controller.activityResuming(next.packageName);
} catch (RemoteException e) {
- mService.mController = null;
+ mAtmService.mController = null;
Watchdog.getInstance().setActivityController(null);
}
@@ -3076,7 +2935,7 @@
destIntent.getComponent(), ActivityManagerService.STOCK_PM_FLAGS,
srec.mUserId);
// TODO(b/64750076): Check if calling pid should really be -1.
- final int res = mService.getActivityStartController()
+ final int res = mAtmService.getActivityStartController()
.obtainStarter(destIntent, "navigateUpTo")
.setCaller(srec.app.getThread())
.setActivityInfo(aInfo)
@@ -3104,10 +2963,9 @@
* an activity moves away from the stack.
*/
void onActivityRemovedFromStack(ActivityRecord r) {
- removeTimeoutsForActivity(r);
+ r.removeTimeouts();
mExitingActivities.remove(r);
- mLruActivities.remove(r);
if (mResumedActivity != null && mResumedActivity == r) {
setResumedActivity(null, "onActivityRemovedFromStack");
@@ -3121,120 +2979,10 @@
if (r.isState(RESUMED)) {
setResumedActivity(r, "onActivityAddedToStack");
}
- if (r.hasProcess()) {
- updateLruList(r);
- }
- }
-
- void removeTimeoutsForActivity(ActivityRecord r) {
- mStackSupervisor.removeTimeoutsForActivityLocked(r);
- removePauseTimeoutForActivity(r);
- removeStopTimeoutForActivity(r);
- removeDestroyTimeoutForActivity(r);
- r.finishLaunchTickingLocked();
- }
-
- void scheduleDestroyActivities(WindowProcessController owner, String reason) {
- final Message msg = mHandler.obtainMessage(DESTROY_ACTIVITIES_MSG);
- msg.obj = new ScheduleDestroyArgs(owner, reason);
- mHandler.sendMessage(msg);
- }
-
- void scheduleDestroyTimeoutForActivity(ActivityRecord r) {
- final Message msg = mHandler.obtainMessage(DESTROY_TIMEOUT_MSG, r);
- mHandler.sendMessageDelayed(msg, DESTROY_TIMEOUT);
- }
-
- void removeDestroyTimeoutForActivity(ActivityRecord r) {
- mHandler.removeMessages(DESTROY_TIMEOUT_MSG, r);
- }
-
- void scheduleStopTimeoutForActivity(ActivityRecord r) {
- final Message msg = mHandler.obtainMessage(STOP_TIMEOUT_MSG, r);
- mHandler.sendMessageDelayed(msg, STOP_TIMEOUT);
- }
-
- void removeStopTimeoutForActivity(ActivityRecord r) {
- mHandler.removeMessages(STOP_TIMEOUT_MSG, r);
- }
-
- /**
- * Schedule a pause timeout in case the app doesn't respond. We don't give it much time because
- * this directly impacts the responsiveness seen by the user.
- */
- private void schedulePauseTimeoutForActivity(ActivityRecord r) {
- final Message msg = mHandler.obtainMessage(PAUSE_TIMEOUT_MSG, r);
- r.pauseTime = SystemClock.uptimeMillis();
- mHandler.sendMessageDelayed(msg, PAUSE_TIMEOUT);
- if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Waiting for pause to complete...");
- }
-
- void removePauseTimeoutForActivity(ActivityRecord r) {
- mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
- }
-
- void scheduleLaunchTickForActivity(ActivityRecord r) {
- final Message msg = mHandler.obtainMessage(LAUNCH_TICK_MSG, r);
- mHandler.sendMessageDelayed(msg, LAUNCH_TICK);
}
void removeLaunchTickMessages() {
- mHandler.removeMessages(LAUNCH_TICK_MSG);
- }
- /// HANDLER INTERFACE END
-
- private void destroyActivities(WindowProcessController owner, String reason) {
- try {
- mStackSupervisor.beginDeferResume();
-
- final PooledConsumer c = PooledLambda.obtainConsumer(ActivityStack::destroyActivity,
- PooledLambda.__(ActivityRecord.class), owner, reason);
- forAllActivities(c);
- c.recycle();
- } finally {
- mStackSupervisor.endDeferResume();
- mRootActivityContainer.resumeFocusedStacksTopActivities();
- }
- }
-
- private static void destroyActivity(
- ActivityRecord r, WindowProcessController owner, String reason) {
- if (r.finishing || (owner != null && r.app != owner) || !r.isDestroyable()) return;
-
- if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Destroying " + r
- + " in state " + r.getState()
- + " resumed=" + r.getStack().mResumedActivity
- + " pausing=" + r.getStack().mPausingActivity + " for reason " + reason);
-
- r.destroyImmediately(true /* removeFromTask */, reason);
- }
-
- private void removeHistoryRecordsForApp(ArrayList<ActivityRecord> list,
- WindowProcessController app, String listName) {
- int i = list.size();
- if (DEBUG_CLEANUP) Slog.v(TAG_CLEANUP,
- "Removing app " + app + " from list " + listName + " with " + i + " entries");
- while (i > 0) {
- i--;
- ActivityRecord r = list.get(i);
- if (DEBUG_CLEANUP) Slog.v(TAG_CLEANUP, "Record #" + i + " " + r);
- if (r.app == app) {
- if (DEBUG_CLEANUP) Slog.v(TAG_CLEANUP, "---> REMOVING this entry!");
- list.remove(i);
- removeTimeoutsForActivity(r);
- }
- }
- }
-
- private boolean removeHistoryRecordsForApp(WindowProcessController app) {
- removeHistoryRecordsForApp(mLruActivities, app, "mLruActivities");
- removeHistoryRecordsForApp(mStackSupervisor.mStoppingActivities, app,
- "mStoppingActivities");
- removeHistoryRecordsForApp(mStackSupervisor.mGoingToSleepActivities, app,
- "mGoingToSleepActivities");
- removeHistoryRecordsForApp(mStackSupervisor.mFinishingActivities, app,
- "mFinishingActivities");
- return mRemoveHistoryRecordsForApp.process(app);
+ forAllActivities(ActivityRecord::removeLaunchTickRunnable);
}
private void updateTransitLocked(int transit, ActivityOptions options) {
@@ -3324,7 +3072,7 @@
mRootActivityContainer.resumeFocusedStacksTopActivities();
EventLogTags.writeWmTaskToFront(tr.mUserId, tr.mTaskId);
- mService.getTaskChangeNotificationController().notifyTaskMovedToFront(tr.getTaskInfo());
+ mAtmService.getTaskChangeNotificationController().notifyTaskMovedToFront(tr.getTaskInfo());
} finally {
getDisplay().continueUpdateImeTarget();
}
@@ -3346,14 +3094,14 @@
// In LockTask mode, moving a locked task to the back of the stack may expose unlocked
// ones. Therefore we need to check if this operation is allowed.
- if (!mService.getLockTaskController().canMoveTaskToBack(tr)) {
+ if (!mAtmService.getLockTaskController().canMoveTaskToBack(tr)) {
return false;
}
// If we have a watcher, preflight the move before committing to it. First check
// for *other* available tasks, but if none are available, then try again allowing the
// current task to be selected.
- if (isTopStackOnDisplay() && mService.mController != null) {
+ if (isTopStackOnDisplay() && mAtmService.mController != null) {
ActivityRecord next = topRunningActivity(null, tr.mTaskId);
if (next == null) {
next = topRunningActivity(null, INVALID_TASK_ID);
@@ -3362,9 +3110,9 @@
// ask watcher if this is allowed
boolean moveOK = true;
try {
- moveOK = mService.mController.activityResuming(next.packageName);
+ moveOK = mAtmService.mController.activityResuming(next.packageName);
} catch (RemoteException e) {
- mService.mController = null;
+ mAtmService.mController = null;
Watchdog.getInstance().setActivityController(null);
}
if (!moveOK) {
@@ -3415,7 +3163,7 @@
}
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "stack.resize_" + mStackId);
- mService.deferWindowLayout();
+ mAtmService.deferWindowLayout();
try {
// Update override configurations of all tasks in the stack.
final Rect taskBounds = tempTaskBounds != null ? tempTaskBounds : bounds;
@@ -3431,7 +3179,7 @@
ensureVisibleActivitiesConfiguration(topRunningActivity(), preserveWindows);
}
} finally {
- mService.continueWindowLayout();
+ mAtmService.continueWindowLayout();
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
}
@@ -3514,7 +3262,7 @@
* @param app The app of the activity that died.
* @return result from removeHistoryRecordsForAppLocked.
*/
- boolean handleAppDiedLocked(WindowProcessController app) {
+ boolean handleAppDied(WindowProcessController app) {
if (mPausingActivity != null && mPausingActivity.app == app) {
if (DEBUG_PAUSE || DEBUG_CLEANUP) Slog.v(TAG_PAUSE,
"App died while pausing: " + mPausingActivity);
@@ -3525,7 +3273,8 @@
mLastNoHistoryActivity = null;
}
- return removeHistoryRecordsForApp(app);
+ mStackSupervisor.removeHistoryRecords(app);
+ return mRemoveHistoryRecordsForApp.process(app);
}
boolean dump(FileDescriptor fd, PrintWriter pw, boolean dumpAll, boolean dumpClient,
@@ -3538,10 +3287,6 @@
boolean printed = dumpActivities(fd, pw, dumpAll, dumpClient, dumpPackage, needSep);
- printed |= dumpHistoryList(fd, pw, mLruActivities, " ", "Run", false,
- !dumpAll, false, dumpPackage, true,
- " Running activities (most recent first):", null);
-
needSep = printed;
boolean pr = printThisActivity(pw, mPausingActivity, dumpPackage, needSep,
" mPausingActivity: ");
@@ -3666,7 +3411,7 @@
EventLogTags.writeWmRemoveTask(((Task) child).mTaskId, mStackId);
if (display.isSingleTaskInstance()) {
- mService.notifySingleTaskDisplayEmpty(display.mDisplayId);
+ mAtmService.notifySingleTaskDisplayEmpty(display.mDisplayId);
}
display.mDisplayContent.setLayoutNeeded();
@@ -3694,11 +3439,11 @@
boolean toTop, ActivityRecord activity, ActivityRecord source,
ActivityOptions options) {
final Task task = Task.create(
- mService, taskId, info, intent, voiceSession, voiceInteractor, this);
+ mAtmService, taskId, info, intent, voiceSession, voiceInteractor, this);
// add the task to stack first, mTaskPositioner might need the stack association
addChild(task, toTop, (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0);
final int displayId = mDisplayId != INVALID_DISPLAY ? mDisplayId : DEFAULT_DISPLAY;
- final boolean isLockscreenShown = mService.mStackSupervisor.getKeyguardController()
+ final boolean isLockscreenShown = mAtmService.mStackSupervisor.getKeyguardController()
.isKeyguardOrAodShowing(displayId);
if (!mStackSupervisor.getLaunchParamsController()
.layoutTask(task, info.windowLayout, activity, source, options)
@@ -3790,19 +3535,18 @@
// Apps may depend on onResume()/onPause() being called in pairs.
if (setResume) {
r.setState(RESUMED, "moveToFrontAndResumeStateIfNeeded");
- updateLruList(r);
}
// If the activity was previously pausing, then ensure we transfer that as well
if (setPause) {
mPausingActivity = r;
- schedulePauseTimeoutForActivity(r);
+ r.schedulePauseTimeout();
}
// Move the stack in which we are placing the activity to the front.
moveToFront(reason);
// If the original state is resumed, there is no state change to update focused app.
// So here makes sure the activity focus is set if it is the top.
if (origState == RESUMED && r == mRootActivityContainer.getTopResumedActivity()) {
- mService.setResumedActivityUncheckLocked(r, reason);
+ mAtmService.setResumedActivityUncheckLocked(r, reason);
}
}
@@ -3902,14 +3646,14 @@
top.savePinnedStackBounds();
}
- mWindowManager.inSurfaceTransaction(() -> {
+ mWmService.inSurfaceTransaction(() -> {
final Task task = getBottomMostTask();
setWindowingMode(WINDOWING_MODE_UNDEFINED);
getDisplay().positionStackAtTop(this, false /* includingParents */);
mStackSupervisor.scheduleUpdatePictureInPictureModeIfNeeded(task, this);
- MetricsLoggerWrapper.logPictureInPictureFullScreen(mService.mContext,
+ MetricsLoggerWrapper.logPictureInPictureFullScreen(mAtmService.mContext,
task.effectiveUid, task.realActivity.flattenToString());
});
}
@@ -5377,11 +5121,11 @@
return false;
}
- return display != null ? display.isSleeping() : mService.isSleepingLocked();
+ return display != null ? display.isSleeping() : mAtmService.isSleepingLocked();
}
boolean shouldSleepOrShutDownActivities() {
- return shouldSleepActivities() || mService.mShuttingDown;
+ return shouldSleepActivities() || mAtmService.mShuttingDown;
}
public void dumpDebug(ProtoOutputStream proto, long fieldId,
diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
index 26d9dbc..9203fcb 100644
--- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
@@ -52,7 +52,9 @@
import static com.android.server.wm.ActivityStack.ActivityState.PAUSED;
import static com.android.server.wm.ActivityStack.ActivityState.PAUSING;
+import static com.android.server.wm.ActivityStack.TAG_CLEANUP;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_ALL;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_CLEANUP;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_IDLE;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_PAUSE;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RECENTS;
@@ -956,9 +958,6 @@
}
r.launchFailed = false;
- if (stack.updateLruList(r)) {
- Slog.w(TAG, "Activity " + r + " being launched, but already in LRU list");
- }
// TODO(lifecycler): Resume or pause requests are done as part of launch transaction,
// so updating the state should be done accordingly.
@@ -2162,7 +2161,7 @@
if (!processPausingActivities && s.isState(PAUSING)) {
// Defer processing pausing activities in this iteration and reschedule
// a delayed idle to reprocess it again
- removeTimeoutsForActivityLocked(idleActivity);
+ removeIdleTimeoutForActivity(idleActivity);
scheduleIdleTimeoutLocked(idleActivity);
continue;
}
@@ -2181,6 +2180,29 @@
return stops;
}
+ void removeHistoryRecords(WindowProcessController app) {
+ removeHistoryRecords(mStoppingActivities, app, "mStoppingActivities");
+ removeHistoryRecords(mGoingToSleepActivities, app, "mGoingToSleepActivities");
+ removeHistoryRecords(mFinishingActivities, app, "mFinishingActivities");
+ }
+
+ private void removeHistoryRecords(ArrayList<ActivityRecord> list, WindowProcessController app,
+ String listName) {
+ int i = list.size();
+ if (DEBUG_CLEANUP) Slog.v(TAG_CLEANUP,
+ "Removing app " + this + " from list " + listName + " with " + i + " entries");
+ while (i > 0) {
+ i--;
+ ActivityRecord r = list.get(i);
+ if (DEBUG_CLEANUP) Slog.v(TAG_CLEANUP, "Record #" + i + " " + r);
+ if (r.app == app) {
+ if (DEBUG_CLEANUP) Slog.v(TAG_CLEANUP, "---> REMOVING this entry!");
+ list.remove(i);
+ r.removeTimeouts();
+ }
+ }
+ }
+
public void dump(PrintWriter pw, String prefix) {
pw.println();
pw.println("ActivityStackSupervisor state:");
@@ -2371,7 +2393,7 @@
scheduleTopResumedActivityStateIfNeeded();
}
- void removeTimeoutsForActivityLocked(ActivityRecord r) {
+ void removeIdleTimeoutForActivity(ActivityRecord r) {
if (DEBUG_IDLE) Slog.d(TAG_IDLE, "removeTimeoutsForActivity: Callers="
+ Debug.getCallers(4));
mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 0864c9c..6f80feb 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -306,7 +306,7 @@
public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityTaskManagerService" : TAG_ATM;
private static final String TAG_STACK = TAG + POSTFIX_STACK;
- private static final String TAG_SWITCH = TAG + POSTFIX_SWITCH;
+ static final String TAG_SWITCH = TAG + POSTFIX_SWITCH;
private static final String TAG_IMMERSIVE = TAG + POSTFIX_IMMERSIVE;
private static final String TAG_FOCUS = TAG + POSTFIX_FOCUS;
private static final String TAG_VISIBILITY = TAG + POSTFIX_VISIBILITY;
@@ -1730,9 +1730,9 @@
final long origId = Binder.clearCallingIdentity();
synchronized (mGlobalLock) {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "activityPaused");
- ActivityStack stack = ActivityRecord.getStackLocked(token);
- if (stack != null) {
- stack.activityPausedLocked(token, false);
+ final ActivityRecord r = ActivityRecord.forTokenLocked(token);
+ if (r != null) {
+ r.activityPaused(false);
}
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
@@ -1765,7 +1765,7 @@
restartingName = r.app.mName;
restartingUid = r.app.mUid;
}
- r.activityStoppedLocked(icicle, persistentState, description);
+ r.activityStopped(icicle, persistentState, description);
}
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
@@ -7304,7 +7304,7 @@
@Override
public void scheduleDestroyAllActivities(String reason) {
synchronized (mGlobalLock) {
- mRootActivityContainer.scheduleDestroyAllActivities(null, reason);
+ mRootActivityContainer.scheduleDestroyAllActivities(reason);
}
}
diff --git a/services/core/java/com/android/server/wm/RootActivityContainer.java b/services/core/java/com/android/server/wm/RootActivityContainer.java
index 4ac918c..c0077e4 100644
--- a/services/core/java/com/android/server/wm/RootActivityContainer.java
+++ b/services/core/java/com/android/server/wm/RootActivityContainer.java
@@ -54,6 +54,7 @@
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RECENTS;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STACK;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STATES;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SWITCH;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_TASKS;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_RECENTS;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_RELEASE;
@@ -62,6 +63,7 @@
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.ActivityTaskManagerService.ANIMATE;
+import static com.android.server.wm.ActivityTaskManagerService.TAG_SWITCH;
import static com.android.server.wm.Task.REPARENT_LEAVE_STACK_IN_PLACE;
import static com.android.server.wm.Task.REPARENT_MOVE_STACK_TO_FRONT;
@@ -205,6 +207,28 @@
private boolean mTmpBoolean;
private RemoteException mTmpRemoteException;
+ private String mDestroyAllActivitiesReason;
+ private final Runnable mDestroyAllActivitiesRunnable = new Runnable() {
+ @Override
+ public void run() {
+ synchronized (mService.mGlobalLock) {
+ try {
+ mStackSupervisor.beginDeferResume();
+
+ final PooledConsumer c = PooledLambda.obtainConsumer(
+ RootActivityContainer::destroyActivity, RootActivityContainer.this,
+ PooledLambda.__(ActivityRecord.class));
+ forAllActivities(c);
+ c.recycle();
+ } finally {
+ mStackSupervisor.endDeferResume();
+ resumeFocusedStacksTopActivities();
+ }
+ }
+ }
+
+ };
+
private final FindTaskResult mTmpFindTaskResult = new FindTaskResult();
static class FindTaskResult implements Function<Task, Boolean> {
ActivityRecord mRecord;
@@ -1653,14 +1677,19 @@
}
}
- void scheduleDestroyAllActivities(WindowProcessController app, String reason) {
- for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
- final DisplayContent display = getChildAt(displayNdx);
- for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getStackAt(stackNdx);
- stack.scheduleDestroyActivities(app, reason);
- }
- }
+ void scheduleDestroyAllActivities(String reason) {
+ mDestroyAllActivitiesReason = reason;
+ mService.mH.post(mDestroyAllActivitiesRunnable);
+ }
+
+ private void destroyActivity(ActivityRecord r) {
+ if (r.finishing || !r.isDestroyable()) return;
+
+ if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Destroying " + r + " in state " + r.getState()
+ + " resumed=" + r.getStack().mResumedActivity + " pausing="
+ + r.getStack().mPausingActivity + " for reason " + mDestroyAllActivitiesReason);
+
+ r.destroyImmediately(true /* removeFromTask */, mDestroyAllActivitiesReason);
}
// Tries to put all activity stacks to sleep. Returns true if all stacks were
@@ -2059,7 +2088,7 @@
final DisplayContent display = getChildAt(displayNdx);
for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = display.getStackAt(stackNdx);
- hasVisibleActivities |= stack.handleAppDiedLocked(app);
+ hasVisibleActivities |= stack.handleAppDied(app);
}
}
return hasVisibleActivities;