Merge "Broadcast USER_INITIALIZE after user is unlocked" into nyc-dev

This commit is contained in:
Fyodor Kupolov
2016-04-27 23:02:08 +00:00
committed by Android (Google) Code Review
2 changed files with 65 additions and 66 deletions

View File

@@ -220,6 +220,7 @@ final class UserController {
private void finishUserBoot(UserState uss, IIntentReceiver resultTo) { private void finishUserBoot(UserState uss, IIntentReceiver resultTo) {
final int userId = uss.mHandle.getIdentifier(); final int userId = uss.mHandle.getIdentifier();
Slog.d(TAG, "Finishing user boot " + userId);
synchronized (mService) { synchronized (mService) {
// Bail if we ended up with a stale user // Bail if we ended up with a stale user
if (mStartedUsers.get(userId) != uss) return; if (mStartedUsers.get(userId) != uss) return;
@@ -248,7 +249,8 @@ final class UserController {
+ "): attempting unlock because parent is unlocked"); + "): attempting unlock because parent is unlocked");
maybeUnlockUser(userId); maybeUnlockUser(userId);
} else { } else {
Slog.d(TAG, "User " + userId + " (parent " + parent.id String parentId = (parent == null) ? "<null>" : String.valueOf(parent.id);
Slog.d(TAG, "User " + userId + " (parent " + parentId
+ "): delaying unlock because parent is locked"); + "): delaying unlock because parent is locked");
} }
} else { } else {
@@ -333,6 +335,10 @@ final class UserController {
synchronized (mService) { synchronized (mService) {
// Bail if we ended up with a stale user // Bail if we ended up with a stale user
if (mStartedUsers.get(uss.mHandle.getIdentifier()) != uss) return; if (mStartedUsers.get(uss.mHandle.getIdentifier()) != uss) return;
final UserInfo userInfo = getUserInfo(userId);
if (userInfo == null) {
return;
}
// Only keep marching forward if user is actually unlocked // Only keep marching forward if user is actually unlocked
if (!isUserKeyUnlocked(userId)) return; if (!isUserKeyUnlocked(userId)) return;
@@ -341,6 +347,25 @@ final class UserController {
// Remember that we logged in // Remember that we logged in
mUserManager.onUserLoggedIn(userId); mUserManager.onUserLoggedIn(userId);
if (!userInfo.isInitialized()) {
if (userId != UserHandle.USER_SYSTEM) {
Slog.d(TAG, "Initializing user #" + userId);
Intent intent = new Intent(Intent.ACTION_USER_INITIALIZE);
intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
mService.broadcastIntentLocked(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) {
// Note: performReceive is called with mService lock held
getUserManager().makeInitialized(userInfo.id);
}
}, 0, null, null, null, AppOpsManager.OP_NONE,
null, true, false, MY_PID, SYSTEM_UID, userId);
}
}
Slog.d(TAG, "Sending BOOT_COMPLETE user #" + userId);
final Intent bootIntent = new Intent(Intent.ACTION_BOOT_COMPLETED, null); final Intent bootIntent = new Intent(Intent.ACTION_BOOT_COMPLETED, null);
bootIntent.putExtra(Intent.EXTRA_USER_HANDLE, userId); bootIntent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
bootIntent.addFlags(Intent.FLAG_RECEIVER_NO_ABORT bootIntent.addFlags(Intent.FLAG_RECEIVER_NO_ABORT
@@ -669,6 +694,35 @@ final class UserController {
} }
} }
/**
* Start user, if its not already running.
* <p>The user will be brought to the foreground, if {@code foreground} parameter is set.
* When starting the user, multiple intents will be broadcast in the following order:</p>
* <ul>
* <li>{@link Intent#ACTION_USER_STARTED} - sent to registered receivers of the new user
* <li>{@link Intent#ACTION_USER_BACKGROUND} - sent to registered receivers of the outgoing
* user and all profiles of this user. Sent only if {@code foreground} parameter is true
* <li>{@link Intent#ACTION_USER_FOREGROUND} - sent to registered receivers of the new
* user and all profiles of this user. Sent only if {@code foreground} parameter is true
* <li>{@link Intent#ACTION_USER_SWITCHED} - sent to registered receivers of the new user.
* Sent only if {@code foreground} parameter is true
* <li>{@link Intent#ACTION_USER_STARTING} - ordered broadcast sent to registered receivers
* of the new fg user
* <li>{@link Intent#ACTION_LOCKED_BOOT_COMPLETED} - ordered broadcast sent to receivers of
* the new user
* <li>{@link Intent#ACTION_USER_UNLOCKED} - sent to registered receivers of the new user
* <li>{@link Intent#ACTION_PRE_BOOT_COMPLETED} - ordered broadcast sent to receivers of the
* new user. Sent only when the user is booting after a system update.
* <li>{@link Intent#ACTION_USER_INITIALIZE} - ordered broadcast sent to receivers of the
* new user. Sent only the first time a user is starting.
* <li>{@link Intent#ACTION_BOOT_COMPLETED} - ordered broadcast sent to receivers of the new
* user. Indicates that the user has finished booting.
* </ul>
*
* @param userId ID of the user to start
* @param foreground true if user should be brought to the foreground
* @return true if the user has been successfully started
*/
boolean startUser(final int userId, final boolean foreground) { boolean startUser(final int userId, final boolean foreground) {
if (mService.checkCallingPermission(INTERACT_ACROSS_USERS_FULL) if (mService.checkCallingPermission(INTERACT_ACROSS_USERS_FULL)
!= PackageManager.PERMISSION_GRANTED) { != PackageManager.PERMISSION_GRANTED) {
@@ -680,7 +734,7 @@ final class UserController {
throw new SecurityException(msg); throw new SecurityException(msg);
} }
if (DEBUG_MU) Slog.i(TAG, "starting userid:" + userId + " fore:" + foreground); Slog.i(TAG, "Starting userid:" + userId + " fg:" + foreground);
final long ident = Binder.clearCallingIdentity(); final long ident = Binder.clearCallingIdentity();
try { try {
@@ -790,36 +844,8 @@ final class UserController {
null, false, false, MY_PID, SYSTEM_UID, userId); null, false, false, MY_PID, SYSTEM_UID, userId);
} }
if ((userInfo.flags&UserInfo.FLAG_INITIALIZED) == 0) {
if (userId != UserHandle.USER_SYSTEM) {
Intent intent = new Intent(Intent.ACTION_USER_INITIALIZE);
intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
mService.broadcastIntentLocked(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) {
mHandler.post(new Runnable() {
@Override
public void run() {
onUserInitialized(uss, foreground,
oldUserId, userId);
}
});
}
}, 0, null, null, null, AppOpsManager.OP_NONE,
null, true, false, MY_PID, SYSTEM_UID, userId);
uss.initializing = true;
} else {
getUserManager().makeInitialized(userInfo.id);
}
}
if (foreground) { if (foreground) {
if (!uss.initializing) {
moveUserToForegroundLocked(uss, oldUserId, userId); moveUserToForegroundLocked(uss, oldUserId, userId);
}
} else { } else {
mService.mUserController.finishUserBoot(uss); mService.mUserController.finishUserBoot(uss);
} }
@@ -996,8 +1022,8 @@ final class UserController {
} }
} }
void dispatchUserSwitch(final UserState uss, final int oldUserId, void dispatchUserSwitch(final UserState uss, final int oldUserId, final int newUserId) {
final int newUserId) { Slog.d(TAG, "Dispatch onUserSwitching oldUser #" + oldUserId + " newUser #" + newUserId);
final int observerCount = mUserSwitchObservers.beginBroadcast(); final int observerCount = mUserSwitchObservers.beginBroadcast();
if (observerCount > 0) { if (observerCount > 0) {
final IRemoteCallback callback = new IRemoteCallback.Stub() { final IRemoteCallback callback = new IRemoteCallback.Stub() {
@@ -1041,39 +1067,14 @@ final class UserController {
} }
void continueUserSwitch(UserState uss, int oldUserId, int newUserId) { void continueUserSwitch(UserState uss, int oldUserId, int newUserId) {
completeSwitchAndInitialize(uss, oldUserId, newUserId, false, true); Slog.d(TAG, "Continue user switch oldUser #" + oldUserId + ", newUser #" + newUserId);
}
void onUserInitialized(UserState uss, boolean foreground, int oldUserId, int newUserId) {
synchronized (mService) { synchronized (mService) {
if (foreground) {
moveUserToForegroundLocked(uss, oldUserId, newUserId);
}
}
completeSwitchAndInitialize(uss, oldUserId, newUserId, true, false);
}
void completeSwitchAndInitialize(UserState uss, int oldUserId, int newUserId,
boolean clearInitializing, boolean clearSwitching) {
boolean unfrozen = false;
synchronized (mService) {
if (clearInitializing) {
uss.initializing = false;
getUserManager().makeInitialized(uss.mHandle.getIdentifier());
}
if (clearSwitching) {
uss.switching = false;
}
if (!uss.switching && !uss.initializing) {
mService.mWindowManager.stopFreezingScreen(); mService.mWindowManager.stopFreezingScreen();
unfrozen = true;
} }
} uss.switching = false;
if (unfrozen) {
mHandler.removeMessages(REPORT_USER_SWITCH_COMPLETE_MSG); mHandler.removeMessages(REPORT_USER_SWITCH_COMPLETE_MSG);
mHandler.sendMessage(mHandler.obtainMessage(REPORT_USER_SWITCH_COMPLETE_MSG, mHandler.sendMessage(mHandler.obtainMessage(REPORT_USER_SWITCH_COMPLETE_MSG,
newUserId, 0)); newUserId, 0));
}
stopGuestOrEphemeralUserIfBackground(); stopGuestOrEphemeralUserIfBackground();
stopBackgroundUsersIfEnforced(oldUserId); stopBackgroundUsersIfEnforced(oldUserId);
} }

View File

@@ -54,7 +54,6 @@ public final class UserState {
public int state = STATE_BOOTING; public int state = STATE_BOOTING;
public int lastState = STATE_BOOTING; public int lastState = STATE_BOOTING;
public boolean switching; public boolean switching;
public boolean initializing;
/** /**
* The last time that a provider was reported to usage stats as being brought to important * The last time that a provider was reported to usage stats as being brought to important
@@ -103,7 +102,6 @@ public final class UserState {
pw.print(prefix); pw.print(prefix);
pw.print("state="); pw.print(stateToString(state)); pw.print("state="); pw.print(stateToString(state));
if (switching) pw.print(" SWITCHING"); if (switching) pw.print(" SWITCHING");
if (initializing) pw.print(" INITIALIZING");
pw.println(); pw.println();
} }
} }