Grant installer and verifier install permissions robustly

bug:22248271

Change-Id: I3a47ae9a112ba7d88b421fcb5f9651d1168ba7a5
diff --git a/api/current.txt b/api/current.txt
index bb1070d..00477cd 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -9465,10 +9465,12 @@
     field public static final int PROTECTION_DANGEROUS = 1; // 0x1
     field public static final int PROTECTION_FLAG_APPOP = 64; // 0x40
     field public static final int PROTECTION_FLAG_DEVELOPMENT = 32; // 0x20
+    field public static final int PROTECTION_FLAG_INSTALLER = 256; // 0x100
     field public static final int PROTECTION_FLAG_PRE23 = 128; // 0x80
     field public static final int PROTECTION_FLAG_SYSTEM = 16; // 0x10
+    field public static final int PROTECTION_FLAG_VERIFIER = 512; // 0x200
     field public static final int PROTECTION_MASK_BASE = 15; // 0xf
-    field public static final int PROTECTION_MASK_FLAGS = 240; // 0xf0
+    field public static final int PROTECTION_MASK_FLAGS = 4080; // 0xff0
     field public static final int PROTECTION_NORMAL = 0; // 0x0
     field public static final int PROTECTION_SIGNATURE = 2; // 0x2
     field public static final int PROTECTION_SIGNATURE_OR_SYSTEM = 3; // 0x3
diff --git a/api/system-current.txt b/api/system-current.txt
index 5861560..f0253bf 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -9800,10 +9800,12 @@
     field public static final int PROTECTION_DANGEROUS = 1; // 0x1
     field public static final int PROTECTION_FLAG_APPOP = 64; // 0x40
     field public static final int PROTECTION_FLAG_DEVELOPMENT = 32; // 0x20
+    field public static final int PROTECTION_FLAG_INSTALLER = 256; // 0x100
     field public static final int PROTECTION_FLAG_PRE23 = 128; // 0x80
     field public static final int PROTECTION_FLAG_SYSTEM = 16; // 0x10
+    field public static final int PROTECTION_FLAG_VERIFIER = 512; // 0x200
     field public static final int PROTECTION_MASK_BASE = 15; // 0xf
-    field public static final int PROTECTION_MASK_FLAGS = 240; // 0xf0
+    field public static final int PROTECTION_MASK_FLAGS = 4080; // 0xff0
     field public static final int PROTECTION_NORMAL = 0; // 0x0
     field public static final int PROTECTION_SIGNATURE = 2; // 0x2
     field public static final int PROTECTION_SIGNATURE_OR_SYSTEM = 3; // 0x3
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index ca6c6ca..844900d 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -74,6 +74,8 @@
 
 public class Am extends BaseCommand {
 
+    private static final String SHELL_PACKAGE_NAME = "com.android.shell";
+
     private IActivityManager mAm;
 
     private int mStartFlags = 0;
@@ -767,7 +769,8 @@
             return;
         }
         System.out.println("Starting service: " + intent);
