summaryrefslogtreecommitdiff
path: root/core/java/android/content/pm/RegisteredServicesCache.java
diff options
context:
space:
mode:
Diffstat (limited to 'core/java/android/content/pm/RegisteredServicesCache.java')
-rw-r--r--core/java/android/content/pm/RegisteredServicesCache.java59
1 files changed, 39 insertions, 20 deletions
diff --git a/core/java/android/content/pm/RegisteredServicesCache.java b/core/java/android/content/pm/RegisteredServicesCache.java
index a8c3b889421b..d7c4439f8258 100644
--- a/core/java/android/content/pm/RegisteredServicesCache.java
+++ b/core/java/android/content/pm/RegisteredServicesCache.java
@@ -17,6 +17,7 @@
package android.content.pm;
import android.Manifest;
+import android.annotation.Nullable;
import android.annotation.UnsupportedAppUsage;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
@@ -176,7 +177,8 @@ public abstract class RegisteredServicesCache<V> {
mContext.registerReceiver(mUserRemovedReceiver, userFilter);
}
- private final void handlePackageEvent(Intent intent, int userId) {
+ @VisibleForTesting
+ protected void handlePackageEvent(Intent intent, int userId) {
// Don't regenerate the services map when the package is removed or its
// ASEC container unmounted as a step in replacement. The subsequent
// _ADDED / _AVAILABLE call will regenerate the map in the final state.
@@ -238,6 +240,9 @@ public abstract class RegisteredServicesCache<V> {
public void invalidateCache(int userId) {
synchronized (mServicesLock) {
+ if (DEBUG) {
+ Slog.d(TAG, "invalidating cache for " + userId + " " + mInterfaceName);
+ }
final UserServices<V> user = findOrCreateUserLocked(userId);
user.services = null;
onServicesChangedLocked(userId);
@@ -465,34 +470,48 @@ public abstract class RegisteredServicesCache<V> {
* or null to assume that everything is affected.
* @param userId the user for whom to update the services map.
*/
- private void generateServicesMap(int[] changedUids, int userId) {
+ private void generateServicesMap(@Nullable int[] changedUids, int userId) {
if (DEBUG) {
Slog.d(TAG, "generateServicesMap() for " + userId + ", changed UIDs = "
+ Arrays.toString(changedUids));
}
- final ArrayList<ServiceInfo<V>> serviceInfos = new ArrayList<>();
- final List<ResolveInfo> resolveInfos = queryIntentServices(userId);
- for (ResolveInfo resolveInfo : resolveInfos) {
- try {
- ServiceInfo<V> info = parseServiceInfo(resolveInfo);
- if (info == null) {
- Log.w(TAG, "Unable to load service info " + resolveInfo.toString());
- continue;
- }
- serviceInfos.add(info);
- } catch (XmlPullParserException|IOException e) {
- Log.w(TAG, "Unable to load service info " + resolveInfo.toString(), e);
- }
- }
-
synchronized (mServicesLock) {
final UserServices<V> user = findOrCreateUserLocked(userId);
- final boolean firstScan = user.services == null;
- if (firstScan) {
+ final boolean cacheInvalid = user.services == null;
+ if (cacheInvalid) {
user.services = Maps.newHashMap();
}
+ final ArrayList<ServiceInfo<V>> serviceInfos = new ArrayList<>();
+ final List<ResolveInfo> resolveInfos = queryIntentServices(userId);
+
+ for (ResolveInfo resolveInfo : resolveInfos) {
+ try {
+ // when changedUids == null, we want to do a rescan of everything, this means
+ // it's the initial scan, and containsUid will trivially return true
+ // when changedUids != null, we got here because a package changed, but
+ // invalidateCache could have been called (thus user.services == null), and we
+ // should query from PackageManager again
+ if (!cacheInvalid
+ && !containsUid(
+ changedUids, resolveInfo.serviceInfo.applicationInfo.uid)) {
+ if (DEBUG) {
+ Slog.d(TAG, "Skipping parseServiceInfo for " + resolveInfo);
+ }
+ continue;
+ }
+ ServiceInfo<V> info = parseServiceInfo(resolveInfo);
+ if (info == null) {
+ Log.w(TAG, "Unable to load service info " + resolveInfo.toString());
+ continue;
+ }
+ serviceInfos.add(info);
+ } catch (XmlPullParserException | IOException e) {
+ Log.w(TAG, "Unable to load service info " + resolveInfo.toString(), e);
+ }
+ }
+
StringBuilder changes = new StringBuilder();
boolean changed = false;
for (ServiceInfo<V> info : serviceInfos) {
@@ -513,7 +532,7 @@ public abstract class RegisteredServicesCache<V> {
changed = true;
user.services.put(info.type, info);
user.persistentServices.put(info.type, info.uid);
- if (!(user.mPersistentServicesFileDidNotExist && firstScan)) {
+ if (!(user.mPersistentServicesFileDidNotExist && cacheInvalid)) {
notifyListener(info.type, userId, false /* removed */);
}
} else if (previousUid == info.uid) {