From ad2e4bf9f36cf612db6c397feca8effb125ee541 Mon Sep 17 00:00:00 2001 From: Amith Yamasani Date: Tue, 26 Apr 2016 14:35:54 -0700 Subject: [PATCH] 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 --- .../statusbar/policy/UserSwitcherController.java | 2 +- .../java/com/android/server/ConnectivityService.java | 6 +++--- .../com/android/server/am/ActivityManagerService.java | 9 +++++++++ .../core/java/com/android/server/am/UserController.java | 2 ++ .../java/com/android/server/content/SyncManager.java | 8 ++++---- .../server/wallpaper/WallpaperManagerService.java | 7 ------- 6 files changed, 19 insertions(+), 15 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java index c82ba3b168902..6800772b754fd 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java @@ -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 */); diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 0287332bb5a4c..d85827e99079a 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -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); diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 9d7ddc7b96c12..ec4d40cad7eb2 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -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) { diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java index cdb68d8aeff6b..5bc1dda588b12 100644 --- a/services/core/java/com/android/server/am/UserController.java +++ b/services/core/java/com/android/server/am/UserController.java @@ -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, diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java index fcf216240a073..493fc4a4bb8ca 100644 --- a/services/core/java/com/android/server/content/SyncManager.java +++ b/services/core/java/com/android/server/content/SyncManager.java @@ -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( diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java index d6ace91f64d49..af7e66d376f18 100644 --- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java +++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java @@ -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);