summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAmith Yamasani <yamasani@google.com>2015-02-06 14:41:40 -0800
committerAmith Yamasani <yamasani@google.com>2015-02-09 11:10:31 -0800
commit460a7b461902d55d20e99f6c19e131947384d04a (patch)
tree6d0937c92b5880e55cafb44b3bb196fef70de9fc
parentf789d45b24acc3745ccc97adb687502d488404f6 (diff)
downloadframeworks_base-460a7b461902d55d20e99f6c19e131947384d04a.zip
frameworks_base-460a7b461902d55d20e99f6c19e131947384d04a.tar.gz
frameworks_base-460a7b461902d55d20e99f6c19e131947384d04a.tar.bz2
Limit cache update to packages that have changed
When updating the RegisteredServicesCache, don't remove any packages that are not in the list of modified packages. Bug: 19228972 Change-Id: Id4f264403b7ceca9005854dfbbc25abfd7b54889
-rw-r--r--core/java/android/content/pm/RegisteredServicesCache.java52
1 files changed, 43 insertions, 9 deletions
diff --git a/core/java/android/content/pm/RegisteredServicesCache.java b/core/java/android/content/pm/RegisteredServicesCache.java
index 4a743a5..391ef22 100644
--- a/core/java/android/content/pm/RegisteredServicesCache.java
+++ b/core/java/android/content/pm/RegisteredServicesCache.java
@@ -35,6 +35,7 @@ import android.util.SparseArray;
import android.util.Xml;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FastXmlSerializer;
import com.google.android.collect.Lists;
import com.google.android.collect.Maps;
@@ -155,9 +156,19 @@ public abstract class RegisteredServicesCache<V> {
// package is going away, but it's the middle of an upgrade: keep the current
// state and do nothing here. This clause is intentionally empty.
} else {
+ int[] uids = null;
// either we're adding/changing, or it's a removal without replacement, so
- // we need to recalculate the set of available services
- generateServicesMap(userId);
+ // we need to update the set of available services
+ if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(action)
+ || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) {
+ uids = intent.getIntArrayExtra(Intent.EXTRA_CHANGED_UID_LIST);
+ } else {
+ int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
+ if (uid > 0) {
+ uids = new int[] { uid };
+ }
+ }
+ generateServicesMap(uids, userId);
}
}
@@ -270,7 +281,7 @@ public abstract class RegisteredServicesCache<V> {
// Find user and lazily populate cache
final UserServices<V> user = findOrCreateUserLocked(userId);
if (user.services == null) {
- generateServicesMap(userId);
+ generateServicesMap(null, userId);
}
return user.services.get(type);
}
@@ -285,7 +296,7 @@ public abstract class RegisteredServicesCache<V> {
// Find user and lazily populate cache
final UserServices<V> user = findOrCreateUserLocked(userId);
if (user.services == null) {
- generateServicesMap(userId);
+ generateServicesMap(null, userId);
}
return Collections.unmodifiableCollection(
new ArrayList<ServiceInfo<V>>(user.services.values()));
@@ -311,10 +322,13 @@ public abstract class RegisteredServicesCache<V> {
/**
* Populate {@link UserServices#services} by scanning installed packages for
* given {@link UserHandle}.
+ * @param changedUids the array of uids that have been affected, as mentioned in the broadcast
+ * or null to assume that everything is affected.
+ * @param userId the user for whom to update the services map.
*/
- private void generateServicesMap(int userId) {
+ private void generateServicesMap(int[] changedUids, int userId) {
if (DEBUG) {
- Slog.d(TAG, "generateServicesMap() for " + userId);
+ Slog.d(TAG, "generateServicesMap() for " + userId + ", changed UIDs = " + changedUids);
}
final PackageManager pm = mContext.getPackageManager();
@@ -341,8 +355,6 @@ public abstract class RegisteredServicesCache<V> {
final boolean firstScan = user.services == null;
if (firstScan) {
user.services = Maps.newHashMap();
- } else {
- user.services.clear();
}
StringBuilder changes = new StringBuilder();
@@ -399,7 +411,10 @@ public abstract class RegisteredServicesCache<V> {
ArrayList<V> toBeRemoved = Lists.newArrayList();
for (V v1 : user.persistentServices.keySet()) {
- if (!containsType(serviceInfos, v1)) {
+ // Remove a persisted service that's not in the currently available services list.
+ // And only if it is in the list of changedUids.
+ if (!containsType(serviceInfos, v1)
+ && containsUid(changedUids, user.persistentServices.get(v1))) {
toBeRemoved.add(v1);
}
}
@@ -409,9 +424,20 @@ public abstract class RegisteredServicesCache<V> {
}
changed = true;
user.persistentServices.remove(v1);
+ user.services.remove(v1);
notifyListener(v1, userId, true /* removed */);
}
if (DEBUG) {
+ Log.d(TAG, "user.services=");
+ for (V v : user.services.keySet()) {
+ Log.d(TAG, " " + v + " " + user.services.get(v));
+ }
+ Log.d(TAG, "user.persistentServices=");
+ for (V v : user.persistentServices.keySet()) {
+ Log.d(TAG, " " + v + " " + user.persistentServices.get(v));
+ }
+ }
+ if (DEBUG) {
if (changes.length() > 0) {
Log.d(TAG, "generateServicesMap(" + mInterfaceName + "): " +
serviceInfos.size() + " services:\n" + changes);
@@ -426,6 +452,14 @@ public abstract class RegisteredServicesCache<V> {
}
}
+ /**
+ * Returns true if the list of changed uids is null (wildcard) or the specified uid
+ * is contained in the list of changed uids.
+ */
+ private boolean containsUid(int[] changedUids, int uid) {
+ return changedUids == null || ArrayUtils.contains(changedUids, uid);
+ }
+
private boolean containsType(ArrayList<ServiceInfo<V>> serviceInfos, V type) {
for (int i = 0, N = serviceInfos.size(); i < N; i++) {
if (serviceInfos.get(i).type.equals(type)) {