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

Commit 4a174d6f authored by Yuting Fang's avatar Yuting Fang Committed by Android (Google) Code Review
Browse files

Merge "Add cache for AppOpsManager#checkPackage" into main

parents f2e187ac ec7ac1f0
Loading
Loading
Loading
Loading
+65 −1
Original line number Diff line number Diff line
@@ -8258,6 +8258,10 @@ public class AppOpsManager {
    private static final String APP_OP_MODE_CACHING_NAME = "appOpModeCache";
    private static final int APP_OP_MODE_CACHING_SIZE = 2048;

    private static final String CHECK_PACKAGE_CACHING_API = "checkPackage";
    private static final String CHECK_PACKAGE_CACHING_NAME = "checkPackageCache";
    private static final int CHECK_PACKAGE_CACHING_SIZE = 512;

    private static final IpcDataCache.QueryHandler<AppOpModeQuery, Integer> sGetAppOpModeQuery =
            new IpcDataCache.QueryHandler<>() {
                @Override
@@ -8278,12 +8282,36 @@ public class AppOpsManager {
                }
            };

    private static final IpcDataCache.QueryHandler<CheckPackageQuery, Integer> sCheckPackageQuery =
            new IpcDataCache.QueryHandler<>() {
                @Override
                public Integer apply(CheckPackageQuery query) {
                    IAppOpsService service = getService();
                    try {
                        return service.checkPackage(query.uid, query.packageName);
                    } catch (RemoteException e) {
                        throw e.rethrowFromSystemServer();
                    }
                }

                @Override
                public boolean shouldBypassCache(@NonNull CheckPackageQuery query) {
                    // If the flag to enable the new caching behavior is off, bypass the cache.
                    return !Flags.checkPackageCachingEnabled();
                }
            };


    // A LRU cache on binder clients that caches AppOp mode by uid, packageName, virtualDeviceId
    // and attributionTag.
    private static final IpcDataCache<AppOpModeQuery, Integer> sAppOpModeCache =
            new IpcDataCache<>(APP_OP_MODE_CACHING_SIZE, IpcDataCache.MODULE_SYSTEM,
                    APP_OP_MODE_CACHING_API, APP_OP_MODE_CACHING_NAME, sGetAppOpModeQuery);

    private static final IpcDataCache<CheckPackageQuery, Integer> sCheckPackageCache =
            new IpcDataCache<>(CHECK_PACKAGE_CACHING_SIZE, IpcDataCache.MODULE_SYSTEM,
                    CHECK_PACKAGE_CACHING_API, CHECK_PACKAGE_CACHING_NAME, sCheckPackageQuery);

    // Ops that we don't want to cache due to:
    // 1) Discrepancy of attributionTag support in checkOp and noteOp that determines if a package
    //    can bypass user restriction of an op: b/240617242. COARSE_LOCATION and FINE_LOCATION are
@@ -8321,6 +8349,34 @@ public class AppOpsManager {
        }
    }

    /**
     * @hide
     */
    public static void invalidateCheckPackageCache() {
        if (Flags.checkPackageCachingEnabled()) {
            IpcDataCache.invalidateCache(IpcDataCache.MODULE_SYSTEM, CHECK_PACKAGE_CACHING_API);
        }
    }

    /**
     * Bypass CheckPackageCache in the local process
     *
     * @hide
     */
    public static void disableCheckPackageCache() {
        if (Flags.checkPackageCachingEnabled()) {
            sCheckPackageCache.disableLocal();
        }
    }

    private record CheckPackageQuery(int uid, @NonNull String packageName) {
        @Override
        public String toString() {
            return TextUtils.formatSimple("CheckPackageQuery(uid=%d, packageName=%s)", uid,
                    packageName);
        }
    }

    private static final class AppOpModeQuery {
        final int op;
        final int uid;
@@ -10122,7 +10178,15 @@ public class AppOpsManager {
    @Deprecated
    public void checkPackage(int uid, @NonNull String packageName) {
        try {
            if (mService.checkPackage(uid, packageName) != MODE_ALLOWED) {
            int mode;
            if (Flags.checkPackageCachingEnabled()) {
                mode = sCheckPackageCache.query(
                        new CheckPackageQuery(uid, packageName));
            } else {
                mode = mService.checkPackage(uid, packageName);
            }

            if (mode != MODE_ALLOWED) {
                throw new SecurityException(
                        "Package " + packageName + " does not belong to " + uid);
            }
+8 −0
Original line number Diff line number Diff line
@@ -605,3 +605,11 @@ flag {
    description: "This flags app ops cell reporting tied to ACCESS_FINE_LOCATION or ACCESS_COARSE_LOCATION"
    bug: "420985100"
}

flag {
    name: "check_package_caching_enabled"
    is_fixed_read_only: true
    namespace: "permissions"
    description: "Enable checkPackage caching in AppOpsManager"
    bug: "423030916"
}
+2 −0
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ import static com.android.server.pm.AppsFilterUtils.canQueryViaUsesLibrary;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.AppOpsManager;
import android.app.ApplicationPackageManager;
import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
@@ -180,6 +181,7 @@ public final class AppsFilterImpl extends AppsFilterLocked implements Watchable,
        PackageManagerService.invalidatePackageInfoCache(invalidationReason);
        PackageManagerService.invalidateGetPackagesForUidCache(invalidationReason);
        ApplicationPackageManager.invalidateQueryIntentActivitiesCache();
        AppOpsManager.invalidateCheckPackageCache();
        dispatchChange(this);
    }

+2 −0
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SpecialUsers.CanBeALL;
import android.annotation.UserIdInt;
import android.app.AppOpsManager;
import android.app.ApplicationExitInfo;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
@@ -265,6 +266,7 @@ final class DeletePackageHelper {
            }
            PackageManagerService.invalidateGetPackagesForUidCache(
                    PackageMetrics.INVALIDATION_REASON_DELETE_PACKAGE);
            AppOpsManager.invalidateCheckPackageCache();
        }

        if (res) {
+1 −0
Original line number Diff line number Diff line
@@ -2528,6 +2528,7 @@ final class InstallPackageHelper {
        }
        PackageManagerService.invalidateGetPackagesForUidCache(
                PackageMetrics.INVALIDATION_REASON_INSTALL_PACKAGE);
        AppOpsManager.invalidateCheckPackageCache();
    }

    @GuardedBy("mPm.mLock")
Loading