summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Songchun Fan <schfan@google.com> 2022-04-01 16:42:38 +0000
committer Songchun Fan <schfan@google.com> 2022-04-06 20:53:31 +0000
commit3def2802db726dc078a5e359b71aa814293aee04 (patch)
treebf1bedb16806d384ba0c7b0931ccca5e870c5ea4
parentaea49e77fdefa2295758ac23f971c39b98548511 (diff)
Revert "Revert "[AppsFilter] read-only interface for snapshots""
This reverts commit 2e06c6008e595b9b167f3463431d9dcdb16687bb. Reason for revert: fixing the boot time regression Provides a read-only interface that is used by computer and snapshots. It fixes the data conflicts when AppsFilter is changed while a snapshot is taken. Test: atest AppsFilterTest Test: atest com.android.server.utils.WatcherTest Test: m RUN_ERROR_PRONE=true framework services.core |& grep AppsFilter BUG: 218411030 Change-Id: I06624ea79ff85160488a6c7863213b0c44fe2154
-rw-r--r--core/java/android/util/SparseSetArray.java21
-rw-r--r--services/core/java/com/android/server/pm/AppsFilterImpl.java (renamed from services/core/java/com/android/server/pm/AppsFilter.java)270
-rw-r--r--services/core/java/com/android/server/pm/AppsFilterSnapshot.java86
-rw-r--r--services/core/java/com/android/server/pm/ComputerEngine.java2
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java7
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerServiceInjector.java6
-rw-r--r--services/core/java/com/android/server/utils/WatchedArrayList.java7
-rw-r--r--services/core/java/com/android/server/utils/WatchedSparseBooleanMatrix.java20
-rw-r--r--services/core/java/com/android/server/utils/WatchedSparseSetArray.java177
-rw-r--r--services/tests/PackageManagerComponentOverrideTests/src/com/android/server/pm/test/override/PackageManagerComponentLabelIconOverrideTest.kt7
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt2
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/AppsFilterImplTest.java (renamed from services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java)215
-rw-r--r--services/tests/servicestests/src/com/android/server/utils/WatcherTest.java61
13 files changed, 685 insertions, 196 deletions
diff --git a/core/java/android/util/SparseSetArray.java b/core/java/android/util/SparseSetArray.java
index f5025f7a9e99..f85280f0264b 100644
--- a/core/java/android/util/SparseSetArray.java
+++ b/core/java/android/util/SparseSetArray.java
@@ -15,15 +15,34 @@
*/
package android.util;
+import android.annotation.NonNull;
+
/**
* A sparse array of ArraySets, which is suitable to hold userid->packages association.
*
* @hide
*/
public class SparseSetArray<T> {
- private final SparseArray<ArraySet<T>> mData = new SparseArray<>();
+ private final SparseArray<ArraySet<T>> mData;
public SparseSetArray() {
+ mData = new SparseArray<>();
+ }
+
+ /**
+ * Copy constructor
+ */
+ public SparseSetArray(@NonNull SparseSetArray<T> src) {
+ final int arraySize = src.size();
+ mData = new SparseArray<>(arraySize);
+ for (int i = 0; i < arraySize; i++) {
+ final int key = src.keyAt(i);
+ final ArraySet<T> set = src.get(key);
+ final int setSize = set.size();
+ for (int j = 0; j < setSize; j++) {
+ add(key, set.valueAt(j));
+ }
+ }
}
/**
diff --git a/services/core/java/com/android/server/pm/AppsFilter.java b/services/core/java/com/android/server/pm/AppsFilterImpl.java
index 29ee28175f57..5865adb96333 100644
--- a/services/core/java/com/android/server/pm/AppsFilter.java
+++ b/services/core/java/com/android/server/pm/AppsFilterImpl.java
@@ -44,7 +44,6 @@ import android.util.ArraySet;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
-import android.util.SparseSetArray;
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
@@ -64,14 +63,18 @@ import com.android.server.pm.pkg.component.ParsedMainComponent;
import com.android.server.pm.pkg.component.ParsedProvider;
import com.android.server.utils.Snappable;
import com.android.server.utils.SnapshotCache;
-import com.android.server.utils.Snapshots;
import com.android.server.utils.Watchable;
import com.android.server.utils.WatchableImpl;
+import com.android.server.utils.Watched;
+import com.android.server.utils.WatchedArrayList;
import com.android.server.utils.WatchedArrayMap;
+import com.android.server.utils.WatchedArraySet;
import com.android.server.utils.WatchedSparseBooleanMatrix;
+import com.android.server.utils.WatchedSparseSetArray;
import com.android.server.utils.Watcher;
import java.io.PrintWriter;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
@@ -84,7 +87,7 @@ import java.util.concurrent.Executor;
* manifests.
*/
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
-public class AppsFilter implements Watchable, Snappable {
+public class AppsFilterImpl implements AppsFilterSnapshot, Watchable, Snappable {
private static final String TAG = "AppsFilter";
@@ -99,32 +102,43 @@ public class AppsFilter implements Watchable, Snappable {
* application B is implicitly allowed to query for application A; regardless of any manifest
* entries.
*/
- private final SparseSetArray<Integer> mImplicitlyQueryable = new SparseSetArray<>();
+ @Watched
+ private final WatchedSparseSetArray<Integer> mImplicitlyQueryable;
+ private final SnapshotCache<WatchedSparseSetArray<Integer>> mImplicitQueryableSnapshot;
/**
* This contains a list of app UIDs that are implicitly queryable because another app explicitly
* interacted with it, but could keep across package updates. For example, if application A
* grants persistable uri permission to application B; regardless of any manifest entries.
*/
- private final SparseSetArray<Integer> mRetainedImplicitlyQueryable = new SparseSetArray<>();
+ @Watched
+ private final WatchedSparseSetArray<Integer> mRetainedImplicitlyQueryable;
+ private final SnapshotCache<WatchedSparseSetArray<Integer>>
+ mRetainedImplicitlyQueryableSnapshot;
/**
* A mapping from the set of App IDs that query other App IDs via package name to the
* list of packages that they can see.
*/
- private final SparseSetArray<Integer> mQueriesViaPackage = new SparseSetArray<>();
+ @Watched
+ private final WatchedSparseSetArray<Integer> mQueriesViaPackage;
+ private final SnapshotCache<WatchedSparseSetArray<Integer>> mQueriesViaPackageSnapshot;
/**
* A mapping from the set of App IDs that query others via component match to the list
* of packages that the they resolve to.
*/
- private final SparseSetArray<Integer> mQueriesViaComponent = new SparseSetArray<>();
+ @Watched
+ private final WatchedSparseSetArray<Integer> mQueriesViaComponent;
+ private final SnapshotCache<WatchedSparseSetArray<Integer>> mQueriesViaComponentSnapshot;
/**
* A mapping from the set of App IDs that query other App IDs via library name to the
* list of packages that they can see.
*/
- private final SparseSetArray<Integer> mQueryableViaUsesLibrary = new SparseSetArray<>();
+ @Watched
+ private final WatchedSparseSetArray<Integer> mQueryableViaUsesLibrary;
+ private final SnapshotCache<WatchedSparseSetArray<Integer>> mQueryableViaUsesLibrarySnapshot;
/**
* Executor for running reasonably short background tasks such as building the initial
@@ -144,7 +158,9 @@ public class AppsFilter implements Watchable, Snappable {
* A set of App IDs that are always queryable by any package, regardless of their manifest
* content.
*/
- private final ArraySet<Integer> mForceQueryable = new ArraySet<>();
+ @Watched
+ private final WatchedArraySet<Integer> mForceQueryable;
+ private final SnapshotCache<WatchedArraySet<Integer>> mForceQueryableSnapshot;
/**
* The set of package names provided by the device that should be force queryable regardless of
@@ -154,14 +170,15 @@ public class AppsFilter implements Watchable, Snappable {
/** True if all system apps should be made queryable by default. */
private final boolean mSystemAppsQueryable;
-
private final FeatureConfig mFeatureConfig;
private final OverlayReferenceMapper mOverlayReferenceMapper;
private final StateProvider mStateProvider;
private final PackageManagerInternal mPmInternal;
-
private SigningDetails mSystemSigningDetails;
- private Set<String> mProtectedBroadcasts = new ArraySet<>();
+
+ @Watched
+ private final WatchedArrayList<String> mProtectedBroadcasts;
+ private final SnapshotCache<WatchedArrayList<String>> mProtectedBroadcastsSnapshot;
private final Object mCacheLock = new Object();
@@ -175,19 +192,21 @@ public class AppsFilter implements Watchable, Snappable {
@GuardedBy("mCacheLock")
@NonNull
private final WatchedSparseBooleanMatrix mShouldFilterCache;
+ private final SnapshotCache<WatchedSparseBooleanMatrix> mShouldFilterCacheSnapshot;
private volatile boolean mSystemReady = false;
/**
* A cached snapshot.
*/
- private final SnapshotCache<AppsFilter> mSnapshot;
+ private final SnapshotCache<AppsFilterImpl> mSnapshot;
- private SnapshotCache<AppsFilter> makeCache() {
- return new SnapshotCache<AppsFilter>(this, this) {
+ private SnapshotCache<AppsFilterImpl> makeCache() {
+ return new SnapshotCache<AppsFilterImpl>(this, this) {
@Override
- public AppsFilter createSnapshot() {
- AppsFilter s = new AppsFilter(mSource);
+ public AppsFilterImpl createSnapshot() {
+ AppsFilterImpl s = new AppsFilterImpl(mSource);
+ s.mWatchable.seal();
return s;
}
};
@@ -197,6 +216,15 @@ public class AppsFilter implements Watchable, Snappable {
* Watchable machinery
*/
private final WatchableImpl mWatchable = new WatchableImpl();
+ /**
+ * The observer that watches for changes from array members
+ */
+ private final Watcher mObserver = new Watcher() {
+ @Override
+ public void onChange(@Nullable Watchable what) {
+ AppsFilterImpl.this.dispatchChange(what);
+ }
+ };
/**
* Ensures an observer is in the list, exactly once. The observer cannot be null. The
@@ -251,7 +279,7 @@ public class AppsFilter implements Watchable, Snappable {
}
@VisibleForTesting(visibility = PRIVATE)
- AppsFilter(StateProvider stateProvider,
+ AppsFilterImpl(StateProvider stateProvider,
FeatureConfig featureConfig,
String[] forceQueryableList,
boolean systemAppsQueryable,
@@ -267,31 +295,67 @@ public class AppsFilter implements Watchable, Snappable {
mPmInternal = pmInternal;
mBackgroundExecutor = backgroundExecutor;
mShouldFilterCache = new WatchedSparseBooleanMatrix();
+ mShouldFilterCacheSnapshot = new SnapshotCache.Auto<>(
+ mShouldFilterCache, mShouldFilterCache, "AppsFilter.mShouldFilterCache");
+ mImplicitlyQueryable = new WatchedSparseSetArray<>();
+ mImplicitQueryableSnapshot = new SnapshotCache.Auto<>(
+ mImplicitlyQueryable, mImplicitlyQueryable, "AppsFilter.mImplicitlyQueryable");
+ mRetainedImplicitlyQueryable = new WatchedSparseSetArray<>();
+ mRetainedImplicitlyQueryableSnapshot = new SnapshotCache.Auto<>(
+ mRetainedImplicitlyQueryable, mRetainedImplicitlyQueryable,
+ "AppsFilter.mRetainedImplicitlyQueryable");
+ mQueriesViaPackage = new WatchedSparseSetArray<>();
+ mQueriesViaPackageSnapshot = new SnapshotCache.Auto<>(
+ mQueriesViaPackage, mQueriesViaPackage, "AppsFilter.mQueriesViaPackage");
+ mQueriesViaComponent = new WatchedSparseSetArray<>();
+ mQueriesViaComponentSnapshot = new SnapshotCache.Auto<>(
+ mQueriesViaComponent, mQueriesViaComponent, "AppsFilter.mQueriesViaComponent");
+ mQueryableViaUsesLibrary = new WatchedSparseSetArray<>();
+ mQueryableViaUsesLibrarySnapshot = new SnapshotCache.Auto<>(
+ mQueryableViaUsesLibrary, mQueryableViaUsesLibrary,
+ "AppsFilter.mQueryableViaUsesLibrary");
+ mForceQueryable = new WatchedArraySet<>();
+ mForceQueryableSnapshot = new SnapshotCache.Auto<>(
+ mForceQueryable, mForceQueryable, "AppsFilter.mForceQueryable");
+ mProtectedBroadcasts = new WatchedArrayList<>();
+ mProtectedBroadcastsSnapshot = new SnapshotCache.Auto<>(
+ mProtectedBroadcasts, mProtectedBroadcasts, "AppsFilter.mProtectedBroadcasts");
+
+ registerObservers();
+ Watchable.verifyWatchedAttributes(this, mObserver);
mSnapshot = makeCache();
}
/**
* The copy constructor is used by PackageManagerService to construct a snapshot.
- * Attributes are not deep-copied since these are supposed to be immutable.
- * TODO: deep-copy the attributes, if necessary.
*/
- private AppsFilter(AppsFilter orig) {
- Snapshots.copy(mImplicitlyQueryable, orig.mImplicitlyQueryable);
- Snapshots.copy(mRetainedImplicitlyQueryable, orig.mRetainedImplicitlyQueryable);
- Snapshots.copy(mQueriesViaPackage, orig.mQueriesViaPackage);
- Snapshots.copy(mQueriesViaComponent, orig.mQueriesViaComponent);
- Snapshots.copy(mQueryableViaUsesLibrary, orig.mQueryableViaUsesLibrary);
+ private AppsFilterImpl(AppsFilterImpl orig) {
+ mImplicitlyQueryable = orig.mImplicitQueryableSnapshot.snapshot();
+ mImplicitQueryableSnapshot = new SnapshotCache.Sealed<>();
+ mRetainedImplicitlyQueryable = orig.mRetainedImplicitlyQueryableSnapshot.snapshot();
+ mRetainedImplicitlyQueryableSnapshot = new SnapshotCache.Sealed<>();
+ mQueriesViaPackage = orig.mQueriesViaPackageSnapshot.snapshot();
+ mQueriesViaPackageSnapshot = new SnapshotCache.Sealed<>();
+ mQueriesViaComponent = orig.mQueriesViaComponentSnapshot.snapshot();
+ mQueriesViaComponentSnapshot = new SnapshotCache.Sealed<>();
+ mQueryableViaUsesLibrary = orig.mQueryableViaUsesLibrarySnapshot.snapshot();
+ mQueryableViaUsesLibrarySnapshot = new SnapshotCache.Sealed<>();
+ mForceQueryable = orig.mForceQueryableSnapshot.snapshot();
+ mForceQueryableSnapshot = new SnapshotCache.Sealed<>();
+ mProtectedBroadcasts = orig.mProtectedBroadcastsSnapshot.snapshot();
+ mProtectedBroadcastsSnapshot = new SnapshotCache.Sealed<>();
mQueriesViaComponentRequireRecompute = orig.mQueriesViaComponentRequireRecompute;
- mForceQueryable.addAll(orig.mForceQueryable);
- mForceQueryableByDevicePackageNames = orig.mForceQueryableByDevicePackageNames;
+ mForceQueryableByDevicePackageNames =
+ Arrays.copyOf(orig.mForceQueryableByDevicePackageNames,
+ orig.mForceQueryableByDevicePackageNames.length);
mSystemAppsQueryable = orig.mSystemAppsQueryable;
mFeatureConfig = orig.mFeatureConfig;
mOverlayReferenceMapper = orig.mOverlayReferenceMapper;
mStateProvider = orig.mStateProvider;
mSystemSigningDetails = orig.mSystemSigningDetails;
- mProtectedBroadcasts = orig.mProtectedBroadcasts;
synchronized (orig.mCacheLock) {
- mShouldFilterCache = orig.mShouldFilterCache.snapshot();
+ mShouldFilterCache = orig.mShouldFilterCacheSnapshot.snapshot();
+ mShouldFilterCacheSnapshot = new SnapshotCache.Sealed<>();
}
mBackgroundExecutor = null;
@@ -300,12 +364,24 @@ public class AppsFilter implements Watchable, Snappable {
mSystemReady = true;
}
+ @SuppressWarnings("GuardedBy")
+ private void registerObservers() {
+ mImplicitlyQueryable.registerObserver(mObserver);
+ mRetainedImplicitlyQueryable.registerObserver(mObserver);
+ mQueriesViaPackage.registerObserver(mObserver);
+ mQueriesViaComponent.registerObserver(mObserver);
+ mQueryableViaUsesLibrary.registerObserver(mObserver);
+ mForceQueryable.registerObserver(mObserver);
+ mProtectedBroadcasts.registerObserver(mObserver);
+ mShouldFilterCache.registerObserver(mObserver);
+ }
+
/**
* Return a snapshot. If the cached snapshot is null, build a new one. The logic in
* the function ensures that this function returns a valid snapshot even if a race
* condition causes the cached snapshot to be cleared asynchronously to this method.
*/
- public AppsFilter snapshot() {
+ public AppsFilterSnapshot snapshot() {
return mSnapshot.snapshot();
}
@@ -366,7 +442,7 @@ public class AppsFilter implements Watchable, Snappable {
@Nullable
private SparseBooleanArray mLoggingEnabled = null;
- private AppsFilter mAppsFilter;
+ private AppsFilterImpl mAppsFilter;
private FeatureConfigImpl(
PackageManagerInternal pmInternal, PackageManagerServiceInjector injector) {
@@ -374,7 +450,7 @@ public class AppsFilter implements Watchable, Snappable {
mInjector = injector;
}
- public void setAppsFilter(AppsFilter filter) {
+ public void setAppsFilter(AppsFilterImpl filter) {
mAppsFilter = filter;
}
@@ -478,8 +554,9 @@ public class AppsFilter implements Watchable, Snappable {
@Override
public void updatePackageState(PackageStateInternal setting, boolean removed) {
- final boolean enableLogging = setting.getPkg() != null &&
- !removed && (setting.getPkg().isTestOnly() || setting.getPkg().isDebuggable());
+ final boolean enableLogging = setting.getPkg() != null
+ && !removed && (setting.getPkg().isTestOnly()
+ || setting.getPkg().isDebuggable());
enableLogging(setting.getAppId(), enableLogging);
if (removed) {
mDisabledPackages.remove(setting.getPackageName());
@@ -490,7 +567,7 @@ public class AppsFilter implements Watchable, Snappable {
}
/** Builder method for an AppsFilter */
- public static AppsFilter create(@NonNull PackageManagerServiceInjector injector,
+ public static AppsFilterImpl create(@NonNull PackageManagerServiceInjector injector,
@NonNull PackageManagerInternal pmInt) {
final boolean forceSystemAppsQueryable =
injector.getContext().getResources()
@@ -514,7 +591,7 @@ public class AppsFilter implements Watchable, Snappable {
injector.getUserManagerInternal().getUserInfos());
}
};
- AppsFilter appsFilter = new AppsFilter(stateProvider, featureConfig,
+ AppsFilterImpl appsFilter = new AppsFilterImpl(stateProvider, featureConfig,
forcedQueryablePackageNames, forceSystemAppsQueryable, null,
injector.getBackgroundExecutor(), pmInt);
featureConfig.setAppsFilter(appsFilter);
@@ -527,7 +604,7 @@ public class AppsFilter implements Watchable, Snappable {
/** Returns true if the querying package may query for the potential target package */
private static boolean canQueryViaComponents(AndroidPackage querying,
- AndroidPackage potentialTarget, Set<String> protectedBroadcasts) {
+ AndroidPackage potentialTarget, WatchedArrayList<String> protectedBroadcasts) {
if (!querying.getQueriesIntents().isEmpty()) {
for (Intent intent : querying.getQueriesIntents()) {
if (matchesPackage(intent, potentialTarget, protectedBroadcasts)) {
@@ -599,7 +676,7 @@ public class AppsFilter implements Watchable, Snappable {
}
private static boolean matchesPackage(Intent intent, AndroidPackage potentialTarget,
- Set<String> protectedBroadcasts) {
+ WatchedArrayList<String> protectedBroadcasts) {
if (matchesAnyComponents(
intent, potentialTarget.getServices(), null /*protectedBroadcasts*/)) {
return true;
@@ -620,7 +697,7 @@ public class AppsFilter implements Watchable, Snappable {
private static boolean matchesAnyComponents(Intent intent,
List<? extends ParsedMainComponent> components,
- Set<String> protectedBroadcasts) {
+ WatchedArrayList<String> protectedBroadcasts) {
for (int i = ArrayUtils.size(components) - 1; i >= 0; i--) {
ParsedMainComponent component = components.get(i);
if (!component.isExported()) {
@@ -634,7 +711,7 @@ public class AppsFilter implements Watchable, Snappable {
}
private static boolean matchesAnyFilter(Intent intent, ParsedComponent component,
- Set<String> protectedBroadcasts) {
+ WatchedArrayList<String> protectedBroadcasts) {
List<ParsedIntentInfo> intents = component.getIntents();
for (int i = ArrayUtils.size(intents) - 1; i >= 0; i--) {
IntentFilter intentFilter = intents.get(i).getIntentFilter();
@@ -646,10 +723,10 @@ public class AppsFilter implements Watchable, Snappable {
}
private static boolean matchesIntentFilter(Intent intent, IntentFilter intentFilter,
- @Nullable Set<String> protectedBroadcasts) {
+ @Nullable WatchedArrayList<String> protectedBroadcasts) {
return intentFilter.match(intent.getAction(), intent.getType(), intent.getScheme(),
- intent.getData(), intent.getCategories(), "AppsFilter", true, protectedBroadcasts)
- > 0;
+ intent.getData(), intent.getCategories(), "AppsFilter", true,
+ protectedBroadcasts != null ? protectedBroadcasts.untrackedStorage() : null) > 0;
}
/**
@@ -665,7 +742,8 @@ public class AppsFilter implements Watchable, Snappable {
if (recipientUid == visibleUid) {
return false;
}
- final boolean changed = retainOnUpdate
+ final boolean changed;
+ changed = retainOnUpdate
? mRetainedImplicitlyQueryable.add(recipientUid, visibleUid)
: mImplicitlyQueryable.add(recipientUid, visibleUid);
if (changed && DEBUG_LOGGING) {
@@ -787,7 +865,8 @@ public class AppsFilter implements Watchable, Snappable {
for (int i = existingSettings.size() - 1; i >= 0; i--) {
final PackageStateInternal existingSetting = existingSettings.valueAt(i);
- if (existingSetting.getAppId() == newPkgSetting.getAppId() || existingSetting.getPkg()
+ if (existingSetting.getAppId() == newPkgSetting.getAppId()
+ || existingSetting.getPkg()
== null) {
continue;
}
@@ -796,11 +875,13 @@ public class AppsFilter implements Watchable, Snappable {
if (!newIsForceQueryable) {
if (!mQueriesViaComponentRequireRecompute && canQueryViaComponents(existingPkg,
newPkg, mProtectedBroadcasts)) {
- mQueriesViaComponent.add(existingSetting.getAppId(), newPkgSetting.getAppId());
+ mQueriesViaComponent.add(existingSetting.getAppId(),
+ newPkgSetting.getAppId());
}
if (canQueryViaPackage(existingPkg, newPkg)
|| canQueryAsInstaller(existingSetting, newPkg)) {
- mQueriesViaPackage.add(existingSetting.getAppId(), newPkgSetting.getAppId());
+ mQueriesViaPackage.add(existingSetting.getAppId(),
+ newPkgSetting.getAppId());
}
if (canQueryViaUsesLibrary(existingPkg, newPkg)) {
mQueryableViaUsesLibrary.add(existingSetting.getAppId(),
@@ -811,11 +892,13 @@ public class AppsFilter implements Watchable, Snappable {
if (!mForceQueryable.contains(existingSetting.getAppId())) {
if (!mQueriesViaComponentRequireRecompute && canQueryViaComponents(newPkg,
existingPkg, mProtectedBroadcasts)) {
- mQueriesViaComponent.add(newPkgSetting.getAppId(), existingSetting.getAppId());
+ mQueriesViaComponent.add(newPkgSetting.getAppId(),
+ existingSetting.getAppId());
}
if (canQueryViaPackage(newPkg, existingPkg)
|| canQueryAsInstaller(newPkgSetting, existingPkg)) {
- mQueriesViaPackage.add(newPkgSetting.getAppId(), existingSetting.getAppId());
+ mQueriesViaPackage.add(newPkgSetting.getAppId(),
+ existingSetting.getAppId());
}
if (canQueryViaUsesLibrary(newPkg, existingPkg)) {
mQueryableViaUsesLibrary.add(newPkgSetting.getAppId(),
@@ -1048,10 +1131,10 @@ public class AppsFilter implements Watchable, Snappable {
&& pkgSetting.getSigningDetails().signaturesMatchExactly(sysSigningDetails);
}
- private ArraySet<String> collectProtectedBroadcasts(
+ private void collectProtectedBroadcasts(
ArrayMap<String, ? extends PackageStateInternal> existingSettings,
@Nullable String excludePackage) {
- ArraySet<String> ret = new ArraySet<>();
+ mProtectedBroadcasts.clear();
for (int i = existingSettings.size() - 1; i >= 0; i--) {
PackageStateInternal setting = existingSettings.valueAt(i);
if (setting.getPkg() == null || setting.getPkg().getPackageName().equals(
@@ -1060,10 +1143,9 @@ public class AppsFilter implements Watchable, Snappable {
}
final List<String> protectedBroadcasts = setting.getPkg().getProtectedBroadcasts();
if (!protectedBroadcasts.isEmpty()) {
- ret.addAll(protectedBroadcasts);
+ mProtectedBroadcasts.addAll(protectedBroadcasts);
}
}
- return ret;
}
/**
@@ -1097,19 +1179,9 @@ public class AppsFilter implements Watchable, Snappable {
}
/**
- * 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
- * all applications.
- *
- * 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 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 allow list should be
- * applied.
+ * See {@link AppsFilterSnapshot#getVisibilityAllowList(PackageStateInternal, int[], ArrayMap)}
*/
+ @Override
@Nullable
public SparseArray<int[]> getVisibilityAllowList(PackageStateInternal setting, int[] users,
ArrayMap<String, ? extends PackageStateInternal> existingSettings) {
@@ -1164,7 +1236,7 @@ public class AppsFilter implements Watchable, Snappable {
* Equivalent to calling {@link #addPackage(PackageStateInternal, boolean)} with
* {@code isReplace} equal to {@code false}.
*
- * @see AppsFilter#addPackage(PackageStateInternal, boolean)
+ * @see AppsFilterImpl#addPackage(PackageStateInternal, boolean)
*/
public void addPackage(PackageStateInternal newPkgSetting) {
addPackage(newPkgSetting, false /* isReplace */);
@@ -1178,13 +1250,15 @@ public class AppsFilter implements Watchable, Snappable {
*/
public void removePackage(PackageStateInternal setting, boolean isReplace) {
mStateProvider.runWithState((settings, users) -> {
+ final ArraySet<String> additionalChangedPackages;
final int userCount = users.length;
for (int u = 0; u < userCount; u++) {
final int userId = users[u].id;
final int removingUid = UserHandle.getUid(userId, setting.getAppId());
mImplicitlyQueryable.remove(removingUid);
for (int i = mImplicitlyQueryable.size() - 1; i >= 0; i--) {
- mImplicitlyQueryable.remove(mImplicitlyQueryable.keyAt(i), removingUid);
+ mImplicitlyQueryable.remove(mImplicitlyQueryable.keyAt(i),
+ removingUid);
}
if (isReplace) {
@@ -1201,12 +1275,14 @@ public class AppsFilter implements Watchable, Snappable {
if (!mQueriesViaComponentRequireRecompute) {
mQueriesViaComponent.remove(setting.getAppId());
for (int i = mQueriesViaComponent.size() - 1; i >= 0; i--) {
- mQueriesViaComponent.remove(mQueriesViaComponent.keyAt(i), setting.getAppId());
+ mQueriesViaComponent.remove(mQueriesViaComponent.keyAt(i),
+ setting.getAppId());
}
}
mQueriesViaPackage.remove(setting.getAppId());
for (int i = mQueriesViaPackage.size() - 1; i >= 0; i--) {
- mQueriesViaPackage.remove(mQueriesViaPackage.keyAt(i), setting.getAppId());
+ mQueriesViaPackage.remove(mQueriesViaPackage.keyAt(i),
+ setting.getAppId());
}
mQueryableViaUsesLibrary.remove(setting.getAppId());
for (int i = mQueryableViaUsesLibrary.size() - 1; i >= 0; i--) {
@@ -1216,23 +1292,26 @@ public class AppsFilter implements Watchable, Snappable {
mForceQueryable.remove(setting.getAppId());
- if (setting.getPkg() != null && !setting.getPkg().getProtectedBroadcasts().isEmpty()) {
+ if (setting.getPkg() != null
+ && !setting.getPkg().getProtectedBroadcasts().isEmpty()) {
final String removingPackageName = setting.getPkg().getPackageName();
- final Set<String> protectedBroadcasts = mProtectedBroadcasts;
- mProtectedBroadcasts = collectProtectedBroadcasts(settings, removingPackageName);
+ final ArrayList<String> protectedBroadcasts = new ArrayList<>();
+ protectedBroadcasts.addAll(mProtectedBroadcasts.untrackedStorage());
+ collectProtectedBroadcasts(settings, removingPackageName);
if (!mProtectedBroadcasts.containsAll(protectedBroadcasts)) {
mQueriesViaComponentRequireRecompute = true;
}
}
- ArraySet<String> additionalChangedPackages =
- mOverlayReferenceMapper.removePkg(setting.getPackageName());
-
+ additionalChangedPackages = mOverlayReferenceMapper.removePkg(setting.getPackageName());
mFeatureConfig.updatePackageState(setting, true /*removed*/);
- // After removing all traces of the package, if it's part of a shared user, re-add other
- // shared user members to re-establish visibility between them and other packages.
- // NOTE: this must come after all removals from data structures but before we update the
+ // After removing all traces of the package, if it's part of a shared user,
+ // re-add other
+ // shared user members to re-establish visibility between them and other
+ // packages.
+ // NOTE: this must come after all removals from data structures but before we
+ // update the
// cache
if (setting.hasSharedUser()) {
final ArraySet<PackageStateInternal> sharedUserPackages =
@@ -1285,15 +1364,11 @@ public class AppsFilter implements Watchable, Snappable {
}
/**
- * Returns true if the calling package should not be able to see the target package, false if no
- * filtering should be done.
- *
- * @param callingUid the uid of the caller attempting to access a package
- * @param callingSetting the setting attempting to access a package or null if it could not be
- * found
- * @param targetPkgSetting the package being accessed
- * @param userId the user in which this access is being attempted
+ * See
+ * {@link AppsFilterSnapshot#shouldFilterApplication(int, Object, PackageStateInternal,
+ * int)}
*/
+ @Override
public boolean shouldFilterApplication(int callingUid, @Nullable Object callingSetting,
PackageStateInternal targetPkgSetting, int userId) {
if (DEBUG_TRACING) {
@@ -1610,7 +1685,11 @@ public class AppsFilter implements Watchable, Snappable {
}
}
- boolean canQueryPackage(@NonNull AndroidPackage querying, String potentialTarget) {
+ /**
+ * See {@link AppsFilterSnapshot#canQueryPackage(AndroidPackage, String)}
+ */
+ @Override
+ public boolean canQueryPackage(@NonNull AndroidPackage querying, String potentialTarget) {
int appId = UserHandle.getAppId(querying.getUid());
if (appId < Process.FIRST_APPLICATION_UID) {
return true;
@@ -1665,6 +1744,11 @@ public class AppsFilter implements Watchable, Snappable {
+ targetPkgSetting + " " + description);
}
+ /**
+ * See {@link AppsFilterSnapshot#dumpQueries(PrintWriter, Integer, DumpState, int[],
+ * QuadFunction)}
+ */
+ @Override
public void dumpQueries(
PrintWriter pw, @Nullable Integer filteringAppId, DumpState dumpState, int[] users,
QuadFunction<Integer, Integer, Integer, Boolean, String[]> getPackagesForUid) {
@@ -1699,7 +1783,8 @@ public class AppsFilter implements Watchable, Snappable {
}
}
pw.println(" system apps queryable: " + mSystemAppsQueryable);
- dumpPackageSet(pw, filteringAppId, mForceQueryable, "forceQueryable", " ", expandPackages);
+ dumpPackageSet(pw, filteringAppId, mForceQueryable.untrackedStorage(),
+ "forceQueryable", " ", expandPackages);
pw.println(" queries via package name:");
dumpQueriesMap(pw, filteringAppId, mQueriesViaPackage, " ", expandPackages);
pw.println(" queries via component:");
@@ -1715,11 +1800,12 @@ public class AppsFilter implements Watchable, Snappable {
mRetainedImplicitlyQueryable, " ", expandPackages);
}
pw.println(" queryable via uses-library:");
- dumpQueriesMap(pw, filteringAppId, mQueryableViaUsesLibrary, " ", expandPackages);
+ dumpQueriesMap(pw, filteringAppId, mQueryableViaUsesLibrary, " ",
+ expandPackages);
}
private static void dumpQueriesMap(PrintWriter pw, @Nullable Integer filteringId,
- SparseSetArray<Integer> queriesMap, String spacing,
+ WatchedSparseSetArray<Integer> queriesMap, String spacing,
@Nullable ToString<Integer> toString) {
for (int i = 0; i < queriesMap.size(); i++) {
Integer callingId = queriesMap.keyAt(i);
@@ -1748,7 +1834,7 @@ public class AppsFilter implements Watchable, Snappable {
}
private static <T> void dumpPackageSet(PrintWriter pw, @Nullable T filteringId,
- Set<T> targetPkgSet, String subTitle, String spacing,
+ ArraySet<T> targetPkgSet, String subTitle, String spacing,
@Nullable ToString<T> toString) {
if (targetPkgSet != null && targetPkgSet.size() > 0
&& (filteringId == null || targetPkgSet.contains(filteringId))) {
diff --git a/services/core/java/com/android/server/pm/AppsFilterSnapshot.java b/services/core/java/com/android/server/pm/AppsFilterSnapshot.java
new file mode 100644
index 000000000000..cb8c649ded00
--- /dev/null
+++ b/services/core/java/com/android/server/pm/AppsFilterSnapshot.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Process;
+import android.util.ArrayMap;
+import android.util.SparseArray;
+
+import com.android.internal.util.function.QuadFunction;
+import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.pkg.PackageStateInternal;
+
+import java.io.PrintWriter;
+
+/**
+ * Read-only interface used by computer and snapshots to query the visibility of packages
+ */
+public interface AppsFilterSnapshot {
+ /**
+ * 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
+ * all applications.
+ *
+ * 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 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 allow list should be
+ * applied.
+ */
+ SparseArray<int[]> getVisibilityAllowList(PackageStateInternal setting, int[] users,
+ ArrayMap<String, ? extends PackageStateInternal> existingSettings);
+
+ /**
+ * Returns true if the calling package should not be able to see the target package, false if no
+ * filtering should be done.
+ *
+ * @param callingUid the uid of the caller attempting to access a package
+ * @param callingSetting the setting attempting to access a package or null if it could not be
+ * found
+ * @param targetPkgSetting the package being accessed
+ * @param userId the user in which this access is being attempted
+ */
+ boolean shouldFilterApplication(int callingUid, @Nullable Object callingSetting,
+ PackageStateInternal targetPkgSetting, int userId);
+
+ /**
+ * Returns whether the querying package is allowed to see the target package.
+ *
+ * @param querying the querying package
+ * @param potentialTarget the package name of the target package
+ */
+ boolean canQueryPackage(@NonNull AndroidPackage querying, String potentialTarget);
+
+ /**
+ * Dump the packages that are queryable by the querying package.
+ *
+ * @param pw the output print writer
+ * @param filteringAppId the querying package's app ID
+ * @param dumpState the state of the dumping
+ * @param users the users for which the packages are installed
+ * @param getPackagesForUid the function that produces the package names for given uids
+ */
+ void dumpQueries(PrintWriter pw, @Nullable Integer filteringAppId, DumpState dumpState,
+ int[] users,
+ QuadFunction<Integer, Integer, Integer, Boolean, String[]> getPackagesForUid);
+
+}
diff --git a/services/core/java/com/android/server/pm/ComputerEngine.java b/services/core/java/com/android/server/pm/ComputerEngine.java
index df7c3ec6f260..80d61b593fd2 100644
--- a/services/core/java/com/android/server/pm/ComputerEngine.java
+++ b/services/core/java/com/android/server/pm/ComputerEngine.java
@@ -385,7 +385,7 @@ public class ComputerEngine implements Computer {
private final ResolveInfo mInstantAppInstallerInfo;
private final InstantAppRegistry mInstantAppRegistry;
private final ApplicationInfo mLocalAndroidApplication;
- private final AppsFilter mAppsFilter;
+ private final AppsFilterSnapshot mAppsFilter;
private final WatchedArrayMap<String, Integer> mFrozenPackages;
// Immutable service attribute
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index bf80a466e034..4f152d6c0819 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -720,7 +720,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService
}
@Watched
- final AppsFilter mAppsFilter;
+ final AppsFilterImpl mAppsFilter;
final PackageParser2.Callback mPackageParserCallback;
@@ -979,7 +979,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService
public final InstantAppRegistry instantAppRegistry;
public final ApplicationInfo androidApplication;
public final String appPredictionServicePackage;
- public final AppsFilter appsFilter;
+ public final AppsFilterSnapshot appsFilter;
public final ComponentResolverApi componentResolver;
public final PackageManagerService service;
public final WatchedArrayMap<String, Integer> frozenPackages;
@@ -1431,7 +1431,8 @@ public class PackageManagerService implements PackageSender, TestUtilityService
RuntimePermissionsPersistence.createInstance(),
i.getPermissionManagerServiceInternal(),
domainVerificationService, lock),
- (i, pm) -> AppsFilter.create(i, i.getLocalService(PackageManagerInternal.class)),
+ (i, pm) -> AppsFilterImpl.create(i,
+ i.getLocalService(PackageManagerInternal.class)),
(i, pm) -> (PlatformCompat) ServiceManager.getService("platform_compat"),
(i, pm) -> SystemConfig.getInstance(),
(i, pm) -> new PackageDexOptimizer(i.getInstaller(), i.getInstallLock(),
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceInjector.java b/services/core/java/com/android/server/pm/PackageManagerServiceInjector.java
index a02237fa90ce..396994b04514 100644
--- a/services/core/java/com/android/server/pm/PackageManagerServiceInjector.java
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceInjector.java
@@ -99,7 +99,7 @@ public class PackageManagerServiceInjector {
private final Singleton<UserManagerService>
mUserManagerProducer;
private final Singleton<Settings> mSettingsProducer;
- private final Singleton<AppsFilter> mAppsFilterProducer;
+ private final Singleton<AppsFilterImpl> mAppsFilterProducer;
private final Singleton<PlatformCompat>
mPlatformCompatProducer;
private final Singleton<SystemConfig> mSystemConfigProducer;
@@ -148,7 +148,7 @@ public class PackageManagerServiceInjector {
Producer<PermissionManagerServiceInternal> permissionManagerServiceProducer,
Producer<UserManagerService> userManagerProducer,
Producer<Settings> settingsProducer,
- Producer<AppsFilter> appsFilterProducer,
+ Producer<AppsFilterImpl> appsFilterProducer,
Producer<PlatformCompat> platformCompatProducer,
Producer<SystemConfig> systemConfigProducer,
Producer<PackageDexOptimizer> packageDexOptimizerProducer,
@@ -282,7 +282,7 @@ public class PackageManagerServiceInjector {
return mSettingsProducer.get(this, mPackageManager);
}
- public AppsFilter getAppsFilter() {
+ public AppsFilterImpl getAppsFilter() {
return mAppsFilterProducer.get(this, mPackageManager);
}
diff --git a/services/core/java/com/android/server/utils/WatchedArrayList.java b/services/core/java/com/android/server/utils/WatchedArrayList.java
index bb0ba1329d86..6059f9675e34 100644
--- a/services/core/java/com/android/server/utils/WatchedArrayList.java
+++ b/services/core/java/com/android/server/utils/WatchedArrayList.java
@@ -273,6 +273,13 @@ public class WatchedArrayList<E> extends WatchableImpl
}
/**
+ * Return true if all the objects in the given collection are in this array list.
+ */
+ public boolean containsAll(Collection<?> c) {
+ return mStorage.containsAll(c);
+ }
+
+ /**
* Ensure capacity.
*/
public void ensureCapacity(int min) {
diff --git a/services/core/java/com/android/server/utils/WatchedSparseBooleanMatrix.java b/services/core/java/com/android/server/utils/WatchedSparseBooleanMatrix.java
index 25ae00004b3e..c43e7f9babe6 100644
--- a/services/core/java/com/android/server/utils/WatchedSparseBooleanMatrix.java
+++ b/services/core/java/com/android/server/utils/WatchedSparseBooleanMatrix.java
@@ -18,6 +18,7 @@ package com.android.server.utils;
import static com.android.internal.annotations.VisibleForTesting.Visibility.PRIVATE;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.Size;
@@ -168,12 +169,19 @@ public class WatchedSparseBooleanMatrix extends WatchableImpl implements Snappab
* A copy constructor that can be used for snapshotting.
*/
private WatchedSparseBooleanMatrix(WatchedSparseBooleanMatrix r) {
- mOrder = r.mOrder;
- mSize = r.mSize;
- mKeys = r.mKeys.clone();
- mMap = r.mMap.clone();
- mInUse = r.mInUse.clone();
- mValues = r.mValues.clone();
+ copyFrom(r);
+ }
+
+ /**
+ * Copy from src to this.
+ */
+ public void copyFrom(@NonNull WatchedSparseBooleanMatrix src) {
+ mOrder = src.mOrder;
+ mSize = src.mSize;
+ mKeys = src.mKeys.clone();
+ mMap = src.mMap.clone();
+ mInUse = src.mInUse.clone();
+ mValues = src.mValues.clone();
}
/**
diff --git a/services/core/java/com/android/server/utils/WatchedSparseSetArray.java b/services/core/java/com/android/server/utils/WatchedSparseSetArray.java
new file mode 100644
index 000000000000..05db12e49a13
--- /dev/null
+++ b/services/core/java/com/android/server/utils/WatchedSparseSetArray.java
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.utils;
+
+import android.annotation.NonNull;
+import android.util.ArraySet;
+import android.util.SparseSetArray;
+
+
+/**
+ * A watched variant of SparseSetArray. Changes to the array are notified to
+ * registered {@link Watcher}s.
+ * @param <T> The element type, stored in the SparseSetArray.
+ */
+public class WatchedSparseSetArray<T> extends WatchableImpl implements Snappable {
+ // The storage
+ private final SparseSetArray mStorage;
+
+ // A private convenience function
+ private void onChanged() {
+ dispatchChange(this);
+ }
+
+ public WatchedSparseSetArray() {
+ mStorage = new SparseSetArray();
+ }
+
+ /**
+ * Creates a new WatchedSparseSetArray from an existing WatchedSparseSetArray and copy its data
+ */
+ public WatchedSparseSetArray(@NonNull WatchedSparseSetArray<T> watchedSparseSetArray) {
+ mStorage = new SparseSetArray(watchedSparseSetArray.untrackedStorage());
+ }
+
+ /**
+ * Return the underlying storage. This breaks the wrapper but is necessary when
+ * passing the array to distant methods.
+ */
+ public SparseSetArray<T> untrackedStorage() {
+ return mStorage;
+ }
+
+ /**
+ * Add a value for key n.
+ * @return FALSE when the value already existed for the given key, TRUE otherwise.
+ */
+ public boolean add(int n, T value) {
+ final boolean res = mStorage.add(n, value);
+ onChanged();
+ return res;
+ }
+
+ /**
+ * Removes all mappings from this SparseSetArray.
+ */
+ public void clear() {
+ mStorage.clear();
+ onChanged();
+ }
+
+ /**
+ * @return whether the value exists for the key n.
+ */
+ public boolean contains(int n, T value) {
+ return mStorage.contains(n, value);
+ }
+
+ /**
+ * @return the set of items of key n
+ */
+ public ArraySet<T> get(int n) {
+ return mStorage.get(n);
+ }
+
+ /**
+ * Remove a value for key n.
+ * @return TRUE when the value existed for the given key and removed, FALSE otherwise.
+ */
+ public boolean remove(int n, T value) {
+ if (mStorage.remove(n, value)) {
+ onChanged();
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Remove all values for key n.
+ */
+ public void remove(int n) {
+ mStorage.remove(n);
+ onChanged();
+ }
+
+ /**
+ * Return the size of the SparseSetArray.
+ */
+ public int size() {
+ return mStorage.size();
+ }
+
+ /**
+ * Return the key stored at the given index.
+ */
+ public int keyAt(int index) {
+ return mStorage.keyAt(index);
+ }
+
+ /**
+ * Return the size of the array at the given index.
+ */
+ public int sizeAt(int index) {
+ return mStorage.sizeAt(index);
+ }
+
+ /**
+ * Return the value in the SetArray at the given key index and value index.
+ */
+ public T valueAt(int intIndex, int valueIndex) {
+ return (T) mStorage.valueAt(intIndex, valueIndex);
+ }
+
+ @NonNull
+ @Override
+ public Object snapshot() {
+ WatchedSparseSetArray l = new WatchedSparseSetArray(this);
+ l.seal();
+ return l;
+ }
+
+ /**
+ * Make <this> a snapshot of the argument. Note that <this> is immutable when the
+ * method returns. <this> must be empty when the function is called.
+ * @param r The source array, which is copied into <this>
+ */
+ public void snapshot(@NonNull WatchedSparseSetArray<T> r) {
+ snapshot(this, r);
+ }
+
+ /**
+ * Make the destination a copy of the source. If the element is a subclass of Snapper then the
+ * copy contains snapshots of the elements. Otherwise the copy contains references to the
+ * elements. The destination must be initially empty. Upon return, the destination is
+ * immutable.
+ * @param dst The destination array. It must be empty.
+ * @param src The source array. It is not modified.
+ */
+ public static void snapshot(@NonNull WatchedSparseSetArray dst,
+ @NonNull WatchedSparseSetArray src) {
+ if (dst.size() != 0) {
+ throw new IllegalArgumentException("snapshot destination is not empty");
+ }
+ final int arraySize = src.size();
+ for (int i = 0; i < arraySize; i++) {
+ final ArraySet set = src.get(i);
+ final int setSize = set.size();
+ for (int j = 0; j < setSize; j++) {
+ dst.add(src.keyAt(i), set.valueAt(j));
+ }
+ }
+ dst.seal();
+ }
+}
diff --git a/services/tests/PackageManagerComponentOverrideTests/src/com/android/server/pm/test/override/PackageManagerComponentLabelIconOverrideTest.kt b/services/tests/PackageManagerComponentOverrideTests/src/com/android/server/pm/test/override/PackageManagerComponentLabelIconOverrideTest.kt
index 7017440a86bb..7b152247eb9c 100644
--- a/services/tests/PackageManagerComponentOverrideTests/src/com/android/server/pm/test/override/PackageManagerComponentLabelIconOverrideTest.kt
+++ b/services/tests/PackageManagerComponentOverrideTests/src/com/android/server/pm/test/override/PackageManagerComponentLabelIconOverrideTest.kt
@@ -34,7 +34,6 @@ import com.android.server.pm.test.override.PackageManagerComponentLabelIconOverr
import com.android.server.testutils.TestHandler
import com.android.server.testutils.mock
import com.android.server.testutils.mockThrowOnUnmocked
-import com.android.server.testutils.spy
import com.android.server.testutils.whenever
import com.android.server.wm.ActivityTaskManagerInternal
import com.google.common.truth.Truth.assertThat
@@ -46,13 +45,9 @@ import org.junit.runner.RunWith
import org.junit.runners.Parameterized
import org.mockito.Mockito.any
import org.mockito.Mockito.anyInt
-import org.mockito.Mockito.clearInvocations
-import org.mockito.Mockito.doAnswer
import org.mockito.Mockito.doReturn
import org.mockito.Mockito.intThat
-import org.mockito.Mockito.never
import org.mockito.Mockito.same
-import org.mockito.Mockito.verify
import org.testng.Assert.assertThrows
import java.io.File
import java.util.UUID
@@ -365,7 +360,7 @@ class PackageManagerComponentLabelIconOverrideTest {
val mockActivityTaskManager: ActivityTaskManagerInternal = mockThrowOnUnmocked {
whenever(this.isCallerRecents(anyInt())) { false }
}
- val mockAppsFilter: AppsFilter = mockThrowOnUnmocked {
+ val mockAppsFilter: AppsFilterImpl = mockThrowOnUnmocked {
whenever(this.shouldFilterApplication(anyInt(), any<PackageSetting>(),
any<PackageSetting>(), anyInt())) { false }
whenever(this.snapshot()) { this@mockThrowOnUnmocked }
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt b/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt
index 0567f58b1bbe..353c8e22cceb 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt
@@ -194,7 +194,7 @@ class MockSystem(withSession: (StaticMockitoSessionBuilder) -> Unit = {}) {
val packageParser: PackageParser2 = mock()
val keySetManagerService: KeySetManagerService = mock()
val packageAbiHelper: PackageAbiHelper = mock()
- val appsFilter: AppsFilter = mock {
+ val appsFilter: AppsFilterImpl = mock {
whenever(snapshot()) { this@mock }
}
val dexManager: DexManager = mock()
diff --git a/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java b/services/tests/servicestests/src/com/android/server/pm/AppsFilterImplTest.java
index b72b8d2ec6e8..d8f4349b95bf 100644
--- a/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/AppsFilterImplTest.java
@@ -77,7 +77,7 @@ import java.util.concurrent.Executor;
@Presubmit
@RunWith(JUnit4.class)
-public class AppsFilterTest {
+public class AppsFilterImplTest {
private static final int DUMMY_CALLING_APPID = 10345;
private static final int DUMMY_TARGET_APPID = 10556;
@@ -98,9 +98,9 @@ public class AppsFilterTest {
}
@Mock
- AppsFilter.FeatureConfig mFeatureConfigMock;
+ AppsFilterImpl.FeatureConfig mFeatureConfigMock;
@Mock
- AppsFilter.StateProvider mStateProvider;
+ AppsFilterImpl.StateProvider mStateProvider;
@Mock
Executor mMockExecutor;
@Mock
@@ -204,11 +204,11 @@ public class AppsFilterTest {
MockitoAnnotations.initMocks(this);
doAnswer(invocation -> {
- ((AppsFilter.StateProvider.CurrentStateCallback) invocation.getArgument(0))
+ ((AppsFilterImpl.StateProvider.CurrentStateCallback) invocation.getArgument(0))
.currentState(mExisting, USER_INFO_LIST);
return new Object();
}).when(mStateProvider)
- .runWithState(any(AppsFilter.StateProvider.CurrentStateCallback.class));
+ .runWithState(any(AppsFilterImpl.StateProvider.CurrentStateCallback.class));
doAnswer(invocation -> {
((Runnable) invocation.getArgument(0)).run();
@@ -218,14 +218,14 @@ public class AppsFilterTest {
when(mFeatureConfigMock.isGloballyEnabled()).thenReturn(true);
when(mFeatureConfigMock.packageIsEnabled(any(AndroidPackage.class))).thenAnswer(
(Answer<Boolean>) invocation ->
- ((AndroidPackage)invocation.getArgument(SYSTEM_USER)).getTargetSdkVersion()
+ ((AndroidPackage) invocation.getArgument(SYSTEM_USER)).getTargetSdkVersion()
>= Build.VERSION_CODES.R);
}
@Test
public void testSystemReadyPropogates() throws Exception {
- final AppsFilter appsFilter =
- new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
+ final AppsFilterImpl appsFilter =
+ new AppsFilterImpl(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
mMockExecutor, mMockPmInternal);
final WatchableTester watcher = new WatchableTester(appsFilter, "onChange");
watcher.register();
@@ -236,8 +236,8 @@ public class AppsFilterTest {
@Test
public void testQueriesAction_FilterMatches() throws Exception {
- final AppsFilter appsFilter =
- new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
+ final AppsFilterImpl appsFilter =
+ new AppsFilterImpl(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
mMockExecutor, mMockPmInternal);
final WatchableTester watcher = new WatchableTester(appsFilter, "onChange");
watcher.register();
@@ -259,8 +259,8 @@ public class AppsFilterTest {
}
@Test
public void testQueriesProtectedAction_FilterDoesNotMatch() throws Exception {
- final AppsFilter appsFilter =
- new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
+ final AppsFilterImpl appsFilter =
+ new AppsFilterImpl(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
mMockExecutor, mMockPmInternal);
final WatchableTester watcher = new WatchableTester(appsFilter, "onChange");
watcher.register();
@@ -308,8 +308,8 @@ public class AppsFilterTest {
@Test
public void testQueriesProvider_FilterMatches() throws Exception {
- final AppsFilter appsFilter =
- new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
+ final AppsFilterImpl appsFilter =
+ new AppsFilterImpl(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
mMockExecutor, mMockPmInternal);
final WatchableTester watcher = new WatchableTester(appsFilter, "onChange");
watcher.register();
@@ -333,8 +333,8 @@ public class AppsFilterTest {
@Test
public void testOnUserUpdated_FilterMatches() throws Exception {
- final AppsFilter appsFilter =
- new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
+ final AppsFilterImpl appsFilter =
+ new AppsFilterImpl(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
mMockExecutor, mMockPmInternal);
simulateAddBasicAndroid(appsFilter);
@@ -356,11 +356,11 @@ public class AppsFilterTest {
// adds new user
doAnswer(invocation -> {
- ((AppsFilter.StateProvider.CurrentStateCallback) invocation.getArgument(0))
+ ((AppsFilterImpl.StateProvider.CurrentStateCallback) invocation.getArgument(0))
.currentState(mExisting, USER_INFO_LIST_WITH_ADDED);
return new Object();
}).when(mStateProvider)
- .runWithState(any(AppsFilter.StateProvider.CurrentStateCallback.class));
+ .runWithState(any(AppsFilterImpl.StateProvider.CurrentStateCallback.class));
appsFilter.onUserCreated(ADDED_USER);
for (int subjectUserId : USER_ARRAY_WITH_ADDED) {
@@ -373,11 +373,11 @@ public class AppsFilterTest {
// delete user
doAnswer(invocation -> {
- ((AppsFilter.StateProvider.CurrentStateCallback) invocation.getArgument(0))
+ ((AppsFilterImpl.StateProvider.CurrentStateCallback) invocation.getArgument(0))
.currentState(mExisting, USER_INFO_LIST);
return new Object();
}).when(mStateProvider)
- .runWithState(any(AppsFilter.StateProvider.CurrentStateCallback.class));
+ .runWithState(any(AppsFilterImpl.StateProvider.CurrentStateCallback.class));
appsFilter.onUserDeleted(ADDED_USER);
for (int subjectUserId : USER_ARRAY) {
@@ -391,8 +391,8 @@ public class AppsFilterTest {
@Test
public void testQueriesDifferentProvider_Filters() throws Exception {
- final AppsFilter appsFilter =
- new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
+ final AppsFilterImpl appsFilter =
+ new AppsFilterImpl(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
mMockExecutor, mMockPmInternal);
final WatchableTester watcher = new WatchableTester(appsFilter, "onChange");
watcher.register();
@@ -416,8 +416,8 @@ public class AppsFilterTest {
@Test
public void testQueriesProviderWithSemiColon_FilterMatches() throws Exception {
- final AppsFilter appsFilter =
- new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
+ final AppsFilterImpl appsFilter =
+ new AppsFilterImpl(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
mMockExecutor, mMockPmInternal);
simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
@@ -435,8 +435,8 @@ public class AppsFilterTest {
@Test
public void testQueriesAction_NoMatchingAction_Filters() throws Exception {
- final AppsFilter appsFilter =
- new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
+ final AppsFilterImpl appsFilter =
+ new AppsFilterImpl(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
mMockExecutor, mMockPmInternal);
simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
@@ -452,8 +452,8 @@ public class AppsFilterTest {
@Test
public void testQueriesAction_NoMatchingActionFilterLowSdk_DoesntFilter() throws Exception {
- final AppsFilter appsFilter =
- new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
+ final AppsFilterImpl appsFilter =
+ new AppsFilterImpl(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
mMockExecutor, mMockPmInternal);
simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
@@ -473,8 +473,8 @@ public class AppsFilterTest {
@Test
public void testNoQueries_Filters() throws Exception {
- final AppsFilter appsFilter =
- new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
+ final AppsFilterImpl appsFilter =
+ new AppsFilterImpl(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
mMockExecutor, mMockPmInternal);
simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
@@ -490,7 +490,7 @@ public class AppsFilterTest {
@Test
public void testNoUsesLibrary_Filters() throws Exception {
- final AppsFilter appsFilter = new AppsFilter(mStateProvider, mFeatureConfigMock,
+ final AppsFilterImpl appsFilter = new AppsFilterImpl(mStateProvider, mFeatureConfigMock,
new String[]{}, /* systemAppsQueryable */ false, /* overlayProvider */ null,
mMockExecutor, mMockPmInternal);
@@ -516,7 +516,7 @@ public class AppsFilterTest {
@Test
public void testUsesLibrary_DoesntFilter() throws Exception {
- final AppsFilter appsFilter = new AppsFilter(mStateProvider, mFeatureConfigMock,
+ final AppsFilterImpl appsFilter = new AppsFilterImpl(mStateProvider, mFeatureConfigMock,
new String[]{}, /* systemAppsQueryable */ false, /* overlayProvider */ null,
mMockExecutor, mMockPmInternal);
@@ -543,7 +543,7 @@ public class AppsFilterTest {
@Test
public void testUsesOptionalLibrary_DoesntFilter() throws Exception {
- final AppsFilter appsFilter = new AppsFilter(mStateProvider, mFeatureConfigMock,
+ final AppsFilterImpl appsFilter = new AppsFilterImpl(mStateProvider, mFeatureConfigMock,
new String[]{}, /* systemAppsQueryable */ false, /* overlayProvider */ null,
mMockExecutor, mMockPmInternal);
@@ -570,7 +570,7 @@ public class AppsFilterTest {
@Test
public void testUsesLibrary_ShareUid_DoesntFilter() throws Exception {
- final AppsFilter appsFilter = new AppsFilter(mStateProvider, mFeatureConfigMock,
+ final AppsFilterImpl appsFilter = new AppsFilterImpl(mStateProvider, mFeatureConfigMock,
new String[]{}, /* systemAppsQueryable */ false, /* overlayProvider */ null,
mMockExecutor, mMockPmInternal);
@@ -602,8 +602,8 @@ public class AppsFilterTest {
@Test
public void testForceQueryable_SystemDoesntFilter() throws Exception {
- final AppsFilter appsFilter =
- new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
+ final AppsFilterImpl appsFilter =
+ new AppsFilterImpl(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
mMockExecutor, mMockPmInternal);
simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
@@ -621,8 +621,8 @@ public class AppsFilterTest {
@Test
public void testForceQueryable_NonSystemFilters() throws Exception {
- final AppsFilter appsFilter =
- new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
+ final AppsFilterImpl appsFilter =
+ new AppsFilterImpl(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
mMockExecutor, mMockPmInternal);
simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
@@ -638,9 +638,10 @@ public class AppsFilterTest {
@Test
public void testForceQueryableByDevice_SystemCaller_DoesntFilter() throws Exception {
- final AppsFilter appsFilter =
- new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{"com.some.package"},
- false, null, mMockExecutor, mMockPmInternal);
+ final AppsFilterImpl appsFilter =
+ new AppsFilterImpl(mStateProvider, mFeatureConfigMock,
+ new String[]{"com.some.package"}, false, null,
+ mMockExecutor, mMockPmInternal);
simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
@@ -657,8 +658,8 @@ public class AppsFilterTest {
@Test
public void testSystemSignedTarget_DoesntFilter() throws CertificateException {
- final AppsFilter appsFilter =
- new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
+ final AppsFilterImpl appsFilter =
+ new AppsFilterImpl(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
mMockExecutor, mMockPmInternal);
appsFilter.onSystemReady();
@@ -686,9 +687,10 @@ public class AppsFilterTest {
@Test
public void testForceQueryableByDevice_NonSystemCaller_Filters() throws Exception {
- final AppsFilter appsFilter =
- new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{"com.some.package"},
- false, null, mMockExecutor, mMockPmInternal);
+ final AppsFilterImpl appsFilter =
+ new AppsFilterImpl(mStateProvider, mFeatureConfigMock,
+ new String[]{"com.some.package"}, false, null,
+ mMockExecutor, mMockPmInternal);
simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
@@ -704,8 +706,8 @@ public class AppsFilterTest {
@Test
public void testSystemQueryable_DoesntFilter() throws Exception {
- final AppsFilter appsFilter =
- new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{},
+ final AppsFilterImpl appsFilter =
+ new AppsFilterImpl(mStateProvider, mFeatureConfigMock, new String[]{},
true /* system force queryable */, null, mMockExecutor,
mMockPmInternal);
simulateAddBasicAndroid(appsFilter);
@@ -723,8 +725,8 @@ public class AppsFilterTest {
@Test
public void testQueriesPackage_DoesntFilter() throws Exception {
- final AppsFilter appsFilter =
- new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
+ final AppsFilterImpl appsFilter =
+ new AppsFilterImpl(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
mMockExecutor, mMockPmInternal);
simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
@@ -742,8 +744,8 @@ public class AppsFilterTest {
public void testNoQueries_FeatureOff_DoesntFilter() throws Exception {
when(mFeatureConfigMock.packageIsEnabled(any(AndroidPackage.class)))
.thenReturn(false);
- final AppsFilter appsFilter =
- new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
+ final AppsFilterImpl appsFilter =
+ new AppsFilterImpl(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
mMockExecutor, mMockPmInternal);
simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
@@ -759,8 +761,8 @@ public class AppsFilterTest {
@Test
public void testSystemUid_DoesntFilter() throws Exception {
- final AppsFilter appsFilter =
- new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
+ final AppsFilterImpl appsFilter =
+ new AppsFilterImpl(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
mMockExecutor, mMockPmInternal);
simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
@@ -775,8 +777,8 @@ public class AppsFilterTest {
@Test
public void testSystemUidSecondaryUser_DoesntFilter() throws Exception {
- final AppsFilter appsFilter =
- new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
+ final AppsFilterImpl appsFilter =
+ new AppsFilterImpl(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
mMockExecutor, mMockPmInternal);
simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
@@ -792,8 +794,8 @@ public class AppsFilterTest {
@Test
public void testNonSystemUid_NoCallingSetting_Filters() throws Exception {
- final AppsFilter appsFilter =
- new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
+ final AppsFilterImpl appsFilter =
+ new AppsFilterImpl(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
mMockExecutor, mMockPmInternal);
simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
@@ -807,8 +809,8 @@ public class AppsFilterTest {
@Test
public void testNoTargetPackage_filters() throws Exception {
- final AppsFilter appsFilter =
- new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
+ final AppsFilterImpl appsFilter =
+ new AppsFilterImpl(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
mMockExecutor, mMockPmInternal);
simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
@@ -838,7 +840,7 @@ public class AppsFilterTest {
.setOverlayTargetOverlayableName("overlayableName");
ParsingPackage actor = pkg("com.some.package.actor");
- final AppsFilter appsFilter = new AppsFilter(
+ final AppsFilterImpl appsFilter = new AppsFilterImpl(
mStateProvider,
mFeatureConfigMock,
new String[]{},
@@ -933,7 +935,7 @@ public class AppsFilterTest {
when(mMockPmInternal.getSharedUserPackages(any(Integer.class))).thenReturn(
actorSharedSettingPackages
);
- final AppsFilter appsFilter = new AppsFilter(
+ final AppsFilterImpl appsFilter = new AppsFilterImpl(
mStateProvider,
mFeatureConfigMock,
new String[]{},
@@ -985,8 +987,8 @@ public class AppsFilterTest {
@Test
public void testInitiatingApp_DoesntFilter() throws Exception {
- final AppsFilter appsFilter =
- new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
+ final AppsFilterImpl appsFilter =
+ new AppsFilterImpl(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
mMockExecutor, mMockPmInternal);
simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
@@ -1003,8 +1005,8 @@ public class AppsFilterTest {
@Test
public void testUninstalledInitiatingApp_Filters() throws Exception {
- final AppsFilter appsFilter =
- new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
+ final AppsFilterImpl appsFilter =
+ new AppsFilterImpl(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
mMockExecutor, mMockPmInternal);
simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
@@ -1021,8 +1023,8 @@ public class AppsFilterTest {
@Test
public void testOriginatingApp_Filters() throws Exception {
- final AppsFilter appsFilter =
- new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
+ final AppsFilterImpl appsFilter =
+ new AppsFilterImpl(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
mMockExecutor, mMockPmInternal);
final WatchableTester watcher = new WatchableTester(appsFilter, "onChange");
watcher.register();
@@ -1046,8 +1048,8 @@ public class AppsFilterTest {
@Test
public void testInstallingApp_DoesntFilter() throws Exception {
- final AppsFilter appsFilter =
- new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
+ final AppsFilterImpl appsFilter =
+ new AppsFilterImpl(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
mMockExecutor, mMockPmInternal);
final WatchableTester watcher = new WatchableTester(appsFilter, "onChange");
watcher.register();
@@ -1071,8 +1073,8 @@ public class AppsFilterTest {
@Test
public void testInstrumentation_DoesntFilter() throws Exception {
- final AppsFilter appsFilter =
- new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
+ final AppsFilterImpl appsFilter =
+ new AppsFilterImpl(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
mMockExecutor, mMockPmInternal);
final WatchableTester watcher = new WatchableTester(appsFilter, "onChange");
watcher.register();
@@ -1100,8 +1102,8 @@ public class AppsFilterTest {
@Test
public void testWhoCanSee() throws Exception {
- final AppsFilter appsFilter =
- new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
+ final AppsFilterImpl appsFilter =
+ new AppsFilterImpl(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
mMockExecutor, mMockPmInternal);
final WatchableTester watcher = new WatchableTester(appsFilter, "onChange");
watcher.register();
@@ -1173,8 +1175,8 @@ public class AppsFilterTest {
@Test
public void testOnChangeReport() throws Exception {
- final AppsFilter appsFilter =
- new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
+ final AppsFilterImpl appsFilter =
+ new AppsFilterImpl(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
mMockExecutor, mMockPmInternal);
final WatchableTester watcher = new WatchableTester(appsFilter, "onChange");
watcher.register();
@@ -1246,8 +1248,8 @@ public class AppsFilterTest {
@Test
public void testOnChangeReportedFilter() throws Exception {
- final AppsFilter appsFilter =
- new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
+ final AppsFilterImpl appsFilter =
+ new AppsFilterImpl(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
mMockExecutor, mMockPmInternal);
simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
@@ -1270,6 +1272,53 @@ public class AppsFilterTest {
watcher.verifyNoChangeReported("shouldFilterApplication");
}
+ @Test
+ public void testAppsFilterRead() throws Exception {
+ final AppsFilterImpl appsFilter =
+ new AppsFilterImpl(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
+ mMockExecutor, mMockPmInternal);
+ simulateAddBasicAndroid(appsFilter);
+ appsFilter.onSystemReady();
+
+ PackageSetting target = simulateAddPackage(appsFilter, pkg("com.some.package"),
+ DUMMY_TARGET_APPID);
+ PackageSetting instrumentation = simulateAddPackage(appsFilter,
+ pkgWithInstrumentation("com.some.other.package", "com.some.package"),
+ DUMMY_CALLING_APPID);
+
+ final int hasProviderAppId = Process.FIRST_APPLICATION_UID + 1;
+ final int queriesProviderAppId = Process.FIRST_APPLICATION_UID + 2;
+ PackageSetting queriesProvider = simulateAddPackage(appsFilter,
+ pkgQueriesProvider("com.yet.some.other.package", "com.some.authority"),
+ queriesProviderAppId);
+ appsFilter.grantImplicitAccess(
+ hasProviderAppId, queriesProviderAppId, false /* retainOnUpdate */);
+
+ AppsFilterSnapshot snapshot = appsFilter.snapshot();
+ assertFalse(
+ snapshot.shouldFilterApplication(DUMMY_CALLING_APPID, instrumentation, target,
+ SYSTEM_USER));
+ assertFalse(
+ snapshot.shouldFilterApplication(DUMMY_TARGET_APPID, target, instrumentation,
+ SYSTEM_USER));
+
+ SparseArray<int[]> queriesProviderFilter =
+ snapshot.getVisibilityAllowList(queriesProvider, USER_ARRAY, mExisting);
+ assertThat(toList(queriesProviderFilter.get(SYSTEM_USER)), contains(queriesProviderAppId));
+ assertTrue(snapshot.canQueryPackage(instrumentation.getPkg(),
+ target.getPackageName()));
+
+ // New changes don't affect the snapshot
+ appsFilter.removePackage(target, false);
+ assertTrue(
+ appsFilter.shouldFilterApplication(DUMMY_CALLING_APPID, instrumentation, target,
+ SYSTEM_USER));
+ assertFalse(
+ snapshot.shouldFilterApplication(DUMMY_CALLING_APPID, instrumentation, target,
+ SYSTEM_USER));
+
+ }
+
private List<Integer> toList(int[] array) {
ArrayList<Integer> ret = new ArrayList<>(array.length);
for (int i = 0; i < array.length; i++) {
@@ -1282,7 +1331,7 @@ public class AppsFilterTest {
PackageSettingBuilder withBuilder(PackageSettingBuilder builder);
}
- private void simulateAddBasicAndroid(AppsFilter appsFilter) throws Exception {
+ private void simulateAddBasicAndroid(AppsFilterImpl appsFilter) throws Exception {
final Signature frameworkSignature = Mockito.mock(Signature.class);
final SigningDetails frameworkSigningDetails =
new SigningDetails(new Signature[]{frameworkSignature}, 1);
@@ -1291,17 +1340,17 @@ public class AppsFilterTest {
b -> b.setSigningDetails(frameworkSigningDetails));
}
- private PackageSetting simulateAddPackage(AppsFilter filter,
+ private PackageSetting simulateAddPackage(AppsFilterImpl filter,
ParsingPackage newPkgBuilder, int appId) {
return simulateAddPackage(filter, newPkgBuilder, appId, null /*settingBuilder*/);
}
- private PackageSetting simulateAddPackage(AppsFilter filter,
+ private PackageSetting simulateAddPackage(AppsFilterImpl filter,
ParsingPackage newPkgBuilder, int appId, @Nullable WithSettingBuilder action) {
return simulateAddPackage(filter, newPkgBuilder, appId, action, null /*sharedUserSetting*/);
}
- private PackageSetting simulateAddPackage(AppsFilter filter,
+ private PackageSetting simulateAddPackage(AppsFilterImpl filter,
ParsingPackage newPkgBuilder, int appId, @Nullable WithSettingBuilder action,
@Nullable SharedUserSetting sharedUserSetting) {
final PackageSetting setting =
@@ -1324,7 +1373,7 @@ public class AppsFilterTest {
return setting;
}
- private void simulateAddPackage(PackageSetting setting, AppsFilter filter,
+ private void simulateAddPackage(PackageSetting setting, AppsFilterImpl filter,
@Nullable SharedUserSetting sharedUserSetting) {
mExisting.put(setting.getPackageName(), setting);
if (sharedUserSetting != null) {
diff --git a/services/tests/servicestests/src/com/android/server/utils/WatcherTest.java b/services/tests/servicestests/src/com/android/server/utils/WatcherTest.java
index 4ed4c236535f..37c95f735d89 100644
--- a/services/tests/servicestests/src/com/android/server/utils/WatcherTest.java
+++ b/services/tests/servicestests/src/com/android/server/utils/WatcherTest.java
@@ -17,6 +17,7 @@
package com.android.server.utils;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@@ -860,6 +861,54 @@ public class WatcherTest {
}
}
+ @Test
+ public void testWatchedSparseSetArray() {
+ final String name = "WatchedSparseSetArray";
+ WatchableTester tester;
+
+ // Test WatchedSparseSetArray
+ WatchedSparseSetArray array = new WatchedSparseSetArray();
+ tester = new WatchableTester(array, name);
+ tester.verify(0, "Initial array - no registration");
+ array.add(INDEX_A, 1);
+ tester.verify(0, "Updates with no registration");
+ tester.register();
+ tester.verify(0, "Updates with no registration");
+ array.add(INDEX_B, 2);
+ tester.verify(1, "Updates with registration");
+ array.add(INDEX_B, 4);
+ array.add(INDEX_C, 5);
+ tester.verify(3, "Updates with registration");
+ // Special methods
+ assertTrue(array.remove(INDEX_C, 5));
+ tester.verify(4, "Removed 5 from key 3");
+ array.remove(INDEX_B);
+ tester.verify(5, "Removed everything for key 2");
+
+ // Snapshot
+ {
+ WatchedSparseSetArray arraySnap = (WatchedSparseSetArray) array.snapshot();
+ tester.verify(5, "Generate snapshot");
+ // Verify that the snapshot is a proper copy of the source.
+ assertEquals("WatchedSparseSetArray snap same size",
+ array.size(), arraySnap.size());
+ for (int i = 0; i < array.size(); i++) {
+ ArraySet set = array.get(array.keyAt(i));
+ ArraySet setSnap = arraySnap.get(arraySnap.keyAt(i));
+ assertNotNull(set);
+ assertTrue(set.equals(setSnap));
+ }
+ array.add(INDEX_D, 9);
+ tester.verify(6, "Tick after snapshot");
+ // Verify that the array is sealed
+ verifySealed(name, ()->arraySnap.add(INDEX_D, 10));
+ assertTrue(!array.isSealed());
+ assertTrue(arraySnap.isSealed());
+ }
+ array.clear();
+ tester.verify(7, "Cleared all entries");
+ }
+
private static class IndexGenerator {
private final int mSeed;
private final Random mRandom;
@@ -1084,6 +1133,18 @@ public class WatcherTest {
assertEquals(a.equals(s), true);
a.put(rowIndex, colIndex, !a.get(rowIndex, colIndex));
assertEquals(a.equals(s), false);
+
+ // Verify copy-in/out
+ {
+ final String msg = name + " copy";
+ WatchedSparseBooleanMatrix copy = new WatchedSparseBooleanMatrix();
+ copy.copyFrom(matrix);
+ final int end = copy.size();
+ assertTrue(msg + " size mismatch " + end + " " + matrix.size(), end == matrix.size());
+ for (int i = 0; i < end; i++) {
+ assertEquals(copy.keyAt(i), keys[i]);
+ }
+ }
}
@Test