Move to non-hidden APIs for handleUser and broadcast registration.
The implementation of handleIncomingUser is copied from
ag/13200660 (1d1547b).
Bug: 181787682
Test: Presubmit
Change-Id: I946199a8844e7fd6ea5574b873da56d8b8630f62
diff --git a/service/java/com/android/server/appsearch/AppSearchManagerService.java b/service/java/com/android/server/appsearch/AppSearchManagerService.java
index 0c07fa0..0709ff5 100644
--- a/service/java/com/android/server/appsearch/AppSearchManagerService.java
+++ b/service/java/com/android/server/appsearch/AppSearchManagerService.java
@@ -17,11 +17,10 @@
import static android.app.appsearch.AppSearchResult.throwableToFailedResult;
import static android.os.Process.INVALID_UID;
-import static android.os.UserHandle.USER_NULL;
+import android.Manifest;
import android.annotation.ElapsedRealtimeLong;
import android.annotation.NonNull;
-import android.app.ActivityManager;
import android.app.appsearch.AppSearchBatchResult;
import android.app.appsearch.AppSearchMigrationHelper;
import android.app.appsearch.AppSearchResult;
@@ -63,6 +62,7 @@
import com.android.server.appsearch.external.localstorage.stats.CallStats;
import com.android.server.appsearch.stats.LoggerInstanceManager;
import com.android.server.appsearch.stats.PlatformLogger;
+import com.android.server.appsearch.util.PackageUtil;
import com.android.server.usage.StorageStatsManagerLocal;
import com.android.server.usage.StorageStatsManagerLocal.StorageStatsAugmenter;
@@ -124,8 +124,10 @@
}
private void registerReceivers() {
- mContext.registerReceiverAsUser(new UserActionReceiver(), UserHandle.ALL,
- new IntentFilter(Intent.ACTION_USER_REMOVED), /*broadcastPermission=*/ null,
+ mContext.registerReceiverForAllUsers(
+ new UserActionReceiver(),
+ new IntentFilter(Intent.ACTION_USER_REMOVED),
+ /*broadcastPermission=*/ null,
/*scheduler=*/ null);
//TODO(b/145759910) Add a direct callback when user clears the data instead of relying on
@@ -135,8 +137,10 @@
packageChangedFilter.addAction(Intent.ACTION_PACKAGE_DATA_CLEARED);
packageChangedFilter.addDataScheme("package");
packageChangedFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
- mContext.registerReceiverAsUser(new PackageChangedReceiver(), UserHandle.ALL,
- packageChangedFilter, /*broadcastPermission=*/ null,
+ mContext.registerReceiverForAllUsers(
+ new PackageChangedReceiver(),
+ packageChangedFilter,
+ /*broadcastPermission=*/ null,
/*scheduler=*/ null);
}
@@ -148,12 +152,13 @@
switch (intent.getAction()) {
case Intent.ACTION_USER_REMOVED:
- int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, USER_NULL);
- if (userId == USER_NULL) {
- Log.e(TAG, "userId is missing in the intent: " + intent);
+ UserHandle userHandle = intent.getParcelableExtra(Intent.EXTRA_USER);
+ if (userHandle == null) {
+ Log.e(TAG, "Extra "
+ + Intent.EXTRA_USER + " is missing in the intent: " + intent);
return;
}
- handleUserRemoved(UserHandle.of(userId));
+ handleUserRemoved(userHandle);
break;
default:
Log.e(TAG, "Received unknown intent: " + intent);
@@ -1183,13 +1188,9 @@
Objects.requireNonNull(actualCallingUser);
Objects.requireNonNull(claimedCallingPackage);
- int claimedCallingUid;
- try {
- Context claimedCallingContext =
- mContext.createContextAsUser(actualCallingUser, /*flags=*/ 0);
- claimedCallingUid = claimedCallingContext.getPackageManager().getPackageUid(
- claimedCallingPackage, /*flags=*/ 0);
- } catch (PackageManager.NameNotFoundException e) {
+ int claimedCallingUid = PackageUtil.getPackageUidAsUser(
+ mContext, claimedCallingPackage, actualCallingUser);
+ if (claimedCallingUid == INVALID_UID) {
throw new SecurityException(
"Specified calling package [" + claimedCallingPackage + "] not found");
}
@@ -1257,23 +1258,44 @@
*
* <p>Takes care of checking permissions and converting USER_CURRENT to the actual current user.
*
+ * @param requestedUser The user which the caller is requesting to execute as.
+ * @param callingUid The actual uid of the caller as determined by Binder.
* @return the user handle that the call should run as. Will always be a concrete user.
*/
// TODO(b/173553485) verifying that the caller has permission to access target user's data
// TODO(b/173553485) Handle ACTION_USER_REMOVED broadcast
// TODO(b/173553485) Implement SystemService.onUserStopping()
@NonNull
- private static UserHandle handleIncomingUser(@NonNull UserHandle userHandle, int callingUid) {
+ private UserHandle handleIncomingUser(@NonNull UserHandle requestedUser, int callingUid) {
int callingPid = Binder.getCallingPid();
- int finalUserId = ActivityManager.handleIncomingUser(
+ UserHandle callingUser = UserHandle.getUserHandleForUid(callingUid);
+ if (callingUser.equals(requestedUser)) {
+ return requestedUser;
+ }
+ // Duplicates UserController#ensureNotSpecialUser
+ if (requestedUser.getIdentifier() < 0) {
+ throw new IllegalArgumentException(
+ "Call does not support special user " + requestedUser);
+ }
+ boolean canInteractAcrossUsers = mContext.checkPermission(
+ Manifest.permission.INTERACT_ACROSS_USERS,
callingPid,
- callingUid,
- userHandle.getIdentifier(),
- /*allowAll=*/ false,
- /*requireFull=*/ false,
- /*name=*/ null,
- /*callerPackage=*/ null);
- return UserHandle.of(finalUserId);
+ callingUid) == PackageManager.PERMISSION_GRANTED;
+ if (!canInteractAcrossUsers) {
+ canInteractAcrossUsers = mContext.checkPermission(
+ Manifest.permission.INTERACT_ACROSS_USERS_FULL,
+ callingPid,
+ callingUid) == PackageManager.PERMISSION_GRANTED;
+ }
+ if (canInteractAcrossUsers) {
+ return requestedUser;
+ }
+ throw new SecurityException(
+ "Permission denied while calling from uid " + callingUid
+ + " with " + requestedUser + "; Need to run as either the calling user ("
+ + callingUser + "), or with one of the following permissions: "
+ + Manifest.permission.INTERACT_ACROSS_USERS + " or "
+ + Manifest.permission.INTERACT_ACROSS_USERS_FULL);
}
// TODO(b/179160886): Cache the previous storage stats.
diff --git a/service/java/com/android/server/appsearch/ImplInstanceManager.java b/service/java/com/android/server/appsearch/ImplInstanceManager.java
index beb4d24..0775272 100644
--- a/service/java/com/android/server/appsearch/ImplInstanceManager.java
+++ b/service/java/com/android/server/appsearch/ImplInstanceManager.java
@@ -172,11 +172,6 @@
@Nullable AppSearchLogger logger)
throws AppSearchException {
File appSearchDir = getAppSearchDir(userHandle);
- // TODO(b/181787682): Swap AppSearchImpl and VisibilityStore to accept a UserHandle too
- return AppSearchImpl.create(
- appSearchDir,
- userContext,
- userHandle.getIdentifier(),
- /*logger=*/ null);
+ return AppSearchImpl.create(appSearchDir, userContext, /*logger=*/ null);
}
}
diff --git a/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java b/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java
index a940dde..29cb57c 100644
--- a/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java
+++ b/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java
@@ -201,7 +201,6 @@
public static AppSearchImpl create(
@NonNull File icingDir,
@NonNull Context userContext,
- int userId,
@Nullable AppSearchLogger logger)
throws AppSearchException {
Objects.requireNonNull(icingDir);
@@ -213,8 +212,7 @@
initStatsBuilder = new InitializeStats.Builder();
}
- AppSearchImpl appSearchImpl =
- new AppSearchImpl(icingDir, userContext, userId, initStatsBuilder);
+ AppSearchImpl appSearchImpl = new AppSearchImpl(icingDir, userContext, initStatsBuilder);
long prepareVisibilityStoreLatencyStartMillis = SystemClock.elapsedRealtime();
appSearchImpl.initializeVisibilityStore();
@@ -238,7 +236,6 @@
private AppSearchImpl(
@NonNull File icingDir,
@NonNull Context userContext,
- int userId,
@Nullable InitializeStats.Builder initStatsBuilder)
throws AppSearchException {
mReadWriteLock.writeLock().lock();
@@ -256,7 +253,7 @@
"Constructing IcingSearchEngine, response",
Objects.hashCode(mIcingSearchEngineLocked));
- mVisibilityStoreLocked = new VisibilityStore(this, userContext, userId);
+ mVisibilityStoreLocked = new VisibilityStore(this, userContext);
// The core initialization procedure. If any part of this fails, we bail into
// resetLocked(), deleting all data (but hopefully allowing AppSearchImpl to come up).
diff --git a/service/java/com/android/server/appsearch/stats/PlatformLogger.java b/service/java/com/android/server/appsearch/stats/PlatformLogger.java
index 7d0ce41..c857fb6 100644
--- a/service/java/com/android/server/appsearch/stats/PlatformLogger.java
+++ b/service/java/com/android/server/appsearch/stats/PlatformLogger.java
@@ -20,7 +20,6 @@
import android.annotation.Nullable;
import android.app.appsearch.exceptions.AppSearchException;
import android.content.Context;
-import android.content.pm.PackageManager;
import android.os.Process;
import android.os.SystemClock;
import android.os.UserHandle;
@@ -36,6 +35,7 @@
import com.android.server.appsearch.external.localstorage.stats.PutDocumentStats;
import com.android.server.appsearch.external.localstorage.stats.RemoveStats;
import com.android.server.appsearch.external.localstorage.stats.SearchStats;
+import com.android.server.appsearch.util.PackageUtil;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
@@ -493,21 +493,13 @@
@GuardedBy("mLock")
private int getPackageUidAsUserLocked(@NonNull String packageName) {
Integer packageUid = mPackageUidCacheLocked.get(packageName);
- if (packageUid != null) {
- return packageUid;
+ if (packageUid == null) {
+ packageUid = PackageUtil.getPackageUidAsUser(mContext, packageName, mUserHandle);
+ if (packageUid != Process.INVALID_UID) {
+ mPackageUidCacheLocked.put(packageName, packageUid);
+ }
}
-
- // TODO(b/173532925) since VisibilityStore has the same method, we can make this a
- // utility function
- try {
- packageUid = mContext.getPackageManager().getPackageUidAsUser(
- packageName, mUserHandle.getIdentifier());
- mPackageUidCacheLocked.put(packageName, packageUid);
- return packageUid;
- } catch (PackageManager.NameNotFoundException e) {
- // Package doesn't exist, continue
- }
- return Process.INVALID_UID;
+ return packageUid;
}
//
diff --git a/service/java/com/android/server/appsearch/util/PackageUtil.java b/service/java/com/android/server/appsearch/util/PackageUtil.java
new file mode 100644
index 0000000..53a1bed
--- /dev/null
+++ b/service/java/com/android/server/appsearch/util/PackageUtil.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2021 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.appsearch.util;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.os.Process;
+import android.os.UserHandle;
+
+/**
+ * Utilities for interacting with {@link android.content.pm.PackageManager},
+ * {@link android.os.UserHandle}, and other parts of dealing with apps and binder.
+ *
+ * @hide
+ */
+public class PackageUtil {
+ private PackageUtil() {}
+
+ /**
+ * Finds the UID of the {@code packageName}. Returns {@link Process#INVALID_UID} if unable to
+ * find the UID.
+ */
+ public static int getPackageUidAsUser(
+ @NonNull Context context, @NonNull String packageName, @NonNull UserHandle user) {
+ Context userContext = context.createContextAsUser(user, /*flags=*/ 0);
+ return getPackageUid(userContext, packageName);
+ }
+
+ /**
+ * Finds the UID of the {@code packageName} in the given {@code context}. Returns
+ * {@link Process#INVALID_UID} if unable to find the UID.
+ */
+ public static int getPackageUid(@NonNull Context context, @NonNull String packageName) {
+ try {
+ return context.getPackageManager().getPackageUid(packageName, /*flags=*/ 0);
+ } catch (PackageManager.NameNotFoundException e) {
+ return Process.INVALID_UID;
+ }
+ }
+}
diff --git a/service/java/com/android/server/appsearch/visibilitystore/VisibilityStore.java b/service/java/com/android/server/appsearch/visibilitystore/VisibilityStore.java
index acff792..95ed368 100644
--- a/service/java/com/android/server/appsearch/visibilitystore/VisibilityStore.java
+++ b/service/java/com/android/server/appsearch/visibilitystore/VisibilityStore.java
@@ -18,7 +18,6 @@
import static android.Manifest.permission.READ_GLOBAL_APP_SEARCH_DATA;
import android.annotation.NonNull;
-import android.annotation.UserIdInt;
import android.app.appsearch.AppSearchResult;
import android.app.appsearch.AppSearchSchema;
import android.app.appsearch.GenericDocument;
@@ -27,7 +26,6 @@
import android.app.appsearch.exceptions.AppSearchException;
import android.content.Context;
import android.content.pm.PackageManager;
-import android.os.Process;
import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.ArraySet;
@@ -35,6 +33,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.appsearch.external.localstorage.AppSearchImpl;
import com.android.server.appsearch.external.localstorage.util.PrefixUtil;
+import com.android.server.appsearch.util.PackageUtil;
import com.google.android.icing.proto.PersistType;
@@ -67,9 +66,6 @@
* @hide
*/
public class VisibilityStore {
-
- private static final String TAG = "AppSearchVisibilityStore";
-
/** No-op user id that won't have any visibility settings. */
public static final int NO_OP_USER_ID = -1;
@@ -95,9 +91,6 @@
// Context of the user that the call is being made as.
private final Context mUserContext;
- // User ID of the caller who we're checking visibility settings for.
- private final int mUserId;
-
/** Stores the schemas that are platform-hidden. All values are prefixed. */
private final NotPlatformSurfaceableMap mNotPlatformSurfaceableMap =
new NotPlatformSurfaceableMap();
@@ -112,13 +105,9 @@
* @param appSearchImpl AppSearchImpl instance
* @param userContext Context of the user that the call is being made as
*/
- public VisibilityStore(
- @NonNull AppSearchImpl appSearchImpl,
- @NonNull Context userContext,
- @UserIdInt int userId) {
+ public VisibilityStore(@NonNull AppSearchImpl appSearchImpl, @NonNull Context userContext) {
mAppSearchImpl = appSearchImpl;
- mUserContext = userContext;
- mUserId = userId;
+ mUserContext = Objects.requireNonNull(userContext);
}
/**
@@ -348,6 +337,9 @@
Set<PackageIdentifier> packageIdentifiers =
mPackageAccessibleMap.getAccessiblePackages(
packageName, databaseName, prefixedSchema);
+ if (packageIdentifiers.isEmpty()) {
+ return false;
+ }
for (PackageIdentifier packageIdentifier : packageIdentifiers) {
// TODO(b/169883602): Consider caching the UIDs of packages. Looking this up in the
// package manager could be costly. We would also need to update the cache on
@@ -357,9 +349,10 @@
// the callerUid since clients can createContextAsUser with some other user, and then
// make calls to us. So just check if the appId portion of the uid is the same. This is
// essentially UserHandle.isSameApp, but that's not a system API for us to use.
- int callerAppId = UserHandle.getAppId((callerUid));
- int userAppId =
- UserHandle.getAppId(getPackageUidAsUser(packageIdentifier.getPackageName()));
+ int callerAppId = UserHandle.getAppId(callerUid);
+ int packageUid =
+ PackageUtil.getPackageUid(mUserContext, packageIdentifier.getPackageName());
+ int userAppId = UserHandle.getAppId(packageUid);
if (callerAppId != userAppId) {
continue;
}
@@ -401,17 +394,4 @@
@NonNull String packageName, @NonNull String databaseName) {
return ID_PREFIX + PrefixUtil.createPrefix(packageName, databaseName);
}
-
- /**
- * Finds the UID of the {@code packageName}. Returns {@link Process#INVALID_UID} if unable to
- * find the UID.
- */
- private int getPackageUidAsUser(@NonNull String packageName) {
- try {
- return mUserContext.getPackageManager().getPackageUidAsUser(packageName, mUserId);
- } catch (PackageManager.NameNotFoundException e) {
- // Package doesn't exist, continue
- }
- return Process.INVALID_UID;
- }
}
diff --git a/testing/servicestests/src/com/android/server/appsearch/AppSearchImplPlatformTest.java b/testing/servicestests/src/com/android/server/appsearch/AppSearchImplPlatformTest.java
index 755795d..3bcbcbd 100644
--- a/testing/servicestests/src/com/android/server/appsearch/AppSearchImplPlatformTest.java
+++ b/testing/servicestests/src/com/android/server/appsearch/AppSearchImplPlatformTest.java
@@ -25,11 +25,18 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.when;
+
+import android.annotation.NonNull;
import android.app.appsearch.AppSearchSchema;
import android.app.appsearch.PackageIdentifier;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.pm.PackageManager;
+import android.os.UserHandle;
+import android.util.ArrayMap;
import androidx.test.core.app.ApplicationProvider;
@@ -43,13 +50,15 @@
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
+import org.mockito.Mockito;
import java.util.Collections;
+import java.util.Map;
/** This tests AppSearchImpl when it's running with a platform-backed VisibilityStore. */
public class AppSearchImplPlatformTest {
@Rule public TemporaryFolder mTemporaryFolder = new TemporaryFolder();
- private MockPackageManager mMockPackageManager = new MockPackageManager();
+ private final Map<UserHandle, PackageManager> mMockPackageManagers = new ArrayMap<>();
private Context mContext;
private AppSearchImpl mAppSearchImpl;
private int mGlobalQuerierUid;
@@ -57,20 +66,28 @@
@Before
public void setUp() throws Exception {
Context context = ApplicationProvider.getApplicationContext();
- mContext =
- new ContextWrapper(context) {
+ mContext = new ContextWrapper(context) {
+ @Override
+ public Context createContextAsUser(UserHandle user, int flags) {
+ return new ContextWrapper(super.createContextAsUser(user, flags)) {
@Override
public PackageManager getPackageManager() {
- return mMockPackageManager.getMockPackageManager();
+ return getMockPackageManager(user);
}
};
+ }
+
+ @Override
+ public PackageManager getPackageManager() {
+ return createContextAsUser(getUser(), /*flags=*/ 0).getPackageManager();
+ }
+ };
// Give ourselves global query permissions
mAppSearchImpl =
AppSearchImpl.create(
mTemporaryFolder.newFolder(),
mContext,
- mContext.getUserId(),
/*logger=*/ null);
mGlobalQuerierUid =
@@ -85,14 +102,19 @@
int uidFoo = 1;
// Make sure foo package will pass package manager checks.
- mMockPackageManager.mockGetPackageUidAsUser(packageNameFoo, mContext.getUserId(), uidFoo);
- mMockPackageManager.mockAddSigningCertificate(packageNameFoo, sha256CertFoo);
+ PackageManager mockPackageManager = getMockPackageManager(mContext.getUser());
+ when(mockPackageManager.getPackageUid(eq(packageNameFoo), /*flags=*/ anyInt()))
+ .thenReturn(uidFoo);
+ when(mockPackageManager.hasSigningCertificate(
+ packageNameFoo, sha256CertFoo, PackageManager.CERT_INPUT_SHA256))
+ .thenReturn(true);
// Make sure we have global query privileges and "foo" doesn't
- mMockPackageManager.mockCheckPermission(
- READ_GLOBAL_APP_SEARCH_DATA, mContext.getPackageName(), PERMISSION_GRANTED);
- mMockPackageManager.mockCheckPermission(
- READ_GLOBAL_APP_SEARCH_DATA, packageNameFoo, PERMISSION_DENIED);
+ when(mockPackageManager.checkPermission(
+ READ_GLOBAL_APP_SEARCH_DATA, mContext.getPackageName()))
+ .thenReturn(PERMISSION_GRANTED);
+ when(mockPackageManager.checkPermission(READ_GLOBAL_APP_SEARCH_DATA, packageNameFoo))
+ .thenReturn(PERMISSION_DENIED);
// Set schema1
String prefix = PrefixUtil.createPrefix("package", "database");
@@ -145,19 +167,16 @@
/*schemaVersion=*/ 0);
// Check that "schema1" still has the same visibility settings
- SystemUtil.runWithShellPermissionIdentity(
- () -> {
- assertThat(
- mAppSearchImpl
- .getVisibilityStoreLocked()
- .isSchemaSearchableByCaller(
- "package",
- "database",
- prefix + "schema1",
- mContext.getPackageName(),
- mGlobalQuerierUid))
- .isFalse();
- },
+ SystemUtil.runWithShellPermissionIdentity(() -> assertThat(
+ mAppSearchImpl
+ .getVisibilityStoreLocked()
+ .isSchemaSearchableByCaller(
+ "package",
+ "database",
+ prefix + "schema1",
+ mContext.getPackageName(),
+ mGlobalQuerierUid))
+ .isFalse(),
READ_GLOBAL_APP_SEARCH_DATA);
assertThat(
@@ -172,19 +191,16 @@
.isTrue();
// "schema2" has default visibility settings
- SystemUtil.runWithShellPermissionIdentity(
- () -> {
- assertThat(
- mAppSearchImpl
- .getVisibilityStoreLocked()
- .isSchemaSearchableByCaller(
- "package",
- "database",
- prefix + "schema2",
- mContext.getPackageName(),
- mGlobalQuerierUid))
- .isTrue();
- },
+ SystemUtil.runWithShellPermissionIdentity(() -> assertThat(
+ mAppSearchImpl
+ .getVisibilityStoreLocked()
+ .isSchemaSearchableByCaller(
+ "package",
+ "database",
+ prefix + "schema2",
+ mContext.getPackageName(),
+ mGlobalQuerierUid))
+ .isTrue(),
READ_GLOBAL_APP_SEARCH_DATA);
assertThat(
@@ -207,14 +223,19 @@
int uidFoo = 1;
// Make sure foo package will pass package manager checks.
- mMockPackageManager.mockGetPackageUidAsUser(packageNameFoo, mContext.getUserId(), uidFoo);
- mMockPackageManager.mockAddSigningCertificate(packageNameFoo, sha256CertFoo);
+ PackageManager mockPackageManager = getMockPackageManager(mContext.getUser());
+ when(mockPackageManager.getPackageUid(eq(packageNameFoo), /*flags=*/ anyInt()))
+ .thenReturn(uidFoo);
+ when(mockPackageManager.hasSigningCertificate(
+ packageNameFoo, sha256CertFoo, PackageManager.CERT_INPUT_SHA256))
+ .thenReturn(true);
// Make sure we have global query privileges and "foo" doesn't
- mMockPackageManager.mockCheckPermission(
- READ_GLOBAL_APP_SEARCH_DATA, mContext.getPackageName(), PERMISSION_GRANTED);
- mMockPackageManager.mockCheckPermission(
- READ_GLOBAL_APP_SEARCH_DATA, packageNameFoo, PERMISSION_DENIED);
+ when(mockPackageManager.checkPermission(
+ READ_GLOBAL_APP_SEARCH_DATA, mContext.getPackageName()))
+ .thenReturn(PERMISSION_GRANTED);
+ when(mockPackageManager.checkPermission(READ_GLOBAL_APP_SEARCH_DATA, packageNameFoo))
+ .thenReturn(PERMISSION_DENIED);
String prefix = PrefixUtil.createPrefix("package", "database");
mAppSearchImpl.setSchema(
@@ -320,8 +341,10 @@
@Test
public void testSetSchema_defaultPlatformVisible() throws Exception {
// Make sure we have global query privileges
- mMockPackageManager.mockCheckPermission(
- READ_GLOBAL_APP_SEARCH_DATA, mContext.getPackageName(), PERMISSION_GRANTED);
+ PackageManager mockPackageManager = getMockPackageManager(mContext.getUser());
+ when(mockPackageManager.checkPermission(
+ READ_GLOBAL_APP_SEARCH_DATA, mContext.getPackageName()))
+ .thenReturn(PERMISSION_GRANTED);
String prefix = PrefixUtil.createPrefix("package", "database");
mAppSearchImpl.setSchema(
@@ -348,8 +371,10 @@
@Test
public void testSetSchema_platformHidden() throws Exception {
// Make sure we have global query privileges
- mMockPackageManager.mockCheckPermission(
- READ_GLOBAL_APP_SEARCH_DATA, mContext.getPackageName(), PERMISSION_GRANTED);
+ PackageManager mockPackageManager = getMockPackageManager(mContext.getUser());
+ when(mockPackageManager.checkPermission(
+ READ_GLOBAL_APP_SEARCH_DATA, mContext.getPackageName()))
+ .thenReturn(PERMISSION_GRANTED);
String prefix = PrefixUtil.createPrefix("package", "database");
mAppSearchImpl.setSchema(
@@ -378,8 +403,9 @@
String packageName = "com.package";
// Make sure package doesn't global query privileges
- mMockPackageManager.mockCheckPermission(
- READ_GLOBAL_APP_SEARCH_DATA, packageName, PERMISSION_DENIED);
+ PackageManager mockPackageManager = getMockPackageManager(mContext.getUser());
+ when(mockPackageManager.checkPermission(
+ READ_GLOBAL_APP_SEARCH_DATA, packageName)).thenReturn(PERMISSION_DENIED);
String prefix = PrefixUtil.createPrefix("package", "database");
mAppSearchImpl.setSchema(
@@ -410,12 +436,16 @@
int uidFoo = 1;
// Make sure foo package will pass package manager checks.
- mMockPackageManager.mockGetPackageUidAsUser(packageNameFoo, mContext.getUserId(), uidFoo);
- mMockPackageManager.mockAddSigningCertificate(packageNameFoo, sha256CertFoo);
+ PackageManager mockPackageManager = getMockPackageManager(mContext.getUser());
+ when(mockPackageManager.getPackageUid(eq(packageNameFoo), /*flags=*/ anyInt()))
+ .thenReturn(uidFoo);
+ when(mockPackageManager.hasSigningCertificate(
+ packageNameFoo, sha256CertFoo, PackageManager.CERT_INPUT_SHA256))
+ .thenReturn(true);
// Make sure foo doesn't have global query privileges
- mMockPackageManager.mockCheckPermission(
- READ_GLOBAL_APP_SEARCH_DATA, packageNameFoo, PERMISSION_DENIED);
+ when(mockPackageManager.checkPermission(READ_GLOBAL_APP_SEARCH_DATA, packageNameFoo))
+ .thenReturn(PERMISSION_DENIED);
String prefix = PrefixUtil.createPrefix("package", "database");
mAppSearchImpl.setSchema(
@@ -439,4 +469,14 @@
uidFoo))
.isTrue();
}
+
+ @NonNull
+ private PackageManager getMockPackageManager(@NonNull UserHandle user) {
+ PackageManager pm = mMockPackageManagers.get(user);
+ if (pm == null) {
+ pm = Mockito.mock(PackageManager.class);
+ mMockPackageManagers.put(user, pm);
+ }
+ return pm;
+ }
}
diff --git a/testing/servicestests/src/com/android/server/appsearch/MockPackageManager.java b/testing/servicestests/src/com/android/server/appsearch/MockPackageManager.java
deleted file mode 100644
index 60e1a8f..0000000
--- a/testing/servicestests/src/com/android/server/appsearch/MockPackageManager.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (C) 2021 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.
- */
-
-// TODO(b/169883602): This is purposely a different package from the path so that AppSearchImplTest
-// can use it without an extra import. This should be moved into a proper package once
-// AppSearchImpl-VisibilityStore's dependencies are refactored.
-package com.android.server.appsearch.external.localstorage;
-
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.when;
-
-import android.annotation.NonNull;
-import android.annotation.UserIdInt;
-import android.content.pm.PackageManager;
-
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-/** Mock to help test package name, UID, and certificate verification. */
-public class MockPackageManager {
-
- @Mock private PackageManager mMockPackageManager;
-
- public MockPackageManager() {
- MockitoAnnotations.initMocks(this);
- }
-
- @NonNull
- public PackageManager getMockPackageManager() {
- return mMockPackageManager;
- }
-
- /** Mock a checkPermission call. */
- public void mockCheckPermission(String permission, String packageName, int permissionResult) {
- when(mMockPackageManager.checkPermission(permission, packageName))
- .thenReturn(permissionResult);
- }
-
- /** Mock a NameNotFoundException if the package name isn't installed. */
- public void mockThrowsNameNotFoundException(String packageName) {
- try {
- when(mMockPackageManager.getPackageUidAsUser(eq(packageName), /*userId=*/ anyInt()))
- .thenThrow(new PackageManager.NameNotFoundException());
- when(mMockPackageManager.getPackageUidAsUser(
- eq(packageName), /*flags=*/ anyInt(), /*userId=*/ anyInt()))
- .thenThrow(new PackageManager.NameNotFoundException());
- } catch (PackageManager.NameNotFoundException e) {
- // Shouldn't ever happen since we're mocking the exception
- e.printStackTrace();
- }
- }
-
- /** Mocks that {@code uid} contains the {@code packageName} */
- public void mockGetPackageUidAsUser(String packageName, @UserIdInt int callerUserId, int uid) {
- try {
- when(mMockPackageManager.getPackageUidAsUser(eq(packageName), eq(callerUserId)))
- .thenReturn(uid);
- when(mMockPackageManager.getPackageUidAsUser(
- eq(packageName), /*flags=*/ anyInt(), eq(callerUserId)))
- .thenReturn(uid);
- } catch (PackageManager.NameNotFoundException e) {
- // Shouldn't ever happen since we're mocking the method.
- e.printStackTrace();
- }
- }
-
- /** Mocks that {@code packageName} has been signed with {@code sha256Cert}. */
- public void mockAddSigningCertificate(String packageName, byte[] sha256Cert) {
- when(mMockPackageManager.hasSigningCertificate(
- packageName, sha256Cert, PackageManager.CERT_INPUT_SHA256))
- .thenReturn(true);
- }
-
- /** Mocks that {@code packageName} has NOT been signed with {@code sha256Cert}. */
- public void mockRemoveSigningCertificate(String packageName, byte[] sha256Cert) {
- when(mMockPackageManager.hasSigningCertificate(
- packageName, sha256Cert, PackageManager.CERT_INPUT_SHA256))
- .thenReturn(false);
- }
-}
diff --git a/testing/servicestests/src/com/android/server/appsearch/VisibilityStoreTest.java b/testing/servicestests/src/com/android/server/appsearch/VisibilityStoreTest.java
index d9cfc54..6ac4d13 100644
--- a/testing/servicestests/src/com/android/server/appsearch/VisibilityStoreTest.java
+++ b/testing/servicestests/src/com/android/server/appsearch/VisibilityStoreTest.java
@@ -25,10 +25,17 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.when;
+
+import android.annotation.NonNull;
import android.app.appsearch.PackageIdentifier;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.pm.PackageManager;
+import android.os.UserHandle;
+import android.util.ArrayMap;
import androidx.test.core.app.ApplicationProvider;
@@ -43,39 +50,47 @@
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
+import org.mockito.Mockito;
import java.util.Collections;
+import java.util.Map;
public class VisibilityStoreTest {
-
@Rule public TemporaryFolder mTemporaryFolder = new TemporaryFolder();
- private MockPackageManager mMockPackageManager = new MockPackageManager();
+ private final Map<UserHandle, PackageManager> mMockPackageManagers = new ArrayMap<>();
private Context mContext;
- private AppSearchImpl mAppSearchImpl;
private VisibilityStore mVisibilityStore;
private int mUid;
@Before
public void setUp() throws Exception {
Context context = ApplicationProvider.getApplicationContext();
- mContext =
- new ContextWrapper(context) {
+ mContext = new ContextWrapper(context) {
+ @Override
+ public Context createContextAsUser(UserHandle user, int flags) {
+ return new ContextWrapper(super.createContextAsUser(user, flags)) {
@Override
public PackageManager getPackageManager() {
- return mMockPackageManager.getMockPackageManager();
+ return getMockPackageManager(user);
}
};
+ }
+
+ @Override
+ public PackageManager getPackageManager() {
+ return createContextAsUser(getUser(), /*flags=*/ 0).getPackageManager();
+ }
+ };
// Give ourselves global query permissions
- mAppSearchImpl =
+ AppSearchImpl appSearchImpl =
AppSearchImpl.create(
mTemporaryFolder.newFolder(),
mContext,
- mContext.getUserId(),
/*logger=*/ null);
mUid = mContext.getPackageManager().getPackageUid(mContext.getPackageName(), /*flags=*/ 0);
- mVisibilityStore = mAppSearchImpl.getVisibilityStoreLocked();
+ mVisibilityStore = appSearchImpl.getVisibilityStoreLocked();
}
/**
@@ -103,8 +118,10 @@
@Test
public void testSetVisibility_platformSurfaceable() throws Exception {
// Make sure we have global query privileges
- mMockPackageManager.mockCheckPermission(
- READ_GLOBAL_APP_SEARCH_DATA, mContext.getPackageName(), PERMISSION_GRANTED);
+ PackageManager mockPackageManager = getMockPackageManager(mContext.getUser());
+ when(mockPackageManager
+ .checkPermission(READ_GLOBAL_APP_SEARCH_DATA, mContext.getPackageName()))
+ .thenReturn(PERMISSION_GRANTED);
mVisibilityStore.setVisibility(
"package",
@@ -210,10 +227,13 @@
int uidNotFooOrBar = 3;
// Make sure none of them have global query privileges
- mMockPackageManager.mockCheckPermission(
- READ_GLOBAL_APP_SEARCH_DATA, packageNameFoo, PERMISSION_DENIED);
- mMockPackageManager.mockCheckPermission(
- READ_GLOBAL_APP_SEARCH_DATA, packageNameBar, PERMISSION_DENIED);
+ PackageManager mockPackageManager = getMockPackageManager(mContext.getUser());
+ when(mockPackageManager
+ .checkPermission(READ_GLOBAL_APP_SEARCH_DATA, packageNameFoo))
+ .thenReturn(PERMISSION_DENIED);
+ when(mockPackageManager
+ .checkPermission(READ_GLOBAL_APP_SEARCH_DATA, packageNameBar))
+ .thenReturn(PERMISSION_DENIED);
// By default, a schema isn't package accessible.
assertThat(
@@ -237,32 +257,43 @@
ImmutableList.of(new PackageIdentifier(packageNameBar, sha256CertBar))));
// Should fail if PackageManager doesn't see that it has the proper certificate
- mMockPackageManager.mockGetPackageUidAsUser(packageNameFoo, mContext.getUserId(), uidFoo);
- mMockPackageManager.mockRemoveSigningCertificate(packageNameFoo, sha256CertFoo);
+ when(mockPackageManager.getPackageUid(eq(packageNameFoo), /*flags=*/ anyInt()))
+ .thenReturn(uidFoo);
+ when(mockPackageManager.hasSigningCertificate(
+ packageNameFoo, sha256CertFoo, PackageManager.CERT_INPUT_SHA256))
+ .thenReturn(false);
assertThat(
mVisibilityStore.isSchemaSearchableByCaller(
"package", "database", "prefix/schemaFoo", packageNameFoo, uidFoo))
.isFalse();
// Should fail if PackageManager doesn't think the package belongs to the uid
- mMockPackageManager.mockGetPackageUidAsUser(
- packageNameFoo, mContext.getUserId(), uidNotFooOrBar);
- mMockPackageManager.mockAddSigningCertificate(packageNameFoo, sha256CertFoo);
+ when(mockPackageManager.getPackageUid(eq(packageNameFoo), /*flags=*/ anyInt()))
+ .thenReturn(uidNotFooOrBar);
+ when(mockPackageManager.hasSigningCertificate(
+ packageNameFoo, sha256CertFoo, PackageManager.CERT_INPUT_SHA256))
+ .thenReturn(true);
assertThat(
mVisibilityStore.isSchemaSearchableByCaller(
"package", "database", "prefix/schemaFoo", packageNameFoo, uidFoo))
.isFalse();
// But if uid and certificate match, then we should have access
- mMockPackageManager.mockGetPackageUidAsUser(packageNameFoo, mContext.getUserId(), uidFoo);
- mMockPackageManager.mockAddSigningCertificate(packageNameFoo, sha256CertFoo);
+ when(mockPackageManager.getPackageUid(eq(packageNameFoo), /*flags=*/ anyInt()))
+ .thenReturn(uidFoo);
+ when(mockPackageManager.hasSigningCertificate(
+ packageNameFoo, sha256CertFoo, PackageManager.CERT_INPUT_SHA256))
+ .thenReturn(true);
assertThat(
mVisibilityStore.isSchemaSearchableByCaller(
"package", "database", "prefix/schemaFoo", packageNameFoo, uidFoo))
.isTrue();
- mMockPackageManager.mockGetPackageUidAsUser(packageNameBar, mContext.getUserId(), uidBar);
- mMockPackageManager.mockAddSigningCertificate(packageNameBar, sha256CertBar);
+ when(mockPackageManager.getPackageUid(eq(packageNameBar), /*flags=*/ anyInt()))
+ .thenReturn(uidBar);
+ when(mockPackageManager.hasSigningCertificate(
+ packageNameBar, sha256CertBar, PackageManager.CERT_INPUT_SHA256))
+ .thenReturn(true);
assertThat(
mVisibilityStore.isSchemaSearchableByCaller(
"package", "database", "prefix/schemaBar", packageNameBar, uidBar))
@@ -278,15 +309,21 @@
"prefix/schemaFoo",
ImmutableList.of(new PackageIdentifier(packageNameFoo, sha256CertFoo))));
- mMockPackageManager.mockGetPackageUidAsUser(packageNameFoo, mContext.getUserId(), uidFoo);
- mMockPackageManager.mockAddSigningCertificate(packageNameFoo, sha256CertFoo);
+ when(mockPackageManager.getPackageUid(eq(packageNameFoo), /*flags=*/ anyInt()))
+ .thenReturn(uidFoo);
+ when(mockPackageManager.hasSigningCertificate(
+ packageNameFoo, sha256CertFoo, PackageManager.CERT_INPUT_SHA256))
+ .thenReturn(true);
assertThat(
mVisibilityStore.isSchemaSearchableByCaller(
"package", "database", "prefix/schemaFoo", packageNameFoo, uidFoo))
.isTrue();
- mMockPackageManager.mockGetPackageUidAsUser(packageNameBar, mContext.getUserId(), uidBar);
- mMockPackageManager.mockAddSigningCertificate(packageNameBar, sha256CertBar);
+ when(mockPackageManager.getPackageUid(eq(packageNameBar), /*flags=*/ anyInt()))
+ .thenReturn(uidBar);
+ when(mockPackageManager.hasSigningCertificate(
+ packageNameBar, sha256CertBar, PackageManager.CERT_INPUT_SHA256))
+ .thenReturn(true);
assertThat(
mVisibilityStore.isSchemaSearchableByCaller(
"package", "database", "prefix/schemaBar", packageNameBar, uidBar))
@@ -302,11 +339,13 @@
int uidFoo = 1;
// Pretend we can't find the Foo package.
- mMockPackageManager.mockThrowsNameNotFoundException(packageNameFoo);
+ PackageManager mockPackageManager = getMockPackageManager(mContext.getUser());
+ when(mockPackageManager.getPackageUid(eq(packageNameFoo), /*flags=*/ anyInt()))
+ .thenThrow(new PackageManager.NameNotFoundException());
// Make sure "foo" doesn't have global query privileges
- mMockPackageManager.mockCheckPermission(
- READ_GLOBAL_APP_SEARCH_DATA, packageNameFoo, PERMISSION_DENIED);
+ when(mockPackageManager.checkPermission(READ_GLOBAL_APP_SEARCH_DATA, packageNameFoo))
+ .thenReturn(PERMISSION_DENIED);
// Grant package access
mVisibilityStore.setVisibility(
@@ -332,10 +371,12 @@
int uidFoo = 1;
// Set it up such that the test package has global query privileges, but "foo" doesn't.
- mMockPackageManager.mockCheckPermission(
- READ_GLOBAL_APP_SEARCH_DATA, mContext.getPackageName(), PERMISSION_GRANTED);
- mMockPackageManager.mockCheckPermission(
- READ_GLOBAL_APP_SEARCH_DATA, packageNameFoo, PERMISSION_DENIED);
+ PackageManager mockPackageManager = getMockPackageManager(mContext.getUser());
+ when(mockPackageManager.checkPermission(
+ READ_GLOBAL_APP_SEARCH_DATA, mContext.getPackageName()))
+ .thenReturn(PERMISSION_GRANTED);
+ when(mockPackageManager.checkPermission(READ_GLOBAL_APP_SEARCH_DATA, packageNameFoo))
+ .thenReturn(PERMISSION_DENIED);
mVisibilityStore.setVisibility(
/*packageName=*/ "",
@@ -354,8 +395,11 @@
mUid))
.isTrue();
- mMockPackageManager.mockGetPackageUidAsUser(packageNameFoo, mContext.getUserId(), uidFoo);
- mMockPackageManager.mockAddSigningCertificate(packageNameFoo, sha256CertFoo);
+ when(mockPackageManager.getPackageUid(eq(packageNameFoo), /*flags=*/ anyInt()))
+ .thenReturn(uidFoo);
+ when(mockPackageManager.hasSigningCertificate(
+ packageNameFoo, sha256CertFoo, PackageManager.CERT_INPUT_SHA256))
+ .thenReturn(true);
assertThat(
mVisibilityStore.isSchemaSearchableByCaller(
/*packageName=*/ "",
@@ -365,4 +409,14 @@
uidFoo))
.isTrue();
}
+
+ @NonNull
+ private PackageManager getMockPackageManager(@NonNull UserHandle user) {
+ PackageManager pm = mMockPackageManagers.get(user);
+ if (pm == null) {
+ pm = Mockito.mock(PackageManager.class);
+ mMockPackageManagers.put(user, pm);
+ }
+ return pm;
+ }
}
diff --git a/testing/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java b/testing/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java
index 031532b..5a8c44c 100644
--- a/testing/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java
+++ b/testing/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java
@@ -86,7 +86,6 @@
AppSearchImpl.create(
mTemporaryFolder.newFolder(),
context,
- VisibilityStore.NO_OP_USER_ID,
/*logger=*/ null);
}
@@ -494,9 +493,7 @@
// Setup the index
Context context = ApplicationProvider.getApplicationContext();
File appsearchDir = mTemporaryFolder.newFolder();
- AppSearchImpl appSearchImpl =
- AppSearchImpl.create(
- appsearchDir, context, VisibilityStore.NO_OP_USER_ID, /*logger=*/ null);
+ AppSearchImpl appSearchImpl = AppSearchImpl.create(appsearchDir, context, /*logger=*/ null);
// Insert schema
List<AppSearchSchema> schemas =
@@ -557,9 +554,7 @@
// Initialize AppSearchImpl. This should cause a reset.
appSearchImpl.close();
- appSearchImpl =
- AppSearchImpl.create(
- appsearchDir, context, VisibilityStore.NO_OP_USER_ID, testLogger);
+ appSearchImpl = AppSearchImpl.create(appsearchDir, context, testLogger);
// Check recovery state
InitializeStats initStats = testLogger.mInitializeStats;
@@ -1688,7 +1683,6 @@
AppSearchImpl.create(
mTemporaryFolder.newFolder(),
context,
- VisibilityStore.NO_OP_USER_ID,
/*logger=*/ null);
// Initial check that we could do something at first.
@@ -1836,9 +1830,7 @@
// Setup the index
Context context = ApplicationProvider.getApplicationContext();
File appsearchDir = mTemporaryFolder.newFolder();
- AppSearchImpl appSearchImpl =
- AppSearchImpl.create(
- appsearchDir, context, VisibilityStore.NO_OP_USER_ID, /*logger=*/ null);
+ AppSearchImpl appSearchImpl = AppSearchImpl.create(appsearchDir, context, /*logger=*/ null);
List<AppSearchSchema> schemas =
Collections.singletonList(new AppSearchSchema.Builder("type").build());
@@ -1864,8 +1856,7 @@
// That document should be visible even from another instance.
AppSearchImpl appSearchImpl2 =
- AppSearchImpl.create(
- appsearchDir, context, VisibilityStore.NO_OP_USER_ID, /*logger=*/ null);
+ AppSearchImpl.create(appsearchDir, context, /*logger=*/ null);
getResult =
appSearchImpl2.getDocument(
"package", "database", "namespace1", "id1", Collections.emptyMap());
@@ -1877,9 +1868,7 @@
// Setup the index
Context context = ApplicationProvider.getApplicationContext();
File appsearchDir = mTemporaryFolder.newFolder();
- AppSearchImpl appSearchImpl =
- AppSearchImpl.create(
- appsearchDir, context, VisibilityStore.NO_OP_USER_ID, /*logger=*/ null);
+ AppSearchImpl appSearchImpl = AppSearchImpl.create(appsearchDir, context, /*logger=*/ null);
List<AppSearchSchema> schemas =
Collections.singletonList(new AppSearchSchema.Builder("type").build());
@@ -1929,8 +1918,7 @@
// Only the second document should be retrievable from another instance.
AppSearchImpl appSearchImpl2 =
- AppSearchImpl.create(
- appsearchDir, context, VisibilityStore.NO_OP_USER_ID, /*logger=*/ null);
+ AppSearchImpl.create(appsearchDir, context, /*logger=*/ null);
expectThrows(
AppSearchException.class,
() ->
@@ -1951,9 +1939,7 @@
// Setup the index
Context context = ApplicationProvider.getApplicationContext();
File appsearchDir = mTemporaryFolder.newFolder();
- AppSearchImpl appSearchImpl =
- AppSearchImpl.create(
- appsearchDir, context, VisibilityStore.NO_OP_USER_ID, /*logger=*/ null);
+ AppSearchImpl appSearchImpl = AppSearchImpl.create(appsearchDir, context, /*logger=*/ null);
List<AppSearchSchema> schemas =
Collections.singletonList(new AppSearchSchema.Builder("type").build());
@@ -2011,8 +1997,7 @@
// Only the second document should be retrievable from another instance.
AppSearchImpl appSearchImpl2 =
- AppSearchImpl.create(
- appsearchDir, context, VisibilityStore.NO_OP_USER_ID, /*logger=*/ null);
+ AppSearchImpl.create(appsearchDir, context, /*logger=*/ null);
expectThrows(
AppSearchException.class,
() ->
diff --git a/testing/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchLoggerTest.java b/testing/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchLoggerTest.java
index d1ca759..f0a6ef1 100644
--- a/testing/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchLoggerTest.java
+++ b/testing/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchLoggerTest.java
@@ -40,7 +40,6 @@
import com.android.server.appsearch.proto.QueryStatsProto;
import com.android.server.appsearch.proto.ScoringSpecProto;
import com.android.server.appsearch.proto.TermMatchType;
-import com.android.server.appsearch.visibilitystore.VisibilityStore;
import org.junit.Before;
import org.junit.Rule;
@@ -64,7 +63,6 @@
AppSearchImpl.create(
mTemporaryFolder.newFolder(),
context,
- VisibilityStore.NO_OP_USER_ID,
/*logger=*/ null);
mLogger = new TestLogger();
}
@@ -292,7 +290,6 @@
AppSearchImpl.create(
mTemporaryFolder.newFolder(),
context,
- VisibilityStore.NO_OP_USER_ID,
mLogger);
InitializeStats iStats = mLogger.mInitializeStats;
diff --git a/testing/servicestests/src/com/android/server/appsearch/stats/PlatformLoggerTest.java b/testing/servicestests/src/com/android/server/appsearch/stats/PlatformLoggerTest.java
index 734f05a..7e1639e 100644
--- a/testing/servicestests/src/com/android/server/appsearch/stats/PlatformLoggerTest.java
+++ b/testing/servicestests/src/com/android/server/appsearch/stats/PlatformLoggerTest.java
@@ -22,6 +22,7 @@
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
import android.annotation.NonNull;
import android.content.Context;
@@ -29,46 +30,46 @@
import android.content.pm.PackageManager;
import android.os.SystemClock;
import android.os.UserHandle;
+import android.util.ArrayMap;
import android.util.SparseIntArray;
import androidx.test.core.app.ApplicationProvider;
-import com.android.server.appsearch.external.localstorage.MockPackageManager;
import com.android.server.appsearch.external.localstorage.stats.CallStats;
import org.junit.Before;
import org.junit.Test;
+import org.mockito.Mockito;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
+import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
+import java.util.Map;
public class PlatformLoggerTest {
private static final int TEST_MIN_TIME_INTERVAL_BETWEEN_SAMPLES_MILLIS = 100;
private static final int TEST_DEFAULT_SAMPLING_INTERVAL = 10;
private static final String TEST_PACKAGE_NAME = "packageName";
- private MockPackageManager mMockPackageManager = new MockPackageManager();
+
+ private final Map<UserHandle, PackageManager> mMockPackageManagers = new ArrayMap<>();
private Context mContext;
@Before
public void setUp() throws Exception {
Context context = ApplicationProvider.getApplicationContext();
- mContext =
- new ContextWrapper(context) {
+ mContext = new ContextWrapper(context) {
+ @Override
+ public Context createContextAsUser(UserHandle user, int flags) {
+ return new ContextWrapper(super.createContextAsUser(user, flags)) {
@Override
public PackageManager getPackageManager() {
- return mMockPackageManager.getMockPackageManager();
+ return getMockPackageManager(user);
}
};
- }
-
- static int calculateHashCodeMd5withBigInteger(@NonNull String str) throws
- NoSuchAlgorithmException, UnsupportedEncodingException {
- MessageDigest md = MessageDigest.getInstance("MD5");
- md.update(str.getBytes(/*charsetName=*/ "UTF-8"));
- byte[] digest = md.digest();
- return new BigInteger(digest).intValue();
+ }
+ };
}
@Test
@@ -294,39 +295,51 @@
TEST_MIN_TIME_INTERVAL_BETWEEN_SAMPLES_MILLIS,
TEST_DEFAULT_SAMPLING_INTERVAL,
/*samplingIntervals=*/ new SparseIntArray()));
- mMockPackageManager.mockGetPackageUidAsUser(testPackageName, mContext.getUserId(), testUid);
+ PackageManager mockPackageManager = getMockPackageManager(mContext.getUser());
+ when(mockPackageManager.getPackageUid(testPackageName, /*flags=*/0)).thenReturn(testUid);
- //
// First time, no cache
- //
PlatformLogger.ExtraStats extraStats = logger.createExtraStatsLocked(testPackageName,
CallStats.CALL_TYPE_PUT_DOCUMENT);
-
- verify(mMockPackageManager.getMockPackageManager(), times(1)).getPackageUidAsUser(
- eq(testPackageName), /*userId=*/ anyInt());
+ verify(mockPackageManager, times(1))
+ .getPackageUid(eq(testPackageName), /*flags=*/ anyInt());
assertThat(extraStats.mPackageUid).isEqualTo(testUid);
- //
// Second time, we have cache
- //
extraStats = logger.createExtraStatsLocked(testPackageName,
CallStats.CALL_TYPE_PUT_DOCUMENT);
// Count is still one since we will use the cache
- verify(mMockPackageManager.getMockPackageManager(), times(1)).getPackageUidAsUser(
- eq(testPackageName), /*userId=*/ anyInt());
+ verify(mockPackageManager, times(1))
+ .getPackageUid(eq(testPackageName), /*flags=*/ anyInt());
assertThat(extraStats.mPackageUid).isEqualTo(testUid);
- //
// Remove the cache and try again
- //
assertThat(logger.removeCachedUidForPackage(testPackageName)).isEqualTo(testUid);
extraStats = logger.createExtraStatsLocked(testPackageName,
CallStats.CALL_TYPE_PUT_DOCUMENT);
// count increased by 1 since cache is cleared
- verify(mMockPackageManager.getMockPackageManager(), times(2)).getPackageUidAsUser(
- eq(testPackageName), /*userId=*/ anyInt());
+ verify(mockPackageManager, times(2))
+ .getPackageUid(eq(testPackageName), /*flags=*/ anyInt());
assertThat(extraStats.mPackageUid).isEqualTo(testUid);
}
+
+ private static int calculateHashCodeMd5withBigInteger(@NonNull String str)
+ throws NoSuchAlgorithmException {
+ MessageDigest md = MessageDigest.getInstance("MD5");
+ md.update(str.getBytes(StandardCharsets.UTF_8));
+ byte[] digest = md.digest();
+ return new BigInteger(digest).intValue();
+ }
+
+ @NonNull
+ private PackageManager getMockPackageManager(@NonNull UserHandle user) {
+ PackageManager pm = mMockPackageManagers.get(user);
+ if (pm == null) {
+ pm = Mockito.mock(PackageManager.class);
+ mMockPackageManagers.put(user, pm);
+ }
+ return pm;
+ }
}