Loading core/java/android/app/ApplicationPackageManager.java +13 −10 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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 { Loading @@ -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 Loading core/java/android/app/PropertyInvalidatedCache.java +26 −6 Original line number Diff line number Diff line Loading @@ -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. */ Loading Loading @@ -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); Loading @@ -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 Loading Loading @@ -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() { Loading core/java/android/content/pm/PackageManager.java +22 −9 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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( Loading Loading @@ -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( Loading services/core/java/com/android/server/pm/AppsFilterImpl.java +5 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); } Loading services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/AppsFilterImplTest.java +55 −1 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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; Loading Loading @@ -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 Loading Loading @@ -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"); Loading Loading
core/java/android/app/ApplicationPackageManager.java +13 −10 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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 { Loading @@ -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 Loading
core/java/android/app/PropertyInvalidatedCache.java +26 −6 Original line number Diff line number Diff line Loading @@ -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. */ Loading Loading @@ -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); Loading @@ -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 Loading Loading @@ -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() { Loading
core/java/android/content/pm/PackageManager.java +22 −9 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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( Loading Loading @@ -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( Loading
services/core/java/com/android/server/pm/AppsFilterImpl.java +5 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); } Loading
services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/AppsFilterImplTest.java +55 −1 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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; Loading Loading @@ -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 Loading Loading @@ -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"); Loading