Determine the originating uid for an install

Bug: 6923241
Change-Id: I281301ca0bece2cb2395cde1d7652be168ffa202
diff --git a/src/com/android/packageinstaller/InstallAppProgress.java b/src/com/android/packageinstaller/InstallAppProgress.java
index e281fd3..fc82078 100755
--- a/src/com/android/packageinstaller/InstallAppProgress.java
+++ b/src/com/android/packageinstaller/InstallAppProgress.java
@@ -252,8 +252,10 @@
                 Intent.EXTRA_INSTALLER_PACKAGE_NAME);
         Uri originatingURI = getIntent().getParcelableExtra(Intent.EXTRA_ORIGINATING_URI);
         Uri referrer = getIntent().getParcelableExtra(Intent.EXTRA_REFERRER);
+        int originatingUid = getIntent().getIntExtra(Intent.EXTRA_ORIGINATING_UID,
+                VerificationParams.NO_UID);
         VerificationParams verificationParams = new VerificationParams(null, originatingURI,
-                referrer, null);
+                referrer, originatingUid, null);
         PackageInstallObserver observer = new PackageInstallObserver();
 
         if ("package".equals(mPackageURI.getScheme())) {
diff --git a/src/com/android/packageinstaller/PackageInstallerActivity.java b/src/com/android/packageinstaller/PackageInstallerActivity.java
index d3b2a94..a0546a2 100644
--- a/src/com/android/packageinstaller/PackageInstallerActivity.java
+++ b/src/com/android/packageinstaller/PackageInstallerActivity.java
@@ -17,6 +17,7 @@
 package com.android.packageinstaller;
 
 import android.app.Activity;
+import android.app.ActivityManagerNative;
 import android.app.AlertDialog;
 import android.app.Dialog;
 import android.content.Context;
@@ -30,6 +31,7 @@
 import android.content.pm.PackageUserState;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.PackageParser;
+import android.content.pm.VerificationParams;
 import android.graphics.Rect;
 import android.net.Uri;
 import android.os.Bundle;
@@ -66,6 +68,8 @@
     private Uri mPackageURI;    
     private Uri mOriginatingURI;
     private Uri mReferrerURI;
+    private int mOriginatingUid = VerificationParams.NO_UID;
+
     private boolean localLOGV = false;
     PackageManager mPm;
     PackageInfo mPkgInfo;
@@ -523,6 +527,8 @@
         mInstallConfirm.setVisibility(View.INVISIBLE);
         PackageUtil.initSnippetForNewApp(this, as, R.id.app_snippet);
 
+        mOriginatingUid = getOriginatingUid(intent);
+
         // Deal with install source.
         String callerPackage = getCallingPackage();
         if (callerPackage != null && intent.getBooleanExtra(
@@ -562,7 +568,78 @@
         }
         initiateInstall();
     }
-    
+
+    /** Get the ApplicationInfo for the calling package, if available */
+    private ApplicationInfo getSourceInfo() {
+        String callingPackage = getCallingPackage();
+        if (callingPackage != null) {
+            try {
+                return mPm.getApplicationInfo(callingPackage, 0);
+            } catch (NameNotFoundException ex) {
+                // ignore
+            }
+        }
+        return null;
+    }
+
+
+    /** Get the originating uid if possible, or VerificationParams.NO_UID if not available */
+    private int getOriginatingUid(Intent intent) {
+        // The originating uid from the intent. We only trust/use this if it comes from a
+        // system application
+        int uidFromIntent = intent.getIntExtra(Intent.EXTRA_ORIGINATING_UID,
+                VerificationParams.NO_UID);
+
+        // Get the source info from the calling package, if available. This will be the
+        // definitive calling package, but it only works if the intent was started using
+        // startActivityForResult,
+        ApplicationInfo sourceInfo = getSourceInfo();
+        if (sourceInfo != null) {
+            if (uidFromIntent != VerificationParams.NO_UID &&
+                    (mSourceInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
+                return uidFromIntent;
+
+            }
+            // We either didn't get a uid in the intent, or we don't trust it. Use the
+            // uid of the calling package instead.
+            return sourceInfo.uid;
+        }
+
+        // We couldn't get the specific calling package. Let's get the uid instead
+        int callingUid;
+        try {
+            callingUid = ActivityManagerNative.getDefault()
+                    .getLaunchedFromUid(getActivityToken());
+        } catch (android.os.RemoteException ex) {
+            Log.w(TAG, "Could not determine the launching uid.");
+            // nothing else we can do
+            return VerificationParams.NO_UID;
+        }
+
+        // If we got a uid from the intent, we need to verify that the caller is a
+        // system package before we use it
+        if (uidFromIntent != VerificationParams.NO_UID) {
+            String[] callingPackages = mPm.getPackagesForUid(callingUid);
+            if (callingPackages != null) {
+                for (String packageName: callingPackages) {
+                    try {
+                        ApplicationInfo applicationInfo =
+                                mPm.getApplicationInfo(packageName, 0);
+
+                        if ((applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
+                            return uidFromIntent;
+                        }
+                    } catch (NameNotFoundException ex) {
+                        // ignore it, and try the next package
+                    }
+                }
+            }
+        }
+        // We either didn't get a uid from the intent, or we don't trust it. Use the
+        // calling uid instead.
+        return callingUid;
+    }
+
     // Generic handling when pressing back key
     public void onCancel(DialogInterface dialog) {
         finish();
@@ -585,6 +662,9 @@
                 if (mReferrerURI != null) {
                     newIntent.putExtra(Intent.EXTRA_REFERRER, mReferrerURI);
                 }
+                if (mOriginatingUid != VerificationParams.NO_UID) {
+                    newIntent.putExtra(Intent.EXTRA_ORIGINATING_UID, mOriginatingUid);
+                }
                 if (installerPackageName != null) {
                     newIntent.putExtra(Intent.EXTRA_INSTALLER_PACKAGE_NAME,
                             installerPackageName);