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

Commit 646ce7ee authored by Lee Shombert's avatar Lee Shombert Committed by Android (Google) Code Review
Browse files

Merge changes Iccf02e4d,Ibc931dab,Iba80142b into sc-dev

* changes:
  Watch ComponentResolver
  Thread WatchedIntentFilter in PackageManagerService
  WatchedIntentResolver now uses WatchedIntentFilter
parents 52e5dd7f b489de6a
Loading
Loading
Loading
Loading
+23 −11
Original line number Diff line number Diff line
@@ -839,33 +839,45 @@ public abstract class IntentResolver<F, R extends Object> {
        }
    };

    // Method to take the snapshot of an F.
    protected F snapshot(F f) {
        return f;
    }

    // Helper method to copy some of the maps.
    private static <E> void copyInto(ArrayMap<String, E[]> l, ArrayMap<String, E[]> r) {
    protected void copyInto(ArrayMap<String, F[]> l, ArrayMap<String, F[]> r) {
        final int end = r.size();
        l.clear();
        l.ensureCapacity(end);
        for (int i = 0; i < end; i++) {
            final E[] val = r.valueAt(i);
            final F[] val = r.valueAt(i);
            final String key = r.keyAt(i);
            l.put(key, Arrays.copyOf(val, val.length));
            final F[] newval = Arrays.copyOf(val, val.length);
            for (int j = 0; j < newval.length; j++) {
                newval[j] = snapshot(newval[j]);
            }
            l.put(key, newval);
        }
    }

    protected void copyInto(ArraySet<F> l, ArraySet<F> r) {
        l.clear();
        final int end = r.size();
        l.ensureCapacity(end);
        for (int i = 0; i < end; i++) {
            l.append(snapshot(r.valueAt(i)));
        }
    }

    // Make <this> a copy of <orig>.  The presumption is that <this> is empty but all
    // arrays are cleared out explicitly, just to be sure.
    protected void copyFrom(IntentResolver orig) {
        mFilters.clear();
        mFilters.addAll(orig.mFilters);
        mTypeToFilter.clear();
        copyInto(mFilters, orig.mFilters);
        copyInto(mTypeToFilter, orig.mTypeToFilter);
        mBaseTypeToFilter.clear();
        copyInto(mBaseTypeToFilter, orig.mBaseTypeToFilter);
        mWildTypeToFilter.clear();
        copyInto(mWildTypeToFilter, orig.mWildTypeToFilter);
        mSchemeToFilter.clear();
        copyInto(mSchemeToFilter, orig.mSchemeToFilter);
        mActionToFilter.clear();
        copyInto(mActionToFilter, orig.mActionToFilter);
        mTypedActionToFilter.clear();
        copyInto(mTypedActionToFilter, orig.mTypedActionToFilter);
    }

+28 −2
Original line number Diff line number Diff line
@@ -19,10 +19,13 @@ package com.android.server;
import android.annotation.NonNull;
import android.annotation.Nullable;

import com.android.server.pm.WatchedIntentFilter;
import com.android.server.utils.Snappable;
import com.android.server.utils.Watchable;
import com.android.server.utils.WatchableImpl;
import com.android.server.utils.Watcher;

import java.util.ArrayList;
import java.util.List;

/**
@@ -31,9 +34,9 @@ import java.util.List;
 * @param <R> The resolver type.
 * {@hide}
 */
public abstract class WatchedIntentResolver<F, R extends Object>
public abstract class WatchedIntentResolver<F extends Watchable, R extends Object>
        extends IntentResolver<F, R>
        implements Watchable {
        implements Watchable, Snappable {

    /**
     * Watchable machinery
@@ -78,6 +81,13 @@ public abstract class WatchedIntentResolver<F, R extends Object>
        mWatchable.dispatchChange(what);
    }

    private final Watcher mWatcher = new Watcher() {
            @Override
            public void onChange(@Nullable Watchable what) {
                dispatchChange(what);
            }
        };

    /**
     * Notify listeners that this object has changed.
     */
@@ -88,17 +98,20 @@ public abstract class WatchedIntentResolver<F, R extends Object>
    @Override
    public void addFilter(F f) {
        super.addFilter(f);
        f.registerObserver(mWatcher);
        onChanged();
    }

    @Override
    public void removeFilter(F f) {
        f.unregisterObserver(mWatcher);
        super.removeFilter(f);
        onChanged();
    }

    @Override
    protected void removeFilterInternal(F f) {
        f.unregisterObserver(mWatcher);
        super.removeFilterInternal(f);
        onChanged();
    }
@@ -109,4 +122,17 @@ public abstract class WatchedIntentResolver<F, R extends Object>
        super.sortResults(results);
        onChanged();
    }

    /**
     * @see IntentResolver#findFilters(IntentFilter)
     */
    public ArrayList<F> findFilters(WatchedIntentFilter matching) {
        return super.findFilters(matching.getIntentFilter());
    }

    // Make <this> a copy of <orig>.  The presumption is that <this> is empty but all
    // arrays are cleared out explicitly, just to be sure.
    protected void copyFrom(WatchedIntentResolver orig) {
        super.copyFrom(orig);
    }
}
+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;
    }
}
+40 −4
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import android.util.TypedXmlPullParser;
import android.util.TypedXmlSerializer;

