diff options
author | 2020-06-10 00:11:43 +0000 | |
---|---|---|
committer | 2020-06-10 00:11:43 +0000 | |
commit | 7da3f04b7e3fc8fbfd29ed9fade5830f2287eeea (patch) | |
tree | 18841283a5d41d6e0504942378eefe58bfbf2d79 | |
parent | d6b9d5a608b8915102f51a728a11d69f8ddb305c (diff) | |
parent | c68d8124bb26c27914f3d7f2ac330b15b8d39e45 (diff) |
Merge "Pre-cache filter results" into rvc-dev
3 files changed, 552 insertions, 301 deletions
diff --git a/services/core/java/com/android/server/pm/AppsFilter.java b/services/core/java/com/android/server/pm/AppsFilter.java index 4b6ee71803a7..ba60f179e661 100644 --- a/services/core/java/com/android/server/pm/AppsFilter.java +++ b/services/core/java/com/android/server/pm/AppsFilter.java @@ -19,6 +19,8 @@ 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; @@ -109,12 +111,25 @@ public class AppsFilter { private final boolean mSystemAppsQueryable; private final FeatureConfig mFeatureConfig; - private final OverlayReferenceMapper mOverlayReferenceMapper; + private final StateProvider mStateProvider; + private PackageParser.SigningDetails mSystemSigningDetails; private Set<String> mProtectedBroadcasts = new ArraySet<>(); - AppsFilter(FeatureConfig featureConfig, String[] forceQueryableWhitelist, + /** + * 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, boolean systemAppsQueryable, @Nullable OverlayReferenceMapper.Provider overlayProvider) { mFeatureConfig = featureConfig; @@ -122,8 +137,23 @@ 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. */ @@ -140,6 +170,7 @@ 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); @@ -147,6 +178,7 @@ 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); @@ -162,6 +194,7 @@ public class AppsFilter { @Nullable private SparseBooleanArray mLoggingEnabled = null; + private AppsFilter mAppsFilter; private FeatureConfigImpl( PackageManagerInternal pmInternal, PackageManagerService.Injector injector) { @@ -169,6 +202,10 @@ public class AppsFilter { mInjector = injector; } + public void setAppsFilter(AppsFilter filter) { + mAppsFilter = filter; + } + @Override public void onSystemReady() { mFeatureEnabled = DeviceConfig.getBoolean( @@ -235,27 +272,28 @@ public class AppsFilter { @Override public void onCompatChange(String packageName) { - updateEnabledState(mPmInternal.getPackage(packageName)); - } - - private void updateEnabledState(AndroidPackage pkg) { final long token = Binder.clearCallingIdentity(); try { - // TODO(b/135203078): Do not use toAppInfo - final boolean enabled = - mInjector.getCompatibility().isChangeEnabled( - PackageManager.FILTER_APPLICATION_QUERY, - pkg.toAppInfoWithoutState()); - if (enabled) { - mDisabledPackages.remove(pkg.getPackageName()); - } else { - mDisabledPackages.add(pkg.getPackageName()); - } + updateEnabledState(mPmInternal.getPackage(packageName)); + mAppsFilter.updateShouldFilterCacheForPackage(packageName); } finally { Binder.restoreCallingIdentity(token); } } + private void updateEnabledState(AndroidPackage pkg) { + // TODO(b/135203078): Do not use toAppInfo + final boolean enabled = + mInjector.getCompatibility().isChangeEnabled( + PackageManager.FILTER_APPLICATION_QUERY, + pkg.toAppInfoWithoutState()); + if (enabled) { + mDisabledPackages.remove(pkg.getPackageName()); + } else { + mDisabledPackages.add(pkg.getPackageName()); + } + } + @Override public void updatePackageState(PackageSetting setting, boolean removed) { final boolean enableLogging = @@ -275,7 +313,7 @@ public class AppsFilter { final boolean forceSystemAppsQueryable = injector.getContext().getResources() .getBoolean(R.bool.config_forceSystemPackagesQueryable); - final FeatureConfig featureConfig = new FeatureConfigImpl(pms, injector); + final FeatureConfigImpl featureConfig = new FeatureConfigImpl(pms, injector); final String[] forcedQueryablePackageNames; if (forceSystemAppsQueryable) { // all system apps already queryable, no need to read and parse individual exceptions @@ -288,8 +326,16 @@ public class AppsFilter { forcedQueryablePackageNames[i] = forcedQueryablePackageNames[i].intern(); } } - return new AppsFilter(featureConfig, forcedQueryablePackageNames, - forceSystemAppsQueryable, null); + 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; } public FeatureConfig getFeatureConfig() { @@ -412,28 +458,54 @@ public class AppsFilter { * visibility of the caller from the target. * * @param recipientUid the uid gaining visibility of the {@code visibleUid}. - * @param visibleUid the uid becoming visible to the {@recipientUid} + * @param visibleUid the uid becoming visible to the {@recipientUid} */ public void grantImplicitAccess(int recipientUid, int visibleUid) { - if (recipientUid != visibleUid - && mImplicitlyQueryable.add(recipientUid, visibleUid) && DEBUG_LOGGING) { - Slog.i(TAG, "implicit access granted: " + recipientUid + " -> " + visibleUid); + if (recipientUid != visibleUid) { + if (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. + * @param newPkgSetting the new setting being added */ - public void addPackage(PackageSetting newPkgSetting, - ArrayMap<String, PackageSetting> existingSettings) { + 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) { if (Objects.equals("android", newPkgSetting.name)) { // let's set aside the framework signatures mSystemSigningDetails = newPkgSetting.signatures.mSigningDetails; @@ -446,79 +518,151 @@ public class AppsFilter { } } - Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "filter.addPackage"); - try { - final AndroidPackage newPkg = newPkgSetting.pkg; - if (newPkg == null) { - // nothing to add - return; - } + final AndroidPackage newPkg = newPkgSetting.pkg; + if (newPkg == null) { + // nothing to add + return; + } - if (!newPkg.getProtectedBroadcasts().isEmpty()) { - mProtectedBroadcasts.addAll(newPkg.getProtectedBroadcasts()); - recomputeComponentVisibility(existingSettings, newPkg.getPackageName()); - } + if (!newPkg.getProtectedBroadcasts().isEmpty()) { + mProtectedBroadcasts.addAll(newPkg.getProtectedBroadcasts()); + recomputeComponentVisibility(existingSettings, newPkg.getPackageName()); + } - final boolean newIsForceQueryable = - mForceQueryable.contains(newPkgSetting.appId) - /* shared user that is already force queryable */ - || newPkg.isForceQueryable() - || newPkgSetting.forceQueryableOverride - || (newPkgSetting.isSystem() && (mSystemAppsQueryable - || ArrayUtils.contains(mForceQueryableByDevicePackageNames, - newPkg.getPackageName()))); - if (newIsForceQueryable - || (mSystemSigningDetails != null - && isSystemSigned(mSystemSigningDetails, newPkgSetting))) { - mForceQueryable.add(newPkgSetting.appId); - } + final boolean newIsForceQueryable = + mForceQueryable.contains(newPkgSetting.appId) + /* shared user that is already force queryable */ + || newPkg.isForceQueryable() + || newPkgSetting.forceQueryableOverride + || (newPkgSetting.isSystem() && (mSystemAppsQueryable + || ArrayUtils.contains(mForceQueryableByDevicePackageNames, + newPkg.getPackageName()))); + if (newIsForceQueryable + || (mSystemSigningDetails != null + && isSystemSigned(mSystemSigningDetails, newPkgSetting))) { + mForceQueryable.add(newPkgSetting.appId); + } - for (int i = existingSettings.size() - 1; i >= 0; i--) { - final PackageSetting existingSetting = existingSettings.valueAt(i); - if (existingSetting.appId == newPkgSetting.appId || existingSetting.pkg == null) { - continue; + for (int i = existingSettings.size() - 1; i >= 0; i--) { + final PackageSetting existingSetting = existingSettings.valueAt(i); + if (existingSetting.appId == newPkgSetting.appId || existingSetting.pkg == null) { + continue; + } + final AndroidPackage existingPkg = existingSetting.pkg; + // let's evaluate the ability of already added packages to see this new package + if (!newIsForceQueryable) { + if (canQueryViaComponents(existingPkg, newPkg, mProtectedBroadcasts)) { + mQueriesViaComponent.add(existingSetting.appId, newPkgSetting.appId); } - final AndroidPackage existingPkg = existingSetting.pkg; - // let's evaluate the ability of already added packages to see this new package - if (!newIsForceQueryable) { - if (canQueryViaComponents(existingPkg, newPkg, mProtectedBroadcasts)) { - mQueriesViaComponent.add(existingSetting.appId, newPkgSetting.appId); - } - if (canQueryViaPackage(existingPkg, newPkg) - || canQueryAsInstaller(existingSetting, newPkg)) { - mQueriesViaPackage.add(existingSetting.appId, newPkgSetting.appId); - } + if (canQueryViaPackage(existingPkg, newPkg) + || canQueryAsInstaller(existingSetting, newPkg)) { + mQueriesViaPackage.add(existingSetting.appId, newPkgSetting.appId); } - // now we'll evaluate our new package's ability to see existing packages - if (!mForceQueryable.contains(existingSetting.appId)) { - if (canQueryViaComponents(newPkg, existingPkg, mProtectedBroadcasts)) { - mQueriesViaComponent.add(newPkgSetting.appId, existingSetting.appId); - } - if (canQueryViaPackage(newPkg, existingPkg) - || canQueryAsInstaller(newPkgSetting, existingPkg)) { - mQueriesViaPackage.add(newPkgSetting.appId, existingSetting.appId); - } + } + // now we'll evaluate our new package's ability to see existing packages + if (!mForceQueryable.contains(existingSetting.appId)) { + if (canQueryViaComponents(newPkg, existingPkg, mProtectedBroadcasts)) { + mQueriesViaComponent.add(newPkgSetting.appId, existingSetting.appId); } - // if either package instruments the other, mark both as visible to one another - if (pkgInstruments(newPkgSetting, existingSetting) - || pkgInstruments(existingSetting, newPkgSetting)) { + if (canQueryViaPackage(newPkg, existingPkg) + || canQueryAsInstaller(newPkgSetting, existingPkg)) { mQueriesViaPackage.add(newPkgSetting.appId, existingSetting.appId); - mQueriesViaPackage.add(existingSetting.appId, newPkgSetting.appId); } } + // if either package instruments the other, mark both as visible to one another + if (pkgInstruments(newPkgSetting, existingSetting) + || pkgInstruments(existingSetting, newPkgSetting)) { + mQueriesViaPackage.add(newPkgSetting.appId, existingSetting.appId); + mQueriesViaPackage.add(existingSetting.appId, newPkgSetting.appId); + } + } - int existingSize = existingSettings.size(); - ArrayMap<String, AndroidPackage> existingPkgs = new ArrayMap<>(existingSize); - for (int index = 0; index < existingSize; index++) { - PackageSetting pkgSetting = existingSettings.valueAt(index); - if (pkgSetting.pkg != null) { - existingPkgs.put(pkgSetting.name, pkgSetting.pkg); + int existingSize = existingSettings.size(); + ArrayMap<String, AndroidPackage> existingPkgs = new ArrayMap<>(existingSize); + for (int index = 0; index < existingSize; index++) { + PackageSetting pkgSetting = existingSettings.valueAt(index); + if (pkgSetting.pkg != null) { + existingPkgs.put(pkgSetting.name, pkgSetting.pkg); + } + } + 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)); } } - mOverlayReferenceMapper.addPkg(newPkgSetting.pkg, existingPkgs); - mFeatureConfig.updatePackageState(newPkgSetting, false /*removed*/); - } finally { - Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } } @@ -569,6 +713,7 @@ 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 @@ -577,11 +722,11 @@ public class AppsFilter { * If the setting is visible to all UIDs, null is returned. If an app is not visible to any * applications, the int array will be empty. * - * @param users the set of users that should be evaluated for this calculation + * @param users the set of users that should be evaluated for this calculation * @param existingSettings the set of all package settings that currently exist on device * @return a SparseArray mapping userIds to a sorted int array of appIds that may view the - * provided setting or null if the app is visible to all and no whitelist should be - * applied. + * provided setting or null if the app is visible to all and no whitelist should be + * applied. */ @Nullable public SparseArray<int[]> getVisibilityWhitelist(PackageSetting setting, int[] users, @@ -626,52 +771,60 @@ 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. + * @param setting the setting of the package being removed. */ - 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--) { - mImplicitlyQueryable.remove(mImplicitlyQueryable.keyAt(i), removingUid); + 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]; + final int removingUid = UserHandle.getUid(userId, setting.appId); + mImplicitlyQueryable.remove(removingUid); + for (int i = mImplicitlyQueryable.size() - 1; i >= 0; i--) { + mImplicitlyQueryable.remove(mImplicitlyQueryable.keyAt(i), removingUid); + } } - } - mQueriesViaComponent.remove(setting.appId); - for (int i = mQueriesViaComponent.size() - 1; i >= 0; i--) { - mQueriesViaComponent.remove(mQueriesViaComponent.keyAt(i), setting.appId); - } - mQueriesViaPackage.remove(setting.appId); - for (int i = mQueriesViaPackage.size() - 1; i >= 0; i--) { - mQueriesViaPackage.remove(mQueriesViaPackage.keyAt(i), setting.appId); - } + mQueriesViaComponent.remove(setting.appId); + for (int i = mQueriesViaComponent.size() - 1; i >= 0; i--) { + mQueriesViaComponent.remove(mQueriesViaComponent.keyAt(i), setting.appId); + } + mQueriesViaPackage.remove(setting.appId); + for (int i = mQueriesViaPackage.size() - 1; i >= 0; i--) { + mQueriesViaPackage.remove(mQueriesViaPackage.keyAt(i), setting.appId); + } - // re-add other shared user members to re-establish visibility between them and other - // packages - if (setting.sharedUser != null) { - for (int i = setting.sharedUser.packages.size() - 1; i >= 0; i--) { - if (setting.sharedUser.packages.valueAt(i) == setting) { - continue; + // re-add other shared user members to re-establish visibility between them and other + // packages + if (setting.sharedUser != null) { + for (int i = setting.sharedUser.packages.size() - 1; i >= 0; i--) { + if (setting.sharedUser.packages.valueAt(i) == setting) { + continue; + } + addPackageInternal( + setting.sharedUser.packages.valueAt(i), settings, users); } - addPackage(setting.sharedUser.packages.valueAt(i), existingSettings); } - } - if (!setting.pkg.getProtectedBroadcasts().isEmpty()) { - final String removingPackageName = setting.pkg.getPackageName(); - mProtectedBroadcasts.clear(); - mProtectedBroadcasts.addAll( - collectProtectedBroadcasts(existingSettings, removingPackageName)); - recomputeComponentVisibility(existingSettings, removingPackageName); - } + if (!setting.pkg.getProtectedBroadcasts().isEmpty()) { + final String removingPackageName = setting.pkg.getPackageName(); + mProtectedBroadcasts.clear(); + mProtectedBroadcasts.addAll( + collectProtectedBroadcasts(settings, removingPackageName)); + recomputeComponentVisibility(settings, 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); + - mOverlayReferenceMapper.removePkg(setting.name); - mFeatureConfig.updatePackageState(setting, true /*removed*/); } /** @@ -688,11 +841,32 @@ public class AppsFilter { PackageSetting targetPkgSetting, int userId) { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "shouldFilterApplication"); try { - - if (!shouldFilterApplicationInternal( - callingUid, callingSetting, targetPkgSetting, userId)) { + 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"); } @@ -703,7 +877,7 @@ public class AppsFilter { } private boolean shouldFilterApplicationInternal(int callingUid, SettingBase callingSetting, - PackageSetting targetPkgSetting, int userId) { + PackageSetting targetPkgSetting, int targetUserId) { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "shouldFilterApplicationInternal"); try { final boolean featureEnabled = mFeatureConfig.isGloballyEnabled(); @@ -713,12 +887,6 @@ 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; @@ -727,8 +895,14 @@ public class AppsFilter { final ArraySet<PackageSetting> callingSharedPkgSettings; Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "callingSetting instanceof"); if (callingSetting instanceof PackageSetting) { - callingPkgSetting = (PackageSetting) callingSetting; - callingSharedPkgSettings = null; + 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; @@ -786,13 +960,17 @@ public class AppsFilter { } try { - 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"); + Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "requestsQueryAllPackages"); + if (callingPkgSetting != null) { + if (requestsQueryAllPackages(callingPkgSetting)) { + return false; + } + } else { + for (int i = callingSharedPkgSettings.size() - 1; i >= 0; i--) { + if (requestsQueryAllPackages(callingSharedPkgSettings.valueAt(i))) { + return false; + } } - return false; } } finally { Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); @@ -833,7 +1011,7 @@ public class AppsFilter { try { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "mImplicitlyQueryable"); - final int targetUid = UserHandle.getUid(userId, targetAppId); + final int targetUid = UserHandle.getUid(targetUserId, targetAppId); if (mImplicitlyQueryable.contains(callingUid, targetUid)) { if (DEBUG_LOGGING) { log(callingSetting, targetPkgSetting, "implicitly queryable for user"); @@ -871,13 +1049,20 @@ 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 { diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 5e5274849fcd..fd37f041450e 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -12362,7 +12362,7 @@ public class PackageManagerService extends IPackageManager.Stub ksms.addScannedPackageLPw(pkg); mComponentResolver.addAllComponents(pkg, chatty); - mAppsFilter.addPackage(pkgSetting, mSettings.mPackages); + mAppsFilter.addPackage(pkgSetting); // Don't allow ephemeral applications to define new permissions groups. if ((scanFlags & SCAN_AS_INSTANT_APP) != 0) { @@ -12536,8 +12536,6 @@ 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()); @@ -14253,7 +14251,7 @@ public class PackageManagerService extends IPackageManager.Stub // Okay! targetPackageSetting.setInstallerPackageName(installerPackageName); mSettings.addInstallerPackageNames(targetPackageSetting.installSource); - mAppsFilter.addPackage(targetPackageSetting, mSettings.mPackages); + mAppsFilter.addPackage(targetPackageSetting); scheduleWriteSettingsLocked(); } } @@ -18706,6 +18704,7 @@ 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; @@ -23463,6 +23462,7 @@ public class PackageManagerService extends IPackageManager.Stub scheduleWritePackageRestrictionsLocked(userId); scheduleWritePackageListLocked(userId); primeDomainVerificationsLPw(userId); + mAppsFilter.onUsersChanged(); } } diff --git a/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java b/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java index f205fde88c0d..399a00f0cb5a 100644 --- a/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java @@ -23,6 +23,7 @@ import static org.hamcrest.Matchers.empty; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -57,6 +58,7 @@ import org.junit.runners.JUnit4; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; +import org.mockito.stubbing.Answer; import java.security.cert.CertificateException; import java.util.ArrayList; @@ -69,16 +71,20 @@ import java.util.Set; @RunWith(JUnit4.class) public class AppsFilterTest { - private static final int DUMMY_CALLING_UID = 10345; - private static final int DUMMY_TARGET_UID = 10556; - private static final int DUMMY_ACTOR_UID = 10656; - private static final int DUMMY_OVERLAY_UID = 10756; - private static final int DUMMY_ACTOR_TWO_UID = 10856; + private static final int DUMMY_CALLING_APPID = 10345; + private static final int DUMMY_TARGET_APPID = 10556; + private static final int DUMMY_ACTOR_APPID = 10656; + private static final int DUMMY_OVERLAY_APPID = 10756; + private static final int SYSTEM_USER = 0; + private static final int[] SINGLE_USER_ARRAY = {SYSTEM_USER}; @Mock AppsFilter.FeatureConfig mFeatureConfigMock; + @Mock + AppsFilter.StateProvider mStateProvider; private ArrayMap<String, PackageSetting> mExisting = new ArrayMap<>(); + private Object mDummyLock = new Object(); private static ParsingPackage pkg(String packageName) { return PackageImpl.forTesting(packageName) @@ -170,15 +176,24 @@ public class AppsFilterTest { mExisting = new ArrayMap<>(); MockitoAnnotations.initMocks(this); + doAnswer(invocation -> { + ((AppsFilter.StateProvider.CurrentStateCallback) invocation.getArgument(0)) + .currentState(mExisting, SINGLE_USER_ARRAY); + return null; + }).when(mStateProvider) + .runWithState(any(AppsFilter.StateProvider.CurrentStateCallback.class)); + when(mFeatureConfigMock.isGloballyEnabled()).thenReturn(true); - when(mFeatureConfigMock.packageIsEnabled(any(AndroidPackage.class))) - .thenReturn(true); + when(mFeatureConfigMock.packageIsEnabled(any(AndroidPackage.class))).thenAnswer( + (Answer<Boolean>) invocation -> + ((AndroidPackage)invocation.getArgument(SYSTEM_USER)).getTargetSdkVersion() + >= Build.VERSION_CODES.R); } @Test public void testSystemReadyPropogates() throws Exception { final AppsFilter appsFilter = - new AppsFilter(mFeatureConfigMock, new String[]{}, false, null); + new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null); appsFilter.onSystemReady(); verify(mFeatureConfigMock).onSystemReady(); } @@ -186,22 +201,23 @@ public class AppsFilterTest { @Test public void testQueriesAction_FilterMatches() throws Exception { final AppsFilter appsFilter = - new AppsFilter(mFeatureConfigMock, new String[]{}, false, null); + new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null); simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); PackageSetting target = simulateAddPackage(appsFilter, - pkg("com.some.package", new IntentFilter("TEST_ACTION")), DUMMY_TARGET_UID); + pkg("com.some.package", new IntentFilter("TEST_ACTION")), DUMMY_TARGET_APPID); PackageSetting calling = simulateAddPackage(appsFilter, - pkg("com.some.other.package", new Intent("TEST_ACTION")), DUMMY_CALLING_UID); + pkg("com.some.other.package", new Intent("TEST_ACTION")), DUMMY_CALLING_APPID); - assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, calling, target, 0)); + assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_APPID, calling, target, + SYSTEM_USER)); } @Test public void testQueriesProtectedAction_FilterDoesNotMatch() throws Exception { final AppsFilter appsFilter = - new AppsFilter(mFeatureConfigMock, new String[]{}, false, null); + new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null); final Signature frameworkSignature = Mockito.mock(Signature.class); final PackageParser.SigningDetails frameworkSigningDetails = new PackageParser.SigningDetails(new Signature[]{frameworkSignature}, 1); @@ -211,164 +227,174 @@ public class AppsFilterTest { b -> b.setSigningDetails(frameworkSigningDetails)); appsFilter.onSystemReady(); - final int activityUid = DUMMY_TARGET_UID; + final int activityUid = DUMMY_TARGET_APPID; PackageSetting targetActivity = simulateAddPackage(appsFilter, pkg("com.target.activity", new IntentFilter("TEST_ACTION")), activityUid); - final int receiverUid = DUMMY_TARGET_UID + 1; + final int receiverUid = DUMMY_TARGET_APPID + 1; PackageSetting targetReceiver = simulateAddPackage(appsFilter, pkgWithReceiver("com.target.receiver", new IntentFilter("TEST_ACTION")), receiverUid); - final int callingUid = DUMMY_CALLING_UID; + final int callingUid = DUMMY_CALLING_APPID; PackageSetting calling = simulateAddPackage(appsFilter, pkg("com.calling.action", new Intent("TEST_ACTION")), callingUid); - final int wildcardUid = DUMMY_CALLING_UID + 1; + final int wildcardUid = DUMMY_CALLING_APPID + 1; PackageSetting callingWildCard = simulateAddPackage(appsFilter, pkg("com.calling.wildcard", new Intent("*")), wildcardUid); - assertFalse(appsFilter.shouldFilterApplication(callingUid, calling, targetActivity, 0)); - assertTrue(appsFilter.shouldFilterApplication(callingUid, calling, targetReceiver, 0)); + assertFalse(appsFilter.shouldFilterApplication(callingUid, calling, targetActivity, + SYSTEM_USER)); + assertTrue(appsFilter.shouldFilterApplication(callingUid, calling, targetReceiver, + SYSTEM_USER)); assertFalse(appsFilter.shouldFilterApplication( - wildcardUid, callingWildCard, targetActivity, 0)); + wildcardUid, callingWildCard, targetActivity, SYSTEM_USER)); assertTrue(appsFilter.shouldFilterApplication( - wildcardUid, callingWildCard, targetReceiver, 0)); + wildcardUid, callingWildCard, targetReceiver, SYSTEM_USER)); } @Test public void testQueriesProvider_FilterMatches() throws Exception { final AppsFilter appsFilter = - new AppsFilter(mFeatureConfigMock, new String[]{}, false, null); + new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null); simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); PackageSetting target = simulateAddPackage(appsFilter, - pkgWithProvider("com.some.package", "com.some.authority"), DUMMY_TARGET_UID); + pkgWithProvider("com.some.package", "com.some.authority"), DUMMY_TARGET_APPID); PackageSetting calling = simulateAddPackage(appsFilter, pkgQueriesProvider("com.some.other.package", "com.some.authority"), - DUMMY_CALLING_UID); + DUMMY_CALLING_APPID); - assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, calling, target, 0)); + assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_APPID, calling, target, + SYSTEM_USER)); } @Test public void testQueriesDifferentProvider_Filters() throws Exception { final AppsFilter appsFilter = - new AppsFilter(mFeatureConfigMock, new String[]{}, false, null); + new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null); simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); PackageSetting target = simulateAddPackage(appsFilter, - pkgWithProvider("com.some.package", "com.some.authority"), DUMMY_TARGET_UID); + pkgWithProvider("com.some.package", "com.some.authority"), DUMMY_TARGET_APPID); PackageSetting calling = simulateAddPackage(appsFilter, pkgQueriesProvider("com.some.other.package", "com.some.other.authority"), - DUMMY_CALLING_UID); + DUMMY_CALLING_APPID); - assertTrue(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, calling, target, 0)); + assertTrue(appsFilter.shouldFilterApplication(DUMMY_CALLING_APPID, calling, target, + SYSTEM_USER)); } @Test public void testQueriesProviderWithSemiColon_FilterMatches() throws Exception { final AppsFilter appsFilter = - new AppsFilter(mFeatureConfigMock, new String[]{}, false, null); + new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null); simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); PackageSetting target = simulateAddPackage(appsFilter, pkgWithProvider("com.some.package", "com.some.authority;com.some.other.authority"), - DUMMY_TARGET_UID); + DUMMY_TARGET_APPID); PackageSetting calling = simulateAddPackage(appsFilter, pkgQueriesProvider("com.some.other.package", "com.some.authority"), - DUMMY_CALLING_UID); + DUMMY_CALLING_APPID); - assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, calling, target, 0)); + assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_APPID, calling, target, + SYSTEM_USER)); } @Test public void testQueriesAction_NoMatchingAction_Filters() throws Exception { final AppsFilter appsFilter = - new AppsFilter(mFeatureConfigMock, new String[]{}, false, null); + new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null); simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); PackageSetting target = simulateAddPackage(appsFilter, - pkg("com.some.package"), DUMMY_TARGET_UID); + pkg("com.some.package"), DUMMY_TARGET_APPID); PackageSetting calling = simulateAddPackage(appsFilter, - pkg("com.some.other.package", new Intent("TEST_ACTION")), DUMMY_CALLING_UID); + pkg("com.some.other.package", new Intent("TEST_ACTION")), DUMMY_CALLING_APPID); - assertTrue(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, calling, target, 0)); + assertTrue(appsFilter.shouldFilterApplication(DUMMY_CALLING_APPID, calling, target, + SYSTEM_USER)); } @Test public void testQueriesAction_NoMatchingActionFilterLowSdk_DoesntFilter() throws Exception { final AppsFilter appsFilter = - new AppsFilter(mFeatureConfigMock, new String[]{}, false, null); + new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null); simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); PackageSetting target = simulateAddPackage(appsFilter, - pkg("com.some.package"), DUMMY_TARGET_UID); - PackageSetting calling = simulateAddPackage(appsFilter, - pkg("com.some.other.package", - new Intent("TEST_ACTION")) - .setTargetSdkVersion(Build.VERSION_CODES.P), - DUMMY_CALLING_UID); + pkg("com.some.package"), DUMMY_TARGET_APPID); + ParsingPackage callingPkg = pkg("com.some.other.package", + new Intent("TEST_ACTION")) + .setTargetSdkVersion(Build.VERSION_CODES.P); + PackageSetting calling = simulateAddPackage(appsFilter, callingPkg, + DUMMY_CALLING_APPID); - when(mFeatureConfigMock.packageIsEnabled(calling.pkg)).thenReturn(false); - assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, calling, target, 0)); + assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_APPID, calling, target, + SYSTEM_USER)); } @Test public void testNoQueries_Filters() throws Exception { final AppsFilter appsFilter = - new AppsFilter(mFeatureConfigMock, new String[]{}, false, null); + new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null); simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); PackageSetting target = simulateAddPackage(appsFilter, - pkg("com.some.package"), DUMMY_TARGET_UID); + pkg("com.some.package"), DUMMY_TARGET_APPID); PackageSetting calling = simulateAddPackage(appsFilter, - pkg("com.some.other.package"), DUMMY_CALLING_UID); + pkg("com.some.other.package"), DUMMY_CALLING_APPID); - assertTrue(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, calling, target, 0)); + assertTrue(appsFilter.shouldFilterApplication(DUMMY_CALLING_APPID, calling, target, + SYSTEM_USER)); } @Test public void testForceQueryable_DoesntFilter() throws Exception { final AppsFilter appsFilter = - new AppsFilter(mFeatureConfigMock, new String[]{}, false, null); + new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null); simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); PackageSetting target = simulateAddPackage(appsFilter, - pkg("com.some.package").setForceQueryable(true), DUMMY_TARGET_UID); + pkg("com.some.package").setForceQueryable(true), DUMMY_TARGET_APPID); PackageSetting calling = simulateAddPackage(appsFilter, - pkg("com.some.other.package"), DUMMY_CALLING_UID); + pkg("com.some.other.package"), DUMMY_CALLING_APPID); - assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, calling, target, 0)); + assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_APPID, calling, target, + SYSTEM_USER)); } @Test public void testForceQueryableByDevice_SystemCaller_DoesntFilter() throws Exception { final AppsFilter appsFilter = - new AppsFilter(mFeatureConfigMock, new String[]{"com.some.package"}, false, null); + new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{"com.some.package"}, + false, null); simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); PackageSetting target = simulateAddPackage(appsFilter, - pkg("com.some.package"), DUMMY_TARGET_UID, + pkg("com.some.package"), DUMMY_TARGET_APPID, setting -> setting.setPkgFlags(ApplicationInfo.FLAG_SYSTEM)); PackageSetting calling = simulateAddPackage(appsFilter, - pkg("com.some.other.package"), DUMMY_CALLING_UID); + pkg("com.some.other.package"), DUMMY_CALLING_APPID); - assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, calling, target, 0)); + assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_APPID, calling, target, + SYSTEM_USER)); } @Test public void testSystemSignedTarget_DoesntFilter() throws CertificateException { final AppsFilter appsFilter = - new AppsFilter(mFeatureConfigMock, new String[]{}, false, null); + new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null); appsFilter.onSystemReady(); final Signature frameworkSignature = Mockito.mock(Signature.class); @@ -382,62 +408,67 @@ public class AppsFilterTest { simulateAddPackage(appsFilter, pkg("android"), 1000, b -> b.setSigningDetails(frameworkSigningDetails)); PackageSetting target = simulateAddPackage(appsFilter, pkg("com.some.package"), - DUMMY_TARGET_UID, + DUMMY_TARGET_APPID, b -> b.setSigningDetails(frameworkSigningDetails) .setPkgFlags(ApplicationInfo.FLAG_SYSTEM)); PackageSetting calling = simulateAddPackage(appsFilter, - pkg("com.some.other.package"), DUMMY_CALLING_UID, + pkg("com.some.other.package"), DUMMY_CALLING_APPID, b -> b.setSigningDetails(otherSigningDetails)); - assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, calling, target, 0)); + assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_APPID, calling, target, + SYSTEM_USER)); } @Test public void testForceQueryableByDevice_NonSystemCaller_Filters() throws Exception { final AppsFilter appsFilter = - new AppsFilter(mFeatureConfigMock, new String[]{"com.some.package"}, false, null); + new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{"com.some.package"}, + false, null); simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); PackageSetting target = simulateAddPackage(appsFilter, - pkg("com.some.package"), DUMMY_TARGET_UID); + pkg("com.some.package"), DUMMY_TARGET_APPID); PackageSetting calling = simulateAddPackage(appsFilter, - pkg("com.some.other.package"), DUMMY_CALLING_UID); + pkg("com.some.other.package"), DUMMY_CALLING_APPID); - assertTrue(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, calling, target, 0)); + assertTrue(appsFilter.shouldFilterApplication(DUMMY_CALLING_APPID, calling, target, + SYSTEM_USER)); } @Test public void testSystemQueryable_DoesntFilter() throws Exception { final AppsFilter appsFilter = - new AppsFilter(mFeatureConfigMock, new String[]{}, + new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, true /* system force queryable */, null); simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); PackageSetting target = simulateAddPackage(appsFilter, - pkg("com.some.package"), DUMMY_TARGET_UID, + pkg("com.some.package"), DUMMY_TARGET_APPID, setting -> setting.setPkgFlags(ApplicationInfo.FLAG_SYSTEM)); PackageSetting calling = simulateAddPackage(appsFilter, - pkg("com.some.other.package"), DUMMY_CALLING_UID); + pkg("com.some.other.package"), DUMMY_CALLING_APPID); - assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, calling, target, 0)); + assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_APPID, calling, target, + SYSTEM_USER)); } @Test public void testQueriesPackage_DoesntFilter() throws Exception { final AppsFilter appsFilter = - new AppsFilter(mFeatureConfigMock, new String[]{}, false, null); + new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null); simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); PackageSetting target = simulateAddPackage(appsFilter, - pkg("com.some.package"), DUMMY_TARGET_UID); + pkg("com.some.package"), DUMMY_TARGET_APPID); PackageSetting calling = simulateAddPackage(appsFilter, - pkg("com.some.other.package", "com.some.package"), DUMMY_CALLING_UID); + pkg("com.some.other.package", "com.some.package"), DUMMY_CALLING_APPID); - assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, calling, target, 0)); + assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_APPID, calling, target, + SYSTEM_USER)); } @Test @@ -445,63 +476,67 @@ public class AppsFilterTest { when(mFeatureConfigMock.packageIsEnabled(any(AndroidPackage.class))) .thenReturn(false); final AppsFilter appsFilter = - new AppsFilter(mFeatureConfigMock, new String[]{}, false, null); + new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null); simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); PackageSetting target = simulateAddPackage( - appsFilter, pkg("com.some.package"), DUMMY_TARGET_UID); + appsFilter, pkg("com.some.package"), DUMMY_TARGET_APPID); PackageSetting calling = simulateAddPackage( - appsFilter, pkg("com.some.other.package"), DUMMY_CALLING_UID); + appsFilter, pkg("com.some.other.package"), DUMMY_CALLING_APPID); - assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, calling, target, 0)); + assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_APPID, calling, target, + SYSTEM_USER)); } @Test public void testSystemUid_DoesntFilter() throws Exception { final AppsFilter appsFilter = - new AppsFilter(mFeatureConfigMock, new String[]{}, false, null); + new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null); simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); PackageSetting target = simulateAddPackage(appsFilter, - pkg("com.some.package"), DUMMY_TARGET_UID); + pkg("com.some.package"), DUMMY_TARGET_APPID); - assertFalse(appsFilter.shouldFilterApplication(0, null, target, 0)); + assertFalse(appsFilter.shouldFilterApplication(SYSTEM_USER, null, target, SYSTEM_USER)); assertFalse(appsFilter.shouldFilterApplication(Process.FIRST_APPLICATION_UID - 1, - null, target, 0)); + null, target, SYSTEM_USER)); } @Test public void testNonSystemUid_NoCallingSetting_Filters() throws Exception { final AppsFilter appsFilter = - new AppsFilter(mFeatureConfigMock, new String[]{}, false, null); + new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null); simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); PackageSetting target = simulateAddPackage(appsFilter, - pkg("com.some.package"), DUMMY_TARGET_UID); + pkg("com.some.package"), DUMMY_TARGET_APPID); - assertTrue(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, null, target, 0)); + assertTrue(appsFilter.shouldFilterApplication(DUMMY_CALLING_APPID, null, target, + SYSTEM_USER)); } @Test public void testNoTargetPackage_filters() throws Exception { final AppsFilter appsFilter = - new AppsFilter(mFeatureConfigMock, new String[]{}, false, null); + new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null); simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); PackageSetting target = new PackageSettingBuilder() + .setAppId(DUMMY_TARGET_APPID) .setName("com.some.package") .setCodePath("/") .setResourcePath("/") .setPVersionCode(1L) .build(); PackageSetting calling = simulateAddPackage(appsFilter, - pkg("com.some.other.package", new Intent("TEST_ACTION")), DUMMY_CALLING_UID); + pkg("com.some.other.package", new Intent("TEST_ACTION")), DUMMY_CALLING_APPID); - assertTrue(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, calling, target, 0)); + assertTrue(appsFilter.shouldFilterApplication(DUMMY_CALLING_APPID, calling, target, + SYSTEM_USER)); } @Test @@ -516,7 +551,11 @@ public class AppsFilterTest { .setOverlayTargetName("overlayableName"); ParsingPackage actor = pkg("com.some.package.actor"); - final AppsFilter appsFilter = new AppsFilter(mFeatureConfigMock, new String[]{}, false, + final AppsFilter appsFilter = new AppsFilter( + mStateProvider, + mFeatureConfigMock, + new String[]{}, + false, new OverlayReferenceMapper.Provider() { @Nullable @Override @@ -544,31 +583,34 @@ public class AppsFilterTest { simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); - PackageSetting targetSetting = simulateAddPackage(appsFilter, target, DUMMY_TARGET_UID); - PackageSetting overlaySetting = simulateAddPackage(appsFilter, overlay, DUMMY_OVERLAY_UID); - PackageSetting actorSetting = simulateAddPackage(appsFilter, actor, DUMMY_ACTOR_UID); + PackageSetting targetSetting = simulateAddPackage(appsFilter, target, DUMMY_TARGET_APPID); + PackageSetting overlaySetting = + simulateAddPackage(appsFilter, overlay, DUMMY_OVERLAY_APPID); + PackageSetting actorSetting = simulateAddPackage(appsFilter, actor, DUMMY_ACTOR_APPID); // Actor can see both target and overlay - assertFalse(appsFilter.shouldFilterApplication(DUMMY_ACTOR_UID, actorSetting, - targetSetting, 0)); - assertFalse(appsFilter.shouldFilterApplication(DUMMY_ACTOR_UID, actorSetting, - overlaySetting, 0)); + assertFalse(appsFilter.shouldFilterApplication(DUMMY_ACTOR_APPID, actorSetting, + targetSetting, SYSTEM_USER)); + assertFalse(appsFilter.shouldFilterApplication(DUMMY_ACTOR_APPID, actorSetting, + overlaySetting, SYSTEM_USER)); // But target/overlay can't see each other - assertTrue(appsFilter.shouldFilterApplication(DUMMY_TARGET_UID, targetSetting, - overlaySetting, 0)); - assertTrue(appsFilter.shouldFilterApplication(DUMMY_OVERLAY_UID, overlaySetting, - targetSetting, 0)); + assertTrue(appsFilter.shouldFilterApplication(DUMMY_TARGET_APPID, targetSetting, + overlaySetting, SYSTEM_USER)); + assertTrue(appsFilter.shouldFilterApplication(DUMMY_OVERLAY_APPID, overlaySetting, + targetSetting, SYSTEM_USER)); // And can't see the actor - assertTrue(appsFilter.shouldFilterApplication(DUMMY_TARGET_UID, targetSetting, - actorSetting, 0)); - assertTrue(appsFilter.shouldFilterApplication(DUMMY_OVERLAY_UID, overlaySetting, - actorSetting, 0)); + assertTrue(appsFilter.shouldFilterApplication(DUMMY_TARGET_APPID, targetSetting, + actorSetting, SYSTEM_USER)); + assertTrue(appsFilter.shouldFilterApplication(DUMMY_OVERLAY_APPID, overlaySetting, + actorSetting, SYSTEM_USER)); } @Test public void testActsOnTargetOfOverlayThroughSharedUser() throws Exception { +// Debug.waitForDebugger(); + final String actorName = "overlay://test/actorName"; ParsingPackage target = pkg("com.some.package.target") @@ -580,7 +622,11 @@ public class AppsFilterTest { ParsingPackage actorOne = pkg("com.some.package.actor.one"); ParsingPackage actorTwo = pkg("com.some.package.actor.two"); - final AppsFilter appsFilter = new AppsFilter(mFeatureConfigMock, new String[]{}, false, + final AppsFilter appsFilter = new AppsFilter( + mStateProvider, + mFeatureConfigMock, + new String[]{}, + false, new OverlayReferenceMapper.Provider() { @Nullable @Override @@ -609,108 +655,114 @@ public class AppsFilterTest { simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); - PackageSetting targetSetting = simulateAddPackage(appsFilter, target, DUMMY_TARGET_UID); - PackageSetting overlaySetting = simulateAddPackage(appsFilter, overlay, DUMMY_OVERLAY_UID); - PackageSetting actorOneSetting = simulateAddPackage(appsFilter, actorOne, DUMMY_ACTOR_UID); - PackageSetting actorTwoSetting = simulateAddPackage(appsFilter, actorTwo, - DUMMY_ACTOR_TWO_UID); - + PackageSetting targetSetting = simulateAddPackage(appsFilter, target, DUMMY_TARGET_APPID); SharedUserSetting actorSharedSetting = new SharedUserSetting("actorSharedUser", - actorOneSetting.pkgFlags, actorOneSetting.pkgPrivateFlags); - actorSharedSetting.addPackage(actorOneSetting); - actorSharedSetting.addPackage(actorTwoSetting); + targetSetting.pkgFlags, targetSetting.pkgPrivateFlags); + PackageSetting overlaySetting = + simulateAddPackage(appsFilter, overlay, DUMMY_OVERLAY_APPID); + simulateAddPackage(appsFilter, actorOne, DUMMY_ACTOR_APPID, + null /*settingBuilder*/, actorSharedSetting); + simulateAddPackage(appsFilter, actorTwo, DUMMY_ACTOR_APPID, + null /*settingBuilder*/, actorSharedSetting); + // actorTwo can see both target and overlay - assertFalse(appsFilter.shouldFilterApplication(DUMMY_ACTOR_TWO_UID, actorSharedSetting, - targetSetting, 0)); - assertFalse(appsFilter.shouldFilterApplication(DUMMY_ACTOR_TWO_UID, actorSharedSetting, - overlaySetting, 0)); + assertFalse(appsFilter.shouldFilterApplication(DUMMY_ACTOR_APPID, actorSharedSetting, + targetSetting, SYSTEM_USER)); + assertFalse(appsFilter.shouldFilterApplication(DUMMY_ACTOR_APPID, actorSharedSetting, + overlaySetting, SYSTEM_USER)); } @Test public void testInitiatingApp_DoesntFilter() throws Exception { final AppsFilter appsFilter = - new AppsFilter(mFeatureConfigMock, new String[]{}, false, null); + new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null); simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); PackageSetting target = simulateAddPackage(appsFilter, pkg("com.some.package"), - DUMMY_TARGET_UID); + DUMMY_TARGET_APPID); PackageSetting calling = simulateAddPackage(appsFilter, pkg("com.some.other.package"), - DUMMY_CALLING_UID, withInstallSource(target.name, null, null, false)); + DUMMY_CALLING_APPID, withInstallSource(target.name, null, null, false)); - assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, calling, target, 0)); + assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_APPID, calling, target, + SYSTEM_USER)); } @Test public void testUninstalledInitiatingApp_Filters() throws Exception { final AppsFilter appsFilter = - new AppsFilter(mFeatureConfigMock, new String[]{}, false, null); + new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null); simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); PackageSetting target = simulateAddPackage(appsFilter, pkg("com.some.package"), - DUMMY_TARGET_UID); + DUMMY_TARGET_APPID); PackageSetting calling = simulateAddPackage(appsFilter, pkg("com.some.other.package"), - DUMMY_CALLING_UID, withInstallSource(target.name, null, null, true)); + DUMMY_CALLING_APPID, withInstallSource(target.name, null, null, true)); - assertTrue(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, calling, target, 0)); + assertTrue(appsFilter.shouldFilterApplication(DUMMY_CALLING_APPID, calling, target, + SYSTEM_USER)); } @Test public void testOriginatingApp_Filters() throws Exception { final AppsFilter appsFilter = - new AppsFilter(mFeatureConfigMock, new String[]{}, false, null); + new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null); simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); PackageSetting target = simulateAddPackage(appsFilter, pkg("com.some.package"), - DUMMY_TARGET_UID); + DUMMY_TARGET_APPID); PackageSetting calling = simulateAddPackage(appsFilter, pkg("com.some.other.package"), - DUMMY_CALLING_UID, withInstallSource(null, target.name, null, false)); + DUMMY_CALLING_APPID, withInstallSource(null, target.name, null, false)); - assertTrue(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, calling, target, 0)); + assertTrue(appsFilter.shouldFilterApplication(DUMMY_CALLING_APPID, calling, target, + SYSTEM_USER)); } @Test public void testInstallingApp_DoesntFilter() throws Exception { final AppsFilter appsFilter = - new AppsFilter(mFeatureConfigMock, new String[]{}, false, null); + new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null); simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); PackageSetting target = simulateAddPackage(appsFilter, pkg("com.some.package"), - DUMMY_TARGET_UID); + DUMMY_TARGET_APPID); PackageSetting calling = simulateAddPackage(appsFilter, pkg("com.some.other.package"), - DUMMY_CALLING_UID, withInstallSource(null, null, target.name, false)); + DUMMY_CALLING_APPID, withInstallSource(null, null, target.name, false)); - assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, calling, target, 0)); + assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_APPID, calling, target, + SYSTEM_USER)); } @Test public void testInstrumentation_DoesntFilter() throws Exception { final AppsFilter appsFilter = - new AppsFilter(mFeatureConfigMock, new String[]{}, false, null); + new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null); simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); PackageSetting target = simulateAddPackage(appsFilter, pkg("com.some.package"), - DUMMY_TARGET_UID); + DUMMY_TARGET_APPID); PackageSetting instrumentation = simulateAddPackage(appsFilter, pkgWithInstrumentation("com.some.other.package", "com.some.package"), - DUMMY_CALLING_UID); + DUMMY_CALLING_APPID); assertFalse( - appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, instrumentation, target, 0)); + appsFilter.shouldFilterApplication(DUMMY_CALLING_APPID, instrumentation, target, + SYSTEM_USER)); assertFalse( - appsFilter.shouldFilterApplication(DUMMY_TARGET_UID, target, instrumentation, 0)); + appsFilter.shouldFilterApplication(DUMMY_TARGET_APPID, target, instrumentation, + SYSTEM_USER)); } @Test public void testWhoCanSee() throws Exception { final AppsFilter appsFilter = - new AppsFilter(mFeatureConfigMock, new String[]{}, false, null); + new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null); simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); @@ -728,21 +780,25 @@ public class AppsFilterTest { queriesProviderAppId); final int[] systemFilter = - appsFilter.getVisibilityWhitelist(system, new int[]{0}, mExisting).get(0); + appsFilter.getVisibilityWhitelist(system, SINGLE_USER_ARRAY, mExisting) + .get(SYSTEM_USER); assertThat(toList(systemFilter), empty()); final int[] seesNothingFilter = - appsFilter.getVisibilityWhitelist(seesNothing, new int[]{0}, mExisting).get(0); + appsFilter.getVisibilityWhitelist(seesNothing, SINGLE_USER_ARRAY, mExisting) + .get(SYSTEM_USER); assertThat(toList(seesNothingFilter), contains(seesNothingAppId)); final int[] hasProviderFilter = - appsFilter.getVisibilityWhitelist(hasProvider, new int[]{0}, mExisting).get(0); + appsFilter.getVisibilityWhitelist(hasProvider, SINGLE_USER_ARRAY, mExisting) + .get(SYSTEM_USER); assertThat(toList(hasProviderFilter), contains(hasProviderAppId, queriesProviderAppId)); int[] queriesProviderFilter = - appsFilter.getVisibilityWhitelist(queriesProvider, new int[]{0}, mExisting).get(0); + appsFilter.getVisibilityWhitelist(queriesProvider, SINGLE_USER_ARRAY, mExisting) + .get(SYSTEM_USER); assertThat(toList(queriesProviderFilter), contains(queriesProviderAppId)); @@ -751,7 +807,8 @@ public class AppsFilterTest { // ensure implicit access is included in the filter queriesProviderFilter = - appsFilter.getVisibilityWhitelist(queriesProvider, new int[]{0}, mExisting).get(0); + appsFilter.getVisibilityWhitelist(queriesProvider, SINGLE_USER_ARRAY, mExisting) + .get(SYSTEM_USER); assertThat(toList(queriesProviderFilter), contains(hasProviderAppId, queriesProviderAppId)); } @@ -779,11 +836,17 @@ public class AppsFilterTest { private PackageSetting simulateAddPackage(AppsFilter filter, ParsingPackage newPkgBuilder, int appId) { - return simulateAddPackage(filter, newPkgBuilder, appId, null); + return simulateAddPackage(filter, newPkgBuilder, appId, null /*settingBuilder*/); } private PackageSetting simulateAddPackage(AppsFilter filter, ParsingPackage newPkgBuilder, int appId, @Nullable WithSettingBuilder action) { + return simulateAddPackage(filter, newPkgBuilder, appId, action, null /*sharedUserSetting*/); + } + + private PackageSetting simulateAddPackage(AppsFilter filter, + ParsingPackage newPkgBuilder, int appId, @Nullable WithSettingBuilder action, + @Nullable SharedUserSetting sharedUserSetting) { AndroidPackage newPkg = ((ParsedPackage) newPkgBuilder.hideAsParsed()).hideAsFinal(); final PackageSettingBuilder settingBuilder = new PackageSettingBuilder() @@ -795,8 +858,12 @@ public class AppsFilterTest { .setPVersionCode(1L); final PackageSetting setting = (action == null ? settingBuilder : action.withBuilder(settingBuilder)).build(); - filter.addPackage(setting, mExisting); mExisting.put(newPkg.getPackageName(), setting); + if (sharedUserSetting != null) { + sharedUserSetting.addPackage(setting); + setting.sharedUser = sharedUserSetting; + } + filter.addPackage(setting); return setting; } @@ -809,4 +876,3 @@ public class AppsFilterTest { return setting -> setting.setInstallSource(installSource); } } - |