Loading services/core/java/com/android/server/pm/AppsFilter.java +149 −334 Original line number Diff line number Diff line Loading @@ -19,8 +19,6 @@ 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; Loading Loading @@ -111,25 +109,12 @@ public class AppsFilter { private final boolean mSystemAppsQueryable; private final FeatureConfig mFeatureConfig; private final OverlayReferenceMapper mOverlayReferenceMapper; private final StateProvider mStateProvider; private final OverlayReferenceMapper mOverlayReferenceMapper; private PackageParser.SigningDetails mSystemSigningDetails; private Set<String> mProtectedBroadcasts = new ArraySet<>(); /** * 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 scan and is null until {@link #onSystemReady()} is called. */ private volatile SparseArray<SparseBooleanArray> mShouldFilterCache; @VisibleForTesting(visibility = PRIVATE) AppsFilter(StateProvider stateProvider, FeatureConfig featureConfig, String[] forceQueryableWhitelist, AppsFilter(FeatureConfig featureConfig, String[] forceQueryableWhitelist, boolean systemAppsQueryable, @Nullable OverlayReferenceMapper.Provider overlayProvider) { mFeatureConfig = featureConfig; Loading @@ -137,23 +122,8 @@ 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, int[] users); } } @VisibleForTesting(visibility = PRIVATE) public interface FeatureConfig { /** Called when the system is ready and components can be queried. */ Loading @@ -170,7 +140,6 @@ 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); Loading @@ -178,7 +147,6 @@ 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); Loading @@ -194,7 +162,6 @@ public class AppsFilter { @Nullable private SparseBooleanArray mLoggingEnabled = null; private AppsFilter mAppsFilter; private FeatureConfigImpl( PackageManagerInternal pmInternal, PackageManagerService.Injector injector) { Loading @@ -202,10 +169,6 @@ public class AppsFilter { mInjector = injector; } public void setAppsFilter(AppsFilter filter) { mAppsFilter = filter; } @Override public void onSystemReady() { mFeatureEnabled = DeviceConfig.getBoolean( Loading Loading @@ -272,16 +235,12 @@ public class AppsFilter { @Override public void onCompatChange(String packageName) { final long token = Binder.clearCallingIdentity(); try { updateEnabledState(mPmInternal.getPackage(packageName)); mAppsFilter.updateShouldFilterCacheForPackage(packageName); } finally { Binder.restoreCallingIdentity(token); } } private void updateEnabledState(AndroidPackage pkg) { final long token = Binder.clearCallingIdentity(); try { // TODO(b/135203078): Do not use toAppInfo final boolean enabled = mInjector.getCompatibility().isChangeEnabled( Loading @@ -292,6 +251,9 @@ public class AppsFilter { } else { mDisabledPackages.add(pkg.getPackageName()); } } finally { Binder.restoreCallingIdentity(token); } } @Override Loading @@ -313,7 +275,7 @@ public class AppsFilter { final boolean forceSystemAppsQueryable = injector.getContext().getResources() .getBoolean(R.bool.config_forceSystemPackagesQueryable); final FeatureConfigImpl featureConfig = new FeatureConfigImpl(pms, injector); final FeatureConfig featureConfig = new FeatureConfigImpl(pms, injector); final String[] forcedQueryablePackageNames; if (forceSystemAppsQueryable) { // all system apps already queryable, no need to read and parse individual exceptions Loading @@ -326,16 +288,8 @@ public class AppsFilter { forcedQueryablePackageNames[i] = forcedQueryablePackageNames[i].intern(); } } final StateProvider stateProvider = command -> { synchronized (injector.getLock()) { command.currentState(injector.getSettings().mPackages, injector.getUserManagerInternal().getUserIds()); } }; AppsFilter appsFilter = new AppsFilter(stateProvider, featureConfig, forcedQueryablePackageNames, forceSystemAppsQueryable, null); featureConfig.setAppsFilter(appsFilter); return appsFilter; return new AppsFilter(featureConfig, forcedQueryablePackageNames, forceSystemAppsQueryable, null); } public FeatureConfig getFeatureConfig() { Loading Loading @@ -461,51 +415,25 @@ public class AppsFilter { * @param visibleUid the uid becoming visible to the {@recipientUid} */ public void grantImplicitAccess(int recipientUid, int visibleUid) { if (recipientUid != visibleUid) { if (mImplicitlyQueryable.add(recipientUid, visibleUid) && DEBUG_LOGGING) { if (recipientUid != visibleUid && 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() { mShouldFilterCache = new SparseArray<>(); 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) { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "filter.addPackage"); try { mStateProvider.runWithState((settings, users) -> { addPackageInternal(newPkgSetting, settings, users); 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, int[] allUsers) { public void addPackage(PackageSetting newPkgSetting, ArrayMap<String, PackageSetting> existingSettings) { if (Objects.equals("android", newPkgSetting.name)) { // let's set aside the framework signatures mSystemSigningDetails = newPkgSetting.signatures.mSigningDetails; Loading @@ -518,6 +446,8 @@ public class AppsFilter { } } Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "filter.addPackage"); try { final AndroidPackage newPkg = newPkgSetting.pkg; if (newPkg == null) { // nothing to add Loading Loading @@ -587,82 +517,8 @@ public class AppsFilter { } mOverlayReferenceMapper.addPkg(newPkgSetting.pkg, existingPkgs); mFeatureConfig.updatePackageState(newPkgSetting, false /*removed*/); } 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, int[] 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; } for (int su = 0; su < allUsers.length; su++) { int subjectUser = allUsers[su]; for (int ou = su; ou < allUsers.length; ou++) { int otherUser = allUsers[ou]; int subjectUid = UserHandle.getUid(subjectUser, subjectSetting.appId); if (!mShouldFilterCache.contains(subjectUid)) { mShouldFilterCache.put(subjectUid, new SparseBooleanArray()); } int otherUid = UserHandle.getUid(otherUser, otherSetting.appId); if (!mShouldFilterCache.contains(otherUid)) { mShouldFilterCache.put(otherUid, new SparseBooleanArray()); } mShouldFilterCache.get(subjectUid).put(otherUid, shouldFilterApplicationInternal( subjectUid, subjectSetting, otherSetting, otherUser)); mShouldFilterCache.get(otherUid).put(subjectUid, shouldFilterApplicationInternal( otherUid, otherSetting, subjectSetting, subjectUser)); } } } finally { Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } } Loading Loading @@ -713,7 +569,6 @@ 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 Loading Loading @@ -772,12 +627,14 @@ 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) { removeAppIdFromVisibilityCache(setting.appId); mStateProvider.runWithState((settings, users) -> { for (int u = 0; u < users.length; u++) { final int userId = users[u]; 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]; final int removingUid = UserHandle.getUid(userId, setting.appId); mImplicitlyQueryable.remove(removingUid); for (int i = mImplicitlyQueryable.size() - 1; i >= 0; i--) { Loading @@ -801,8 +658,7 @@ public class AppsFilter { if (setting.sharedUser.packages.valueAt(i) == setting) { continue; } addPackageInternal( setting.sharedUser.packages.valueAt(i), settings, users); addPackage(setting.sharedUser.packages.valueAt(i), existingSettings); } } Loading @@ -810,21 +666,12 @@ public class AppsFilter { final String removingPackageName = setting.pkg.getPackageName(); mProtectedBroadcasts.clear(); mProtectedBroadcasts.addAll( collectProtectedBroadcasts(settings, removingPackageName)); recomputeComponentVisibility(settings, removingPackageName); collectProtectedBroadcasts(existingSettings, removingPackageName)); recomputeComponentVisibility(existingSettings, 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); } /** Loading @@ -841,32 +688,11 @@ 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"); } Loading @@ -877,7 +703,7 @@ public class AppsFilter { } private boolean shouldFilterApplicationInternal(int callingUid, SettingBase callingSetting, PackageSetting targetPkgSetting, int targetUserId) { PackageSetting targetPkgSetting, int userId) { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "shouldFilterApplicationInternal"); try { final boolean featureEnabled = mFeatureConfig.isGloballyEnabled(); Loading @@ -887,6 +713,12 @@ 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; Loading @@ -895,14 +727,8 @@ 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; Loading Loading @@ -960,18 +786,14 @@ public class AppsFilter { } try { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "requestsQueryAllPackages"); if (callingPkgSetting != null) { if (requestsQueryAllPackages(callingPkgSetting)) { return false; 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"); } } else { for (int i = callingSharedPkgSettings.size() - 1; i >= 0; i--) { if (requestsQueryAllPackages(callingSharedPkgSettings.valueAt(i))) { return false; } } } } finally { Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } Loading Loading @@ -1011,7 +833,7 @@ public class AppsFilter { try { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "mImplicitlyQueryable"); final int targetUid = UserHandle.getUid(targetUserId, targetAppId); final int targetUid = UserHandle.getUid(userId, targetAppId); if (mImplicitlyQueryable.contains(callingUid, targetUid)) { if (DEBUG_LOGGING) { log(callingSetting, targetPkgSetting, "implicitly queryable for user"); Loading Loading @@ -1049,20 +871,13 @@ 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 { Loading services/core/java/com/android/server/pm/PackageManagerService.java +4 −4 Original line number Diff line number Diff line Loading @@ -12362,7 +12362,7 @@ public class PackageManagerService extends IPackageManager.Stub ksms.addScannedPackageLPw(pkg); mComponentResolver.addAllComponents(pkg, chatty); mAppsFilter.addPackage(pkgSetting); mAppsFilter.addPackage(pkgSetting, mSettings.mPackages); // Don't allow ephemeral applications to define new permissions groups. if ((scanFlags & SCAN_AS_INSTANT_APP) != 0) { Loading Loading @@ -12536,6 +12536,8 @@ 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()); Loading Loading @@ -14251,7 +14253,7 @@ public class PackageManagerService extends IPackageManager.Stub // Okay! targetPackageSetting.setInstallerPackageName(installerPackageName); mSettings.addInstallerPackageNames(targetPackageSetting.installSource); mAppsFilter.addPackage(targetPackageSetting); mAppsFilter.addPackage(targetPackageSetting, mSettings.mPackages); scheduleWriteSettingsLocked(); } } Loading Loading @@ -18701,7 +18703,6 @@ 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; Loading Loading @@ -23459,7 +23460,6 @@ public class PackageManagerService extends IPackageManager.Stub scheduleWritePackageRestrictionsLocked(userId); scheduleWritePackageListLocked(userId); primeDomainVerificationsLPw(userId); mAppsFilter.onUsersChanged(); } } services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java +148 −214 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
services/core/java/com/android/server/pm/AppsFilter.java +149 −334 Original line number Diff line number Diff line Loading @@ -19,8 +19,6 @@ 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; Loading Loading @@ -111,25 +109,12 @@ public class AppsFilter { private final boolean mSystemAppsQueryable; private final FeatureConfig mFeatureConfig; private final OverlayReferenceMapper mOverlayReferenceMapper; private final StateProvider mStateProvider; private final OverlayReferenceMapper mOverlayReferenceMapper; private PackageParser.SigningDetails mSystemSigningDetails; private Set<String> mProtectedBroadcasts = new ArraySet<>(); /** * 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 scan and is null until {@link #onSystemReady()} is called. */ private volatile SparseArray<SparseBooleanArray> mShouldFilterCache; @VisibleForTesting(visibility = PRIVATE) AppsFilter(StateProvider stateProvider, FeatureConfig featureConfig, String[] forceQueryableWhitelist, AppsFilter(FeatureConfig featureConfig, String[] forceQueryableWhitelist, boolean systemAppsQueryable, @Nullable OverlayReferenceMapper.Provider overlayProvider) { mFeatureConfig = featureConfig; Loading @@ -137,23 +122,8 @@ 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, int[] users); } } @VisibleForTesting(visibility = PRIVATE) public interface FeatureConfig { /** Called when the system is ready and components can be queried. */ Loading @@ -170,7 +140,6 @@ 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); Loading @@ -178,7 +147,6 @@ 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); Loading @@ -194,7 +162,6 @@ public class AppsFilter { @Nullable private SparseBooleanArray mLoggingEnabled = null; private AppsFilter mAppsFilter; private FeatureConfigImpl( PackageManagerInternal pmInternal, PackageManagerService.Injector injector) { Loading @@ -202,10 +169,6 @@ public class AppsFilter { mInjector = injector; } public void setAppsFilter(AppsFilter filter) { mAppsFilter = filter; } @Override public void onSystemReady() { mFeatureEnabled = DeviceConfig.getBoolean( Loading Loading @@ -272,16 +235,12 @@ public class AppsFilter { @Override public void onCompatChange(String packageName) { final long token = Binder.clearCallingIdentity(); try { updateEnabledState(mPmInternal.getPackage(packageName)); mAppsFilter.updateShouldFilterCacheForPackage(packageName); } finally { Binder.restoreCallingIdentity(token); } } private void updateEnabledState(AndroidPackage pkg) { final long token = Binder.clearCallingIdentity(); try { // TODO(b/135203078): Do not use toAppInfo final boolean enabled = mInjector.getCompatibility().isChangeEnabled( Loading @@ -292,6 +251,9 @@ public class AppsFilter { } else { mDisabledPackages.add(pkg.getPackageName()); } } finally { Binder.restoreCallingIdentity(token); } } @Override Loading @@ -313,7 +275,7 @@ public class AppsFilter { final boolean forceSystemAppsQueryable = injector.getContext().getResources() .getBoolean(R.bool.config_forceSystemPackagesQueryable); final FeatureConfigImpl featureConfig = new FeatureConfigImpl(pms, injector); final FeatureConfig featureConfig = new FeatureConfigImpl(pms, injector); final String[] forcedQueryablePackageNames; if (forceSystemAppsQueryable) { // all system apps already queryable, no need to read and parse individual exceptions Loading @@ -326,16 +288,8 @@ public class AppsFilter { forcedQueryablePackageNames[i] = forcedQueryablePackageNames[i].intern(); } } final StateProvider stateProvider = command -> { synchronized (injector.getLock()) { command.currentState(injector.getSettings().mPackages, injector.getUserManagerInternal().getUserIds()); } }; AppsFilter appsFilter = new AppsFilter(stateProvider, featureConfig, forcedQueryablePackageNames, forceSystemAppsQueryable, null); featureConfig.setAppsFilter(appsFilter); return appsFilter; return new AppsFilter(featureConfig, forcedQueryablePackageNames, forceSystemAppsQueryable, null); } public FeatureConfig getFeatureConfig() { Loading Loading @@ -461,51 +415,25 @@ public class AppsFilter { * @param visibleUid the uid becoming visible to the {@recipientUid} */ public void grantImplicitAccess(int recipientUid, int visibleUid) { if (recipientUid != visibleUid) { if (mImplicitlyQueryable.add(recipientUid, visibleUid) && DEBUG_LOGGING) { if (recipientUid != visibleUid && 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() { mShouldFilterCache = new SparseArray<>(); 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) { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "filter.addPackage"); try { mStateProvider.runWithState((settings, users) -> { addPackageInternal(newPkgSetting, settings, users); 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, int[] allUsers) { public void addPackage(PackageSetting newPkgSetting, ArrayMap<String, PackageSetting> existingSettings) { if (Objects.equals("android", newPkgSetting.name)) { // let's set aside the framework signatures mSystemSigningDetails = newPkgSetting.signatures.mSigningDetails; Loading @@ -518,6 +446,8 @@ public class AppsFilter { } } Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "filter.addPackage"); try { final AndroidPackage newPkg = newPkgSetting.pkg; if (newPkg == null) { // nothing to add Loading Loading @@ -587,82 +517,8 @@ public class AppsFilter { } mOverlayReferenceMapper.addPkg(newPkgSetting.pkg, existingPkgs); mFeatureConfig.updatePackageState(newPkgSetting, false /*removed*/); } 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, int[] 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; } for (int su = 0; su < allUsers.length; su++) { int subjectUser = allUsers[su]; for (int ou = su; ou < allUsers.length; ou++) { int otherUser = allUsers[ou]; int subjectUid = UserHandle.getUid(subjectUser, subjectSetting.appId); if (!mShouldFilterCache.contains(subjectUid)) { mShouldFilterCache.put(subjectUid, new SparseBooleanArray()); } int otherUid = UserHandle.getUid(otherUser, otherSetting.appId); if (!mShouldFilterCache.contains(otherUid)) { mShouldFilterCache.put(otherUid, new SparseBooleanArray()); } mShouldFilterCache.get(subjectUid).put(otherUid, shouldFilterApplicationInternal( subjectUid, subjectSetting, otherSetting, otherUser)); mShouldFilterCache.get(otherUid).put(subjectUid, shouldFilterApplicationInternal( otherUid, otherSetting, subjectSetting, subjectUser)); } } } finally { Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } } Loading Loading @@ -713,7 +569,6 @@ 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 Loading Loading @@ -772,12 +627,14 @@ 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) { removeAppIdFromVisibilityCache(setting.appId); mStateProvider.runWithState((settings, users) -> { for (int u = 0; u < users.length; u++) { final int userId = users[u]; 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]; final int removingUid = UserHandle.getUid(userId, setting.appId); mImplicitlyQueryable.remove(removingUid); for (int i = mImplicitlyQueryable.size() - 1; i >= 0; i--) { Loading @@ -801,8 +658,7 @@ public class AppsFilter { if (setting.sharedUser.packages.valueAt(i) == setting) { continue; } addPackageInternal( setting.sharedUser.packages.valueAt(i), settings, users); addPackage(setting.sharedUser.packages.valueAt(i), existingSettings); } } Loading @@ -810,21 +666,12 @@ public class AppsFilter { final String removingPackageName = setting.pkg.getPackageName(); mProtectedBroadcasts.clear(); mProtectedBroadcasts.addAll( collectProtectedBroadcasts(settings, removingPackageName)); recomputeComponentVisibility(settings, removingPackageName); collectProtectedBroadcasts(existingSettings, removingPackageName)); recomputeComponentVisibility(existingSettings, 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); } /** Loading @@ -841,32 +688,11 @@ 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"); } Loading @@ -877,7 +703,7 @@ public class AppsFilter { } private boolean shouldFilterApplicationInternal(int callingUid, SettingBase callingSetting, PackageSetting targetPkgSetting, int targetUserId) { PackageSetting targetPkgSetting, int userId) { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "shouldFilterApplicationInternal"); try { final boolean featureEnabled = mFeatureConfig.isGloballyEnabled(); Loading @@ -887,6 +713,12 @@ 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; Loading @@ -895,14 +727,8 @@ 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; Loading Loading @@ -960,18 +786,14 @@ public class AppsFilter { } try { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "requestsQueryAllPackages"); if (callingPkgSetting != null) { if (requestsQueryAllPackages(callingPkgSetting)) { return false; 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"); } } else { for (int i = callingSharedPkgSettings.size() - 1; i >= 0; i--) { if (requestsQueryAllPackages(callingSharedPkgSettings.valueAt(i))) { return false; } } } } finally { Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } Loading Loading @@ -1011,7 +833,7 @@ public class AppsFilter { try { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "mImplicitlyQueryable"); final int targetUid = UserHandle.getUid(targetUserId, targetAppId); final int targetUid = UserHandle.getUid(userId, targetAppId); if (mImplicitlyQueryable.contains(callingUid, targetUid)) { if (DEBUG_LOGGING) { log(callingSetting, targetPkgSetting, "implicitly queryable for user"); Loading Loading @@ -1049,20 +871,13 @@ 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 { Loading
services/core/java/com/android/server/pm/PackageManagerService.java +4 −4 Original line number Diff line number Diff line Loading @@ -12362,7 +12362,7 @@ public class PackageManagerService extends IPackageManager.Stub ksms.addScannedPackageLPw(pkg); mComponentResolver.addAllComponents(pkg, chatty); mAppsFilter.addPackage(pkgSetting); mAppsFilter.addPackage(pkgSetting, mSettings.mPackages); // Don't allow ephemeral applications to define new permissions groups. if ((scanFlags & SCAN_AS_INSTANT_APP) != 0) { Loading Loading @@ -12536,6 +12536,8 @@ 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()); Loading Loading @@ -14251,7 +14253,7 @@ public class PackageManagerService extends IPackageManager.Stub // Okay! targetPackageSetting.setInstallerPackageName(installerPackageName); mSettings.addInstallerPackageNames(targetPackageSetting.installSource); mAppsFilter.addPackage(targetPackageSetting); mAppsFilter.addPackage(targetPackageSetting, mSettings.mPackages); scheduleWriteSettingsLocked(); } } Loading Loading @@ -18701,7 +18703,6 @@ 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; Loading Loading @@ -23459,7 +23460,6 @@ public class PackageManagerService extends IPackageManager.Stub scheduleWritePackageRestrictionsLocked(userId); scheduleWritePackageListLocked(userId); primeDomainVerificationsLPw(userId); mAppsFilter.onUsersChanged(); } }
services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java +148 −214 File changed.Preview size limit exceeded, changes collapsed. Show changes