From 1a6d740c4c0d66665f5e6646fdf27d051c8a2729 Mon Sep 17 00:00:00 2001 From: Felipe Leme Date: Tue, 26 Oct 2021 17:03:02 -0700 Subject: [PATCH] Fixed booting logic on ActivityTaskSupervisor.activityIdleInternal() It was clearing the list of users being switched when the device is "booting", which could be a problem on systems running on headless mode: if the method was called by a non-null record (like the FallBackHome) before it was called by null, the non-system user would never finish switching. Test: manual verification # on automotive and phones Fixes: 190854171 Bug: 203885241 Change-Id: I4c589fd618b104689434bf918ebb48a64cef30e4 --- .../server/am/ActivityManagerService.java | 4 +++- .../java/com/android/server/am/UserState.java | 7 +++++++ .../server/wm/ActivityTaskSupervisor.java | 17 ++++++++++++----- 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index c22c90e359254..b1a1e0d230198 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -4932,6 +4932,8 @@ public class ActivityManagerService extends IActivityManager.Stub @Override public void bootAnimationComplete() { + if (DEBUG_ALL) Slog.d(TAG, "bootAnimationComplete: Callers=" + Debug.getCallers(4)); + final boolean callFinishBooting; synchronized (this) { callFinishBooting = mCallFinishBooting; @@ -7765,7 +7767,7 @@ public class ActivityManagerService extends IActivityManager.Stub // On Automotive, at this point the system user has already been started and unlocked, // and some of the tasks we do here have already been done. So skip those in that case. - // TODO(b/132262830): this workdound shouldn't be necessary once we move the + // TODO(b/132262830, b/203885241): this workdound shouldn't be necessary once we move the // headless-user start logic to UserManager-land final boolean bootingSystemUser = currentUserId == UserHandle.USER_SYSTEM; diff --git a/services/core/java/com/android/server/am/UserState.java b/services/core/java/com/android/server/am/UserState.java index 1fe76080fc6fe..40fc3066e2bb5 100644 --- a/services/core/java/com/android/server/am/UserState.java +++ b/services/core/java/com/android/server/am/UserState.java @@ -145,4 +145,11 @@ public final class UserState { proto.write(UserStateProto.SWITCHING, switching); proto.end(token); } + + @Override + public String toString() { + return "[UserState: id=" + mHandle.getIdentifier() + ", state=" + stateToString(state) + + ", lastState=" + stateToString(lastState) + ", switching=" + switching + + ", tokenProvided=" + tokenProvided + "]"; + } } diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java index b35d84b45cbc8..371cfc53c477c 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java +++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java @@ -147,6 +147,7 @@ import com.android.internal.util.function.pooled.PooledLambda; import com.android.server.LocalServices; import com.android.server.am.ActivityManagerService; import com.android.server.am.UserState; +import com.android.server.utils.Slogf; import com.android.server.wm.ActivityMetricsLogger.LaunchingState; import java.io.FileDescriptor; @@ -1322,8 +1323,6 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks { // us, we can now deliver. r.idle = true; - //Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout); - // Check if able to finish booting when device is booting and all resumed activities // are idle. if ((mService.isBooting() && mRootWindowContainer.allResumedActivitiesIdle()) @@ -1356,14 +1355,21 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks { // Atomically retrieve all of the other things to do. processStoppingAndFinishingActivities(r, processPausingActivities, "idle"); + if (DEBUG_IDLE) { + Slogf.i(TAG, "activityIdleInternal(): r=%s, booting=%b, mStartingUsers=%s", r, booting, + mStartingUsers); + } + if (!mStartingUsers.isEmpty()) { final ArrayList startingUsers = new ArrayList<>(mStartingUsers); mStartingUsers.clear(); - - if (!booting) { + // TODO(b/190854171): remove the isHeadlessSystemUserMode() check on master + if (!booting || UserManager.isHeadlessSystemUserMode()) { // Complete user switch. for (int i = 0; i < startingUsers.size(); i++) { - mService.mAmInternal.finishUserSwitch(startingUsers.get(i)); + UserState userState = startingUsers.get(i); + Slogf.i(TAG, "finishing switch of user %d", userState.mHandle.getIdentifier()); + mService.mAmInternal.finishUserSwitch(userState); } } } @@ -2012,6 +2018,7 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks { final void scheduleIdle() { if (!mHandler.hasMessages(IDLE_NOW_MSG)) { + if (DEBUG_IDLE) Slog.d(TAG_IDLE, "scheduleIdle: Callers=" + Debug.getCallers(4)); mHandler.sendEmptyMessage(IDLE_NOW_MSG); } }