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

Commit 28c8fcb5 authored by Rhed Jao's avatar Rhed Jao Committed by Android (Google) Code Review
Browse files

Merge changes I301a7f78,Id9dbd4e5

* changes:
  Improve the cache rebuild latency of AppsFilter on boot #2
  Improve the cache rebuild latency of AppsFilter on boot
parents 4fdfbd70 0931466b
Loading
Loading
Loading
Loading
+8 −18
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@ import com.android.internal.util.function.QuadFunction;
import com.android.server.om.OverlayReferenceMapper;
import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageStateInternal;
import com.android.server.pm.pkg.SharedUserApi;
import com.android.server.pm.snapshot.PackageDataSnapshot;
import com.android.server.utils.SnapshotCache;
import com.android.server.utils.Watched;
@@ -51,7 +52,6 @@ import com.android.server.utils.WatchedSparseSetArray;

import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Collection;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean;

@@ -137,10 +137,9 @@ public abstract class AppsFilterBase implements AppsFilterSnapshot {
    protected SnapshotCache<WatchedSparseSetArray<Integer>> mQueryableViaUsesPermissionSnapshot;

    /**
     * Handler for running reasonably short background tasks such as building the initial
     * visibility cache.
     * Handler for running tasks such as building the initial visibility cache.
     */
    protected Handler mBackgroundHandler;
    protected Handler mHandler;

    /**
     * Pending full recompute of mQueriesViaComponent. Occurs when a package adds a new set of
@@ -410,9 +409,11 @@ public abstract class AppsFilterBase implements AppsFilterSnapshot {
                final PackageStateInternal packageState = (PackageStateInternal) callingSetting;
                if (packageState.hasSharedUser()) {
                    callingPkgSetting = null;
                    callingSharedPkgSettings.addAll(getSharedUserPackages(
                            packageState.getSharedUserAppId(), snapshot.getAllSharedUsers()));

                    final SharedUserApi sharedUserApi =
                            snapshot.getSharedUser(packageState.getSharedUserAppId());
                    if (sharedUserApi != null) {
                        callingSharedPkgSettings.addAll(sharedUserApi.getPackageStates());
                    }
                } else {
                    callingPkgSetting = packageState;
                }
@@ -699,17 +700,6 @@ public abstract class AppsFilterBase implements AppsFilterSnapshot {
                        + targetPkgSetting + " " + description);
    }

    protected ArraySet<? extends PackageStateInternal> getSharedUserPackages(int sharedUserAppId,
            Collection<SharedUserSetting> sharedUserSettings) {
        for (SharedUserSetting setting : sharedUserSettings) {
            if (setting.mAppId != sharedUserAppId) {
                continue;
            }
            return setting.getPackageStates();
        }
        return new ArraySet<>();
    }

    /**
     * See {@link AppsFilterSnapshot#dumpQueries(PrintWriter, Integer, DumpState, int[],
     * QuadFunction)}
+19 −37
Original line number Diff line number Diff line
@@ -35,7 +35,6 @@ import static com.android.server.pm.AppsFilterUtils.canQueryAsInstaller;
import static com.android.server.pm.AppsFilterUtils.canQueryViaComponents;
import static com.android.server.pm.AppsFilterUtils.canQueryViaPackage;
import static com.android.server.pm.AppsFilterUtils.canQueryViaUsesLibrary;
import static com.android.server.pm.AppsFilterUtils.requestsQueryAllPackages;

import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -63,9 +62,11 @@ import com.android.internal.util.FrameworkStatsLog;
import com.android.server.FgThread;
import com.android.server.compat.CompatChange;
import com.android.server.om.OverlayReferenceMapper;
import com.android.server.pm.AppsFilterUtils.ParallelComputeComponentVisibility;
import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageStateInternal;
import com.android.server.pm.pkg.SharedUserApi;
import com.android.server.pm.pkg.component.ParsedInstrumentation;
import com.android.server.pm.pkg.component.ParsedPermission;
import com.android.server.pm.pkg.component.ParsedUsesPermission;
@@ -80,7 +81,6 @@ import com.android.server.utils.Watcher;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Objects;

@@ -185,13 +185,13 @@ public final class AppsFilterImpl extends AppsFilterLocked implements Watchable,
            String[] forceQueryableList,
            boolean systemAppsQueryable,
            @Nullable OverlayReferenceMapper.Provider overlayProvider,
            Handler backgroundHandler) {
            Handler handler) {
        mFeatureConfig = featureConfig;
        mForceQueryableByDevicePackageNames = forceQueryableList;
        mSystemAppsQueryable = systemAppsQueryable;
        mOverlayReferenceMapper = new OverlayReferenceMapper(true /*deferRebuild*/,
                overlayProvider);
        mBackgroundHandler = backgroundHandler;
        mHandler = handler;
        mShouldFilterCache = new WatchedSparseBooleanMatrix();
        mShouldFilterCacheSnapshot = new SnapshotCache.Auto<>(
                mShouldFilterCache, mShouldFilterCache, "AppsFilter.mShouldFilterCache");
