diff options
author | Christopher Tate <ctate@google.com> | 2013-05-02 13:27:27 -0700 |
---|---|---|
committer | Christopher Tate <ctate@google.com> | 2013-05-02 14:18:51 -0700 |
commit | 1e08f5c3b358b75792a1839f758bc61409f71a58 (patch) | |
tree | b7fe4571b3710e6b98500a45f2ad5258853bb66a | |
parent | c31126088fea61a9b5ba6cdb1fd2791e86800a8a (diff) | |
download | frameworks_base-1e08f5c3b358b75792a1839f758bc61409f71a58.zip frameworks_base-1e08f5c3b358b75792a1839f758bc61409f71a58.tar.gz frameworks_base-1e08f5c3b358b75792a1839f758bc61409f71a58.tar.bz2 |
Send package-changed broadcasts to the correct users
Also be sure to drop any pending package-changed broadcasts
that are targeted to a now-removed user.
Bug 8594153
Change-Id: Ib14874b4a67b968bbf6ca12ee095c85383aff324
-rw-r--r-- | services/java/com/android/server/pm/PackageManagerService.java | 105 |
1 files changed, 88 insertions, 17 deletions
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java index ada600d..e201d29 100644 --- a/services/java/com/android/server/pm/PackageManagerService.java +++ b/services/java/com/android/server/pm/PackageManagerService.java @@ -422,8 +422,71 @@ public class PackageManagerService extends IPackageManager.Stub { PackageParser.Package mPlatformPackage; // Set of pending broadcasts for aggregating enable/disable of components. - final HashMap<String, ArrayList<String>> mPendingBroadcasts - = new HashMap<String, ArrayList<String>>(); + static class PendingPackageBroadcasts { + // for each user id, a map of <package name -> components within that package> + final SparseArray<HashMap<String, ArrayList<String>>> mUidMap; + + public PendingPackageBroadcasts() { + mUidMap = new SparseArray<HashMap<String, ArrayList<String>>>(); + } + + public ArrayList<String> get(int userId, String packageName) { + HashMap<String, ArrayList<String>> packages = getOrAllocate(userId); + return packages.get(packageName); + } + + public void put(int userId, String packageName, ArrayList<String> components) { + HashMap<String, ArrayList<String>> packages = getOrAllocate(userId); + packages.put(packageName, components); + } + + public void remove(int userId, String packageName) { + HashMap<String, ArrayList<String>> packages = mUidMap.get(userId); + if (packages != null) { + packages.remove(packageName); + } + } + + public void remove(int userId) { + mUidMap.remove(userId); + } + + public int userIdCount() { + return mUidMap.size(); + } + + public int userIdAt(int n) { + return mUidMap.keyAt(n); + } + + public HashMap<String, ArrayList<String>> packagesForUserId(int userId) { + return mUidMap.get(userId); + } + + public int size() { + // total number of pending broadcast entries across all userIds + int num = 0; + for (int i = 0; i< mUidMap.size(); i++) { + num += mUidMap.valueAt(i).size(); + } + return num; + } + + public void clear() { + mUidMap.clear(); + } + + private HashMap<String, ArrayList<String>> getOrAllocate(int userId) { + HashMap<String, ArrayList<String>> map = mUidMap.get(userId); + if (map == null) { + map = new HashMap<String, ArrayList<String>>(); + mUidMap.put(userId, map); + } + return map; + } + } + final PendingPackageBroadcasts mPendingBroadcasts = new PendingPackageBroadcasts(); + // Service Connection to remote media container service to copy // package uri's from external media onto secure containers // or internal storage. @@ -667,16 +730,23 @@ public class PackageManagerService extends IPackageManager.Stub { packages = new String[size]; components = new ArrayList[size]; uids = new int[size]; - Iterator<Map.Entry<String, ArrayList<String>>> - it = mPendingBroadcasts.entrySet().iterator(); - int i = 0; - while (it.hasNext() && i < size) { - Map.Entry<String, ArrayList<String>> ent = it.next(); - packages[i] = ent.getKey(); - components[i] = ent.getValue(); - PackageSetting ps = mSettings.mPackages.get(ent.getKey()); - uids[i] = (ps != null) ? ps.appId : -1; - i++; + int i = 0; // filling out the above arrays + + for (int n = 0; n < mPendingBroadcasts.userIdCount(); n++) { + int packageUserId = mPendingBroadcasts.userIdAt(n); + Iterator<Map.Entry<String, ArrayList<String>>> it + = mPendingBroadcasts.packagesForUserId(packageUserId) + .entrySet().iterator(); + while (it.hasNext() && i < size) { + Map.Entry<String, ArrayList<String>> ent = it.next(); + packages[i] = ent.getKey(); + components[i] = ent.getValue(); + PackageSetting ps = mSettings.mPackages.get(ent.getKey()); + uids[i] = (ps != null) + ? UserHandle.getUid(packageUserId, ps.appId) + : -1; + i++; + } } size = i; mPendingBroadcasts.clear(); @@ -9541,8 +9611,7 @@ public class PackageManagerService extends IPackageManager.Stub { } } mSettings.writePackageRestrictionsLPr(userId); - packageUid = UserHandle.getUid(userId, pkgSetting.appId); - components = mPendingBroadcasts.get(packageName); + components = mPendingBroadcasts.get(userId, packageName); final boolean newPackage = components == null; if (newPackage) { components = new ArrayList<String>(); @@ -9554,10 +9623,10 @@ public class PackageManagerService extends IPackageManager.Stub { sendNow = true; // Purge entry from pending broadcast list if another one exists already // since we are sending one right away. - mPendingBroadcasts.remove(packageName); + mPendingBroadcasts.remove(userId, packageName); } else { if (newPackage) { - mPendingBroadcasts.put(packageName, components); + mPendingBroadcasts.put(userId, packageName, components); } if (!mHandler.hasMessages(SEND_PENDING_BROADCAST)) { // Schedule a message @@ -9569,6 +9638,7 @@ public class PackageManagerService extends IPackageManager.Stub { long callingId = Binder.clearCallingIdentity(); try { if (sendNow) { + packageUid = UserHandle.getUid(userId, pkgSetting.appId); sendPackageChangedBroadcast(packageName, (flags&PackageManager.DONT_KILL_APP) != 0, components, packageUid); } @@ -10704,8 +10774,9 @@ public class PackageManagerService extends IPackageManager.Stub { /** Called by UserManagerService */ void cleanUpUserLILPw(int userHandle) { - if (mDirtyUsers.remove(userHandle)); + mDirtyUsers.remove(userHandle); mSettings.removeUserLPr(userHandle); + mPendingBroadcasts.remove(userHandle); if (mInstaller != null) { // Technically, we shouldn't be doing this with the package lock // held. However, this is very rare, and there is already so much |