Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b489de6a authored by Lee Shombert's avatar Lee Shombert
Browse files

Watch ComponentResolver

Bug: 181964615

Make ComponentResolver a watched object, where changes are notified to
PackageManagerService.  At the same time, make it snappable, since it
has state that is changed by PMS.
commit.

Test: atest
 * FrameworksServicesTests:AppsFilterTest
 * FrameworksServicesTests:PackageInstallerSessionTest
 * FrameworksServicesTests:PackageManagerServiceTest
 * FrameworksServicesTests:PackageManagerSettingsTests
 * FrameworksServicesTests:ScanTests
 * FrameworksServicesTests:UserSystemPackageInstallerTest
 * PackageManagerServiceBootTest
 * UserLifecycleTests#startUser
 * UserLifecycleTests#stopUser
 * UserLifecycleTests#switchUser
 * android.appsecurity.cts.EphemeralTest
 * android.appsecurity.cts.InstantAppUserTest
 * FrameworksServicesTests:WatcherTest
 * CtsContentTestCases:IntentFilterTest
 * CtsDynamicMimeHostTestCases
 * CtsRoleTestCases

Change-Id: Iccf02e4d32170ca91cf0976603a9bfc0b0627303
parent 16c00cb2
Loading
Loading
Loading
Loading
+177 −55
Original line number Diff line number Diff line
@@ -59,6 +59,9 @@ import com.android.server.IntentResolver;
import com.android.server.pm.parsing.PackageInfoUtils;
import com.android.server.pm.parsing.PackageInfoUtils.CachedApplicationInfoGenerator;
import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.utils.Snappable;
import com.android.server.utils.SnapshotCache;
import com.android.server.utils.WatchableImpl;

import java.io.PrintWriter;
import java.util.ArrayList;
@@ -72,12 +75,19 @@ import java.util.Set;
import java.util.function.Function;

