Secure MATCH_UNINSTALLED_PACKAGES across users

Introduce a new internal flag MATCH_ANY_USER for genuine uses
of searching through all apps on the device.

Some temporary accommodations for Launchers that reach across
to the work profile until we have a new LauncherApps API to do
that officially.

Bug: 31000380
Test: CTS tests added
Change-Id: I2e43dc49d6c2e11814a8f8d1eb07ef557f31af34
diff --git a/core/java/android/content/pm/LauncherActivityInfo.java b/core/java/android/content/pm/LauncherActivityInfo.java
index 2beca7b..358787e 100644
--- a/core/java/android/content/pm/LauncherActivityInfo.java
+++ b/core/java/android/content/pm/LauncherActivityInfo.java
@@ -89,6 +89,7 @@
      * @return The label for the activity.
      */
     public CharSequence getLabel() {
+        // TODO: Go through LauncherAppsService
         return mActivityInfo.loadLabel(mPm);
     }
 
@@ -101,6 +102,7 @@
      * @return The drawable associated with the activity.
      */
     public Drawable getIcon(int density) {
+        // TODO: Go through LauncherAppsService
         final int iconRes = mActivityInfo.getIconResource();
         Drawable icon = null;
         // Get the preferred density icon from the app's resources
@@ -144,8 +146,9 @@
      */
     public long getFirstInstallTime() {
         try {
+            // TODO: Go through LauncherAppsService
             return mPm.getPackageInfo(mActivityInfo.packageName,
-                    PackageManager.GET_UNINSTALLED_PACKAGES).firstInstallTime;
+                    PackageManager.MATCH_UNINSTALLED_PACKAGES).firstInstallTime;
         } catch (NameNotFoundException nnfe) {
             // Sorry, can't find package
             return 0;
@@ -171,6 +174,7 @@
         Drawable originalIcon = getIcon(density);
 
         if (originalIcon instanceof BitmapDrawable) {
+            // TODO: Go through LauncherAppsService
             return mPm.getUserBadgedIcon(originalIcon, mUser);
         } else {
             Log.e(TAG, "Unable to create badged icon for " + mActivityInfo);
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index 6b23da9..7fc8044 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -447,12 +447,12 @@
     /**
      * Retrieve all of the information we know about a particular package / application.
      *
-     * @param packageName The package of the application
+     * @param packageName The package name of the application
      * @param flags Additional option flags {@link PackageManager#getApplicationInfo}
      * @param user The UserHandle of the profile.
      *
      * @return An {@link ApplicationInfo} containing information about the package or
-     *         null of the package isn't found.
+     *         null if the package isn't installed for the given user.
      * @hide
      */
     public ApplicationInfo getApplicationInfo(String packageName, @ApplicationInfoFlags int flags,
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 5087bc8..3f052d38 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -435,6 +435,20 @@
     public static final int MATCH_FACTORY_ONLY = 0x00200000;
 
     /**
+     * Allows querying of packages installed for any user, not just the specific one. This flag
+     * is only meant for use by apps that have INTERACT_ACROSS_USERS_FULL permission.
+     * @hide
+     */
+    public static final int MATCH_ANY_USER = 0x00400000;
+
+    /**
+     * Combination of MATCH_ANY_USER and MATCH_UNINSTALLED_PACKAGES to mean any known
+     * package.
+     * @hide
+     */
+    public static final int MATCH_KNOWN_PACKAGES = MATCH_UNINSTALLED_PACKAGES | MATCH_ANY_USER;
+
+    /**
      * Internal flag used to indicate that a system component has done their
      * homework and verified that they correctly handle packages and components
      * that come and go over time. In particular:
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index bb9c18a..a910271 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -478,20 +478,25 @@
     /**
      * Returns true if the package is installed and not hidden, or if the caller
      * explicitly wanted all uninstalled and hidden packages as well.
+     * @param appInfo The applicationInfo of the app being checked.
      */
-    private static boolean checkUseInstalledOrHidden(int flags, PackageUserState state) {
-        return (state.installed && !state.hidden)
-                || (flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0;
+    private static boolean checkUseInstalledOrHidden(int flags, PackageUserState state,
+            ApplicationInfo appInfo) {
+        // If available for the target user, or trying to match uninstalled packages and it's
+        // a system app.
+        return state.isAvailable(flags)
+                || (appInfo != null && appInfo.isSystemApp()
+                        && (flags & PackageManager.MATCH_KNOWN_PACKAGES) != 0);
     }
 
     public static boolean isAvailable(PackageUserState state) {
-        return checkUseInstalledOrHidden(0, state);
+        return checkUseInstalledOrHidden(0, state, null);
     }
 
     public static PackageInfo generatePackageInfo(PackageParser.Package p,
             int gids[], int flags, long firstInstallTime, long lastUpdateTime,
             Set<String> grantedPermissions, PackageUserState state, int userId) {
-        if (!checkUseInstalledOrHidden(flags, state) || !p.isMatch(flags)) {
+        if (!checkUseInstalledOrHidden(flags, state, p.applicationInfo) || !p.isMatch(flags)) {
             return null;
         }
         PackageInfo pi = new PackageInfo();
@@ -5445,7 +5450,7 @@
     public static ApplicationInfo generateApplicationInfo(Package p, int flags,
             PackageUserState state, int userId) {
         if (p == null) return null;
-        if (!checkUseInstalledOrHidden(flags, state) || !p.isMatch(flags)) {
+        if (!checkUseInstalledOrHidden(flags, state, p.applicationInfo) || !p.isMatch(flags)) {
             return null;
         }
         if (!copyNeeded(flags, p, state, null, userId)
@@ -5483,7 +5488,7 @@
     public static ApplicationInfo generateApplicationInfo(ApplicationInfo ai, int flags,
             PackageUserState state, int userId) {
         if (ai == null) return null;
-        if (!checkUseInstalledOrHidden(flags, state)) {
+        if (!checkUseInstalledOrHidden(flags, state, ai)) {
             return null;
         }
         // This is only used to return the ResolverActivity; we will just always
@@ -5549,7 +5554,7 @@
     public static final ActivityInfo generateActivityInfo(Activity a, int flags,
             PackageUserState state, int userId) {
         if (a == null) return null;
-        if (!checkUseInstalledOrHidden(flags, state)) {
+        if (!checkUseInstalledOrHidden(flags, state, a.owner.applicationInfo)) {
             return null;
         }
         if (!copyNeeded(flags, a.owner, state, a.metaData, userId)) {
@@ -5565,7 +5570,7 @@
     public static final ActivityInfo generateActivityInfo(ActivityInfo ai, int flags,
             PackageUserState state, int userId) {
         if (ai == null) return null;
-        if (!checkUseInstalledOrHidden(flags, state)) {
+        if (!checkUseInstalledOrHidden(flags, state, ai.applicationInfo)) {
             return null;
         }
         // This is only used to return the ResolverActivity; we will just always
@@ -5603,7 +5608,7 @@
     public static final ServiceInfo generateServiceInfo(Service s, int flags,
             PackageUserState state, int userId) {
         if (s == null) return null;
-        if (!checkUseInstalledOrHidden(flags, state)) {
+        if (!checkUseInstalledOrHidden(flags, state, s.owner.applicationInfo)) {
             return null;
         }
         if (!copyNeeded(flags, s.owner, state, s.metaData, userId)) {
@@ -5652,7 +5657,7 @@
     public static final ProviderInfo generateProviderInfo(Provider p, int flags,
             PackageUserState state, int userId) {
         if (p == null) return null;
-        if (!checkUseInstalledOrHidden(flags, state)) {
+        if (!checkUseInstalledOrHidden(flags, state, p.owner.applicationInfo)) {
             return null;
         }
         if (!copyNeeded(flags, p.owner, state, p.metaData, userId)
diff --git a/core/java/android/content/pm/PackageUserState.java b/core/java/android/content/pm/PackageUserState.java
index 8ce8a13..1821458 100644
--- a/core/java/android/content/pm/PackageUserState.java
+++ b/core/java/android/content/pm/PackageUserState.java
@@ -29,7 +29,6 @@
 
 import android.util.ArraySet;
 
-import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.ArrayUtils;
 
 /**
@@ -80,9 +79,14 @@
     /**
      * Test if this package is installed.
      */
-    public boolean isInstalled(int flags) {
-        return (this.installed && !this.hidden)
-                || (flags & PackageManager.MATCH_UNINSTALLED_PACKAGES) != 0;
+    public boolean isAvailable(int flags) {
+        // True if it is installed for this user and it is not hidden. If it is hidden,
+        // still return true if the caller requested MATCH_UNINSTALLED_PACKAGES
+        final boolean matchAnyUser = (flags & PackageManager.MATCH_ANY_USER) != 0;
+        final boolean matchUninstalled = (flags & PackageManager.MATCH_UNINSTALLED_PACKAGES) != 0;
+        return matchAnyUser
+                || (this.installed
+                        && (!this.hidden || matchUninstalled));
     }
 
     /**
@@ -95,11 +99,14 @@
      * </p>
      */
     public boolean isMatch(ComponentInfo componentInfo, int flags) {
-        if (!isInstalled(flags)) return false;
+        final boolean isSystemApp = componentInfo.applicationInfo.isSystemApp();
+        final boolean matchUninstalled = (flags & PackageManager.MATCH_KNOWN_PACKAGES) != 0;
+        if (!isAvailable(flags)
+                && !(isSystemApp && matchUninstalled)) return false;
         if (!isEnabled(componentInfo, flags)) return false;
 
         if ((flags & MATCH_SYSTEM_ONLY) != 0) {
-            if (!componentInfo.applicationInfo.isSystemApp()) {
+            if (!isSystemApp) {
                 return false;
             }
         }
diff --git a/core/java/android/service/notification/StatusBarNotification.java b/core/java/android/service/notification/StatusBarNotification.java
index dfb6b86..b0b2065 100644
--- a/core/java/android/service/notification/StatusBarNotification.java
+++ b/core/java/android/service/notification/StatusBarNotification.java
@@ -349,7 +349,8 @@
         if (mContext == null) {
             try {
                 ApplicationInfo ai = context.getPackageManager()
-                        .getApplicationInfo(pkg, PackageManager.GET_UNINSTALLED_PACKAGES);
+                        .getApplicationInfoAsUser(pkg, PackageManager.MATCH_UNINSTALLED_PACKAGES,
+                                getUserId());
                 mContext = context.createApplicationContext(ai,
                         Context.CONTEXT_RESTRICTED);
             } catch (PackageManager.NameNotFoundException e) {
diff --git a/core/java/com/android/internal/content/PackageHelper.java b/core/java/com/android/internal/content/PackageHelper.java
index a3134b3b..98d87d3 100644
--- a/core/java/com/android/internal/content/PackageHelper.java
+++ b/core/java/com/android/internal/content/PackageHelper.java
@@ -355,7 +355,7 @@
         ApplicationInfo existingInfo = null;
         try {
             existingInfo = context.getPackageManager().getApplicationInfo(packageName,
-                    PackageManager.GET_UNINSTALLED_PACKAGES);
+                    PackageManager.MATCH_ANY_USER);
         } catch (NameNotFoundException ignored) {
         }
 
@@ -445,7 +445,7 @@
         ApplicationInfo existingInfo = null;
         try {
             existingInfo = context.getPackageManager().getApplicationInfo(packageName,
-                    PackageManager.GET_UNINSTALLED_PACKAGES);
+                    PackageManager.MATCH_ANY_USER);
         } catch (NameNotFoundException ignored) {
         }
 
diff --git a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
index a15cba0..33a0493 100644
--- a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
+++ b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
@@ -620,7 +620,7 @@
                 try {
                     pkgInfo = pm.getPackageInfo(pkg,
                             PackageManager.GET_PERMISSIONS
-                            | PackageManager.GET_UNINSTALLED_PACKAGES);
+                            | PackageManager.MATCH_UNINSTALLED_PACKAGES);
                 } catch (NameNotFoundException e) {
                     pkgInfo = null;
                 }
@@ -712,7 +712,7 @@
             // Make sure the package doesn't exist
             try {
                 ApplicationInfo appInfo = pm.getApplicationInfo(pkg.packageName,
-                        PackageManager.GET_UNINSTALLED_PACKAGES);
+                        PackageManager.MATCH_UNINSTALLED_PACKAGES);
                 GenericReceiver receiver = new DeleteReceiver(pkg.packageName);
                 invokeDeletePackage(pkg.packageName, 0, receiver);
             } catch (NameNotFoundException e) {
@@ -974,7 +974,7 @@
     public boolean invokeDeletePackage(final String pkgName, int flags, GenericReceiver receiver)
             throws Exception {
         ApplicationInfo info = getPm().getApplicationInfo(pkgName,
-                PackageManager.GET_UNINSTALLED_PACKAGES);
+                PackageManager.MATCH_UNINSTALLED_PACKAGES);
 
         mContext.registerReceiver(receiver, receiver.filter);
         try {
@@ -1019,7 +1019,7 @@
             Log.i(TAG, "okay4");
             try {
                 info = getPm().getApplicationInfo(ip.pkg.packageName,
-                        PackageManager.GET_UNINSTALLED_PACKAGES);
+                        PackageManager.MATCH_UNINSTALLED_PACKAGES);
             } catch (NameNotFoundException e) {
                 info = null;
             }
@@ -1323,7 +1323,7 @@
 
         ApplicationInfo info = null;
         try {
-            info = getPm().getApplicationInfo(packageName, PackageManager.GET_UNINSTALLED_PACKAGES);
+            info = getPm().getApplicationInfo(packageName, PackageManager.MATCH_UNINSTALLED_PACKAGES);
         } catch (NameNotFoundException ignored) {
         }
 
@@ -1350,7 +1350,7 @@
         Log.i(TAG, "Deleting package : " + pkgName);
         try {
             ApplicationInfo info = getPm().getApplicationInfo(pkgName,
-                    PackageManager.GET_UNINSTALLED_PACKAGES);
+                    PackageManager.MATCH_UNINSTALLED_PACKAGES);
 
             if (info != null) {
                 DeleteObserver observer = new DeleteObserver(pkgName);
@@ -3756,7 +3756,7 @@
 
     public void testGetUnInstalledPackages() throws Exception {
         List<PackageInfo> packages = getPm().getInstalledPackages(
-                PackageManager.GET_UNINSTALLED_PACKAGES);
+                PackageManager.MATCH_UNINSTALLED_PACKAGES);
         assertNotNull("installed packages cannot be null", packages);
         assertTrue("installed packages cannot be empty", packages.size() > 0);
     }
@@ -3769,7 +3769,7 @@
                 | PackageManager.GET_CONFIGURATIONS | PackageManager.GET_INSTRUMENTATION
                 | PackageManager.GET_PERMISSIONS | PackageManager.GET_PROVIDERS
                 | PackageManager.GET_RECEIVERS | PackageManager.GET_SERVICES
-                | PackageManager.GET_SIGNATURES | PackageManager.GET_UNINSTALLED_PACKAGES;
+                | PackageManager.GET_SIGNATURES | PackageManager.MATCH_UNINSTALLED_PACKAGES;
 
         final InstallParams ip =
                 installFromRawResource("install.apk", R.raw.install_complete_package_info,
@@ -3809,12 +3809,12 @@
      * flags when the GET_UNINSTALLED_PACKAGES flag is set.
      */
     public void testGetUnInstalledPackagesAll() throws Exception {
-        final int flags = PackageManager.GET_UNINSTALLED_PACKAGES
+        final int flags = PackageManager.MATCH_UNINSTALLED_PACKAGES
                 | PackageManager.GET_ACTIVITIES | PackageManager.GET_GIDS
                 | PackageManager.GET_CONFIGURATIONS | PackageManager.GET_INSTRUMENTATION
                 | PackageManager.GET_PERMISSIONS | PackageManager.GET_PROVIDERS
                 | PackageManager.GET_RECEIVERS | PackageManager.GET_SERVICES
-                | PackageManager.GET_SIGNATURES | PackageManager.GET_UNINSTALLED_PACKAGES;
+                | PackageManager.GET_SIGNATURES;
 
         // first, install the package
         final InstallParams ip =
diff --git a/graphics/java/android/graphics/drawable/Icon.java b/graphics/java/android/graphics/drawable/Icon.java
index 2b950d3..9772009 100644
--- a/graphics/java/android/graphics/drawable/Icon.java
+++ b/graphics/java/android/graphics/drawable/Icon.java
@@ -299,7 +299,7 @@
                         final PackageManager pm = context.getPackageManager();
                         try {
                             ApplicationInfo ai = pm.getApplicationInfo(
-                                    resPackage, PackageManager.GET_UNINSTALLED_PACKAGES);
+                                    resPackage, PackageManager.MATCH_UNINSTALLED_PACKAGES);
                             if (ai != null) {
                                 mObj1 = pm.getResourcesForApplication(ai);
                             } else {
diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
index f0ec1078..2b1582d 100644
--- a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
+++ b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
@@ -135,11 +135,11 @@
         mBackgroundHandler = new BackgroundHandler(mThread.getLooper());
 
         // Only the owner can see all apps.
-        mAdminRetrieveFlags = PackageManager.GET_UNINSTALLED_PACKAGES |
-                PackageManager.GET_DISABLED_COMPONENTS |
-                PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS;
-        mRetrieveFlags = PackageManager.GET_DISABLED_COMPONENTS |
-                PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS;
+        mAdminRetrieveFlags = PackageManager.MATCH_ANY_USER |
+                PackageManager.MATCH_DISABLED_COMPONENTS |
+                PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS;
+        mRetrieveFlags = PackageManager.MATCH_DISABLED_COMPONENTS |
+                PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS;
 
         /**
          * This is a trick to prevent the foreground thread from being delayed.
@@ -855,7 +855,7 @@
                         // explicitly include both direct boot aware and unaware components here.
                         List<ResolveInfo> intents = mPm.queryIntentActivitiesAsUser(
                                 launchIntent,
-                                PackageManager.GET_DISABLED_COMPONENTS
+                                PackageManager.MATCH_DISABLED_COMPONENTS
                                         | PackageManager.MATCH_DIRECT_BOOT_AWARE
                                         | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
                                 userId
diff --git a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageMeasurement.java b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageMeasurement.java
index 5c577f8..e520319 100644
--- a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageMeasurement.java
+++ b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageMeasurement.java
@@ -409,8 +409,8 @@
         // Measure all apps hosted on this volume for all users
         if (mVolume.getType() == VolumeInfo.TYPE_PRIVATE) {
             final List<ApplicationInfo> apps = packageManager.getInstalledApplications(
-                    PackageManager.GET_UNINSTALLED_PACKAGES
-                    | PackageManager.GET_DISABLED_COMPONENTS);
+                    PackageManager.MATCH_ANY_USER
+                    | PackageManager.MATCH_DISABLED_COMPONENTS);
 
             final List<ApplicationInfo> volumeApps = new ArrayList<>();
             for (ApplicationInfo app : apps) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/users/AppRestrictionsHelper.java b/packages/SettingsLib/src/com/android/settingslib/users/AppRestrictionsHelper.java
index c189e1d..c4aa57d 100644
--- a/packages/SettingsLib/src/com/android/settingslib/users/AppRestrictionsHelper.java
+++ b/packages/SettingsLib/src/com/android/settingslib/users/AppRestrictionsHelper.java
@@ -112,7 +112,7 @@
             // Enable selected apps
             try {
                 ApplicationInfo info = mIPm.getApplicationInfo(packageName,
-                        PackageManager.MATCH_UNINSTALLED_PACKAGES, userId);
+                        PackageManager.MATCH_ANY_USER, userId);
                 if (info == null || !info.enabled
                         || (info.flags&ApplicationInfo.FLAG_INSTALLED) == 0) {
                     mIPm.installExistingPackageAsUser(packageName, mUser.getIdentifier());
@@ -178,7 +178,7 @@
         addSystemApps(mVisibleApps, widgetIntent, excludePackages);
 
         List<ApplicationInfo> installedApps = pm.getInstalledApplications(
-                PackageManager.MATCH_UNINSTALLED_PACKAGES);
+                PackageManager.MATCH_ANY_USER);
         for (ApplicationInfo app : installedApps) {
             // If it's not installed, skip
             if ((app.flags & ApplicationInfo.FLAG_INSTALLED) == 0) continue;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index f5ca678..414ebec 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -1073,8 +1073,8 @@
         int appUid = -1;
         try {
             final ApplicationInfo info = pmUser.getApplicationInfo(pkg,
-                    PackageManager.GET_UNINSTALLED_PACKAGES
-                            | PackageManager.GET_DISABLED_COMPONENTS);
+                    PackageManager.MATCH_UNINSTALLED_PACKAGES
+                            | PackageManager.MATCH_DISABLED_COMPONENTS);
             if (info != null) {
                 appname = String.valueOf(pmUser.getApplicationLabel(info));
                 pkgicon = pmUser.getApplicationIcon(info);
@@ -1643,8 +1643,8 @@
             String appname = pkg;
             try {
                 final ApplicationInfo info = pmUser.getApplicationInfo(pkg,
-                        PackageManager.GET_UNINSTALLED_PACKAGES
-                                | PackageManager.GET_DISABLED_COMPONENTS);
+                        PackageManager.MATCH_UNINSTALLED_PACKAGES
+                                | PackageManager.MATCH_DISABLED_COMPONENTS);
                 if (info != null) {
                     appname = String.valueOf(pmUser.getApplicationLabel(info));
                 }
diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java
index 07322fc..8092b4a 100644
--- a/services/core/java/com/android/server/DeviceIdleController.java
+++ b/services/core/java/com/android/server/DeviceIdleController.java
@@ -1430,7 +1430,7 @@
         synchronized (this) {
             try {
                 ApplicationInfo ai = getContext().getPackageManager().getApplicationInfo(name,
-                        PackageManager.MATCH_UNINSTALLED_PACKAGES);
+                        PackageManager.MATCH_ANY_USER);
                 if (mPowerSaveWhitelistUserApps.put(name, UserHandle.getAppId(ai.uid)) == null) {
                     reportPowerSaveWhitelistChangedLocked();
                     updateWhitelistAppIdsLocked();
@@ -2396,7 +2396,7 @@
                     if (name != null) {
                         try {
                             ApplicationInfo ai = pm.getApplicationInfo(name,
-                                    PackageManager.MATCH_UNINSTALLED_PACKAGES);
+                                    PackageManager.MATCH_ANY_USER);
                             mPowerSaveWhitelistUserApps.put(ai.packageName,
                                     UserHandle.getAppId(ai.uid));
                         } catch (PackageManager.NameNotFoundException e) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index dce0378..dd339db 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -275,6 +275,7 @@
 import static android.content.pm.PackageManager.FEATURE_LEANBACK_ONLY;
 import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE;
 import static android.content.pm.PackageManager.GET_PROVIDERS;
+import static android.content.pm.PackageManager.MATCH_ANY_USER;
 import static android.content.pm.PackageManager.MATCH_DEBUG_TRIAGED_MISSING;
 import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE;
 import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
@@ -14430,7 +14431,7 @@
         if (dumpPackage != null) {
             IPackageManager pm = AppGlobals.getPackageManager();
             try {
-                dumpUid = pm.getPackageUid(dumpPackage, MATCH_UNINSTALLED_PACKAGES, 0);
+                dumpUid = pm.getPackageUid(dumpPackage, MATCH_ANY_USER, 0);
             } catch (RemoteException e) {
             }
         }
@@ -15407,7 +15408,7 @@
             if (dumpPackage != null) {
                 try {
                     dumpUid = mContext.getPackageManager().getPackageUidAsUser(dumpPackage,
-                            MATCH_UNINSTALLED_PACKAGES, 0);
+                            MATCH_ANY_USER, 0);
                 } catch (NameNotFoundException e) {
                     dumpUid = -1;
                 }
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index 67cac47..0ea78b3 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -1283,7 +1283,7 @@
 
         if (useCheckinFormat) {
             List<ApplicationInfo> apps = mContext.getPackageManager().getInstalledApplications(
-                    PackageManager.MATCH_UNINSTALLED_PACKAGES | PackageManager.MATCH_ALL);
+                    PackageManager.MATCH_ANY_USER | PackageManager.MATCH_ALL);
             if (isRealCheckin) {
                 // For a real checkin, first we want to prefer to use the last complete checkin
                 // file if there is one.
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index 86e3ccc..0bc12ee 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -1417,8 +1417,8 @@
                 try {
                     ApplicationInfo ai = pm.getApplicationInfo(
                             checkIntent.getComponent().getPackageName(),
-                            PackageManager.GET_UNINSTALLED_PACKAGES
-                                    | PackageManager.GET_DISABLED_COMPONENTS, userId);
+                            PackageManager.MATCH_UNINSTALLED_PACKAGES
+                                    | PackageManager.MATCH_DISABLED_COMPONENTS, userId);
                     if (ai != null) {
                         effectiveUid = ai.uid;
                     }
diff --git a/services/core/java/com/android/server/firewall/SenderPackageFilter.java b/services/core/java/com/android/server/firewall/SenderPackageFilter.java
index 91c9671..2184245 100644
--- a/services/core/java/com/android/server/firewall/SenderPackageFilter.java
+++ b/services/core/java/com/android/server/firewall/SenderPackageFilter.java
@@ -47,7 +47,7 @@
         try {
             // USER_SYSTEM here is not important. Only app id is used and getPackageUid() will
             // return a uid whether the app is installed for a user or not.
-            packageUid = pm.getPackageUid(mPackageName, PackageManager.MATCH_UNINSTALLED_PACKAGES,
+            packageUid = pm.getPackageUid(mPackageName, PackageManager.MATCH_ANY_USER,
                     UserHandle.USER_SYSTEM);
         } catch (RemoteException ex) {
             // handled below
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index c99d8be..f42c5be 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -1820,7 +1820,7 @@
                 String pkg = args[opti];
                 try {
                     filterUid = getContext().getPackageManager().getPackageUid(pkg,
-                            PackageManager.MATCH_UNINSTALLED_PACKAGES);
+                            PackageManager.MATCH_ANY_USER);
                 } catch (NameNotFoundException ignored) {
                     pw.println("Invalid package: " + pkg);
                     return;
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index c1506b9..533307e 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -2720,7 +2720,7 @@
             // update rules for all installed applications
             final List<UserInfo> users = mUserManager.getUsers();
             final List<ApplicationInfo> apps = pm.getInstalledApplications(
-                    PackageManager.MATCH_UNINSTALLED_PACKAGES | PackageManager.MATCH_DISABLED_COMPONENTS
+                    PackageManager.MATCH_ANY_USER | PackageManager.MATCH_DISABLED_COMPONENTS
                             | PackageManager.MATCH_DIRECT_BOOT_AWARE
                             | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
 
diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index 4658c046..8ca6086 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -1212,7 +1212,8 @@
         // Build list of UIDs that we should clean up
         int[] uids = new int[0];
         final List<ApplicationInfo> apps = mContext.getPackageManager().getInstalledApplications(
-                PackageManager.GET_UNINSTALLED_PACKAGES | PackageManager.GET_DISABLED_COMPONENTS);
+                PackageManager.MATCH_ANY_USER
+                | PackageManager.MATCH_DISABLED_COMPONENTS);
         for (ApplicationInfo app : apps) {
             final int uid = UserHandle.getUid(userId, app.uid);
             uids = ArrayUtils.appendInt(uids, uid);
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index 29fa754..66fb976 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -595,7 +595,7 @@
                     if (RULE_INSTANCE_GRACE_PERIOD < (currentTime - rule.creationTime)) {
                         try {
                             mPm.getPackageInfo(rule.component.getPackageName(),
-                                    PackageManager.MATCH_UNINSTALLED_PACKAGES);
+                                    PackageManager.MATCH_ANY_USER);
                         } catch (PackageManager.NameNotFoundException e) {
                             newConfig.automaticRules.removeAt(i);
                         }
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 3490503..dc25ce4 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -59,11 +59,13 @@
 import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER;
 import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
 import static android.content.pm.PackageManager.MATCH_ALL;
+import static android.content.pm.PackageManager.MATCH_ANY_USER;
 import static android.content.pm.PackageManager.MATCH_DEBUG_TRIAGED_MISSING;
 import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE;
 import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
 import static android.content.pm.PackageManager.MATCH_DISABLED_COMPONENTS;
 import static android.content.pm.PackageManager.MATCH_FACTORY_ONLY;
+import static android.content.pm.PackageManager.MATCH_KNOWN_PACKAGES;
 import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
 import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES;
 import static android.content.pm.PackageManager.MOVE_FAILED_DEVICE_ADMIN;
@@ -100,6 +102,7 @@
 import android.Manifest;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UserIdInt;
 import android.app.ActivityManager;
 import android.app.AppOpsManager;
 import android.app.IActivityManager;
@@ -3140,6 +3143,11 @@
                 ? Collections.<String>emptySet() : permissionsState.getPermissions(userId);
         final PackageUserState state = ps.readUserState(userId);
 
+        if ((flags & MATCH_UNINSTALLED_PACKAGES) != 0
+                && ps.isSystem()) {
+            flags |= MATCH_ANY_USER;
+        }
+
         return PackageParser.generatePackageInfo(p, gids, flags,
                 ps.firstInstallTime, ps.lastUpdateTime, permissions, state, userId);
     }
@@ -3221,7 +3229,7 @@
             if (p != null) {
                 return generatePackageInfo((PackageSetting)p.mExtras, flags, userId);
             }
-            if (!matchFactoryOnly && (flags & MATCH_UNINSTALLED_PACKAGES) != 0) {
+            if (!matchFactoryOnly && (flags & MATCH_KNOWN_PACKAGES) != 0) {
                 final PackageSetting ps = mSettings.mPackages.get(packageName);
                 return generatePackageInfo(ps, flags, userId);
             }
@@ -3268,7 +3276,7 @@
             if (p != null && p.isMatch(flags)) {
                 return UserHandle.getUid(userId, p.applicationInfo.uid);
             }
-            if ((flags & MATCH_UNINSTALLED_PACKAGES) != 0) {
+            if ((flags & MATCH_KNOWN_PACKAGES) != 0) {
                 final PackageSetting ps = mSettings.mPackages.get(packageName);
                 if (ps != null && ps.isMatch(flags)) {
                     return UserHandle.getUid(userId, ps.appId);
@@ -3292,9 +3300,11 @@
             final PackageParser.Package p = mPackages.get(packageName);
             if (p != null && p.isMatch(flags)) {
                 PackageSetting ps = (PackageSetting) p.mExtras;
+                // TODO: Shouldn't this be checking for package installed state for userId and
+                // return null?
                 return ps.getPermissionsState().computeGids(userId);
             }
-            if ((flags & MATCH_UNINSTALLED_PACKAGES) != 0) {
+            if ((flags & MATCH_KNOWN_PACKAGES) != 0) {
                 final PackageSetting ps = mSettings.mPackages.get(packageName);
                 if (ps != null && ps.isMatch(flags)) {
                     return ps.getPermissionsState().computeGids(userId);
@@ -3418,7 +3428,7 @@
             if ("android".equals(packageName)||"system".equals(packageName)) {
                 return mAndroidApplication;
             }
-            if ((flags & MATCH_UNINSTALLED_PACKAGES) != 0) {
+            if ((flags & MATCH_KNOWN_PACKAGES) != 0) {
                 return generateApplicationInfoFromSettingsLPw(packageName, flags, userId);
             }
         }
@@ -3527,6 +3537,7 @@
      * Update given flags when being used to request {@link PackageInfo}.
      */
     private int updateFlagsForPackage(int flags, int userId, Object cookie) {
+        final boolean isCallerSystemUser = UserHandle.getCallingUserId() == UserHandle.USER_SYSTEM;
         boolean triaged = true;
         if ((flags & (PackageManager.GET_ACTIVITIES | PackageManager.GET_RECEIVERS
                 | PackageManager.GET_SERVICES | PackageManager.GET_PROVIDERS)) != 0) {
@@ -3543,6 +3554,18 @@
                 | PackageManager.MATCH_DEBUG_TRIAGED_MISSING)) == 0) {
             triaged = false;
         }
+        if ((flags & PackageManager.MATCH_ANY_USER) != 0) {
+            enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false,
+                    "MATCH_ANY_USER flag requires INTERACT_ACROSS_USERS permission at "
+                    + Debug.getCallers(5));
+        } else if ((flags & PackageManager.MATCH_UNINSTALLED_PACKAGES) != 0 && isCallerSystemUser
+                && sUserManager.hasManagedProfile(UserHandle.USER_SYSTEM)) {
+            // If the caller wants all packages and has a restricted profile associated with it,
+            // then match all users. This is to make sure that launchers that need to access work
+            // profile apps don't start breaking. TODO: Remove this hack when launchers stop using
+            // MATCH_UNINSTALLED_PACKAGES to query apps in other profiles. b/31000380
+            flags |= PackageManager.MATCH_ANY_USER;
+        }
         if (DEBUG_TRIAGED_MISSING && (Binder.getCallingUid() == Process.SYSTEM_UID) && !triaged) {
             Log.w(TAG, "Caller hasn't been triaged for missing apps; they asked about " + cookie
                     + " with flags 0x" + Integer.toHexString(flags), new Throwable());
@@ -6299,7 +6322,7 @@
     public ParceledListSlice<PackageInfo> getInstalledPackages(int flags, int userId) {
         if (!sUserManager.exists(userId)) return ParceledListSlice.emptyList();
         flags = updateFlagsForPackage(flags, userId, null);
-        final boolean listUninstalled = (flags & MATCH_UNINSTALLED_PACKAGES) != 0;
+        final boolean listUninstalled = (flags & MATCH_KNOWN_PACKAGES) != 0;
         enforceCrossUserPermission(Binder.getCallingUid(), userId,
                 true /* requireFullPermission */, false /* checkShell */,
                 "get installed packages");
@@ -6383,7 +6406,10 @@
             String[] permissions, int flags, int userId) {
         if (!sUserManager.exists(userId)) return ParceledListSlice.emptyList();
         flags = updateFlagsForPackage(flags, userId, permissions);
-        final boolean listUninstalled = (flags & MATCH_UNINSTALLED_PACKAGES) != 0;
+        enforceCrossUserPermission(Binder.getCallingUid(), userId,
+                true /* requireFullPermission */, false /* checkShell */,
+                "get packages holding permissions");
+        final boolean listUninstalled = (flags & MATCH_KNOWN_PACKAGES) != 0;
 
         // writer
         synchronized (mPackages) {
@@ -6391,7 +6417,8 @@
             boolean[] tmpBools = new boolean[permissions.length];
             if (listUninstalled) {
                 for (PackageSetting ps : mSettings.mPackages.values()) {
-                    addPackageHoldingPermissions(list, ps, permissions, tmpBools, flags, userId);
+                    addPackageHoldingPermissions(list, ps, permissions, tmpBools, flags,
+                            userId);
                 }
             } else {
                 for (PackageParser.Package pkg : mPackages.values()) {
@@ -6411,7 +6438,7 @@
     public ParceledListSlice<ApplicationInfo> getInstalledApplications(int flags, int userId) {
         if (!sUserManager.exists(userId)) return ParceledListSlice.emptyList();
         flags = updateFlagsForApplication(flags, userId, null);
-        final boolean listUninstalled = (flags & MATCH_UNINSTALLED_PACKAGES) != 0;
+        final boolean listUninstalled = (flags & MATCH_KNOWN_PACKAGES) != 0;
 
         // writer
         synchronized (mPackages) {
@@ -6420,11 +6447,16 @@
                 list = new ArrayList<ApplicationInfo>(mSettings.mPackages.size());
                 for (PackageSetting ps : mSettings.mPackages.values()) {
                     ApplicationInfo ai;
+                    int effectiveFlags = flags;
+                    if (ps.isSystem()) {
+                        effectiveFlags |= PackageManager.MATCH_ANY_USER;
+                    }
                     if (ps.pkg != null) {
-                        ai = PackageParser.generateApplicationInfo(ps.pkg, flags,
+                        ai = PackageParser.generateApplicationInfo(ps.pkg, effectiveFlags,
                                 ps.readUserState(userId), userId);
                     } else {
-                        ai = generateApplicationInfoFromSettingsLPw(ps.name, flags, userId);
+                        ai = generateApplicationInfoFromSettingsLPw(ps.name, effectiveFlags,
+                                userId);
                     }
                     if (ai != null) {
                         list.add(ai);
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 834d343..fd2b504 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -610,7 +610,7 @@
                         showUid = true;
                         break;
                     case "-u":
-                        getFlags |= PackageManager.GET_UNINSTALLED_PACKAGES;
+                        getFlags |= PackageManager.MATCH_UNINSTALLED_PACKAGES;
                         break;
                     case "-3":
                         listThirdParty = true;
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 20afed7..c4241e7 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -2716,7 +2716,7 @@
     public Bundle getApplicationRestrictionsForUser(String packageName, int userId) {
         if (UserHandle.getCallingUserId() != userId
                 || !UserHandle.isSameApp(Binder.getCallingUid(), getUidForPackage(packageName))) {
-            checkSystemOrRoot("get application restrictions for other users/apps");
+            checkSystemOrRoot("get application restrictions for other user/app " + packageName);
         }
         synchronized (mPackagesLock) {
             // Read the restrictions from XML
@@ -2751,7 +2751,7 @@
         long ident = Binder.clearCallingIdentity();
         try {
             return mContext.getPackageManager().getApplicationInfo(packageName,
-                    PackageManager.MATCH_UNINSTALLED_PACKAGES).uid;
+                    PackageManager.MATCH_ANY_USER).uid;
         } catch (NameNotFoundException nnfe) {
             return -1;
         } finally {
@@ -3717,4 +3717,23 @@
         }
         return 0;
     }
+
+    /**
+     * Checks if the given user has a managed profile associated with it.
+     * @param userId The parent user
+     * @return
+     */
+    boolean hasManagedProfile(int userId) {
+        synchronized (mUsersLock) {
+            UserInfo userInfo = getUserInfoLU(userId);
+            final int userSize = mUsers.size();
+            for (int i = 0; i < userSize; i++) {
+                UserInfo profile = mUsers.valueAt(i).info;
+                if (userId != profile.id && isProfileOf(userInfo, profile)) {
+                    return true;
+                }
+            }
+            return false;
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/webkit/SystemImpl.java b/services/core/java/com/android/server/webkit/SystemImpl.java
index 61319cf..7ba95a4 100644
--- a/services/core/java/com/android/server/webkit/SystemImpl.java
+++ b/services/core/java/com/android/server/webkit/SystemImpl.java
@@ -291,5 +291,5 @@
     // flags declaring we want extra info from the package manager for webview providers
     private final static int PACKAGE_FLAGS = PackageManager.GET_META_DATA
             | PackageManager.GET_SIGNATURES | PackageManager.MATCH_DEBUG_TRIAGED_MISSING
-            | PackageManager.MATCH_UNINSTALLED_PACKAGES;
+            | PackageManager.MATCH_ANY_USER;
 }
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 2f27201..b922261 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -20,7 +20,7 @@
 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_COMPLEX;
 import static android.app.admin.DevicePolicyManager.WIPE_EXTERNAL_STORAGE;
 import static android.app.admin.DevicePolicyManager.WIPE_RESET_PROTECTION_DATA;
-import static android.content.pm.PackageManager.GET_UNINSTALLED_PACKAGES;
+import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES;
 
 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PROVISIONING_ENTRY_POINT_ADB;
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW;
@@ -7032,7 +7032,8 @@
                 boolean systemService = false;
                 try {
                     ApplicationInfo applicationInfo = mIPackageManager.getApplicationInfo(
-                            enabledPackage, PackageManager.GET_UNINSTALLED_PACKAGES, userIdToCheck);
+                            enabledPackage, PackageManager.MATCH_UNINSTALLED_PACKAGES,
+                            userIdToCheck);
                     systemService = (applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
                 } catch (RemoteException e) {
                     Log.i(LOG_TAG, "Can't talk to package managed", e);
@@ -7787,7 +7788,7 @@
 
     private boolean isSystemApp(IPackageManager pm, String packageName, int userId)
             throws RemoteException {
-        ApplicationInfo appInfo = pm.getApplicationInfo(packageName, GET_UNINSTALLED_PACKAGES,
+        ApplicationInfo appInfo = pm.getApplicationInfo(packageName, MATCH_UNINSTALLED_PACKAGES,
                 userId);
         if (appInfo == null) {
             throw new IllegalArgumentException("The application " + packageName +
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 7217c3b..515370f 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -791,7 +791,7 @@
     int getAppId(String packageName) {
         try {
             ApplicationInfo ai = mPackageManager.getApplicationInfo(packageName,
-                    PackageManager.MATCH_UNINSTALLED_PACKAGES
+                    PackageManager.MATCH_ANY_USER
                             | PackageManager.MATCH_DISABLED_COMPONENTS);
             return ai.uid;
         } catch (NameNotFoundException re) {