Run verifications on callingUser, not targetUser.

We have two verifications on each API call: 1) that the caller is not
coming from an instant app, in which case it shouldn't have access to
other app data, and 2) that the calling uid matches the caller's package
name and user handle. We were previously running these checks on the
targetUser, which could be different from the callingUser.

This is one of the blockers re-enabling cross-user support.

Bug: 193902620
Bug: 194939218
Test: atest -m -c --rebuild-module-info CtsAppSearchTestCases
FrameworksCoreTests:android.app.appsearch
FrameworksServicesTests:com.android.server.appsearch
CtsAppSearchHostTestCases

Change-Id: I9ef21efcbf26e2680c712867f05fd4adbf243b8e
diff --git a/service/java/com/android/server/appsearch/AppSearchManagerService.java b/service/java/com/android/server/appsearch/AppSearchManagerService.java
index 6a4f4db..c33d5ec 100644
--- a/service/java/com/android/server/appsearch/AppSearchManagerService.java
+++ b/service/java/com/android/server/appsearch/AppSearchManagerService.java
@@ -332,20 +332,20 @@
 
             long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
             int callingUid = Binder.getCallingUid();
-            UserHandle targetUser = handleIncomingUser(userHandle, callingUid);
             EXECUTOR.execute(() -> {
                 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
                 AppSearchUserInstance instance = null;
                 int operationSuccessCount = 0;
                 int operationFailureCount = 0;
                 try {
-                    Context targetUserContext = mContext.createContextAsUser(targetUser,
-                            /*flags=*/ 0);
+                    verifyCaller(callingUid, packageName);
+
+                    // Obtain the user where the client wants to run the operations in. This should
+                    // end up being the same as userHandle, assuming it is not a special user and
+                    // the client is allowed to run operations in that user.
+                    UserHandle targetUser = handleIncomingUser(userHandle, callingUid);
                     verifyUserUnlocked(targetUser);
-                    // TODO(b/193902620): Pass in the callingUser and not the targetUser.
-                    verifyCallingPackage(targetUserContext, targetUser, callingUid, packageName);
-                    // TODO(b/194939218): Pass in the callingUser and not the targetUser.
-                    verifyNotInstantApp(targetUserContext, packageName);
+
                     List<AppSearchSchema> schemas = new ArrayList<>(schemaBundles.size());
                     for (int i = 0; i < schemaBundles.size(); i++) {
                         schemas.add(new AppSearchSchema(schemaBundles.get(i)));
@@ -421,16 +421,16 @@
             Objects.requireNonNull(callback);
 
             int callingUid = Binder.getCallingUid();
-            UserHandle targetUser = handleIncomingUser(userHandle, callingUid);
             EXECUTOR.execute(() -> {
                 try {
-                    Context targetUserContext = mContext.createContextAsUser(targetUser,
-                            /*flags=*/ 0);
+                    verifyCaller(callingUid, packageName);
+
+                    // Obtain the user where the client wants to run the operations in. This should
+                    // end up being the same as userHandle, assuming it is not a special user and
+                    // the client is allowed to run operations in that user.
+                    UserHandle targetUser = handleIncomingUser(userHandle, callingUid);
                     verifyUserUnlocked(targetUser);
-                    // TODO(b/193902620): Pass in the callingUser and not the targetUser.
-                    verifyCallingPackage(targetUserContext, targetUser, callingUid, packageName);
-                    // TODO(b/194939218): Pass in the callingUser and not the targetUser.
-                    verifyNotInstantApp(targetUserContext, packageName);
+
                     AppSearchUserInstance instance =
                             mAppSearchUserInstanceManager.getUserInstance(targetUser);
                     GetSchemaResponse response =
@@ -456,16 +456,16 @@
             Objects.requireNonNull(callback);
 
             int callingUid = Binder.getCallingUid();
-            UserHandle targetUser = handleIncomingUser(userHandle, callingUid);
             EXECUTOR.execute(() -> {
                 try {
-                    Context targetUserContext = mContext.createContextAsUser(targetUser,
-                            /*flags=*/ 0);
+                    verifyCaller(callingUid, packageName);
+
+                    // Obtain the user where the client wants to run the operations in. This should
+                    // end up being the same as userHandle, assuming it is not a special user and
+                    // the client is allowed to run operations in that user.
+                    UserHandle targetUser = handleIncomingUser(userHandle, callingUid);
                     verifyUserUnlocked(targetUser);
-                    // TODO(b/193902620): Pass in the callingUser and not the targetUser.
-                    verifyCallingPackage(targetUserContext, targetUser, callingUid, packageName);
-                    // TODO(b/194939218): Pass in the callingUser and not the targetUser.
-                    verifyNotInstantApp(targetUserContext, packageName);
+
                     AppSearchUserInstance instance =
                             mAppSearchUserInstanceManager.getUserInstance(targetUser);
                     List<String> namespaces =
@@ -494,20 +494,20 @@
 
             long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
             int callingUid = Binder.getCallingUid();
-            UserHandle targetUser = handleIncomingUser(userHandle, callingUid);
             EXECUTOR.execute(() -> {
                 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
                 AppSearchUserInstance instance = null;
                 int operationSuccessCount = 0;
                 int operationFailureCount = 0;
                 try {
-                    Context targetUserContext = mContext.createContextAsUser(targetUser,
-                            /*flags=*/ 0);
+                    verifyCaller(callingUid, packageName);
+
+                    // Obtain the user where the client wants to run the operations in. This should
+                    // end up being the same as userHandle, assuming it is not a special user and
+                    // the client is allowed to run operations in that user.
+                    UserHandle targetUser = handleIncomingUser(userHandle, callingUid);
                     verifyUserUnlocked(targetUser);
-                    // TODO(b/193902620): Pass in the callingUser and not the targetUser.
-                    verifyCallingPackage(targetUserContext, targetUser, callingUid, packageName);
-                    // TODO(b/194939218): Pass in the callingUser and not the targetUser.
-                    verifyNotInstantApp(targetUserContext, packageName);
+
                     AppSearchBatchResult.Builder<String, Void> resultBuilder =
                             new AppSearchBatchResult.Builder<>();
                     instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
@@ -583,20 +583,20 @@
 
             long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
             int callingUid = Binder.getCallingUid();
-            UserHandle targetUser = handleIncomingUser(userHandle, callingUid);
             EXECUTOR.execute(() -> {
                 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
                 AppSearchUserInstance instance = null;
                 int operationSuccessCount = 0;
                 int operationFailureCount = 0;
                 try {
-                    Context targetUserContext = mContext.createContextAsUser(targetUser,
-                            /*flags=*/ 0);
+                    verifyCaller(callingUid, packageName);
+
+                    // Obtain the user where the client wants to run the operations in. This should
+                    // end up being the same as userHandle, assuming it is not a special user and
+                    // the client is allowed to run operations in that user.
+                    UserHandle targetUser = handleIncomingUser(userHandle, callingUid);
                     verifyUserUnlocked(targetUser);
-                    // TODO(b/193902620): Pass in the callingUser and not the targetUser.
-                    verifyCallingPackage(targetUserContext, targetUser, callingUid, packageName);
-                    // TODO(b/194939218): Pass in the callingUser and not the targetUser.
-                    verifyNotInstantApp(targetUserContext, packageName);
+
                     AppSearchBatchResult.Builder<String, Bundle> resultBuilder =
                             new AppSearchBatchResult.Builder<>();
                     instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
@@ -667,20 +667,20 @@
 
             long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
             int callingUid = Binder.getCallingUid();
-            UserHandle targetUser = handleIncomingUser(userHandle, callingUid);
             EXECUTOR.execute(() -> {
                 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
                 AppSearchUserInstance instance = null;
                 int operationSuccessCount = 0;
                 int operationFailureCount = 0;
                 try {
-                    Context targetUserContext = mContext.createContextAsUser(targetUser,
-                            /*flags=*/ 0);
+                    verifyCaller(callingUid, packageName);
+
+                    // Obtain the user where the client wants to run the operations in. This should
+                    // end up being the same as userHandle, assuming it is not a special user and
+                    // the client is allowed to run operations in that user.
+                    UserHandle targetUser = handleIncomingUser(userHandle, callingUid);
                     verifyUserUnlocked(targetUser);
-                    // TODO(b/193902620): Pass in the callingUser and not the targetUser.
-                    verifyCallingPackage(targetUserContext, targetUser, callingUid, packageName);
-                    // TODO(b/194939218): Pass in the callingUser and not the targetUser.
-                    verifyNotInstantApp(targetUserContext, packageName);
+
                     instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
                     SearchResultPage searchResultPage = instance.getAppSearchImpl().query(
                             packageName,
@@ -736,20 +736,20 @@
 
             long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
             int callingUid = Binder.getCallingUid();
-            UserHandle targetUser = handleIncomingUser(userHandle, callingUid);
             EXECUTOR.execute(() -> {
                 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
                 AppSearchUserInstance instance = null;
                 int operationSuccessCount = 0;
                 int operationFailureCount = 0;
                 try {
-                    Context targetUserContext = mContext.createContextAsUser(targetUser,
-                            /*flags=*/ 0);
+                    verifyCaller(callingUid, packageName);
+
+                    // Obtain the user where the client wants to run the operations in. This should
+                    // end up being the same as userHandle, assuming it is not a special user and
+                    // the client is allowed to run operations in that user.
+                    UserHandle targetUser = handleIncomingUser(userHandle, callingUid);
                     verifyUserUnlocked(targetUser);
-                    // TODO(b/193902620): Pass in the callingUser and not the targetUser.
-                    verifyCallingPackage(targetUserContext, targetUser, callingUid, packageName);
-                    // TODO(b/194939218): Pass in the callingUser and not the targetUser.
-                    verifyNotInstantApp(targetUserContext, packageName);
+
                     instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
 
                     boolean callerHasSystemAccess =
@@ -804,18 +804,16 @@
             Objects.requireNonNull(callback);
 
             int callingUid = Binder.getCallingUid();
-            UserHandle targetUser = handleIncomingUser(userHandle, callingUid);
-            // TODO(b/162450968) check nextPageToken is being advanced by the same uid as originally
-            // opened it
             EXECUTOR.execute(() -> {
                 try {
-                    Context targetUserContext = mContext.createContextAsUser(targetUser,
-                            /*flags=*/ 0);
+                    verifyCaller(callingUid, packageName);
+
+                    // Obtain the user where the client wants to run the operations in. This should
+                    // end up being the same as userHandle, assuming it is not a special user and
+                    // the client is allowed to run operations in that user.
+                    UserHandle targetUser = handleIncomingUser(userHandle, callingUid);
                     verifyUserUnlocked(targetUser);
-                    // TODO(b/193902620): Pass in the callingUser and not the targetUser.
-                    verifyCallingPackage(targetUserContext, targetUser, callingUid, packageName);
-                    // TODO(b/194939218): Pass in the callingUser and not the targetUser.
-                    verifyNotInstantApp(targetUserContext, packageName);
+
                     AppSearchUserInstance instance =
                             mAppSearchUserInstanceManager.getUserInstance(targetUser);
                     SearchResultPage searchResultPage =
@@ -836,16 +834,16 @@
             Objects.requireNonNull(userHandle);
 
             int callingUid = Binder.getCallingUid();
-            UserHandle targetUser = handleIncomingUser(userHandle, callingUid);
             EXECUTOR.execute(() -> {
                 try {
-                    Context targetUserContext = mContext.createContextAsUser(targetUser,
-                            /*flags=*/ 0);
+                    verifyCaller(callingUid, packageName);
+
+                    // Obtain the user where the client wants to run the operations in. This should
+                    // end up being the same as userHandle, assuming it is not a special user and
+                    // the client is allowed to run operations in that user.
+                    UserHandle targetUser = handleIncomingUser(userHandle, callingUid);
                     verifyUserUnlocked(targetUser);
-                    // TODO(b/193902620): Pass in the callingUser and not the targetUser.
-                    verifyCallingPackage(targetUserContext, targetUser, callingUid, packageName);
-                    // TODO(b/194939218): Pass in the callingUser and not the targetUser.
-                    verifyNotInstantApp(targetUserContext, packageName);
+
                     AppSearchUserInstance instance =
                             mAppSearchUserInstanceManager.getUserInstance(targetUser);
                     instance.getAppSearchImpl().invalidateNextPageToken(packageName, nextPageToken);
@@ -873,16 +871,16 @@
             Objects.requireNonNull(callback);
 
             int callingUid = Binder.getCallingUid();
-            UserHandle targetUser = handleIncomingUser(userHandle, callingUid);
             EXECUTOR.execute(() -> {
                 try {
-                    Context targetUserContext = mContext.createContextAsUser(targetUser,
-                            /*flags=*/ 0);
+                    verifyCaller(callingUid, packageName);
+
+                    // Obtain the user where the client wants to run the operations in. This should
+                    // end up being the same as userHandle, assuming it is not a special user and
+                    // the client is allowed to run operations in that user.
+                    UserHandle targetUser = handleIncomingUser(userHandle, callingUid);
                     verifyUserUnlocked(targetUser);
-                    // TODO(b/193902620): Pass in the callingUser and not the targetUser.
-                    verifyCallingPackage(targetUserContext, targetUser, callingUid, packageName);
-                    // TODO(b/194939218): Pass in the callingUser and not the targetUser.
-                    verifyNotInstantApp(targetUserContext, packageName);
+
                     AppSearchUserInstance instance =
                             mAppSearchUserInstanceManager.getUserInstance(targetUser);
                     // we don't need to append the file. The file is always brand new.
@@ -925,16 +923,16 @@
             Objects.requireNonNull(callback);
 
             int callingUid = Binder.getCallingUid();
-            UserHandle targetUser = handleIncomingUser(userHandle, callingUid);
             EXECUTOR.execute(() -> {
                 try {
-                    Context targetUserContext = mContext.createContextAsUser(targetUser,
-                            /*flags=*/ 0);
+                    verifyCaller(callingUid, packageName);
+
+                    // Obtain the user where the client wants to run the operations in. This should
+                    // end up being the same as userHandle, assuming it is not a special user and
+                    // the client is allowed to run operations in that user.
+                    UserHandle targetUser = handleIncomingUser(userHandle, callingUid);
                     verifyUserUnlocked(targetUser);
-                    // TODO(b/193902620): Pass in the callingUser and not the targetUser.
-                    verifyCallingPackage(targetUserContext, targetUser, callingUid, packageName);
-                    // TODO(b/194939218): Pass in the callingUser and not the targetUser.
-                    verifyNotInstantApp(targetUserContext, packageName);
+
                     AppSearchUserInstance instance =
                             mAppSearchUserInstanceManager.getUserInstance(targetUser);
 
@@ -990,16 +988,16 @@
             Objects.requireNonNull(callback);
 
             int callingUid = Binder.getCallingUid();
-            UserHandle targetUser = handleIncomingUser(userHandle, callingUid);
             EXECUTOR.execute(() -> {
                 try {
-                    Context targetUserContext = mContext.createContextAsUser(targetUser,
-                            /*flags=*/ 0);
+                    verifyCaller(callingUid, packageName);
+
+                    // Obtain the user where the client wants to run the operations in. This should
+                    // end up being the same as userHandle, assuming it is not a special user and
+                    // the client is allowed to run operations in that user.
+                    UserHandle targetUser = handleIncomingUser(userHandle, callingUid);
                     verifyUserUnlocked(targetUser);
-                    // TODO(b/193902620): Pass in the callingUser and not the targetUser.
-                    verifyCallingPackage(targetUserContext, targetUser, callingUid, packageName);
-                    // TODO(b/194939218): Pass in the callingUser and not the targetUser.
-                    verifyNotInstantApp(targetUserContext, packageName);
+
                     AppSearchUserInstance instance =
                             mAppSearchUserInstanceManager.getUserInstance(targetUser);
 
@@ -1040,20 +1038,20 @@
 
             long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
             int callingUid = Binder.getCallingUid();
-            UserHandle targetUser = handleIncomingUser(userHandle, callingUid);
             EXECUTOR.execute(() -> {
                 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
                 AppSearchUserInstance instance = null;
                 int operationSuccessCount = 0;
                 int operationFailureCount = 0;
                 try {
-                    Context targetUserContext = mContext.createContextAsUser(targetUser,
-                            /*flags=*/ 0);
+                    verifyCaller(callingUid, packageName);
+
+                    // Obtain the user where the client wants to run the operations in. This should
+                    // end up being the same as userHandle, assuming it is not a special user and
+                    // the client is allowed to run operations in that user.
+                    UserHandle targetUser = handleIncomingUser(userHandle, callingUid);
                     verifyUserUnlocked(targetUser);
-                    // TODO(b/193902620): Pass in the callingUser and not the targetUser.
-                    verifyCallingPackage(targetUserContext, targetUser, callingUid, packageName);
-                    // TODO(b/194939218): Pass in the callingUser and not the targetUser.
-                    verifyNotInstantApp(targetUserContext, packageName);
+
                     AppSearchBatchResult.Builder<String, Void> resultBuilder =
                             new AppSearchBatchResult.Builder<>();
                     instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
@@ -1129,20 +1127,20 @@
 
             long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
             int callingUid = Binder.getCallingUid();
-            UserHandle targetUser = handleIncomingUser(userHandle, callingUid);
             EXECUTOR.execute(() -> {
                 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
                 AppSearchUserInstance instance = null;
                 int operationSuccessCount = 0;
                 int operationFailureCount = 0;
                 try {
-                    Context targetUserContext = mContext.createContextAsUser(targetUser,
-                            /*flags=*/ 0);
+                    verifyCaller(callingUid, packageName);
+
+                    // Obtain the user where the client wants to run the operations in. This should
+                    // end up being the same as userHandle, assuming it is not a special user and
+                    // the client is allowed to run operations in that user.
+                    UserHandle targetUser = handleIncomingUser(userHandle, callingUid);
                     verifyUserUnlocked(targetUser);
-                    // TODO(b/193902620): Pass in the callingUser and not the targetUser.
-                    verifyCallingPackage(targetUserContext, targetUser, callingUid, packageName);
-                    // TODO(b/194939218): Pass in the callingUser and not the targetUser.
-                    verifyNotInstantApp(targetUserContext, packageName);
+
                     instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
                     instance.getAppSearchImpl().removeByQuery(
                             packageName,
@@ -1196,16 +1194,16 @@
             Objects.requireNonNull(callback);
 
             int callingUid = Binder.getCallingUid();
-            UserHandle targetUser = handleIncomingUser(userHandle, callingUid);
             EXECUTOR.execute(() -> {
                 try {
-                    Context targetUserContext = mContext.createContextAsUser(targetUser,
-                            /*flags=*/ 0);
+                    verifyCaller(callingUid, packageName);
+
+                    // Obtain the user where the client wants to run the operations in. This should
+                    // end up being the same as userHandle, assuming it is not a special user and
+                    // the client is allowed to run operations in that user.
+                    UserHandle targetUser = handleIncomingUser(userHandle, callingUid);
                     verifyUserUnlocked(targetUser);
-                    // TODO(b/193902620): Pass in the callingUser and not the targetUser.
-                    verifyCallingPackage(targetUserContext, targetUser, callingUid, packageName);
-                    // TODO(b/194939218): Pass in the callingUser and not the targetUser.
-                    verifyNotInstantApp(targetUserContext, packageName);
+
                     AppSearchUserInstance instance =
                             mAppSearchUserInstanceManager.getUserInstance(targetUser);
                     StorageInfo storageInfo = instance.getAppSearchImpl()
@@ -1229,20 +1227,20 @@
 
             long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
             int callingUid = Binder.getCallingUid();
-            UserHandle targetUser = handleIncomingUser(userHandle, callingUid);
             EXECUTOR.execute(() -> {
                 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
                 AppSearchUserInstance instance = null;
                 int operationSuccessCount = 0;
                 int operationFailureCount = 0;
                 try {
-                    Context targetUserContext = mContext.createContextAsUser(targetUser,
-                            /*flags=*/ 0);
+                    verifyCaller(callingUid, packageName);
+
+                    // Obtain the user where the client wants to run the operations in. This should
+                    // end up being the same as userHandle, assuming it is not a special user and
+                    // the client is allowed to run operations in that user.
+                    UserHandle targetUser = handleIncomingUser(userHandle, callingUid);
                     verifyUserUnlocked(targetUser);
-                    // TODO(b/193902620): Pass in the callingUser and not the targetUser.
-                    verifyCallingPackage(targetUserContext, targetUser, callingUid, packageName);
-                    // TODO(b/194939218): Pass in the callingUser and not the targetUser.
-                    verifyNotInstantApp(targetUserContext, packageName);
+
                     instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
                     instance.getAppSearchImpl().persistToDisk(PersistType.Code.FULL);
                     ++operationSuccessCount;
@@ -1284,7 +1282,6 @@
 
             long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
             int callingUid = Binder.getCallingUid();
-            UserHandle targetUser = handleIncomingUser(userHandle, callingUid);
 
             EXECUTOR.execute(() -> {
                 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
@@ -1292,13 +1289,16 @@
                 int operationSuccessCount = 0;
                 int operationFailureCount = 0;
                 try {
+                    verifyCaller(callingUid, packageName);
+
+                    // Obtain the user where the client wants to run the operations in. This should
+                    // end up being the same as userHandle, assuming it is not a special user and
+                    // the client is allowed to run operations in that user.
+                    UserHandle targetUser = handleIncomingUser(userHandle, callingUid);
+                    verifyUserUnlocked(targetUser);
+
                     Context targetUserContext = mContext.createContextAsUser(targetUser,
                             /*flags=*/ 0);
-                    verifyUserUnlocked(targetUser);
-                    // TODO(b/193902620): Pass in the callingUser and not the targetUser.
-                    verifyCallingPackage(targetUserContext, targetUser, callingUid, packageName);
-                    // TODO(b/194939218): Pass in the callingUser and not the targetUser.
-                    verifyNotInstantApp(targetUserContext, packageName);
                     instance = mAppSearchUserInstanceManager.getOrCreateUserInstance(
                             targetUserContext, targetUser, AppSearchConfig.getInstance(EXECUTOR));
                     ++operationSuccessCount;
@@ -1329,29 +1329,6 @@
             });
         }
 
-        private void verifyCallingPackage(
-                @NonNull Context userContext,
-                @NonNull UserHandle actualCallingUser,
-                int actualCallingUid,
-                @NonNull String claimedCallingPackage) {
-            Objects.requireNonNull(actualCallingUser);
-            Objects.requireNonNull(claimedCallingPackage);
-
-            int claimedCallingUid = PackageUtil.getPackageUid(
-                    userContext, claimedCallingPackage);
-            if (claimedCallingUid == INVALID_UID) {
-                throw new SecurityException(
-                        "Specified calling package [" + claimedCallingPackage + "] not found");
-            }
-            if (claimedCallingUid != actualCallingUid) {
-                throw new SecurityException(
-                        "Specified calling package ["
-                                + claimedCallingPackage
-                                + "] does not match the calling uid "
-                                + actualCallingUid);
-            }
-        }
-
         /** Invokes the {@link IAppSearchResultCallback} with the result. */
         private void invokeCallbackOnResult(
                 IAppSearchResultCallback callback, AppSearchResult<?> result) {
@@ -1428,10 +1405,49 @@
     }
 
     /**
-     * Helper for ensuring instant apps can't make calls to AppSearch.
+     * Verify various aspects of the calling user.
      *
-     * @param userContext Context of the user making the call.
-     * @param packageName Package name of the caller.
+     * @param callingUid Uid of the caller, usually retrieved from Binder for authenticity.
+     * @param claimedCallingPackage Package name the caller claims to be.
+     */
+    private void verifyCaller(int callingUid, @NonNull String claimedCallingPackage) {
+        // Obtain the user where the client is running in. Note that this could be different from
+        // the userHandle where the client wants to run the AppSearch operation in.
+        UserHandle callingUserHandle = UserHandle.getUserHandleForUid(callingUid);
+        Context callingUserContext = mContext.createContextAsUser(callingUserHandle,
+                /*flags=*/ 0);
+
+        verifyCallingPackage(callingUserContext, callingUid, claimedCallingPackage);
+        verifyNotInstantApp(callingUserContext, claimedCallingPackage);
+    }
+
+    /**
+     * Check that the caller's supposed package name matches the uid making the call.
+     *
+     * @throws SecurityException if the package name and uid don't match.
+     */
+    private void verifyCallingPackage(
+            @NonNull Context actualCallingUserContext,
+            int actualCallingUid,
+            @NonNull String claimedCallingPackage) {
+        int claimedCallingUid = PackageUtil.getPackageUid(
+                actualCallingUserContext, claimedCallingPackage);
+        if (claimedCallingUid == INVALID_UID) {
+            throw new SecurityException(
+                    "Specified calling package [" + claimedCallingPackage + "] not found");
+        }
+        if (claimedCallingUid != actualCallingUid) {
+            throw new SecurityException(
+                    "Specified calling package ["
+                            + claimedCallingPackage
+                            + "] does not match the calling uid "
+                            + actualCallingUid);
+        }
+    }
+
+    /**
+     * Ensure instant apps can't make calls to AppSearch.
+     *
      * @throws SecurityException if the caller is an instant app.
      */
     private void verifyNotInstantApp(@NonNull Context userContext, @NonNull String packageName) {