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

Commit 242d2ce3 authored by Patrick Baumann's avatar Patrick Baumann Committed by Automerger Merge Worker
Browse files

Pre-cache filter results am: 0192f737

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/11817533

Change-Id: I82c8d3e60cb1b0e28121945d57327a877cdfa061
parents 52d0ab6d 0192f737
Loading
Loading
Loading
Loading
+330 −135
Original line number Diff line number Diff line
@@ -19,6 +19,8 @@ package com.android.server.pm;
import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
import static android.provider.DeviceConfig.NAMESPACE_PACKAGE_MANAGER_SERVICE;

import static com.android.internal.annotations.VisibleForTesting.Visibility.PRIVATE;

import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -27,6 +29,7 @@ import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
import android.content.pm.PackageParser;
import android.content.pm.UserInfo;
import android.content.pm.parsing.component.ParsedComponent;
import android.content.pm.parsing.component.ParsedInstrumentation;
import android.content.pm.parsing.component.ParsedIntentInfo;
@@ -108,12 +111,25 @@ public class AppsFilter {
    private final boolean mSystemAppsQueryable;

    private final FeatureConfig mFeatureConfig;

    private final OverlayReferenceMapper mOverlayReferenceMapper;
    private final StateProvider mStateProvider;

    private PackageParser.SigningDetails mSystemSigningDetails;
    private Set<String> mProtectedBroadcasts = new ArraySet<>();

    AppsFilter(FeatureConfig featureConfig, String[] forceQueryableWhitelist,
    /**
     * This structure maps uid -> uid and indicates whether access from the first should be
     * filtered to the second. It's essentially a cache of the
     * {@link #shouldFilterApplicationInternal(int, SettingBase, PackageSetting, int)} call.
     * NOTE: It can only be relied upon after the system is ready to avoid unnecessary update on
     * initial scam and is null until {@link #onSystemReady()} is called.
     */
    private volatile SparseArray<SparseBooleanArray> mShouldFilterCache;

    @VisibleForTesting(visibility = PRIVATE)
    AppsFilter(StateProvider stateProvider,
            FeatureConfig featureConfig,
            String[] forceQueryableWhitelist,
            boolean systemAppsQueryable,
            @Nullable OverlayReferenceMapper.Provider overlayProvider) {
        mFeatureConfig = featureConfig;
@@ -121,8 +137,23 @@ public class AppsFilter {
        mSystemAppsQueryable = systemAppsQueryable;
        mOverlayReferenceMapper = new OverlayReferenceMapper(true /*deferRebuild*/,
                overlayProvider);
        mStateProvider = stateProvider;
    }

    /**
     * Provides system state to AppsFilter via {@link CurrentStateCallback} after properly guarding
     * the data with the package lock.
     */
    @VisibleForTesting(visibility = PRIVATE)
    public interface StateProvider {
        void runWithState(CurrentStateCallback callback);

        interface CurrentStateCallback {
            void currentState(ArrayMap<String, PackageSetting> settings, UserInfo[] users);
        }
    }

    @VisibleForTesting(visibility = PRIVATE)
    public interface FeatureConfig {

        /** Called when the system is ready and components can be queried. */
@@ -139,6 +170,7 @@ public class AppsFilter {

        /**
         * Turns on logging for the given appId
         *
         * @param enable true if logging should be enabled, false if disabled.
         */
        void enableLogging(int appId, boolean enable);
@@ -146,6 +178,7 @@ public class AppsFilter {
        /**
         * Initializes the package enablement state for the given package. This gives opportunity
         * to do any expensive operations ahead of the actual checks.
         *
         * @param removed true if adding, false if removing
         */
        void updatePackageState(PackageSetting setting, boolean removed);
@@ -161,6 +194,7 @@ public class AppsFilter {

        @Nullable
        private SparseBooleanArray mLoggingEnabled = null;
        private AppsFilter mAppsFilter;

        private FeatureConfigImpl(
                PackageManagerInternal pmInternal, PackageManagerService.Injector injector) {
@@ -168,6 +202,10 @@ public class AppsFilter {
            mInjector = injector;
        }

        public void setAppsFilter(AppsFilter filter) {
            mAppsFilter = filter;
        }

        @Override
        public void onSystemReady() {
            mFeatureEnabled = DeviceConfig.getBoolean(
@@ -235,11 +273,12 @@ public class AppsFilter {
        @Override
        public void onCompatChange(String packageName) {
            updateEnabledState(mPmInternal.getPackage(packageName));
            mAppsFilter.updateShouldFilterCacheForPackage(packageName);
        }

        private void updateEnabledState(AndroidPackage pkg) {
            // TODO(b/135203078): Do not use toAppInfo
            final boolean enabled = mInjector.getCompatibility().isChangeEnabledInternal(
            final boolean enabled = mInjector.getCompatibility().isChangeEnabled(
                    PackageManager.FILTER_APPLICATION_QUERY, pkg.toAppInfoWithoutState());
            if (enabled) {
                mDisabledPackages.remove(pkg.getPackageName());
@@ -267,7 +306,7 @@ public class AppsFilter {
        final boolean forceSystemAppsQueryable =
                injector.getContext().getResources()
                        .getBoolean(R.bool.config_forceSystemPackagesQueryable);
        final FeatureConfig featureConfig = new FeatureConfigImpl(pms, injector);
        final FeatureConfigImpl featureConfig = new FeatureConfigImpl(pms, injector);
        final String[] forcedQueryablePackageNames;
        if (forceSystemAppsQueryable) {
            // all system apps already queryable, no need to read and parse individual exceptions
@@ -280,8 +319,16 @@ public class AppsFilter {
                forcedQueryablePackageNames[i] = forcedQueryablePackageNames[i].intern();
            }
        }
        return new AppsFilter(featureConfig, forcedQueryablePackageNames,
                forceSystemAppsQueryable, null);
        final StateProvider stateProvider = command -> {
            synchronized (injector.getLock()) {
                command.currentState(injector.getSettings().mPackages,
                        injector.getUserManagerInternal().getUserInfos());
            }
        };
        AppsFilter appsFilter = new AppsFilter(stateProvider, featureConfig,
                forcedQueryablePackageNames, forceSystemAppsQueryable, null);
        featureConfig.setAppsFilter(appsFilter);
        return appsFilter;
    }

    public FeatureConfig getFeatureConfig() {
@@ -407,24 +454,56 @@ public class AppsFilter {
     * @param visibleUid   the uid becoming visible to the {@recipientUid}
     */
    public void grantImplicitAccess(int recipientUid, int visibleUid) {
        if (recipientUid != visibleUid
                && mImplicitlyQueryable.add(recipientUid, visibleUid) && DEBUG_LOGGING) {
        if (recipientUid != visibleUid) {
            if (mImplicitlyQueryable.add(recipientUid, visibleUid) && DEBUG_LOGGING) {
                Slog.i(TAG, "implicit access granted: " + recipientUid + " -> " + visibleUid);
            }
            if (mShouldFilterCache != null) {
                // update the cache in a one-off manner since we've got all the information we need.
                SparseBooleanArray visibleUids = mShouldFilterCache.get(recipientUid);
                if (visibleUids == null) {
                    visibleUids = new SparseBooleanArray();
                    mShouldFilterCache.put(recipientUid, visibleUids);
                }
                visibleUids.put(visibleUid, false);
            }
        }
    }

    public void onSystemReady() {
        mStateProvider.runWithState(new StateProvider.CurrentStateCallback() {
            @Override
            public void currentState(ArrayMap<String, PackageSetting> settings,
                    UserInfo[] users) {
                mShouldFilterCache = new SparseArray<>(users.length * settings.size());
            }
        });
        mFeatureConfig.onSystemReady();
        mOverlayReferenceMapper.rebuildIfDeferred();
        updateEntireShouldFilterCache();
    }

    /**
     * Adds a package that should be considered when filtering visibility between apps.
     *
     * @param newPkgSetting the new setting being added
     * @param existingSettings all other settings currently on the device.
     */
    public void addPackage(PackageSetting newPkgSetting,
    public void addPackage(PackageSetting newPkgSetting) {
        Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "filter.addPackage");
        try {
            mStateProvider.runWithState((settings, users) -> {
                addPackageInternal(newPkgSetting, settings);
                if (mShouldFilterCache != null) {
                    updateShouldFilterCacheForPackage(
                            null, newPkgSetting, settings, users, settings.size());
                } // else, rebuild entire cache when system is ready
            });
        } finally {
            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
        }
    }

    private void addPackageInternal(PackageSetting newPkgSetting,
            ArrayMap<String, PackageSetting> existingSettings) {
        if (Objects.equals("android", newPkgSetting.name)) {
            // let's set aside the framework signatures
@@ -438,8 +517,6 @@ public class AppsFilter {
            }
        }

        Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "filter.addPackage");
        try {
        final AndroidPackage newPkg = newPkgSetting.pkg;
        if (newPkg == null) {
            // nothing to add
@@ -509,8 +586,84 @@ public class AppsFilter {
        }
        mOverlayReferenceMapper.addPkg(newPkgSetting.pkg, existingPkgs);
        mFeatureConfig.updatePackageState(newPkgSetting, false /*removed*/);
        } finally {
            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
    }

    private void removeAppIdFromVisibilityCache(int appId) {
        if (mShouldFilterCache == null) {
            return;
        }
        for (int i = mShouldFilterCache.size() - 1; i >= 0; i--) {
            if (UserHandle.getAppId(mShouldFilterCache.keyAt(i)) == appId) {
                mShouldFilterCache.removeAt(i);
                continue;
            }
            SparseBooleanArray targetSparseArray = mShouldFilterCache.valueAt(i);
            for (int j = targetSparseArray.size() - 1; j >= 0; j--) {
                if (UserHandle.getAppId(targetSparseArray.keyAt(j)) == appId) {
                    targetSparseArray.removeAt(j);
                }
            }
        }
    }

    private void updateEntireShouldFilterCache() {
        mStateProvider.runWithState((settings, users) -> {
            mShouldFilterCache.clear();
            for (int i = settings.size() - 1; i >= 0; i--) {
                updateShouldFilterCacheForPackage(
                        null /*skipPackage*/, settings.valueAt(i), settings, users, i);
            }
        });
    }

    public void onUsersChanged() {
        if (mShouldFilterCache != null) {
            updateEntireShouldFilterCache();
        }
    }

    private void updateShouldFilterCacheForPackage(String packageName) {
        mStateProvider.runWithState((settings, users) -> {
            updateShouldFilterCacheForPackage(null /* skipPackage */, settings.get(packageName),
                    settings, users, settings.size() /*maxIndex*/);
        });

    }

    private void updateShouldFilterCacheForPackage(@Nullable String skipPackageName,
            PackageSetting subjectSetting, ArrayMap<String, PackageSetting> allSettings,
            UserInfo[] allUsers, int maxIndex) {
        for (int i = Math.min(maxIndex, allSettings.size() - 1); i >= 0; i--) {
            PackageSetting otherSetting = allSettings.valueAt(i);
            if (subjectSetting.appId == otherSetting.appId) {
                continue;
            }
            //noinspection StringEquality
            if (subjectSetting.name == skipPackageName || otherSetting.name == skipPackageName) {
                continue;
            }
            final int userCount = allUsers.length;
            final int appxUidCount = userCount * allSettings.size();
            for (int su = 0; su < userCount; su++) {
                int subjectUser = allUsers[su].id;
                for (int ou = su; ou < userCount; ou++) {
                    int otherUser = allUsers[ou].id;
                    int subjectUid = UserHandle.getUid(subjectUser, subjectSetting.appId);
                    if (!mShouldFilterCache.contains(subjectUid)) {
                        mShouldFilterCache.put(subjectUid, new SparseBooleanArray(appxUidCount));
                    }
                    int otherUid = UserHandle.getUid(otherUser, otherSetting.appId);
                    if (!mShouldFilterCache.contains(otherUid)) {
                        mShouldFilterCache.put(otherUid, new SparseBooleanArray(appxUidCount));
                    }
                    mShouldFilterCache.get(subjectUid).put(otherUid,
                            shouldFilterApplicationInternal(
                                    subjectUid, subjectSetting, otherSetting, otherUser));
                    mShouldFilterCache.get(otherUid).put(subjectUid,
                            shouldFilterApplicationInternal(
                                    otherUid, otherSetting, subjectSetting, subjectUser));
                }
            }
        }
    }

@@ -561,6 +714,7 @@ public class AppsFilter {
            }
        }
    }

    /**
     * Fetches all app Ids that a given setting is currently visible to, per provided user. This
     * only includes UIDs >= {@link Process#FIRST_APPLICATION_UID} as all other UIDs can already see
@@ -619,14 +773,13 @@ public class AppsFilter {
     * Removes a package for consideration when filtering visibility between apps.
     *
     * @param setting the setting of the package being removed.
     * @param allUsers array of all current users on device.
     */
    public void removePackage(PackageSetting setting, int[] allUsers,
            ArrayMap<String, PackageSetting> existingSettings) {
        mForceQueryable.remove(setting.appId);

        for (int u = 0; u < allUsers.length; u++) {
            final int userId = allUsers[u];
    public void removePackage(PackageSetting setting) {
        removeAppIdFromVisibilityCache(setting.appId);
        mStateProvider.runWithState((settings, users) -> {
            final int userCount = users.length;
            for (int u = 0; u < userCount; u++) {
                final int userId = users[u].id;
                final int removingUid = UserHandle.getUid(userId, setting.appId);
                mImplicitlyQueryable.remove(removingUid);
                for (int i = mImplicitlyQueryable.size() - 1; i >= 0; i--) {
@@ -650,7 +803,8 @@ public class AppsFilter {
                    if (setting.sharedUser.packages.valueAt(i) == setting) {
                        continue;
                    }
                addPackage(setting.sharedUser.packages.valueAt(i), existingSettings);
                    addPackageInternal(
                            setting.sharedUser.packages.valueAt(i), settings);
                }
            }

@@ -658,12 +812,21 @@ public class AppsFilter {
                final String removingPackageName = setting.pkg.getPackageName();
                mProtectedBroadcasts.clear();
                mProtectedBroadcasts.addAll(
                    collectProtectedBroadcasts(existingSettings, removingPackageName));
            recomputeComponentVisibility(existingSettings, removingPackageName);
                        collectProtectedBroadcasts(settings, removingPackageName));
                recomputeComponentVisibility(settings, removingPackageName);
            }

            mOverlayReferenceMapper.removePkg(setting.name);
            mFeatureConfig.updatePackageState(setting, true /*removed*/);

            if (mShouldFilterCache != null) {
                updateShouldFilterCacheForPackage(
                        setting.name, setting, settings, users, settings.size());
            }
        });
        mForceQueryable.remove(setting.appId);


    }

    /**
@@ -680,11 +843,32 @@ public class AppsFilter {
            PackageSetting targetPkgSetting, int userId) {
        Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "shouldFilterApplication");
        try {

            if (callingUid < Process.FIRST_APPLICATION_UID
                    || UserHandle.getAppId(callingUid) == targetPkgSetting.appId) {
                return false;
            }
            if (mShouldFilterCache != null) { // use cache
                SparseBooleanArray shouldFilterTargets = mShouldFilterCache.get(callingUid);
                final int targetUid = UserHandle.getUid(userId, targetPkgSetting.appId);
                if (shouldFilterTargets == null) {
                    Slog.wtf(TAG, "Encountered calling uid with no cached rules: " + callingUid);
                    return true;
                }
                int indexOfTargetUid = shouldFilterTargets.indexOfKey(targetUid);
                if (indexOfTargetUid < 0) {
                    Slog.w(TAG, "Encountered calling -> target with no cached rules: "
                            + callingUid + " -> " + targetUid);
                    return true;
                }
                if (!shouldFilterTargets.valueAt(indexOfTargetUid)) {
                    return false;
                }
            } else {
                if (!shouldFilterApplicationInternal(
                        callingUid, callingSetting, targetPkgSetting, userId)) {
                    return false;
                }
            }
            if (DEBUG_LOGGING || mFeatureConfig.isLoggingEnabled(UserHandle.getAppId(callingUid))) {
                log(callingSetting, targetPkgSetting, "BLOCKED");
            }
@@ -695,7 +879,7 @@ public class AppsFilter {
    }

    private boolean shouldFilterApplicationInternal(int callingUid, SettingBase callingSetting,
            PackageSetting targetPkgSetting, int userId) {
            PackageSetting targetPkgSetting, int targetUserId) {
        Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "shouldFilterApplicationInternal");
        try {
            final boolean featureEnabled = mFeatureConfig.isGloballyEnabled();
@@ -705,12 +889,6 @@ public class AppsFilter {
                }
                return false;
            }
            if (callingUid < Process.FIRST_APPLICATION_UID) {
                if (DEBUG_LOGGING) {
                    Slog.d(TAG, "filtering skipped; " + callingUid + " is system");
                }
                return false;
            }
            if (callingSetting == null) {
                Slog.wtf(TAG, "No setting found for non system uid " + callingUid);
                return true;
@@ -719,8 +897,14 @@ public class AppsFilter {
            final ArraySet<PackageSetting> callingSharedPkgSettings;
            Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "callingSetting instanceof");
            if (callingSetting instanceof PackageSetting) {
                if (((PackageSetting) callingSetting).sharedUser == null) {
                    callingPkgSetting = (PackageSetting) callingSetting;
                    callingSharedPkgSettings = null;
                } else {
                    callingPkgSetting = null;
                    callingSharedPkgSettings =
                            ((PackageSetting) callingSetting).sharedUser.packages;
                }
            } else {
                callingPkgSetting = null;
                callingSharedPkgSettings = ((SharedUserSetting) callingSetting).packages;
@@ -778,14 +962,18 @@ public class AppsFilter {
            }

            try {
                Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "hasPermission");
                if (callingSetting.getPermissionsState().hasPermission(
                        Manifest.permission.QUERY_ALL_PACKAGES, UserHandle.getUserId(callingUid))) {
                    if (DEBUG_LOGGING) {
                        log(callingSetting, targetPkgSetting, "has query-all permission");
                Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "requestsQueryAllPackages");
                if (callingPkgSetting != null) {
                    if (requestsQueryAllPackages(callingPkgSetting)) {
                        return false;
                    }
                } else {
                    for (int i = callingSharedPkgSettings.size() - 1; i >= 0; i--) {
                        if (requestsQueryAllPackages(callingSharedPkgSettings.valueAt(i))) {
                            return false;
                        }
                    }
                }
            } finally {
                Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
            }
@@ -825,7 +1013,7 @@ public class AppsFilter {

            try {
                Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "mImplicitlyQueryable");
                final int targetUid = UserHandle.getUid(userId, targetAppId);
                final int targetUid = UserHandle.getUid(targetUserId, targetAppId);
                if (mImplicitlyQueryable.contains(callingUid, targetUid)) {
                    if (DEBUG_LOGGING) {
                        log(callingSetting, targetPkgSetting, "implicitly queryable for user");
@@ -863,13 +1051,20 @@ public class AppsFilter {
                Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
            }


            return true;
        } finally {
            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
        }
    }


    private static boolean requestsQueryAllPackages(PackageSetting pkgSetting) {
        // we're not guaranteed to have permissions yet analyzed at package add, so we inspect the
        // package directly
        return pkgSetting.pkg.getRequestedPermissions().contains(
                Manifest.permission.QUERY_ALL_PACKAGES);
    }

    /** Returns {@code true} if the source package instruments the target package. */
    private static boolean pkgInstruments(PackageSetting source, PackageSetting target) {
        try {
+4 −4
Original line number Diff line number Diff line
@@ -12362,7 +12362,7 @@ public class PackageManagerService extends IPackageManager.Stub
            ksms.addScannedPackageLPw(pkg);
            mComponentResolver.addAllComponents(pkg, chatty);
            mAppsFilter.addPackage(pkgSetting, mSettings.mPackages);
            mAppsFilter.addPackage(pkgSetting);
            // Don't allow ephemeral applications to define new permissions groups.
            if ((scanFlags & SCAN_AS_INSTANT_APP) != 0) {
@@ -12536,8 +12536,6 @@ public class PackageManagerService extends IPackageManager.Stub
    void cleanPackageDataStructuresLILPw(AndroidPackage pkg, boolean chatty) {
        mComponentResolver.removeAllComponents(pkg, chatty);
        mAppsFilter.removePackage(getPackageSetting(pkg.getPackageName()),
                mInjector.getUserManagerInternal().getUserIds(), mSettings.mPackages);
        mPermissionManager.removeAllPermissions(pkg, chatty);
        final int instrumentationSize = ArrayUtils.size(pkg.getInstrumentations());
@@ -14264,7 +14262,7 @@ public class PackageManagerService extends IPackageManager.Stub
            // Okay!
            targetPackageSetting.setInstallerPackageName(installerPackageName);
            mSettings.addInstallerPackageNames(targetPackageSetting.installSource);
            mAppsFilter.addPackage(targetPackageSetting, mSettings.mPackages);
            mAppsFilter.addPackage(targetPackageSetting);
            scheduleWriteSettingsLocked();
        }
    }
@@ -18717,6 +18715,7 @@ public class PackageManagerService extends IPackageManager.Stub
                    clearIntentFilterVerificationsLPw(deletedPs.name, UserHandle.USER_ALL, true);
                    clearDefaultBrowserIfNeeded(packageName);
                    mSettings.mKeySetManagerService.removeAppKeySetDataLPw(packageName);
                    mAppsFilter.removePackage(getPackageSetting(packageName));
                    removedAppId = mSettings.removePackageLPw(packageName);
                    if (outInfo != null) {
                        outInfo.removedAppId = removedAppId;
@@ -23474,6 +23473,7 @@ public class PackageManagerService extends IPackageManager.Stub
            scheduleWritePackageRestrictionsLocked(userId);
            scheduleWritePackageListLocked(userId);
            primeDomainVerificationsLPw(userId);
            mAppsFilter.onUsersChanged();
        }
    }
+229 −157

File changed.

Preview size limit exceeded, changes collapsed.