Fix cross user package visibility leakage for filterAppAccess API

- To fix apis which invoke the #filterAppAccess leak the package
  existence information of other users, this CL returns true if
  the target package is not installed under the given user id.

- Add an extra boolean parameter to the #filterAppAccess API for
  the LauncherApp module to not filter the uninstalled package
  when monitoring package changes events.

- Correct wrong user id usages of the filterAppAccess API in
  some modules.

Bug: 229684723
Test: atest android.content.pm.cts.PackageManagerTest
Test: atest android.appenumeration.cts.AppEnumerationTests
Test: atest android.appwidget.cts.AppWidgetTest
Test: atest com.android.cts.devicepolicy.ManagedProfileCrossProfileTest
Test: atest com.android.cts.devicepolicy.LauncherAppsProfileTest
Test: atest android.devicepolicy.cts.LauncherAppsTests
Change-Id: I3cced4668d1cc4488665c928e4cbe4e194c249cf
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index 40110e7..9466a31 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -1695,7 +1695,7 @@
                         && mSecurityPolicy.isProviderInCallerOrInProfileAndWhitelListed(
                         providerPackageName, providerProfileId)
                         && !mPackageManagerInternal.filterAppAccess(providerPackageName, callingUid,
-                        userId)) {
+                        profileId)) {
                     result.add(cloneIfLocalBinder(info));
                 }
             }
diff --git a/services/core/java/android/content/pm/PackageManagerInternal.java b/services/core/java/android/content/pm/PackageManagerInternal.java
index 7cb7c0b..6063668 100644
--- a/services/core/java/android/content/pm/PackageManagerInternal.java
+++ b/services/core/java/android/content/pm/PackageManagerInternal.java
@@ -737,28 +737,49 @@
     public abstract @Nullable String getInstantAppPackageName(int uid);
 
     /**
-     * Returns whether or not access to the application should be filtered.
+     * Returns whether or not access to the application should be filtered. The access is not
+     * allowed if the application is not installed under the given user.
      * <p>
      * Access may be limited based upon whether the calling or target applications
      * are instant applications.
      *
      * @see #canAccessInstantApps
+     *
+     * @param pkg The package to be accessed.
+     * @param callingUid The uid that attempts to access the package.
+     * @param userId The user id where the package resides.
      */
     public abstract boolean filterAppAccess(
             @NonNull AndroidPackage pkg, int callingUid, int userId);
 
     /**
-     * Returns whether or not access to the application should be filtered.
+     * Returns whether or not access to the application should be filtered. The access is not
+     * allowed if the application is not installed under the given user.
      *
      * @see #filterAppAccess(AndroidPackage, int, int)
      */
+    public boolean filterAppAccess(@NonNull String packageName, int callingUid, int userId) {
+        return filterAppAccess(packageName, callingUid, userId, true /* filterUninstalled */);
+    }
+
+    /**
+     * Returns whether or not access to the application should be filtered.
+     *
+     * @param packageName The package to be accessed.
+     * @param callingUid The uid that attempts to access the package.
+     * @param userId The user id where the package resides.
+     * @param filterUninstalled Set to true to filter the access if the package is not installed
+     *                        under the given user.
+     * @see #filterAppAccess(AndroidPackage, int, int)
+     */
     public abstract boolean filterAppAccess(
-            @NonNull String packageName, int callingUid, int userId);
+            @NonNull String packageName, int callingUid, int userId, boolean filterUninstalled);
 
     /**
      * Returns whether or not access to the application which belongs to the given UID should be
      * filtered. If the UID is part of a shared user ID, return {@code true} if all applications
-     * belong to the shared user ID should be filtered.
+     * belong to the shared user ID should be filtered. The access is not allowed if the uid does
+     * not exist in the device.
      *
      * @see #filterAppAccess(AndroidPackage, int, int)
      */
