Loading services/core/java/com/android/server/am/ActivityManagerService.java +6 −22 Original line number Diff line number Diff line Loading @@ -8613,7 +8613,7 @@ public class ActivityManagerService extends IActivityManager.Stub // On Automotive / Headless System User Mode, 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. The duplicate system user start is guarded in SystemServiceManager. // TODO(b/242195409): this workaround shouldn't be necessary once we move the headless-user // TODO(b/266158156): this workaround shouldn't be necessary once we move the headless-user // start logic to UserManager-land. mUserController.onSystemUserStarting(); Loading Loading @@ -8646,7 +8646,7 @@ public class ActivityManagerService extends IActivityManager.Stub // Some systems - like automotive - will explicitly unlock system user then switch // to a secondary user. // TODO(b/242195409): this workaround shouldn't be necessary once we move // TODO(b/266158156): this workaround shouldn't be necessary once we move // the headless-user start logic to UserManager-land. if (isBootingSystemUser && !UserManager.isHeadlessSystemUserMode()) { t.traceBegin("startHomeOnAllDisplays"); Loading @@ -8669,26 +8669,10 @@ public class ActivityManagerService extends IActivityManager.Stub final int callingPid = Binder.getCallingPid(); final long ident = Binder.clearCallingIdentity(); try { Intent intent = new Intent(Intent.ACTION_USER_STARTED); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND); intent.putExtra(Intent.EXTRA_USER_HANDLE, currentUserId); broadcastIntentLocked(null, null, null, intent, null, null, 0, null, null, null, null, null, OP_NONE, null, false, false, MY_PID, SYSTEM_UID, callingUid, callingPid, currentUserId); intent = new Intent(Intent.ACTION_USER_STARTING); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); intent.putExtra(Intent.EXTRA_USER_HANDLE, currentUserId); broadcastIntentLocked(null, null, null, intent, null, new IIntentReceiver.Stub() { @Override public void performReceive(Intent intent, int resultCode, String data, Bundle extras, boolean ordered, boolean sticky, int sendingUser) {} }, 0, null, null, new String[] {INTERACT_ACROSS_USERS}, null, null, OP_NONE, null, true, false, MY_PID, SYSTEM_UID, callingUid, callingPid, UserHandle.USER_ALL); mUserController.sendUserStartedBroadcast( currentUserId, callingUid, callingPid); mUserController.sendUserStartingBroadcast( currentUserId, callingUid, callingPid); } catch (Throwable e) { Slog.wtf(TAG, "Failed sending first user broadcasts", e); } finally { Loading services/core/java/com/android/server/am/UserController.java +93 −31 Original line number Diff line number Diff line Loading @@ -365,13 +365,13 @@ class UserController implements Handler.Callback { private volatile ArraySet<String> mCurWaitingUserSwitchCallbacks; /** * Messages for for switching from {@link android.os.UserHandle#SYSTEM}. * Messages for switching from {@link android.os.UserHandle#SYSTEM}. */ @GuardedBy("mLock") private String mSwitchingFromSystemUserMessage; /** * Messages for for switching to {@link android.os.UserHandle#SYSTEM}. * Messages for switching to {@link android.os.UserHandle#SYSTEM}. */ @GuardedBy("mLock") private String mSwitchingToSystemUserMessage; Loading @@ -384,6 +384,16 @@ class UserController implements Handler.Callback { private final LockPatternUtils mLockPatternUtils; // TODO(b/266158156): remove this once we improve/refactor the way broadcasts are sent for // the system user in HSUM. @GuardedBy("mLock") private boolean mIsBroadcastSentForSystemUserStarted; // TODO(b/266158156): remove this once we improve/refactor the way broadcasts are sent for // the system user in HSUM. @GuardedBy("mLock") private boolean mIsBroadcastSentForSystemUserStarting; volatile boolean mBootCompleted; /** Loading Loading @@ -635,7 +645,7 @@ class UserController implements Handler.Callback { // user transitions to RUNNING_LOCKED. However, in "headless system user mode", the // system user is explicitly started before the device has finished booting. In // that case, we need to wait until onBootComplete() to send the broadcast. if (!(UserManager.isHeadlessSystemUserMode() && uss.mHandle.isSystem())) { if (!(mInjector.isHeadlessSystemUserMode() && uss.mHandle.isSystem())) { // ACTION_LOCKED_BOOT_COMPLETED sendLockedBootCompletedBroadcast(resultTo, userId); } Loading Loading @@ -1823,15 +1833,17 @@ class UserController implements Handler.Callback { needStart = false; } if (needStart) { // Send USER_STARTED broadcast Intent intent = new Intent(Intent.ACTION_USER_STARTED); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND); intent.putExtra(Intent.EXTRA_USER_HANDLE, userId); mInjector.broadcastIntent(intent, null, null, 0, null, null, null, AppOpsManager.OP_NONE, null, false, false, MY_PID, SYSTEM_UID, callingUid, callingPid, userId); // In most cases, broadcast for the system user starting/started is sent by // ActivityManagerService#systemReady(). However on some HSUM devices (e.g. tablets) // the user switches from the system user to a secondary user while running // ActivityManagerService#systemReady(), thus broadcast is not sent for the system user. // Therefore we send the broadcast for the system user here as well in HSUM. // TODO(b/266158156): Improve/refactor the way broadcasts are sent for the system user // in HSUM. Ideally it'd be best to have one single place that sends this notification. final boolean isSystemUserInHeadlessMode = (userId == UserHandle.USER_SYSTEM) && mInjector.isHeadlessSystemUserMode(); if (needStart || isSystemUserInHeadlessMode) { sendUserStartedBroadcast(userId, callingUid, callingPid); } t.traceEnd(); Loading @@ -1845,23 +1857,9 @@ class UserController implements Handler.Callback { t.traceEnd(); } if (needStart) { if (needStart || isSystemUserInHeadlessMode) { t.traceBegin("sendRestartBroadcast"); Intent intent = new Intent(Intent.ACTION_USER_STARTING); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); intent.putExtra(Intent.EXTRA_USER_HANDLE, userId); mInjector.broadcastIntent(intent, null, new IIntentReceiver.Stub() { @Override public void performReceive(Intent intent, int resultCode, String data, Bundle extras, boolean ordered, boolean sticky, int sendingUser) throws RemoteException { } }, 0, null, null, new String[]{INTERACT_ACROSS_USERS}, AppOpsManager.OP_NONE, null, true, false, MY_PID, SYSTEM_UID, callingUid, callingPid, UserHandle.USER_ALL); sendUserStartingBroadcast(userId, callingUid, callingPid); t.traceEnd(); } } finally { Loading Loading @@ -2283,6 +2281,62 @@ class UserController implements Handler.Callback { EventLogTags.writeAmSwitchUser(newUserId); } // The two methods sendUserStartedBroadcast() and sendUserStartingBroadcast() // could be merged for better reuse. However, the params they are calling broadcastIntent() // with are different - resultCode receiver, permissions, ordered, and userId, etc. Therefore, // we decided to keep two separate methods for better code readability/clarity. // TODO(b/266158156): Improve/refactor the way broadcasts are sent for the system user // in HSUM. Ideally it'd be best to have one single place that sends this notification. /** Sends {@code ACTION_USER_STARTED} broadcast. */ void sendUserStartedBroadcast(@UserIdInt int userId, int callingUid, int callingPid) { if (userId == UserHandle.USER_SYSTEM) { synchronized (mLock) { // Make sure that the broadcast is sent only once for the system user. if (mIsBroadcastSentForSystemUserStarted) { return; } mIsBroadcastSentForSystemUserStarted = true; } } final Intent intent = new Intent(Intent.ACTION_USER_STARTED); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND); intent.putExtra(Intent.EXTRA_USER_HANDLE, userId); mInjector.broadcastIntent(intent, /* resolvedType= */ null, /* resultTo= */ null, /* resultCode= */ 0, /* resultData= */ null, /* resultExtras= */ null, /* requiredPermissions= */ null, AppOpsManager.OP_NONE, /* bOptions= */ null, /* ordered= */ false, /* sticky= */ false, MY_PID, SYSTEM_UID, callingUid, callingPid, userId); } /** Sends {@code ACTION_USER_STARTING} broadcast. */ void sendUserStartingBroadcast(@UserIdInt int userId, int callingUid, int callingPid) { if (userId == UserHandle.USER_SYSTEM) { synchronized (mLock) { // Make sure that the broadcast is sent only once for the system user. if (mIsBroadcastSentForSystemUserStarting) { return; } mIsBroadcastSentForSystemUserStarting = true; } } final Intent intent = new Intent(Intent.ACTION_USER_STARTING); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); intent.putExtra(Intent.EXTRA_USER_HANDLE, userId); mInjector.broadcastIntent(intent, /* resolvedType= */ null, new IIntentReceiver.Stub() { @Override public void performReceive(Intent intent, int resultCode, String data, Bundle extras, boolean ordered, boolean sticky, int sendingUser) throws RemoteException { } }, /* resultCode= */ 0, /* resultData= */ null, /* resultExtras= */ null, new String[]{INTERACT_ACROSS_USERS}, AppOpsManager.OP_NONE, /* bOptions= */ null, /* ordered= */ true, /* sticky= */ false, MY_PID, SYSTEM_UID, callingUid, callingPid, UserHandle.USER_ALL); } void sendUserSwitchBroadcasts(int oldUserId, int newUserId) { final int callingUid = Binder.getCallingUid(); final int callingPid = Binder.getCallingPid(); Loading Loading @@ -2568,7 +2622,7 @@ class UserController implements Handler.Callback { for (int i = 0; i < startedUsers.size(); i++) { int userId = startedUsers.keyAt(i); UserState uss = startedUsers.valueAt(i); if (!UserManager.isHeadlessSystemUserMode()) { if (!mInjector.isHeadlessSystemUserMode()) { finishUserBoot(uss, resultTo); } else { if (userId == UserHandle.USER_SYSTEM) { Loading @@ -2589,9 +2643,9 @@ class UserController implements Handler.Callback { mInjector.reportCurWakefulnessUsageEvent(); } // TODO(b/242195409): remove this method if initial system user boot logic is refactored? // TODO(b/266158156): remove this method if initial system user boot logic is refactored? void onSystemUserStarting() { if (!UserManager.isHeadlessSystemUserMode()) { if (!mInjector.isHeadlessSystemUserMode()) { // Don't need to call on HSUM because it will be called when the system user is // restarted on background mInjector.onUserStarting(UserHandle.USER_SYSTEM); Loading Loading @@ -3059,6 +3113,10 @@ class UserController implements Handler.Callback { pw.println(" mMaxRunningUsers:" + mMaxRunningUsers); pw.println(" mUserSwitchUiEnabled:" + mUserSwitchUiEnabled); pw.println(" mInitialized:" + mInitialized); pw.println(" mIsBroadcastSentForSystemUserStarted:" + mIsBroadcastSentForSystemUserStarted); pw.println(" mIsBroadcastSentForSystemUserStarting:" + mIsBroadcastSentForSystemUserStarting); if (mSwitchingFromSystemUserMessage != null) { pw.println(" mSwitchingFromSystemUserMessage: " + mSwitchingFromSystemUserMessage); } Loading Loading @@ -3749,6 +3807,10 @@ class UserController implements Handler.Callback { }, /* message= */ null); } boolean isHeadlessSystemUserMode() { return UserManager.isHeadlessSystemUserMode(); } boolean isUsersOnSecondaryDisplaysEnabled() { return UserManager.isVisibleBackgroundUsersEnabled(); } Loading services/tests/servicestests/src/com/android/server/am/UserControllerTest.java +30 −0 Original line number Diff line number Diff line Loading @@ -133,6 +133,7 @@ public class UserControllerTest { private static final int TEST_USER_ID1 = 101; private static final int TEST_USER_ID2 = 102; private static final int TEST_USER_ID3 = 103; private static final int SYSTEM_USER_ID = UserHandle.SYSTEM.getIdentifier(); private static final int NONEXIST_USER_ID = 2; private static final int TEST_PRE_CREATED_USER_ID = 103; Loading Loading @@ -230,6 +231,31 @@ public class UserControllerTest { verifyUserAssignedToDisplay(TEST_USER_ID, Display.DEFAULT_DISPLAY); } @Test public void testStartUser_sendsNoBroadcastsForSystemUserInNonHeadlessMode() { setUpUser(SYSTEM_USER_ID, UserInfo.FLAG_SYSTEM, /* preCreated= */ false, UserManager.USER_TYPE_FULL_SYSTEM); mockIsHeadlessSystemUserMode(false); mUserController.startUser(SYSTEM_USER_ID, USER_START_MODE_FOREGROUND); assertWithMessage("Broadcasts for starting the system user in non-headless mode") .that(mInjector.mSentIntents).isEmpty(); } @Test public void testStartUser_sendsBroadcastsForSystemUserInHeadlessMode() { setUpUser(SYSTEM_USER_ID, UserInfo.FLAG_SYSTEM, /* preCreated= */ false, UserManager.USER_TYPE_SYSTEM_HEADLESS); mockIsHeadlessSystemUserMode(true); mUserController.startUser(SYSTEM_USER_ID, USER_START_MODE_FOREGROUND); assertWithMessage("Broadcasts for starting the system user in headless mode") .that(getActions(mInjector.mSentIntents)).containsExactly( Intent.ACTION_USER_STARTED, Intent.ACTION_USER_STARTING); } @Test public void testStartUser_displayAssignmentFailed() { doReturn(UserManagerInternal.USER_ASSIGNMENT_RESULT_FAILURE) Loading Loading @@ -999,6 +1025,10 @@ public class UserControllerTest { } } private void mockIsHeadlessSystemUserMode(boolean value) { when(mInjector.isHeadlessSystemUserMode()).thenReturn(value); } private void mockIsUsersOnSecondaryDisplaysEnabled(boolean value) { when(mInjector.isUsersOnSecondaryDisplaysEnabled()).thenReturn(value); } Loading Loading
services/core/java/com/android/server/am/ActivityManagerService.java +6 −22 Original line number Diff line number Diff line Loading @@ -8613,7 +8613,7 @@ public class ActivityManagerService extends IActivityManager.Stub // On Automotive / Headless System User Mode, 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. The duplicate system user start is guarded in SystemServiceManager. // TODO(b/242195409): this workaround shouldn't be necessary once we move the headless-user // TODO(b/266158156): this workaround shouldn't be necessary once we move the headless-user // start logic to UserManager-land. mUserController.onSystemUserStarting(); Loading Loading @@ -8646,7 +8646,7 @@ public class ActivityManagerService extends IActivityManager.Stub // Some systems - like automotive - will explicitly unlock system user then switch // to a secondary user. // TODO(b/242195409): this workaround shouldn't be necessary once we move // TODO(b/266158156): this workaround shouldn't be necessary once we move // the headless-user start logic to UserManager-land. if (isBootingSystemUser && !UserManager.isHeadlessSystemUserMode()) { t.traceBegin("startHomeOnAllDisplays"); Loading @@ -8669,26 +8669,10 @@ public class ActivityManagerService extends IActivityManager.Stub final int callingPid = Binder.getCallingPid(); final long ident = Binder.clearCallingIdentity(); try { Intent intent = new Intent(Intent.ACTION_USER_STARTED); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND); intent.putExtra(Intent.EXTRA_USER_HANDLE, currentUserId); broadcastIntentLocked(null, null, null, intent, null, null, 0, null, null, null, null, null, OP_NONE, null, false, false, MY_PID, SYSTEM_UID, callingUid, callingPid, currentUserId); intent = new Intent(Intent.ACTION_USER_STARTING); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); intent.putExtra(Intent.EXTRA_USER_HANDLE, currentUserId); broadcastIntentLocked(null, null, null, intent, null, new IIntentReceiver.Stub() { @Override public void performReceive(Intent intent, int resultCode, String data, Bundle extras, boolean ordered, boolean sticky, int sendingUser) {} }, 0, null, null, new String[] {INTERACT_ACROSS_USERS}, null, null, OP_NONE, null, true, false, MY_PID, SYSTEM_UID, callingUid, callingPid, UserHandle.USER_ALL); mUserController.sendUserStartedBroadcast( currentUserId, callingUid, callingPid); mUserController.sendUserStartingBroadcast( currentUserId, callingUid, callingPid); } catch (Throwable e) { Slog.wtf(TAG, "Failed sending first user broadcasts", e); } finally { Loading
services/core/java/com/android/server/am/UserController.java +93 −31 Original line number Diff line number Diff line Loading @@ -365,13 +365,13 @@ class UserController implements Handler.Callback { private volatile ArraySet<String> mCurWaitingUserSwitchCallbacks; /** * Messages for for switching from {@link android.os.UserHandle#SYSTEM}. * Messages for switching from {@link android.os.UserHandle#SYSTEM}. */ @GuardedBy("mLock") private String mSwitchingFromSystemUserMessage; /** * Messages for for switching to {@link android.os.UserHandle#SYSTEM}. * Messages for switching to {@link android.os.UserHandle#SYSTEM}. */ @GuardedBy("mLock") private String mSwitchingToSystemUserMessage; Loading @@ -384,6 +384,16 @@ class UserController implements Handler.Callback { private final LockPatternUtils mLockPatternUtils; // TODO(b/266158156): remove this once we improve/refactor the way broadcasts are sent for // the system user in HSUM. @GuardedBy("mLock") private boolean mIsBroadcastSentForSystemUserStarted; // TODO(b/266158156): remove this once we improve/refactor the way broadcasts are sent for // the system user in HSUM. @GuardedBy("mLock") private boolean mIsBroadcastSentForSystemUserStarting; volatile boolean mBootCompleted; /** Loading Loading @@ -635,7 +645,7 @@ class UserController implements Handler.Callback { // user transitions to RUNNING_LOCKED. However, in "headless system user mode", the // system user is explicitly started before the device has finished booting. In // that case, we need to wait until onBootComplete() to send the broadcast. if (!(UserManager.isHeadlessSystemUserMode() && uss.mHandle.isSystem())) { if (!(mInjector.isHeadlessSystemUserMode() && uss.mHandle.isSystem())) { // ACTION_LOCKED_BOOT_COMPLETED sendLockedBootCompletedBroadcast(resultTo, userId); } Loading Loading @@ -1823,15 +1833,17 @@ class UserController implements Handler.Callback { needStart = false; } if (needStart) { // Send USER_STARTED broadcast Intent intent = new Intent(Intent.ACTION_USER_STARTED); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND); intent.putExtra(Intent.EXTRA_USER_HANDLE, userId); mInjector.broadcastIntent(intent, null, null, 0, null, null, null, AppOpsManager.OP_NONE, null, false, false, MY_PID, SYSTEM_UID, callingUid, callingPid, userId); // In most cases, broadcast for the system user starting/started is sent by // ActivityManagerService#systemReady(). However on some HSUM devices (e.g. tablets) // the user switches from the system user to a secondary user while running // ActivityManagerService#systemReady(), thus broadcast is not sent for the system user. // Therefore we send the broadcast for the system user here as well in HSUM. // TODO(b/266158156): Improve/refactor the way broadcasts are sent for the system user // in HSUM. Ideally it'd be best to have one single place that sends this notification. final boolean isSystemUserInHeadlessMode = (userId == UserHandle.USER_SYSTEM) && mInjector.isHeadlessSystemUserMode(); if (needStart || isSystemUserInHeadlessMode) { sendUserStartedBroadcast(userId, callingUid, callingPid); } t.traceEnd(); Loading @@ -1845,23 +1857,9 @@ class UserController implements Handler.Callback { t.traceEnd(); } if (needStart) { if (needStart || isSystemUserInHeadlessMode) { t.traceBegin("sendRestartBroadcast"); Intent intent = new Intent(Intent.ACTION_USER_STARTING); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); intent.putExtra(Intent.EXTRA_USER_HANDLE, userId); mInjector.broadcastIntent(intent, null, new IIntentReceiver.Stub() { @Override public void performReceive(Intent intent, int resultCode, String data, Bundle extras, boolean ordered, boolean sticky, int sendingUser) throws RemoteException { } }, 0, null, null, new String[]{INTERACT_ACROSS_USERS}, AppOpsManager.OP_NONE, null, true, false, MY_PID, SYSTEM_UID, callingUid, callingPid, UserHandle.USER_ALL); sendUserStartingBroadcast(userId, callingUid, callingPid); t.traceEnd(); } } finally { Loading Loading @@ -2283,6 +2281,62 @@ class UserController implements Handler.Callback { EventLogTags.writeAmSwitchUser(newUserId); } // The two methods sendUserStartedBroadcast() and sendUserStartingBroadcast() // could be merged for better reuse. However, the params they are calling broadcastIntent() // with are different - resultCode receiver, permissions, ordered, and userId, etc. Therefore, // we decided to keep two separate methods for better code readability/clarity. // TODO(b/266158156): Improve/refactor the way broadcasts are sent for the system user // in HSUM. Ideally it'd be best to have one single place that sends this notification. /** Sends {@code ACTION_USER_STARTED} broadcast. */ void sendUserStartedBroadcast(@UserIdInt int userId, int callingUid, int callingPid) { if (userId == UserHandle.USER_SYSTEM) { synchronized (mLock) { // Make sure that the broadcast is sent only once for the system user. if (mIsBroadcastSentForSystemUserStarted) { return; } mIsBroadcastSentForSystemUserStarted = true; } } final Intent intent = new Intent(Intent.ACTION_USER_STARTED); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND); intent.putExtra(Intent.EXTRA_USER_HANDLE, userId); mInjector.broadcastIntent(intent, /* resolvedType= */ null, /* resultTo= */ null, /* resultCode= */ 0, /* resultData= */ null, /* resultExtras= */ null, /* requiredPermissions= */ null, AppOpsManager.OP_NONE, /* bOptions= */ null, /* ordered= */ false, /* sticky= */ false, MY_PID, SYSTEM_UID, callingUid, callingPid, userId); } /** Sends {@code ACTION_USER_STARTING} broadcast. */ void sendUserStartingBroadcast(@UserIdInt int userId, int callingUid, int callingPid) { if (userId == UserHandle.USER_SYSTEM) { synchronized (mLock) { // Make sure that the broadcast is sent only once for the system user. if (mIsBroadcastSentForSystemUserStarting) { return; } mIsBroadcastSentForSystemUserStarting = true; } } final Intent intent = new Intent(Intent.ACTION_USER_STARTING); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); intent.putExtra(Intent.EXTRA_USER_HANDLE, userId); mInjector.broadcastIntent(intent, /* resolvedType= */ null, new IIntentReceiver.Stub() { @Override public void performReceive(Intent intent, int resultCode, String data, Bundle extras, boolean ordered, boolean sticky, int sendingUser) throws RemoteException { } }, /* resultCode= */ 0, /* resultData= */ null, /* resultExtras= */ null, new String[]{INTERACT_ACROSS_USERS}, AppOpsManager.OP_NONE, /* bOptions= */ null, /* ordered= */ true, /* sticky= */ false, MY_PID, SYSTEM_UID, callingUid, callingPid, UserHandle.USER_ALL); } void sendUserSwitchBroadcasts(int oldUserId, int newUserId) { final int callingUid = Binder.getCallingUid(); final int callingPid = Binder.getCallingPid(); Loading Loading @@ -2568,7 +2622,7 @@ class UserController implements Handler.Callback { for (int i = 0; i < startedUsers.size(); i++) { int userId = startedUsers.keyAt(i); UserState uss = startedUsers.valueAt(i); if (!UserManager.isHeadlessSystemUserMode()) { if (!mInjector.isHeadlessSystemUserMode()) { finishUserBoot(uss, resultTo); } else { if (userId == UserHandle.USER_SYSTEM) { Loading @@ -2589,9 +2643,9 @@ class UserController implements Handler.Callback { mInjector.reportCurWakefulnessUsageEvent(); } // TODO(b/242195409): remove this method if initial system user boot logic is refactored? // TODO(b/266158156): remove this method if initial system user boot logic is refactored? void onSystemUserStarting() { if (!UserManager.isHeadlessSystemUserMode()) { if (!mInjector.isHeadlessSystemUserMode()) { // Don't need to call on HSUM because it will be called when the system user is // restarted on background mInjector.onUserStarting(UserHandle.USER_SYSTEM); Loading Loading @@ -3059,6 +3113,10 @@ class UserController implements Handler.Callback { pw.println(" mMaxRunningUsers:" + mMaxRunningUsers); pw.println(" mUserSwitchUiEnabled:" + mUserSwitchUiEnabled); pw.println(" mInitialized:" + mInitialized); pw.println(" mIsBroadcastSentForSystemUserStarted:" + mIsBroadcastSentForSystemUserStarted); pw.println(" mIsBroadcastSentForSystemUserStarting:" + mIsBroadcastSentForSystemUserStarting); if (mSwitchingFromSystemUserMessage != null) { pw.println(" mSwitchingFromSystemUserMessage: " + mSwitchingFromSystemUserMessage); } Loading Loading @@ -3749,6 +3807,10 @@ class UserController implements Handler.Callback { }, /* message= */ null); } boolean isHeadlessSystemUserMode() { return UserManager.isHeadlessSystemUserMode(); } boolean isUsersOnSecondaryDisplaysEnabled() { return UserManager.isVisibleBackgroundUsersEnabled(); } Loading
services/tests/servicestests/src/com/android/server/am/UserControllerTest.java +30 −0 Original line number Diff line number Diff line Loading @@ -133,6 +133,7 @@ public class UserControllerTest { private static final int TEST_USER_ID1 = 101; private static final int TEST_USER_ID2 = 102; private static final int TEST_USER_ID3 = 103; private static final int SYSTEM_USER_ID = UserHandle.SYSTEM.getIdentifier(); private static final int NONEXIST_USER_ID = 2; private static final int TEST_PRE_CREATED_USER_ID = 103; Loading Loading @@ -230,6 +231,31 @@ public class UserControllerTest { verifyUserAssignedToDisplay(TEST_USER_ID, Display.DEFAULT_DISPLAY); } @Test public void testStartUser_sendsNoBroadcastsForSystemUserInNonHeadlessMode() { setUpUser(SYSTEM_USER_ID, UserInfo.FLAG_SYSTEM, /* preCreated= */ false, UserManager.USER_TYPE_FULL_SYSTEM); mockIsHeadlessSystemUserMode(false); mUserController.startUser(SYSTEM_USER_ID, USER_START_MODE_FOREGROUND); assertWithMessage("Broadcasts for starting the system user in non-headless mode") .that(mInjector.mSentIntents).isEmpty(); } @Test public void testStartUser_sendsBroadcastsForSystemUserInHeadlessMode() { setUpUser(SYSTEM_USER_ID, UserInfo.FLAG_SYSTEM, /* preCreated= */ false, UserManager.USER_TYPE_SYSTEM_HEADLESS); mockIsHeadlessSystemUserMode(true); mUserController.startUser(SYSTEM_USER_ID, USER_START_MODE_FOREGROUND); assertWithMessage("Broadcasts for starting the system user in headless mode") .that(getActions(mInjector.mSentIntents)).containsExactly( Intent.ACTION_USER_STARTED, Intent.ACTION_USER_STARTING); } @Test public void testStartUser_displayAssignmentFailed() { doReturn(UserManagerInternal.USER_ASSIGNMENT_RESULT_FAILURE) Loading Loading @@ -999,6 +1025,10 @@ public class UserControllerTest { } } private void mockIsHeadlessSystemUserMode(boolean value) { when(mInjector.isHeadlessSystemUserMode()).thenReturn(value); } private void mockIsUsersOnSecondaryDisplaysEnabled(boolean value) { when(mInjector.isUsersOnSecondaryDisplaysEnabled()).thenReturn(value); } Loading