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

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

Merge changes Idb673c94,I44312a68,Ifa4cd756,Ibf6b2b5f,Ifb243cf9

* changes:
  PackageManager lock reduction: server reconfiguration
  PackageManager lock reduction: InstantAppRegistry
  PackageManager lock reduction: AppsFilter
  PackageManager lock reduction: Settings
  PackageManager lock reduction: IntentResolver
parents b910c7da fd7a3d3f
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -839,6 +839,17 @@ public abstract class IntentResolver<F, R extends Object> {
        }
    };

    // Make <this> a copy of <orig>.  The presumption is that <this> is empty.
    protected void doCopy(IntentResolver orig) {
        mFilters.addAll(orig.mFilters);
        mTypeToFilter.putAll(orig.mTypeToFilter);
        mBaseTypeToFilter.putAll(orig.mBaseTypeToFilter);
        mWildTypeToFilter.putAll(orig.mWildTypeToFilter);
        mSchemeToFilter.putAll(orig.mSchemeToFilter);
        mActionToFilter.putAll(orig.mActionToFilter);
        mTypedActionToFilter.putAll(orig.mTypedActionToFilter);
    }

    /**
     * All filters that have been registered.
     */
+117 −3
Original line number Diff line number Diff line
@@ -55,6 +55,12 @@ import com.android.server.FgThread;
import com.android.server.compat.CompatChange;
import com.android.server.om.OverlayReferenceMapper;
import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.utils.Snappable;
import com.android.server.utils.Snapshots;
import com.android.server.utils.Watchable;
import com.android.server.utils.WatchableImpl;
import com.android.server.utils.WatchedArrayMap;
import com.android.server.utils.Watcher;

import java.io.PrintWriter;
import java.util.Arrays;
@@ -69,7 +75,7 @@ import java.util.concurrent.Executor;
 * manifests.
 */
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
public class AppsFilter {
public class AppsFilter implements Watchable, Snappable {

