System installed launcher can see instant apps

Change-Id: I97f791b61f9b4f7ed33305345bf3d92394b40ae4
Fixes: 38202759
Test: cts-tradefed run commandAndExit cts-dev -m CtsAppSecurityHostTestCases -t android.appsecurity.cts.EphemeralTest
Test: Manual. Create sample app that replaces the launcher to test ability to see ephemeral apps.
diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java
index 87e6a84..4cee2df 100644
--- a/core/java/android/content/pm/PackageManagerInternal.java
+++ b/core/java/android/content/pm/PackageManagerInternal.java
@@ -343,5 +343,5 @@
     public abstract int getUidTargetSdkVersion(int uid);
 
     /** Whether the binder caller can access instant apps. */
-    public abstract boolean canAccessInstantApps(int callingUid);
+    public abstract boolean canAccessInstantApps(int callingUid, int userId);
 }
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 18cfc99..8ed76de 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -3317,12 +3317,16 @@
          confirmation UI for full backup/restore -->
     <uses-permission android:name="android.permission.CONFIRM_FULL_BACKUP"/>
 
-
-    <!-- Allows the holder to access the instant applications on the device.
+    <!-- Allows the holder to access and manage instant applications on the device.
     @hide -->
     <permission android:name="android.permission.ACCESS_INSTANT_APPS"
             android:protectionLevel="signature|installer|verifier" />
 
+    <!-- Allows the holder to view the instant applications on the device.
+    @hide -->
+    <permission android:name="android.permission.VIEW_INSTANT_APPS"
+            android:protectionLevel="signature|preinstalled" />
+
     <!-- Allows receiving the usage of media resource e.g. video/audio codec and
          graphic memory.
          @hide -->
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index de51bd4..8d9ab4c 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -3517,16 +3517,25 @@
      *     system partition.</li>
      * </ol>
      */
-    private boolean canAccessInstantApps(int callingUid) {
-        final boolean isSpecialProcess =
-                callingUid == Process.SYSTEM_UID
-                        || callingUid == Process.SHELL_UID
-                        || callingUid == Process.ROOT_UID;
-        final boolean allowMatchInstant =
-                isSpecialProcess
-                        || mContext.checkCallingOrSelfPermission(
-                        android.Manifest.permission.ACCESS_INSTANT_APPS) == PERMISSION_GRANTED;
-        return allowMatchInstant;
+    private boolean canViewInstantApps(int callingUid, int userId) {
+        if (callingUid == Process.SYSTEM_UID
+                || callingUid == Process.SHELL_UID
+                || callingUid == Process.ROOT_UID) {
+            return true;
+        }
+        if (mContext.checkCallingOrSelfPermission(
+                android.Manifest.permission.ACCESS_INSTANT_APPS) == PERMISSION_GRANTED) {
+            return true;
+        }
+        if (mContext.checkCallingOrSelfPermission(
+                android.Manifest.permission.VIEW_INSTANT_APPS) == PERMISSION_GRANTED) {
+            final ComponentName homeComponent = getDefaultHomeActivity(userId);
+            if (homeComponent != null
+                    && isCallerSameApp(homeComponent.getPackageName(), callingUid)) {
+                return true;
+            }
+        }
+        return false;
     }
 
     private PackageInfo generatePackageInfo(PackageSetting ps, int flags, int userId) {
@@ -3784,7 +3793,7 @@
         }
         if (ps.getInstantApp(userId)) {
             // caller can see all components of all instant applications, don't filter
-            if (canAccessInstantApps(callingUid)) {
+            if (canViewInstantApps(callingUid, userId)) {
                 return false;
             }
             // request for a specific instant application component, filter
@@ -4408,11 +4417,12 @@
             flags |= PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY;
             flags |= PackageManager.MATCH_INSTANT;
         } else {
+            final boolean wantMatchInstant = (flags & PackageManager.MATCH_INSTANT) != 0;
             final boolean allowMatchInstant =
                     (wantInstantApps
                             && Intent.ACTION_VIEW.equals(intent.getAction())
                             && hasWebURI(intent))
-                    || canAccessInstantApps(callingUid);
+                    || (wantMatchInstant && canViewInstantApps(callingUid, userId));
             flags &= ~(PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY
                     | PackageManager.MATCH_EXPLICITLY_VISIBLE_ONLY);
             if (!allowMatchInstant) {
@@ -5937,7 +5947,7 @@
         final int callingUid = Binder.getCallingUid();
         final int callingUserId = UserHandle.getUserId(callingUid);
         synchronized (mPackages) {
-            if (canAccessInstantApps(callingUid)) {
+            if (canViewInstantApps(callingUid, callingUserId)) {
                 return new ArrayList<String>(mPackages.keySet());
             }
             final String instantAppPkgName = getInstantAppPackageName(callingUid);
@@ -8146,9 +8156,7 @@
             final boolean returnAllowed =
                     ps != null
                     && (isCallerSameApp(packageName, callingUid)
-                            || mContext.checkCallingOrSelfPermission(
-                                    android.Manifest.permission.ACCESS_INSTANT_APPS)
-                                            == PERMISSION_GRANTED
+                            || canViewInstantApps(callingUid, userId)
                             || mInstantAppRegistry.isInstantAccessGranted(
                                     userId, UserHandle.getAppId(callingUid), ps.appId));
             if (returnAllowed) {
@@ -24370,8 +24378,8 @@
         }
 
         @Override
-        public boolean canAccessInstantApps(int callingUid) {
-            return PackageManagerService.this.canAccessInstantApps(callingUid);
+        public boolean canAccessInstantApps(int callingUid, int userId) {
+            return PackageManagerService.this.canViewInstantApps(callingUid, userId);
         }
     }
 
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 0de3c7c..5211fd6 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -411,8 +411,8 @@
         }
     }
 
-    private boolean shouldObfuscateInstantAppsForCaller(int callingUid) {
-        return !mPackageManagerInternal.canAccessInstantApps(callingUid);
+    private boolean shouldObfuscateInstantAppsForCaller(int callingUid, int userId) {
+        return !mPackageManagerInternal.canAccessInstantApps(callingUid, userId);
     }
 
     void clearAppIdleForPackage(String packageName, int userId) {
@@ -1387,7 +1387,7 @@
             }
 
             final boolean obfuscateInstantApps = shouldObfuscateInstantAppsForCaller(
-                    Binder.getCallingUid());
+                    Binder.getCallingUid(), UserHandle.getCallingUserId());
 
             final int userId = UserHandle.getCallingUserId();
             final long token = Binder.clearCallingIdentity();
@@ -1432,7 +1432,7 @@
             }
 
             final boolean obfuscateInstantApps = shouldObfuscateInstantAppsForCaller(
-                    Binder.getCallingUid());
+                    Binder.getCallingUid(), UserHandle.getCallingUserId());
 
             final int userId = UserHandle.getCallingUserId();
             final long token = Binder.clearCallingIdentity();
@@ -1453,7 +1453,7 @@
                 throw re.rethrowFromSystemServer();
             }
             final boolean obfuscateInstantApps = shouldObfuscateInstantAppsForCaller(
-                    Binder.getCallingUid());
+                    Binder.getCallingUid(), userId);
             final long token = Binder.clearCallingIdentity();
             try {
                 return UsageStatsService.this.isAppIdleFilteredOrParoled(packageName, userId,