Merge "Work on issue #22303510: Additional permissions aren't properly..." into mnc-dev
diff --git a/api/current.txt b/api/current.txt
index a129a63..741ff9b 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -9445,6 +9445,7 @@
     method public java.lang.CharSequence loadDescription(android.content.pm.PackageManager);
     field public static final android.os.Parcelable.Creator<android.content.pm.PermissionInfo> CREATOR;
     field public static final int FLAG_COSTS_MONEY = 1; // 0x1
+    field public static final int FLAG_INSTALLED = 1073741824; // 0x40000000
     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
diff --git a/api/system-current.txt b/api/system-current.txt
index c2fd0d1f..4c2d7b1 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -9783,6 +9783,7 @@
     method public java.lang.CharSequence loadDescription(android.content.pm.PackageManager);
     field public static final android.os.Parcelable.Creator<android.content.pm.PermissionInfo> CREATOR;
     field public static final int FLAG_COSTS_MONEY = 1; // 0x1
+    field public static final int FLAG_INSTALLED = 1073741824; // 0x40000000
     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
diff --git a/core/java/android/content/pm/PermissionInfo.java b/core/java/android/content/pm/PermissionInfo.java
index 2828d83..d514513 100644
--- a/core/java/android/content/pm/PermissionInfo.java
+++ b/core/java/android/content/pm/PermissionInfo.java
@@ -145,12 +145,10 @@
     public static final int FLAG_COSTS_MONEY = 1<<0;
 
     /**
-     * Flag for {@link #protectionLevel}, corresponding
-     * to the <code>hide</code> value of
-     * {@link android.R.attr#permissionFlags}.
-     * @hide
+     * Flag for {@link #flags}, indicating that this permission has been
+     * installed into the system's globally defined permissions.
      */