@@ -428,7 +428,7 @@ public final class AppsFilterImpl extends AppsFilterLocked implements Watchable,
        }
        AppsFilterImpl appsFilter = new AppsFilterImpl(featureConfig,
                forcedQueryablePackageNames, forceSystemAppsQueryable, null,
                injector.getBackgroundHandler());
                injector.getHandler());
        featureConfig.setAppsFilter(appsFilter);
        return appsFilter;
    }
@@ -797,7 +797,7 @@ public final class AppsFilterImpl extends AppsFilterLocked implements Watchable,

    private void updateEntireShouldFilterCacheAsync(PackageManagerInternal pmInternal,
            long delayMs, int reason) {
        mBackgroundHandler.postDelayed(() -> {
        mHandler.postDelayed(() -> {
            if (!mCacheValid.compareAndSet(CACHE_INVALID, CACHE_VALID)) {
                // Cache is already valid.
                return;
@@ -990,34 +990,15 @@ public final class AppsFilterImpl extends AppsFilterLocked implements Watchable,
     */
    private void recomputeComponentVisibility(
            ArrayMap<String, ? extends PackageStateInternal> existingSettings) {
        synchronized (mQueriesViaComponentLock) {
            mQueriesViaComponent.clear();
        }
        for (int i = existingSettings.size() - 1; i >= 0; i--) {
            PackageStateInternal setting = existingSettings.valueAt(i);
            if (setting.getPkg() == null || requestsQueryAllPackages(setting.getPkg())) {
                continue;
            }
            for (int j = existingSettings.size() - 1; j >= 0; j--) {
                if (i == j) {
                    continue;
                }
                final PackageStateInternal otherSetting = existingSettings.valueAt(j);
                if (otherSetting.getPkg() == null || mForceQueryable.contains(
                        otherSetting.getAppId())) {
                    continue;
                }
                final boolean canQueryViaComponents;
        final WatchedArraySet<String> protectedBroadcasts;
        synchronized (mProtectedBroadcastsLock) {
                    canQueryViaComponents = canQueryViaComponents(setting.getPkg(),
                            otherSetting.getPkg(), mProtectedBroadcasts);
            protectedBroadcasts = mProtectedBroadcasts.snapshot();
        }
                if (canQueryViaComponents) {
        final ParallelComputeComponentVisibility computer = new ParallelComputeComponentVisibility(
                existingSettings, mForceQueryable, protectedBroadcasts);
        synchronized (mQueriesViaComponentLock) {
                        mQueriesViaComponent.add(setting.getAppId(), otherSetting.getAppId());
                    }
                }
            }
            mQueriesViaComponent.clear();
            computer.execute(mQueriesViaComponent);
        }

        mQueriesViaComponentRequireRecompute.set(false);
@@ -1066,7 +1047,6 @@ public final class AppsFilterImpl extends AppsFilterLocked implements Watchable,
        final ArrayMap<String, ? extends PackageStateInternal> settings =
                snapshot.getPackageStates();
        final UserInfo[] users = snapshot.getUserInfos();
        final Collection<SharedUserSetting> sharedUserSettings = snapshot.getAllSharedUsers();
        final int userCount = users.length;
        if (!isReplace || !retainImplicitGrantOnReplace) {
            synchronized (mImplicitlyQueryableLock) {
@@ -1175,9 +1155,11 @@ public final class AppsFilterImpl extends AppsFilterLocked implements Watchable,
        // shared user members to re-establish visibility between them and other packages.
        // NOTE: this must come after all removals from data structures but before we update the
        // cache
        if (setting.hasSharedUser()) {
        final SharedUserApi sharedUserApi = setting.hasSharedUser()
                ? snapshot.getSharedUser(setting.getSharedUserAppId()) : null;
        if (sharedUserApi != null) {
            final ArraySet<? extends PackageStateInternal> sharedUserPackages =
                    getSharedUserPackages(setting.getSharedUserAppId(), sharedUserSettings);
                    sharedUserApi.getPackageStates();
            for (int i = sharedUserPackages.size() - 1; i >= 0; i--) {
                if (sharedUserPackages.valueAt(i) == setting) {
                    continue;
@@ -1190,9 +1172,9 @@ public final class AppsFilterImpl extends AppsFilterLocked implements Watchable,
        if (mCacheReady) {
            removeAppIdFromVisibilityCache(setting.getAppId());

            if (setting.hasSharedUser()) {
            if (sharedUserApi != null) {
                final ArraySet<? extends PackageStateInternal> sharedUserPackages =
                        getSharedUserPackages(setting.getSharedUserAppId(), sharedUserSettings);
                        sharedUserApi.getPackageStates();
                for (int i = sharedUserPackages.size() - 1; i >= 0; i--) {
                    PackageStateInternal siblingSetting =
                            sharedUserPackages.valueAt(i);
+1 −1
Original line number Diff line number Diff line
@@ -77,6 +77,6 @@ public final class AppsFilterSnapshotImpl extends AppsFilterBase {
        mCacheEnabled = orig.mCacheEnabled;
        mShouldFilterCacheSnapshot = new SnapshotCache.Sealed<>();

        mBackgroundHandler = null;
        mHandler = null;
    }
}
+101 −0
Original line number Diff line number Diff line
@@ -16,24 +16,36 @@

package com.android.server.pm;

import static android.os.Process.THREAD_PRIORITY_DEFAULT;

import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Intent;
import android.content.IntentFilter;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Pair;

import com.android.internal.util.ArrayUtils;
import com.android.internal.util.ConcurrentUtils;
import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageState;
import com.android.server.pm.pkg.PackageStateInternal;
import com.android.server.pm.pkg.component.ParsedComponent;
import com.android.server.pm.pkg.component.ParsedIntentInfo;
import com.android.server.pm.pkg.component.ParsedMainComponent;
import com.android.server.pm.pkg.component.ParsedProvider;
import com.android.server.utils.WatchedArraySet;
import com.android.server.utils.WatchedSparseSetArray;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;

final class AppsFilterUtils {
    public static boolean requestsQueryAllPackages(@NonNull AndroidPackage pkg) {
@@ -169,4 +181,93 @@ final class AppsFilterUtils {
                intent.getData(), intent.getCategories(), "AppsFilter", true,
                protectedBroadcasts != null ? protectedBroadcasts.untrackedStorage() : null) > 0;
    }

    /**
     * A helper class for parallel computing of component visibility of all packages on the device.
     */
    public static final class ParallelComputeComponentVisibility {
        private static final int MAX_THREADS = 4;

        private final ArrayMap<String, ? extends PackageStateInternal> mExistingSettings;
        private final WatchedArraySet<Integer> mForceQueryable;
        private final WatchedArraySet<String> mProtectedBroadcasts;

        ParallelComputeComponentVisibility(
                @NonNull ArrayMap<String, ? extends PackageStateInternal> existingSettings,
                @NonNull WatchedArraySet<Integer> forceQueryable,
                @NonNull WatchedArraySet<String> protectedBroadcasts) {
            mExistingSettings = existingSettings;
            mForceQueryable = forceQueryable;
            mProtectedBroadcasts = protectedBroadcasts;
        }

        /**
         * Computes component visibility of all packages in parallel from a thread pool.
         */
        void execute(@NonNull WatchedSparseSetArray<Integer> outQueriesViaComponent) {
            final ExecutorService pool = ConcurrentUtils.newFixedThreadPool(
                    MAX_THREADS, ParallelComputeComponentVisibility.class.getSimpleName(),
                    THREAD_PRIORITY_DEFAULT);
            try {
                final List<Pair<PackageState, Future<ArraySet<Integer>>>> futures =
                        new ArrayList<>();
                for (int i = mExistingSettings.size() - 1; i >= 0; i--) {
                    final PackageStateInternal setting = mExistingSettings.valueAt(i);
                    final AndroidPackage pkg = setting.getPkg();
                    if (pkg == null || requestsQueryAllPackages(pkg)) {
                        continue;
                    }
                    if (pkg.getQueriesIntents().isEmpty()
                            && pkg.getQueriesProviders().isEmpty()) {
                        continue;
                    }
                    futures.add(new Pair(setting,
                            pool.submit(() -> getVisibleListOfQueryViaComponents(setting))));
                }
                for (int i = 0; i < futures.size(); i++) {
                    final int appId = futures.get(i).first.getAppId();
                    final Future<ArraySet<Integer>> future = futures.get(i).second;
                    try {
                        final ArraySet<Integer> visibleList = future.get();
                        if (visibleList.size() != 0) {
                            outQueriesViaComponent.addAll(appId, visibleList);
                        }
                    } catch (InterruptedException | ExecutionException e) {
                        throw new IllegalStateException(e);
                    }
                }
            } finally {
                pool.shutdownNow();
            }
        }

        /**
         * Returns a set of app IDs that contains components resolved by the queries intent
         * or provider that declared in the manifest of the querying package.
         *
         * @param setting The package to query.
         * @return A set of app IDs.
         */
        @NonNull
        private ArraySet<Integer> getVisibleListOfQueryViaComponents(
                @NonNull PackageStateInternal setting) {
            final ArraySet<Integer> result = new ArraySet();
            for (int i = mExistingSettings.size() - 1; i >= 0; i--) {
                final PackageStateInternal otherSetting = mExistingSettings.valueAt(i);
                if (setting.getAppId() == otherSetting.getAppId()) {
                    continue;
                }
                if (otherSetting.getPkg() == null || mForceQueryable.contains(
                        otherSetting.getAppId())) {
                    continue;
                }
                final boolean canQuery = canQueryViaComponents(
                        setting.getPkg(), otherSetting.getPkg(), mProtectedBroadcasts);
                if (canQuery) {
                    result.add(otherSetting.getAppId());
                }
            }
            return result;
        }
    }
}
+8 −0
Original line number Diff line number Diff line
@@ -64,6 +64,14 @@ public class WatchedSparseSetArray<T> extends WatchableImpl implements Snappable
        return res;
    }

    /**
     * Add a set of values for key n.
     */
    public void addAll(int n, ArraySet<T> values) {
        mStorage.addAll(n, values);
        onChanged();
    }

    /**
     * Removes all mappings from this SparseSetArray.
     */
Loading