/** Resolves all Android component types [activities, services, providers and receivers]. */
public class ComponentResolver {
public class ComponentResolver
        extends WatchableImpl
        implements Snappable {
    private static final boolean DEBUG = false;
    private static final String TAG = "PackageManager";
    private static final boolean DEBUG_FILTERS = false;
    private static final boolean DEBUG_SHOW_INFO = false;

    // Convenience function to report that this object has changed.
    private void onChanged() {
        dispatchChange(this);
    }

    /**
     * The set of all protected actions [i.e. those actions for which a high priority
     * intent filter is disallowed].
@@ -158,27 +168,27 @@ public class ComponentResolver {
     * would be able to hold its lock while checking the package setting state.</li>
     * </ol>
     */
    private final Object mLock;
    private final PackageManagerTracedLock mLock;

    /** All available activities, for your resolving pleasure. */
    @GuardedBy("mLock")
    private final ActivityIntentResolver mActivities = new ActivityIntentResolver();
    private final ActivityIntentResolver mActivities;

    /** All available providers, for your resolving pleasure. */
    @GuardedBy("mLock")
    private final ProviderIntentResolver mProviders = new ProviderIntentResolver();
    private final ProviderIntentResolver mProviders;

    /** All available receivers, for your resolving pleasure. */
    @GuardedBy("mLock")
    private final ActivityIntentResolver mReceivers = new ReceiverIntentResolver();
    private final ReceiverIntentResolver mReceivers;

    /** All available services, for your resolving pleasure. */
    @GuardedBy("mLock")
    private final ServiceIntentResolver mServices = new ServiceIntentResolver();
    private final ServiceIntentResolver mServices;

    /** Mapping from provider authority [first directory in content URI codePath) to provider. */
    @GuardedBy("mLock")
    private final ArrayMap<String, ParsedProvider> mProvidersByAuthority = new ArrayMap<>();
    private final ArrayMap<String, ParsedProvider> mProvidersByAuthority;

    /** Whether or not processing protected filters should be deferred. */
    private boolean mDeferProtectedFilters = true;
@@ -200,12 +210,57 @@ public class ComponentResolver {

    ComponentResolver(UserManagerService userManager,
            PackageManagerInternal packageManagerInternal,
            Object lock) {
            PackageManagerTracedLock lock) {
        sPackageManagerInternal = packageManagerInternal;
        sUserManager = userManager;
        mLock = lock;

        mActivities = new ActivityIntentResolver();
        mProviders = new ProviderIntentResolver();
        mReceivers = new ReceiverIntentResolver();
        mServices = new ServiceIntentResolver();
        mProvidersByAuthority = new ArrayMap<>();
        mDeferProtectedFilters = true;

        mSnapshot = new SnapshotCache<ComponentResolver>(this, this) {
                @Override
                public ComponentResolver createSnapshot() {
                    return new ComponentResolver(mSource);
                }};
    }

    // Copy constructor used in creating snapshots.
    private ComponentResolver(ComponentResolver orig) {
        // Do not set the static variables that are set in the default constructor.   Do
        // create a new object for the lock.  The snapshot is read-only, so a lock is not
        // strictly required.  However, the current code is simpler if the lock exists,
        // but does not contend with any outside class.
        // TODO: make the snapshot lock-free
        mLock = new PackageManagerTracedLock();

        mActivities = new ActivityIntentResolver(orig.mActivities);
        mProviders = new ProviderIntentResolver(orig.mProviders);
        mReceivers = new ReceiverIntentResolver(orig.mReceivers);
        mServices = new ServiceIntentResolver(orig.mServices);
        mProvidersByAuthority = new ArrayMap<>(orig.mProvidersByAuthority);
        mDeferProtectedFilters = orig.mDeferProtectedFilters;
        mProtectedFilters = (mProtectedFilters == null)
                            ? null
                            : new ArrayList<>(orig.mProtectedFilters);

        mSnapshot = null;
    }

    final SnapshotCache<ComponentResolver> mSnapshot;

    /**
     * Create a snapshot.
     */
    public ComponentResolver snapshot() {
        return mSnapshot.snapshot();
    }


    /** Returns the given activity */
    @Nullable
    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
@@ -474,6 +529,7 @@ public class ComponentResolver {
            addReceiversLocked(pkg, chatty);
            addProvidersLocked(pkg, chatty);
            addServicesLocked(pkg, chatty);
            onChanged();
        }
        // expect single setupwizard package
        final String setupWizardPackage = ArrayUtils.firstOrNull(
@@ -489,6 +545,7 @@ public class ComponentResolver {
            final List<ParsedActivity> systemActivities =
                    disabledPkg != null ? disabledPkg.getActivities() : null;
            adjustPriority(systemActivities, pair.first, pair.second, setupWizardPackage);
            onChanged();
        }
    }

@@ -496,6 +553,7 @@ public class ComponentResolver {
    void removeAllComponents(AndroidPackage pkg, boolean chatty) {
        synchronized (mLock) {
            removeAllComponentsLocked(pkg, chatty);
            onChanged();
        }
    }

@@ -504,6 +562,7 @@ public class ComponentResolver {
     * all of the filters defined on the /system partition and know the special components.
     */
    void fixProtectedFilterPriorities() {
        synchronized (mLock) {
            if (!mDeferProtectedFilters) {
                return;
            }
@@ -550,6 +609,8 @@ public class ComponentResolver {
                }
                filter.setPriority(0);
            }
            onChanged();
        }
    }

    void dumpActivityResolvers(PrintWriter pw, DumpState dumpState, String packageName) {
@@ -1181,9 +1242,20 @@ public class ComponentResolver {
    private abstract static class MimeGroupsAwareIntentResolver<F extends Pair<?
            extends ParsedComponent, ParsedIntentInfo>, R>
            extends IntentResolver<F, R> {
        private ArrayMap<String, F[]> mMimeGroupToFilter = new ArrayMap<>();
        private final ArrayMap<String, F[]> mMimeGroupToFilter = new ArrayMap<>();
        private boolean mIsUpdatingMimeGroup = false;

        // Default constructor
        MimeGroupsAwareIntentResolver() {
        }

        // Copy constructor used in creating snapshots
        MimeGroupsAwareIntentResolver(MimeGroupsAwareIntentResolver<F, R> orig) {
            copyFrom(orig);
            copyInto(mMimeGroupToFilter, orig.mMimeGroupToFilter);
            mIsUpdatingMimeGroup = orig.mIsUpdatingMimeGroup;
        }

        @Override
        public void addFilter(F f) {
            IntentFilter intentFilter = getIntentFilter(f);
@@ -1282,6 +1354,17 @@ public class ComponentResolver {
    private static class ActivityIntentResolver
            extends MimeGroupsAwareIntentResolver<Pair<ParsedActivity, ParsedIntentInfo>, ResolveInfo> {

        // Default constructor
        ActivityIntentResolver() {
        }

        // Copy constructor used in creating snapshots
        ActivityIntentResolver(ActivityIntentResolver orig) {
            super(orig);
            mActivities.putAll(orig.mActivities);
            mFlags = orig.mFlags;
        }

        @Override
        public List<ResolveInfo> queryIntent(Intent intent, String resolvedType,
                boolean defaultOnly, int userId) {
@@ -1330,7 +1413,7 @@ public class ComponentResolver {
            return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut, userId);
        }

        private void addActivity(ParsedActivity a, String type,
        protected void addActivity(ParsedActivity a, String type,
                List<Pair<ParsedActivity, ParsedIntentInfo>> newIntents) {
            mActivities.put(a.getComponentName(), a);
            if (DEBUG_SHOW_INFO) {
@@ -1354,7 +1437,7 @@ public class ComponentResolver {
            }
        }

        private void removeActivity(ParsedActivity a, String type) {
        protected void removeActivity(ParsedActivity a, String type) {
            mActivities.remove(a.getComponentName());
            if (DEBUG_SHOW_INFO) {
                Log.v(TAG, "  " + type + ":");
@@ -1567,8 +1650,11 @@ public class ComponentResolver {
            return pkg.getActivities();
        }

        // Keys are String (activity class name), values are Activity.
        private final ArrayMap<ComponentName, ParsedActivity> mActivities =
        // Keys are String (activity class name), values are Activity.  This attribute is
        // protected because it is accessed directly from ComponentResolver.  That works
        // even if the attribute is private, but fails for subclasses of
        // ActivityIntentResolver.
        protected final ArrayMap<ComponentName, ParsedActivity> mActivities =
                new ArrayMap<>();
        private int mFlags;
    }
@@ -1576,6 +1662,15 @@ public class ComponentResolver {
    // Both receivers and activities share a class, but point to different get methods
    private static final class ReceiverIntentResolver extends ActivityIntentResolver {

        // Default constructor
        ReceiverIntentResolver() {
        }

        // Copy constructor used in creating snapshots
        ReceiverIntentResolver(ReceiverIntentResolver orig) {
            super(orig);
        }

        @Override
        protected List<ParsedActivity> getResolveList(AndroidPackage pkg) {
            return pkg.getReceivers();
@@ -1584,6 +1679,17 @@ public class ComponentResolver {

    private static final class ProviderIntentResolver
            extends MimeGroupsAwareIntentResolver<Pair<ParsedProvider, ParsedIntentInfo>, ResolveInfo> {
        // Default constructor
        ProviderIntentResolver() {
        }

        // Copy constructor used in creating snapshots
        ProviderIntentResolver(ProviderIntentResolver orig) {
            super(orig);
            mProviders.putAll(orig.mProviders);
            mFlags = orig.mFlags;
        }

        @Override
        public List<ResolveInfo> queryIntent(Intent intent, String resolvedType,
                boolean defaultOnly, int userId) {
@@ -1829,6 +1935,17 @@ public class ComponentResolver {

    private static final class ServiceIntentResolver
            extends MimeGroupsAwareIntentResolver<Pair<ParsedService, ParsedIntentInfo>, ResolveInfo> {
        // Default constructor
        ServiceIntentResolver() {
        }

        // Copy constructor used in creating snapshots
        ServiceIntentResolver(ServiceIntentResolver orig) {
            copyFrom(orig);
            mServices.putAll(orig.mServices);
            mFlags = orig.mFlags;
        }

        @Override
        public List<ResolveInfo> queryIntent(Intent intent, String resolvedType,
                boolean defaultOnly, int userId) {
@@ -2213,11 +2330,16 @@ public class ComponentResolver {
     * @return true if any intent filters were changed due to this update
     */
    boolean updateMimeGroup(String packageName, String group) {
        boolean hasChanges = mActivities.updateMimeGroup(packageName, group);
        boolean hasChanges = false;
        synchronized (mLock) {
            hasChanges |= mActivities.updateMimeGroup(packageName, group);
            hasChanges |= mProviders.updateMimeGroup(packageName, group);
            hasChanges |= mReceivers.updateMimeGroup(packageName, group);
            hasChanges |= mServices.updateMimeGroup(packageName, group);

            if (hasChanges) {
                onChanged();
            }
        }
        return hasChanges;
    }
}
+7 −1
Original line number Diff line number Diff line
@@ -1481,7 +1481,9 @@ public class PackageManagerService extends IPackageManager.Stub
    // Internal interface for permission manager
    private final PermissionManagerServiceInternal mPermissionManager;
    @Watched
    private final ComponentResolver mComponentResolver;
    // List of packages names to keep cached, even if they are uninstalled for all users
    private List<String> mKeepUninstalledPackages;
@@ -1854,6 +1856,7 @@ public class PackageManagerService extends IPackageManager.Stub
        public final ApplicationInfo androidApplication;
        public final String appPredictionServicePackage;
        public final AppsFilter appsFilter;
        public final ComponentResolver componentResolver;
        public final PackageManagerService service;
        Snapshot(int type) {
@@ -1879,6 +1882,7 @@ public class PackageManagerService extends IPackageManager.Stub
                        : new ApplicationInfo(mAndroidApplication);
                appPredictionServicePackage = mAppPredictionServicePackage;
                appsFilter = mAppsFilter.snapshot();
                componentResolver = mComponentResolver.snapshot();
            } else if (type == Snapshot.LIVE) {
                settings = mSettings;
                isolatedOwners = mIsolatedOwners;
@@ -1895,6 +1899,7 @@ public class PackageManagerService extends IPackageManager.Stub
                androidApplication = mAndroidApplication;
                appPredictionServicePackage = mAppPredictionServicePackage;
                appsFilter = mAppsFilter;
                componentResolver = mComponentResolver;
            } else {
                throw new IllegalArgumentException();
            }
@@ -2142,6 +2147,7 @@ public class PackageManagerService extends IPackageManager.Stub
            mInstantAppRegistry = args.instantAppRegistry;
            mLocalAndroidApplication = args.androidApplication;
            mAppsFilter = args.appsFilter;
            mComponentResolver = args.componentResolver;
            mAppPredictionServicePackage = args.appPredictionServicePackage;
@@ -2152,7 +2158,6 @@ public class PackageManagerService extends IPackageManager.Stub
            mContext = args.service.mContext;
            mInjector = args.service.mInjector;
            mApexManager = args.service.mApexManager;
            mComponentResolver = args.service.mComponentResolver;
            mInstantAppResolverConnection = args.service.mInstantAppResolverConnection;
            mDefaultAppProvider = args.service.mDefaultAppProvider;
            mDomainVerificationManager = args.service.mDomainVerificationManager;
@@ -6159,6 +6164,7 @@ public class PackageManagerService extends IPackageManager.Stub
        mInstantAppRegistry.registerObserver(mWatcher);
        mSettings.registerObserver(mWatcher);
        mIsolatedOwners.registerObserver(mWatcher);
        mComponentResolver.registerObserver(mWatcher);
        // If neither "build" attribute is true then this may be a mockito test, and verification
        // can fail as a false positive.
        Watchable.verifyWatchedAttributes(this, mWatcher, !(mIsEngBuild || mIsUserDebugBuild));