import com.android.internal.util.XmlUtils;
import com.android.server.utils.SnapshotCache;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -35,7 +36,7 @@ import java.io.IOException;
 * If an {@link Intent} matches the {@link CrossProfileIntentFilter}, then activities in the user
 * {@link #mTargetUserId} can access it.
 */
class CrossProfileIntentFilter extends IntentFilter {
class CrossProfileIntentFilter extends WatchedIntentFilter {
    private static final String ATTR_TARGET_USER_ID = "targetUserId";
    private static final String ATTR_FLAGS = "flags";
    private static final String ATTR_OWNER_PACKAGE = "ownerPackage";
@@ -48,12 +49,41 @@ class CrossProfileIntentFilter extends IntentFilter {
    final String mOwnerPackage; // packageName of the app.
    final int mFlags;

    // The cache for snapshots, so they are not rebuilt if the base object has not
    // changed.
    final SnapshotCache<CrossProfileIntentFilter> mSnapshot;

    private SnapshotCache makeCache() {
        return new SnapshotCache<CrossProfileIntentFilter>(this, this) {
            @Override
            public CrossProfileIntentFilter createSnapshot() {
                CrossProfileIntentFilter s = new CrossProfileIntentFilter(mSource);
                s.seal();
                return s;
            }};
    }

    CrossProfileIntentFilter(IntentFilter filter, String ownerPackage, int targetUserId,
            int flags) {
        super(filter);
        mTargetUserId = targetUserId;
        mOwnerPackage = ownerPackage;
        mFlags = flags;
        mSnapshot = makeCache();
    }

    CrossProfileIntentFilter(WatchedIntentFilter filter, String ownerPackage, int targetUserId,
            int flags) {
        this(filter.mFilter, ownerPackage, targetUserId, flags);
    }

    // Copy constructor used only to create a snapshot.
    private CrossProfileIntentFilter(CrossProfileIntentFilter f) {
        super(f);
        mTargetUserId = f.mTargetUserId;
        mOwnerPackage = f.mOwnerPackage;
        mFlags = f.mFlags;
        mSnapshot = new SnapshotCache.Sealed();
    }

    public int getTargetUserId() {
@@ -72,6 +102,7 @@ class CrossProfileIntentFilter extends IntentFilter {
        mTargetUserId = parser.getAttributeInt(null, ATTR_TARGET_USER_ID, UserHandle.USER_NULL);
        mOwnerPackage = getStringFromXml(parser, ATTR_OWNER_PACKAGE, "");
        mFlags = parser.getAttributeInt(null, ATTR_FLAGS, 0);
        mSnapshot = makeCache();

        int outerDepth = parser.getDepth();
        String tagName = parser.getName();
@@ -94,7 +125,7 @@ class CrossProfileIntentFilter extends IntentFilter {
            }
        }
        if (tagName.equals(ATTR_FILTER)) {
            readFromXml(parser);
            mFilter.readFromXml(parser);
        } else {
            String msg = "Missing element under " + TAG + ": " + ATTR_FILTER +
                    " at " + parser.getPositionDescription();
@@ -103,7 +134,8 @@ class CrossProfileIntentFilter extends IntentFilter {
        }
    }

    String getStringFromXml(TypedXmlPullParser parser, String attribute, String defaultValue) {
    private String getStringFromXml(TypedXmlPullParser parser, String attribute,
            String defaultValue) {
        String value = parser.getAttributeValue(null, attribute);
        if (value == null) {
            String msg = "Missing element under " + TAG +": " + attribute + " at " +
@@ -120,7 +152,7 @@ class CrossProfileIntentFilter extends IntentFilter {
        serializer.attributeInt(null, ATTR_FLAGS, mFlags);
        serializer.attribute(null, ATTR_OWNER_PACKAGE, mOwnerPackage);
        serializer.startTag(null, ATTR_FILTER);
            super.writeToXml(serializer);
        mFilter.writeToXml(serializer);
        serializer.endTag(null, ATTR_FILTER);
    }

@@ -135,4 +167,8 @@ class CrossProfileIntentFilter extends IntentFilter {
                && mOwnerPackage.equals(other.mOwnerPackage)
                && mFlags == other.mFlags;
    }

    public CrossProfileIntentFilter snapshot() {
        return mSnapshot.snapshot();
    }
}
+30 −4
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import android.content.IntentFilter;

import com.android.server.WatchedIntentResolver;
import com.android.server.utils.Snappable;
import com.android.server.utils.SnapshotCache;

import java.util.List;

@@ -47,7 +48,34 @@ class CrossProfileIntentResolver

    @Override
    protected IntentFilter getIntentFilter(@NonNull CrossProfileIntentFilter input) {
        return input;
        return input.getIntentFilter();
    }

    CrossProfileIntentResolver() {
        mSnapshot = makeCache();
    }

    // Take the snapshot of F
    protected CrossProfileIntentFilter snapshot(CrossProfileIntentFilter f) {
        return (f == null) ? null : f.snapshot();
    }

    // Copy constructor used only to create a snapshot.
    private CrossProfileIntentResolver(CrossProfileIntentResolver f) {
        copyFrom(f);
        mSnapshot = new SnapshotCache.Sealed();
    }

    // The cache for snapshots, so they are not rebuilt if the base object has not
    // changed.
    final SnapshotCache<CrossProfileIntentResolver> mSnapshot;

    private SnapshotCache makeCache() {
        return new SnapshotCache<CrossProfileIntentResolver>(this, this) {
            @Override
            public CrossProfileIntentResolver createSnapshot() {
                return new CrossProfileIntentResolver(mSource);
            }};
    }

    /**
@@ -56,8 +84,6 @@ class CrossProfileIntentResolver
     * @return A snapshot of the current object.
     */
    public CrossProfileIntentResolver snapshot() {
        CrossProfileIntentResolver result = new CrossProfileIntentResolver();
        result.copyFrom(this);
        return result;
        return mSnapshot.snapshot();
    }
}
Loading