-        ComponentName cn = mAm.startService(null, intent, intent.getType(), null, mUserId);
+        ComponentName cn = mAm.startService(null, intent, intent.getType(),
+                SHELL_PACKAGE_NAME, mUserId);
         if (cn == null) {
             System.err.println("Error: Not found; no service started.");
         } else if (cn.getPackageName().equals("!")) {
diff --git a/core/java/android/content/pm/PermissionInfo.java b/core/java/android/content/pm/PermissionInfo.java
index 0a1f148..1857ecf 100644
--- a/core/java/android/content/pm/PermissionInfo.java
+++ b/core/java/android/content/pm/PermissionInfo.java
@@ -83,6 +83,20 @@
     public static final int PROTECTION_FLAG_PRE23 = 0x80;
 
     /**
+     * Additional flag for {@link #protectionLevel}, corresponding
+     * to the <code>installer</code> value of
+     * {@link android.R.attr#protectionLevel}.
+     */
+    public static final int PROTECTION_FLAG_INSTALLER = 0x100;
+
+    /**
+     * Additional flag for {@link #protectionLevel}, corresponding
+     * to the <code>verifier</code> value of
+     * {@link android.R.attr#protectionLevel}.
+     */
+    public static final int PROTECTION_FLAG_VERIFIER = 0x200;
+
+    /**
      * Mask for {@link #protectionLevel}: the basic protection type.
      */
     public static final int PROTECTION_MASK_BASE = 0xf;
@@ -90,7 +104,7 @@
     /**
      * Mask for {@link #protectionLevel}: additional flag bits.
      */
-    public static final int PROTECTION_MASK_FLAGS = 0xf0;
+    public static final int PROTECTION_MASK_FLAGS = 0xff0;
 
     /**
      * The level of access this permission is protecting, as per
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 8c868c9..e18e44c 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1327,7 +1327,7 @@
          that removes restrictions on where broadcasts can be sent and allows other
          types of interactions. -->
     <permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL"
-        android:protectionLevel="signature" />
+        android:protectionLevel="signature|installer" />
 
     <!-- @SystemApi @hide Allows an application to call APIs that allow it to query and manage
          users on the device. This permission is not available to
@@ -1769,7 +1769,7 @@
     <!-- @SystemApi Allows an application to update application operation statistics. Not for
          use by third party apps. @hide -->
     <permission android:name="android.permission.UPDATE_APP_OPS_STATS"
-        android:protectionLevel="signature|system" />
+        android:protectionLevel="signature|system|installer" />
 
     <!-- @SystemApi Allows an application to open windows that are for use by parts
          of the system user interface.
@@ -2016,7 +2016,7 @@
          @hide
     -->
     <permission android:name="android.permission.CLEAR_APP_USER_DATA"
-        android:protectionLevel="signature" />
+        android:protectionLevel="signature|installer" />
 
     <!-- @SystemApi Allows an application to delete cache files.
     <p>Not for use by third-party applications. -->
@@ -2041,7 +2041,7 @@
 
     <!-- @hide Allows an application to grant or revoke specific permissions. -->
     <permission android:name="android.permission.GRANT_REVOKE_PERMISSIONS"
-        android:protectionLevel="signature" />
+        android:protectionLevel="signature|installer" />
 
     <!-- @hide Allows an application to observe permission changes. -->
     <permission android:name="android.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS"
@@ -2552,7 +2552,7 @@
         <p>Not for use by third-party applications.
          @hide -->
     <permission android:name="android.permission.KILL_UID"
-                android:protectionLevel="signature" />
+                android:protectionLevel="signature|installer" />
 
     <!-- Allows applications to act as network scorers. @hide @SystemApi-->
     <permission android:name="android.permission.LOCAL_MAC_ADDRESS"
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 70f9db9..c501329 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -220,6 +220,12 @@
              {@link android.os.Build.VERSION_CODES#MNC} (before runtime permissions
              were introduced). -->
         <flag name="pre23" value="0x80" />
+        <!-- Additional flag from base permission type: this permission can be automatically
+            granted to system apps that install packages. -->
+        <flag name="installer" value="0x100" />
+        <!-- Additional flag from base permission type: this permission can be automatically
+            granted to system apps that verify packages. -->
+        <flag name="verifier" value="0x200" />
     </attr>
 
     <!-- Flags indicating more context for a permission group. -->
diff --git a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
index 453f123..b10894f 100644
--- a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
@@ -54,7 +54,6 @@
     private static final String TAG = "DefaultPermGrantPolicy"; // must be <= 23 chars
     private static final boolean DEBUG = false;
 
-    private static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive";
     private static final String AUDIO_MIME_TYPE = "audio/mpeg";
 
     private static final Set<String> PHONE_PERMISSIONS = new ArraySet<>();
@@ -127,19 +126,6 @@
         SETTINGS_PERMISSIONS.add(Manifest.permission.WRITE_SETTINGS);
     }
 
-    private static final Set<String> INSTALLER_PERMISSIONS = new ArraySet<>();
-    static {
-        INSTALLER_PERMISSIONS.add(Manifest.permission.GRANT_REVOKE_PERMISSIONS);
-        INSTALLER_PERMISSIONS.add(Manifest.permission.INTERACT_ACROSS_USERS_FULL);
-        INSTALLER_PERMISSIONS.add(Manifest.permission.CLEAR_APP_USER_DATA);
-        INSTALLER_PERMISSIONS.add(Manifest.permission.KILL_UID);
-    }
-
-    private static final Set<String> VERIFIER_PERMISSIONS = new ArraySet<>();
-    static {
-        INSTALLER_PERMISSIONS.add(Manifest.permission.GRANT_REVOKE_PERMISSIONS);
-    }
-
     private final PackageManagerService mService;
 
     private PackagesProvider mImePackagesProvider;
@@ -250,30 +236,20 @@
                 syncAdapterPackagesProvider.getPackages(CalendarContract.AUTHORITY, userId) : null;
 
         synchronized (mService.mPackages) {
-            // Installers
-            Intent installerIntent = new Intent(Intent.ACTION_INSTALL_PACKAGE);
-            installerIntent.addCategory(Intent.CATEGORY_DEFAULT);
-            installerIntent.setDataAndType(Uri.fromFile(new File("foo.apk")),
-                    PACKAGE_MIME_TYPE);
-            List<PackageParser.Package> installerPackages =
-                    getPrivilegedHandlerActivityPackagesLPr(installerIntent, userId);
-            final int installerCount = installerPackages.size();
-            for (int i = 0; i < installerCount; i++) {
-                PackageParser.Package installPackage = installerPackages.get(i);
-                grantInstallPermissionsLPw(installPackage, INSTALLER_PERMISSIONS, userId);
-                grantRuntimePermissionsLPw(installPackage, STORAGE_PERMISSIONS, true, userId);
+            // Installer
+            PackageParser.Package installerPackage = getSystemPackageLPr(
+                    mService.mRequiredInstallerPackage);
+            if (installerPackage != null
+                    && doesPackageSupportRuntimePermissions(installerPackage)) {
+                grantRuntimePermissionsLPw(installerPackage, STORAGE_PERMISSIONS, true, userId);
             }
 
-            // Verifiers
-            Intent verifierIntent = new Intent(Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
-            verifierIntent.setType(PACKAGE_MIME_TYPE);
-            List<PackageParser.Package> verifierPackages =
-                    getPrivilegedHandlerReceiverPackagesLPr(verifierIntent, userId);
-            final int verifierCount = verifierPackages.size();
-            for (int i = 0; i < verifierCount; i++) {
-                PackageParser.Package verifierPackage = verifierPackages.get(i);
-                grantInstallPermissionsLPw(verifierPackage, VERIFIER_PERMISSIONS, userId);
-                grantRuntimePermissionsLPw(verifierPackage, STORAGE_PERMISSIONS, userId);
+            // Verifier
+            PackageParser.Package verifierPackage = getSystemPackageLPr(
+                    mService.mRequiredVerifierPackage);
+            if (verifierPackage != null
+                    && doesPackageSupportRuntimePermissions(verifierPackage)) {
+                grantRuntimePermissionsLPw(verifierPackage, STORAGE_PERMISSIONS, true, userId);
             }
 
             // SetupWizard
@@ -636,39 +612,10 @@
         }
     }
 
-    private List<PackageParser.Package> getPrivilegedHandlerReceiverPackagesLPr(
-            Intent intent, int userId) {
-        List<ResolveInfo> handlers = mService.queryIntentReceivers(
-                intent, intent.resolveTypeIfNeeded(mService.mContext.getContentResolver()),
-                0, userId);
-        return getPrivilegedPackages(handlers);
-    }
-
-    private List<PackageParser.Package> getPrivilegedHandlerActivityPackagesLPr(
-            Intent intent, int userId) {
-        List<ResolveInfo> handlers = mService.queryIntentActivities(
-                intent, intent.resolveTypeIfNeeded(mService.mContext.getContentResolver()),
-                0, userId);
-        return getPrivilegedPackages(handlers);
-    }
-
-    private List<PackageParser.Package> getPrivilegedPackages(List<ResolveInfo> resolveInfos) {
-        List<PackageParser.Package> handlerPackages = new ArrayList<>();
-        final int handlerCount = resolveInfos.size();
-        for (int i = 0; i < handlerCount; i++) {
-            ResolveInfo handler = resolveInfos.get(i);
-            PackageParser.Package handlerPackage = getPrivilegedPackageLPr(
-                    handler.activityInfo.packageName);
-            if (handlerPackage != null) {
-                handlerPackages.add(handlerPackage);
-            }
-        }
-        return handlerPackages;
-    }
-
     private PackageParser.Package getDefaultSystemHandlerActivityPackageLPr(
             Intent intent, int userId) {
-        List<ResolveInfo> handlers = mService.queryIntentActivities(intent, null, 0, userId);
+        List<ResolveInfo> handlers = mService.queryIntentActivities(intent,
+                intent.resolveType(mService.mContext.getContentResolver()), 0, userId);
         final int handlerCount = handlers.size();
         for (int i = 0; i < handlerCount; i++) {
             ResolveInfo handler = handlers.get(i);
@@ -728,18 +675,9 @@
         return null;
     }
 
-    private PackageParser.Package getPrivilegedPackageLPr(String packageName) {
-        PackageParser.Package pkg = mService.mPackages.get(packageName);
-        if (pkg != null && pkg.applicationInfo.isPrivilegedApp()) {
-            return !isSysComponentOrPersistentPrivApp(pkg) ? pkg : null;
-        }
-        return null;
-    }
-
     private void grantRuntimePermissionsLPw(PackageParser.Package pkg, Set<String> permissions,
             int userId) {
         grantRuntimePermissionsLPw(pkg, permissions, false, userId);
-
     }
 
     private void grantRuntimePermissionsLPw(PackageParser.Package pkg, Set<String> permissions,
@@ -781,36 +719,6 @@
         }
     }
 
-    private void grantInstallPermissionsLPw(PackageParser.Package pkg, Set<String> permissions,
-            int userId) {
-        List<String> requestedPermissions = pkg.requestedPermissions;
-
-        if (pkg.isUpdatedSystemApp()) {
-            PackageSetting sysPs = mService.mSettings.getDisabledSystemPkgLPr(pkg.packageName);
-            if (sysPs != null) {
-                requestedPermissions = sysPs.pkg.requestedPermissions;
-            }
-        }
-
-        final int permissionCount = requestedPermissions.size();
-        for (int i = 0; i < permissionCount; i++) {
-            String permission = requestedPermissions.get(i);
-            if (permissions.contains(permission)) {
-                final int flags = mService.getPermissionFlags(permission, pkg.packageName, userId);
-
-                // If any flags are set to the permission, then it is either set in
-                // its current state by the system or device/profile owner or the user.
-                // In all these cases we do not want to clobber the current state.
-                if (flags == 0) {
-                    mService.grantInstallPermissionLPw(permission, pkg);
-                    if (DEBUG) {
-                        Log.i(TAG, "Granted install " + permission + " to " + pkg.packageName);
-                    }
-                }
-            }
-        }
-    }
-
     private static boolean isSysComponentOrPersistentPrivApp(PackageParser.Package pkg) {
         return UserHandle.getAppId(pkg.applicationInfo.uid) < FIRST_APPLICATION_UID
                 || ((pkg.applicationInfo.privateFlags
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 0240dbb..5e0d3d8 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -928,7 +928,8 @@
     private static final String TAG_DEFAULT_APPS = "da";
     private static final String TAG_INTENT_FILTER_VERIFICATION = "iv";
 
-    private final String mRequiredVerifierPackage;
+    final String mRequiredVerifierPackage;
+    final String mRequiredInstallerPackage;
 
     private final PackageUsage mPackageUsage = new PackageUsage();
 
@@ -2262,6 +2263,7 @@
                     SystemClock.uptimeMillis());
 
             mRequiredVerifierPackage = getRequiredVerifierLPr();
+            mRequiredInstallerPackage = getRequiredInstallerLPr();
 
             mInstallerService = new PackageInstallerService(context, this);
 
@@ -2328,6 +2330,39 @@
         return requiredVerifier;
     }
 
+    private String getRequiredInstallerLPr() {
+        Intent installerIntent = new Intent(Intent.ACTION_INSTALL_PACKAGE);
+        installerIntent.addCategory(Intent.CATEGORY_DEFAULT);
+        installerIntent.setDataAndType(Uri.fromFile(new File("foo.apk")), PACKAGE_MIME_TYPE);
+
+        final List<ResolveInfo> installers = queryIntentActivities(installerIntent,
+                PACKAGE_MIME_TYPE, 0, 0);
+
+        String requiredInstaller = null;
+
+        final int N = installers.size();
+        for (int i = 0; i < N; i++) {
+            final ResolveInfo info = installers.get(i);
+            final String packageName = info.activityInfo.packageName;
+
+            if (!info.activityInfo.applicationInfo.isSystemApp()) {
+                continue;
+            }
+
+            if (requiredInstaller != null) {
+                throw new RuntimeException("There must be one required installer");
+            }
+
+            requiredInstaller = packageName;
+        }
+
+        if (requiredInstaller == null) {
+            throw new RuntimeException("There must be one required installer");
+        }
+
+        return requiredInstaller;
+    }
+
     private ComponentName getIntentFilterVerifierComponentNameLPr() {
         final Intent verification = new Intent(Intent.ACTION_INTENT_FILTER_NEEDS_VERIFICATION);
         final List<ResolveInfo> receivers = queryIntentReceivers(verification, PACKAGE_MIME_TYPE,
@@ -8428,6 +8463,18 @@
             // we still want to blindly grant it to old apps.
             allowed = true;
         }
+        if (!allowed && (bp.protectionLevel & PermissionInfo.PROTECTION_FLAG_INSTALLER) != 0
+                && pkg.packageName.equals(mRequiredInstallerPackage)) {
+            // If this permission is to be granted to the system installer and
+            // this app is an installer, then it gets the permission.
+            allowed = true;
+        }
+        if (!allowed && (bp.protectionLevel & PermissionInfo.PROTECTION_FLAG_VERIFIER) != 0
+                && pkg.packageName.equals(mRequiredVerifierPackage)) {
+            // If this permission is to be granted to the system verifier and
+            // this app is a verifier, then it gets the permission.
+            allowed = true;
+        }
         if (!allowed && (bp.protectionLevel
                 & PermissionInfo.PROTECTION_FLAG_DEVELOPMENT) != 0) {
             // For development permissions, a development permission