Add a system API to make a package become visible to other package

Expose a system API PackageManager#makeUidVisible for
mainline module to make a package become visible to the caller.

Bug: 222205552
Test: atest AppEnumerationTests
Test: atest PermissionPolicyTest
Ignore-AOSP-First: (for packages/Shell/AndroidManifest.xml) Permission
Change-Id: I6cf322ddfea09a8a4c0c442a6789af4e79d294d7
diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt
index 7aef9a6..dd253ac 100644
--- a/core/api/module-lib-current.txt
+++ b/core/api/module-lib-current.txt
@@ -102,6 +102,7 @@
   public abstract class PackageManager {
     method @NonNull public String getPermissionControllerPackageName();
     method @NonNull public String getSdkSandboxPackageName();
+    method @RequiresPermission("android.permission.MAKE_UID_VISIBLE") public void makeUidVisible(int, int);
     field public static final String EXTRA_VERIFICATION_ROOT_HASH = "android.content.pm.extra.VERIFICATION_ROOT_HASH";
     field public static final int MATCH_STATIC_SHARED_AND_SDK_LIBRARIES = 67108864; // 0x4000000
   }
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 5aec193..e7ea13d 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -19,6 +19,7 @@
     field public static final String FORCE_STOP_PACKAGES = "android.permission.FORCE_STOP_PACKAGES";
     field public static final String INSTALL_TEST_ONLY_PACKAGE = "android.permission.INSTALL_TEST_ONLY_PACKAGE";
     field public static final String KEEP_UNINSTALLED_PACKAGES = "android.permission.KEEP_UNINSTALLED_PACKAGES";
+    field public static final String MAKE_UID_VISIBLE = "android.permission.MAKE_UID_VISIBLE";
     field @Deprecated public static final String MANAGE_ACTIVITY_STACKS = "android.permission.MANAGE_ACTIVITY_STACKS";
     field public static final String MANAGE_ACTIVITY_TASKS = "android.permission.MANAGE_ACTIVITY_TASKS";
     field public static final String MANAGE_CRATES = "android.permission.MANAGE_CRATES";
@@ -836,6 +837,7 @@
     method @Nullable public String getSystemTextClassifierPackageName();
     method @Nullable public String getWellbeingPackageName();
     method public void holdLock(android.os.IBinder, int);
+    method @RequiresPermission(android.Manifest.permission.MAKE_UID_VISIBLE) public void makeUidVisible(int, int);
     method @RequiresPermission(android.Manifest.permission.KEEP_UNINSTALLED_PACKAGES) public void setKeepUninstalledPackages(@NonNull java.util.List<java.lang.String>);
     field public static final String FEATURE_ADOPTABLE_STORAGE = "android.software.adoptable_storage";
     field public static final String FEATURE_COMMUNAL_MODE = "android.software.communal_mode";
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index dca5c54..7ffa61b 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -3832,4 +3832,13 @@
             throw re.rethrowAsRuntimeException();
         }
     }
+
+    @Override
+    public void makeUidVisible(int recipientUid, int visibleUid) {
+        try {
+            mPM.makeUidVisible(recipientUid, visibleUid);
+        } catch (RemoteException e) {
+            throw e.rethrowAsRuntimeException();
+        }
+    }
 }
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 0f236df..ca7d77b 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -781,7 +781,11 @@
 
     boolean isAutoRevokeWhitelisted(String packageName);
 
-    void grantImplicitAccess(int queryingUid, String visibleAuthority);
+    void makeProviderVisible(int recipientAppId, String visibleAuthority);
+
+    @JavaPassthrough(annotation = "@android.annotation.RequiresPermission(android.Manifest"
+            + ".permission.MAKE_UID_VISIBLE)")
+    void makeUidVisible(int recipientAppId, int visibleUid);
 
     IBinder getHoldLockToken();
 
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index f9beaa7..81c941e 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -10281,19 +10281,38 @@
     }
 
     /**
-     * Grants implicit visibility of the package that provides an authority to a querying UID.
+     * Makes a package that provides an authority {@code visibleAuthority} become visible to the
+     * application {@code recipientUid}.
      *
      * @throws SecurityException when called by a package other than the contacts provider
      * @hide
      */
