summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/pm/ComponentResolver.java232
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java8
2 files changed, 184 insertions, 56 deletions
diff --git a/services/core/java/com/android/server/pm/ComponentResolver.java b/services/core/java/com/android/server/pm/ComponentResolver.java
index 1d556fec31ea..dde9f822ac76 100644
--- a/services/core/java/com/android/server/pm/ComponentResolver.java
+++ b/services/core/java/com/android/server/pm/ComponentResolver.java
@@ -59,6 +59,9 @@ import com.android.server.IntentResolver;
import com.android.server.pm.parsing.PackageInfoUtils;
import com.android.server.pm.parsing.PackageInfoUtils.CachedApplicationInfoGenerator;
import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.utils.Snappable;
+import com.android.server.utils.SnapshotCache;
+import com.android.server.utils.WatchableImpl;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -72,12 +75,19 @@ import java.util.Set;
import java.util.function.Function;
/** Resolves all Android component types [activities, services, providers and receivers]. */
-public class ComponentResolver {
+public class ComponentResolver
+ extends WatchableImpl
+ implements Snappable {
private static final boolean DEBUG = false;
private static final String TAG = "PackageManager";
private static final boolean DEBUG_FILTERS = false;
private static final boolean DEBUG_SHOW_INFO = false;
+ // Convenience function to report that this object has changed.
+ private void onChanged() {
+ dispatchChange(this);
+ }
+
/**
* The set of all protected actions [i.e. those actions for which a high priority
* intent filter is disallowed].
@@ -158,27 +168,27 @@ public class ComponentResolver {
* would be able to hold its lock while checking the package setting state.</li>
* </ol>
*/
- private final Object mLock;
+ private final PackageManagerTracedLock mLock;
/** All available activities, for your resolving pleasure. */
@GuardedBy("mLock")
- private final ActivityIntentResolver mActivities = new ActivityIntentResolver();
+ private final ActivityIntentResolver mActivities;
/** All available providers, for your resolving pleasure. */
@GuardedBy("mLock")
- private final ProviderIntentResolver mProviders = new ProviderIntentResolver();
+ private final ProviderIntentResolver mProviders;
/** All available receivers, for your resolving pleasure. */
@GuardedBy("mLock")
- private final ActivityIntentResolver mReceivers = new ReceiverIntentResolver();
+ private final ReceiverIntentResolver mReceivers;
/** All available services, for your resolving pleasure. */
@GuardedBy("mLock")
- private final ServiceIntentResolver mServices = new ServiceIntentResolver();
+ private final ServiceIntentResolver mServices;
/** Mapping from provider authority [first directory in content URI codePath) to provider. */
@GuardedBy("mLock")
- private final ArrayMap<String, ParsedProvider> mProvidersByAuthority = new ArrayMap<>();
+ private final ArrayMap<String, ParsedProvider> mProvidersByAuthority;
/** Whether or not processing protected filters should be deferred. */
private boolean mDeferProtectedFilters = true;
@@ -200,12 +210,57 @@ public class ComponentResolver {
ComponentResolver(UserManagerService userManager,
PackageManagerInternal packageManagerInternal,
- Object lock) {
+ PackageManagerTracedLock lock) {
sPackageManagerInternal = packageManagerInternal;
sUserManager = userManager;
mLock = lock;
+
+ mActivities = new ActivityIntentResolver();
+ mProviders = new ProviderIntentResolver();
+ mReceivers = new ReceiverIntentResolver();
+ mServices = new ServiceIntentResolver();
+ mProvidersByAuthority = new ArrayMap<>();
+ mDeferProtectedFilters = true;
+
+ mSnapshot = new SnapshotCache<ComponentResolver>(this, this) {
+ @Override
+ public ComponentResolver createSnapshot() {
+ return new ComponentResolver(mSource);
+ }};
+ }
+
+ // Copy constructor used in creating snapshots.
+ private ComponentResolver(ComponentResolver orig) {
+ // Do not set the static variables that are set in the default constructor. Do
+ // create a new object for the lock. The snapshot is read-only, so a lock is not
+ // strictly required. However, the current code is simpler if the lock exists,
+ // but does not contend with any outside class.
+ // TODO: make the snapshot lock-free
+ mLock = new PackageManagerTracedLock();
+
+ mActivities = new ActivityIntentResolver(orig.mActivities);
+ mProviders = new ProviderIntentResolver(orig.mProviders);
+ mReceivers = new ReceiverIntentResolver(orig.mReceivers);
+ mServices = new ServiceIntentResolver(orig.mServices);
+ mProvidersByAuthority = new ArrayMap<>(orig.mProvidersByAuthority);
+ mDeferProtectedFilters = orig.mDeferProtectedFilters;
+ mProtectedFilters = (mProtectedFilters == null)
+ ? null
+ : new ArrayList<>(orig.mProtectedFilters);
+
+ mSnapshot = null;
}
+ final SnapshotCache<ComponentResolver> mSnapshot;
+
+ /**
+ * Create a snapshot.
+ */
+ public ComponentResolver snapshot() {
+ return mSnapshot.snapshot();
+ }
+
+
/** Returns the given activity */
@Nullable
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
@@ -474,6 +529,7 @@ public class ComponentResolver {
addReceiversLocked(pkg, chatty);
addProvidersLocked(pkg, chatty);
addServicesLocked(pkg, chatty);
+ onChanged();
}
// expect single setupwizard package
final String setupWizardPackage = ArrayUtils.firstOrNull(
@@ -489,6 +545,7 @@ public class ComponentResolver {
final List<ParsedActivity> systemActivities =
disabledPkg != null ? disabledPkg.getActivities() : null;
adjustPriority(systemActivities, pair.first, pair.second, setupWizardPackage);
+ onChanged();
}
}
@@ -496,6 +553,7 @@ public class ComponentResolver {
void removeAllComponents(AndroidPackage pkg, boolean chatty) {
synchronized (mLock) {
removeAllComponentsLocked(pkg, chatty);
+ onChanged();
}
}
@@ -504,51 +562,54 @@ public class ComponentResolver {
* all of the filters defined on the /system partition and know the special components.
*/
void fixProtectedFilterPriorities() {
- if (!mDeferProtectedFilters) {
- return;
- }
- mDeferProtectedFilters = false;
+ synchronized (mLock) {
+ if (!mDeferProtectedFilters) {
+ return;
+ }
+ mDeferProtectedFilters = false;
- if (mProtectedFilters == null || mProtectedFilters.size() == 0) {
- return;
- }
- final List<Pair<ParsedMainComponent, ParsedIntentInfo>> protectedFilters =
- mProtectedFilters;
- mProtectedFilters = null;
+ if (mProtectedFilters == null || mProtectedFilters.size() == 0) {
+ return;
+ }
+ final List<Pair<ParsedMainComponent, ParsedIntentInfo>> protectedFilters =
+ mProtectedFilters;
+ mProtectedFilters = null;
- // expect single setupwizard package
- final String setupWizardPackage = ArrayUtils.firstOrNull(
+ // expect single setupwizard package
+ final String setupWizardPackage = ArrayUtils.firstOrNull(
sPackageManagerInternal.getKnownPackageNames(
- PACKAGE_SETUP_WIZARD, UserHandle.USER_SYSTEM));
-
- if (DEBUG_FILTERS && setupWizardPackage == null) {
- Slog.i(TAG, "No setup wizard;"
- + " All protected intents capped to priority 0");
- }
- for (int i = protectedFilters.size() - 1; i >= 0; --i) {
- final Pair<ParsedMainComponent, ParsedIntentInfo> pair = protectedFilters.get(i);
- ParsedMainComponent component = pair.first;
- ParsedIntentInfo filter = pair.second;
- String packageName = component.getPackageName();
- String className = component.getClassName();
- if (packageName.equals(setupWizardPackage)) {
+ PACKAGE_SETUP_WIZARD, UserHandle.USER_SYSTEM));
+
+ if (DEBUG_FILTERS && setupWizardPackage == null) {
+ Slog.i(TAG, "No setup wizard;"
+ + " All protected intents capped to priority 0");
+ }
+ for (int i = protectedFilters.size() - 1; i >= 0; --i) {
+ final Pair<ParsedMainComponent, ParsedIntentInfo> pair = protectedFilters.get(i);
+ ParsedMainComponent component = pair.first;
+ ParsedIntentInfo filter = pair.second;
+ String packageName = component.getPackageName();
+ String className = component.getClassName();
+ if (packageName.equals(setupWizardPackage)) {
+ if (DEBUG_FILTERS) {
+ Slog.i(TAG, "Found setup wizard;"
+ + " allow priority " + filter.getPriority() + ";"
+ + " package: " + packageName
+ + " activity: " + className
+ + " priority: " + filter.getPriority());
+ }
+ // skip setup wizard; allow it to keep the high priority filter
+ continue;
+ }
if (DEBUG_FILTERS) {
- Slog.i(TAG, "Found setup wizard;"
- + " allow priority " + filter.getPriority() + ";"
+ Slog.i(TAG, "Protected action; cap priority to 0;"
+ " package: " + packageName
+ " activity: " + className
- + " priority: " + filter.getPriority());
+ + " origPrio: " + filter.getPriority());
}
- // skip setup wizard; allow it to keep the high priority filter
- continue;
- }
- if (DEBUG_FILTERS) {
- Slog.i(TAG, "Protected action; cap priority to 0;"
- + " package: " + packageName
- + " activity: " + className
- + " origPrio: " + filter.getPriority());
+ filter.setPriority(0);
}
- filter.setPriority(0);
+ onChanged();
}
}
@@ -1181,9 +1242,20 @@ public class ComponentResolver {
private abstract static class MimeGroupsAwareIntentResolver<F extends Pair<?
extends ParsedComponent, ParsedIntentInfo>, R>
extends IntentResolver<F, R> {
- private ArrayMap<String, F[]> mMimeGroupToFilter = new ArrayMap<>();
+ private final ArrayMap<String, F[]> mMimeGroupToFilter = new ArrayMap<>();
private boolean mIsUpdatingMimeGroup = false;
+ // Default constructor
+ MimeGroupsAwareIntentResolver() {
+ }
+
+ // Copy constructor used in creating snapshots
+ MimeGroupsAwareIntentResolver(MimeGroupsAwareIntentResolver<F, R> orig) {
+ copyFrom(orig);
+ copyInto(mMimeGroupToFilter, orig.mMimeGroupToFilter);
+ mIsUpdatingMimeGroup = orig.mIsUpdatingMimeGroup;
+ }
+
@Override
public void addFilter(F f) {
IntentFilter intentFilter = getIntentFilter(f);
@@ -1282,6 +1354,17 @@ public class ComponentResolver {
private static class ActivityIntentResolver
extends MimeGroupsAwareIntentResolver<Pair<ParsedActivity, ParsedIntentInfo>, ResolveInfo> {
+ // Default constructor
+ ActivityIntentResolver() {
+ }
+
+ // Copy constructor used in creating snapshots
+ ActivityIntentResolver(ActivityIntentResolver orig) {
+ super(orig);
+ mActivities.putAll(orig.mActivities);
+ mFlags = orig.mFlags;
+ }
+
@Override
public List<ResolveInfo> queryIntent(Intent intent, String resolvedType,
boolean defaultOnly, int userId) {
@@ -1330,7 +1413,7 @@ public class ComponentResolver {
return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut, userId);
}
- private void addActivity(ParsedActivity a, String type,
+ protected void addActivity(ParsedActivity a, String type,
List<Pair<ParsedActivity, ParsedIntentInfo>> newIntents) {
mActivities.put(a.getComponentName(), a);
if (DEBUG_SHOW_INFO) {
@@ -1354,7 +1437,7 @@ public class ComponentResolver {
}
}
- private void removeActivity(ParsedActivity a, String type) {
+ protected void removeActivity(ParsedActivity a, String type) {
mActivities.remove(a.getComponentName());
if (DEBUG_SHOW_INFO) {
Log.v(TAG, " " + type + ":");
@@ -1567,8 +1650,11 @@ public class ComponentResolver {
return pkg.getActivities();
}
- // Keys are String (activity class name), values are Activity.
- private final ArrayMap<ComponentName, ParsedActivity> mActivities =
+ // Keys are String (activity class name), values are Activity. This attribute is
+ // protected because it is accessed directly from ComponentResolver. That works
+ // even if the attribute is private, but fails for subclasses of
+ // ActivityIntentResolver.
+ protected final ArrayMap<ComponentName, ParsedActivity> mActivities =
new ArrayMap<>();
private int mFlags;
}
@@ -1576,6 +1662,15 @@ public class ComponentResolver {
// Both receivers and activities share a class, but point to different get methods
private static final class ReceiverIntentResolver extends ActivityIntentResolver {
+ // Default constructor
+ ReceiverIntentResolver() {
+ }
+
+ // Copy constructor used in creating snapshots
+ ReceiverIntentResolver(ReceiverIntentResolver orig) {
+ super(orig);
+ }
+
@Override
protected List<ParsedActivity> getResolveList(AndroidPackage pkg) {
return pkg.getReceivers();
@@ -1584,6 +1679,17 @@ public class ComponentResolver {
private static final class ProviderIntentResolver
extends MimeGroupsAwareIntentResolver<Pair<ParsedProvider, ParsedIntentInfo>, ResolveInfo> {
+ // Default constructor
+ ProviderIntentResolver() {
+ }
+
+ // Copy constructor used in creating snapshots
+ ProviderIntentResolver(ProviderIntentResolver orig) {
+ super(orig);
+ mProviders.putAll(orig.mProviders);
+ mFlags = orig.mFlags;
+ }
+
@Override
public List<ResolveInfo> queryIntent(Intent intent, String resolvedType,
boolean defaultOnly, int userId) {
@@ -1829,6 +1935,17 @@ public class ComponentResolver {
private static final class ServiceIntentResolver
extends MimeGroupsAwareIntentResolver<Pair<ParsedService, ParsedIntentInfo>, ResolveInfo> {
+ // Default constructor
+ ServiceIntentResolver() {
+ }
+
+ // Copy constructor used in creating snapshots
+ ServiceIntentResolver(ServiceIntentResolver orig) {
+ copyFrom(orig);
+ mServices.putAll(orig.mServices);
+ mFlags = orig.mFlags;
+ }
+
@Override
public List<ResolveInfo> queryIntent(Intent intent, String resolvedType,
boolean defaultOnly, int userId) {
@@ -2213,11 +2330,16 @@ public class ComponentResolver {
* @return true if any intent filters were changed due to this update
*/
boolean updateMimeGroup(String packageName, String group) {
- boolean hasChanges = mActivities.updateMimeGroup(packageName, group);
- hasChanges |= mProviders.updateMimeGroup(packageName, group);
- hasChanges |= mReceivers.updateMimeGroup(packageName, group);
- hasChanges |= mServices.updateMimeGroup(packageName, group);
-
+ boolean hasChanges = false;
+ synchronized (mLock) {
+ hasChanges |= mActivities.updateMimeGroup(packageName, group);
+ hasChanges |= mProviders.updateMimeGroup(packageName, group);
+ hasChanges |= mReceivers.updateMimeGroup(packageName, group);
+ hasChanges |= mServices.updateMimeGroup(packageName, group);
+ if (hasChanges) {
+ onChanged();
+ }
+ }
return hasChanges;
}
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 95a2ae6c13f5..2b2205abbe74 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -1481,7 +1481,9 @@ public class PackageManagerService extends IPackageManager.Stub
// Internal interface for permission manager
private final PermissionManagerServiceInternal mPermissionManager;
+ @Watched
private final ComponentResolver mComponentResolver;
+
// List of packages names to keep cached, even if they are uninstalled for all users
private List<String> mKeepUninstalledPackages;
@@ -1854,6 +1856,7 @@ public class PackageManagerService extends IPackageManager.Stub
public final ApplicationInfo androidApplication;
public final String appPredictionServicePackage;
public final AppsFilter appsFilter;
+ public final ComponentResolver componentResolver;
public final PackageManagerService service;
Snapshot(int type) {
@@ -1879,6 +1882,7 @@ public class PackageManagerService extends IPackageManager.Stub
: new ApplicationInfo(mAndroidApplication);
appPredictionServicePackage = mAppPredictionServicePackage;
appsFilter = mAppsFilter.snapshot();
+ componentResolver = mComponentResolver.snapshot();
} else if (type == Snapshot.LIVE) {
settings = mSettings;
isolatedOwners = mIsolatedOwners;
@@ -1895,6 +1899,7 @@ public class PackageManagerService extends IPackageManager.Stub
androidApplication = mAndroidApplication;
appPredictionServicePackage = mAppPredictionServicePackage;
appsFilter = mAppsFilter;
+ componentResolver = mComponentResolver;
} else {
throw new IllegalArgumentException();
}
@@ -2142,6 +2147,7 @@ public class PackageManagerService extends IPackageManager.Stub
mInstantAppRegistry = args.instantAppRegistry;
mLocalAndroidApplication = args.androidApplication;
mAppsFilter = args.appsFilter;
+ mComponentResolver = args.componentResolver;
mAppPredictionServicePackage = args.appPredictionServicePackage;
@@ -2152,7 +2158,6 @@ public class PackageManagerService extends IPackageManager.Stub
mContext = args.service.mContext;
mInjector = args.service.mInjector;
mApexManager = args.service.mApexManager;
- mComponentResolver = args.service.mComponentResolver;
mInstantAppResolverConnection = args.service.mInstantAppResolverConnection;
mDefaultAppProvider = args.service.mDefaultAppProvider;
mDomainVerificationManager = args.service.mDomainVerificationManager;
@@ -6159,6 +6164,7 @@ public class PackageManagerService extends IPackageManager.Stub
mInstantAppRegistry.registerObserver(mWatcher);
mSettings.registerObserver(mWatcher);
mIsolatedOwners.registerObserver(mWatcher);
+ mComponentResolver.registerObserver(mWatcher);
// If neither "build" attribute is true then this may be a mockito test, and verification
// can fail as a false positive.
Watchable.verifyWatchedAttributes(this, mWatcher, !(mIsEngBuild || mIsUserDebugBuild));