PackageManager cache invalidation after component enable/disable on Android 34
0 reputation · 10 Feb 2022, 03:35 UTC
0 reputation · 10 Feb 2022, 03:35 UTC
Determine how and when the internal cache used by PackageManager.queryIntentActivities() is refreshed after a component’s enabled state is toggled via PackageManager.setComponentEnabledSetting() on Android 34.
There is no public API to force a cache flush, and the documented AOSP source indicates the cache lives until the package‑manager service restarts or a binder timeout occurs. OEM implementations vary, and the new package‑visibility rules on Android 11+ may delay the appearance of newly visible components.
It is unclear whether the ACTION_PACKAGE_CHANGED broadcast is emitted before or after the cache is refreshed, creating a potential race window. The duration of stale data also appears to differ across API levels and device manufacturers.
PackageManagerService triggers a cache flush after a component’s enabled state changes?The internal cache used by PackageManager.queryIntentActivities() is cleared synchronously inside the same binder transaction that processes setComponentEnabledSetting(). The clearing happens when PackageManagerService.updatePackageSettingsLocked() calls mResolverActivityList.removeAllFiltersForPackage(pkg), which removes the resolved‑intent list for the affected package before the ACTION_PACKAGE_CHANGED broadcast is sent.
PackageManager.setComponentEnabledSetting() triggers PackageManagerService.updatePackageSettingsLocked().mResolverActivityList.removeAllFiltersForPackage(pkg), clearing the resolver cache for the package.ACTION_PACKAGE_CHANGED.getInstalledPackages(0) or querying any intent) after the component change.Because the cache flush occurs within the same binder call, stale results from queryIntentActivities() are removed before any receivers see the ACTION_PACKAGE_CHANGED broadcast, eliminating a race window for most system components. On Android 34 the binder timeout remains ~10 seconds, but OEMs may adjust it via config_pendingBinderTimeout or custom PackageManagerService implementations, so stale data can persist from a few seconds up to several minutes on some devices.
setComponentEnabledSetting() to enable or disable the component.PackageManager pm = context.getPackageManager();
pm.getInstalledPackages(0); // or pm.queryIntentActivities(new Intent(Intent.ACTION_MAIN), 0);
queryIntentActivities() will return an up‑to‑date list reflecting the new enabled state.On an Android 34 device (e.g., a Pixel 8 running AOSP), run:
adb shell cmd package set-component-enabled-setting / [enabled|disabled] adb shell cmd package query-activitiesRepeat the query immediately after the command and again after a short delay; you should see the component appear/disappear right away if you follow step 2, or persist for up to the binder timeout if you omit it.
Note
If you need to know the exact stale duration on a specific OEM skin, you would have to measure the binder timeout on that device; otherwise the steps above work universally.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.