-    public void grantImplicitAccess(int queryingUid, String visibleAuthority) {
+    public void makeProviderVisible(int recipientUid, String visibleAuthority) {
         try {
-            ActivityThread.getPackageManager().grantImplicitAccess(queryingUid, visibleAuthority);
+            ActivityThread.getPackageManager().makeProviderVisible(recipientUid, visibleAuthority);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
     }
 
+    /**
+     * Makes the package associated with the uid {@code visibleUid} become visible to the
+     * recipient uid application.
+     *
+     * @param recipientUid The uid of the application that is being given access to {@code
+     *                     visibleUid}
+     * @param visibleUid The uid of the application that is becoming accessible to {@code
+     *                   recipientAppId}
+     * @hide
+     */
+    @RequiresPermission(android.Manifest.permission.MAKE_UID_VISIBLE)
+    @TestApi
+    @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+    public void makeUidVisible(int recipientUid, int visibleUid) {
+        throw new UnsupportedOperationException(
+                "makeUidVisible not implemented in subclass");
+    }
+
     // Some of the flags don't affect the query result, but let's be conservative and cache
     // each combination of flags separately.
 
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index becac7f..1c8ec0f 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -6420,6 +6420,12 @@
     <permission android:name="android.permission.WRITE_SECURITY_LOG"
         android:protectionLevel="signature|privileged" />
 
+    <!-- Allows an UID to be visible to the application based on an interaction between the
+         two apps. This permission is not intended to be held by apps.
+         @hide @TestApi  -->
+    <permission android:name="android.permission.MAKE_UID_VISIBLE"
+                android:protectionLevel="signature" />
+
     <!-- Attribution for Geofencing service. -->
     <attribution android:tag="GeofencingService" android:label="@string/geofencing_service"/>
     <!-- Attribution for Country Detector. -->
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index dae63a8..8c922ca 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -668,6 +668,9 @@
     <!-- Permission required for CTS test - CtsTelephonyTestCases -->
     <uses-permission android:name="android.permission.BIND_TELECOM_CONNECTION_SERVICE" />
 
+    <!-- Permission required for CTS test - CtsAppEnumerationTestCases -->
+    <uses-permission android:name="android.permission.MAKE_UID_VISIBLE" />
+
     <application android:label="@string/app_label"
                 android:theme="@android:style/Theme.DeviceDefault.DayNight"
                 android:defaultToDeviceProtectedStorage="true"
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 99c9c68..67056ea 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -5062,7 +5062,7 @@
         }
 
         @Override
-        public void grantImplicitAccess(int recipientUid, @NonNull String visibleAuthority) {
+        public void makeProviderVisible(int recipientUid, @NonNull String visibleAuthority) {
             final Computer snapshot = snapshotComputer();
             final int recipientUserId = UserHandle.getUserId(recipientUid);
             final ProviderInfo providerInfo =
@@ -5077,6 +5077,26 @@
         }
 
         @Override
+        public void makeUidVisible(int recipientUid, int visibleUid) {
+            mContext.enforceCallingOrSelfPermission(
+                    android.Manifest.permission.MAKE_UID_VISIBLE, "makeUidVisible");
+            final int callingUid = Binder.getCallingUid();
+            final int recipientUserId = UserHandle.getUserId(recipientUid);
+            final int visibleUserId = UserHandle.getUserId(visibleUid);
+            final Computer snapshot = snapshotComputer();
+            snapshot.enforceCrossUserPermission(callingUid, recipientUserId,
+                    false /* requireFullPermission */, false /* checkShell */, "makeUidVisible");
+            snapshot.enforceCrossUserPermission(callingUid, visibleUserId,
+                    false /* requireFullPermission */, false /* checkShell */, "makeUidVisible");
+            snapshot.enforceCrossUserPermission(recipientUid, visibleUserId,
+                    false /* requireFullPermission */, false /* checkShell */, "makeUidVisible");
+
+            PackageManagerService.this.grantImplicitAccess(snapshot, recipientUserId,
+                    null /*Intent*/, UserHandle.getAppId(recipientUid), visibleUid,
+                    false /*direct*/, false /* retainOnUpdate */);
+        }
+
+        @Override
         public void holdLock(IBinder token, int durationMs) {
             mTestUtilityService.verifyHoldLockToken(token);