Fix NullPointerException in PIA when installing from Files app

* Added a null check while fetching packages by UID.
* Removed dependency on Intent.EXTRA_ORIGINATING_UID sent by DocumentsManager and DownloadsProvider since they were sent to PIA as INVALID_UID. Instead, PIA uses callingUid to determine if the install request comes from the above mentioned sources to bypass REQUEST_INSTALL_PACKAGES permission check.
* PIA iterates over all packages with a sharedUid to check if any of the packages in sharedUid have access to a target package having a content provider.


Bug: 277074364
Bug: 271500460
Test: adb push file.apk /sdcard/directory
      open preinstalled files app and install the apk
Change-Id: Ie2f8d251c558b677759cf4c05ebb016c743c4439
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/InstallStart.java b/packages/PackageInstaller/src/com/android/packageinstaller/InstallStart.java
index ac32020..d0f4e21 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/InstallStart.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/InstallStart.java
@@ -77,7 +77,21 @@
         }
 
         final ApplicationInfo sourceInfo = getSourceInfo(callingPackage);
-        final int originatingUid = getOriginatingUid(sourceInfo);
+        // Uid of the source package, coming from ActivityManager
+        int callingUid = getLaunchedFromUid();
+        if (callingUid == Process.INVALID_UID) {
+            // Cannot reach ActivityManager. Aborting install.
+            Log.e(LOG_TAG, "Could not determine the launching uid.");
+        }
+        // Uid of the source package, with a preference to uid from ApplicationInfo
+        final int originatingUid = sourceInfo != null ? sourceInfo.uid : callingUid;
+
+        if (callingUid == Process.INVALID_UID && sourceInfo == null) {
+            mAbortInstall = true;
+        }
+
+        boolean isDocumentsManager = checkPermission(Manifest.permission.MANAGE_DOCUMENTS,
+                -1, callingUid) == PackageManager.PERMISSION_GRANTED;
         boolean isTrustedSource = false;
         if (sourceInfo != null && sourceInfo.isPrivilegedApp()) {
             isTrustedSource = intent.getBooleanExtra(Intent.EXTRA_NOT_UNKNOWN_SOURCE, false) || (
@@ -86,7 +100,8 @@
                             == PackageManager.PERMISSION_GRANTED);
         }
 
-        if (!isTrustedSource && originatingUid != Process.INVALID_UID) {
+        if (!isTrustedSource && !isSystemDownloadsProvider(callingUid) && !isDocumentsManager
+                && originatingUid != Process.INVALID_UID) {
             final int targetSdkVersion = getMaxTargetSdkVersionForUid(this, originatingUid);
             if (targetSdkVersion < 0) {
                 Log.w(LOG_TAG, "Cannot get target sdk version for uid " + originatingUid);
@@ -144,7 +159,7 @@
 
             if (packageUri != null
                     && packageUri.getScheme().equals(ContentResolver.SCHEME_CONTENT)
-                    && canPackageQuery(originatingUid, packageUri)) {
+                    && canPackageQuery(callingUid, packageUri)) {
                 // [IMPORTANT] This path is deprecated, but should still work. Only necessary
                 // features should be added.
 
@@ -212,41 +227,6 @@
         return null;
     }
 
-    /**
-     * Get the originating uid if possible, or {@link Process#INVALID_UID} if not available
-     *
-     * @param sourceInfo The source of this installation
-     * @return The UID of the installation source or INVALID_UID
-     */
-    private int getOriginatingUid(@Nullable ApplicationInfo sourceInfo) {
-        // The originating uid from the intent. We only trust/use this if it comes from either
-        // the document manager app or the downloads provider
-        final int uidFromIntent = getIntent().getIntExtra(Intent.EXTRA_ORIGINATING_UID,
-                Process.INVALID_UID);
-
-        final int callingUid;
-        if (sourceInfo != null) {
-            callingUid = sourceInfo.uid;
-        } else {
-            callingUid = getLaunchedFromUid();
-            if (callingUid == Process.INVALID_UID) {
-                // Cannot reach ActivityManager. Aborting install.
-                Log.e(LOG_TAG, "Could not determine the launching uid.");
-                mAbortInstall = true;
-                return Process.INVALID_UID;
-            }
-        }
-        if (checkPermission(Manifest.permission.MANAGE_DOCUMENTS, -1, callingUid)
-                == PackageManager.PERMISSION_GRANTED) {
-            return uidFromIntent;
-        }
-        if (isSystemDownloadsProvider(callingUid)) {
-            return uidFromIntent;
-        }
-        // We don't trust uid from the intent. Use the calling uid instead.
-        return callingUid;
-    }
-
     private boolean isSystemDownloadsProvider(int uid) {
         final ProviderInfo downloadProviderPackage = getPackageManager().resolveContentProvider(
                 DOWNLOADS_AUTHORITY, 0);
@@ -260,8 +240,7 @@
     }
 
     @NonNull
-    private boolean canPackageQuery(int originatingUid, Uri packageUri) {
-        String callingPackage = mPackageManager.getPackagesForUid(originatingUid)[0];
+    private boolean canPackageQuery(int callingUid, Uri packageUri) {
         ProviderInfo info = mPackageManager.resolveContentProvider(packageUri.getAuthority(),
                 PackageManager.ComponentInfoFlags.of(0));
         if (info == null) {
@@ -269,11 +248,20 @@
         }
         String targetPackage = info.packageName;
 
-        try {
-            return mPackageManager.canPackageQuery(callingPackage, targetPackage);
-        } catch (PackageManager.NameNotFoundException e) {
+        String[] callingPackages = mPackageManager.getPackagesForUid(callingUid);
+        if (callingPackages == null) {
             return false;
         }
+        for (String callingPackage: callingPackages) {
+            try {
+                if (mPackageManager.canPackageQuery(callingPackage, targetPackage)) {
+                    return true;
+                }
+            } catch (PackageManager.NameNotFoundException e) {
+                // no-op
+            }
+        }
+        return false;
     }
 
     private boolean isCallerSessionOwner(int originatingUid, int sessionId) {