-    public static final int PROTECTION_FLAG_HIDE = 1<<1;
+    public static final int FLAG_INSTALLED = 1<<30;
 
     /**
      * Additional flags about this permission as given by
@@ -210,6 +208,15 @@
         if ((level&PermissionInfo.PROTECTION_FLAG_PRE23) != 0) {
             protLevel += "|pre23";
         }
+        if ((level&PermissionInfo.PROTECTION_FLAG_INSTALLER) != 0) {
+            protLevel += "|installer";
+        }
+        if ((level&PermissionInfo.PROTECTION_FLAG_VERIFIER) != 0) {
+            protLevel += "|verifier";
+        }
+        if ((level&PermissionInfo.PROTECTION_FLAG_PREINSTALLED) != 0) {
+            protLevel += "|preinstalled";
+        }
         return protLevel;
     }
 
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index c139389..e456370 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -7321,6 +7321,9 @@
             for (i=0; i<N; i++) {
                 PackageParser.Permission p = pkg.permissions.get(i);
 
+                // Assume by default that we did not install this permission into the system.
+                p.info.flags &= ~PermissionInfo.FLAG_INSTALLED;
+
                 // Now that permission groups have a special meaning, we ignore permission
                 // groups for legacy apps to prevent unexpected behavior. In particular,
                 // permissions for one app being granted to someone just becuase they happen
@@ -7350,6 +7353,7 @@
                             bp.perm = p;
                             bp.uid = pkg.applicationInfo.uid;
                             bp.sourcePackage = p.info.packageName;
+                            p.info.flags |= PermissionInfo.FLAG_INSTALLED;
                         } else if (!currentOwnerIsSystem) {
                             String msg = "New decl " + p.owner + " of permission  "
                                     + p.info.name + " is system; overriding " + bp.sourcePackage;
@@ -7375,6 +7379,7 @@
                             bp.perm = p;
                             bp.uid = pkg.applicationInfo.uid;
                             bp.sourcePackage = p.info.packageName;
+                            p.info.flags |= PermissionInfo.FLAG_INSTALLED;
                             if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
                                 if (r == null) {
                                     r = new StringBuilder(256);
@@ -14688,12 +14693,12 @@
                 pw.println("    s[hared-users]: dump shared user IDs");
                 pw.println("    m[essages]: print collected runtime messages");
                 pw.println("    v[erifiers]: print package verifier info");
-                pw.println("    version: print database version info");
-                pw.println("    write: write current settings now");
-                pw.println("    <package.name>: info about given package");
-                pw.println("    installs: details about install sessions");
                 pw.println("    d[omain-preferred-apps]: print domains preferred apps");
                 pw.println("    i[ntent-filter-verifiers]|ifv: print intent filter verifier info");
+                pw.println("    version: print database version info");
+                pw.println("    write: write current settings now");
+                pw.println("    installs: details about install sessions");
+                pw.println("    <package.name>: info about given package");
                 return;
             } else if ("--checkin".equals(opt)) {
                 checkin = true;
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 92b9da6..736b153 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -4120,6 +4120,28 @@
         pw.print(prefix); pw.print("  pkgFlags="); printFlags(pw, ps.pkgFlags, FLAG_DUMP_SPEC);
                 pw.println();
 
+        if (ps.pkg != null && ps.pkg.permissions != null && ps.pkg.permissions.size() > 0) {
+            final ArrayList<PackageParser.Permission> perms = ps.pkg.permissions;
+            pw.print(prefix); pw.println("  declared permissions:");
+            for (int i=0; i<perms.size(); i++) {
+                PackageParser.Permission perm = perms.get(i);
+                if (permissionNames != null
+                        && !permissionNames.contains(perm.info.name)) {
+                    continue;
+                }
+                pw.print(prefix); pw.print("    "); pw.print(perm.info.name);
+                pw.print(": prot=");
+                pw.print(PermissionInfo.protectionToString(perm.info.protectionLevel));
+                if ((perm.info.flags&PermissionInfo.FLAG_COSTS_MONEY) != 0) {
+                    pw.print(", COSTS_MONEY");
+                }
+                if ((perm.info.flags&PermissionInfo.FLAG_INSTALLED) != 0) {
+                    pw.print(", INSTALLED");
+                }
+                pw.println();
+            }
+        }
+
         if (ps.sharedUser == null || permissionNames != null) {
             PermissionsState permissionsState = ps.getPermissionsState();
             dumpInstallPermissionsLPr(pw, prefix + "  ", permissionNames, permissionsState);
@@ -4155,14 +4177,14 @@
                 if (cmp != null && cmp.size() > 0) {
                     pw.print(prefix); pw.println("    disabledComponents:");
                     for (String s : cmp) {
-                        pw.print(prefix); pw.print("    "); pw.println(s);
+                        pw.print(prefix); pw.print("      "); pw.println(s);
                     }
                 }
                 cmp = ps.getEnabledComponents(user.id);
                 if (cmp != null && cmp.size() > 0) {
                     pw.print(prefix); pw.println("    enabledComponents:");
                     for (String s : cmp) {
-                        pw.print(prefix); pw.print("    "); pw.println(s);
+                        pw.print(prefix); pw.print("      "); pw.println(s);
                     }
                 }
             }
@@ -4267,11 +4289,14 @@
                     pw.print(" type="); pw.print(p.type);
                     pw.print(" prot=");
                     pw.println(PermissionInfo.protectionToString(p.protectionLevel));
-            if (p.packageSetting != null) {
-                pw.print("    packageSetting="); pw.println(p.packageSetting);
-            }
             if (p.perm != null) {
                 pw.print("    perm="); pw.println(p.perm);
+                if (p.perm.info.flags != PermissionInfo.FLAG_INSTALLED) {
+                    pw.print("    flags=0x"); pw.println(Integer.toHexString(p.perm.info.flags));
+                }
+            }
+            if (p.packageSetting != null) {
+                pw.print("    packageSetting="); pw.println(p.packageSetting);
             }
             if (READ_EXTERNAL_STORAGE.equals(p.name)) {
                 pw.print("    enforced=");
@@ -4372,24 +4397,32 @@
                     continue;
                 }
                 pw.print(prefix); pw.print("  "); pw.print(permissionState.getName());
-                pw.print(", granted="); pw.print(permissionState.isGranted());
-                    pw.print(", flags="); pw.println(permissionFlagsToString(
-                        permissionState.getFlags()));
+                pw.print(": granted="); pw.print(permissionState.isGranted());
+                    pw.println(permissionFlagsToString(", flags=",
+                            permissionState.getFlags()));
             }
         }
     }
 
-    private static String permissionFlagsToString(int flags) {
-        StringBuilder flagsString = new StringBuilder();
-        flagsString.append("[ ");
+    private static String permissionFlagsToString(String prefix, int flags) {
+        StringBuilder flagsString = null;
         while (flags != 0) {
+            if (flagsString == null) {
+                flagsString = new StringBuilder();
+                flagsString.append(prefix);
+                flagsString.append("[ ");
+            }
             final int flag = 1 << Integer.numberOfTrailingZeros(flags);
             flags &= ~flag;
             flagsString.append(PackageManager.permissionFlagToString(flag));
             flagsString.append(' ');
         }
-        flagsString.append(']');
-        return flagsString.toString();
+        if (flagsString != null) {
+            flagsString.append(']');
+            return flagsString.toString();
+        } else {
+            return "";
+        }
     }
 
     void dumpInstallPermissionsLPr(PrintWriter pw, String prefix, ArraySet<String> permissionNames,
@@ -4403,8 +4436,8 @@
                     continue;
                 }
                 pw.print(prefix); pw.print("  "); pw.print(permissionState.getName());
-                    pw.print(", granted="); pw.print(permissionState.isGranted());
-                    pw.print(", flags="); pw.println(permissionFlagsToString(
+                    pw.print(": granted="); pw.print(permissionState.isGranted());
+                    pw.println(permissionFlagsToString(", flags=",
                         permissionState.getFlags()));
             }
         }