diff --git a/services/core/java/com/android/server/pm/Computer.java b/services/core/java/com/android/server/pm/Computer.java
index 5a2f6fe..b898b1c 100644
--- a/services/core/java/com/android/server/pm/Computer.java
+++ b/services/core/java/com/android/server/pm/Computer.java
@@ -305,7 +305,8 @@
     SigningDetails getSigningDetails(@NonNull String packageName);
     SigningDetails getSigningDetails(int uid);
     boolean filterAppAccess(AndroidPackage pkg, int callingUid, int userId);
-    boolean filterAppAccess(String packageName, int callingUid, int userId);
+    boolean filterAppAccess(String packageName, int callingUid, int userId,
+            boolean filterUninstalled);
     boolean filterAppAccess(int uid, int callingUid);
     void dump(int type, FileDescriptor fd, PrintWriter pw, DumpState dumpState);
     PackageManagerService.FindPreferredActivityBodyResult findPreferredActivityInternal(
diff --git a/services/core/java/com/android/server/pm/ComputerEngine.java b/services/core/java/com/android/server/pm/ComputerEngine.java
index 5bdc9d8..31847bc 100644
--- a/services/core/java/com/android/server/pm/ComputerEngine.java
+++ b/services/core/java/com/android/server/pm/ComputerEngine.java
@@ -3162,30 +3162,31 @@
 
     public boolean filterAppAccess(AndroidPackage pkg, int callingUid, int userId) {
         PackageStateInternal ps = getPackageStateInternal(pkg.getPackageName());
-        return shouldFilterApplication(ps, callingUid,
-                userId);
+        return shouldFilterApplicationIncludingUninstalled(ps, callingUid, userId);
     }
 
-    public boolean filterAppAccess(String packageName, int callingUid, int userId) {
+    public boolean filterAppAccess(String packageName, int callingUid, int userId,
+            boolean filterUninstalled) {
         PackageStateInternal ps = getPackageStateInternal(packageName);
-        return shouldFilterApplication(ps, callingUid,
-                userId);
+        return shouldFilterApplication(
+                ps, callingUid, null /* component */, TYPE_UNKNOWN, userId, filterUninstalled);
     }
 
     public boolean filterAppAccess(int uid, int callingUid) {
         final int userId = UserHandle.getUserId(uid);
         final int appId = UserHandle.getAppId(uid);
         final Object setting = mSettings.getSettingBase(appId);
-
+        if (setting == null) {
+            return true;
+        }
         if (setting instanceof SharedUserSetting) {
-            return shouldFilterApplication(
+            return shouldFilterApplicationIncludingUninstalled(
                     (SharedUserSetting) setting, callingUid, userId);
-        } else if (setting == null
-                || setting instanceof PackageStateInternal) {
-            return shouldFilterApplication(
+        } else if (setting instanceof PackageStateInternal) {
+            return shouldFilterApplicationIncludingUninstalled(
                     (PackageStateInternal) setting, callingUid, userId);
         }
-        return false;
+        return true;
     }
 
     public void dump(int type, FileDescriptor fd, PrintWriter pw, DumpState dumpState) {
diff --git a/services/core/java/com/android/server/pm/DomainVerificationConnection.java b/services/core/java/com/android/server/pm/DomainVerificationConnection.java
index 20e4dd8..4134671 100644
--- a/services/core/java/com/android/server/pm/DomainVerificationConnection.java
+++ b/services/core/java/com/android/server/pm/DomainVerificationConnection.java
@@ -89,7 +89,8 @@
 
     @Override
     public boolean filterAppAccess(String packageName, int callingUid, int userId) {
-        return mPm.snapshotComputer().filterAppAccess(packageName, callingUid, userId);
+        return mPm.snapshotComputer().filterAppAccess(
+                packageName, callingUid, userId, true /* filterUninstalled */);
     }
 
     @Override
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index 5e0fc3b..59bd427 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -1358,10 +1358,19 @@
                     user.getIdentifier(), debugMsg, false);
         }
 
-        /** Returns whether or not the result to the listener should be filtered. */
-        private boolean isPackageVisibleToListener(String packageName, BroadcastCookie cookie) {
+        /**
+         * Returns whether or not the result to the listener should be filtered.
+         *
+         * @param packageName The package to be accessed by the listener.
+         * @param cookie      The listener
+         * @param user        The user where the package resides.
+         */
+        private boolean isPackageVisibleToListener(String packageName, BroadcastCookie cookie,
+                UserHandle user) {
+            // Do not filter the uninstalled package access since it might break callbacks such as
+            // shortcut changes and unavailable packages events.
             return !mPackageManagerInternal.filterAppAccess(packageName, cookie.callingUid,
-                    cookie.user.getIdentifier());
+                    user.getIdentifier(), false /* filterUninstalled */);
         }
 
         /** Returns whether or not the given appId is in allow list */
@@ -1372,10 +1381,11 @@
             return Arrays.binarySearch(appIdAllowList, appId) > -1;
         }
 
-        private String[] getFilteredPackageNames(String[] packageNames, BroadcastCookie cookie) {
+        private String[] getFilteredPackageNames(String[] packageNames, BroadcastCookie cookie,
+                UserHandle user) {
             final List<String> filteredPackageNames = new ArrayList<>();
             for (String packageName : packageNames) {
-                if (!isPackageVisibleToListener(packageName, cookie)) {
+                if (!isPackageVisibleToListener(packageName, cookie, user)) {
                     continue;
                 }
                 filteredPackageNames.add(packageName);
@@ -1619,7 +1629,7 @@
                         if (!isEnabledProfileOf(cookie.user, user, "onPackageAdded")) {
                             continue;
                         }
-                        if (!isPackageVisibleToListener(packageName, cookie)) {
+                        if (!isPackageVisibleToListener(packageName, cookie, user)) {
                             continue;
                         }
                         try {
@@ -1653,7 +1663,7 @@
                         if (!isEnabledProfileOf(cookie.user, user, "onPackageModified")) {
                             continue;
                         }
-                        if (!isPackageVisibleToListener(packageName, cookie)) {
+                        if (!isPackageVisibleToListener(packageName, cookie, user)) {
                             continue;
                         }
                         try {
@@ -1678,7 +1688,8 @@
                         if (!isEnabledProfileOf(cookie.user, user, "onPackagesAvailable")) {
                             continue;
                         }
-                        final String[] filteredPackages = getFilteredPackageNames(packages, cookie);
+                        final String[] filteredPackages =
+                                getFilteredPackageNames(packages, cookie, user);
                         // If all packages are filtered, skip notifying listener.
                         if (ArrayUtils.isEmpty(filteredPackages)) {
                             continue;
@@ -1707,7 +1718,8 @@
                         if (!isEnabledProfileOf(cookie.user, user, "onPackagesUnavailable")) {
                             continue;
                         }
-                        final String[] filteredPackages = getFilteredPackageNames(packages, cookie);
+                        final String[] filteredPackages =
+                                getFilteredPackageNames(packages, cookie, user);
                         // If all packages are filtered, skip notifying listener.
                         if (ArrayUtils.isEmpty(filteredPackages)) {
                             continue;
@@ -1751,7 +1763,7 @@
                             continue;
                         }
                         final String[] filteredPackagesWithoutExtras =
-                                getFilteredPackageNames(packagesNullExtras, cookie);
+                                getFilteredPackageNames(packagesNullExtras, cookie, user);
                         try {
                             if (!ArrayUtils.isEmpty(filteredPackagesWithoutExtras)) {
                                 listener.onPackagesSuspended(user, filteredPackagesWithoutExtras,
@@ -1759,7 +1771,8 @@
                             }
                             for (int idx = 0; idx < packagesWithExtras.size(); idx++) {
                                 Pair<String, Bundle> packageExtraPair = packagesWithExtras.get(idx);
-                                if (!isPackageVisibleToListener(packageExtraPair.first, cookie)) {
+                                if (!isPackageVisibleToListener(
+                                        packageExtraPair.first, cookie, user)) {
                                     continue;
                                 }
                                 listener.onPackagesSuspended(user,
@@ -1786,7 +1799,8 @@
                         if (!isEnabledProfileOf(cookie.user, user, "onPackagesUnsuspended")) {
                             continue;
                         }
-                        final String[] filteredPackages = getFilteredPackageNames(packages, cookie);
+                        final String[] filteredPackages =
+                                getFilteredPackageNames(packages, cookie, user);
                         // If all packages are filtered, skip notifying listener.
                         if (ArrayUtils.isEmpty(filteredPackages)) {
                             continue;
@@ -1822,7 +1836,7 @@
                         if (!isEnabledProfileOf(cookie.user, user, "onShortcutChanged")) {
                             continue;
                         }
-                        if (!isPackageVisibleToListener(packageName, cookie)) {
+                        if (!isPackageVisibleToListener(packageName, cookie, user)) {
                             continue;
                         }
                         final int launcherUserId = cookie.user.getIdentifier();
@@ -1896,7 +1910,7 @@
                         if (!isEnabledProfileOf(cookie.user, mUser, "onLoadingProgressChanged")) {
                             continue;
                         }
-                        if (!isPackageVisibleToListener(mPackageName, cookie)) {
+                        if (!isPackageVisibleToListener(mPackageName, cookie, mUser)) {
                             continue;
                         }
                         try {
diff --git a/services/core/java/com/android/server/pm/PackageManagerInternalBase.java b/services/core/java/com/android/server/pm/PackageManagerInternalBase.java
index b594866..c8db297 100644
--- a/services/core/java/com/android/server/pm/PackageManagerInternalBase.java
+++ b/services/core/java/com/android/server/pm/PackageManagerInternalBase.java
@@ -122,8 +122,9 @@
 
     @Override
     @Deprecated
-    public final boolean filterAppAccess(String packageName, int callingUid, int userId) {
-        return snapshot().filterAppAccess(packageName, callingUid, userId);
+    public final boolean filterAppAccess(String packageName, int callingUid, int userId,
+            boolean filterUninstalled) {
+        return snapshot().filterAppAccess(packageName, callingUid, userId, filterUninstalled);
     }
 
     @Override
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
index d545d41..ccd9066 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
@@ -524,7 +524,7 @@
 
         final int callingUserId = UserHandle.getUserId(callingUid);
         out.removeIf(it -> mPackageManagerInt.filterAppAccess(it.packageName, callingUid,
-                callingUserId));
+                callingUserId, false /* filterUninstalled */));
         return out;
     }
 
@@ -549,7 +549,7 @@
 
         final int callingUserId = UserHandle.getUserId(callingUid);
         if (mPackageManagerInt.filterAppAccess(permissionGroupInfo.packageName, callingUid,
-                callingUserId)) {
+                callingUserId, false /* filterUninstalled */)) {
             EventLog.writeEvent(0x534e4554, "186113473", callingUid, groupName);
             return null;
         }
@@ -579,7 +579,7 @@
 
         final int callingUserId = UserHandle.getUserId(callingUid);
         if (mPackageManagerInt.filterAppAccess(permissionInfo.packageName, callingUid,
-                callingUserId)) {
+                callingUserId, false /* filterUninstalled */)) {
             EventLog.writeEvent(0x534e4554, "183122164", callingUid, permName);
             return null;
         }
@@ -624,11 +624,12 @@
 
         final int callingUserId = UserHandle.getUserId(callingUid);
         if (permissionGroup != null && mPackageManagerInt.filterAppAccess(
-                permissionGroup.getPackageName(), callingUid, callingUserId)) {
+                permissionGroup.getPackageName(), callingUid, callingUserId,
+                false /* filterUninstalled */)) {
             return null;
         }
         out.removeIf(it -> mPackageManagerInt.filterAppAccess(it.packageName, callingUid,
-                callingUserId));
+                callingUserId, false /* filterUninstalled */));
         return out;
     }
 
@@ -710,7 +711,8 @@
         if (pkg == null) {
             return 0;
         }
-        if (mPackageManagerInt.filterAppAccess(pkg, callingUid, userId)) {
+        if (mPackageManagerInt.filterAppAccess(packageName, callingUid, userId,
+                false /* filterUninstalled */)) {
             return 0;
         }
 
@@ -820,7 +822,8 @@
             Log.e(TAG, "Unknown package: " + packageName);
             return;
         }
-        if (mPackageManagerInt.filterAppAccess(pkg, callingUid, userId)) {
+        if (mPackageManagerInt.filterAppAccess(packageName, callingUid, userId,
+                false /* filterUninstalled */)) {
             throw new IllegalArgumentException("Unknown package: " + packageName);
         }
 
@@ -946,7 +949,8 @@
             @NonNull String permissionName, @UserIdInt int userId) {
         final int callingUid = Binder.getCallingUid();
         if (isPackageExplicit || pkg.getSharedUserId() == null) {
-            if (mPackageManagerInt.filterAppAccess(pkg, callingUid, userId)) {
+            if (mPackageManagerInt.filterAppAccess(pkg.getPackageName(), callingUid, userId,
+                    false /* filterUninstalled */)) {
                 return PackageManager.PERMISSION_DENIED;
             }
         } else {
@@ -1082,7 +1086,8 @@
         }
 
         final int callingUid = Binder.getCallingUid();
-        if (mPackageManagerInt.filterAppAccess(pkg, callingUid, UserHandle.getCallingUserId())) {
+        if (mPackageManagerInt.filterAppAccess(packageName, callingUid,
+                UserHandle.getCallingUserId(), false /* filterUninstalled */)) {
             return null;
         }
         final boolean isCallerPrivileged = mContext.checkCallingOrSelfPermission(
@@ -1196,7 +1201,8 @@
 
         final int callingUid = Binder.getCallingUid();
         final int callingUserId = UserHandle.getUserId(callingUid);
-        if (mPackageManagerInt.filterAppAccess(permissionPackageName, callingUid, callingUserId)) {
+        if (mPackageManagerInt.filterAppAccess(permissionPackageName, callingUid, callingUserId,
+                false /* filterUninstalled */)) {
             EventLog.writeEvent(0x534e4554, "186404356", callingUid, permName);
             return false;
         }
@@ -1254,7 +1260,8 @@
         }
 
         final int callingUid = Binder.getCallingUid();
-        if (mPackageManagerInt.filterAppAccess(pkg, callingUid, UserHandle.getCallingUserId())) {
+        if (mPackageManagerInt.filterAppAccess(packageName, callingUid,
+                UserHandle.getCallingUserId(), false /* filterUninstalled */)) {
             return false;
         }
 
@@ -1353,7 +1360,8 @@
             Log.e(TAG, "Unknown package: " + packageName);
             return;
         }
-        if (mPackageManagerInt.filterAppAccess(pkg, callingUid, userId)) {
+        if (mPackageManagerInt.filterAppAccess(packageName, callingUid, userId,
+                false /* filterUninstalled */)) {
             throw new IllegalArgumentException("Unknown package: " + packageName);
         }
 
@@ -1550,7 +1558,8 @@
             Log.e(TAG, "Unknown package: " + packageName);
             return;
         }
-        if (mPackageManagerInt.filterAppAccess(pkg, callingUid, userId)) {
+        if (mPackageManagerInt.filterAppAccess(packageName, callingUid, userId,
+                false /* filterUninstalled */)) {
             throw new IllegalArgumentException("Unknown package: " + packageName);
         }
 
@@ -1966,7 +1975,8 @@
         }
 
         final int callingUid = Binder.getCallingUid();
-        if (mPackageManagerInt.filterAppAccess(packageName, callingUid, userId)) {
+        if (mPackageManagerInt.filterAppAccess(packageName, callingUid, userId,
+                false /* filterUninstalled */)) {
             return false;
         }