Merge "Send user starting broadcast for non-automotive devices in HSUM." into udc-dev
This commit is contained in:
@@ -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();
|
||||
|
||||
@@ -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");
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
|
||||
/**
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
@@ -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 {
|
||||
@@ -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();
|
||||
@@ -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) {
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
}
|
||||
@@ -3749,6 +3807,10 @@ class UserController implements Handler.Callback {
|
||||
}, /* message= */ null);
|
||||
}
|
||||
|
||||
boolean isHeadlessSystemUserMode() {
|
||||
return UserManager.isHeadlessSystemUserMode();
|
||||
}
|
||||
|
||||
boolean isUsersOnSecondaryDisplaysEnabled() {
|
||||
return UserManager.isVisibleBackgroundUsersEnabled();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user