Loading services/core/java/com/android/server/wm/ActivityRecord.java +6 −6 Original line number Diff line number Diff line Loading @@ -4763,7 +4763,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } // Schedule an idle timeout in case the app doesn't do it for us. mStackSupervisor.scheduleIdleTimeoutLocked(this); mStackSupervisor.scheduleIdleTimeout(this); mStackSupervisor.reportResumedActivityLocked(this); Loading Loading @@ -4984,9 +4984,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A + "immediate=" + !idleDelayed); } if (!idleDelayed) { mStackSupervisor.scheduleIdleLocked(); mStackSupervisor.scheduleIdle(); } else { mStackSupervisor.scheduleIdleTimeoutLocked(this); mStackSupervisor.scheduleIdleTimeout(this); } } else { stack.checkReadyForSleep(); Loading Loading @@ -6102,13 +6102,13 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // the full stop of this activity. This is because we won't do that while they are still // waiting for the animation to finish. if (mAtmService.mStackSupervisor.mStoppingActivities.contains(this)) { mAtmService.mStackSupervisor.scheduleIdleLocked(); mStackSupervisor.scheduleIdle(); } } else { // Instead of doing the full stop routine here, let's just hide any activities // we now can, and let them stop when the normal idle happens. mAtmService.mStackSupervisor.processStoppingActivitiesLocked(null /* idleActivity */, false /* remove */, true /* processPausingActivities */); mStackSupervisor.processStoppingActivities(null /* launchedActivity */, true /* onlyUpdateVisibility */, true /* unused */, null /* unused */); } Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); } Loading services/core/java/com/android/server/wm/ActivityStack.java +2 −2 Original line number Diff line number Diff line Loading @@ -1276,7 +1276,7 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn // Make sure that there is no activity waiting for this to launch. if (!mStackSupervisor.mWaitingActivityLaunched.isEmpty()) { mStackSupervisor.removeIdleTimeoutForActivity(r); mStackSupervisor.scheduleIdleTimeoutLocked(r); mStackSupervisor.scheduleIdleTimeout(r); } } Loading Loading @@ -1329,7 +1329,7 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Sleep still need to stop " + mStackSupervisor.mStoppingActivities.size() + " activities"); mStackSupervisor.scheduleIdleLocked(); mStackSupervisor.scheduleIdle(); shouldSleep = false; } Loading services/core/java/com/android/server/wm/ActivityStackSupervisor.java +156 −163 Original line number Diff line number Diff line Loading @@ -1301,22 +1301,14 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { return booting; } // Checked. @GuardedBy("mService") final ActivityRecord activityIdleInternalLocked(final IBinder token, boolean fromTimeout, void activityIdleInternal(ActivityRecord r, boolean fromTimeout, boolean processPausingActivities, Configuration config) { if (DEBUG_ALL) Slog.v(TAG, "Activity idle: " + token); if (DEBUG_ALL) Slog.v(TAG, "Activity idle: " + r); ArrayList<ActivityRecord> finishes = null; ArrayList<UserState> startingUsers = null; int NS = 0; int NF = 0; boolean booting = false; boolean activityRemoved = false; ActivityRecord r = ActivityRecord.forTokenLocked(token); if (r != null) { if (DEBUG_IDLE) Slog.d(TAG_IDLE, "activityIdleInternalLocked: Callers=" if (DEBUG_IDLE) Slog.d(TAG_IDLE, "activityIdleInternal: Callers=" + Debug.getCallers(4)); mHandler.removeMessages(IDLE_TIMEOUT_MSG, r); r.finishLaunchTickingLocked(); Loading Loading @@ -1369,47 +1361,14 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { } // Atomically retrieve all of the other things to do. final ArrayList<ActivityRecord> stops = processStoppingActivitiesLocked(r, true /* remove */, processPausingActivities); NS = stops != null ? stops.size() : 0; if ((NF = mFinishingActivities.size()) > 0) { finishes = new ArrayList<>(mFinishingActivities); mFinishingActivities.clear(); } processStoppingAndFinishingActivities(r, processPausingActivities, "idle"); if (mStartingUsers.size() > 0) { startingUsers = new ArrayList<>(mStartingUsers); if (!mStartingUsers.isEmpty()) { final ArrayList<UserState> startingUsers = new ArrayList<>(mStartingUsers); mStartingUsers.clear(); } // Stop any activities that are scheduled to do so but have been // waiting for the next one to start. for (int i = 0; i < NS; i++) { r = stops.get(i); final ActivityStack stack = r.getActivityStack(); if (stack != null) { if (r.finishing) { // TODO(b/137329632): Wait for idle of the right activity, not just any. r.destroyIfPossible("activityIdleInternalLocked"); } else { r.stopIfPossible(); } } } // Finish any activities that are scheduled to do so but have been // waiting for the next one to start. for (int i = 0; i < NF; i++) { r = finishes.get(i); final ActivityStack stack = r.getActivityStack(); if (stack != null) { activityRemoved |= r.destroyImmediately(true /* removeFromApp */, "finish-idle"); } } if (!booting) { // Complete user switch if (startingUsers != null) { // Complete user switch. for (int i = 0; i < startingUsers.size(); i++) { mService.mAmInternal.finishUserSwitch(startingUsers.get(i)); } Loading @@ -1417,14 +1376,6 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { } mService.mH.post(() -> mService.mAmInternal.trimApplications()); //dump(); //mWindowManager.dump(); if (activityRemoved) { mRootWindowContainer.resumeFocusedStacksTopActivities(); } return r; } /** This doesn't just find a task, it also moves the task to front. */ Loading Loading @@ -1765,7 +1716,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { stack.mForceHidden = true; stack.ensureActivitiesVisible(null, 0, PRESERVE_WINDOWS); stack.mForceHidden = false; activityIdleInternalLocked(null, false /* fromTimeout */, activityIdleInternal(null /* idleActivity */, false /* fromTimeout */, true /* processPausingActivities */, null /* configuration */); // Move all the tasks to the bottom of the fullscreen stack Loading Loading @@ -2133,19 +2084,46 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { return false; } // TODO: Change method name to reflect what it actually does. final ArrayList<ActivityRecord> processStoppingActivitiesLocked(ActivityRecord idleActivity, boolean remove, boolean processPausingActivities) { ArrayList<ActivityRecord> stops = null; /** * Processes the activities to be stopped or destroyed. This should be called when the resumed * activities are idle or drawn. */ private void processStoppingAndFinishingActivities(ActivityRecord launchedActivity, boolean processPausingActivities, String reason) { // Stop any activities that are scheduled to do so but have been waiting for the transition // animation to finish. processStoppingActivities(launchedActivity, false /* onlyUpdateVisibility */, processPausingActivities, reason); final int numFinishingActivities = mFinishingActivities.size(); if (numFinishingActivities == 0) { return; } final boolean nowVisible = mRootWindowContainer.allResumedActivitiesVisible(); for (int activityNdx = mStoppingActivities.size() - 1; activityNdx >= 0; --activityNdx) { ActivityRecord s = mStoppingActivities.get(activityNdx); // Finish any activities that are scheduled to do so but have been waiting for the next one // to start. final ArrayList<ActivityRecord> finishingActivities = new ArrayList<>(mFinishingActivities); mFinishingActivities.clear(); for (int i = 0; i < numFinishingActivities; i++) { final ActivityRecord r = finishingActivities.get(i); if (r.isInHistory()) { r.destroyImmediately(true /* removeFromApp */, "finish-" + reason); } } } final boolean animating = s.isAnimating(TRANSITION); /** Stop or destroy the stopping activities if they are not interactive. */ void processStoppingActivities(ActivityRecord launchedActivity, boolean onlyUpdateVisibility, boolean processPausingActivities, String reason) { final int numStoppingActivities = mStoppingActivities.size(); if (numStoppingActivities == 0) { return; } ArrayList<ActivityRecord> readyToStopActivities = null; if (DEBUG_STATES) Slog.v(TAG, "Stopping " + s + ": nowVisible=" + nowVisible + " animating=" + animating + " finishing=" + s.finishing); final boolean nowVisible = mRootWindowContainer.allResumedActivitiesVisible(); for (int activityNdx = numStoppingActivities - 1; activityNdx >= 0; --activityNdx) { final ActivityRecord s = mStoppingActivities.get(activityNdx); if (nowVisible && s.finishing) { // If this activity is finishing, it is sitting on top of Loading @@ -2156,7 +2134,14 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { if (DEBUG_STATES) Slog.v(TAG, "Before stopping, can hide: " + s); s.setVisibility(false); } if (remove) { if (onlyUpdateVisibility) { continue; } final boolean animating = s.isAnimating(TRANSITION); if (DEBUG_STATES) Slog.v(TAG, "Stopping " + s + ": nowVisible=" + nowVisible + " animating=" + animating + " finishing=" + s.finishing); final ActivityStack stack = s.getActivityStack(); final boolean shouldSleepOrShutDown = stack != null ? stack.shouldSleepOrShutDownActivities() Loading @@ -2165,23 +2150,33 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { if (!processPausingActivities && s.isState(PAUSING)) { // Defer processing pausing activities in this iteration and reschedule // a delayed idle to reprocess it again removeIdleTimeoutForActivity(idleActivity); scheduleIdleTimeoutLocked(idleActivity); removeIdleTimeoutForActivity(launchedActivity); scheduleIdleTimeout(launchedActivity); continue; } if (DEBUG_STATES) Slog.v(TAG, "Ready to stop: " + s); if (stops == null) { stops = new ArrayList<>(); if (readyToStopActivities == null) { readyToStopActivities = new ArrayList<>(); } stops.add(s); readyToStopActivities.add(s); mStoppingActivities.remove(activityNdx); } } } return stops; final int numReadyStops = readyToStopActivities == null ? 0 : readyToStopActivities.size(); for (int i = 0; i < numReadyStops; i++) { final ActivityRecord r = readyToStopActivities.get(i); if (r.isInHistory()) { if (r.finishing) { // TODO(b/137329632): Wait for idle of the right activity, not just any. r.destroyIfPossible(reason); } else { r.stopIfPossible(); } } } } void removeHistoryRecords(WindowProcessController app) { Loading Loading @@ -2319,14 +2314,13 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { return printed; } void scheduleIdleTimeoutLocked(ActivityRecord next) { if (DEBUG_IDLE) Slog.d(TAG_IDLE, "scheduleIdleTimeoutLocked: Callers=" + Debug.getCallers(4)); void scheduleIdleTimeout(ActivityRecord next) { if (DEBUG_IDLE) Slog.d(TAG_IDLE, "scheduleIdleTimeout: Callers=" + Debug.getCallers(4)); Message msg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG, next); mHandler.sendMessageDelayed(msg, IDLE_TIMEOUT); } final void scheduleIdleLocked() { final void scheduleIdle() { mHandler.sendEmptyMessage(IDLE_NOW_MSG); } Loading Loading @@ -2620,65 +2614,84 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { private final class ActivityStackSupervisorHandler extends Handler { public ActivityStackSupervisorHandler(Looper looper) { ActivityStackSupervisorHandler(Looper looper) { super(looper); } void activityIdleInternal(ActivityRecord r, boolean processPausingActivities) { @Override public void handleMessage(Message msg) { synchronized (mService.mGlobalLock) { if (handleMessageInner(msg)) { return; } } // The cases that some invocations cannot be locked by WM. switch (msg.what) { case RESTART_ACTIVITY_PROCESS_TIMEOUT_MSG: { final ActivityRecord r = (ActivityRecord) msg.obj; String processName = null; int uid = 0; synchronized (mService.mGlobalLock) { activityIdleInternalLocked(r != null ? r.appToken : null, true /* fromTimeout */, processPausingActivities, null); if (r.attachedToProcess() && r.isState(ActivityStack.ActivityState.RESTARTING_PROCESS)) { processName = r.app.mName; uid = r.app.mUid; } } if (processName != null) { mService.mAmInternal.killProcess(processName, uid, "restartActivityProcessTimeout"); } } break; } } @Override public void handleMessage(Message msg) { private void activityIdleFromMessage(ActivityRecord idleActivity, boolean fromTimeout) { activityIdleInternal(idleActivity, fromTimeout, fromTimeout /* processPausingActivities */, null /* config */); } /** * Handles the message with lock held. * * @return {@code true} if the message is handled. */ private boolean handleMessageInner(Message msg) { switch (msg.what) { case REPORT_MULTI_WINDOW_MODE_CHANGED_MSG: { synchronized (mService.mGlobalLock) { for (int i = mMultiWindowModeChangedActivities.size() - 1; i >= 0; i--) { final ActivityRecord r = mMultiWindowModeChangedActivities.remove(i); r.updateMultiWindowMode(); } } } break; case REPORT_PIP_MODE_CHANGED_MSG: { synchronized (mService.mGlobalLock) { for (int i = mPipModeChangedActivities.size() - 1; i >= 0; i--) { final ActivityRecord r = mPipModeChangedActivities.remove(i); r.updatePictureInPictureMode(mPipModeChangedTargetStackBounds, false /* forceUpdate */); } } } break; case IDLE_TIMEOUT_MSG: { if (DEBUG_IDLE) Slog.d(TAG_IDLE, "handleMessage: IDLE_TIMEOUT_MSG: r=" + 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. activityIdleInternal((ActivityRecord) msg.obj, true /* processPausingActivities */); // We don't at this point know if the activity is fullscreen, so we need to be // conservative and assume it isn't. activityIdleFromMessage((ActivityRecord) msg.obj, true /* fromTimeout */); } break; case IDLE_NOW_MSG: { if (DEBUG_IDLE) Slog.d(TAG_IDLE, "handleMessage: IDLE_NOW_MSG: r=" + msg.obj); activityIdleInternal((ActivityRecord) msg.obj, false /* processPausingActivities */); activityIdleFromMessage((ActivityRecord) msg.obj, false /* fromTimeout */); } break; case RESUME_TOP_ACTIVITY_MSG: { synchronized (mService.mGlobalLock) { mRootWindowContainer.resumeFocusedStacksTopActivities(); } } break; case SLEEP_TIMEOUT_MSG: { synchronized (mService.mGlobalLock) { if (mService.isSleepingOrShuttingDownLocked()) { Slog.w(TAG, "Sleep timeout! Sleeping now."); checkReadyForSleepLocked(false /* allowDelay */); } } } break; case LAUNCH_TIMEOUT_MSG: { synchronized (mService.mGlobalLock) { if (mLaunchingActivityWakeLock.isHeld()) { Slog.w(TAG, "Launch timeout has expired, giving up wake lock!"); if (VALIDATE_WAKE_LOCK_CALLER Loading @@ -2687,52 +2700,32 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { } mLaunchingActivityWakeLock.release(); } } } break; case LAUNCH_TASK_BEHIND_COMPLETE: { synchronized (mService.mGlobalLock) { ActivityRecord r = ActivityRecord.forTokenLocked((IBinder) msg.obj); final ActivityRecord r = ActivityRecord.forTokenLocked((IBinder) msg.obj); if (r != null) { handleLaunchTaskBehindCompleteLocked(r); } } } break; case RESTART_ACTIVITY_PROCESS_TIMEOUT_MSG: { final ActivityRecord r = (ActivityRecord) msg.obj; String processName = null; int uid = 0; synchronized (mService.mGlobalLock) { if (r.attachedToProcess() && r.isState(ActivityStack.ActivityState.RESTARTING_PROCESS)) { processName = r.app.mName; uid = r.app.mUid; } } if (processName != null) { mService.mAmInternal.killProcess(processName, uid, "restartActivityProcessTimeout"); } } break; case REPORT_HOME_CHANGED_MSG: { synchronized (mService.mGlobalLock) { mHandler.removeMessages(REPORT_HOME_CHANGED_MSG); // Start home activities on displays with no activities. mRootWindowContainer.startHomeOnEmptyDisplays("homeChanged"); } } break; case TOP_RESUMED_STATE_LOSS_TIMEOUT_MSG: { ActivityRecord r = (ActivityRecord) msg.obj; final ActivityRecord r = (ActivityRecord) msg.obj; Slog.w(TAG, "Activity top resumed state loss timeout for " + r); synchronized (mService.mGlobalLock) { if (r.hasProcess()) { mService.logAppTooSlow(r.app, r.topResumedStateLossTime, "top state loss for " + r); } } handleTopResumedStateReleased(true /* timeout */); } break; default: return false; } return true; } } Loading services/core/java/com/android/server/wm/ActivityTaskManagerService.java +8 −12 Original line number Diff line number Diff line Loading @@ -1685,20 +1685,16 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { public final void activityIdle(IBinder token, Configuration config, boolean stopProfiling) { final long origId = Binder.clearCallingIdentity(); try { WindowProcessController proc = null; synchronized (mGlobalLock) { Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "activityIdle"); ActivityStack stack = ActivityRecord.getStackLocked(token); if (stack == null) { final ActivityRecord r = ActivityRecord.forTokenLocked(token); if (r == null) { return; } final ActivityRecord r = mStackSupervisor.activityIdleInternalLocked(token, false /* fromTimeout */, false /* processPausingActivities */, config); if (r != null) { proc = r.app; } if (stopProfiling && proc != null) { proc.clearProfilerIfNeeded(); mStackSupervisor.activityIdleInternal(r, false /* fromTimeout */, false /* processPausingActivities */, config); if (stopProfiling && r.hasProcess()) { r.app.clearProfilerIfNeeded(); } } } finally { Loading Loading @@ -6905,7 +6901,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { if (mRootWindowContainer.finishDisabledPackageActivities( packageName, disabledClasses, true, false, userId) && booted) { mRootWindowContainer.resumeFocusedStacksTopActivities(); mStackSupervisor.scheduleIdleLocked(); mStackSupervisor.scheduleIdle(); } // Clean-up disabled tasks Loading @@ -6932,7 +6928,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { synchronized (mGlobalLock) { mRootWindowContainer.resumeFocusedStacksTopActivities(); if (scheduleIdle) { mStackSupervisor.scheduleIdleLocked(); mStackSupervisor.scheduleIdle(); } } } Loading services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java +2 −2 Original line number Diff line number Diff line Loading @@ -484,8 +484,8 @@ public class SystemServicesTestRule implements TestRule { spyOn(this); // Do not schedule idle that may touch methods outside the scope of the test. doNothing().when(this).scheduleIdleLocked(); doNothing().when(this).scheduleIdleTimeoutLocked(any()); doNothing().when(this).scheduleIdle(); doNothing().when(this).scheduleIdleTimeout(any()); // unit test version does not handle launch wake lock doNothing().when(this).acquireLaunchWakelock(); doReturn(mock(KeyguardController.class)).when(this).getKeyguardController(); Loading Loading
services/core/java/com/android/server/wm/ActivityRecord.java +6 −6 Original line number Diff line number Diff line Loading @@ -4763,7 +4763,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } // Schedule an idle timeout in case the app doesn't do it for us. mStackSupervisor.scheduleIdleTimeoutLocked(this); mStackSupervisor.scheduleIdleTimeout(this); mStackSupervisor.reportResumedActivityLocked(this); Loading Loading @@ -4984,9 +4984,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A + "immediate=" + !idleDelayed); } if (!idleDelayed) { mStackSupervisor.scheduleIdleLocked(); mStackSupervisor.scheduleIdle(); } else { mStackSupervisor.scheduleIdleTimeoutLocked(this); mStackSupervisor.scheduleIdleTimeout(this); } } else { stack.checkReadyForSleep(); Loading Loading @@ -6102,13 +6102,13 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // the full stop of this activity. This is because we won't do that while they are still // waiting for the animation to finish. if (mAtmService.mStackSupervisor.mStoppingActivities.contains(this)) { mAtmService.mStackSupervisor.scheduleIdleLocked(); mStackSupervisor.scheduleIdle(); } } else { // Instead of doing the full stop routine here, let's just hide any activities // we now can, and let them stop when the normal idle happens. mAtmService.mStackSupervisor.processStoppingActivitiesLocked(null /* idleActivity */, false /* remove */, true /* processPausingActivities */); mStackSupervisor.processStoppingActivities(null /* launchedActivity */, true /* onlyUpdateVisibility */, true /* unused */, null /* unused */); } Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); } Loading
services/core/java/com/android/server/wm/ActivityStack.java +2 −2 Original line number Diff line number Diff line Loading @@ -1276,7 +1276,7 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn // Make sure that there is no activity waiting for this to launch. if (!mStackSupervisor.mWaitingActivityLaunched.isEmpty()) { mStackSupervisor.removeIdleTimeoutForActivity(r); mStackSupervisor.scheduleIdleTimeoutLocked(r); mStackSupervisor.scheduleIdleTimeout(r); } } Loading Loading @@ -1329,7 +1329,7 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Sleep still need to stop " + mStackSupervisor.mStoppingActivities.size() + " activities"); mStackSupervisor.scheduleIdleLocked(); mStackSupervisor.scheduleIdle(); shouldSleep = false; } Loading
services/core/java/com/android/server/wm/ActivityStackSupervisor.java +156 −163 Original line number Diff line number Diff line Loading @@ -1301,22 +1301,14 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { return booting; } // Checked. @GuardedBy("mService") final ActivityRecord activityIdleInternalLocked(final IBinder token, boolean fromTimeout, void activityIdleInternal(ActivityRecord r, boolean fromTimeout, boolean processPausingActivities, Configuration config) { if (DEBUG_ALL) Slog.v(TAG, "Activity idle: " + token); if (DEBUG_ALL) Slog.v(TAG, "Activity idle: " + r); ArrayList<ActivityRecord> finishes = null; ArrayList<UserState> startingUsers = null; int NS = 0; int NF = 0; boolean booting = false; boolean activityRemoved = false; ActivityRecord r = ActivityRecord.forTokenLocked(token); if (r != null) { if (DEBUG_IDLE) Slog.d(TAG_IDLE, "activityIdleInternalLocked: Callers=" if (DEBUG_IDLE) Slog.d(TAG_IDLE, "activityIdleInternal: Callers=" + Debug.getCallers(4)); mHandler.removeMessages(IDLE_TIMEOUT_MSG, r); r.finishLaunchTickingLocked(); Loading Loading @@ -1369,47 +1361,14 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { } // Atomically retrieve all of the other things to do. final ArrayList<ActivityRecord> stops = processStoppingActivitiesLocked(r, true /* remove */, processPausingActivities); NS = stops != null ? stops.size() : 0; if ((NF = mFinishingActivities.size()) > 0) { finishes = new ArrayList<>(mFinishingActivities); mFinishingActivities.clear(); } processStoppingAndFinishingActivities(r, processPausingActivities, "idle"); if (mStartingUsers.size() > 0) { startingUsers = new ArrayList<>(mStartingUsers); if (!mStartingUsers.isEmpty()) { final ArrayList<UserState> startingUsers = new ArrayList<>(mStartingUsers); mStartingUsers.clear(); } // Stop any activities that are scheduled to do so but have been // waiting for the next one to start. for (int i = 0; i < NS; i++) { r = stops.get(i); final ActivityStack stack = r.getActivityStack(); if (stack != null) { if (r.finishing) { // TODO(b/137329632): Wait for idle of the right activity, not just any. r.destroyIfPossible("activityIdleInternalLocked"); } else { r.stopIfPossible(); } } } // Finish any activities that are scheduled to do so but have been // waiting for the next one to start. for (int i = 0; i < NF; i++) { r = finishes.get(i); final ActivityStack stack = r.getActivityStack(); if (stack != null) { activityRemoved |= r.destroyImmediately(true /* removeFromApp */, "finish-idle"); } } if (!booting) { // Complete user switch if (startingUsers != null) { // Complete user switch. for (int i = 0; i < startingUsers.size(); i++) { mService.mAmInternal.finishUserSwitch(startingUsers.get(i)); } Loading @@ -1417,14 +1376,6 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { } mService.mH.post(() -> mService.mAmInternal.trimApplications()); //dump(); //mWindowManager.dump(); if (activityRemoved) { mRootWindowContainer.resumeFocusedStacksTopActivities(); } return r; } /** This doesn't just find a task, it also moves the task to front. */ Loading Loading @@ -1765,7 +1716,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { stack.mForceHidden = true; stack.ensureActivitiesVisible(null, 0, PRESERVE_WINDOWS); stack.mForceHidden = false; activityIdleInternalLocked(null, false /* fromTimeout */, activityIdleInternal(null /* idleActivity */, false /* fromTimeout */, true /* processPausingActivities */, null /* configuration */); // Move all the tasks to the bottom of the fullscreen stack Loading Loading @@ -2133,19 +2084,46 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { return false; } // TODO: Change method name to reflect what it actually does. final ArrayList<ActivityRecord> processStoppingActivitiesLocked(ActivityRecord idleActivity, boolean remove, boolean processPausingActivities) { ArrayList<ActivityRecord> stops = null; /** * Processes the activities to be stopped or destroyed. This should be called when the resumed * activities are idle or drawn. */ private void processStoppingAndFinishingActivities(ActivityRecord launchedActivity, boolean processPausingActivities, String reason) { // Stop any activities that are scheduled to do so but have been waiting for the transition // animation to finish. processStoppingActivities(launchedActivity, false /* onlyUpdateVisibility */, processPausingActivities, reason); final int numFinishingActivities = mFinishingActivities.size(); if (numFinishingActivities == 0) { return; } final boolean nowVisible = mRootWindowContainer.allResumedActivitiesVisible(); for (int activityNdx = mStoppingActivities.size() - 1; activityNdx >= 0; --activityNdx) { ActivityRecord s = mStoppingActivities.get(activityNdx); // Finish any activities that are scheduled to do so but have been waiting for the next one // to start. final ArrayList<ActivityRecord> finishingActivities = new ArrayList<>(mFinishingActivities); mFinishingActivities.clear(); for (int i = 0; i < numFinishingActivities; i++) { final ActivityRecord r = finishingActivities.get(i); if (r.isInHistory()) { r.destroyImmediately(true /* removeFromApp */, "finish-" + reason); } } } final boolean animating = s.isAnimating(TRANSITION); /** Stop or destroy the stopping activities if they are not interactive. */ void processStoppingActivities(ActivityRecord launchedActivity, boolean onlyUpdateVisibility, boolean processPausingActivities, String reason) { final int numStoppingActivities = mStoppingActivities.size(); if (numStoppingActivities == 0) { return; } ArrayList<ActivityRecord> readyToStopActivities = null; if (DEBUG_STATES) Slog.v(TAG, "Stopping " + s + ": nowVisible=" + nowVisible + " animating=" + animating + " finishing=" + s.finishing); final boolean nowVisible = mRootWindowContainer.allResumedActivitiesVisible(); for (int activityNdx = numStoppingActivities - 1; activityNdx >= 0; --activityNdx) { final ActivityRecord s = mStoppingActivities.get(activityNdx); if (nowVisible && s.finishing) { // If this activity is finishing, it is sitting on top of Loading @@ -2156,7 +2134,14 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { if (DEBUG_STATES) Slog.v(TAG, "Before stopping, can hide: " + s); s.setVisibility(false); } if (remove) { if (onlyUpdateVisibility) { continue; } final boolean animating = s.isAnimating(TRANSITION); if (DEBUG_STATES) Slog.v(TAG, "Stopping " + s + ": nowVisible=" + nowVisible + " animating=" + animating + " finishing=" + s.finishing); final ActivityStack stack = s.getActivityStack(); final boolean shouldSleepOrShutDown = stack != null ? stack.shouldSleepOrShutDownActivities() Loading @@ -2165,23 +2150,33 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { if (!processPausingActivities && s.isState(PAUSING)) { // Defer processing pausing activities in this iteration and reschedule // a delayed idle to reprocess it again removeIdleTimeoutForActivity(idleActivity); scheduleIdleTimeoutLocked(idleActivity); removeIdleTimeoutForActivity(launchedActivity); scheduleIdleTimeout(launchedActivity); continue; } if (DEBUG_STATES) Slog.v(TAG, "Ready to stop: " + s); if (stops == null) { stops = new ArrayList<>(); if (readyToStopActivities == null) { readyToStopActivities = new ArrayList<>(); } stops.add(s); readyToStopActivities.add(s); mStoppingActivities.remove(activityNdx); } } } return stops; final int numReadyStops = readyToStopActivities == null ? 0 : readyToStopActivities.size(); for (int i = 0; i < numReadyStops; i++) { final ActivityRecord r = readyToStopActivities.get(i); if (r.isInHistory()) { if (r.finishing) { // TODO(b/137329632): Wait for idle of the right activity, not just any. r.destroyIfPossible(reason); } else { r.stopIfPossible(); } } } } void removeHistoryRecords(WindowProcessController app) { Loading Loading @@ -2319,14 +2314,13 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { return printed; } void scheduleIdleTimeoutLocked(ActivityRecord next) { if (DEBUG_IDLE) Slog.d(TAG_IDLE, "scheduleIdleTimeoutLocked: Callers=" + Debug.getCallers(4)); void scheduleIdleTimeout(ActivityRecord next) { if (DEBUG_IDLE) Slog.d(TAG_IDLE, "scheduleIdleTimeout: Callers=" + Debug.getCallers(4)); Message msg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG, next); mHandler.sendMessageDelayed(msg, IDLE_TIMEOUT); } final void scheduleIdleLocked() { final void scheduleIdle() { mHandler.sendEmptyMessage(IDLE_NOW_MSG); } Loading Loading @@ -2620,65 +2614,84 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { private final class ActivityStackSupervisorHandler extends Handler { public ActivityStackSupervisorHandler(Looper looper) { ActivityStackSupervisorHandler(Looper looper) { super(looper); } void activityIdleInternal(ActivityRecord r, boolean processPausingActivities) { @Override public void handleMessage(Message msg) { synchronized (mService.mGlobalLock) { if (handleMessageInner(msg)) { return; } } // The cases that some invocations cannot be locked by WM. switch (msg.what) { case RESTART_ACTIVITY_PROCESS_TIMEOUT_MSG: { final ActivityRecord r = (ActivityRecord) msg.obj; String processName = null; int uid = 0; synchronized (mService.mGlobalLock) { activityIdleInternalLocked(r != null ? r.appToken : null, true /* fromTimeout */, processPausingActivities, null); if (r.attachedToProcess() && r.isState(ActivityStack.ActivityState.RESTARTING_PROCESS)) { processName = r.app.mName; uid = r.app.mUid; } } if (processName != null) { mService.mAmInternal.killProcess(processName, uid, "restartActivityProcessTimeout"); } } break; } } @Override public void handleMessage(Message msg) { private void activityIdleFromMessage(ActivityRecord idleActivity, boolean fromTimeout) { activityIdleInternal(idleActivity, fromTimeout, fromTimeout /* processPausingActivities */, null /* config */); } /** * Handles the message with lock held. * * @return {@code true} if the message is handled. */ private boolean handleMessageInner(Message msg) { switch (msg.what) { case REPORT_MULTI_WINDOW_MODE_CHANGED_MSG: { synchronized (mService.mGlobalLock) { for (int i = mMultiWindowModeChangedActivities.size() - 1; i >= 0; i--) { final ActivityRecord r = mMultiWindowModeChangedActivities.remove(i); r.updateMultiWindowMode(); } } } break; case REPORT_PIP_MODE_CHANGED_MSG: { synchronized (mService.mGlobalLock) { for (int i = mPipModeChangedActivities.size() - 1; i >= 0; i--) { final ActivityRecord r = mPipModeChangedActivities.remove(i); r.updatePictureInPictureMode(mPipModeChangedTargetStackBounds, false /* forceUpdate */); } } } break; case IDLE_TIMEOUT_MSG: { if (DEBUG_IDLE) Slog.d(TAG_IDLE, "handleMessage: IDLE_TIMEOUT_MSG: r=" + 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. activityIdleInternal((ActivityRecord) msg.obj, true /* processPausingActivities */); // We don't at this point know if the activity is fullscreen, so we need to be // conservative and assume it isn't. activityIdleFromMessage((ActivityRecord) msg.obj, true /* fromTimeout */); } break; case IDLE_NOW_MSG: { if (DEBUG_IDLE) Slog.d(TAG_IDLE, "handleMessage: IDLE_NOW_MSG: r=" + msg.obj); activityIdleInternal((ActivityRecord) msg.obj, false /* processPausingActivities */); activityIdleFromMessage((ActivityRecord) msg.obj, false /* fromTimeout */); } break; case RESUME_TOP_ACTIVITY_MSG: { synchronized (mService.mGlobalLock) { mRootWindowContainer.resumeFocusedStacksTopActivities(); } } break; case SLEEP_TIMEOUT_MSG: { synchronized (mService.mGlobalLock) { if (mService.isSleepingOrShuttingDownLocked()) { Slog.w(TAG, "Sleep timeout! Sleeping now."); checkReadyForSleepLocked(false /* allowDelay */); } } } break; case LAUNCH_TIMEOUT_MSG: { synchronized (mService.mGlobalLock) { if (mLaunchingActivityWakeLock.isHeld()) { Slog.w(TAG, "Launch timeout has expired, giving up wake lock!"); if (VALIDATE_WAKE_LOCK_CALLER Loading @@ -2687,52 +2700,32 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { } mLaunchingActivityWakeLock.release(); } } } break; case LAUNCH_TASK_BEHIND_COMPLETE: { synchronized (mService.mGlobalLock) { ActivityRecord r = ActivityRecord.forTokenLocked((IBinder) msg.obj); final ActivityRecord r = ActivityRecord.forTokenLocked((IBinder) msg.obj); if (r != null) { handleLaunchTaskBehindCompleteLocked(r); } } } break; case RESTART_ACTIVITY_PROCESS_TIMEOUT_MSG: { final ActivityRecord r = (ActivityRecord) msg.obj; String processName = null; int uid = 0; synchronized (mService.mGlobalLock) { if (r.attachedToProcess() && r.isState(ActivityStack.ActivityState.RESTARTING_PROCESS)) { processName = r.app.mName; uid = r.app.mUid; } } if (processName != null) { mService.mAmInternal.killProcess(processName, uid, "restartActivityProcessTimeout"); } } break; case REPORT_HOME_CHANGED_MSG: { synchronized (mService.mGlobalLock) { mHandler.removeMessages(REPORT_HOME_CHANGED_MSG); // Start home activities on displays with no activities. mRootWindowContainer.startHomeOnEmptyDisplays("homeChanged"); } } break; case TOP_RESUMED_STATE_LOSS_TIMEOUT_MSG: { ActivityRecord r = (ActivityRecord) msg.obj; final ActivityRecord r = (ActivityRecord) msg.obj; Slog.w(TAG, "Activity top resumed state loss timeout for " + r); synchronized (mService.mGlobalLock) { if (r.hasProcess()) { mService.logAppTooSlow(r.app, r.topResumedStateLossTime, "top state loss for " + r); } } handleTopResumedStateReleased(true /* timeout */); } break; default: return false; } return true; } } Loading
services/core/java/com/android/server/wm/ActivityTaskManagerService.java +8 −12 Original line number Diff line number Diff line Loading @@ -1685,20 +1685,16 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { public final void activityIdle(IBinder token, Configuration config, boolean stopProfiling) { final long origId = Binder.clearCallingIdentity(); try { WindowProcessController proc = null; synchronized (mGlobalLock) { Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "activityIdle"); ActivityStack stack = ActivityRecord.getStackLocked(token); if (stack == null) { final ActivityRecord r = ActivityRecord.forTokenLocked(token); if (r == null) { return; } final ActivityRecord r = mStackSupervisor.activityIdleInternalLocked(token, false /* fromTimeout */, false /* processPausingActivities */, config); if (r != null) { proc = r.app; } if (stopProfiling && proc != null) { proc.clearProfilerIfNeeded(); mStackSupervisor.activityIdleInternal(r, false /* fromTimeout */, false /* processPausingActivities */, config); if (stopProfiling && r.hasProcess()) { r.app.clearProfilerIfNeeded(); } } } finally { Loading Loading @@ -6905,7 +6901,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { if (mRootWindowContainer.finishDisabledPackageActivities( packageName, disabledClasses, true, false, userId) && booted) { mRootWindowContainer.resumeFocusedStacksTopActivities(); mStackSupervisor.scheduleIdleLocked(); mStackSupervisor.scheduleIdle(); } // Clean-up disabled tasks Loading @@ -6932,7 +6928,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { synchronized (mGlobalLock) { mRootWindowContainer.resumeFocusedStacksTopActivities(); if (scheduleIdle) { mStackSupervisor.scheduleIdleLocked(); mStackSupervisor.scheduleIdle(); } } } Loading
services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java +2 −2 Original line number Diff line number Diff line Loading @@ -484,8 +484,8 @@ public class SystemServicesTestRule implements TestRule { spyOn(this); // Do not schedule idle that may touch methods outside the scope of the test. doNothing().when(this).scheduleIdleLocked(); doNothing().when(this).scheduleIdleTimeoutLocked(any()); doNothing().when(this).scheduleIdle(); doNothing().when(this).scheduleIdleTimeout(any()); // unit test version does not handle launch wake lock doNothing().when(this).acquireLaunchWakelock(); doReturn(mock(KeyguardController.class)).when(this).getKeyguardController(); Loading