    private static final String TAG = "AppsFilter";

@@ -145,6 +151,55 @@ public class AppsFilter {
    @GuardedBy("mCacheLock")
    private volatile SparseArray<SparseBooleanArray> mShouldFilterCache;

    /**
     * A cached snapshot.
     */
    private volatile AppsFilter mSnapshot = null;

    /**
     * Watchable machinery
     */
    private final WatchableImpl mWatchable = new WatchableImpl();

    /**
     * Ensures an observer is in the list, exactly once. The observer cannot be null.  The
     * function quietly returns if the observer is already in the list.
     *
     * @param observer The {@link Watcher} to be notified when the {@link Watchable} changes.
     */
    public void registerObserver(@NonNull Watcher observer) {
        mWatchable.registerObserver(observer);
    }

    /**
     * Ensures an observer is not in the list. The observer must not be null.  The function
     * quietly returns if the objserver is not in the list.
     *
     * @param observer The {@link Watcher} that should not be in the notification list.
     */
    public void unregisterObserver(@NonNull Watcher observer) {
        mWatchable.unregisterObserver(observer);
    }

    /**
     * Invokes {@link Watcher#onChange} on each registered observer.  The method can be called
     * with the {@link Watchable} that generated the event.  In a tree of {@link Watchable}s, this
     * is generally the first (deepest) {@link Watchable} to detect a change.
     *
     * @param what The {@link Watchable} that generated the event.
     */
    public void dispatchChange(@Nullable Watchable what) {
        mSnapshot = null;
        mWatchable.dispatchChange(what);
    }

    /**
     * Report a change to observers.
     */
    private void onChanged() {
        dispatchChange(this);
    }

    @VisibleForTesting(visibility = PRIVATE)
    AppsFilter(StateProvider stateProvider,
            FeatureConfig featureConfig,
@@ -161,6 +216,44 @@ public class AppsFilter {
        mBackgroundExecutor = backgroundExecutor;
    }

    /**
     * The copy constructor is used by PackageManagerService to construct a snapshot.
     * Attributes are not deep-copied since these are supposed to be immutable.
     * TODO: deep-copy the attributes, if necessary.
     */
    private AppsFilter(AppsFilter orig) {
        Snapshots.copy(mImplicitlyQueryable, orig.mImplicitlyQueryable);
        Snapshots.copy(mQueriesViaPackage, orig.mQueriesViaPackage);
        Snapshots.copy(mQueriesViaComponent, orig.mQueriesViaComponent);
        mQueriesViaComponentRequireRecompute = orig.mQueriesViaComponentRequireRecompute;
        mForceQueryable.addAll(orig.mForceQueryable);
        mForceQueryableByDevicePackageNames = orig.mForceQueryableByDevicePackageNames;
        mSystemAppsQueryable = orig.mSystemAppsQueryable;
        mFeatureConfig = orig.mFeatureConfig;
        mOverlayReferenceMapper = orig.mOverlayReferenceMapper;
        mStateProvider = orig.mStateProvider;
        mSystemSigningDetails = orig.mSystemSigningDetails;
        mProtectedBroadcasts = orig.mProtectedBroadcasts;
        mShouldFilterCache = orig.mShouldFilterCache;

        mBackgroundExecutor = null;
    }

    /**
     * Return a snapshot.  If the cached snapshot is null, build a new one.  The logic in
     * the function ensures that this function returns a valid snapshot even if a race
     * condition causes the cached snapshot to be cleared asynchronously to this method.
     */
    public AppsFilter snapshot() {
        AppsFilter s = mSnapshot;
        if (s == null) {
            s = new AppsFilter(this);
            s.mWatchable.seal();
            mSnapshot = s;
        }
        return s;
    }

    /**
     * Provides system state to AppsFilter via {@link CurrentStateCallback} after properly guarding
     * the data with the package lock.
@@ -311,6 +404,9 @@ public class AppsFilter {
            } else {
                mDisabledPackages.add(pkg.getPackageName());
            }
            if (mAppsFilter != null) {
                mAppsFilter.onChanged();
            }
        }

        @Override
@@ -347,7 +443,7 @@ public class AppsFilter {
        }
        final StateProvider stateProvider = command -> {
            synchronized (injector.getLock()) {
                command.currentState(injector.getSettings().getPackagesLocked(),
                command.currentState(injector.getSettings().getPackagesLocked().untrackedMap(),
                        injector.getUserManagerInternal().getUserInfos());
            }
        };
@@ -482,7 +578,8 @@ public class AppsFilter {
     */
    public void grantImplicitAccess(int recipientUid, int visibleUid) {
        if (recipientUid != visibleUid) {
            if (mImplicitlyQueryable.add(recipientUid, visibleUid) && DEBUG_LOGGING) {
            final boolean changed = mImplicitlyQueryable.add(recipientUid, visibleUid);
            if (changed && DEBUG_LOGGING) {
                Slog.i(TAG, "implicit access granted: " + recipientUid + " -> " + visibleUid);
            }
            synchronized (mCacheLock) {
@@ -497,6 +594,9 @@ public class AppsFilter {
                    visibleUids.put(visibleUid, false);
                }
            }
            if (changed) {
                onChanged();
            }
        }
    }

@@ -505,6 +605,7 @@ public class AppsFilter {
        mFeatureConfig.onSystemReady();

        updateEntireShouldFilterCacheAsync();
        onChanged();
    }

    /**
@@ -530,6 +631,7 @@ public class AppsFilter {
                }
            });
        } finally {
            onChanged();
            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
        }
    }
@@ -712,6 +814,7 @@ public class AppsFilter {
        synchronized (mCacheLock) {
            if (mShouldFilterCache != null) {
                updateEntireShouldFilterCache();
                onChanged();
            }
        }
    }
@@ -869,6 +972,16 @@ public class AppsFilter {
        return result;
    }

    /**
     * This api does type conversion on the <existingSettings> parameter.
     */
    @VisibleForTesting(visibility = PRIVATE)
    @Nullable
    SparseArray<int[]> getVisibilityAllowList(PackageSetting setting, int[] users,
            WatchedArrayMap<String, PackageSetting> existingSettings) {
        return getVisibilityAllowList(setting, users, existingSettings.untrackedMap());
    }

    /**
     * Equivalent to calling {@link #addPackage(PackageSetting, boolean)} with {@code isReplace}
     * equal to {@code false}.
@@ -946,6 +1059,7 @@ public class AppsFilter {
                                siblingSetting, settings, users, settings.size());
                    }
                }
                onChanged();
            }
        });
    }
+16 −4
Original line number Diff line number Diff line
@@ -14,21 +14,22 @@
 * limitations under the License.
 */


package com.android.server.pm;


import android.annotation.NonNull;
import android.content.IntentFilter;

import com.android.server.IntentResolver;
import com.android.server.utils.Snappable;
import com.android.server.utils.WatchableIntentResolver;

import java.util.List;

/**
 * Used to find a list of {@link CrossProfileIntentFilter}s that match an intent.
 */
class CrossProfileIntentResolver
        extends IntentResolver<CrossProfileIntentFilter, CrossProfileIntentFilter> {
        extends WatchableIntentResolver<CrossProfileIntentFilter, CrossProfileIntentFilter>
        implements Snappable {
    @Override
    protected CrossProfileIntentFilter[] newArray(int size) {
        return new CrossProfileIntentFilter[size];
@@ -48,4 +49,15 @@ class CrossProfileIntentResolver
    protected IntentFilter getIntentFilter(@NonNull CrossProfileIntentFilter input) {
        return input;
    }

    /**
     * Return a snapshot of the current object.  The snapshot is a read-only copy suitable
     * for read-only methods.
     * @return A snapshot of the current object.
     */
    public CrossProfileIntentResolver snapshot() {
        CrossProfileIntentResolver result = new CrossProfileIntentResolver();
        result.doCopy(this);
        return result;
    }
}
+119 −69
Original line number Diff line number Diff line
@@ -42,7 +42,6 @@ import android.util.AtomicFile;
import android.util.PackageUtils;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
import android.util.TypedXmlPullParser;
import android.util.TypedXmlSerializer;
import android.util.Xml;
@@ -55,20 +54,23 @@ import com.android.internal.util.XmlUtils;
import com.android.server.pm.parsing.PackageInfoUtils;
import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.permission.PermissionManagerServiceInternal;
import com.android.server.utils.Snappable;
import com.android.server.utils.Watchable;
import com.android.server.utils.WatchableImpl;
import com.android.server.utils.WatchedSparseArray;
import com.android.server.utils.WatchedSparseBooleanArray;
import com.android.server.utils.Watcher;

import libcore.io.IoUtils;
import libcore.util.HexEncoding;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.List;
@@ -82,7 +84,7 @@ import java.util.function.Predicate;
 * pruning installed instant apps and meta-data for uninstalled instant apps
 * when free space is needed.
 */
class InstantAppRegistry {
class InstantAppRegistry implements Watchable, Snappable {
    private static final boolean DEBUG = false;

    private static final String LOG_TAG = "InstantAppRegistry";
@@ -120,7 +122,7 @@ class InstantAppRegistry {

    /** State for uninstalled instant apps */
    @GuardedBy("mService.mLock")
    private SparseArray<List<UninstalledInstantAppState>> mUninstalledInstantApps;
    private final WatchedSparseArray<List<UninstalledInstantAppState>> mUninstalledInstantApps;

    /**
     * Automatic grants for access to instant app metadata.
@@ -129,17 +131,90 @@ class InstantAppRegistry {
     * UserID -> TargetAppId -> InstantAppId
     */
    @GuardedBy("mService.mLock")
    private SparseArray<SparseArray<SparseBooleanArray>> mInstantGrants;
    private final WatchedSparseArray<WatchedSparseArray<WatchedSparseBooleanArray>> mInstantGrants;

    /** The set of all installed instant apps. UserID -> AppID */
    @GuardedBy("mService.mLock")
    private SparseArray<SparseBooleanArray> mInstalledInstantAppUids;
    private final WatchedSparseArray<WatchedSparseBooleanArray> mInstalledInstantAppUids;

    /**
     * The cached snapshot
     */
    private volatile InstantAppRegistry mSnapshot = null;

    /**
     * Watchable machinery
     */
    private final WatchableImpl mWatchable = new WatchableImpl();
    public void registerObserver(@NonNull Watcher observer) {
        mWatchable.registerObserver(observer);
    }
    public void unregisterObserver(@NonNull Watcher observer) {
        mWatchable.unregisterObserver(observer);
    }
    public void dispatchChange(@Nullable Watchable what) {
        mSnapshot = null;
        mWatchable.dispatchChange(what);
    }
    /**
     * Notify listeners that this object has changed.
     */
    private void onChanged() {
        dispatchChange(this);
    }

    /** The list of observers */
    private final Watcher mObserver = new Watcher() {
            @Override
            public void onChange(@Nullable Watchable what) {
                InstantAppRegistry.this.onChanged();
            }
        };

    public InstantAppRegistry(PackageManagerService service,
            PermissionManagerServiceInternal permissionManager) {
        mService = service;
        mPermissionManager = permissionManager;
        mCookiePersistence = new CookiePersistence(BackgroundThread.getHandler().getLooper());

        mUninstalledInstantApps = new WatchedSparseArray<List<UninstalledInstantAppState>>();
        mInstantGrants = new WatchedSparseArray<WatchedSparseArray<WatchedSparseBooleanArray>>();
        mInstalledInstantAppUids = new WatchedSparseArray<WatchedSparseBooleanArray>();

        mUninstalledInstantApps.registerObserver(mObserver);
        mInstantGrants.registerObserver(mObserver);
        mInstalledInstantAppUids.registerObserver(mObserver);
    }

    /**
     * The copy constructor is used by PackageManagerService to construct a snapshot.
     */
    private InstantAppRegistry(InstantAppRegistry r) {
        mService = r.mService;
        mPermissionManager = r.mPermissionManager;
        mCookiePersistence = null;

        mUninstalledInstantApps = new WatchedSparseArray<List<UninstalledInstantAppState>>(
            r.mUninstalledInstantApps);
        mInstantGrants = new WatchedSparseArray<WatchedSparseArray<WatchedSparseBooleanArray>>(
            r.mInstantGrants);
        mInstalledInstantAppUids = new WatchedSparseArray<WatchedSparseBooleanArray>(
            r.mInstalledInstantAppUids);

        // Do not register any observers.  This is a clone
    }

    /**
     * Return a snapshot: the value is the cached snapshot if available.
     */
    public InstantAppRegistry snapshot() {
        InstantAppRegistry s = mSnapshot;
        if (s == null) {
            s = new InstantAppRegistry(this);
            s.mWatchable.seal();
            mSnapshot = s;
        }
        return s;
    }

    @GuardedBy("mService.mLock")
@@ -370,37 +445,20 @@ class InstantAppRegistry {

    @GuardedBy("mService.mLock")
    public void onUserRemovedLPw(int userId) {
        if (mUninstalledInstantApps != null) {
        mUninstalledInstantApps.remove(userId);
            if (mUninstalledInstantApps.size() <= 0) {
                mUninstalledInstantApps = null;
            }
        }
        if (mInstalledInstantAppUids != null) {
        mInstalledInstantAppUids.remove(userId);
            if (mInstalledInstantAppUids.size() <= 0) {
                mInstalledInstantAppUids = null;
            }
        }
        if (mInstantGrants != null) {
        mInstantGrants.remove(userId);
            if (mInstantGrants.size() <= 0) {
                mInstantGrants = null;
            }
        }
        deleteDir(getInstantApplicationsDir(userId));
    }

    public boolean isInstantAccessGranted(@UserIdInt int userId, int targetAppId,
            int instantAppId) {
        if (mInstantGrants == null) {
            return false;
        }
        final SparseArray<SparseBooleanArray> targetAppList = mInstantGrants.get(userId);
        final WatchedSparseArray<WatchedSparseBooleanArray> targetAppList =
                mInstantGrants.get(userId);
        if (targetAppList == null) {
            return false;
        }
        final SparseBooleanArray instantGrantList = targetAppList.get(targetAppId);
        final WatchedSparseBooleanArray instantGrantList = targetAppList.get(targetAppId);
        if (instantGrantList == null) {
            return false;
        }
@@ -413,7 +471,7 @@ class InstantAppRegistry {
        if (mInstalledInstantAppUids == null) {
            return;     // no instant apps installed; no need to grant
        }
        SparseBooleanArray instantAppList = mInstalledInstantAppUids.get(userId);
        WatchedSparseBooleanArray instantAppList = mInstalledInstantAppUids.get(userId);
        if (instantAppList == null || !instantAppList.get(instantAppId)) {
            return;     // instant app id isn't installed; no need to grant
        }
@@ -426,17 +484,14 @@ class InstantAppRegistry {
                return;  // launched via VIEW/BROWSABLE intent; no need to grant
            }
        }
        if (mInstantGrants == null) {
            mInstantGrants = new SparseArray<>();
        }
        SparseArray<SparseBooleanArray> targetAppList = mInstantGrants.get(userId);
        WatchedSparseArray<WatchedSparseBooleanArray> targetAppList = mInstantGrants.get(userId);
        if (targetAppList == null) {
            targetAppList = new SparseArray<>();
            targetAppList = new WatchedSparseArray<>();
            mInstantGrants.put(userId, targetAppList);
        }
        SparseBooleanArray instantGrantList = targetAppList.get(recipientUid);
        WatchedSparseBooleanArray instantGrantList = targetAppList.get(recipientUid);
        if (instantGrantList == null) {
            instantGrantList = new SparseBooleanArray();
            instantGrantList = new WatchedSparseBooleanArray();
            targetAppList.put(recipientUid, instantGrantList);
        }
        instantGrantList.put(instantAppId, true /*granted*/);
@@ -444,15 +499,13 @@ class InstantAppRegistry {

    @GuardedBy("mService.mLock")
    public void addInstantAppLPw(@UserIdInt int userId, int instantAppId) {
        if (mInstalledInstantAppUids == null) {
            mInstalledInstantAppUids = new SparseArray<>();
        }
        SparseBooleanArray instantAppList = mInstalledInstantAppUids.get(userId);
        WatchedSparseBooleanArray instantAppList = mInstalledInstantAppUids.get(userId);
        if (instantAppList == null) {
            instantAppList = new SparseBooleanArray();
            instantAppList = new WatchedSparseBooleanArray();
            mInstalledInstantAppUids.put(userId, instantAppList);
        }
        instantAppList.put(instantAppId, true /*installed*/);
        onChanged();
    }

    @GuardedBy("mService.mLock")
@@ -461,24 +514,29 @@ class InstantAppRegistry {
        if (mInstalledInstantAppUids == null) {
            return; // no instant apps on the system
        }
        final SparseBooleanArray instantAppList = mInstalledInstantAppUids.get(userId);
        final WatchedSparseBooleanArray instantAppList = mInstalledInstantAppUids.get(userId);
        if (instantAppList == null) {
            return;
        }

        try {
            instantAppList.delete(instantAppId);

            // remove any grants
            if (mInstantGrants == null) {
                return; // no grants on the system
            }
        final SparseArray<SparseBooleanArray> targetAppList = mInstantGrants.get(userId);
            final WatchedSparseArray<WatchedSparseBooleanArray> targetAppList =
                    mInstantGrants.get(userId);
            if (targetAppList == null) {
                return; // no grants for this user
            }
            for (int i = targetAppList.size() - 1; i >= 0; --i) {
                targetAppList.valueAt(i).delete(instantAppId);
            }
        } finally {
            onChanged();
        }
    }

    @GuardedBy("mService.mLock")
@@ -487,11 +545,13 @@ class InstantAppRegistry {
        if (mInstantGrants == null) {
            return; // no grants on the system
        }
        final SparseArray<SparseBooleanArray> targetAppList = mInstantGrants.get(userId);
        final WatchedSparseArray<WatchedSparseBooleanArray> targetAppList =
                mInstantGrants.get(userId);
        if (targetAppList == null) {
            return; // no grants for this user
        }
        targetAppList.delete(targetAppId);
        onChanged();
    }

    @GuardedBy("mService.mLock")
@@ -502,9 +562,6 @@ class InstantAppRegistry {
        if (uninstalledApp == null) {
            return;
        }
        if (mUninstalledInstantApps == null) {
            mUninstalledInstantApps = new SparseArray<>();
        }
        List<UninstalledInstantAppState> uninstalledAppStates =
                mUninstalledInstantApps.get(userId);
        if (uninstalledAppStates == null) {
@@ -593,9 +650,7 @@ class InstantAppRegistry {
            uninstalledAppStates.remove(i);
            if (uninstalledAppStates.isEmpty()) {
                mUninstalledInstantApps.remove(userId);
                if (mUninstalledInstantApps.size() <= 0) {
                    mUninstalledInstantApps = null;
                }
                onChanged();
                return;
            }
        }
@@ -994,12 +1049,7 @@ class InstantAppRegistry {
            }
        }

        if (uninstalledAppStates != null) {
            if (mUninstalledInstantApps == null) {
                mUninstalledInstantApps = new SparseArray<>();
            }
        mUninstalledInstantApps.put(userId, uninstalledAppStates);
        }

        return uninstalledAppStates;
    }
+142 −42

File changed.

Preview size limit exceeded, changes collapsed.

Loading