Stop user faster and clear stale broadcasts

Moved several USER_STOPPING registered receivers to listen
to USER_STOPPED, since they don't need to be blocking the
shutdown of the user.

Clear all stale broadcasts when stopping a user, so that we
don't unnecessarily start up processes and deliver stale
broadcasts. This was causing code to run when the user was
already stopped and resulted in crashes when other providers
and services couldn't be started anymore. Hopefully this fixes
many of those races.

Bug: 28371487
Change-Id: Ic35a7a23fa8fe009a53f8bf7545d4dad5fa34134
This commit is contained in:
Amith Yamasani
2016-04-26 14:35:54 -07:00
parent 0f018570ff
commit ad2e4bf9f3
6 changed files with 19 additions and 15 deletions

View File

@@ -119,7 +119,7 @@ public class UserSwitcherController {
filter.addAction(Intent.ACTION_USER_REMOVED);
filter.addAction(Intent.ACTION_USER_INFO_CHANGED);
filter.addAction(Intent.ACTION_USER_SWITCHED);
filter.addAction(Intent.ACTION_USER_STOPPING);
filter.addAction(Intent.ACTION_USER_STOPPED);
filter.addAction(Intent.ACTION_USER_UNLOCKED);
mContext.registerReceiverAsUser(mReceiver, UserHandle.SYSTEM, filter,
null /* permission */, null /* scheduler */);

View File

@@ -730,7 +730,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
//set up the listener for user state for creating user VPNs
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_USER_STARTING);
intentFilter.addAction(Intent.ACTION_USER_STOPPING);
intentFilter.addAction(Intent.ACTION_USER_STOPPED);
intentFilter.addAction(Intent.ACTION_USER_ADDED);
intentFilter.addAction(Intent.ACTION_USER_REMOVED);
intentFilter.addAction(Intent.ACTION_USER_UNLOCKED);
@@ -3619,7 +3619,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
synchronized(mVpns) {
Vpn userVpn = mVpns.get(userId);
if (userVpn == null) {
loge("Stopping user has no VPN");
loge("Stopped user has no VPN");
return;
}
mVpns.delete(userId);
@@ -3664,7 +3664,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
if (Intent.ACTION_USER_STARTING.equals(action)) {
onUserStart(userId);
} else if (Intent.ACTION_USER_STOPPING.equals(action)) {
} else if (Intent.ACTION_USER_STOPPED.equals(action)) {
onUserStop(userId);
} else if (Intent.ACTION_USER_ADDED.equals(action)) {
onUserAdded(userId);

View File

@@ -5949,6 +5949,15 @@ public final class ActivityManagerService extends ActivityManagerNative
}
final boolean clearBroadcastQueueForUserLocked(int userId) {
boolean didSomething = false;
for (int i = mBroadcastQueues.length - 1; i >= 0; i--) {
didSomething |= mBroadcastQueues[i].cleanupDisabledPackageReceiversLocked(
null, null, userId, true);
}
return didSomething;
}
final boolean forceStopPackageLocked(String packageName, int appId,
boolean callerWillRestart, boolean purgeCache, boolean doit,
boolean evenPersistent, boolean uninstalling, int userId, String reason) {

View File

@@ -483,6 +483,8 @@ final class UserController {
});
}
};
// Clear broadcast queue for the user to avoid delivering stale broadcasts
mService.clearBroadcastQueueForUserLocked(userId);
// Kick things off.
mService.broadcastIntentLocked(null, null, stoppingIntent,
null, stoppingReceiver, 0, null, null,

View File

@@ -396,8 +396,8 @@ public class SyncManager {
onUserRemoved(userId);
} else if (Intent.ACTION_USER_UNLOCKED.equals(action)) {
onUserUnlocked(userId);
} else if (Intent.ACTION_USER_STOPPING.equals(action)) {
onUserStopping(userId);
} else if (Intent.ACTION_USER_STOPPED.equals(action)) {
onUserStopped(userId);
}
}
};
@@ -550,7 +550,7 @@ public class SyncManager {
intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_USER_REMOVED);
intentFilter.addAction(Intent.ACTION_USER_UNLOCKED);
intentFilter.addAction(Intent.ACTION_USER_STOPPING);
intentFilter.addAction(Intent.ACTION_USER_STOPPED);
mContext.registerReceiverAsUser(
mUserIntentReceiver, UserHandle.ALL, intentFilter, null, null);
@@ -1422,7 +1422,7 @@ public class SyncManager {
}
}
private void onUserStopping(int userId) {
private void onUserStopped(int userId) {
updateRunningAccounts(null /* Don't sync any target */);
cancelActiveSync(

View File

@@ -862,7 +862,6 @@ public class WallpaperManagerService extends IWallpaperManager.Stub {
IntentFilter userFilter = new IntentFilter();
userFilter.addAction(Intent.ACTION_USER_REMOVED);
userFilter.addAction(Intent.ACTION_USER_STOPPING);
mContext.registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@@ -871,12 +870,6 @@ public class WallpaperManagerService extends IWallpaperManager.Stub {
onRemoveUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
UserHandle.USER_NULL));
}
// TODO: Race condition causing problems when cleaning up on stopping a user.
// Comment this out for now.
// else if (Intent.ACTION_USER_STOPPING.equals(action)) {
// onStoppingUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
// UserHandle.USER_NULL));
// }
}
}, userFilter);