@@ -3739,8 +3739,7 @@ private void forceStopPackageLocked(final String packageName, int uid) {
37393739 private void forceStopUserLocked(int userId) {
37403740 forceStopPackageLocked(null, -1, false, false, true, false, userId);
37413741 Intent intent = new Intent(Intent.ACTION_USER_STOPPED);
3742- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
3743- | Intent.FLAG_RECEIVER_FOREGROUND);
3742+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
37443743 intent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
37453744 broadcastIntentLocked(null, null, intent,
37463745 null, null, 0, null, null, null,
@@ -14128,6 +14127,19 @@ public boolean switchUser(int userId) {
1412814127
1412914128 final UserStartedState uss = mStartedUsers.get(userId);
1413014129
14130+ // Make sure user is in the started state. If it is currently
14131+ // stopping, we need to knock that off.
14132+ if (uss.mState == UserStartedState.STATE_STOPPING) {
14133+ // If we are stopping, we haven't sent ACTION_SHUTDOWN,
14134+ // so we can just fairly silently bring the user back from
14135+ // the almost-dead.
14136+ uss.mState = UserStartedState.STATE_RUNNING;
14137+ } else if (uss.mState == UserStartedState.STATE_SHUTDOWN) {
14138+ // This means ACTION_SHUTDOWN has been sent, so we will
14139+ // need to treat this as a new boot of the user.
14140+ uss.mState = UserStartedState.STATE_BOOTING;
14141+ }
14142+
1413114143 mHandler.removeMessages(REPORT_USER_SWITCH_MSG);
1413214144 mHandler.removeMessages(USER_SWITCH_TIMEOUT_MSG);
1413314145 mHandler.sendMessage(mHandler.obtainMessage(REPORT_USER_SWITCH_MSG,
@@ -14205,6 +14217,19 @@ void sendUserSwitchBroadcastsLocked(int oldUserId, int newUserId) {
1420514217 null, null, 0, null, null,
1420614218 android.Manifest.permission.MANAGE_USERS,
1420714219 false, false, MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL);
14220+ intent = new Intent(Intent.ACTION_USER_STARTING);
14221+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
14222+ intent.putExtra(Intent.EXTRA_USER_HANDLE, newUserId);
14223+ broadcastIntentLocked(null, null, intent,
14224+ null, new IIntentReceiver.Stub() {
14225+ @Override
14226+ public void performReceive(Intent intent, int resultCode, String data,
14227+ Bundle extras, boolean ordered, boolean sticky, int sendingUser)
14228+ throws RemoteException {
14229+ }
14230+ }, 0, null, null,
14231+ android.Manifest.permission.INTERACT_ACROSS_USERS,
14232+ false, false, MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL);
1420814233 }
1420914234 } finally {
1421014235 Binder.restoreCallingIdentity(ident);
@@ -14293,7 +14318,8 @@ void completeSwitchAndInitalizeLocked(UserStartedState uss) {
1429314318
1429414319 void finishUserSwitch(UserStartedState uss) {
1429514320 synchronized (this) {
14296- if (uss.mState == UserStartedState.STATE_BOOTING
14321+ if ((uss.mState == UserStartedState.STATE_BOOTING
14322+ || uss.mState == UserStartedState.STATE_SHUTDOWN)
1429714323 && mStartedUsers.get(uss.mHandle.getIdentifier()) == uss) {
1429814324 uss.mState = UserStartedState.STATE_RUNNING;
1429914325 final int userId = uss.mHandle.getIdentifier();
@@ -14315,7 +14341,8 @@ void finishUserSwitch(UserStartedState uss) {
1431514341 num--;
1431614342 continue;
1431714343 }
14318- if (oldUss.mState == UserStartedState.STATE_STOPPING) {
14344+ if (oldUss.mState == UserStartedState.STATE_STOPPING
14345+ || oldUss.mState == UserStartedState.STATE_SHUTDOWN) {
1431914346 // This user is already stopping, doesn't count.
1432014347 num--;
1432114348 i++;
@@ -14380,23 +14407,50 @@ public void run() {
1438014407 uss.mStopCallbacks.add(callback);
1438114408 }
1438214409
14383- if (uss.mState != UserStartedState.STATE_STOPPING) {
14410+ if (uss.mState != UserStartedState.STATE_STOPPING
14411+ && uss.mState != UserStartedState.STATE_SHUTDOWN) {
1438414412 uss.mState = UserStartedState.STATE_STOPPING;
1438514413
1438614414 long ident = Binder.clearCallingIdentity();
1438714415 try {
14388- // Inform of user switch
14389- Intent intent = new Intent(Intent.ACTION_SHUTDOWN);
14390- final IIntentReceiver resultReceiver = new IIntentReceiver.Stub() {
14416+ // We are going to broadcast ACTION_USER_STOPPING and then
14417+ // once that is down send a final ACTION_SHUTDOWN and then
14418+ // stop the user.
14419+ final Intent stoppingIntent = new Intent(Intent.ACTION_USER_STOPPING);
14420+ stoppingIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
14421+ stoppingIntent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
14422+ final Intent shutdownIntent = new Intent(Intent.ACTION_SHUTDOWN);
14423+ // This is the result receiver for the final shutdown broadcast.
14424+ final IIntentReceiver shutdownReceiver = new IIntentReceiver.Stub() {
1439114425 @Override
1439214426 public void performReceive(Intent intent, int resultCode, String data,
1439314427 Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
1439414428 finishUserStop(uss);
1439514429 }
1439614430 };
14397- broadcastIntentLocked(null, null, intent,
14398- null, resultReceiver, 0, null, null, null,
14399- true, false, MY_PID, Process.SYSTEM_UID, userId);
14431+ // This is the result receiver for the initial stopping broadcast.
14432+ final IIntentReceiver stoppingReceiver = new IIntentReceiver.Stub() {
14433+ @Override
14434+ public void performReceive(Intent intent, int resultCode, String data,
14435+ Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
14436+ // On to the next.
14437+ synchronized (ActivityManagerService.this) {
14438+ if (uss.mState != UserStartedState.STATE_STOPPING) {
14439+ // Whoops, we are being started back up. Abort, abort!
14440+ return;
14441+ }
14442+ uss.mState = UserStartedState.STATE_SHUTDOWN;
14443+ }
14444+ broadcastIntentLocked(null, null, shutdownIntent,
14445+ null, shutdownReceiver, 0, null, null, null,
14446+ true, false, MY_PID, Process.SYSTEM_UID, userId);
14447+ }
14448+ };
14449+ // Kick things off.
14450+ broadcastIntentLocked(null, null, stoppingIntent,
14451+ null, stoppingReceiver, 0, null, null,
14452+ android.Manifest.permission.INTERACT_ACROSS_USERS,
14453+ true, false, MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL);
1440014454 } finally {
1440114455 Binder.restoreCallingIdentity(ident);
1440214456 }
@@ -14411,8 +14465,9 @@ void finishUserStop(UserStartedState uss) {
1441114465 ArrayList<IStopUserCallback> callbacks;
1441214466 synchronized (this) {
1441314467 callbacks = new ArrayList<IStopUserCallback>(uss.mStopCallbacks);
14414- if (uss.mState != UserStartedState.STATE_STOPPING
14415- || mStartedUsers.get(userId) != uss) {
14468+ if (mStartedUsers.get(userId) != uss) {
14469+ stopped = false;
14470+ } else if (uss.mState != UserStartedState.STATE_SHUTDOWN) {
1441614471 stopped = false;
1441714472 } else {
1441814473 stopped = true;
@@ -14476,7 +14531,8 @@ public boolean isUserRunning(int userId) {
1447614531
1447714532 boolean isUserRunningLocked(int userId) {
1447814533 UserStartedState state = mStartedUsers.get(userId);
14479- return state != null && state.mState != UserStartedState.STATE_STOPPING;
14534+ return state != null && state.mState != UserStartedState.STATE_STOPPING
14535+ && state.mState != UserStartedState.STATE_SHUTDOWN;
1448014536 }
1448114537
1448214538 @Override
0 commit comments