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

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

Merge "PM caches now cache nulls" into main

parents 4a26f673 e6751e09
Loading
Loading
Loading
Loading
+13 −10
Original line number Diff line number Diff line
@@ -17,7 +17,6 @@
package android.app;

import static android.app.PropertyInvalidatedCache.MODULE_SYSTEM;
import static android.app.PropertyInvalidatedCache.createSystemCacheKey;
import static android.app.admin.DevicePolicyResources.Drawables.Style.SOLID_COLORED;
import static android.app.admin.DevicePolicyResources.Drawables.Style.SOLID_NOT_COLORED;
import static android.app.admin.DevicePolicyResources.Drawables.WORK_PROFILE_ICON;
@@ -1146,12 +1145,16 @@ public class ApplicationPackageManager extends PackageManager {
        }
    }

    private static final String CACHE_KEY_PACKAGES_FOR_UID_PROPERTY =
            createSystemCacheKey("get_packages_for_uid");
    private static final PropertyInvalidatedCache<Integer, GetPackagesForUidResult>
            mGetPackagesForUidCache =
            new PropertyInvalidatedCache<Integer, GetPackagesForUidResult>(
                1024, CACHE_KEY_PACKAGES_FOR_UID_PROPERTY) {
    private static final String CACHE_KEY_PACKAGES_FOR_UID_API = "get_packages_for_uid";

    /** @hide */
    @VisibleForTesting
    public static final PropertyInvalidatedCache<Integer, GetPackagesForUidResult>
            sGetPackagesForUidCache = new PropertyInvalidatedCache<>(
                new PropertyInvalidatedCache.Args(MODULE_SYSTEM)
                .maxEntries(1024).api(CACHE_KEY_PACKAGES_FOR_UID_API).cacheNulls(true),
                CACHE_KEY_PACKAGES_FOR_UID_API, null) {

                @Override
                public GetPackagesForUidResult recompute(Integer uid) {
                    try {
@@ -1170,17 +1173,17 @@ public class ApplicationPackageManager extends PackageManager {

    @Override
    public String[] getPackagesForUid(int uid) {
        return mGetPackagesForUidCache.query(uid).value();
        return sGetPackagesForUidCache.query(uid).value();
    }

    /** @hide */
    public static void disableGetPackagesForUidCache() {
        mGetPackagesForUidCache.disableLocal();
        sGetPackagesForUidCache.disableLocal();
    }

    /** @hide */
    public static void invalidateGetPackagesForUidCache() {
        PropertyInvalidatedCache.invalidateCache(CACHE_KEY_PACKAGES_FOR_UID_PROPERTY);
        sGetPackagesForUidCache.invalidateCache();
    }

    @Override
+26 −6
Original line number Diff line number Diff line
@@ -1162,6 +1162,17 @@ public class PropertyInvalidatedCache<Query, Result> {
        return new NonceWatcher(getNonceHandler(propertyName));
    }

    /**
     * Return the current cache nonce.
     * @hide
     */
    @VisibleForTesting
    public long getNonce() {
        synchronized (mLock) {
            return mNonce.getNonce();
        }
    }

    /**
     * Complete key prefixes.
     */
@@ -1314,7 +1325,7 @@ public class PropertyInvalidatedCache<Query, Result> {

    /**
     * Burst a property name into module and api.  Throw if the key is invalid.  This method is
     * used in to transition legacy cache constructors to the args constructor.
     * used to transition legacy cache constructors to the Args constructor.
     */
    private static Args argsFromProperty(@NonNull String name) {
        throwIfInvalidCacheKey(name);
@@ -1326,6 +1337,15 @@ public class PropertyInvalidatedCache<Query, Result> {
        return new Args(module).api(api);
    }

    /**
     * Return the API porting of a legacy property.  This method is used to transition caches to
     * the Args constructor.
     * @hide
     */
    public static String apiFromProperty(@NonNull String name) {
        return argsFromProperty(name).mApi;
    }

    /**
     * Make a new property invalidated cache.  This constructor names the cache after the
     * property name.  New clients should prefer the constructor that takes an explicit
@@ -2036,11 +2056,11 @@ public class PropertyInvalidatedCache<Query, Result> {
    }

    /**
     * Disable all caches in the local process.  This is primarily useful for testing when
     * the test needs to bypass the cache or when the test is for a server, and the test
     * process does not have privileges to write SystemProperties. Once disabled it is not
     * possible to re-enable caching in the current process.  If a client wants to
     * temporarily disable caching, use the corking mechanism.
     * Disable all caches in the local process.  This is primarily useful for testing when the
     * test needs to bypass the cache or when the test is for a server, and the test process does
     * not have privileges to write the nonce. Once disabled it is not possible to re-enable
     * caching in the current process.  See {@link #testPropertyName} for a more focused way to
     * bypass caches when the test is for a server.
     * @hide
     */
    public static void disableForTestMode() {
+22 −9
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package android.content.pm;

import static android.app.PropertyInvalidatedCache.MODULE_SYSTEM;
import static android.content.pm.SigningInfo.AppSigningSchemeVersion;
import static android.media.audio.Flags.FLAG_FEATURE_SPATIAL_AUDIO_HEADTRACKING_LOW_LATENCY;

@@ -11659,11 +11660,22 @@ public abstract class PackageManager {
        }
    }

    private static final PropertyInvalidatedCache<ApplicationInfoQuery, ApplicationInfo>
            sApplicationInfoCache =
            new PropertyInvalidatedCache<ApplicationInfoQuery, ApplicationInfo>(
                    2048, PermissionManager.CACHE_KEY_PACKAGE_INFO_CACHE,
                    "getApplicationInfo") {
    private static String packageInfoApi() {
        return PropertyInvalidatedCache.apiFromProperty(
            PermissionManager.CACHE_KEY_PACKAGE_INFO_CACHE);
    }

    // The maximum number of entries to keep in the packageInfo and applicationInfo caches.
    private final static int MAX_INFO_CACHE_ENTRIES = 2048;

    /** @hide */
    @VisibleForTesting
    public static final PropertyInvalidatedCache<ApplicationInfoQuery, ApplicationInfo>
            sApplicationInfoCache = new PropertyInvalidatedCache<>(
                new PropertyInvalidatedCache.Args(MODULE_SYSTEM)
                .maxEntries(MAX_INFO_CACHE_ENTRIES).api(packageInfoApi()).cacheNulls(true),
                "getApplicationInfo", null) {

                @Override
                public ApplicationInfo recompute(ApplicationInfoQuery query) {
                    return getApplicationInfoAsUserUncached(
@@ -11749,10 +11761,11 @@ public abstract class PackageManager {
    }

    private static final PropertyInvalidatedCache<PackageInfoQuery, PackageInfo>
            sPackageInfoCache =
            new PropertyInvalidatedCache<PackageInfoQuery, PackageInfo>(
                    2048, PermissionManager.CACHE_KEY_PACKAGE_INFO_CACHE,
                    "getPackageInfo") {
            sPackageInfoCache = new PropertyInvalidatedCache<>(
                new PropertyInvalidatedCache.Args(MODULE_SYSTEM)
                .maxEntries(MAX_INFO_CACHE_ENTRIES).api(packageInfoApi()).cacheNulls(true),
                "getPackageInfo", null) {

                @Override
                public PackageInfo recompute(PackageInfoQuery query) {
                    return getPackageInfoAsUserUncached(
+5 −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.ApplicationPackageManager;
import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
import android.content.pm.SigningDetails;
@@ -173,6 +174,10 @@ public final class AppsFilterImpl extends AppsFilterLocked implements Watchable,
     * Report a change to observers.
     */
    private void onChanged() {
        // App visibility may have changed, which means that earlier fetches from these caches may
        // be invalid.
        PackageManager.invalidatePackageInfoCache();
        ApplicationPackageManager.invalidateGetPackagesForUidCache();
        dispatchChange(this);
    }

+55 −1
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@ import android.content.pm.PackageManagerInternal;
import android.content.pm.Signature;
import android.content.pm.SigningDetails;
import android.content.pm.UserInfo;
import android.app.PropertyInvalidatedCache;
import android.os.Build;
import android.os.Handler;
import android.os.Message;
@@ -50,6 +51,8 @@ import android.util.SparseArray;

import androidx.annotation.NonNull;

import android.app.ApplicationPackageManager;
import android.content.pm.PackageManager;
import com.android.internal.pm.parsing.pkg.PackageImpl;
import com.android.internal.pm.parsing.pkg.ParsedPackage;
import com.android.internal.pm.pkg.component.ParsedActivity;
@@ -64,8 +67,10 @@ import com.android.internal.pm.pkg.component.ParsedUsesPermissionImpl;
import com.android.internal.pm.pkg.parsing.ParsingPackage;
import com.android.server.om.OverlayReferenceMapper;
import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.utils.Watchable;
import com.android.server.utils.WatchableTester;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -244,6 +249,55 @@ public class AppsFilterImplTest {
                (Answer<Boolean>) invocation ->
                        ((AndroidPackage) invocation.getArgument(SYSTEM_USER)).getTargetSdkVersion()
                                >= Build.VERSION_CODES.R);
        PropertyInvalidatedCache.setTestMode(true);
        PackageManager.sApplicationInfoCache.testPropertyName();
        ApplicationPackageManager.sGetPackagesForUidCache.testPropertyName();
    }

    @After
    public void tearDown() {
        PropertyInvalidatedCache.setTestMode(false);
    }

    /**
     * A class to make it easier to verify that PM caches are properly invalidated by
     * AppsFilterImpl operations.  This extends WatchableTester to test the cache nonces along
     * with change reporting.
     */
    private static class NonceTester extends WatchableTester {
        // The nonces from caches under consideration.  The no-parameter constructor fetches the
        // values from the cacches.
        private static record Nonces(long applicationInfo, long packageInfo) {
            Nonces() {
                this(ApplicationPackageManager.sGetPackagesForUidCache.getNonce(),
                        PackageManager.sApplicationInfoCache.getNonce());
            }
        }

        // Track the latest cache nonces.
        private Nonces mNonces;

        NonceTester(Watchable w, String k) {
            super(w, k);
            mNonces = new Nonces();
        }

        @Override
        public void verifyChangeReported(String msg) {
            super.verifyChangeReported(msg);
            Nonces update = new Nonces();
            assertTrue(msg, update.applicationInfo != mNonces.applicationInfo);
            assertTrue(msg, update.packageInfo != mNonces.packageInfo);
            mNonces = update;
        }

        @Override
        public void verifyNoChangeReported(String msg) {
            super.verifyNoChangeReported(msg);
            Nonces update = new Nonces();
            assertTrue(msg, update.applicationInfo == mNonces.applicationInfo);
            assertTrue(msg, update.packageInfo == mNonces.packageInfo);
        }
    }

    @Test
@@ -1167,7 +1221,7 @@ public class AppsFilterImplTest {
        final AppsFilterImpl appsFilter =
                new AppsFilterImpl(mFeatureConfigMock, new String[]{}, /* systemAppsQueryable */
                        false, /* overlayProvider */ null, mMockHandler);
        final WatchableTester watcher = new WatchableTester(appsFilter, "onChange");
        final WatchableTester watcher = new NonceTester(appsFilter, "onChange");
        watcher.register();
        simulateAddBasicAndroid(appsFilter);
        watcher.verifyChangeReported("addBasicAndroid");