Support of restart process of non-top visible activity
Since the method restartTaskActivityProcessIfVisible is added, restartProcessIfVisible may not only be called for the top activity. Then if the current top finishes itself, there may be a timing that the restarting state is changed by resuming next. That will break the restart procedure when receiving onStop completion of the target app. By checking if the activity is scheduled to be restarted, the restarting state can be recovered and continue the procedure. Fix: 259042920 Test: SizeCompatTests#testRestartProcessIfVisible Change-Id: Idb5833480e7f029c9da3c3ea6e4d9df911df5a0c
This commit is contained in:
@@ -46,6 +46,7 @@ import static com.android.server.wm.ActivityRecord.State.DESTROYING;
|
||||
import static com.android.server.wm.ActivityRecord.State.PAUSING;
|
||||
import static com.android.server.wm.ActivityRecord.State.RESTARTING_PROCESS;
|
||||
import static com.android.server.wm.ActivityRecord.State.RESUMED;
|
||||
import static com.android.server.wm.ActivityRecord.State.STOPPING;
|
||||
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_ALL;
|
||||
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SWITCH;
|
||||
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
|
||||
@@ -240,11 +241,21 @@ class ActivityClientController extends IActivityClientController.Stub {
|
||||
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "activityStopped");
|
||||
r = ActivityRecord.isInRootTaskLocked(token);
|
||||
if (r != null) {
|
||||
if (!r.isState(STOPPING, RESTARTING_PROCESS)
|
||||
&& mTaskSupervisor.hasScheduledRestartTimeouts(r)) {
|
||||
// Recover the restarting state which was replaced by other lifecycle changes.
|
||||
r.setState(RESTARTING_PROCESS, "continue-restart");
|
||||
}
|
||||
if (r.attachedToProcess() && r.isState(RESTARTING_PROCESS)) {
|
||||
// The activity was requested to restart from
|
||||
// {@link #restartActivityProcessIfVisible}.
|
||||
restartingName = r.app.mName;
|
||||
restartingUid = r.app.mUid;
|
||||
// Make EnsureActivitiesVisibleHelper#makeVisibleAndRestartIfNeeded not skip
|
||||
// restarting non-top activity.
|
||||
if (r != r.getTask().topRunningActivity()) {
|
||||
r.setVisibleRequested(false);
|
||||
}
|
||||
}
|
||||
r.activityStopped(icicle, persistentState, description);
|
||||
}
|
||||
|
||||
@@ -2243,6 +2243,10 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
|
||||
mHandler.sendEmptyMessageDelayed(SLEEP_TIMEOUT_MSG, SLEEP_TIMEOUT);
|
||||
}
|
||||
|
||||
boolean hasScheduledRestartTimeouts(ActivityRecord r) {
|
||||
return mHandler.hasMessages(RESTART_ACTIVITY_PROCESS_TIMEOUT_MSG, r);
|
||||
}
|
||||
|
||||
void removeRestartTimeouts(ActivityRecord r) {
|
||||
mHandler.removeMessages(RESTART_ACTIVITY_PROCESS_TIMEOUT_MSG, r);
|
||||
}
|
||||
|
||||
@@ -295,6 +295,15 @@ public class SizeCompatTests extends WindowTestsBase {
|
||||
|
||||
assertEquals(RESTARTING_PROCESS, mActivity.getState());
|
||||
assertNotEquals(originalOverrideBounds, mActivity.getBounds());
|
||||
|
||||
// Even if the state is changed (e.g. a floating activity on top is finished and make it
|
||||
// resume), the restart procedure should recover the state and continue to kill the process.
|
||||
mActivity.setState(RESUMED, "anyStateChange");
|
||||
doReturn(true).when(mSupervisor).hasScheduledRestartTimeouts(mActivity);
|
||||
mAtm.mActivityClientController.activityStopped(mActivity.token, null /* icicle */,
|
||||
null /* persistentState */, null /* description */);
|
||||
assertEquals(RESTARTING_PROCESS, mActivity.getState());
|
||||
verify(mSupervisor).removeRestartTimeouts(mActivity);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user