Fix ComponentResolver Computer consistency

Migrates ComponentResolver and ResolveIntentHelper away from calling
PM directly in favor of using a consistent Computer snapshot. This
saves on snapshot rebuild and ensures data consistency within a single
method call.

Bug: 215403184

Change-Id: Id017db704493f38d94fd498f77d2264fe008ef45
diff --git a/services/core/java/android/content/pm/PackageManagerInternal.java b/services/core/java/android/content/pm/PackageManagerInternal.java
index e335a16..09ef03c 100644
--- a/services/core/java/android/content/pm/PackageManagerInternal.java
+++ b/services/core/java/android/content/pm/PackageManagerInternal.java
@@ -52,6 +52,7 @@
 import com.android.server.pm.pkg.SharedUserApi;
 import com.android.server.pm.pkg.component.ParsedMainComponent;
 import com.android.server.pm.pkg.mutate.PackageStateMutator;
+import com.android.server.pm.snapshot.PackageDataSnapshot;
 
 import java.io.IOException;
 import java.lang.annotation.Retention;
@@ -718,7 +719,8 @@
     /**
      * Returns a package object for the disabled system package name.
      */
-    public abstract @Nullable PackageSetting getDisabledSystemPackage(@NonNull String packageName);
+    public abstract @Nullable PackageStateInternal getDisabledSystemPackage(
+            @NonNull String packageName);
 
     /**
      * Returns the package name for the disabled system package.
@@ -1334,4 +1336,12 @@
     public abstract PackageStateMutator.Result commitPackageStateMutation(
             @Nullable PackageStateMutator.InitialState state,
             @NonNull Consumer<PackageStateMutator> consumer);
+
+    /**
+     * @return package data snapshot for use with other PackageManager infrastructure. This should
+     * only be used as a parameter passed to another PM related class. Do not call methods on this
+     * directly.
+     */
+    @NonNull
+    public abstract PackageDataSnapshot snapshot();
 }
diff --git a/services/core/java/com/android/server/IntentResolver.java b/services/core/java/com/android/server/IntentResolver.java
index aae1cc0..c375c73 100644
--- a/services/core/java/com/android/server/IntentResolver.java
+++ b/services/core/java/com/android/server/IntentResolver.java
@@ -17,6 +17,8 @@
 package com.android.server;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.UserIdInt;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.net.Uri;
@@ -32,6 +34,9 @@
 import android.util.proto.ProtoOutputStream;
 
 import com.android.internal.util.FastPrintWriter;
+import com.android.server.pm.Computer;
+import com.android.server.pm.pkg.PackageStateInternal;
+import com.android.server.pm.snapshot.PackageDataSnapshot;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -51,7 +56,7 @@
     final private static boolean localLOGV = DEBUG || false;
     final private static boolean localVerificationLOGV = DEBUG || false;
 
-    public void addFilter(F f) {
+    public void addFilter(@Nullable PackageDataSnapshot snapshot, F f) {
         IntentFilter intentFilter = getIntentFilter(f);
         if (localLOGV) {
             Slog.v(TAG, "Adding filter: " + f);
@@ -420,8 +425,9 @@
         return Collections.unmodifiableSet(mFilters);
     }
 
-    public List<R> queryIntentFromList(Intent intent, String resolvedType, boolean defaultOnly,
-            ArrayList<F[]> listCut, int userId) {
+    public List<R> queryIntentFromList(@NonNull Computer computer, Intent intent,
+            String resolvedType, boolean defaultOnly, ArrayList<F[]> listCut, int userId,
+            long customFlags) {
         ArrayList<R> resultList = new ArrayList<R>();
 
         final boolean debug = localLOGV ||
@@ -431,16 +437,21 @@
         final String scheme = intent.getScheme();
         int N = listCut.size();
         for (int i = 0; i < N; ++i) {
-            buildResolveList(intent, categories, debug, defaultOnly, resolvedType, scheme,
-                    listCut.get(i), resultList, userId);
+            buildResolveList(computer, intent, categories, debug, defaultOnly, resolvedType, scheme,
+                    listCut.get(i), resultList, userId, customFlags);
         }
         filterResults(resultList);
         sortResults(resultList);
         return resultList;
     }
 
-    public List<R> queryIntent(Intent intent, String resolvedType, boolean defaultOnly,
-            int userId) {
+    public List<R> queryIntent(@NonNull PackageDataSnapshot snapshot, Intent intent,
+            String resolvedType, boolean defaultOnly, @UserIdInt int userId) {
+        return queryIntent(snapshot, intent, resolvedType, defaultOnly, userId, 0);
+    }
+
+    protected final List<R> queryIntent(@NonNull PackageDataSnapshot snapshot, Intent intent,
+            String resolvedType, boolean defaultOnly, @UserIdInt int userId, long customFlags) {
         String scheme = intent.getScheme();
 
         ArrayList<R> finalList = new ArrayList<R>();
@@ -512,21 +523,22 @@
         }
 
         FastImmutableArraySet<String> categories = getFastIntentCategories(intent);
+        Computer computer = (Computer) snapshot;
         if (firstTypeCut != null) {
-            buildResolveList(intent, categories, debug, defaultOnly, resolvedType,
-                    scheme, firstTypeCut, finalList, userId);
+            buildResolveList(computer, intent, categories, debug, defaultOnly, resolvedType,
+                    scheme, firstTypeCut, finalList, userId, customFlags);
         }
         if (secondTypeCut != null) {
-            buildResolveList(intent, categories, debug, defaultOnly, resolvedType,
-                    scheme, secondTypeCut, finalList, userId);
+            buildResolveList(computer, intent, categories, debug, defaultOnly, resolvedType,
+                    scheme, secondTypeCut, finalList, userId, customFlags);
         }
         if (thirdTypeCut != null) {
-            buildResolveList(intent, categories, debug, defaultOnly, resolvedType,
-                    scheme, thirdTypeCut, finalList, userId);
+            buildResolveList(computer, intent, categories, debug, defaultOnly, resolvedType,
+                    scheme, thirdTypeCut, finalList, userId, customFlags);
         }
         if (schemeCut != null) {
-            buildResolveList(intent, categories, debug, defaultOnly, resolvedType,
-                    scheme, schemeCut, finalList, userId);
+            buildResolveList(computer, intent, categories, debug, defaultOnly, resolvedType,
+                    scheme, schemeCut, finalList, userId, customFlags);
         }
         filterResults(finalList);
         sortResults(finalList);
@@ -554,7 +566,7 @@
      * "stopped", that is whether it should not be included in the result
      * if the intent requests to excluded stopped objects.
      */
-    protected boolean isFilterStopped(F filter, int userId) {
+    protected boolean isFilterStopped(PackageStateInternal packageState, @UserIdInt int userId) {
         return false;
     }
 
@@ -584,7 +596,8 @@
     protected abstract F[] newArray(int size);
 
     @SuppressWarnings("unchecked")
-    protected R newResult(F filter, int match, int userId) {
+    protected R newResult(@NonNull Computer computer, F filter, int match, int userId,
+            long customFlags) {
         return (R)filter;
     }
 
@@ -764,9 +777,10 @@
         return new FastImmutableArraySet<String>(categories.toArray(new String[categories.size()]));
     }
 
-    private void buildResolveList(Intent intent, FastImmutableArraySet<String> categories,
-            boolean debug, boolean defaultOnly, String resolvedType, String scheme,
-            F[] src, List<R> dest, int userId) {
+    private void buildResolveList(@NonNull Computer computer, Intent intent,
+            FastImmutableArraySet<String> categories, boolean debug, boolean defaultOnly,
+            String resolvedType, String scheme, F[] src, List<R> dest, int userId,
+            long customFlags) {
         final String action = intent.getAction();
         final Uri data = intent.getData();
         final String packageName = intent.getPackage();
@@ -791,7 +805,8 @@
             int match;
             if (debug) Slog.v(TAG, "Matching against filter " + filter);
 
-            if (excludingStopped && isFilterStopped(filter, userId)) {
+            if (excludingStopped && isFilterStopped(computer.getPackageStateInternal(packageName),
+                    userId)) {
                 if (debug) {
                     Slog.v(TAG, "  Filter's target is stopped; skipping");
                 }
@@ -833,7 +848,7 @@
                         Integer.toHexString(match) + " hasDefault="
                         + intentFilter.hasCategory(Intent.CATEGORY_DEFAULT));
                 if (!defaultOnly || intentFilter.hasCategory(Intent.CATEGORY_DEFAULT)) {
-                    final R oneResult = newResult(filter, match, userId);
+                    final R oneResult = newResult(computer, filter, match, userId, customFlags);
                     if (debug) Slog.v(TAG, "    Created result: " + oneResult);
                     if (oneResult != null) {
                         dest.add(oneResult);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 6c39a11..d21203f 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -395,12 +395,14 @@
 import com.android.server.graphics.fonts.FontManagerInternal;
 import com.android.server.job.JobSchedulerInternal;
 import com.android.server.os.NativeTombstoneManager;
+import com.android.server.pm.Computer;
 import com.android.server.pm.Installer;
 import com.android.server.pm.UserManagerInternal;
 import com.android.server.pm.parsing.pkg.AndroidPackage;
 import com.android.server.pm.permission.PermissionManagerServiceInternal;
 import com.android.server.pm.pkg.SELinuxUtil;
 import com.android.server.pm.pkg.parsing.ParsingPackageUtils;
+import com.android.server.pm.snapshot.PackageDataSnapshot;
 import com.android.server.uri.GrantUri;
 import com.android.server.uri.NeededUriGrants;
 import com.android.server.uri.UriGrantsManagerInternal;
@@ -1105,10 +1107,11 @@
         }
 
         @Override
-        protected BroadcastFilter newResult(BroadcastFilter filter, int match, int userId) {
+        protected BroadcastFilter newResult(@NonNull Computer computer, BroadcastFilter filter,
+                int match, int userId, long customFlags) {
             if (userId == UserHandle.USER_ALL || filter.owningUserId == UserHandle.USER_ALL
                     || userId == filter.owningUserId) {
-                return super.newResult(filter, match, userId);
+                return super.newResult(computer, filter, match, userId, customFlags);
             }
             return null;
         }
@@ -13039,7 +13042,7 @@
                 if (!bf.debugCheck()) {
                     Slog.w(TAG, "==> For Dynamic broadcast");
                 }
-                mReceiverResolver.addFilter(bf);
+                mReceiverResolver.addFilter(getPackageManagerInternal().snapshot(), bf);
             }
 
             // Enqueue broadcasts for all existing stickies that match
@@ -13861,6 +13864,7 @@
                     intent, resolvedType, callingUid, users, broadcastAllowList);
         }
         if (intent.getComponent() == null) {
+            final PackageDataSnapshot snapshot = getPackageManagerInternal().snapshot();
             if (userId == UserHandle.USER_ALL && callingUid == SHELL_UID) {
                 // Query one target user at a time, excluding shell-restricted users
                 for (int i = 0; i < users.length; i++) {
@@ -13869,7 +13873,7 @@
                         continue;
                     }
                     List<BroadcastFilter> registeredReceiversForUser =
-                            mReceiverResolver.queryIntent(intent,
+                            mReceiverResolver.queryIntent(snapshot, intent,
                                     resolvedType, false /*defaultOnly*/, users[i]);
                     if (registeredReceivers == null) {
                         registeredReceivers = registeredReceiversForUser;
@@ -13878,7 +13882,7 @@
                     }
                 }
             } else {
-                registeredReceivers = mReceiverResolver.queryIntent(intent,
+                registeredReceivers = mReceiverResolver.queryIntent(snapshot, intent,
                         resolvedType, false /*defaultOnly*/, userId);
             }
         }
diff --git a/services/core/java/com/android/server/firewall/IntentFirewall.java b/services/core/java/com/android/server/firewall/IntentFirewall.java
index 1139d28..bb8a744 100644
--- a/services/core/java/com/android/server/firewall/IntentFirewall.java
+++ b/services/core/java/com/android/server/firewall/IntentFirewall.java
@@ -24,6 +24,7 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal;
 import android.os.Environment;
 import android.os.FileObserver;
 import android.os.Handler;
@@ -38,6 +39,8 @@
 import com.android.internal.util.XmlUtils;
 import com.android.server.EventLogTags;
 import com.android.server.IntentResolver;
+import com.android.server.LocalServices;
+import com.android.server.pm.Computer;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -75,6 +78,9 @@
 
     private final RuleObserver mObserver;
 
+    @NonNull
+    private PackageManagerInternal mPackageManager;
+
     private FirewallIntentResolver mActivityResolver = new FirewallIntentResolver();
     private FirewallIntentResolver mBroadcastResolver = new FirewallIntentResolver();
     private FirewallIntentResolver mServiceResolver = new FirewallIntentResolver();
@@ -123,6 +129,13 @@
         mObserver.startWatching();
     }
 
+    private PackageManagerInternal getPackageManager() {
+        if (mPackageManager == null) {
+            mPackageManager = LocalServices.getService(PackageManagerInternal.class);
+        }
+        return mPackageManager;
+    }
+
     /**
      * This is called from ActivityManager to check if a start activity intent should be allowed.
      * It is assumed the caller is already holding the global ActivityManagerService lock.
@@ -154,7 +167,8 @@
         // For the first pass, find all the rules that have at least one intent-filter or
         // component-filter that matches this intent
         List<Rule> candidateRules;
-        candidateRules = resolver.queryIntent(intent, resolvedType, false /*defaultOnly*/, 0);
+        candidateRules = resolver.queryIntent(getPackageManager().snapshot(), intent, resolvedType,
+                false /*defaultOnly*/, 0);
         if (candidateRules == null) {
             candidateRules = new ArrayList<Rule>();
         }
@@ -375,7 +389,7 @@
             for (int ruleIndex=0; ruleIndex<rules.size(); ruleIndex++) {
                 Rule rule = rules.get(ruleIndex);
                 for (int i=0; i<rule.getIntentFilterCount(); i++) {
-                    resolver.addFilter(rule.getIntentFilter(i));
+                    resolver.addFilter(null, rule.getIntentFilter(i));
                 }
                 for (int i=0; i<rule.getComponentFilterCount(); i++) {
                     resolver.addComponentFilter(rule.getComponentFilter(i), rule);
@@ -512,7 +526,8 @@
         }
 
         @Override
-        protected Rule newResult(FirewallIntentFilter filter, int match, int userId) {
+        protected Rule newResult(@NonNull Computer computer, FirewallIntentFilter filter,
+                int match, int userId, long customFlags) {
             return filter.rule;
         }
 
diff --git a/services/core/java/com/android/server/pm/Computer.java b/services/core/java/com/android/server/pm/Computer.java
index 0d9ccd2..2a4882a 100644
--- a/services/core/java/com/android/server/pm/Computer.java
+++ b/services/core/java/com/android/server/pm/Computer.java
@@ -51,6 +51,8 @@
 import com.android.server.pm.pkg.PackageState;
 import com.android.server.pm.pkg.PackageStateInternal;
 import com.android.server.pm.pkg.SharedUserApi;
+import com.android.server.pm.resolution.ComponentResolverApi;
+import com.android.server.pm.snapshot.PackageDataSnapshot;
 import com.android.server.utils.WatchedArrayMap;
 import com.android.server.utils.WatchedLongSparseArray;
 
@@ -98,7 +100,7 @@
  * {@link ComputerEngine} and {@link ComputerLocked}.
  */
 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
-public interface Computer {
+public interface Computer extends PackageDataSnapshot {
 
     /**
      * Every method must be annotated.
@@ -178,6 +180,18 @@
     @Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED)
     List<CrossProfileIntentFilter> getMatchingCrossProfileIntentFilters(Intent intent,
             String resolvedType, int userId);
+
+    /**
+     * Filters out ephemeral activities.
+     * <p>When resolving for an ephemeral app, only activities that 1) are defined in the
+     * ephemeral app or 2) marked with {@code visibleToEphemeral} are returned.
+     *
+     * @param resolveInfos The pre-filtered list of resolved activities
+     * @param ephemeralPkgName The ephemeral package name. If {@code null}, no filtering
+     *          is performed.
+     * @param intent
+     * @return A filtered list of resolved activities.
+     */
     @Computer.LiveImplementation(override = Computer.LiveImplementation.NOT_ALLOWED)
     List<ResolveInfo> applyPostResolutionFilter(@NonNull List<ResolveInfo> resolveInfos,
             String ephemeralPkgName, boolean allowDynamicSplits, int filterCallingUid,
@@ -648,4 +662,16 @@
     @Computer.LiveImplementation(override = LiveImplementation.MANDATORY)
     @NonNull
     ArraySet<PackageStateInternal> getSharedUserPackages(int sharedUserAppId);
+
+    @Computer.LiveImplementation(override = LiveImplementation.MANDATORY)
+    @NonNull
+    ComponentResolverApi getComponentResolver();
+
+    @Computer.LiveImplementation(override = LiveImplementation.MANDATORY)
+    @Nullable
+    PackageStateInternal getDisabledSystemPackage(@NonNull String packageName);
+
+    @Computer.LiveImplementation(override = LiveImplementation.MANDATORY)
+    @Nullable
+    ResolveInfo getInstantAppInstallerInfo();
 }
diff --git a/services/core/java/com/android/server/pm/ComputerEngine.java b/services/core/java/com/android/server/pm/ComputerEngine.java
index c437697..9e87898 100644
--- a/services/core/java/com/android/server/pm/ComputerEngine.java
+++ b/services/core/java/com/android/server/pm/ComputerEngine.java
@@ -49,7 +49,6 @@
 
 import static com.android.internal.app.IntentForwarderActivity.FORWARD_INTENT_TO_MANAGED_PROFILE;
 import static com.android.internal.app.IntentForwarderActivity.FORWARD_INTENT_TO_PARENT;
-import static com.android.server.pm.ComponentResolver.RESOLVE_PRIORITY_SORTER;
 import static com.android.server.pm.PackageManagerService.DEBUG_DOMAIN_VERIFICATION;
 import static com.android.server.pm.PackageManagerService.DEBUG_INSTALL;
 import static com.android.server.pm.PackageManagerService.DEBUG_INSTANT;
@@ -59,6 +58,7 @@
 import static com.android.server.pm.PackageManagerService.HIDE_EPHEMERAL_APIS;
 import static com.android.server.pm.PackageManagerService.TAG;
 import static com.android.server.pm.PackageManagerServiceUtils.compareSignatures;
+import static com.android.server.pm.resolution.ComponentResolver.RESOLVE_PRIORITY_SORTER;
 
 import android.Manifest;
 import android.annotation.NonNull;
@@ -143,6 +143,7 @@
 import com.android.server.pm.pkg.component.ParsedProvider;
 import com.android.server.pm.pkg.component.ParsedService;
 import com.android.server.pm.pkg.parsing.PackageInfoWithoutStateUtils;
+import com.android.server.pm.resolution.ComponentResolverApi;
 import com.android.server.pm.verify.domain.DomainVerificationManagerInternal;
 import com.android.server.pm.verify.domain.DomainVerificationUtils;
 import com.android.server.uri.UriGrantsManagerInternal;
@@ -362,7 +363,7 @@
     private final PermissionManagerServiceInternal mPermissionManager;
     private final ApexManager mApexManager;
     private final PackageManagerServiceInjector mInjector;
-    private final ComponentResolver mComponentResolver;
+    private final ComponentResolverApi mComponentResolver;
     private final InstantAppResolverConnection mInstantAppResolverConnection;
     private final DefaultAppProvider mDefaultAppProvider;
     private final DomainVerificationManagerInternal mDomainVerificationManager;
@@ -644,7 +645,7 @@
         // reader
         String pkgName = intent.getPackage();
         if (pkgName == null) {
-            final List<ResolveInfo> resolveInfos = mComponentResolver.queryServices(intent,
+            final List<ResolveInfo> resolveInfos = mComponentResolver.queryServices(this, intent,
                     resolvedType, flags, userId);
             if (resolveInfos == null) {
                 return Collections.emptyList();
@@ -654,7 +655,7 @@
         }
         final AndroidPackage pkg = mPackages.get(pkgName);
         if (pkg != null) {
-            final List<ResolveInfo> resolveInfos = mComponentResolver.queryServices(intent,
+            final List<ResolveInfo> resolveInfos = mComponentResolver.queryServices(this, intent,
                     resolvedType, flags, pkg.getServices(),
                     userId);
             if (resolveInfos == null) {
@@ -691,7 +692,7 @@
             }
 
             // Check for results in the current profile.
-            result = filterIfNotSystemUser(mComponentResolver.queryActivities(
+            result = filterIfNotSystemUser(mComponentResolver.queryActivities(this,
                     intent, resolvedType, flags, userId), userId);
             addInstant = isInstantAppResolutionAllowed(intent, result, userId,
                     false /*skipPackageCheck*/, flags);
@@ -753,7 +754,7 @@
             result = null;
             if (setting != null && setting.getAndroidPackage() != null && (resolveForStart
                     || !shouldFilterApplication(setting, filterCallingUid, userId))) {
-                result = filterIfNotSystemUser(mComponentResolver.queryActivities(
+                result = filterIfNotSystemUser(mComponentResolver.queryActivities(this,
                         intent, resolvedType, flags, setting.getAndroidPackage().getActivities(),
                         userId), userId);
             }
@@ -1181,7 +1182,7 @@
                 sourceUserId)) {
             return null;
         }
-        List<ResolveInfo> resultTargetUser = mComponentResolver.queryActivities(intent,
+        List<ResolveInfo> resultTargetUser = mComponentResolver.queryActivities(this, intent,
                 resolvedType, flags, parentUserId);
 
         if (resultTargetUser == null || resultTargetUser.isEmpty()) {
@@ -1232,7 +1233,7 @@
             Intent intent, String resolvedType, int userId) {
         CrossProfileIntentResolver resolver = mSettings.getCrossProfileIntentResolver(userId);
         if (resolver != null) {
-            return resolver.queryIntent(intent, resolvedType, false /*defaultOnly*/, userId);
+            return resolver.queryIntent(this, intent, resolvedType, false /*defaultOnly*/, userId);
         }
         return null;
     }
@@ -1447,7 +1448,7 @@
         ResolveInfo localInstantApp = null;
         boolean blockResolution = false;
         if (!alreadyResolvedLocally) {
-            final List<ResolveInfo> instantApps = mComponentResolver.queryActivities(
+            final List<ResolveInfo> instantApps = mComponentResolver.queryActivities(this,
                     intent,
                     resolvedType,
                     flags
@@ -1493,8 +1494,8 @@
                                 null /*callingFeatureId*/, isRequesterInstantApp, userId,
                                 null /*verificationBundle*/, resolveForStart,
                                 digest.getDigestPrefixSecure(), token);
-                auxiliaryResponse = InstantAppResolver.doInstantAppResolutionPhaseOne(
-                        mInstantAppResolverConnection, requestObject);
+                auxiliaryResponse = InstantAppResolver.doInstantAppResolutionPhaseOne(this,
+                        mUserManager, mInstantAppResolverConnection, requestObject);
                 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
             } else {
                 // we have an instant application locally, but, we can't admit that since
@@ -1830,7 +1831,7 @@
             return null;
         }
 
-        List<ResolveInfo> resultTargetUser = mComponentResolver.queryActivities(intent,
+        List<ResolveInfo> resultTargetUser = mComponentResolver.queryActivities(this, intent,
                 resolvedType, flags, targetUserId);
         if (CollectionUtils.isEmpty(resultTargetUser)) {
             return null;
@@ -2586,7 +2587,7 @@
                 mSettings.getPersistentPreferredActivities(userId);
         //TODO(b/158003772): Remove double query
         List<PersistentPreferredActivity> pprefs = ppir != null
-                ? ppir.queryIntent(intent, resolvedType,
+                ? ppir.queryIntent(this, intent, resolvedType,
                 (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0,
                 userId)
                 : new ArrayList<>();
@@ -3244,7 +3245,7 @@
         // Get the list of preferred activities that handle the intent
         if (DEBUG_PREFERRED || debug) Slog.v(TAG, "Looking for preferred activities...");
         List<PreferredActivity> prefs = pir != null
-                ? pir.queryIntent(intent, resolvedType,
+                ? pir.queryIntent(this, intent, resolvedType,
                 (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0,
                 userId)
                 : null;
@@ -3376,7 +3377,7 @@
                                         pa.mPref.mComponent,
                                         pa.mPref.mAlways);
                                 pir.removeFilter(pa);
-                                pir.addFilter(freshPa);
+                                pir.addFilter(this, freshPa);
                                 result.mChanged = true;
                             } else {
                                 if (DEBUG_PREFERRED) {
@@ -3399,7 +3400,7 @@
                                 PreferredActivity lastChosen = new PreferredActivity(
                                         pa, pa.mPref.mMatch, null, pa.mPref.mComponent,
                                         false);
-                                pir.addFilter(lastChosen);
+                                pir.addFilter(this, lastChosen);
                                 result.mChanged = true;
                             }
                             result.mPreferredResolveInfo = null;
@@ -3454,7 +3455,7 @@
             Slog.v(TAG, "Looking for persistent preferred activities...");
         }
         List<PersistentPreferredActivity> pprefs = ppir != null
-                ? ppir.queryIntent(intent, resolvedType,
+                ? ppir.queryIntent(this, intent, resolvedType,
                 (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0,
                 userId)
                 : null;
@@ -4661,7 +4662,8 @@
             int callingUid) {
         if (!mUserManager.exists(userId)) return null;
         flags = updateFlagsForComponent(flags, userId);
-        final ProviderInfo providerInfo = mComponentResolver.queryProvider(name, flags, userId);
+        final ProviderInfo providerInfo = mComponentResolver.queryProvider(this, name, flags,
+                userId);
         boolean checkedGrants = false;
         if (providerInfo != null) {
             // Looking for cross-user grants before enforcing the typical cross-users permissions
@@ -4739,7 +4741,7 @@
         final List<String> names = new ArrayList<>();
         final List<ProviderInfo> infos = new ArrayList<>();
         final int callingUserId = UserHandle.getCallingUserId();
-        mComponentResolver.querySyncProviders(names, infos, safeMode, callingUserId);
+        mComponentResolver.querySyncProviders(this, names, infos, safeMode, callingUserId);
         for (int i = infos.size() - 1; i >= 0; i--) {
             final ProviderInfo providerInfo = infos.get(i);
             final PackageStateInternal ps = mSettings.getPackage(providerInfo.packageName);
@@ -4771,8 +4773,8 @@
         if (!mUserManager.exists(userId)) return ParceledListSlice.emptyList();
         flags = updateFlagsForComponent(flags, userId);
         ArrayList<ProviderInfo> finalList = null;
-        final List<ProviderInfo> matchList =
-                mComponentResolver.queryProviders(processName, metaDataKey, uid, flags, userId);
+        final List<ProviderInfo> matchList = mComponentResolver.queryProviders(this, processName,
+                metaDataKey, uid, flags, userId);
         final int listSize = (matchList == null ? 0 : matchList.size());
         for (int i = 0; i < listSize; i++) {
             final ProviderInfo providerInfo = matchList.get(i);
@@ -5674,4 +5676,22 @@
     public ArraySet<PackageStateInternal> getSharedUserPackages(int sharedUserAppId) {
         return mSettings.getSharedUserPackages(sharedUserAppId);
     }
+
+    @NonNull
+    @Override
+    public ComponentResolverApi getComponentResolver() {
+        return mComponentResolver;
+    }
+
+    @Nullable
+    @Override
+    public PackageStateInternal getDisabledSystemPackage(@NonNull String packageName) {
+        return mSettings.getDisabledSystemPkg(packageName);
+    }
+
+    @Nullable
+    @Override
+    public ResolveInfo getInstantAppInstallerInfo() {
+        return mInstantAppInstallerInfo;
+    }
 }
diff --git a/services/core/java/com/android/server/pm/ComputerLocked.java b/services/core/java/com/android/server/pm/ComputerLocked.java
index 583348b..5d89c7d 100644
--- a/services/core/java/com/android/server/pm/ComputerLocked.java
+++ b/services/core/java/com/android/server/pm/ComputerLocked.java
@@ -48,6 +48,7 @@
 import com.android.server.pm.pkg.PackageState;
 import com.android.server.pm.pkg.PackageStateInternal;
 import com.android.server.pm.pkg.SharedUserApi;
+import com.android.server.pm.resolution.ComponentResolverApi;
 import com.android.server.utils.WatchedArrayMap;
 import com.android.server.utils.WatchedLongSparseArray;
 
@@ -868,4 +869,28 @@
             return super.getSharedUserPackages(sharedUserAppId);
         }
     }
+
+    @NonNull
+    @Override
+    public ComponentResolverApi getComponentResolver() {
+        synchronized (mLock) {
+            return super.getComponentResolver();
+        }
+    }
+
+    @Nullable
+    @Override
+    public PackageStateInternal getDisabledSystemPackage(@NonNull String packageName) {
+        synchronized (mLock) {
+            return super.getDisabledSystemPackage(packageName);
+        }
+    }
+
+    @Nullable
+    @Override
+    public ResolveInfo getInstantAppInstallerInfo() {
+        synchronized (mLock) {
+            return super.getInstantAppInstallerInfo();
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/pm/ComputerTracker.java b/services/core/java/com/android/server/pm/ComputerTracker.java
index 72e67da..216ad71 100644
--- a/services/core/java/com/android/server/pm/ComputerTracker.java
+++ b/services/core/java/com/android/server/pm/ComputerTracker.java
@@ -49,6 +49,7 @@
 import com.android.server.pm.pkg.PackageState;
 import com.android.server.pm.pkg.PackageStateInternal;
 import com.android.server.pm.pkg.SharedUserApi;
+import com.android.server.pm.resolution.ComponentResolverApi;
 import com.android.server.utils.WatchedArrayMap;
 import com.android.server.utils.WatchedLongSparseArray;
 
@@ -1299,4 +1300,28 @@
             return current.mComputer.getSharedUserPackages(sharedUserAppId);
         }
     }
+
+    @NonNull
+    @Override
+    public ComponentResolverApi getComponentResolver() {
+        try (ThreadComputer current = snapshot()) {
+            return current.mComputer.getComponentResolver();
+        }
+    }
+
+    @Nullable
+    @Override
+    public PackageStateInternal getDisabledSystemPackage(@NonNull String packageName) {
+        try (ThreadComputer current = snapshot()) {
+            return current.mComputer.getDisabledSystemPackage(packageName);
+        }
+    }
+
+    @Nullable
+    @Override
+    public ResolveInfo getInstantAppInstallerInfo() {
+        try (ThreadComputer current = snapshot()) {
+            return current.mComputer.getInstantAppInstallerInfo();
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/pm/DumpHelper.java b/services/core/java/com/android/server/pm/DumpHelper.java
index d5a882b..2b46ed4 100644
--- a/services/core/java/com/android/server/pm/DumpHelper.java
+++ b/services/core/java/com/android/server/pm/DumpHelper.java
@@ -405,7 +405,8 @@
         }
 
         if (!checkin && dumpState.isDumping(DumpState.DUMP_PROVIDERS)) {
-            mPm.mComponentResolver.dumpContentProviders(pw, dumpState, packageName);
+            mPm.mComponentResolver.dumpContentProviders(mPm.snapshotComputer(), pw, dumpState,
+                    packageName);
         }
 
         if (!checkin
diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java
index 2ef092e..234a230 100644
--- a/services/core/java/com/android/server/pm/InstallPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java
@@ -36,6 +36,7 @@
 import static android.content.pm.PackageManager.INSTALL_REASON_DEVICE_SETUP;
 import static android.content.pm.PackageManager.INSTALL_SUCCEEDED;
 import static android.content.pm.PackageManager.UNINSTALL_REASON_UNKNOWN;
+import static android.content.pm.PackageManagerInternal.PACKAGE_SETUP_WIZARD;
 import static android.content.pm.SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V4;
 import static android.content.pm.parsing.ApkLiteParseUtils.isApkFile;
 import static android.os.PowerExemptionManager.REASON_PACKAGE_REPLACED;
@@ -454,7 +455,8 @@
             KeySetManagerService ksms = mPm.mSettings.getKeySetManagerService();
             ksms.addScannedPackageLPw(pkg);
 
-            mPm.mComponentResolver.addAllComponents(pkg, chatty);
+            mPm.mComponentResolver.addAllComponents(pkg, chatty, mPm.mSetupWizardPackage,
+                    mPm.snapshotComputer());
             mPm.mAppsFilter.addPackage(pkgSetting, isReplace);
             mPm.addAllPackageProperties(pkg);
 
diff --git a/services/core/java/com/android/server/pm/InstantAppResolver.java b/services/core/java/com/android/server/pm/InstantAppResolver.java
index 79f8dc1..92d6a82 100644
--- a/services/core/java/com/android/server/pm/InstantAppResolver.java
+++ b/services/core/java/com/android/server/pm/InstantAppResolver.java
@@ -57,6 +57,7 @@
 import com.android.internal.logging.nano.MetricsProto;
 import com.android.server.pm.InstantAppResolverConnection.ConnectionException;
 import com.android.server.pm.InstantAppResolverConnection.PhaseTwoCallback;
+import com.android.server.pm.resolution.ComponentResolver;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -134,8 +135,9 @@
         }
     }
 
-    public static AuxiliaryResolveInfo doInstantAppResolutionPhaseOne(
-            InstantAppResolverConnection connection, InstantAppRequest requestObj) {
+    public static AuxiliaryResolveInfo doInstantAppResolutionPhaseOne(@NonNull Computer computer,
+            @NonNull UserManagerService userManager, InstantAppResolverConnection connection,
+            InstantAppRequest requestObj) {
         final long startTime = System.currentTimeMillis();
         final String token = requestObj.token;
         if (DEBUG_INSTANT) {
@@ -149,7 +151,7 @@
             final List<InstantAppResolveInfo> instantAppResolveInfoList =
                     connection.getInstantAppResolveInfoList(buildRequestInfo(requestObj));
             if (instantAppResolveInfoList != null && instantAppResolveInfoList.size() > 0) {
-                resolveInfo = InstantAppResolver.filterInstantAppIntent(
+                resolveInfo = InstantAppResolver.filterInstantAppIntent(computer, userManager,
                         instantAppResolveInfoList, origIntent, requestObj.resolvedType,
                         requestObj.userId, origIntent.getPackage(), token,
                         requestObj.hostDigestPrefixSecure);
@@ -187,9 +189,10 @@
         return resolveInfo;
     }
 
-    public static void doInstantAppResolutionPhaseTwo(Context context,
-            InstantAppResolverConnection connection, InstantAppRequest requestObj,
-            ActivityInfo instantAppInstaller, Handler callbackHandler) {
+    public static void doInstantAppResolutionPhaseTwo(Context context, @NonNull Computer computer,
+            @NonNull UserManagerService userManager, InstantAppResolverConnection connection,
+            InstantAppRequest requestObj, ActivityInfo instantAppInstaller,
+            Handler callbackHandler) {
         final long startTime = System.currentTimeMillis();
         final String token = requestObj.token;
         if (DEBUG_INSTANT) {
@@ -205,7 +208,7 @@
                 final Intent failureIntent;
                 if (instantAppResolveInfoList != null && instantAppResolveInfoList.size() > 0) {
                     final AuxiliaryResolveInfo instantAppIntentInfo =
-                            InstantAppResolver.filterInstantAppIntent(
+                            InstantAppResolver.filterInstantAppIntent(computer, userManager,
                                     instantAppResolveInfoList, origIntent, null /*resolvedType*/,
                                     0 /*userId*/, origIntent.getPackage(),
                                     token, requestObj.hostDigestPrefixSecure);
@@ -386,7 +389,8 @@
         );
     }
 
-    private static AuxiliaryResolveInfo filterInstantAppIntent(
+    private static AuxiliaryResolveInfo filterInstantAppIntent(@NonNull Computer computer,
+            @NonNull UserManagerService userManager,
             List<InstantAppResolveInfo> instantAppResolveInfoList, Intent origIntent,
             String resolvedType, int userId, String packageName, String token,
             int[] hostDigestPrefixSecure) {
@@ -421,7 +425,8 @@
             }
             // We matched a resolve info; resolve the filters to see if anything matches completely.
             List<AuxiliaryResolveInfo.AuxiliaryFilter> matchFilters = computeResolveFilters(
-                    origIntent, resolvedType, userId, packageName, token, instantAppResolveInfo);
+                    computer, userManager, origIntent, resolvedType, userId, packageName, token,
+                    instantAppResolveInfo);
             if (matchFilters != null) {
                 if (matchFilters.isEmpty()) {
                     requiresSecondPhase = true;
@@ -464,7 +469,8 @@
      *
      */
     private static List<AuxiliaryResolveInfo.AuxiliaryFilter> computeResolveFilters(
-            Intent origIntent, String resolvedType, int userId, String packageName, String token,
+            @NonNull Computer computer, @NonNull UserManagerService userManager, Intent origIntent,
+            String resolvedType, int userId, String packageName, String token,
             InstantAppResolveInfo instantAppInfo) {
         if (instantAppInfo.shouldLetInstallerDecide()) {
             return Collections.singletonList(
@@ -490,7 +496,7 @@
             return Collections.emptyList();
         }
         final ComponentResolver.InstantAppIntentResolver instantAppResolver =
-                new ComponentResolver.InstantAppIntentResolver();
+                new ComponentResolver.InstantAppIntentResolver(userManager);
         for (int j = instantAppFilters.size() - 1; j >= 0; --j) {
             final InstantAppIntentFilter instantAppFilter = instantAppFilters.get(j);
             final List<IntentFilter> splitFilters = instantAppFilter.getFilters();
@@ -508,7 +514,7 @@
                         && filter.hasCategory(Intent.CATEGORY_BROWSABLE)) {
                     continue;
                 }
-                instantAppResolver.addFilter(
+                instantAppResolver.addFilter(computer,
                         new AuxiliaryResolveInfo.AuxiliaryFilter(
                                 filter,
                                 instantAppInfo,
@@ -518,8 +524,8 @@
             }
         }
         List<AuxiliaryResolveInfo.AuxiliaryFilter> matchedResolveInfoList =
-                instantAppResolver.queryIntent(
-                        origIntent, resolvedType, false /*defaultOnly*/, userId);
+                instantAppResolver.queryIntent(computer, origIntent, resolvedType,
+                        false /*defaultOnly*/, userId);
         if (!matchedResolveInfoList.isEmpty()) {
             if (DEBUG_INSTANT) {
                 Log.d(TAG, "[" + token + "] Found match(es); " + matchedResolveInfoList);
diff --git a/services/core/java/com/android/server/pm/PackageHandler.java b/services/core/java/com/android/server/pm/PackageHandler.java
index ec71940..46e2aa3 100644
--- a/services/core/java/com/android/server/pm/PackageHandler.java
+++ b/services/core/java/com/android/server/pm/PackageHandler.java
@@ -313,6 +313,8 @@
             }
             case INSTANT_APP_RESOLUTION_PHASE_TWO: {
                 InstantAppResolver.doInstantAppResolutionPhaseTwo(mPm.mContext,
+                        mPm.snapshotComputer(),
+                        mPm.mUserManager,
                         mPm.mInstantAppResolverConnection,
                         (InstantAppRequest) msg.obj,
                         mPm.mInstantAppInstallerActivity,
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 725e92a..0b7a6a7 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -111,7 +111,6 @@
 import android.content.pm.PackageManager.Property;
 import android.content.pm.PackageManager.PropertyLocation;
 import android.content.pm.PackageManagerInternal;
-import android.content.pm.PackageManagerInternal.PrivateResolveFlags;
 import android.content.pm.PackagePartitions;
 import android.content.pm.ParceledListSlice;
 import android.content.pm.PermissionGroupInfo;
@@ -242,6 +241,8 @@
 import com.android.server.pm.pkg.mutate.PackageStateWrite;
 import com.android.server.pm.pkg.mutate.PackageUserStateWrite;
 import com.android.server.pm.pkg.parsing.ParsingPackageUtils;
+import com.android.server.pm.resolution.ComponentResolver;
+import com.android.server.pm.resolution.ComponentResolverApi;
 import com.android.server.pm.verify.domain.DomainVerificationManagerInternal;
 import com.android.server.pm.verify.domain.DomainVerificationService;
 import com.android.server.pm.verify.domain.proxy.DomainVerificationProxy;
@@ -791,9 +792,6 @@
     private final AtomicInteger mNextMoveId = new AtomicInteger();
     final MovePackageHelper.MoveCallbacks mMoveCallbacks;
 
-    // Cache of users who need badging.
-    private final SparseBooleanArray mUserNeedsBadging = new SparseBooleanArray();
-
     /**
      * Token for keys in mPendingVerification.
      * Handler thread only!
@@ -912,6 +910,8 @@
 
     final UserManagerService mUserManager;
 
+    final UserNeedsBadgingCache mUserNeedsBadging;
+
     // Stores a list of users whose package restrictions file needs to be updated
     final ArraySet<Integer> mDirtyUsers = new ArraySet<>();
 
@@ -992,7 +992,7 @@
         public final ApplicationInfo androidApplication;
         public final String appPredictionServicePackage;
         public final AppsFilter appsFilter;
-        public final ComponentResolver componentResolver;
+        public final ComponentResolverApi componentResolver;
         public final PackageManagerService service;
         public final WatchedArrayMap<String, Integer> frozenPackages;
         public final SharedLibrariesRead sharedLibraries;
@@ -1081,17 +1081,10 @@
     private final SnapshotStatistics mSnapshotStatistics;
 
     /**
-     * Return the live computer.
-     */
-    Computer liveComputer() {
-        return mLiveComputer;
-    }
-
-    /**
      * Return the cached computer.  The method will rebuild the cached computer if necessary.
      * The live computer will be returned if snapshots are disabled.
      */
-    Computer snapshotComputer() {
+    public Computer snapshotComputer() {
         if (Thread.holdsLock(mLock)) {
             // If the current thread holds mLock then it may have modified state but not
             // yet invalidated the snapshot.  Always give the thread the live computer.
@@ -1171,8 +1164,8 @@
 
     @Override
     public void notifyPackagesReplacedReceived(String[] packages) {
-        ArraySet<String> packagesToNotify =
-                mComputer.getNotifyPackagesForReplacedReceived(packages);
+        Computer computer = snapshotComputer();
+        ArraySet<String> packagesToNotify = computer.getNotifyPackagesForReplacedReceived(packages);
         for (int index = 0; index < packagesToNotify.size(); index++) {
             notifyInstallObserver(packagesToNotify.valueAt(index));
         }
@@ -1441,7 +1434,7 @@
                 context, lock, installer, installLock, new PackageAbiHelperImpl(),
                 backgroundHandler,
                 SYSTEM_PARTITIONS,
-                (i, pm) -> new ComponentResolver(i.getUserManagerService(), pm.mPmInternal, lock),
+                (i, pm) -> new ComponentResolver(i.getUserManagerService(), pm.mUserNeedsBadging),
                 (i, pm) -> PermissionManagerService.create(context,
                         i.getSystemConfig().getAvailableFeatures()),
                 (i, pm) -> new UserManagerService(context, pm,
@@ -1619,6 +1612,7 @@
         mPermissionManager = injector.getPermissionManagerServiceInternal();
         mSettings = injector.getSettings();
         mUserManager = injector.getUserManagerService();
+        mUserNeedsBadging = new UserNeedsBadgingCache(mUserManager);
         mDomainVerificationManager = injector.getDomainVerificationManagerInternal();
         mHandler = injector.getHandler();
         mSharedLibraries = injector.getSharedLibrariesImpl();
@@ -1744,6 +1738,7 @@
         mTestUtilityService = LocalServices.getService(TestUtilityService.class);
         LocalServices.addService(PackageManagerInternal.class, mPmInternal);
         mUserManager = injector.getUserManagerService();
+        mUserNeedsBadging = new UserNeedsBadgingCache(mUserManager);
         mComponentResolver = injector.getComponentResolver();
         mPermissionManager = injector.getPermissionManagerServiceInternal();
         mSettings = injector.getSettings();
@@ -1846,7 +1841,9 @@
                 mAppDataHelper);
         mSharedLibraries.setDeletePackageHelper(mDeletePackageHelper);
         mPreferredActivityHelper = new PreferredActivityHelper(this);
-        mResolveIntentHelper = new ResolveIntentHelper(this, mPreferredActivityHelper);
+        mResolveIntentHelper = new ResolveIntentHelper(mContext, mPreferredActivityHelper,
+                injector.getCompatibility(), mUserManager, mDomainVerificationManager,
+                mUserNeedsBadging, () -> mResolveInfo, () -> mInstantAppInstallerActivity);
         mDexOptHelper = new DexOptHelper(this);
         mSuspendPackageHelper = new SuspendPackageHelper(this, mInjector, mBroadcastHelper,
                 mProtectedPackages);
@@ -1862,6 +1859,7 @@
             registerObservers(true);
         }
 
+        Computer computer = mLiveComputer;
         // CHECKSTYLE:OFF IndentationCheck
         synchronized (mInstallLock) {
         // writer
@@ -1975,12 +1973,12 @@
                     userIds, startTime);
 
             // Resolve the storage manager.
-            mStorageManagerPackage = getStorageManagerPackageName();
+            mStorageManagerPackage = getStorageManagerPackageName(computer);
 
             // Resolve protected action filters. Only the setup wizard is allowed to
             // have a high priority filter for these actions.
-            mSetupWizardPackage = getSetupWizardPackageNameImpl();
-            mComponentResolver.fixProtectedFilterPriorities();
+            mSetupWizardPackage = getSetupWizardPackageNameImpl(computer);
+            mComponentResolver.fixProtectedFilterPriorities(mPmInternal.getSetupWizardPackageName());
 
             mDefaultTextClassifierPackage = getDefaultTextClassifierPackageName();
             mSystemTextClassifierPackageName = getSystemTextClassifierPackageName();
@@ -2108,13 +2106,13 @@
                     SystemClock.uptimeMillis());
 
             if (!mOnlyCore) {
-                mRequiredVerifierPackage = getRequiredButNotReallyRequiredVerifierLPr();
-                mRequiredInstallerPackage = getRequiredInstallerLPr();
-                mRequiredUninstallerPackage = getRequiredUninstallerLPr();
+                mRequiredVerifierPackage = getRequiredButNotReallyRequiredVerifierLPr(computer);
+                mRequiredInstallerPackage = getRequiredInstallerLPr(computer);
+                mRequiredUninstallerPackage = getRequiredUninstallerLPr(computer);
                 ComponentName intentFilterVerifierComponent =
-                        getIntentFilterVerifierComponentNameLPr();
+                        getIntentFilterVerifierComponentNameLPr(computer);
                 ComponentName domainVerificationAgent =
-                        getDomainVerificationAgentComponentNameLPr();
+                        getDomainVerificationAgentComponentNameLPr(computer);
 
                 DomainVerificationProxy domainVerificationProxy = DomainVerificationProxy.makeProxy(
                         intentFilterVerifierComponent, domainVerificationAgent, mContext,
@@ -2137,7 +2135,7 @@
 
             // PermissionController hosts default permission granting and role management, so it's a
             // critical part of the core system.
-            mRequiredPermissionControllerPackage = getRequiredPermissionControllerLPr();
+            mRequiredPermissionControllerPackage = getRequiredPermissionControllerLPr(computer);
 
             mSettings.setPermissionControllerVersion(
                     getPackageInfo(mRequiredPermissionControllerPackage, 0,
@@ -2170,7 +2168,8 @@
                 mInstantAppResolverConnection =
                         mInjector.getInstantAppResolverConnection(instantAppResolverComponent);
                 mInstantAppResolverSettingsComponent =
-                        getInstantAppResolverSettingsLPr(instantAppResolverComponent);
+                        getInstantAppResolverSettingsLPr(computer,
+                                instantAppResolverComponent);
             } else {
                 mInstantAppResolverConnection = null;
                 mInstantAppResolverSettingsComponent = null;
@@ -2258,11 +2257,13 @@
                 "persist.pm.mock-upgrade", false /* default */);
     }
 
-    private @Nullable String getRequiredButNotReallyRequiredVerifierLPr() {
+    @Nullable
+    private String getRequiredButNotReallyRequiredVerifierLPr(@NonNull Computer computer) {
         final Intent intent = new Intent(Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
 
         final List<ResolveInfo> matches =
-                mResolveIntentHelper.queryIntentReceiversInternal(intent, PACKAGE_MIME_TYPE,
+                mResolveIntentHelper.queryIntentReceiversInternal(computer, intent,
+                        PACKAGE_MIME_TYPE,
                         MATCH_SYSTEM_ONLY | MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE,
                         UserHandle.USER_SYSTEM, Binder.getCallingUid());
         if (matches.size() == 1) {
@@ -2300,12 +2301,13 @@
         return servicesExtensionPackage;
     }
 
-    private @NonNull String getRequiredInstallerLPr() {
+    private @NonNull String getRequiredInstallerLPr(@NonNull Computer computer) {
         final Intent intent = new Intent(Intent.ACTION_INSTALL_PACKAGE);
         intent.addCategory(Intent.CATEGORY_DEFAULT);
         intent.setDataAndType(Uri.parse("content://com.example/foo.apk"), PACKAGE_MIME_TYPE);
 
-        final List<ResolveInfo> matches = queryIntentActivitiesInternal(intent, PACKAGE_MIME_TYPE,
+        final List<ResolveInfo> matches = computer.queryIntentActivitiesInternal(intent,
+                PACKAGE_MIME_TYPE,
                 MATCH_SYSTEM_ONLY | MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE,
                 UserHandle.USER_SYSTEM);
         if (matches.size() == 1) {
@@ -2319,14 +2321,14 @@
         }
     }
 
-    private @NonNull String getRequiredUninstallerLPr() {
+    private @NonNull String getRequiredUninstallerLPr(@NonNull Computer computer) {
         final Intent intent = new Intent(Intent.ACTION_UNINSTALL_PACKAGE);
         intent.addCategory(Intent.CATEGORY_DEFAULT);
         intent.setData(Uri.fromParts(PACKAGE_SCHEME, "foo.bar", null));
 
-        final ResolveInfo resolveInfo = resolveIntent(intent, null,
-                MATCH_SYSTEM_ONLY | MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE,
-                UserHandle.USER_SYSTEM);
+        final ResolveInfo resolveInfo = mResolveIntentHelper.resolveIntentInternal(computer, intent,
+                null, MATCH_SYSTEM_ONLY | MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE,
+                0 /*privateResolveFlags*/, UserHandle.USER_SYSTEM, false, Binder.getCallingUid());
         if (resolveInfo == null ||
                 mResolveActivity.name.equals(resolveInfo.getComponentInfo().name)) {
             throw new RuntimeException("There must be exactly one uninstaller; found "
@@ -2335,11 +2337,11 @@
         return resolveInfo.getComponentInfo().packageName;
     }
 
-    private @NonNull String getRequiredPermissionControllerLPr() {
+    private @NonNull String getRequiredPermissionControllerLPr(@NonNull Computer computer) {
         final Intent intent = new Intent(Intent.ACTION_MANAGE_PERMISSIONS);
         intent.addCategory(Intent.CATEGORY_DEFAULT);
 
-        final List<ResolveInfo> matches = queryIntentActivitiesInternal(intent, null,
+        final List<ResolveInfo> matches = computer.queryIntentActivitiesInternal(intent, null,
                 MATCH_SYSTEM_ONLY | MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE,
                 UserHandle.USER_SYSTEM);
         if (matches.size() == 1) {
@@ -2354,11 +2356,13 @@
         }
     }
 
-    private @NonNull ComponentName getIntentFilterVerifierComponentNameLPr() {
+    @NonNull
+    private ComponentName getIntentFilterVerifierComponentNameLPr(@NonNull Computer computer) {
         final Intent intent = new Intent(Intent.ACTION_INTENT_FILTER_NEEDS_VERIFICATION);
 
         final List<ResolveInfo> matches =
-                mResolveIntentHelper.queryIntentReceiversInternal(intent, PACKAGE_MIME_TYPE,
+                mResolveIntentHelper.queryIntentReceiversInternal(computer, intent,
+                        PACKAGE_MIME_TYPE,
                         MATCH_SYSTEM_ONLY | MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE,
                         UserHandle.USER_SYSTEM, Binder.getCallingUid());
         ResolveInfo best = null;
@@ -2384,10 +2388,10 @@
     }
 
     @Nullable
-    private ComponentName getDomainVerificationAgentComponentNameLPr() {
+    private ComponentName getDomainVerificationAgentComponentNameLPr(@NonNull Computer computer) {
         Intent intent = new Intent(Intent.ACTION_DOMAINS_NEED_VERIFICATION);
         List<ResolveInfo> matches =
-                mResolveIntentHelper.queryIntentReceiversInternal(intent, null,
+                mResolveIntentHelper.queryIntentReceiversInternal(computer, intent, null,
                         MATCH_SYSTEM_ONLY | MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE,
                         UserHandle.USER_SYSTEM, Binder.getCallingUid());
         ResolveInfo best = null;
@@ -2496,13 +2500,14 @@
                         | MATCH_DIRECT_BOOT_UNAWARE
                         | Intent.FLAG_IGNORE_EPHEMERAL
                         | (mIsEngBuild ? 0 : MATCH_SYSTEM_ONLY);
+        final Computer computer = snapshotComputer();
         final Intent intent = new Intent();
         intent.addCategory(Intent.CATEGORY_DEFAULT);
         intent.setDataAndType(Uri.fromFile(new File("foo.apk")), PACKAGE_MIME_TYPE);
         List<ResolveInfo> matches = null;
         for (String action : orderedActions) {
             intent.setAction(action);
-            matches = queryIntentActivitiesInternal(intent, PACKAGE_MIME_TYPE,
+            matches = computer.queryIntentActivitiesInternal(intent, PACKAGE_MIME_TYPE,
                     resolveFlags, UserHandle.USER_SYSTEM);
             if (matches.isEmpty()) {
                 if (DEBUG_INSTANT) {
@@ -2532,14 +2537,14 @@
         }
     }
 
-    private @Nullable ComponentName getInstantAppResolverSettingsLPr(
+    private @Nullable ComponentName getInstantAppResolverSettingsLPr(@NonNull Computer computer,
             @NonNull ComponentName resolver) {
         final Intent intent =  new Intent(Intent.ACTION_INSTANT_APP_RESOLVER_SETTINGS)
                 .addCategory(Intent.CATEGORY_DEFAULT)
                 .setPackage(resolver.getPackageName());
         final int resolveFlags = MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE;
-        List<ResolveInfo> matches = queryIntentActivitiesInternal(intent, null, resolveFlags,
-                UserHandle.USER_SYSTEM);
+        List<ResolveInfo> matches = computer.queryIntentActivitiesInternal(intent, null,
+                resolveFlags, UserHandle.USER_SYSTEM);
         if (matches.isEmpty()) {
             return null;
         }
@@ -2942,27 +2947,6 @@
     }
 
     /**
-     * Update given flags when being used to request {@link PackageInfo}.
-     */
-    private long updateFlagsForPackage(long flags, int userId) {
-        return mComputer.updateFlagsForPackage(flags, userId);
-    }
-
-    /**
-     * Update given flags when being used to request {@link ApplicationInfo}.
-     */
-    private long updateFlagsForApplication(long flags, int userId) {
-        return mComputer.updateFlagsForApplication(flags, userId);
-    }
-
-    /**
-     * Update given flags when being used to request {@link ComponentInfo}.
-     */
-    private long updateFlagsForComponent(long flags, int userId) {
-        return mComputer.updateFlagsForComponent(flags, userId);
-    }
-
-    /**
      * Update given flags when being used to request {@link ResolveInfo}.
      * <p>Instant apps are resolved specially, depending upon context. Minimally,
      * {@code}flags{@code} must have the {@link PackageManager#MATCH_INSTANT}
@@ -3314,8 +3298,8 @@
     @Override
     public ResolveInfo resolveIntent(Intent intent, String resolvedType,
             @PackageManager.ResolveInfoFlagsBits long flags, int userId) {
-        return mResolveIntentHelper.resolveIntentInternal(intent, resolvedType, flags,
-                0 /*privateResolveFlags*/, userId, false, Binder.getCallingUid());
+        return mResolveIntentHelper.resolveIntentInternal(snapshotComputer(), intent, resolvedType,
+                flags, 0 /*privateResolveFlags*/, userId, false, Binder.getCallingUid());
     }
 
     @Override
@@ -3414,8 +3398,8 @@
         try {
             Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "queryIntentActivities");
 
-            return new ParceledListSlice<>(
-                    queryIntentActivitiesInternal(intent, resolvedType, flags, userId));
+            return new ParceledListSlice<>(snapshotComputer().queryIntentActivitiesInternal(intent,
+                    resolvedType, flags, userId));
         } finally {
             Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
         }
@@ -3429,68 +3413,28 @@
         return mComputer.getInstantAppPackageName(callingUid);
     }
 
-    @NonNull List<ResolveInfo> queryIntentActivitiesInternal(Intent intent,
-            String resolvedType, @PackageManager.ResolveInfoFlagsBits long flags, int userId) {
-        return mComputer.queryIntentActivitiesInternal(intent,
-                resolvedType, flags, userId);
-    }
-
-    @NonNull List<ResolveInfo> queryIntentActivitiesInternal(Intent intent,
-            String resolvedType, @PackageManager.ResolveInfoFlagsBits long flags,
-            @PrivateResolveFlags long privateResolveFlags, int filterCallingUid, int userId,
-            boolean resolveForStart, boolean allowDynamicSplits) {
-        return mComputer.queryIntentActivitiesInternal(intent,
-                resolvedType, flags, privateResolveFlags,
-                filterCallingUid, userId, resolveForStart, allowDynamicSplits);
-    }
-
-    private CrossProfileDomainInfo getCrossProfileDomainPreferredLpr(Intent intent,
-            String resolvedType, @PackageManager.ResolveInfoFlagsBits long flags, int sourceUserId,
-            int parentUserId) {
-        return mComputer.getCrossProfileDomainPreferredLpr(intent,
-                resolvedType, flags, sourceUserId, parentUserId);
-    }
-
-    /**
-     * Filters out ephemeral activities.
-     * <p>When resolving for an ephemeral app, only activities that 1) are defined in the
-     * ephemeral app or 2) marked with {@code visibleToEphemeral} are returned.
-     *
-     * @param resolveInfos The pre-filtered list of resolved activities
-     * @param ephemeralPkgName The ephemeral package name. If {@code null}, no filtering
-     *          is performed.
-     * @param intent
-     * @return A filtered list of resolved activities.
-     */
-    List<ResolveInfo> applyPostResolutionFilter(@NonNull List<ResolveInfo> resolveInfos,
-            String ephemeralPkgName, boolean allowDynamicSplits, int filterCallingUid,
-            boolean resolveForStart, int userId, Intent intent) {
-        return mComputer.applyPostResolutionFilter(resolveInfos,
-                ephemeralPkgName, allowDynamicSplits, filterCallingUid,
-                resolveForStart, userId, intent);
-    }
-
     @Override
     public @NonNull ParceledListSlice<ResolveInfo> queryIntentActivityOptions(ComponentName caller,
             Intent[] specifics, String[] specificTypes, Intent intent,
             String resolvedType, @PackageManager.ResolveInfoFlagsBits long flags, int userId) {
         return new ParceledListSlice<>(mResolveIntentHelper.queryIntentActivityOptionsInternal(
-                caller, specifics, specificTypes, intent, resolvedType, flags, userId));
+                snapshotComputer(), caller, specifics, specificTypes, intent, resolvedType, flags,
+                userId));
     }
 
     @Override
     public @NonNull ParceledListSlice<ResolveInfo> queryIntentReceivers(Intent intent,
             String resolvedType, @PackageManager.ResolveInfoFlagsBits long flags, int userId) {
-        return new ParceledListSlice<>(mResolveIntentHelper.queryIntentReceiversInternal(intent,
-                resolvedType, flags, userId, Binder.getCallingUid()));
+        return new ParceledListSlice<>(mResolveIntentHelper.queryIntentReceiversInternal(
+                snapshotComputer(), intent, resolvedType, flags, userId, Binder.getCallingUid()));
     }
 
     @Override
     public ResolveInfo resolveService(Intent intent, String resolvedType,
             @PackageManager.ResolveInfoFlagsBits long flags, int userId) {
         final int callingUid = Binder.getCallingUid();
-        return mResolveIntentHelper.resolveServiceInternal(intent, resolvedType, flags, userId,
-                callingUid);
+        return mResolveIntentHelper.resolveServiceInternal(snapshotComputer(), intent, resolvedType,
+                flags, userId, callingUid);
     }
 
     @Override
@@ -3513,7 +3457,7 @@
     public @NonNull ParceledListSlice<ResolveInfo> queryIntentContentProviders(Intent intent,
             String resolvedType, @PackageManager.ResolveInfoFlagsBits long flags, int userId) {
         return new ParceledListSlice<>(mResolveIntentHelper.queryIntentContentProvidersInternal(
-                intent, resolvedType, flags, userId));
+                snapshotComputer(), intent, resolvedType, flags, userId));
     }
 
     @Override
@@ -3907,15 +3851,9 @@
         synchronized (mLock) {
             mPackageUsage.writeNow(mSettings.getPackagesLocked());
 
-            // This is the last chance to write out pending restriction settings
-            if (mHandler.hasMessages(WRITE_PACKAGE_RESTRICTIONS)) {
-                mHandler.removeMessages(WRITE_PACKAGE_RESTRICTIONS);
-                synchronized (mDirtyUsers) {
-                    for (int userId : mDirtyUsers) {
-                        mSettings.writePackageRestrictionsLPr(userId);
-                    }
-                    mDirtyUsers.clear();
-                }
+            if (mHandler.hasMessages(WRITE_SETTINGS)) {
+                mHandler.removeMessages(WRITE_SETTINGS);
+                writeSettings();
             }
         }
     }
@@ -5409,7 +5347,7 @@
                     }
                 }
             }
-            resolver.addFilter(newFilter);
+            resolver.addFilter(snapshotComputer(), newFilter);
         }
         scheduleWritePackageRestrictions(sourceUserId);
     }
@@ -5498,11 +5436,11 @@
         mPreferredActivityHelper.setHomeActivity(comp, userId);
     }
 
-    private @Nullable String getSetupWizardPackageNameImpl() {
+    private @Nullable String getSetupWizardPackageNameImpl(@NonNull Computer computer) {
         final Intent intent = new Intent(Intent.ACTION_MAIN);
         intent.addCategory(Intent.CATEGORY_SETUP_WIZARD);
 
-        final List<ResolveInfo> matches = queryIntentActivitiesInternal(intent, null,
+        final List<ResolveInfo> matches = computer.queryIntentActivitiesInternal(intent, null,
                 MATCH_SYSTEM_ONLY | MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE
                         | MATCH_DISABLED_COMPONENTS,
                 UserHandle.myUserId());
@@ -5515,10 +5453,10 @@
         }
     }
 
-    private @Nullable String getStorageManagerPackageName() {
+    private @Nullable String getStorageManagerPackageName(@NonNull Computer computer) {
         final Intent intent = new Intent(StorageManager.ACTION_MANAGE_STORAGE);
 
-        final List<ResolveInfo> matches = queryIntentActivitiesInternal(intent, null,
+        final List<ResolveInfo> matches = computer.queryIntentActivitiesInternal(intent, null,
                 MATCH_SYSTEM_ONLY | MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE
                         | MATCH_DISABLED_COMPONENTS,
                 UserHandle.myUserId());
@@ -6784,21 +6722,7 @@
     }
 
     boolean userNeedsBadging(int userId) {
-        int index = mUserNeedsBadging.indexOfKey(userId);
-        if (index < 0) {
-            final UserInfo userInfo;
-            final long token = Binder.clearCallingIdentity();
-            try {
-                userInfo = mUserManager.getUserInfo(userId);
-            } finally {
-                Binder.restoreCallingIdentity(token);
-            }
-            final boolean b;
-            b = userInfo != null && userInfo.isManagedProfile();
-            mUserNeedsBadging.put(userId, b);
-            return b;
-        }
-        return mUserNeedsBadging.valueAt(index);
+        return mUserNeedsBadging.get(userId);
     }
 
     @Nullable
@@ -7034,16 +6958,14 @@
         }
 
         @Override
-        public PackageSetting getDisabledSystemPackage(@NonNull String packageName) {
-            synchronized (mLock) {
-                return mSettings.getDisabledSystemPkgLPr(packageName);
-            }
+        public PackageStateInternal getDisabledSystemPackage(@NonNull String packageName) {
+            return snapshotComputer().getDisabledSystemPackage(packageName);
         }
 
         @Override
         public @Nullable
         String getDisabledSystemPackageName(@NonNull String packageName) {
-            PackageSetting disabledPkgSetting = getDisabledSystemPackage(
+            PackageStateInternal disabledPkgSetting = getDisabledSystemPackage(
                     packageName);
             AndroidPackage disabledPkg = disabledPkgSetting == null
                     ? null : disabledPkgSetting.getPkg();
@@ -7183,9 +7105,8 @@
         public List<ResolveInfo> queryIntentActivities(
                 Intent intent, String resolvedType, @PackageManager.ResolveInfoFlagsBits long flags,
                 int filterCallingUid, int userId) {
-            return PackageManagerService.this
-                    .queryIntentActivitiesInternal(intent, resolvedType, flags, 0, filterCallingUid,
-                            userId, false /*resolveForStart*/, true /*allowDynamicSplits*/);
+            return snapshotComputer().queryIntentActivitiesInternal(intent, resolvedType, flags,
+                    userId);
         }
 
         @Override
@@ -7193,7 +7114,7 @@
                 String resolvedType, @PackageManager.ResolveInfoFlagsBits long flags,
                 int filterCallingUid, int userId) {
             return PackageManagerService.this.mResolveIntentHelper.queryIntentReceiversInternal(
-                    intent, resolvedType, flags, userId, filterCallingUid);
+                    snapshotComputer(), intent, resolvedType, flags, userId, filterCallingUid);
         }
 
         @Override
@@ -7436,7 +7357,7 @@
                 @PackageManager.ResolveInfoFlagsBits long flags,
                 @PackageManagerInternal.PrivateResolveFlags long privateResolveFlags, int userId,
                 boolean resolveForStart, int filterCallingUid) {
-            return mResolveIntentHelper.resolveIntentInternal(
+            return mResolveIntentHelper.resolveIntentInternal(snapshotComputer(),
                     intent, resolvedType, flags, privateResolveFlags, userId, resolveForStart,
                     filterCallingUid);
         }
@@ -7444,8 +7365,8 @@
         @Override
         public ResolveInfo resolveService(Intent intent, String resolvedType,
                 @PackageManager.ResolveInfoFlagsBits long flags, int userId, int callingUid) {
-            return mResolveIntentHelper.resolveServiceInternal(intent, resolvedType, flags, userId,
-                    callingUid);
+            return mResolveIntentHelper.resolveServiceInternal(snapshotComputer(), intent,
+                    resolvedType, flags, userId, callingUid);
         }
 
         @Override
@@ -7900,6 +7821,12 @@
                 @NonNull Consumer<PackageStateMutator> consumer) {
             return PackageManagerService.this.commitPackageStateMutation(state, consumer);
         }
+
+        @NonNull
+        @Override
+        public Computer snapshot() {
+            return snapshotComputer();
+        }
     }
 
     private boolean setEnabledOverlayPackages(@UserIdInt int userId,
@@ -8346,16 +8273,6 @@
         }
     }
 
-    private void applyMimeGroupChanges(String packageName, String mimeGroup) {
-        if (mComponentResolver.updateMimeGroup(packageName, mimeGroup)) {
-            Binder.withCleanCallingIdentity(() ->
-                    mPreferredActivityHelper.clearPackagePreferredActivities(packageName,
-                            UserHandle.USER_ALL));
-        }
-
-        mPmInternal.writeSettings(false);
-    }
-
     @Override
     public void setMimeGroup(String packageName, String mimeGroup, List<String> mimeTypes) {
         enforceOwnerRights(packageName, Binder.getCallingUid());
@@ -8375,7 +8292,13 @@
         commitPackageStateMutation(null, packageName, packageStateWrite -> {
             packageStateWrite.setMimeGroup(mimeGroup, mimeTypesSet);
         });
-        applyMimeGroupChanges(packageName, mimeGroup);
+        if (mComponentResolver.updateMimeGroup(snapshotComputer(), packageName, mimeGroup)) {
+            Binder.withCleanCallingIdentity(() ->
+                    mPreferredActivityHelper.clearPackagePreferredActivities(packageName,
+                            UserHandle.USER_ALL));
+        }
+
+        scheduleWriteSettings();
     }
 
     @Override
@@ -8607,8 +8530,8 @@
     @Override
     public IntentSender getLaunchIntentSenderForPackage(String packageName, String callingPackage,
             String featureId, int userId) throws RemoteException {
-        return mResolveIntentHelper.getLaunchIntentSenderForPackage(packageName, callingPackage,
-                featureId, userId);
+        return mResolveIntentHelper.getLaunchIntentSenderForPackage(snapshotComputer(),
+                packageName, callingPackage, featureId, userId);
     }
 
     @Override
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceInjector.java b/services/core/java/com/android/server/pm/PackageManagerServiceInjector.java
index 05bb01e..a02237f 100644
--- a/services/core/java/com/android/server/pm/PackageManagerServiceInjector.java
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceInjector.java
@@ -34,6 +34,7 @@
 import com.android.server.pm.parsing.PackageParser2;
 import com.android.server.pm.permission.LegacyPermissionManagerInternal;
 import com.android.server.pm.permission.PermissionManagerServiceInternal;
+import com.android.server.pm.resolution.ComponentResolver;
 import com.android.server.pm.verify.domain.DomainVerificationManagerInternal;
 
 import java.util.List;
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
index 2f56bfe..a9471cf 100644
--- a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
@@ -93,6 +93,7 @@
 import com.android.server.pm.parsing.pkg.AndroidPackage;
 import com.android.server.pm.pkg.PackageStateInternal;
 import com.android.server.pm.pkg.component.ParsedMainComponent;
+import com.android.server.pm.resolution.ComponentResolverApi;
 import com.android.server.pm.verify.domain.DomainVerificationManagerInternal;
 
 import dalvik.system.VMRuntime;
@@ -1064,7 +1065,7 @@
 
     // Static to give access to ComputeEngine
     public static void applyEnforceIntentFilterMatching(
-            PlatformCompat compat, ComponentResolver resolver,
+            PlatformCompat compat, ComponentResolverApi resolver,
             List<ResolveInfo> resolveInfos, boolean isReceiver,
             Intent intent, String resolvedType, int filterCallingUid) {
         // Do not enforce filter matching when the caller is system or root.
diff --git a/services/core/java/com/android/server/pm/PreferredActivityHelper.java b/services/core/java/com/android/server/pm/PreferredActivityHelper.java
index bb82e6a..8c49baf 100644
--- a/services/core/java/com/android/server/pm/PreferredActivityHelper.java
+++ b/services/core/java/com/android/server/pm/PreferredActivityHelper.java
@@ -140,8 +140,8 @@
             return false;
         }
         final Intent intent = mPm.getHomeIntent();
-        final List<ResolveInfo> resolveInfos = mPm.queryIntentActivitiesInternal(intent, null,
-                MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE, userId);
+        final List<ResolveInfo> resolveInfos = mPm.snapshotComputer().queryIntentActivitiesInternal(
+                intent, null, MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE, userId);
         final ResolveInfo preferredResolveInfo = findPreferredActivityNotLocked(
                 intent, null, 0, resolveInfos, true, false, false, userId);
         final String packageName = preferredResolveInfo != null
@@ -209,7 +209,8 @@
             if (removeExisting && existing != null) {
                 Settings.removeFilters(pir, filter, existing);
             }
-            pir.addFilter(new PreferredActivity(filter, match, set, activity, always));
+            pir.addFilter(mPm.snapshotComputer(),
+                    new PreferredActivity(filter, match, set, activity, always));
             mPm.scheduleWritePackageRestrictions(userId);
         }
         if (!(isHomeFilter(filter) && updateDefaultHomeNotLocked(userId))) {
@@ -394,6 +395,7 @@
         }
         synchronized (mPm.mLock) {
             mPm.mSettings.editPersistentPreferredActivitiesLPw(userId).addFilter(
+                    mPm.snapshotComputer(),
                     new PersistentPreferredActivity(filter, activity, true));
             mPm.scheduleWritePackageRestrictions(userId);
         }
@@ -672,8 +674,8 @@
                 0, userId, callingUid, false /*includeInstantApps*/,
                 mPm.isImplicitImageCaptureIntentAndNotSetByDpcLocked(intent, userId, resolvedType,
                         0));
-        final List<ResolveInfo> query = mPm.queryIntentActivitiesInternal(intent, resolvedType,
-                flags, userId);
+        final List<ResolveInfo> query = mPm.snapshotComputer().queryIntentActivitiesInternal(intent,
+                resolvedType, flags, userId);
         synchronized (mPm.mLock) {
             return mPm.findPersistentPreferredActivityLP(intent, resolvedType, flags, query, false,
                     userId);
@@ -699,8 +701,8 @@
             filter.dump(new PrintStreamPrinter(System.out), "    ");
         }
         intent.setComponent(null);
-        final List<ResolveInfo> query = mPm.queryIntentActivitiesInternal(intent, resolvedType,
-                flags, userId);
+        final List<ResolveInfo> query = mPm.snapshotComputer().queryIntentActivitiesInternal(intent,
+                resolvedType, flags, userId);
         // Find any earlier preferred or last chosen entries and nuke them
         findPreferredActivityNotLocked(
                 intent, resolvedType, flags, query, false, true, false, userId);
@@ -715,8 +717,8 @@
         }
         final int userId = UserHandle.getCallingUserId();
         if (DEBUG_PREFERRED) Log.v(TAG, "Querying last chosen activity for " + intent);
-        final List<ResolveInfo> query = mPm.queryIntentActivitiesInternal(intent, resolvedType,
-                flags, userId);
+        final List<ResolveInfo> query = mPm.snapshotComputer().queryIntentActivitiesInternal(intent,
+                resolvedType, flags, userId);
         return findPreferredActivityNotLocked(
                 intent, resolvedType, flags, query, false, false, false, userId);
     }
diff --git a/services/core/java/com/android/server/pm/ResolveIntentHelper.java b/services/core/java/com/android/server/pm/ResolveIntentHelper.java
index 2aff90f..25356a4 100644
--- a/services/core/java/com/android/server/pm/ResolveIntentHelper.java
+++ b/services/core/java/com/android/server/pm/ResolveIntentHelper.java
@@ -27,6 +27,8 @@
 import android.app.ActivityManager;
 import android.app.PendingIntent;
 import android.content.ComponentName;
+import android.content.ContentResolver;
+import android.content.Context;
 import android.content.IIntentSender;
 import android.content.Intent;
 import android.content.IntentFilter;
@@ -50,23 +52,52 @@
 
 import com.android.internal.app.ResolverActivity;
 import com.android.internal.util.ArrayUtils;
+import com.android.server.compat.PlatformCompat;
 import com.android.server.pm.parsing.pkg.AndroidPackage;
 import com.android.server.pm.pkg.PackageStateInternal;
+import com.android.server.pm.resolution.ComponentResolverApi;
+import com.android.server.pm.verify.domain.DomainVerificationManagerInternal;
 
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Objects;
+import java.util.function.Supplier;
 
 final class ResolveIntentHelper {
-    private final PackageManagerService mPm;
+    @NonNull
+    private final Context mContext;
+    @NonNull
+    private final PlatformCompat mPlatformCompat;
+    @NonNull
+    private final UserManagerService mUserManager;
+    @NonNull
     private final PreferredActivityHelper mPreferredActivityHelper;
+    @NonNull
+    private final DomainVerificationManagerInternal mDomainVerificationManager;
+    @NonNull
+    private final UserNeedsBadgingCache mUserNeedsBadging;
+    @NonNull
+    private final Supplier<ResolveInfo> mResolveInfoSupplier;
+    @NonNull
+    private final Supplier<ActivityInfo> mInstantAppInstallerActivitySupplier;
 
-    // TODO(b/198166813): remove PMS dependency
-    ResolveIntentHelper(PackageManagerService pm, PreferredActivityHelper preferredActivityHelper) {
-        mPm = pm;
+    ResolveIntentHelper(@NonNull Context context,
+            @NonNull PreferredActivityHelper preferredActivityHelper,
+            @NonNull PlatformCompat platformCompat, @NonNull UserManagerService userManager,
+            @NonNull DomainVerificationManagerInternal domainVerificationManager,
+            @NonNull UserNeedsBadgingCache userNeedsBadgingCache,
+            @NonNull Supplier<ResolveInfo> resolveInfoSupplier,
+            @NonNull Supplier<ActivityInfo> instantAppInstallerActivitySupplier) {
+        mContext = context;
         mPreferredActivityHelper = preferredActivityHelper;
+        mPlatformCompat = platformCompat;
+        mUserManager = userManager;
+        mDomainVerificationManager = domainVerificationManager;
+        mUserNeedsBadging = userNeedsBadgingCache;
+        mResolveInfoSupplier = resolveInfoSupplier;
+        mInstantAppInstallerActivitySupplier = instantAppInstallerActivitySupplier;
     }
 
     /**
@@ -74,35 +105,33 @@
      * However, if {@code resolveForStart} is {@code true}, all instant apps are visible
      * since we need to allow the system to start any installed application.
      */
-    public ResolveInfo resolveIntentInternal(Intent intent, String resolvedType,
+    public ResolveInfo resolveIntentInternal(Computer computer, Intent intent, String resolvedType,
             @PackageManager.ResolveInfoFlagsBits long flags,
             @PackageManagerInternal.PrivateResolveFlags long privateResolveFlags, int userId,
             boolean resolveForStart, int filterCallingUid) {
         try {
             Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "resolveIntent");
 
-            if (!mPm.mUserManager.exists(userId)) return null;
+            if (!mUserManager.exists(userId)) return null;
             final int callingUid = Binder.getCallingUid();
-            flags = mPm.updateFlagsForResolve(flags, userId, filterCallingUid, resolveForStart,
-                    mPm.isImplicitImageCaptureIntentAndNotSetByDpcLocked(intent, userId,
+            flags = computer.updateFlagsForResolve(flags, userId, filterCallingUid, resolveForStart,
+                    computer.isImplicitImageCaptureIntentAndNotSetByDpcLocked(intent, userId,
                             resolvedType, flags));
-            mPm.enforceCrossUserPermission(callingUid, userId, false /*requireFullPermission*/,
+            computer.enforceCrossUserPermission(callingUid, userId, false /*requireFullPermission*/,
                     false /*checkShell*/, "resolve intent");
 
             Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "queryIntentActivities");
-            final List<ResolveInfo> query = mPm.queryIntentActivitiesInternal(intent, resolvedType,
-                    flags, privateResolveFlags, filterCallingUid, userId, resolveForStart,
-                    true /*allowDynamicSplits*/);
+            final List<ResolveInfo> query = computer.queryIntentActivitiesInternal(intent,
+                    resolvedType, flags, privateResolveFlags, filterCallingUid, userId,
+                    resolveForStart, true /*allowDynamicSplits*/);
             Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
 
             final boolean queryMayBeFiltered =
                     UserHandle.getAppId(filterCallingUid) >= Process.FIRST_APPLICATION_UID
                             && !resolveForStart;
 
-            final ResolveInfo bestChoice =
-                    chooseBestActivity(
-                            intent, resolvedType, flags, privateResolveFlags, query, userId,
-                            queryMayBeFiltered);
+            final ResolveInfo bestChoice = chooseBestActivity(computer, intent, resolvedType, flags,
+                    privateResolveFlags, query, userId, queryMayBeFiltered);
             final boolean nonBrowserOnly =
                     (privateResolveFlags & PackageManagerInternal.RESOLVE_NON_BROWSER_ONLY) != 0;
             if (nonBrowserOnly && bestChoice != null && bestChoice.handleAllWebDataURI) {
@@ -114,7 +143,7 @@
         }
     }
 
-    private ResolveInfo chooseBestActivity(Intent intent, String resolvedType,
+    private ResolveInfo chooseBestActivity(Computer computer, Intent intent, String resolvedType,
             @PackageManager.ResolveInfoFlagsBits long flags,
             @PackageManagerInternal.PrivateResolveFlags long privateResolveFlags,
             List<ResolveInfo> query, int userId, boolean queryMayBeFiltered) {
@@ -156,9 +185,10 @@
                     // If we have an ephemeral app, use it
                     if (ri.activityInfo.applicationInfo.isInstantApp()) {
                         final String packageName = ri.activityInfo.packageName;
-                        final PackageStateInternal ps = mPm.getPackageStateInternal(packageName);
+                        final PackageStateInternal ps =
+                                computer.getPackageStateInternal(packageName);
                         if (ps != null && PackageManagerServiceUtils.hasAnyDomainApproval(
-                                mPm.mDomainVerificationManager, ps, intent, flags, userId)) {
+                                mDomainVerificationManager, ps, intent, flags, userId)) {
                             return ri;
                         }
                     }
@@ -167,7 +197,7 @@
                         & PackageManagerInternal.RESOLVE_NON_RESOLVER_ONLY) != 0) {
                     return null;
                 }
-                ri = new ResolveInfo(mPm.getResolveInfo());
+                ri = new ResolveInfo(mResolveInfoSupplier.get());
                 // if all resolve options are browsers, mark the resolver's info as if it were
                 // also a browser.
                 ri.handleAllWebDataURI = browserCount == n;
@@ -184,7 +214,7 @@
                 if (!TextUtils.isEmpty(intentPackage) && allHavePackage(query, intentPackage)) {
                     final ApplicationInfo appi = query.get(0).activityInfo.applicationInfo;
                     ri.resolvePackageName = intentPackage;
-                    if (mPm.userNeedsBadging(userId)) {
+                    if (mUserNeedsBadging.get(userId)) {
                         ri.noResourceId = true;
                     } else {
                         ri.icon = appi.icon;
@@ -225,13 +255,14 @@
         return true;
     }
 
-    public IntentSender getLaunchIntentSenderForPackage(String packageName, String callingPackage,
-            String featureId, int userId) throws RemoteException {
+    public IntentSender getLaunchIntentSenderForPackage(@NonNull Computer computer,
+            String packageName, String callingPackage, String featureId, int userId)
+            throws RemoteException {
         Objects.requireNonNull(packageName);
         final int callingUid = Binder.getCallingUid();
-        mPm.enforceCrossUserPermission(callingUid, userId, false /* requireFullPermission */,
+        computer.enforceCrossUserPermission(callingUid, userId, false /* requireFullPermission */,
                 false /* checkShell */, "get launch intent sender for package");
-        final int packageUid = mPm.getPackageUid(callingPackage, 0 /* flags */, userId);
+        final int packageUid = computer.getPackageUid(callingPackage, 0 /* flags */, userId);
         if (!UserHandle.isSameApp(callingUid, packageUid)) {
             throw new SecurityException("getLaunchIntentSenderForPackage() from calling uid: "
                     + callingUid + " does not own package: " + callingPackage);
@@ -242,17 +273,17 @@
         final Intent intentToResolve = new Intent(Intent.ACTION_MAIN);
         intentToResolve.addCategory(Intent.CATEGORY_INFO);
         intentToResolve.setPackage(packageName);
-        String resolvedType = intentToResolve.resolveTypeIfNeeded(
-                mPm.mContext.getContentResolver());
-        List<ResolveInfo> ris = mPm.queryIntentActivitiesInternal(intentToResolve, resolvedType,
+        final ContentResolver contentResolver = mContext.getContentResolver();
+        String resolvedType = intentToResolve.resolveTypeIfNeeded(contentResolver);
+        List<ResolveInfo> ris = computer.queryIntentActivitiesInternal(intentToResolve, resolvedType,
                 0 /* flags */, 0 /* privateResolveFlags */, callingUid, userId,
                 true /* resolveForStart */, false /* allowDynamicSplits */);
         if (ris == null || ris.size() <= 0) {
             intentToResolve.removeCategory(Intent.CATEGORY_INFO);
             intentToResolve.addCategory(Intent.CATEGORY_LAUNCHER);
             intentToResolve.setPackage(packageName);
-            resolvedType = intentToResolve.resolveTypeIfNeeded(mPm.mContext.getContentResolver());
-            ris = mPm.queryIntentActivitiesInternal(intentToResolve, resolvedType,
+            resolvedType = intentToResolve.resolveTypeIfNeeded(contentResolver);
+            ris = computer.queryIntentActivitiesInternal(intentToResolve, resolvedType,
                     0 /* flags */, 0 /* privateResolveFlags */, callingUid, userId,
                     true /* resolveForStart */, false /* allowDynamicSplits */);
         }
@@ -277,17 +308,17 @@
 
     // In this method, we have to know the actual calling UID, but in some cases Binder's
     // call identity is removed, so the UID has to be passed in explicitly.
-    public @NonNull List<ResolveInfo> queryIntentReceiversInternal(Intent intent,
+    public @NonNull List<ResolveInfo> queryIntentReceiversInternal(Computer computer, Intent intent,
             String resolvedType, @PackageManager.ResolveInfoFlagsBits long flags, int userId,
             int filterCallingUid) {
-        if (!mPm.mUserManager.exists(userId)) return Collections.emptyList();
-        mPm.enforceCrossUserPermission(filterCallingUid, userId, false /*requireFullPermission*/,
+        if (!mUserManager.exists(userId)) return Collections.emptyList();
+        computer.enforceCrossUserPermission(filterCallingUid, userId, false /*requireFullPermission*/,
                 false /*checkShell*/, "query intent receivers");
-        final String instantAppPkgName = mPm.getInstantAppPackageName(filterCallingUid);
-        flags = mPm.updateFlagsForResolve(
-                flags, userId, filterCallingUid, false /*includeInstantApps*/,
-                mPm.isImplicitImageCaptureIntentAndNotSetByDpcLocked(intent, userId, resolvedType,
-                        flags));
+        final String instantAppPkgName = computer.getInstantAppPackageName(filterCallingUid);
+        flags = computer.updateFlagsForResolve(flags, userId, filterCallingUid,
+                false /*includeInstantApps*/,
+                computer.isImplicitImageCaptureIntentAndNotSetByDpcLocked(intent, userId,
+                        resolvedType, flags));
         Intent originalIntent = null;
         ComponentName comp = intent.getComponent();
         if (comp == null) {
@@ -297,9 +328,10 @@
                 comp = intent.getComponent();
             }
         }
+        final ComponentResolverApi componentResolver = computer.getComponentResolver();
         List<ResolveInfo> list = Collections.emptyList();
         if (comp != null) {
-            final ActivityInfo ai = mPm.getReceiverInfo(comp, flags, userId);
+            final ActivityInfo ai = computer.getReceiverInfo(comp, flags, userId);
             if (ai != null) {
                 // When specifying an explicit component, we prevent the activity from being
                 // used when either 1) the calling package is normal and the activity is within
@@ -335,28 +367,25 @@
                     list = new ArrayList<>(1);
                     list.add(ri);
                     PackageManagerServiceUtils.applyEnforceIntentFilterMatching(
-                            mPm.mInjector.getCompatibility(), mPm.mComponentResolver,
-                            list, true, intent, resolvedType, filterCallingUid);
+                            mPlatformCompat, componentResolver, list, true, intent,
+                            resolvedType, filterCallingUid);
                 }
             }
         } else {
-            // reader
-            synchronized (mPm.mLock) {
-                String pkgName = intent.getPackage();
-                if (pkgName == null) {
-                    final List<ResolveInfo> result = mPm.mComponentResolver.queryReceivers(
-                            intent, resolvedType, flags, userId);
-                    if (result != null) {
-                        list = result;
-                    }
+            String pkgName = intent.getPackage();
+            if (pkgName == null) {
+                final List<ResolveInfo> result = componentResolver
+                        .queryReceivers(computer, intent, resolvedType, flags, userId);
+                if (result != null) {
+                    list = result;
                 }
-                final AndroidPackage pkg = mPm.mPackages.get(pkgName);
-                if (pkg != null) {
-                    final List<ResolveInfo> result = mPm.mComponentResolver.queryReceivers(
-                            intent, resolvedType, flags, pkg.getReceivers(), userId);
-                    if (result != null) {
-                        list = result;
-                    }
+            }
+            final AndroidPackage pkg = computer.getPackage(pkgName);
+            if (pkg != null) {
+                final List<ResolveInfo> result = componentResolver.queryReceivers(computer,
+                        intent, resolvedType, flags, pkg.getReceivers(), userId);
+                if (result != null) {
+                    list = result;
                 }
             }
         }
@@ -364,21 +393,22 @@
         if (originalIntent != null) {
             // We also have to ensure all components match the original intent
             PackageManagerServiceUtils.applyEnforceIntentFilterMatching(
-                    mPm.mInjector.getCompatibility(), mPm.mComponentResolver,
+                    mPlatformCompat, componentResolver,
                     list, true, originalIntent, resolvedType, filterCallingUid);
         }
 
-        return mPm.applyPostResolutionFilter(
-                list, instantAppPkgName, false, filterCallingUid, false, userId, intent);
+        return computer.applyPostResolutionFilter(list, instantAppPkgName, false, filterCallingUid,
+                false, userId, intent);
     }
 
 
-    public ResolveInfo resolveServiceInternal(Intent intent, String resolvedType,
-            @PackageManager.ResolveInfoFlagsBits long flags, int userId, int callingUid) {
-        if (!mPm.mUserManager.exists(userId)) return null;
-        flags = mPm.updateFlagsForResolve(flags, userId, callingUid, false /*includeInstantApps*/,
+    public ResolveInfo resolveServiceInternal(@NonNull Computer computer, Intent intent,
+            String resolvedType, @PackageManager.ResolveInfoFlagsBits long flags, int userId,
+            int callingUid) {
+        if (!mUserManager.exists(userId)) return null;
+        flags = computer.updateFlagsForResolve(flags, userId, callingUid, false /*includeInstantApps*/,
                 false /* isImplicitImageCaptureIntentAndNotSetByDpc */);
-        List<ResolveInfo> query = mPm.queryIntentServicesInternal(
+        List<ResolveInfo> query = computer.queryIntentServicesInternal(
                 intent, resolvedType, flags, userId, callingUid, false /*includeInstantApps*/);
         if (query != null) {
             if (query.size() >= 1) {
@@ -391,12 +421,12 @@
     }
 
     public @NonNull List<ResolveInfo> queryIntentContentProvidersInternal(
-            Intent intent, String resolvedType, @PackageManager.ResolveInfoFlagsBits long flags,
-            int userId) {
-        if (!mPm.mUserManager.exists(userId)) return Collections.emptyList();
+            @NonNull Computer computer, Intent intent, String resolvedType,
+            @PackageManager.ResolveInfoFlagsBits long flags, int userId) {
+        if (!mUserManager.exists(userId)) return Collections.emptyList();
         final int callingUid = Binder.getCallingUid();
-        final String instantAppPkgName = mPm.getInstantAppPackageName(callingUid);
-        flags = mPm.updateFlagsForResolve(flags, userId, callingUid, false /*includeInstantApps*/,
+        final String instantAppPkgName = computer.getInstantAppPackageName(callingUid);
+        flags = computer.updateFlagsForResolve(flags, userId, callingUid, false /*includeInstantApps*/,
                 false /* isImplicitImageCaptureIntentAndNotSetByDpc */);
         ComponentName comp = intent.getComponent();
         if (comp == null) {
@@ -407,7 +437,7 @@
         }
         if (comp != null) {
             final List<ResolveInfo> list = new ArrayList<>(1);
-            final ProviderInfo pi = mPm.getProviderInfo(comp, flags, userId);
+            final ProviderInfo pi = computer.getProviderInfo(comp, flags, userId);
             if (pi != null) {
                 // When specifying an explicit component, we prevent the provider from being
                 // used when either 1) the provider is in an instant application and the
@@ -432,8 +462,8 @@
                                 || (matchVisibleToInstantAppOnly && isCallerInstantApp
                                 && isTargetHiddenFromInstantApp));
                 final boolean blockNormalResolution = !isTargetInstantApp && !isCallerInstantApp
-                        && mPm.shouldFilterApplication(
-                        mPm.getPackageStateInternal(pi.applicationInfo.packageName,
+                        && computer.shouldFilterApplication(
+                        computer.getPackageStateInternal(pi.applicationInfo.packageName,
                                 Process.SYSTEM_UID), callingUid, userId);
                 if (!blockResolution && !blockNormalResolution) {
                     final ResolveInfo ri = new ResolveInfo();
@@ -444,46 +474,40 @@
             return list;
         }
 
-        // reader
-        synchronized (mPm.mLock) {
-            String pkgName = intent.getPackage();
-            if (pkgName == null) {
-                final List<ResolveInfo> resolveInfos = mPm.mComponentResolver.queryProviders(intent,
-                        resolvedType, flags, userId);
-                if (resolveInfos == null) {
-                    return Collections.emptyList();
-                }
-                return applyPostContentProviderResolutionFilter(
-                        resolveInfos, instantAppPkgName, userId, callingUid);
+        final ComponentResolverApi componentResolver = computer.getComponentResolver();
+        String pkgName = intent.getPackage();
+        if (pkgName == null) {
+            final List<ResolveInfo> resolveInfos = componentResolver.queryProviders(computer,
+                    intent, resolvedType, flags, userId);
+            if (resolveInfos == null) {
+                return Collections.emptyList();
             }
-            final AndroidPackage pkg = mPm.mPackages.get(pkgName);
-            if (pkg != null) {
-                final List<ResolveInfo> resolveInfos = mPm.mComponentResolver.queryProviders(intent,
-                        resolvedType, flags,
-                        pkg.getProviders(), userId);
-                if (resolveInfos == null) {
-                    return Collections.emptyList();
-                }
-                return applyPostContentProviderResolutionFilter(
-                        resolveInfos, instantAppPkgName, userId, callingUid);
-            }
-            return Collections.emptyList();
+            return applyPostContentProviderResolutionFilter(computer, resolveInfos,
+                    instantAppPkgName, userId, callingUid);
         }
+        final AndroidPackage pkg = computer.getPackage(pkgName);
+        if (pkg != null) {
+            final List<ResolveInfo> resolveInfos = componentResolver.queryProviders(computer,
+                    intent, resolvedType, flags, pkg.getProviders(), userId);
+            if (resolveInfos == null) {
+                return Collections.emptyList();
+            }
+            return applyPostContentProviderResolutionFilter(computer, resolveInfos,
+                    instantAppPkgName, userId, callingUid);
+        }
+        return Collections.emptyList();
     }
 
-    private List<ResolveInfo> applyPostContentProviderResolutionFilter(
+    private List<ResolveInfo> applyPostContentProviderResolutionFilter(@NonNull Computer computer,
             List<ResolveInfo> resolveInfos, String instantAppPkgName,
             @UserIdInt int userId, int callingUid) {
         for (int i = resolveInfos.size() - 1; i >= 0; i--) {
             final ResolveInfo info = resolveInfos.get(i);
 
             if (instantAppPkgName == null) {
-                SettingBase callingSetting =
-                        mPm.mSettings.getSettingLPr(UserHandle.getAppId(callingUid));
-                PackageStateInternal resolvedSetting =
-                        mPm.getPackageStateInternal(info.providerInfo.packageName, 0);
-                if (!mPm.mAppsFilter.shouldFilterApplication(
-                        callingUid, callingSetting, resolvedSetting, userId)) {
+                PackageStateInternal resolvedSetting = computer.getPackageStateInternal(
+                        info.providerInfo.packageName, 0);
+                if (!computer.shouldFilterApplication(resolvedSetting, callingUid, userId)) {
                     continue;
                 }
             }
@@ -494,7 +518,7 @@
                 if (info.providerInfo.splitName != null
                         && !ArrayUtils.contains(info.providerInfo.applicationInfo.splitNames,
                         info.providerInfo.splitName)) {
-                    if (mPm.mInstantAppInstallerActivity == null) {
+                    if (mInstantAppInstallerActivitySupplier.get() == null) {
                         if (DEBUG_INSTANT) {
                             Slog.v(TAG, "No installer - not adding it to the ResolveInfo list");
                         }
@@ -507,7 +531,7 @@
                         Slog.v(TAG, "Adding ephemeral installer to the ResolveInfo list");
                     }
                     final ResolveInfo installerInfo = new ResolveInfo(
-                            mPm.getInstantAppInstallerInfo());
+                            computer.getInstantAppInstallerInfo());
                     installerInfo.auxiliaryInfo = new AuxiliaryResolveInfo(
                             null /*failureActivity*/,
                             info.providerInfo.packageName,
@@ -531,20 +555,21 @@
         return resolveInfos;
     }
 
-    public @NonNull List<ResolveInfo> queryIntentActivityOptionsInternal(ComponentName caller,
-            Intent[] specifics, String[] specificTypes, Intent intent,
+    public @NonNull List<ResolveInfo> queryIntentActivityOptionsInternal(Computer computer,
+            ComponentName caller, Intent[] specifics, String[] specificTypes, Intent intent,
             String resolvedType, @PackageManager.ResolveInfoFlagsBits long flags, int userId) {
-        if (!mPm.mUserManager.exists(userId)) return Collections.emptyList();
+        if (!mUserManager.exists(userId)) return Collections.emptyList();
         final int callingUid = Binder.getCallingUid();
-        flags = mPm.updateFlagsForResolve(flags, userId, callingUid, false /*includeInstantApps*/,
-                mPm.isImplicitImageCaptureIntentAndNotSetByDpcLocked(intent, userId, resolvedType,
-                        flags));
-        mPm.enforceCrossUserPermission(callingUid, userId, false /*requireFullPermission*/,
+        flags = computer.updateFlagsForResolve(flags, userId, callingUid,
+                false /*includeInstantApps*/,
+                computer.isImplicitImageCaptureIntentAndNotSetByDpcLocked(intent, userId,
+                        resolvedType, flags));
+        computer.enforceCrossUserPermission(callingUid, userId, false /*requireFullPermission*/,
                 false /*checkShell*/, "query intent activity options");
         final String resultsAction = intent.getAction();
 
-        final List<ResolveInfo> results = mPm.queryIntentActivitiesInternal(intent, resolvedType,
-                flags | PackageManager.GET_RESOLVED_FILTER, userId);
+        final List<ResolveInfo> results = computer.queryIntentActivitiesInternal(intent,
+                resolvedType, flags | PackageManager.GET_RESOLVED_FILTER, userId);
 
         if (DEBUG_INTENT_MATCHING) {
             Log.v(TAG, "Query " + intent + ": " + results);
@@ -584,21 +609,20 @@
 
                 ComponentName comp = sintent.getComponent();
                 if (comp == null) {
-                    ri = mPm.resolveIntent(
-                            sintent,
-                            specificTypes != null ? specificTypes[i] : null,
-                            flags, userId);
+                    ri = resolveIntentInternal(computer, sintent,
+                            specificTypes != null ? specificTypes[i] : null, flags,
+                            0 /*privateResolveFlags*/, userId, false, Binder.getCallingUid());
                     if (ri == null) {
                         continue;
                     }
-                    if (ri == mPm.getResolveInfo()) {
+                    if (ri == mResolveInfoSupplier.get()) {
                         // ACK!  Must do something better with this.
                     }
                     ai = ri.activityInfo;
                     comp = new ComponentName(ai.applicationInfo.packageName,
                             ai.name);
                 } else {
-                    ai = mPm.getActivityInfo(comp, flags, userId);
+                    ai = computer.getActivityInfo(comp, flags, userId);
                     if (ai == null) {
                         continue;
                     }
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 4d7da1b..2ad35b7 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -120,6 +120,7 @@
 import com.android.server.pm.pkg.component.ParsedPermission;
 import com.android.server.pm.pkg.component.ParsedProcess;
 import com.android.server.pm.pkg.parsing.PackageInfoWithoutStateUtils;
+import com.android.server.pm.resolution.ComponentResolver;
 import com.android.server.pm.verify.domain.DomainVerificationLegacySettings;
 import com.android.server.pm.verify.domain.DomainVerificationManagerInternal;
 import com.android.server.pm.verify.domain.DomainVerificationPersistence;
@@ -1551,7 +1552,7 @@
                 if (pa.mPref.getParseError() == null) {
                     final PreferredIntentResolver resolver = editPreferredActivitiesLPw(userId);
                     if (resolver.shouldAddPreferredActivity(pa)) {
-                        resolver.addFilter(pa);
+                        resolver.addFilter(null, pa);
                     }
                 } else {
                     PackageManagerService.reportSettingsProblem(Log.WARN,
@@ -1579,7 +1580,7 @@
             String tagName = parser.getName();
             if (tagName.equals(TAG_ITEM)) {
                 PersistentPreferredActivity ppa = new PersistentPreferredActivity(parser);
-                editPersistentPreferredActivitiesLPw(userId).addFilter(ppa);
+                editPersistentPreferredActivitiesLPw(userId).addFilter(null, ppa);
             } else {
                 PackageManagerService.reportSettingsProblem(Log.WARN,
                         "Unknown element under <" + TAG_PERSISTENT_PREFERRED_ACTIVITIES + ">: "
@@ -1601,7 +1602,7 @@
             final String tagName = parser.getName();
             if (tagName.equals(TAG_ITEM)) {
                 CrossProfileIntentFilter cpif = new CrossProfileIntentFilter(parser);
-                editCrossProfileIntentResolverLPw(userId).addFilter(cpif);
+                editCrossProfileIntentResolverLPw(userId).addFilter(null, cpif);
             } else {
                 String msg = "Unknown element under " +  TAG_CROSS_PROFILE_INTENT_FILTERS + ": " +
                         tagName;
@@ -1868,8 +1869,7 @@
                                 .build();
                     }
                     if (suspended && suspendParamsMap == null) {
-                        final SuspendParams suspendParams =
-                                SuspendParams.getInstanceOrNull(
+                        final SuspendParams suspendParams = new SuspendParams(
                                         oldSuspendDialogInfo,
                                         suspendedAppExtras,
                                         suspendedLauncherExtras);
@@ -3517,7 +3517,7 @@
                 removeFilters(pir, filter, existing);
             }
             PreferredActivity pa = new PreferredActivity(filter, systemMatch, set, cn, true);
-            pir.addFilter(pa);
+            pir.addFilter(null, pa);
         } else if (haveNonSys == null) {
             StringBuilder sb = new StringBuilder();
             sb.append("No component ");
diff --git a/services/core/java/com/android/server/pm/SuspendPackageHelper.java b/services/core/java/com/android/server/pm/SuspendPackageHelper.java
index 85d1367..bd1c9c7 100644
--- a/services/core/java/com/android/server/pm/SuspendPackageHelper.java
+++ b/services/core/java/com/android/server/pm/SuspendPackageHelper.java
@@ -112,7 +112,7 @@
         }
 
         final SuspendParams newSuspendParams =
-                SuspendParams.getInstanceOrNull(dialogInfo, appExtras, launcherExtras);
+                new SuspendParams(dialogInfo, appExtras, launcherExtras);
 
         final List<String> changedPackagesList = new ArrayList<>(packageNames.length);
         final IntArray changedUids = new IntArray(packageNames.length);
@@ -148,13 +148,12 @@
 
                 final WatchedArrayMap<String, SuspendParams> suspendParamsMap =
                         packageState.getUserStateOrDefault(userId).getSuspendParams();
-                final SuspendParams suspendParams = suspendParamsMap == null
-                        ? null : suspendParamsMap.get(packageName);
-                boolean hasSuspension = suspendParams != null;
                 if (suspended) {
-                    if (hasSuspension) {
+                    if (suspendParamsMap != null && suspendParamsMap.containsKey(packageName)) {
+                        final SuspendParams suspendParams = suspendParamsMap.get(packageName);
                         // Skip if there's no changes
-                        if (Objects.equals(suspendParams.getDialogInfo(), dialogInfo)
+                        if (suspendParams != null
+                                && Objects.equals(suspendParams.getDialogInfo(), dialogInfo)
                                 && Objects.equals(suspendParams.getAppExtras(), appExtras)
                                 && Objects.equals(suspendParams.getLauncherExtras(),
                                 launcherExtras)) {
diff --git a/services/core/java/com/android/server/pm/UserNeedsBadgingCache.java b/services/core/java/com/android/server/pm/UserNeedsBadgingCache.java
new file mode 100644
index 0000000..90c9228
--- /dev/null
+++ b/services/core/java/com/android/server/pm/UserNeedsBadgingCache.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm;
+
+import android.annotation.NonNull;
+import android.annotation.UserIdInt;
+import android.content.pm.UserInfo;
+import android.os.Binder;
+import android.util.SparseBooleanArray;
+
+import com.android.internal.annotations.GuardedBy;
+
+public class UserNeedsBadgingCache {
+
+    private final Object mLock = new Object();
+
+    // Cache of users who need badging.
+    @GuardedBy("mLock")
+    @NonNull
+    private final SparseBooleanArray mUserCache = new SparseBooleanArray();
+
+    @NonNull
+    private final UserManagerService mUserManager;
+
+    public UserNeedsBadgingCache(@NonNull UserManagerService userManager) {
+        mUserManager = userManager;
+    }
+
+    public void delete(@UserIdInt int userId) {
+        synchronized (mLock) {
+            mUserCache.delete(userId);
+        }
+    }
+
+    public boolean get(@UserIdInt int userId) {
+        synchronized (mLock) {
+            int index = mUserCache.indexOfKey(userId);
+            if (index >= 0) {
+                return mUserCache.valueAt(index);
+            }
+        }
+
+        final UserInfo userInfo;
+        final long token = Binder.clearCallingIdentity();
+        try {
+            userInfo = mUserManager.getUserInfo(userId);
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+        final boolean b;
+        b = userInfo != null && userInfo.isManagedProfile();
+        synchronized (mLock) {
+            mUserCache.put(userId, b);
+        }
+        return b;
+    }
+}
diff --git a/services/core/java/com/android/server/pm/WatchedIntentResolver.java b/services/core/java/com/android/server/pm/WatchedIntentResolver.java
index 1c3d884..daa50ab 100644
--- a/services/core/java/com/android/server/pm/WatchedIntentResolver.java
+++ b/services/core/java/com/android/server/pm/WatchedIntentResolver.java
@@ -18,8 +18,10 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.content.IntentFilter;
 
 import com.android.server.IntentResolver;
+import com.android.server.pm.snapshot.PackageDataSnapshot;
 import com.android.server.utils.Snappable;
 import com.android.server.utils.Watchable;
 import com.android.server.utils.WatchableImpl;
@@ -99,8 +101,8 @@
     }
 
     @Override
-    public void addFilter(F f) {
-        super.addFilter(f);
+    public void addFilter(@Nullable PackageDataSnapshot snapshot, F f) {
+        super.addFilter(snapshot, f);
         f.registerObserver(mWatcher);
         onChanged();
     }
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
index ed47bfb7..87494a6 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
@@ -3364,7 +3364,7 @@
             // For updated system applications, a privileged/oem permission
             // is granted only if it had been defined by the original application.
             if (pkgSetting.getTransientState().isUpdatedSystemApp()) {
-                final PackageSetting disabledPs = mPackageManagerInt
+                final PackageStateInternal disabledPs = mPackageManagerInt
                         .getDisabledSystemPackage(pkg.getPackageName());
                 final AndroidPackage disabledPkg = disabledPs == null ? null : disabledPs.getPkg();
                 if (disabledPkg != null
@@ -3762,7 +3762,7 @@
             return;
         }
 
-        PackageSetting disabledPs = mPackageManagerInt.getDisabledSystemPackage(
+        PackageStateInternal disabledPs = mPackageManagerInt.getDisabledSystemPackage(
                 pkg.getPackageName());
         boolean isShadowingSystemPkg = disabledPs != null && disabledPs.getAppId() == pkg.getUid();
 
@@ -4104,7 +4104,7 @@
     }
 
     private boolean isPermissionDeclaredByDisabledSystemPkg(@NonNull Permission permission) {
-        final PackageSetting disabledSourcePs = mPackageManagerInt.getDisabledSystemPackage(
+        final PackageStateInternal disabledSourcePs = mPackageManagerInt.getDisabledSystemPackage(
                     permission.getPackageName());
         if (disabledSourcePs != null && disabledSourcePs.getPkg() != null) {
             final String permissionName = permission.getName();
diff --git a/services/core/java/com/android/server/pm/pkg/SuspendParams.java b/services/core/java/com/android/server/pm/pkg/SuspendParams.java
index d24ce96..0926ba2 100644
--- a/services/core/java/com/android/server/pm/pkg/SuspendParams.java
+++ b/services/core/java/com/android/server/pm/pkg/SuspendParams.java
@@ -46,27 +46,13 @@
     private final PersistableBundle appExtras;
     private final PersistableBundle launcherExtras;
 
-    private SuspendParams(SuspendDialogInfo dialogInfo, PersistableBundle appExtras,
+    public SuspendParams(SuspendDialogInfo dialogInfo, PersistableBundle appExtras,
             PersistableBundle launcherExtras) {
         this.dialogInfo = dialogInfo;
         this.appExtras = appExtras;
         this.launcherExtras = launcherExtras;
     }
 
-    /**
-     * Returns a {@link SuspendParams} object with the given fields. Returns {@code null} if all
-     * the fields are {@code null}.
-     *
-     * @return A {@link SuspendParams} object or {@code null}.
-     */
-    public static SuspendParams getInstanceOrNull(SuspendDialogInfo dialogInfo,
-            PersistableBundle appExtras, PersistableBundle launcherExtras) {
-        if (dialogInfo == null && appExtras == null && launcherExtras == null) {
-            return null;
-        }
-        return new SuspendParams(dialogInfo, appExtras, launcherExtras);
-    }
-
     @Override
     public boolean equals(@Nullable Object obj) {
         if (this == obj) {
@@ -170,7 +156,7 @@
             Slog.e(LOG_TAG, "Exception while trying to parse SuspendParams,"
                     + " some fields may default", e);
         }
-        return getInstanceOrNull(readDialogInfo, readAppExtras, readLauncherExtras);
+        return new SuspendParams(readDialogInfo, readAppExtras, readLauncherExtras);
     }
 
     public SuspendDialogInfo getDialogInfo() {
diff --git a/services/core/java/com/android/server/pm/ComponentResolver.java b/services/core/java/com/android/server/pm/resolution/ComponentResolver.java
similarity index 70%
rename from services/core/java/com/android/server/pm/ComponentResolver.java
rename to services/core/java/com/android/server/pm/resolution/ComponentResolver.java
index aa393d2..cf9370d 100644
--- a/services/core/java/com/android/server/pm/ComponentResolver.java
+++ b/services/core/java/com/android/server/pm/resolution/ComponentResolver.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,16 +14,16 @@
  * limitations under the License.
  */
 
-package com.android.server.pm;
+package com.android.server.pm.resolution;
 
 import static android.content.pm.PackageManager.INSTALL_FAILED_CONFLICTING_PROVIDER;
-import static android.content.pm.PackageManagerInternal.PACKAGE_SETUP_WIZARD;
 
 import static com.android.server.pm.PackageManagerService.DEBUG_PACKAGE_SCANNING;
 import static com.android.server.pm.PackageManagerService.DEBUG_REMOVE;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UserIdInt;
 import android.content.ComponentName;
 import android.content.Intent;
 import android.content.IntentFilter;
@@ -32,11 +32,9 @@
 import android.content.pm.AuxiliaryResolveInfo;
 import android.content.pm.InstantAppResolveInfo;
 import android.content.pm.PackageManager;
-import android.content.pm.PackageManagerInternal;
 import android.content.pm.ProviderInfo;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
-import android.os.UserHandle;
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.DebugUtils;
@@ -46,14 +44,18 @@
 import android.util.Slog;
 
 import com.android.internal.annotations.GuardedBy;
-import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.ArrayUtils;
 import com.android.server.IntentResolver;
+import com.android.server.pm.Computer;
+import com.android.server.pm.DumpState;
+import com.android.server.pm.PackageManagerException;
+import com.android.server.pm.UserManagerService;
+import com.android.server.pm.UserNeedsBadgingCache;
 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.pm.parsing.pkg.AndroidPackageUtils;
 import com.android.server.pm.pkg.PackageStateInternal;
+import com.android.server.pm.pkg.PackageStateUtils;
 import com.android.server.pm.pkg.PackageUserStateInternal;
 import com.android.server.pm.pkg.component.ComponentMutateUtils;
 import com.android.server.pm.pkg.component.ParsedActivity;
@@ -63,12 +65,13 @@
 import com.android.server.pm.pkg.component.ParsedProvider;
 import com.android.server.pm.pkg.component.ParsedProviderImpl;
 import com.android.server.pm.pkg.component.ParsedService;
+import com.android.server.pm.snapshot.PackageDataSnapshot;
 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;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.Iterator;
@@ -79,9 +82,7 @@
 import java.util.function.Function;
 
 /** Resolves all Android component types [activities, services, providers and receivers]. */
-public class ComponentResolver
-        extends WatchableImpl
-        implements Snappable {
+public class ComponentResolver extends ComponentResolverLocked implements Snappable {
     private static final boolean DEBUG = false;
     private static final String TAG = "PackageManager";
     private static final boolean DEBUG_FILTERS = false;
@@ -104,7 +105,7 @@
         PROTECTED_ACTIONS.add(Intent.ACTION_VIEW);
     }
 
-    static final Comparator<ResolveInfo> RESOLVE_PRIORITY_SORTER = (r1, r2) -> {
+    public static final Comparator<ResolveInfo> RESOLVE_PRIORITY_SORTER = (r1, r2) -> {
         int v1 = r1.priority;
         int v2 = r2.priority;
         //System.out.println("Comparing: q1=" + q1 + " q2=" + q2);
@@ -140,62 +141,8 @@
         return 0;
     };
 
-    private static UserManagerService sUserManager;
-    private static PackageManagerInternal sPackageManagerInternal;
-
-    /**
-     * Locking within package manager is going to get worse before it gets better. Currently,
-     * we need to share the {@link PackageManagerService} lock to prevent deadlocks. This occurs
-     * because in order to safely query the resolvers, we need to obtain this lock. However,
-     * during resolution, we call into the {@link PackageManagerService}. This is _not_ to
-     * operate on data controlled by the service proper, but, to check the state of package
-     * settings [contained in a {@link Settings} object]. However, the {@link Settings} object
-     * happens to be protected by the main {@link PackageManagerService} lock.
-     * <p>
-     * There are a couple potential solutions.
-     * <ol>
-     * <li>Split all of our locks into reader/writer locks. This would allow multiple,
-     * simultaneous read operations and means we don't have to be as cautious about lock
-     * layering. Only when we want to perform a write operation will we ever be in a
-     * position to deadlock the system.</li>
-     * <li>Use the same lock across all classes within the {@code com.android.server.pm}
-     * package. By unifying the lock object, we remove any potential lock layering issues
-     * within the package manager. However, we already have a sense that this lock is
-     * heavily contended and merely adding more dependencies on it will have further
-     * impact.</li>
-     * <li>Implement proper lock ordering within the package manager. By defining the
-     * relative layer of the component [eg. {@link PackageManagerService} is at the top.
-     * Somewhere in the middle would be {@link ComponentResolver}. At the very bottom
-     * would be {@link Settings}.] The ordering would allow higher layers to hold their
-     * lock while calling down. Lower layers must relinquish their lock before calling up.
-     * Since {@link Settings} would live at the lowest layer, the {@link ComponentResolver}
-     * would be able to hold its lock while checking the package setting state.</li>
-     * </ol>
-     */
-    private final PackageManagerTracedLock mLock;
-
-    /** All available activities, for your resolving pleasure. */
-    @GuardedBy("mLock")
-    private final ActivityIntentResolver mActivities;
-
-    /** All available providers, for your resolving pleasure. */
-    @GuardedBy("mLock")
-    private final ProviderIntentResolver mProviders;
-
-    /** All available receivers, for your resolving pleasure. */
-    @GuardedBy("mLock")
-    private final ReceiverIntentResolver mReceivers;
-
-    /** All available services, for your resolving pleasure. */
-    @GuardedBy("mLock")
-    private final ServiceIntentResolver mServices;
-
-    /** Mapping from provider authority [first directory in content URI codePath) to provider. */
-    @GuardedBy("mLock")
-    private final ArrayMap<String, ParsedProvider> mProvidersByAuthority;
-
     /** Whether or not processing protected filters should be deferred. */
-    private boolean mDeferProtectedFilters = true;
+    boolean mDeferProtectedFilters = true;
 
     /**
      * Tracks high priority intent filters for protected actions. During boot, certain
@@ -210,348 +157,62 @@
      * This is a pair of component package name to actual filter, because we don't store the
      * name inside the filter. It's technically independent of the component it's contained in.
      */
-    private List<Pair<ParsedMainComponent, ParsedIntentInfo>> mProtectedFilters;
+    List<Pair<ParsedMainComponent, ParsedIntentInfo>> mProtectedFilters;
 
-    ComponentResolver(UserManagerService userManager,
-            PackageManagerInternal packageManagerInternal,
-            PackageManagerTracedLock lock) {
-        sPackageManagerInternal = packageManagerInternal;
-        sUserManager = userManager;
-        mLock = lock;
-
-        mActivities = new ActivityIntentResolver();
-        mProviders = new ProviderIntentResolver();
-        mReceivers = new ReceiverIntentResolver();
-        mServices = new ServiceIntentResolver();
+    public ComponentResolver(@NonNull UserManagerService userManager,
+            @NonNull UserNeedsBadgingCache userNeedsBadgingCache) {
+        super(userManager);
+        mActivities = new ActivityIntentResolver(userManager, userNeedsBadgingCache);
+        mProviders = new ProviderIntentResolver(userManager);
+        mReceivers = new ReceiverIntentResolver(userManager, userNeedsBadgingCache);
+        mServices = new ServiceIntentResolver(userManager);
         mProvidersByAuthority = new ArrayMap<>();
         mDeferProtectedFilters = true;
 
-        mSnapshot = new SnapshotCache<ComponentResolver>(this, this) {
+        mSnapshot = new SnapshotCache<ComponentResolverApi>(this, this) {
                 @Override
-                public ComponentResolver createSnapshot() {
-                    return new ComponentResolver(mSource);
+                public ComponentResolverApi createSnapshot() {
+                    return new ComponentResolverSnapshot(ComponentResolver.this,
+                            userNeedsBadgingCache);
                 }};
     }
 
-    // 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;
+    final SnapshotCache<ComponentResolverApi> mSnapshot;
 
     /**
      * Create a snapshot.
      */
-    public ComponentResolver snapshot() {
+    public ComponentResolverApi snapshot() {
         return mSnapshot.snapshot();
     }
 
-
-    /** Returns the given activity */
-    @Nullable
-    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
-    public ParsedActivity getActivity(@NonNull ComponentName component) {
-        synchronized (mLock) {
-            return mActivities.mActivities.get(component);
-        }
-    }
-
-    /** Returns the given provider */
-    @Nullable
-    ParsedProvider getProvider(@NonNull ComponentName component) {
-        synchronized (mLock) {
-            return mProviders.mProviders.get(component);
-        }
-    }
-
-    /** Returns the given receiver */
-    @Nullable
-    ParsedActivity getReceiver(@NonNull ComponentName component) {
-        synchronized (mLock) {
-            return mReceivers.mActivities.get(component);
-        }
-    }
-
-    /** Returns the given service */
-    @Nullable
-    ParsedService getService(@NonNull ComponentName component) {
-        synchronized (mLock) {
-            return mServices.mServices.get(component);
-        }
-    }
-
-    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
-    public boolean componentExists(@NonNull ComponentName componentName) {
-        synchronized (mLock) {
-            ParsedMainComponent component = mActivities.mActivities.get(componentName);
-            if (component != null) {
-                return true;
-            }
-            component = mReceivers.mActivities.get(componentName);
-            if (component != null) {
-                return true;
-            }
-            component = mServices.mServices.get(componentName);
-            if (component != null) {
-                return true;
-            }
-            return mProviders.mProviders.get(componentName) != null;
-        }
-    }
-
-    @Nullable
-    List<ResolveInfo> queryActivities(Intent intent, String resolvedType, long flags,
-            int userId) {
-        synchronized (mLock) {
-            return mActivities.queryIntent(intent, resolvedType, flags, userId);
-        }
-    }
-
-    @Nullable
-    List<ResolveInfo> queryActivities(Intent intent, String resolvedType, long flags,
-            List<ParsedActivity> activities, int userId) {
-        synchronized (mLock) {
-            return mActivities.queryIntentForPackage(
-                    intent, resolvedType, flags, activities, userId);
-        }
-    }
-
-    @Nullable
-    List<ResolveInfo> queryProviders(Intent intent, String resolvedType, long flags, int userId) {
-        synchronized (mLock) {
-            return mProviders.queryIntent(intent, resolvedType, flags, userId);
-        }
-    }
-
-    @Nullable
-    List<ResolveInfo> queryProviders(Intent intent, String resolvedType, long flags,
-            List<ParsedProvider> providers, int userId) {
-        synchronized (mLock) {
-            return mProviders.queryIntentForPackage(intent, resolvedType, flags, providers, userId);
-        }
-    }
-
-    @Nullable
-    List<ProviderInfo> queryProviders(String processName, String metaDataKey, int uid, long flags,
-            int userId) {
-        if (!sUserManager.exists(userId)) {
-            return null;
-        }
-        List<ProviderInfo> providerList = null;
-        CachedApplicationInfoGenerator appInfoGenerator = null;
-        synchronized (mLock) {
-            for (int i = mProviders.mProviders.size() - 1; i >= 0; --i) {
-                final ParsedProvider p = mProviders.mProviders.valueAt(i);
-                if (p.getAuthority() == null) {
-                    continue;
-                }
-
-                final PackageStateInternal ps =
-                        sPackageManagerInternal.getPackageStateInternal(p.getPackageName());
-                if (ps == null) {
-                    continue;
-                }
-
-                AndroidPackage pkg = sPackageManagerInternal.getPackage(p.getPackageName());
-                if (pkg == null) {
-                    continue;
-                }
-
-                if (processName != null && (!p.getProcessName().equals(processName)
-                        || !UserHandle.isSameApp(pkg.getUid(), uid))) {
-                    continue;
-                }
-                // See PM.queryContentProviders()'s javadoc for why we have the metaData parameter.
-                if (metaDataKey != null && !p.getMetaData().containsKey(metaDataKey)) {
-                    continue;
-                }
-                if (appInfoGenerator == null) {
-                    appInfoGenerator = new CachedApplicationInfoGenerator();
-                }
-                final PackageUserStateInternal state = ps.getUserStateOrDefault(userId);
-                final ApplicationInfo appInfo =
-                        appInfoGenerator.generate(pkg, flags, state, userId, ps);
-                if (appInfo == null) {
-                    continue;
-                }
-
-                final ProviderInfo info = PackageInfoUtils.generateProviderInfo(
-                        pkg, p, flags, state, appInfo, userId, ps);
-                if (info == null) {
-                    continue;
-                }
-                if (providerList == null) {
-                    providerList = new ArrayList<>(i + 1);
-                }
-                providerList.add(info);
-            }
-        }
-        return providerList;
-    }
-
-    @Nullable
-    ProviderInfo queryProvider(String authority, long flags, int userId) {
-        synchronized (mLock) {
-            final ParsedProvider p = mProvidersByAuthority.get(authority);
-            if (p == null) {
-                return null;
-            }
-            final PackageStateInternal ps =
-                    sPackageManagerInternal.getPackageStateInternal(p.getPackageName());
-            if (ps == null) {
-                return null;
-            }
-            final AndroidPackage pkg = sPackageManagerInternal.getPackage(p.getPackageName());
-            if (pkg == null) {
-                return null;
-            }
-            final PackageUserStateInternal state = ps.getUserStateOrDefault(userId);
-            ApplicationInfo appInfo = PackageInfoUtils.generateApplicationInfo(
-                    pkg, flags, state, userId, ps);
-            if (appInfo == null) {
-                return null;
-            }
-            return PackageInfoUtils.generateProviderInfo(pkg, p, flags, state, appInfo, userId, ps);
-        }
-    }
-
-    void querySyncProviders(List<String> outNames, List<ProviderInfo> outInfo, boolean safeMode,
-            int userId) {
-        synchronized (mLock) {
-            CachedApplicationInfoGenerator appInfoGenerator = null;
-            for (int i = mProvidersByAuthority.size() - 1; i >= 0; --i) {
-                final ParsedProvider p = mProvidersByAuthority.valueAt(i);
-                if (!p.isSyncable()) {
-                    continue;
-                }
-
-                final PackageStateInternal ps =
-                        sPackageManagerInternal.getPackageStateInternal(p.getPackageName());
-                if (ps == null) {
-                    continue;
-                }
-
-                final AndroidPackage pkg = sPackageManagerInternal.getPackage(p.getPackageName());
-                if (pkg == null) {
-                    continue;
-                }
-
-                if (safeMode && !pkg.isSystem()) {
-                    continue;
-                }
-                if (appInfoGenerator == null) {
-                    appInfoGenerator = new CachedApplicationInfoGenerator();
-                }
-                final PackageUserStateInternal state = ps.getUserStateOrDefault(userId);
-                final ApplicationInfo appInfo =
-                        appInfoGenerator.generate(pkg, 0, state, userId, ps);
-                if (appInfo == null) {
-                    continue;
-                }
-
-                final ProviderInfo info = PackageInfoUtils.generateProviderInfo(
-                        pkg, p, 0, state, appInfo, userId, ps);
-                if (info == null) {
-                    continue;
-                }
-                outNames.add(mProvidersByAuthority.keyAt(i));
-                outInfo.add(info);
-            }
-        }
-    }
-
-    @Nullable
-    List<ResolveInfo> queryReceivers(Intent intent, String resolvedType, long flags, int userId) {
-        synchronized (mLock) {
-            return mReceivers.queryIntent(intent, resolvedType, flags, userId);
-        }
-    }
-
-    @Nullable
-    List<ResolveInfo> queryReceivers(Intent intent, String resolvedType, long flags,
-            List<ParsedActivity> receivers, int userId) {
-        synchronized (mLock) {
-            return mReceivers.queryIntentForPackage(intent, resolvedType, flags, receivers, userId);
-        }
-    }
-
-    @Nullable
-    List<ResolveInfo> queryServices(Intent intent, String resolvedType, long flags, int userId) {
-        synchronized (mLock) {
-            return mServices.queryIntent(intent, resolvedType, flags, userId);
-        }
-    }
-
-    @Nullable
-    List<ResolveInfo> queryServices(Intent intent, String resolvedType, long flags,
-            List<ParsedService> services, int userId) {
-        synchronized (mLock) {
-            return mServices.queryIntentForPackage(intent, resolvedType, flags, services, userId);
-        }
-    }
-
-    /** Returns {@code true} if the given activity is defined by some package */
-    boolean isActivityDefined(ComponentName component) {
-        synchronized (mLock) {
-            return mActivities.mActivities.get(component) != null;
-        }
-    }
-
-    /** Asserts none of the providers defined in the given package haven't already been defined. */
-    void assertProvidersNotDefined(AndroidPackage pkg) throws PackageManagerException {
-        synchronized (mLock) {
-            assertProvidersNotDefinedLocked(pkg);
-        }
-    }
-
     /** Add all components defined in the given package to the internal structures. */
-    void addAllComponents(AndroidPackage pkg, boolean chatty) {
+    public void addAllComponents(AndroidPackage pkg, boolean chatty,
+            @Nullable String setupWizardPackage, @NonNull Computer computer) {
         final ArrayList<Pair<ParsedActivity, ParsedIntentInfo>> newIntents = new ArrayList<>();
         synchronized (mLock) {
-            addActivitiesLocked(pkg, newIntents, chatty);
-            addReceiversLocked(pkg, chatty);
-            addProvidersLocked(pkg, chatty);
-            addServicesLocked(pkg, chatty);
+            addActivitiesLocked(computer, pkg, newIntents, chatty);
+            addReceiversLocked(computer, pkg, chatty);
+            addProvidersLocked(computer, pkg, chatty);
+            addServicesLocked(computer, pkg, chatty);
             onChanged();
         }
-        // expect single setupwizard package
-        final String setupWizardPackage = ArrayUtils.firstOrNull(
-                sPackageManagerInternal.getKnownPackageNames(
-                        PACKAGE_SETUP_WIZARD, UserHandle.USER_SYSTEM));
 
         for (int i = newIntents.size() - 1; i >= 0; --i) {
             final Pair<ParsedActivity, ParsedIntentInfo> pair = newIntents.get(i);
-            final PackageSetting disabledPkgSetting = (PackageSetting) sPackageManagerInternal
+            final PackageStateInternal disabledPkgSetting = computer
                     .getDisabledSystemPackage(pair.first.getPackageName());
             final AndroidPackage disabledPkg =
                     disabledPkgSetting == null ? null : disabledPkgSetting.getPkg();
             final List<ParsedActivity> systemActivities =
                     disabledPkg != null ? disabledPkg.getActivities() : null;
-            adjustPriority(systemActivities, pair.first, pair.second, setupWizardPackage);
+            adjustPriority(computer, systemActivities, pair.first, pair.second, setupWizardPackage);
             onChanged();
         }
     }
 
     /** Removes all components defined in the given package from the internal structures. */
-    void removeAllComponents(AndroidPackage pkg, boolean chatty) {
+    public void removeAllComponents(AndroidPackage pkg, boolean chatty) {
         synchronized (mLock) {
             removeAllComponentsLocked(pkg, chatty);
             onChanged();
@@ -562,7 +223,7 @@
      * Reprocess any protected filters that have been deferred. At this point, we've scanned
      * all of the filters defined on the /system partition and know the special components.
      */
-    void fixProtectedFilterPriorities() {
+    public void fixProtectedFilterPriorities(@Nullable String setupWizardPackage) {
         synchronized (mLock) {
             if (!mDeferProtectedFilters) {
                 return;
@@ -576,11 +237,6 @@
                     mProtectedFilters;
             mProtectedFilters = null;
 
-            // 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");
@@ -615,7 +271,7 @@
         }
     }
 
-    void dumpActivityResolvers(PrintWriter pw, DumpState dumpState, String packageName) {
+    public void dumpActivityResolvers(PrintWriter pw, DumpState dumpState, String packageName) {
         synchronized (mLock) {
             if (mActivities.dump(pw, dumpState.getTitlePrinted() ? "\nActivity Resolver Table:"
                             : "Activity Resolver Table:", "  ", packageName,
@@ -625,7 +281,7 @@
         }
     }
 
-    void dumpProviderResolvers(PrintWriter pw, DumpState dumpState, String packageName) {
+    public void dumpProviderResolvers(PrintWriter pw, DumpState dumpState, String packageName) {
         synchronized (mLock) {
             if (mProviders.dump(pw, dumpState.getTitlePrinted() ? "\nProvider Resolver Table:"
                             : "Provider Resolver Table:", "  ", packageName,
@@ -635,7 +291,7 @@
         }
     }
 
-    void dumpReceiverResolvers(PrintWriter pw, DumpState dumpState, String packageName) {
+    public void dumpReceiverResolvers(PrintWriter pw, DumpState dumpState, String packageName) {
         synchronized (mLock) {
             if (mReceivers.dump(pw, dumpState.getTitlePrinted() ? "\nReceiver Resolver Table:"
                             : "Receiver Resolver Table:", "  ", packageName,
@@ -645,7 +301,7 @@
         }
     }
 
-    void dumpServiceResolvers(PrintWriter pw, DumpState dumpState, String packageName) {
+    public void dumpServiceResolvers(PrintWriter pw, DumpState dumpState, String packageName) {
         synchronized (mLock) {
             if (mServices.dump(pw, dumpState.getTitlePrinted() ? "\nService Resolver Table:"
                             : "Service Resolver Table:", "  ", packageName,
@@ -655,7 +311,8 @@
         }
     }
 
-    void dumpContentProviders(PrintWriter pw, DumpState dumpState, String packageName) {
+    public void dumpContentProviders(@NonNull Computer computer, PrintWriter pw,
+            DumpState dumpState, String packageName) {
         synchronized (mLock) {
             boolean printedSomething = false;
             for (ParsedProvider p : mProviders.mProviders.values()) {
@@ -695,7 +352,7 @@
                 pw.print("    ");
                 pw.println(p.toString());
 
-                AndroidPackage pkg = sPackageManagerInternal.getPackage(p.getPackageName());
+                AndroidPackage pkg = computer.getPackage(p.getPackageName());
 
                 if (pkg != null) {
                     pw.print("      applicationInfo=");
@@ -705,7 +362,7 @@
         }
     }
 
-    void dumpServicePermissions(PrintWriter pw, DumpState dumpState) {
+    public void dumpServicePermissions(PrintWriter pw, DumpState dumpState) {
         synchronized (mLock) {
             if (dumpState.onTitlePrinted()) pw.println();
             pw.println("Service permissions:");
@@ -728,13 +385,13 @@
     }
 
     @GuardedBy("mLock")
-    private void addActivitiesLocked(AndroidPackage pkg,
+    private void addActivitiesLocked(@NonNull Computer computer, AndroidPackage pkg,
             List<Pair<ParsedActivity, ParsedIntentInfo>> newIntents, boolean chatty) {
         final int activitiesSize = ArrayUtils.size(pkg.getActivities());
         StringBuilder r = null;
         for (int i = 0; i < activitiesSize; i++) {
             ParsedActivity a = pkg.getActivities().get(i);
-            mActivities.addActivity(a, "activity", newIntents);
+            mActivities.addActivity(computer, a, "activity", newIntents);
             if (DEBUG_PACKAGE_SCANNING && chatty) {
                 if (r == null) {
                     r = new StringBuilder(256);
@@ -750,12 +407,12 @@
     }
 
     @GuardedBy("mLock")
-    private void addProvidersLocked(AndroidPackage pkg, boolean chatty) {
+    private void addProvidersLocked(@NonNull Computer computer, AndroidPackage pkg, boolean chatty) {
         final int providersSize = ArrayUtils.size(pkg.getProviders());
         StringBuilder r = null;
         for (int i = 0; i < providersSize; i++) {
             ParsedProvider p = pkg.getProviders().get(i);
-            mProviders.addProvider(p);
+            mProviders.addProvider(computer, p);
             if (p.getAuthority() != null) {
                 String[] names = p.getAuthority().split(";");
 
@@ -814,12 +471,12 @@
     }
 
     @GuardedBy("mLock")
-    private void addReceiversLocked(AndroidPackage pkg, boolean chatty) {
+    private void addReceiversLocked(@NonNull Computer computer, AndroidPackage pkg, boolean chatty) {
         final int receiversSize = ArrayUtils.size(pkg.getReceivers());
         StringBuilder r = null;
         for (int i = 0; i < receiversSize; i++) {
             ParsedActivity a = pkg.getReceivers().get(i);
-            mReceivers.addActivity(a, "receiver", null);
+            mReceivers.addActivity(computer, a, "receiver", null);
             if (DEBUG_PACKAGE_SCANNING && chatty) {
                 if (r == null) {
                     r = new StringBuilder(256);
@@ -835,12 +492,12 @@
     }
 
     @GuardedBy("mLock")
-    private void addServicesLocked(AndroidPackage pkg, boolean chatty) {
+    private void addServicesLocked(@NonNull Computer computer, AndroidPackage pkg, boolean chatty) {
         final int servicesSize = ArrayUtils.size(pkg.getServices());
         StringBuilder r = null;
         for (int i = 0; i < servicesSize; i++) {
             ParsedService s = pkg.getServices().get(i);
-            mServices.addService(s);
+            mServices.addService(computer, s);
             if (DEBUG_PACKAGE_SCANNING && chatty) {
                 if (r == null) {
                     r = new StringBuilder(256);
@@ -945,8 +602,8 @@
      * <em>NOTE:</em> There is one exception. For security reasons, the setup wizard is
      * allowed to obtain any priority on any action.
      */
-    private void adjustPriority(List<ParsedActivity> systemActivities, ParsedActivity activity,
-            ParsedIntentInfo intentInfo, String setupWizardPackage) {
+    private void adjustPriority(@NonNull Computer computer, List<ParsedActivity> systemActivities,
+            ParsedActivity activity, ParsedIntentInfo intentInfo, String setupWizardPackage) {
         // nothing to do; priority is fine as-is
         IntentFilter intentFilter = intentInfo.getIntentFilter();
         if (intentFilter.getPriority() <= 0) {
@@ -954,7 +611,7 @@
         }
 
         String packageName = activity.getPackageName();
-        AndroidPackage pkg = sPackageManagerInternal.getPackage(packageName);
+        AndroidPackage pkg = computer.getPackage(packageName);
 
         final boolean privilegedApp = pkg.isPrivileged();
         String className = activity.getClassName();
@@ -1231,28 +888,30 @@
         }
     }
 
-    @GuardedBy("mLock")
-    private void assertProvidersNotDefinedLocked(AndroidPackage pkg)
+    /** Asserts none of the providers defined in the given package haven't already been defined. */
+    public void assertProvidersNotDefined(@NonNull AndroidPackage pkg)
             throws PackageManagerException {
-        final int providersSize = ArrayUtils.size(pkg.getProviders());
-        int i;
-        for (i = 0; i < providersSize; i++) {
-            ParsedProvider p = pkg.getProviders().get(i);
-            if (p.getAuthority() != null) {
-                final String[] names = p.getAuthority().split(";");
-                for (int j = 0; j < names.length; j++) {
-                    if (mProvidersByAuthority.containsKey(names[j])) {
-                        final ParsedProvider other = mProvidersByAuthority.get(names[j]);
-                        final String otherPackageName =
-                                (other != null && other.getComponentName() != null)
-                                        ? other.getComponentName().getPackageName() : "?";
-                        // if we're installing over the same already-installed package, this is ok
-                        if (!otherPackageName.equals(pkg.getPackageName())) {
-                            throw new PackageManagerException(
-                                    INSTALL_FAILED_CONFLICTING_PROVIDER,
-                                    "Can't install because provider name " + names[j]
-                                            + " (in package " + pkg.getPackageName()
-                                            + ") is already used by " + otherPackageName);
+        synchronized (mLock) {
+            final int providersSize = ArrayUtils.size(pkg.getProviders());
+            int i;
+            for (i = 0; i < providersSize; i++) {
+                ParsedProvider p = pkg.getProviders().get(i);
+                if (p.getAuthority() != null) {
+                    final String[] names = p.getAuthority().split(";");
+                    for (int j = 0; j < names.length; j++) {
+                        if (mProvidersByAuthority.containsKey(names[j])) {
+                            final ParsedProvider other = mProvidersByAuthority.get(names[j]);
+                            final String otherPackageName =
+                                    (other != null && other.getComponentName() != null)
+                                            ? other.getComponentName().getPackageName() : "?";
+                            // if installing over the same already-installed package,this is ok
+                            if (!otherPackageName.equals(pkg.getPackageName())) {
+                                throw new PackageManagerException(
+                                        INSTALL_FAILED_CONFLICTING_PROVIDER,
+                                        "Can't install because provider name " + names[j]
+                                                + " (in package " + pkg.getPackageName()
+                                                + ") is already used by " + otherPackageName);
+                            }
                         }
                     }
                 }
@@ -1266,22 +925,31 @@
         private final ArrayMap<String, F[]> mMimeGroupToFilter = new ArrayMap<>();
         private boolean mIsUpdatingMimeGroup = false;
 
+        @NonNull
+        protected final UserManagerService mUserManager;
+
         // Default constructor
-        MimeGroupsAwareIntentResolver() {
+        MimeGroupsAwareIntentResolver(@NonNull UserManagerService userManager) {
+            mUserManager = userManager;
         }
 
         // Copy constructor used in creating snapshots
-        MimeGroupsAwareIntentResolver(MimeGroupsAwareIntentResolver<F, R> orig) {
+        MimeGroupsAwareIntentResolver(MimeGroupsAwareIntentResolver<F, R> orig,
+                @NonNull UserManagerService userManager) {
+            mUserManager = userManager;
             copyFrom(orig);
             copyInto(mMimeGroupToFilter, orig.mMimeGroupToFilter);
             mIsUpdatingMimeGroup = orig.mIsUpdatingMimeGroup;
         }
 
         @Override
-        public void addFilter(F f) {
+        public void addFilter(@Nullable PackageDataSnapshot snapshot, F f) {
             IntentFilter intentFilter = getIntentFilter(f);
-            applyMimeGroups(f);
-            super.addFilter(f);
+            // We assume Computer is available for this class and all subclasses. Because this class
+            // uses subclass method override to handle logic, the Computer parameter must be in the
+            // base, leading to this odd nullability.
+            applyMimeGroups((Computer) snapshot, f);
+            super.addFilter(snapshot, f);
 
             if (!mIsUpdatingMimeGroup) {
                 register_intent_filter(f, intentFilter.mimeGroupsIterator(), mMimeGroupToFilter,
@@ -1309,7 +977,8 @@
          * @param mimeGroup MIME group to update
          * @return true, if any intent filters were changed due to this update
          */
-        public boolean updateMimeGroup(String packageName, String mimeGroup) {
+        public boolean updateMimeGroup(@NonNull Computer computer, String packageName,
+                String mimeGroup) {
             F[] filters = mMimeGroupToFilter.get(mimeGroup);
             int n = filters != null ? filters.length : 0;
 
@@ -1318,18 +987,18 @@
             F filter;
             for (int i = 0; i < n && (filter = filters[i]) != null; i++) {
                 if (isPackageForFilter(packageName, filter)) {
-                    hasChanges |= updateFilter(filter);
+                    hasChanges |= updateFilter(computer, filter);
                 }
             }
             mIsUpdatingMimeGroup = false;
             return hasChanges;
         }
 
-        private boolean updateFilter(F f) {
+        private boolean updateFilter(@NonNull Computer computer, F f) {
             IntentFilter filter = getIntentFilter(f);
             List<String> oldTypes = filter.dataTypes();
             removeFilter(f);
-            addFilter(f);
+            addFilter(computer, f);
             List<String> newTypes = filter.dataTypes();
             return !equalLists(oldTypes, newTypes);
         }
@@ -1350,16 +1019,18 @@
             return first.equals(second);
         }
 
-        private void applyMimeGroups(F f) {
+        private void applyMimeGroups(@NonNull Computer computer, F f) {
             IntentFilter filter = getIntentFilter(f);
 
             for (int i = filter.countMimeGroups() - 1; i >= 0; i--) {
-                List<String> mimeTypes = sPackageManagerInternal.getMimeGroup(
-                        f.first.getPackageName(), filter.getMimeGroup(i));
+                final PackageStateInternal packageState = computer.getPackageStateInternal(
+                        f.first.getPackageName());
 
-                for (int typeIndex = mimeTypes.size() - 1; typeIndex >= 0; typeIndex--) {
-                    String mimeType = mimeTypes.get(typeIndex);
+                Collection<String> mimeTypes = packageState == null
+                        ? Collections.emptyList() : packageState.getMimeGroups()
+                        .get(filter.getMimeGroup(i));
 
+                for (String mimeType : mimeTypes) {
                     try {
                         filter.addDynamicDataType(mimeType);
                     } catch (IntentFilter.MalformedMimeTypeException e) {
@@ -1370,50 +1041,74 @@
                 }
             }
         }
+
+        @Override
+        protected boolean isFilterStopped(@Nullable PackageStateInternal packageState,
+                @UserIdInt int userId) {
+            if (!mUserManager.exists(userId)) {
+                return true;
+            }
+
+            if (packageState == null || packageState.getPkg() == null) {
+                return false;
+            }
+
+            // System apps are never considered stopped for purposes of
+            // filtering, because there may be no way for the user to
+            // actually re-launch them.
+            return !packageState.isSystem()
+                    && packageState.getUserStateOrDefault(userId).isStopped();
+        }
     }
 
-    private static class ActivityIntentResolver
+    public static class ActivityIntentResolver
             extends MimeGroupsAwareIntentResolver<Pair<ParsedActivity, ParsedIntentInfo>, ResolveInfo> {
 
+        @NonNull
+        private UserNeedsBadgingCache mUserNeedsBadging;
+
         // Default constructor
-        ActivityIntentResolver() {
+        ActivityIntentResolver(@NonNull UserManagerService userManager,
+                @NonNull UserNeedsBadgingCache userNeedsBadgingCache) {
+            super(userManager);
+            mUserNeedsBadging = userNeedsBadgingCache;
         }
 
         // Copy constructor used in creating snapshots
-        ActivityIntentResolver(ActivityIntentResolver orig) {
-            super(orig);
+        ActivityIntentResolver(@NonNull ActivityIntentResolver orig,
+                @NonNull UserManagerService userManager,
+                @NonNull UserNeedsBadgingCache userNeedsBadgingCache) {
+            super(orig, userManager);
             mActivities.putAll(orig.mActivities);
-            mFlags = orig.mFlags;
+            mUserNeedsBadging = userNeedsBadgingCache;
         }
 
         @Override
-        public List<ResolveInfo> queryIntent(Intent intent, String resolvedType,
-                boolean defaultOnly, int userId) {
-            if (!sUserManager.exists(userId)) return null;
-            mFlags = (defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0);
-            return super.queryIntent(intent, resolvedType, defaultOnly, userId);
+        public List<ResolveInfo> queryIntent(@NonNull PackageDataSnapshot snapshot, Intent intent,
+                String resolvedType, boolean defaultOnly, @UserIdInt int userId) {
+            if (!mUserManager.exists(userId)) return null;
+            long flags = (defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0);
+            return super.queryIntent(snapshot, intent, resolvedType, defaultOnly, userId, flags);
         }
 
-        List<ResolveInfo> queryIntent(Intent intent, String resolvedType, long flags,
-                int userId) {
-            if (!sUserManager.exists(userId)) {
+        List<ResolveInfo> queryIntent(@NonNull Computer computer, Intent intent,
+                String resolvedType, long flags, int userId) {
+            if (!mUserManager.exists(userId)) {
                 return null;
             }
-            mFlags = flags;
-            return super.queryIntent(intent, resolvedType,
-                    (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0,
-                    userId);
+            return super.queryIntent(computer, intent, resolvedType,
+                    (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, userId, flags);
         }
 
-        List<ResolveInfo> queryIntentForPackage(Intent intent, String resolvedType,
-                long flags, List<ParsedActivity> packageActivities, int userId) {
-            if (!sUserManager.exists(userId)) {
+        List<ResolveInfo> queryIntentForPackage(@NonNull Computer computer, Intent intent,
+                String resolvedType, long flags, List<ParsedActivity> packageActivities,
+                int userId) {
+            if (!mUserManager.exists(userId)) {
                 return null;
             }
             if (packageActivities == null) {
                 return Collections.emptyList();
             }
-            mFlags = flags;
             final boolean defaultOnly = (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0;
             final int activitiesSize = packageActivities.size();
             ArrayList<Pair<ParsedActivity, ParsedIntentInfo>[]> listCut =
@@ -1431,10 +1126,11 @@
                     listCut.add(array);
                 }
             }
-            return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut, userId);
+            return super.queryIntentFromList(computer, intent, resolvedType,
+                    defaultOnly, listCut, userId, flags);
         }
 
-        protected void addActivity(ParsedActivity a, String type,
+        protected void addActivity(@NonNull Computer computer, ParsedActivity a, String type,
                 List<Pair<ParsedActivity, ParsedIntentInfo>> newIntents) {
             mActivities.put(a.getComponentName(), a);
             if (DEBUG_SHOW_INFO) {
@@ -1455,7 +1151,7 @@
                 if (!intentFilter.debugCheck()) {
                     Log.w(TAG, "==> For Activity " + a.getName());
                 }
-                addFilter(Pair.create(a, intent));
+                addFilter(computer, Pair.create(a, intent));
             }
         }
 
@@ -1497,11 +1193,6 @@
         }
 
         @Override
-        protected boolean isFilterStopped(Pair<ParsedActivity, ParsedIntentInfo> filter, int userId) {
-            return ComponentResolver.isFilterStopped(filter, userId);
-        }
-
-        @Override
         protected boolean isPackageForFilter(String packageName,
                 Pair<ParsedActivity, ParsedIntentInfo> info) {
             return packageName.equals(info.first.getPackageName());
@@ -1517,43 +1208,35 @@
         }
 
         @Override
-        protected ResolveInfo newResult(Pair<ParsedActivity, ParsedIntentInfo> pair,
-                int match, int userId) {
+        protected ResolveInfo newResult(@NonNull Computer computer,
+                Pair<ParsedActivity, ParsedIntentInfo> pair, int match, int userId,
+                long customFlags) {
             ParsedActivity activity = pair.first;
             ParsedIntentInfo info = pair.second;
             IntentFilter intentFilter = info.getIntentFilter();
 
-            if (!sUserManager.exists(userId)) {
+            if (!mUserManager.exists(userId)) {
                 if (DEBUG) {
                     log("User doesn't exist", info, match, userId);
                 }
                 return null;
             }
 
-            AndroidPackage pkg = sPackageManagerInternal.getPackage(activity.getPackageName());
-            if (pkg == null) {
-                return null;
-            }
-
-            if (!sPackageManagerInternal.isEnabledAndMatches(activity, mFlags, userId)) {
+            final PackageStateInternal packageState =
+                    computer.getPackageStateInternal(activity.getPackageName());
+            if (packageState == null || packageState.getPkg() == null
+                    || !PackageStateUtils.isEnabledAndMatches(packageState, activity, customFlags,
+                    userId)) {
                 if (DEBUG) {
-                    log("!PackageManagerInternal.isEnabledAndMatches; mFlags="
-                            + DebugUtils.flagsToString(PackageManager.class, "MATCH_", mFlags),
+                    log("!PackageManagerInternal.isEnabledAndMatches; flags="
+                            + DebugUtils.flagsToString(PackageManager.class, "MATCH_", customFlags),
                             info, match, userId);
                 }
                 return null;
             }
-            PackageStateInternal ps =
-                    sPackageManagerInternal.getPackageStateInternal(activity.getPackageName());
-            if (ps == null) {
-                if (DEBUG) {
-                    log("info.activity.owner.mExtras == null", info, match, userId);
-                }
-                return null;
-            }
-            final PackageUserStateInternal userState = ps.getUserStateOrDefault(userId);
-            ActivityInfo ai = PackageInfoUtils.generateActivityInfo(pkg, activity, mFlags,
-                    userState, userId, ps);
+            final PackageUserStateInternal userState = packageState.getUserStateOrDefault(userId);
+            ActivityInfo ai = PackageInfoUtils.generateActivityInfo(packageState.getPkg(), activity,
+                    customFlags, userState, userId, packageState);
             if (ai == null) {
                 if (DEBUG) {
                     log("Failed to create ActivityInfo based on " + activity, info, match,
@@ -1562,15 +1245,15 @@
                 return null;
             }
             final boolean matchExplicitlyVisibleOnly =
-                    (mFlags & PackageManager.MATCH_EXPLICITLY_VISIBLE_ONLY) != 0;
+                    (customFlags & PackageManager.MATCH_EXPLICITLY_VISIBLE_ONLY) != 0;
             final boolean matchVisibleToInstantApp =
-                    (mFlags & PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY) != 0;
+                    (customFlags & PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY) != 0;
             final boolean componentVisible =
                     matchVisibleToInstantApp
                     && intentFilter.isVisibleToInstantApp()
                     && (!matchExplicitlyVisibleOnly
                             || intentFilter.isExplicitlyVisibleToInstantApp());
-            final boolean matchInstantApp = (mFlags & PackageManager.MATCH_INSTANT) != 0;
+            final boolean matchInstantApp = (customFlags & PackageManager.MATCH_INSTANT) != 0;
             // throw out filters that aren't visible to ephemeral apps
             if (matchVisibleToInstantApp && !(componentVisible || userState.isInstantApp())) {
                 if (DEBUG) {
@@ -1595,7 +1278,7 @@
             }
             // throw out instant app filters if updates are available; will trigger
             // instant app resolution
-            if (userState.isInstantApp() && ps.isUpdateAvailable()) {
+            if (userState.isInstantApp() && packageState.isUpdateAvailable()) {
                 if (DEBUG) {
                     log("Instant app update is available", info, match, userId);
                 }
@@ -1604,7 +1287,7 @@
             final ResolveInfo res =
                     new ResolveInfo(intentFilter.hasCategory(Intent.CATEGORY_BROWSABLE));
             res.activityInfo = ai;
-            if ((mFlags & PackageManager.GET_RESOLVED_FILTER) != 0) {
+            if ((customFlags & PackageManager.GET_RESOLVED_FILTER) != 0) {
                 res.filter = intentFilter;
             }
             res.handleAllWebDataURI = intentFilter.handleAllWebDataURI();
@@ -1617,7 +1300,7 @@
             res.isDefault = info.isHasDefault();
             res.labelRes = info.getLabelRes();
             res.nonLocalizedLabel = info.getNonLocalizedLabel();
-            if (sPackageManagerInternal.userNeedsBadging(userId)) {
+            if (mUserNeedsBadging.get(userId)) {
                 res.noResourceId = true;
             } else {
                 res.icon = info.getIcon();
@@ -1683,19 +1366,22 @@
         // ActivityIntentResolver.
         protected final ArrayMap<ComponentName, ParsedActivity> mActivities =
                 new ArrayMap<>();
-        private long mFlags;
     }
 
     // Both receivers and activities share a class, but point to different get methods
-    private static final class ReceiverIntentResolver extends ActivityIntentResolver {
+    public static final class ReceiverIntentResolver extends ActivityIntentResolver {
 
         // Default constructor
-        ReceiverIntentResolver() {
+        ReceiverIntentResolver(@NonNull UserManagerService userManager,
+                @NonNull UserNeedsBadgingCache userNeedsBadgingCache) {
+            super(userManager, userNeedsBadgingCache);
         }
 
         // Copy constructor used in creating snapshots
-        ReceiverIntentResolver(ReceiverIntentResolver orig) {
-            super(orig);
+        ReceiverIntentResolver(@NonNull ReceiverIntentResolver orig,
+                @NonNull UserManagerService userManager,
+                @NonNull UserNeedsBadgingCache userNeedsBadgingCache) {
+            super(orig, userManager, userNeedsBadgingCache);
         }
 
         @Override
@@ -1704,48 +1390,50 @@
         }
     }
 
-    private static final class ProviderIntentResolver
+    public static final class ProviderIntentResolver
             extends MimeGroupsAwareIntentResolver<Pair<ParsedProvider, ParsedIntentInfo>, ResolveInfo> {
         // Default constructor
-        ProviderIntentResolver() {
+        ProviderIntentResolver(@NonNull UserManagerService userManager) {
+            super(userManager);
         }
 
         // Copy constructor used in creating snapshots
-        ProviderIntentResolver(ProviderIntentResolver orig) {
-            super(orig);
+        ProviderIntentResolver(@NonNull ProviderIntentResolver orig,
+                @NonNull UserManagerService userManager) {
+            super(orig, userManager);
             mProviders.putAll(orig.mProviders);
-            mFlags = orig.mFlags;
         }
 
         @Override
-        public List<ResolveInfo> queryIntent(Intent intent, String resolvedType,
-                boolean defaultOnly, int userId) {
-            mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
-            return super.queryIntent(intent, resolvedType, defaultOnly, userId);
-        }
-
-        @Nullable
-        List<ResolveInfo> queryIntent(Intent intent, String resolvedType, long flags,
-                int userId) {
-            if (!sUserManager.exists(userId)) {
+        public List<ResolveInfo> queryIntent(@NonNull PackageDataSnapshot snapshot, Intent intent,
+                String resolvedType, boolean defaultOnly, @UserIdInt int userId) {
+            if (!mUserManager.exists(userId)) {
                 return null;
             }
-            mFlags = flags;
-            return super.queryIntent(intent, resolvedType,
-                    (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0,
-                    userId);
+            long flags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
+            return super.queryIntent(snapshot, intent, resolvedType, defaultOnly, userId, flags);
         }
 
         @Nullable
-        List<ResolveInfo> queryIntentForPackage(Intent intent, String resolvedType,
-                long flags, List<ParsedProvider> packageProviders, int userId) {
-            if (!sUserManager.exists(userId)) {
+        List<ResolveInfo> queryIntent(@NonNull Computer computer, Intent intent,
+                String resolvedType, long flags, int userId) {
+            if (!mUserManager.exists(userId)) {
+                return null;
+            }
+            return super.queryIntent(computer, intent, resolvedType,
+                    (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, userId, flags);
+        }
+
+        @Nullable
+        List<ResolveInfo> queryIntentForPackage(@NonNull Computer computer, Intent intent,
+                String resolvedType, long flags, List<ParsedProvider> packageProviders,
+                int userId) {
+            if (!mUserManager.exists(userId)) {
                 return null;
             }
             if (packageProviders == null) {
                 return Collections.emptyList();
             }
-            mFlags = flags;
             final boolean defaultOnly = (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0;
             final int providersSize = packageProviders.size();
             ArrayList<Pair<ParsedProvider, ParsedIntentInfo>[]> listCut =
@@ -1763,10 +1451,11 @@
                     listCut.add(array);
                 }
             }
-            return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut, userId);
+            return super.queryIntentFromList(computer, intent, resolvedType,
+                    defaultOnly, listCut, userId, flags);
         }
 
-        void addProvider(ParsedProvider p) {
+        void addProvider(@NonNull Computer computer, ParsedProvider p) {
             if (mProviders.containsKey(p.getComponentName())) {
                 Slog.w(TAG, "Provider " + p.getComponentName() + " already defined; ignoring");
                 return;
@@ -1789,7 +1478,7 @@
                 if (!intentFilter.debugCheck()) {
                     Log.w(TAG, "==> For Provider " + p.getName());
                 }
-                addFilter(Pair.create(p, intent));
+                addFilter(computer, Pair.create(p, intent));
             }
         }
 
@@ -1832,21 +1521,16 @@
         }
 
         @Override
-        protected boolean isFilterStopped(Pair<ParsedProvider, ParsedIntentInfo> filter,
-                int userId) {
-            return ComponentResolver.isFilterStopped(filter, userId);
-        }
-
-        @Override
         protected boolean isPackageForFilter(String packageName,
                 Pair<ParsedProvider, ParsedIntentInfo> info) {
             return packageName.equals(info.first.getPackageName());
         }
 
         @Override
-        protected ResolveInfo newResult(Pair<ParsedProvider, ParsedIntentInfo> pair,
-                int match, int userId) {
-            if (!sUserManager.exists(userId)) {
+        protected ResolveInfo newResult(@NonNull Computer computer,
+                Pair<ParsedProvider, ParsedIntentInfo> pair, int match, int userId,
+                long customFlags) {
+            if (!mUserManager.exists(userId)) {
                 return null;
             }
 
@@ -1854,24 +1538,18 @@
             ParsedIntentInfo intentInfo = pair.second;
             IntentFilter filter = intentInfo.getIntentFilter();
 
-            AndroidPackage pkg = sPackageManagerInternal.getPackage(provider.getPackageName());
-            if (pkg == null) {
+            PackageStateInternal packageState =
+                    computer.getPackageStateInternal(provider.getPackageName());
+            if (packageState == null || packageState.getPkg() == null
+                    || !PackageStateUtils.isEnabledAndMatches(packageState, provider, customFlags,
+                    userId)) {
                 return null;
             }
 
-            if (!sPackageManagerInternal.isEnabledAndMatches(provider, mFlags, userId)) {
-                return null;
-            }
-
-            PackageStateInternal ps =
-                    sPackageManagerInternal.getPackageStateInternal(provider.getPackageName());
-            if (ps == null) {
-                return null;
-            }
-            final PackageUserStateInternal userState = ps.getUserStateOrDefault(userId);
-            final boolean matchVisibleToInstantApp = (mFlags
+            final PackageUserStateInternal userState = packageState.getUserStateOrDefault(userId);
+            final boolean matchVisibleToInstantApp = (customFlags
                     & PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY) != 0;
-            final boolean isInstantApp = (mFlags & PackageManager.MATCH_INSTANT) != 0;
+            final boolean isInstantApp = (customFlags & PackageManager.MATCH_INSTANT) != 0;
             // throw out filters that aren't visible to instant applications
             if (matchVisibleToInstantApp
                     && !(filter.isVisibleToInstantApp() || userState.isInstantApp())) {
@@ -1883,22 +1561,22 @@
             }
             // throw out instant application filters if updates are available; will trigger
             // instant application resolution
-            if (userState.isInstantApp() && ps.isUpdateAvailable()) {
+            if (userState.isInstantApp() && packageState.isUpdateAvailable()) {
                 return null;
             }
             final ApplicationInfo appInfo = PackageInfoUtils.generateApplicationInfo(
-                    pkg, mFlags, userState, userId, ps);
+                    packageState.getPkg(), customFlags, userState, userId, packageState);
             if (appInfo == null) {
                 return null;
             }
-            ProviderInfo pi = PackageInfoUtils.generateProviderInfo(pkg, provider, mFlags,
-                    userState, appInfo, userId, ps);
+            ProviderInfo pi = PackageInfoUtils.generateProviderInfo(packageState.getPkg(), provider,
+                    customFlags, userState, appInfo, userId, packageState);
             if (pi == null) {
                 return null;
             }
             final ResolveInfo res = new ResolveInfo();
             res.providerInfo = pi;
-            if ((mFlags & PackageManager.GET_RESOLVED_FILTER) != 0) {
+            if ((customFlags & PackageManager.GET_RESOLVED_FILTER) != 0) {
                 res.filter = filter;
             }
             res.priority = filter.getPriority();
@@ -1959,46 +1637,46 @@
             return input.second.getIntentFilter();
         }
 
-        private final ArrayMap<ComponentName, ParsedProvider> mProviders = new ArrayMap<>();
-        private long mFlags;
+        final ArrayMap<ComponentName, ParsedProvider> mProviders = new ArrayMap<>();
     }
 
-    private static final class ServiceIntentResolver
+    public static final class ServiceIntentResolver
             extends MimeGroupsAwareIntentResolver<Pair<ParsedService, ParsedIntentInfo>, ResolveInfo> {
         // Default constructor
-        ServiceIntentResolver() {
+        ServiceIntentResolver(@NonNull UserManagerService userManager) {
+            super(userManager);
         }
 
         // Copy constructor used in creating snapshots
-        ServiceIntentResolver(ServiceIntentResolver orig) {
-            copyFrom(orig);
+        ServiceIntentResolver(@NonNull ServiceIntentResolver orig,
+                @NonNull UserManagerService userManager) {
+            super(orig, userManager);
             mServices.putAll(orig.mServices);
-            mFlags = orig.mFlags;
         }
 
         @Override
-        public List<ResolveInfo> queryIntent(Intent intent, String resolvedType,
-                boolean defaultOnly, int userId) {
-            mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
-            return super.queryIntent(intent, resolvedType, defaultOnly, userId);
+        public List<ResolveInfo> queryIntent(@NonNull PackageDataSnapshot snapshot, Intent intent,
+                String resolvedType, boolean defaultOnly, @UserIdInt int userId) {
+            if (!mUserManager.exists(userId)) {
+                return null;
+            }
+            long flags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
+            return super.queryIntent(snapshot, intent, resolvedType, defaultOnly, userId, flags);
         }
 
-        List<ResolveInfo> queryIntent(Intent intent, String resolvedType, long flags,
-                int userId) {
-            if (!sUserManager.exists(userId)) return null;
-            mFlags = flags;
-            return super.queryIntent(intent, resolvedType,
-                    (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0,
-                    userId);
+        List<ResolveInfo> queryIntent(@NonNull Computer computer, Intent intent,
+                String resolvedType, long flags, int userId) {
+            if (!mUserManager.exists(userId)) return null;
+            return super.queryIntent(computer, intent, resolvedType,
+                    (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, userId, flags);
         }
 
-        List<ResolveInfo> queryIntentForPackage(Intent intent, String resolvedType,
-                long flags, List<ParsedService> packageServices, int userId) {
-            if (!sUserManager.exists(userId)) return null;
+        List<ResolveInfo> queryIntentForPackage(@NonNull Computer computer, Intent intent,
+                String resolvedType, long flags, List<ParsedService> packageServices, int userId) {
+            if (!mUserManager.exists(userId)) return null;
             if (packageServices == null) {
                 return Collections.emptyList();
             }
-            mFlags = flags;
             final boolean defaultOnly = (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0;
             final int servicesSize = packageServices.size();
             ArrayList<Pair<ParsedService, ParsedIntentInfo>[]> listCut =
@@ -2016,10 +1694,11 @@
                     listCut.add(array);
                 }
             }
-            return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut, userId);
+            return super.queryIntentFromList(computer, intent, resolvedType,
+                    defaultOnly, listCut, userId, flags);
         }
 
-        void addService(ParsedService s) {
+        void addService(@NonNull Computer computer, ParsedService s) {
             mServices.put(s.getComponentName(), s);
             if (DEBUG_SHOW_INFO) {
                 Log.v(TAG, "  service:");
@@ -2037,7 +1716,7 @@
                 if (!intentFilter.debugCheck()) {
                     Log.w(TAG, "==> For Service " + s.getName());
                 }
-                addFilter(Pair.create(s, intent));
+                addFilter(computer, Pair.create(s, intent));
             }
         }
 
@@ -2080,48 +1759,38 @@
         }
 
         @Override
-        protected boolean isFilterStopped(Pair<ParsedService, ParsedIntentInfo> filter, int userId) {
-            return ComponentResolver.isFilterStopped(filter, userId);
-        }
-
-        @Override
         protected boolean isPackageForFilter(String packageName,
                 Pair<ParsedService, ParsedIntentInfo> info) {
             return packageName.equals(info.first.getPackageName());
         }
 
         @Override
-        protected ResolveInfo newResult(Pair<ParsedService, ParsedIntentInfo> pair, int match,
-                int userId) {
-            if (!sUserManager.exists(userId)) return null;
+        protected ResolveInfo newResult(@NonNull Computer computer,
+                Pair<ParsedService, ParsedIntentInfo> pair, int match, int userId,
+                long customFlags) {
+            if (!mUserManager.exists(userId)) return null;
 
             ParsedService service = pair.first;
             ParsedIntentInfo intentInfo = pair.second;
             IntentFilter filter = intentInfo.getIntentFilter();
 
-            AndroidPackage pkg = sPackageManagerInternal.getPackage(service.getPackageName());
-            if (pkg == null) {
+            final PackageStateInternal packageState = computer.getPackageStateInternal(
+                    service.getPackageName());
+            if (packageState == null || packageState.getPkg() == null
+                    || !PackageStateUtils.isEnabledAndMatches(packageState, service, customFlags,
+                    userId)) {
                 return null;
             }
 
-            if (!sPackageManagerInternal.isEnabledAndMatches(service, mFlags, userId)) {
-                return null;
-            }
-
-            PackageStateInternal ps =
-                    sPackageManagerInternal.getPackageStateInternal(service.getPackageName());
-            if (ps == null) {
-                return null;
-            }
-            final PackageUserStateInternal userState = ps.getUserStateOrDefault(userId);
-            ServiceInfo si = PackageInfoUtils.generateServiceInfo(pkg, service, mFlags,
-                    userState, userId, ps);
+            final PackageUserStateInternal userState = packageState.getUserStateOrDefault(userId);
+            ServiceInfo si = PackageInfoUtils.generateServiceInfo(packageState.getPkg(), service,
+                    customFlags, userState, userId, packageState);
             if (si == null) {
                 return null;
             }
             final boolean matchVisibleToInstantApp =
-                    (mFlags & PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY) != 0;
-            final boolean isInstantApp = (mFlags & PackageManager.MATCH_INSTANT) != 0;
+                    (customFlags & PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY) != 0;
+            final boolean isInstantApp = (customFlags & PackageManager.MATCH_INSTANT) != 0;
             // throw out filters that aren't visible to ephemeral apps
             if (matchVisibleToInstantApp
                     && !(filter.isVisibleToInstantApp() || userState.isInstantApp())) {
@@ -2133,12 +1802,12 @@
             }
             // throw out instant app filters if updates are available; will trigger
             // instant app resolution
-            if (userState.isInstantApp() && ps.isUpdateAvailable()) {
+            if (userState.isInstantApp() && packageState.isUpdateAvailable()) {
                 return null;
             }
             final ResolveInfo res = new ResolveInfo();
             res.serviceInfo = si;
-            if ((mFlags & PackageManager.GET_RESOLVED_FILTER) != 0) {
+            if ((customFlags & PackageManager.GET_RESOLVED_FILTER) != 0) {
                 res.filter = filter;
             }
             res.priority = filter.getPriority();
@@ -2203,11 +1872,10 @@
         }
 
         // Keys are String (activity class name), values are Activity.
-        private final ArrayMap<ComponentName, ParsedService> mServices = new ArrayMap<>();
-        private long mFlags;
+        final ArrayMap<ComponentName, ParsedService> mServices = new ArrayMap<>();
     }
 
-    static final class InstantAppIntentResolver
+    public static final class InstantAppIntentResolver
             extends IntentResolver<AuxiliaryResolveInfo.AuxiliaryFilter,
             AuxiliaryResolveInfo.AuxiliaryFilter> {
         /**
@@ -2224,6 +1892,13 @@
         final ArrayMap<String, Pair<Integer, InstantAppResolveInfo>> mOrderResult =
                 new ArrayMap<>();
 
+        @NonNull
+        private final UserManagerService mUserManager;
+
+        public InstantAppIntentResolver(@NonNull UserManagerService userManager) {
+            mUserManager = userManager;
+        }
+
         @Override
         protected AuxiliaryResolveInfo.AuxiliaryFilter[] newArray(int size) {
             return new AuxiliaryResolveInfo.AuxiliaryFilter[size];
@@ -2236,9 +1911,10 @@
         }
 
         @Override
-        protected AuxiliaryResolveInfo.AuxiliaryFilter newResult(
-                AuxiliaryResolveInfo.AuxiliaryFilter responseObj, int match, int userId) {
-            if (!sUserManager.exists(userId)) {
+        protected AuxiliaryResolveInfo.AuxiliaryFilter newResult(@NonNull Computer computer,
+                AuxiliaryResolveInfo.AuxiliaryFilter responseObj, int match, int userId,
+                long customFlags) {
+            if (!mUserManager.exists(userId)) {
                 return null;
             }
             final String packageName = responseObj.resolveInfo.getPackageName();
@@ -2296,40 +1972,17 @@
         }
     }
 
-    private static boolean isFilterStopped(Pair<? extends ParsedComponent, ParsedIntentInfo> pair,
-            int userId) {
-        if (!sUserManager.exists(userId)) {
-            return true;
-        }
-
-        AndroidPackage pkg = sPackageManagerInternal.getPackage(pair.first.getPackageName());
-        if (pkg == null) {
-            return false;
-        }
-
-        PackageStateInternal ps =
-                sPackageManagerInternal.getPackageStateInternal(pair.first.getPackageName());
-        if (ps == null) {
-            return false;
-        }
-
-        // System apps are never considered stopped for purposes of
-        // filtering, because there may be no way for the user to
-        // actually re-launch them.
-        return !ps.isSystem() && ps.getUserStateOrDefault(userId).isStopped();
-    }
-
     /**
      * Removes MIME type from the group, by delegating to IntentResolvers
      * @return true if any intent filters were changed due to this update
      */
-    boolean updateMimeGroup(String packageName, String group) {
+    public boolean updateMimeGroup(@NonNull Computer computer, String packageName, String 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);
+            hasChanges |= mActivities.updateMimeGroup(computer, packageName, group);
+            hasChanges |= mProviders.updateMimeGroup(computer, packageName, group);
+            hasChanges |= mReceivers.updateMimeGroup(computer, packageName, group);
+            hasChanges |= mServices.updateMimeGroup(computer, packageName, group);
             if (hasChanges) {
                 onChanged();
             }
diff --git a/services/core/java/com/android/server/pm/resolution/ComponentResolverApi.java b/services/core/java/com/android/server/pm/resolution/ComponentResolverApi.java
new file mode 100644
index 0000000..b6f2b2a0
--- /dev/null
+++ b/services/core/java/com/android/server/pm/resolution/ComponentResolverApi.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm.resolution;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.UserIdInt;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.pm.ProviderInfo;
+import android.content.pm.ResolveInfo;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.pm.Computer;
+import com.android.server.pm.pkg.component.ParsedActivity;
+import com.android.server.pm.pkg.component.ParsedProvider;
+import com.android.server.pm.pkg.component.ParsedService;
+
+import java.util.List;
+
+public interface ComponentResolverApi {
+
+    boolean isActivityDefined(@NonNull ComponentName component);
+
+    @Nullable
+    ParsedActivity getActivity(@NonNull ComponentName component);
+
+    @Nullable
+    ParsedProvider getProvider(@NonNull ComponentName component);
+
+    @Nullable
+    ParsedActivity getReceiver(@NonNull ComponentName component);
+
+    @Nullable
+    ParsedService getService(@NonNull ComponentName component);
+
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+    boolean componentExists(@NonNull ComponentName componentName);
+
+    @Nullable
+    List<ResolveInfo> queryActivities(@NonNull Computer computer, @NonNull Intent intent,
+            @Nullable String resolvedType, long flags, @UserIdInt int userId);
+
+    @Nullable
+    List<ResolveInfo> queryActivities(@NonNull Computer computer, @NonNull Intent intent,
+            @Nullable String resolvedType, long flags, @NonNull List<ParsedActivity> activities,
+            @UserIdInt int userId);
+
+    @Nullable
+    ProviderInfo queryProvider(@NonNull Computer computer, @NonNull String authority, long flags,
+            @UserIdInt int userId);
+
+    @Nullable
+    List<ResolveInfo> queryProviders(@NonNull Computer computer, @NonNull Intent intent,
+            @Nullable String resolvedType, long flags, @UserIdInt int userId);
+
+    @Nullable
+    List<ResolveInfo> queryProviders(@NonNull Computer computer, @NonNull Intent intent,
+            @Nullable String resolvedType, long flags, @NonNull List<ParsedProvider> providers,
+            @UserIdInt int userId);
+
+    @Nullable
+    List<ProviderInfo> queryProviders(@NonNull Computer computer, @Nullable String processName,
+            @Nullable String metaDataKey, int uid, long flags, @UserIdInt int userId);
+
+    @Nullable
+    List<ResolveInfo> queryReceivers(@NonNull Computer computer, @NonNull Intent intent,
+            @Nullable String resolvedType, long flags, @UserIdInt int userId);
+
+    @Nullable
+    List<ResolveInfo> queryReceivers(@NonNull Computer computer, @NonNull Intent intent,
+            @Nullable String resolvedType, long flags, @NonNull List<ParsedActivity> receivers,
+            @UserIdInt int userId);
+
+    @Nullable
+    List<ResolveInfo> queryServices(@NonNull Computer computer, @NonNull Intent intent,
+            @Nullable String resolvedType, long flags, @UserIdInt int userId);
+
+    @Nullable
+    List<ResolveInfo> queryServices(@NonNull Computer computer, @NonNull Intent intent,
+            @Nullable String resolvedType, long flags, @NonNull List<ParsedService> services,
+            @UserIdInt int userId);
+
+    void querySyncProviders(@NonNull Computer computer, @NonNull List<String> outNames,
+            @NonNull List<ProviderInfo> outInfo, boolean safeMode, @UserIdInt int userId);
+}
diff --git a/services/core/java/com/android/server/pm/resolution/ComponentResolverBase.java b/services/core/java/com/android/server/pm/resolution/ComponentResolverBase.java
new file mode 100644
index 0000000..6b50fc6
--- /dev/null
+++ b/services/core/java/com/android/server/pm/resolution/ComponentResolverBase.java
@@ -0,0 +1,308 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm.resolution;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.UserIdInt;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.ProviderInfo;
+import android.content.pm.ResolveInfo;
+import android.os.UserHandle;
+import android.util.ArrayMap;
+
+import com.android.server.pm.Computer;
+import com.android.server.pm.UserManagerService;
+import com.android.server.pm.parsing.PackageInfoUtils;
+import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.pkg.PackageStateInternal;
+import com.android.server.pm.pkg.PackageUserStateInternal;
+import com.android.server.pm.pkg.component.ParsedActivity;
+import com.android.server.pm.pkg.component.ParsedMainComponent;
+import com.android.server.pm.pkg.component.ParsedProvider;
+import com.android.server.pm.pkg.component.ParsedService;
+import com.android.server.utils.WatchableImpl;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public abstract class ComponentResolverBase extends WatchableImpl implements ComponentResolverApi {
+
+    @NonNull
+    protected ComponentResolver.ActivityIntentResolver mActivities;
+
+    @NonNull
+    protected ComponentResolver.ProviderIntentResolver mProviders;
+
+    @NonNull
+    protected ComponentResolver.ReceiverIntentResolver mReceivers;
+
+    @NonNull
+    protected ComponentResolver.ServiceIntentResolver mServices;
+
+    /** Mapping from provider authority [first directory in content URI codePath) to provider. */
+    @NonNull
+    protected ArrayMap<String, ParsedProvider> mProvidersByAuthority;
+
+    @NonNull
+    protected UserManagerService mUserManager;
+
+    protected ComponentResolverBase(@NonNull UserManagerService userManager) {
+        mUserManager = userManager;
+    }
+
+    @Override
+    public boolean componentExists(@NonNull ComponentName componentName) {
+        ParsedMainComponent component = mActivities.mActivities.get(componentName);
+        if (component != null) {
+            return true;
+        }
+        component = mReceivers.mActivities.get(componentName);
+        if (component != null) {
+            return true;
+        }
+        component = mServices.mServices.get(componentName);
+        if (component != null) {
+            return true;
+        }
+        return mProviders.mProviders.get(componentName) != null;
+    }
+
+    @Nullable
+    @Override
+    public ParsedActivity getActivity(@NonNull ComponentName component) {
+        return mActivities.mActivities.get(component);
+    }
+
+    @Nullable
+    @Override
+    public ParsedProvider getProvider(@NonNull ComponentName component) {
+        return mProviders.mProviders.get(component);
+    }
+
+    @Nullable
+    @Override
+    public ParsedActivity getReceiver(@NonNull ComponentName component) {
+        return mReceivers.mActivities.get(component);
+    }
+
+    @Nullable
+    @Override
+    public ParsedService getService(@NonNull ComponentName component) {
+        return mServices.mServices.get(component);
+    }
+
+    /**
+     * Returns {@code true} if the given activity is defined by some package
+     */
+    @Override
+    public boolean isActivityDefined(@NonNull ComponentName component) {
+        return mActivities.mActivities.get(component) != null;
+    }
+
+    @Nullable
+    @Override
+    public List<ResolveInfo> queryActivities(@NonNull Computer computer, @NonNull Intent intent,
+            @Nullable String resolvedType, long flags, int userId) {
+        return mActivities.queryIntent(computer, intent, resolvedType, flags, userId);
+    }
+
+    @Nullable
+    @Override
+    public List<ResolveInfo> queryActivities(@NonNull Computer computer, @NonNull Intent intent,
+            @Nullable String resolvedType, long flags, @NonNull List<ParsedActivity> activities,
+            int userId) {
+        return mActivities.queryIntentForPackage(computer, intent, resolvedType, flags, activities,
+                userId);
+    }
+
+    @Nullable
+    @Override
+    public ProviderInfo queryProvider(@NonNull Computer computer, @NonNull String authority,
+            long flags, int userId) {
+        final ParsedProvider p = mProvidersByAuthority.get(authority);
+        if (p == null) {
+            return null;
+        }
+        PackageStateInternal packageState = computer.getPackageStateInternal(p.getPackageName());
+        if (packageState == null) {
+            return null;
+        }
+        final AndroidPackage pkg = packageState.getPkg();
+        if (pkg == null) {
+            return null;
+        }
+        final PackageUserStateInternal state = packageState.getUserStateOrDefault(userId);
+        ApplicationInfo appInfo = PackageInfoUtils.generateApplicationInfo(
+                pkg, flags, state, userId, packageState);
+        if (appInfo == null) {
+            return null;
+        }
+        return PackageInfoUtils.generateProviderInfo(pkg, p, flags, state, appInfo, userId,
+                packageState);
+    }
+
+    @Nullable
+    @Override
+    public List<ResolveInfo> queryProviders(@NonNull Computer computer, @NonNull Intent intent,
+            @Nullable String resolvedType, long flags, int userId) {
+        return mProviders.queryIntent(computer, intent, resolvedType, flags, userId);
+    }
+
+    @Nullable
+    @Override
+    public List<ResolveInfo> queryProviders(@NonNull Computer computer, @NonNull Intent intent,
+            @Nullable String resolvedType, long flags, @NonNull List<ParsedProvider> providers,
+            @UserIdInt int userId) {
+        return mProviders.queryIntentForPackage(computer, intent, resolvedType, flags, providers,
+                userId);
+    }
+
+    @Nullable
+    @Override
+    public List<ProviderInfo> queryProviders(@NonNull Computer computer,
+            @Nullable String processName, @Nullable String metaDataKey, int uid, long flags,
+            int userId) {
+        if (!mUserManager.exists(userId)) {
+            return null;
+        }
+        List<ProviderInfo> providerList = null;
+        PackageInfoUtils.CachedApplicationInfoGenerator appInfoGenerator = null;
+        for (int i = mProviders.mProviders.size() - 1; i >= 0; --i) {
+            final ParsedProvider p = mProviders.mProviders.valueAt(i);
+            if (p.getAuthority() == null) {
+                continue;
+            }
+
+            final PackageStateInternal ps = computer.getPackageStateInternal(p.getPackageName());
+            if (ps == null) {
+                continue;
+            }
+
+            AndroidPackage pkg = ps.getPkg();
+            if (pkg == null) {
+                continue;
+            }
+
+            if (processName != null && (!p.getProcessName().equals(processName)
+                    || !UserHandle.isSameApp(pkg.getUid(), uid))) {
+                continue;
+            }
+            // See PM.queryContentProviders()'s javadoc for why we have the metaData parameter.
+            if (metaDataKey != null && !p.getMetaData().containsKey(metaDataKey)) {
+                continue;
+            }
+            if (appInfoGenerator == null) {
+                appInfoGenerator = new PackageInfoUtils.CachedApplicationInfoGenerator();
+            }
+            final PackageUserStateInternal state = ps.getUserStateOrDefault(userId);
+            final ApplicationInfo appInfo =
+                    appInfoGenerator.generate(pkg, flags, state, userId, ps);
+            if (appInfo == null) {
+                continue;
+            }
+
+            final ProviderInfo info = PackageInfoUtils.generateProviderInfo(
+                    pkg, p, flags, state, appInfo, userId, ps);
+            if (info == null) {
+                continue;
+            }
+            if (providerList == null) {
+                providerList = new ArrayList<>(i + 1);
+            }
+            providerList.add(info);
+        }
+        return providerList;
+    }
+
+    @Nullable
+    @Override
+    public List<ResolveInfo> queryReceivers(@NonNull Computer computer, @NonNull Intent intent,
+            @Nullable String resolvedType, long flags, int userId) {
+        return mReceivers.queryIntent(computer, intent, resolvedType, flags, userId);
+    }
+
+    @Nullable
+    @Override
+    public List<ResolveInfo> queryReceivers(@NonNull Computer computer, @NonNull Intent intent,
+            @Nullable String resolvedType, long flags, @NonNull List<ParsedActivity> receivers,
+            @UserIdInt int userId) {
+        return mReceivers.queryIntentForPackage(computer, intent, resolvedType, flags, receivers,
+                userId);
+    }
+
+    @Nullable
+    @Override
+    public List<ResolveInfo> queryServices(@NonNull Computer computer, @NonNull Intent intent,
+            @Nullable String resolvedType, long flags, @UserIdInt int userId) {
+        return mServices.queryIntent(computer, intent, resolvedType, flags, userId);
+    }
+
+    @Nullable
+    @Override
+    public List<ResolveInfo> queryServices(@NonNull Computer computer, @NonNull Intent intent,
+            @Nullable String resolvedType, long flags, @NonNull List<ParsedService> services,
+            @UserIdInt int userId) {
+        return mServices.queryIntentForPackage(computer, intent, resolvedType, flags, services,
+                userId);
+    }
+
+    @Override
+    public void querySyncProviders(@NonNull Computer computer, @NonNull List<String> outNames,
+            @NonNull List<ProviderInfo> outInfo, boolean safeMode, int userId) {
+        PackageInfoUtils.CachedApplicationInfoGenerator appInfoGenerator = null;
+        for (int i = mProvidersByAuthority.size() - 1; i >= 0; --i) {
+            final ParsedProvider p = mProvidersByAuthority.valueAt(i);
+            if (!p.isSyncable()) {
+                continue;
+            }
+
+            final PackageStateInternal ps = computer.getPackageStateInternal(p.getPackageName());
+            if (ps == null) {
+                continue;
+            }
+
+            final AndroidPackage pkg = ps.getPkg();
+            if (pkg == null) {
+                continue;
+            }
+
+            if (safeMode && !pkg.isSystem()) {
+                continue;
+            }
+            if (appInfoGenerator == null) {
+                appInfoGenerator = new PackageInfoUtils.CachedApplicationInfoGenerator();
+            }
+            final PackageUserStateInternal state = ps.getUserStateOrDefault(userId);
+            final ApplicationInfo appInfo =
+                    appInfoGenerator.generate(pkg, 0, state, userId, ps);
+            if (appInfo == null) {
+                continue;
+            }
+
+            final ProviderInfo info = PackageInfoUtils.generateProviderInfo(
+                    pkg, p, 0, state, appInfo, userId, ps);
+            if (info == null) {
+                continue;
+            }
+            outNames.add(mProvidersByAuthority.keyAt(i));
+            outInfo.add(info);
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/pm/resolution/ComponentResolverLocked.java b/services/core/java/com/android/server/pm/resolution/ComponentResolverLocked.java
new file mode 100644
index 0000000..ecc53eb
--- /dev/null
+++ b/services/core/java/com/android/server/pm/resolution/ComponentResolverLocked.java
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm.resolution;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.UserIdInt;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.pm.ProviderInfo;
+import android.content.pm.ResolveInfo;
+
+import com.android.server.pm.Computer;
+import com.android.server.pm.PackageManagerTracedLock;
+import com.android.server.pm.UserManagerService;
+import com.android.server.pm.pkg.component.ParsedActivity;
+import com.android.server.pm.pkg.component.ParsedProvider;
+import com.android.server.pm.pkg.component.ParsedService;
+
+import java.util.List;
+
+public abstract class ComponentResolverLocked extends ComponentResolverBase {
+
+    protected final PackageManagerTracedLock mLock = new PackageManagerTracedLock();
+
+    protected ComponentResolverLocked(@NonNull UserManagerService userManager) {
+        super(userManager);
+    }
+
+    @Override
+    public boolean componentExists(@NonNull ComponentName componentName) {
+        synchronized (mLock) {
+            return super.componentExists(componentName);
+        }
+    }
+
+    @Nullable
+    @Override
+    public ParsedActivity getActivity(@NonNull ComponentName component) {
+        synchronized (mLock) {
+            return super.getActivity(component);
+        }
+    }
+
+    @Nullable
+    @Override
+    public ParsedProvider getProvider(@NonNull ComponentName component) {
+        synchronized (mLock) {
+            return super.getProvider(component);
+        }
+    }
+
+    @Nullable
+    @Override
+    public ParsedActivity getReceiver(@NonNull ComponentName component) {
+        synchronized (mLock) {
+            return super.getReceiver(component);
+        }
+    }
+
+    @Nullable
+    @Override
+    public ParsedService getService(@NonNull ComponentName component) {
+        synchronized (mLock) {
+            return super.getService(component);
+        }
+    }
+
+    @Override
+    public boolean isActivityDefined(@NonNull ComponentName component) {
+        synchronized (mLock) {
+            return super.isActivityDefined(component);
+        }
+    }
+
+    @Nullable
+    @Override
+    public List<ResolveInfo> queryActivities(@NonNull Computer computer, @NonNull Intent intent,
+            @Nullable String resolvedType, long flags, @UserIdInt int userId) {
+        synchronized (mLock) {
+            return super.queryActivities(computer, intent, resolvedType, flags, userId);
+        }
+    }
+
+    @Nullable
+    @Override
+    public List<ResolveInfo> queryActivities(@NonNull Computer computer, @NonNull Intent intent,
+            @Nullable String resolvedType, long flags, @NonNull List<ParsedActivity> activities,
+            @UserIdInt int userId) {
+        synchronized (mLock) {
+            return super.queryActivities(computer, intent, resolvedType, flags, activities, userId);
+        }
+    }
+
+    @Nullable
+    @Override
+    public ProviderInfo queryProvider(@NonNull Computer computer, @NonNull String authority,
+            long flags, @UserIdInt int userId) {
+        synchronized (mLock) {
+            return super.queryProvider(computer, authority, flags, userId);
+        }
+    }
+
+    @Nullable
+    @Override
+    public List<ResolveInfo> queryProviders(@NonNull Computer computer, @NonNull Intent intent,
+            @Nullable String resolvedType, long flags, @UserIdInt int userId) {
+        synchronized (mLock) {
+            return super.queryProviders(computer, intent, resolvedType, flags, userId);
+        }
+    }
+
+    @Nullable
+    @Override
+    public List<ResolveInfo> queryProviders(@NonNull Computer computer, @NonNull Intent intent,
+            @Nullable String resolvedType, long flags, @NonNull List<ParsedProvider> providers,
+            @UserIdInt int userId) {
+        synchronized (mLock) {
+            return super.queryProviders(computer, intent, resolvedType, flags, providers, userId);
+        }
+    }
+
+    @Nullable
+    @Override
+    public List<ProviderInfo> queryProviders(@NonNull Computer computer,
+            @Nullable String processName, @Nullable String metaDataKey, int uid, long flags,
+            @UserIdInt int userId) {
+        synchronized (mLock) {
+            return super.queryProviders(computer, processName, metaDataKey, uid, flags, userId);
+        }
+    }
+
+    @Nullable
+    @Override
+    public List<ResolveInfo> queryReceivers(@NonNull Computer computer, @NonNull Intent intent,
+            @Nullable String resolvedType, long flags, @UserIdInt int userId) {
+        synchronized (mLock) {
+            return super.queryReceivers(computer, intent, resolvedType, flags, userId);
+        }
+    }
+
+    @Nullable
+    @Override
+    public List<ResolveInfo> queryReceivers(@NonNull Computer computer, @NonNull Intent intent,
+            @Nullable String resolvedType, long flags, @NonNull List<ParsedActivity> receivers,
+            @UserIdInt int userId) {
+        synchronized (mLock) {
+            return super.queryReceivers(computer, intent, resolvedType, flags, receivers, userId);
+        }
+    }
+
+    @Nullable
+    @Override
+    public List<ResolveInfo> queryServices(@NonNull Computer computer, @NonNull Intent intent,
+            @Nullable String resolvedType, long flags, @UserIdInt int userId) {
+        synchronized (mLock) {
+            return super.queryServices(computer, intent, resolvedType, flags, userId);
+        }
+    }
+
+    @Nullable
+    @Override
+    public List<ResolveInfo> queryServices(@NonNull Computer computer, @NonNull Intent intent,
+            @Nullable String resolvedType, long flags, @NonNull List<ParsedService> services,
+            @UserIdInt int userId) {
+        synchronized (mLock) {
+            return super.queryServices(computer, intent, resolvedType, flags, services, userId);
+        }
+    }
+
+    @Override
+    public void querySyncProviders(@NonNull Computer computer, @NonNull List<String> outNames,
+            @NonNull List<ProviderInfo> outInfo, boolean safeMode, @UserIdInt int userId) {
+        synchronized (mLock) {
+            super.querySyncProviders(computer, outNames, outInfo, safeMode, userId);
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/pm/resolution/ComponentResolverSnapshot.java b/services/core/java/com/android/server/pm/resolution/ComponentResolverSnapshot.java
new file mode 100644
index 0000000..3a96fe6
--- /dev/null
+++ b/services/core/java/com/android/server/pm/resolution/ComponentResolverSnapshot.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm.resolution;
+
+import android.annotation.NonNull;
+import android.util.ArrayMap;
+
+import com.android.server.pm.UserManagerService;
+import com.android.server.pm.UserNeedsBadgingCache;
+
+public class ComponentResolverSnapshot extends ComponentResolverBase {
+
+    public ComponentResolverSnapshot(@NonNull ComponentResolver orig,
+            @NonNull UserNeedsBadgingCache userNeedsBadgingCache) {
+        super(UserManagerService.getInstance());
+        mActivities = new ComponentResolver.ActivityIntentResolver(orig.mActivities, mUserManager,
+                userNeedsBadgingCache);
+        mProviders = new ComponentResolver.ProviderIntentResolver(orig.mProviders, mUserManager);
+        mReceivers = new ComponentResolver.ReceiverIntentResolver(orig.mReceivers, mUserManager,
+                userNeedsBadgingCache);
+        mServices = new ComponentResolver.ServiceIntentResolver(orig.mServices, mUserManager);
+        mProvidersByAuthority = new ArrayMap<>(orig.mProvidersByAuthority);
+    }
+}
diff --git a/services/core/java/com/android/server/pm/snapshot/PackageDataSnapshot.java b/services/core/java/com/android/server/pm/snapshot/PackageDataSnapshot.java
new file mode 100644
index 0000000..b091445
--- /dev/null
+++ b/services/core/java/com/android/server/pm/snapshot/PackageDataSnapshot.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm.snapshot;
+
+public interface PackageDataSnapshot {
+}
diff --git a/services/tests/PackageManagerComponentOverrideTests/src/com/android/server/pm/test/override/PackageManagerComponentLabelIconOverrideTest.kt b/services/tests/PackageManagerComponentOverrideTests/src/com/android/server/pm/test/override/PackageManagerComponentLabelIconOverrideTest.kt
index c5709fc..43b2e1e 100644
--- a/services/tests/PackageManagerComponentOverrideTests/src/com/android/server/pm/test/override/PackageManagerComponentLabelIconOverrideTest.kt
+++ b/services/tests/PackageManagerComponentOverrideTests/src/com/android/server/pm/test/override/PackageManagerComponentLabelIconOverrideTest.kt
@@ -29,6 +29,7 @@
 import com.android.server.pm.parsing.pkg.AndroidPackage
 import com.android.server.pm.parsing.pkg.PackageImpl
 import com.android.server.pm.parsing.pkg.ParsedPackage
+import com.android.server.pm.resolution.ComponentResolver
 import com.android.server.pm.test.override.PackageManagerComponentLabelIconOverrideTest.Companion.Params.AppType
 import com.android.server.testutils.TestHandler
 import com.android.server.testutils.mock
@@ -46,6 +47,8 @@
 import org.mockito.Mockito.any
 import org.mockito.Mockito.anyInt
 import org.mockito.Mockito.clearInvocations
+import org.mockito.Mockito.doAnswer
+import org.mockito.Mockito.doReturn
 import org.mockito.Mockito.intThat
 import org.mockito.Mockito.never
 import org.mockito.Mockito.same
@@ -337,8 +340,8 @@
         val mockSettings = Settings(mockedPkgSettings)
         val mockComponentResolver: ComponentResolver = mockThrowOnUnmocked {
             params.componentName?.let {
-                whenever(this.componentExists(same(it))) { mockActivity != null }
-                whenever(this.getActivity(same(it))) { mockActivity }
+                doReturn(mockActivity != null).`when`(this).componentExists(same(it))
+                doReturn(mockActivity).`when`(this).getActivity(same(it))
             }
             whenever(this.snapshot()) { this@mockThrowOnUnmocked }
             whenever(registerObserver(any())).thenCallRealMethod()
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt b/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt
index 4ec1641..ca5bf20 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt
@@ -68,6 +68,7 @@
 import com.android.server.pm.permission.PermissionManagerServiceInternal
 import com.android.server.pm.pkg.parsing.ParsingPackage
 import com.android.server.pm.pkg.parsing.ParsingPackageUtils
+import com.android.server.pm.resolution.ComponentResolver
 import com.android.server.pm.verify.domain.DomainVerificationManagerInternal
 import com.android.server.supplementalprocess.SupplementalProcessManagerLocal
 import com.android.server.testutils.TestHandler
@@ -632,7 +633,7 @@
     }
 
     private fun mockQueryActivities(action: String, vararg activities: ActivityInfo) {
-        whenever(mocks.componentResolver.queryActivities(
+        whenever(mocks.componentResolver.queryActivities(any(),
                 argThat { intent: Intent? -> intent != null && (action == intent.action) },
                 nullable(), anyLong(), anyInt())) {
             ArrayList(activities.asList().map { info: ActivityInfo? ->
@@ -642,7 +643,7 @@
     }
 
     private fun mockQueryServices(action: String, vararg services: ServiceInfo) {
-        whenever(mocks.componentResolver.queryServices(
+        whenever(mocks.componentResolver.queryServices(any(),
                 argThat { intent: Intent? -> intent != null && (action == intent.action) },
                 nullable(), anyLong(), anyInt())) {
             ArrayList(services.asList().map { info ->
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
index 8873f42..6789af4 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
@@ -225,7 +225,11 @@
         assertThat(packageUserState1.isSuspended(), is(true));
         assertThat(packageUserState1.getSuspendParams().size(), is(1));
         assertThat(packageUserState1.getSuspendParams().keyAt(0), is("android"));
-        assertThat(packageUserState1.getSuspendParams().valueAt(0), is(nullValue()));
+        assertThat(packageUserState1.getSuspendParams().valueAt(0).getAppExtras(), is(nullValue()));
+        assertThat(packageUserState1.getSuspendParams().valueAt(0).getDialogInfo(),
+                is(nullValue()));
+        assertThat(packageUserState1.getSuspendParams().valueAt(0).getLauncherExtras(),
+                is(nullValue()));
 
         // Verify that the snapshot returns the same answers
         ps1 = snapshot.mPackages.get(PACKAGE_NAME_1);
@@ -233,7 +237,11 @@
         assertThat(packageUserState1.isSuspended(), is(true));
         assertThat(packageUserState1.getSuspendParams().size(), is(1));
         assertThat(packageUserState1.getSuspendParams().keyAt(0), is("android"));
-        assertThat(packageUserState1.getSuspendParams().valueAt(0), is(nullValue()));
+        assertThat(packageUserState1.getSuspendParams().valueAt(0).getAppExtras(), is(nullValue()));
+        assertThat(packageUserState1.getSuspendParams().valueAt(0).getDialogInfo(),
+                is(nullValue()));
+        assertThat(packageUserState1.getSuspendParams().valueAt(0).getLauncherExtras(),
+                is(nullValue()));
 
         PackageSetting ps2 = settingsUnderTest.mPackages.get(PACKAGE_NAME_2);
         PackageUserStateInternal packageUserState2 = ps2.readUserState(0);
@@ -315,14 +323,14 @@
                 .build();
 
         ps1.modifyUserState(0).putSuspendParams( "suspendingPackage1",
-                SuspendParams.getInstanceOrNull(dialogInfo1, appExtras1, launcherExtras1));
+                new SuspendParams(dialogInfo1, appExtras1, launcherExtras1));
         ps1.modifyUserState(0).putSuspendParams( "suspendingPackage2",
-                SuspendParams.getInstanceOrNull(dialogInfo2, appExtras2, launcherExtras2));
+                new SuspendParams(dialogInfo2, appExtras2, launcherExtras2));
         settingsUnderTest.mPackages.put(PACKAGE_NAME_1, ps1);
         watcher.verifyChangeReported("put package 1");
 
         ps2.modifyUserState(0).putSuspendParams( "suspendingPackage3",
-                SuspendParams.getInstanceOrNull(null, appExtras1, null));
+                new SuspendParams(null, appExtras1, null));
         settingsUnderTest.mPackages.put(PACKAGE_NAME_2, ps2);
         watcher.verifyChangeReported("put package 2");
 
@@ -686,7 +694,7 @@
                 .setNeutralButtonAction(BUTTON_ACTION_MORE_DETAILS)
                 .build();
         origPkgSetting01.modifyUserState(0).putSuspendParams("suspendingPackage1",
-                SuspendParams.getInstanceOrNull(dialogInfo1, appExtras1, launcherExtras1));
+                new SuspendParams(dialogInfo1, appExtras1, launcherExtras1));
         final PackageSetting testPkgSetting01 = new PackageSetting(
                 PACKAGE_NAME /*pkgName*/,
                 REAL_PACKAGE_NAME /*realPkgName*/,
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageUserStateTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageUserStateTest.java
index 4dc9612..9ad503c 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageUserStateTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageUserStateTest.java
@@ -85,7 +85,7 @@
 
         oldUserState = new PackageUserStateImpl();
         oldUserState.putSuspendParams("suspendingPackage",
-                SuspendParams.getInstanceOrNull(null, new PersistableBundle(), null));
+                new SuspendParams(null, new PersistableBundle(), null));
         assertThat(testUserState.equals(oldUserState), is(false));
 
         oldUserState = new PackageUserStateImpl();
@@ -185,7 +185,7 @@
 
     private static SuspendParams createSuspendParams(SuspendDialogInfo dialogInfo,
             PersistableBundle appExtras, PersistableBundle launcherExtras) {
-        return SuspendParams.getInstanceOrNull(dialogInfo, appExtras, launcherExtras);
+        return new SuspendParams(dialogInfo, appExtras, launcherExtras);
     }
 
     private static PersistableBundle createPersistableBundle(String lKey, long lValue, String sKey,
diff --git a/services/tests/servicestests/src/com/android/server/pm/WatchedIntentHandlingTest.java b/services/tests/servicestests/src/com/android/server/pm/WatchedIntentHandlingTest.java
index 95af1e1..6e03569 100644
--- a/services/tests/servicestests/src/com/android/server/pm/WatchedIntentHandlingTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/WatchedIntentHandlingTest.java
@@ -145,7 +145,7 @@
         IntentFilter i = new IntentFilter("TEST_ACTION");
         PreferredActivity a1 = new PreferredActivity(i, 1, components, component, true);
 
-        r.addFilter(a1);
+        r.addFilter(null, a1);
         watcher.verifyChangeReported("addFilter");
         i.setPriority(i.getPriority() + 1);
         watcher.verifyNoChangeReported("indepenent intent");