Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e639da7b authored by Dianne Hackborn's avatar Dianne Hackborn
Browse files

New development permissions.

These are permissions that an application can request, but won't
normally be granted.  To have the permission granted, the user
must explicitly do so through a new "adb shell pm grant" command.

I put these permissions in the "development tools" permission
group.  Looking at the stuff there, I think all of the permissions
we already had in that group should be turned to development
permissions; I don't think any of them are protecting public APIs,
and they are really not things normal applications should use.

The support this, the protectionLevel of a permission has been
modified to consist of a base protection type with additional
flags.  The signatureOrSystem permission has thus been converted
to a signature base type with a new "system" flag; you can use
"system" and/or "dangerous" flags with signature permissions as
desired.

The permissions UI has been updated to understand these new types
of permissions and know when to display them.  Along with doing
that, it also now shows you which permissions are new when updating
an existing application.

This also starts laying the ground-work for "optional" permissions
(which development permissions are a certain specialized form of).
Completing that work requires some more features in the package
manager to understand generic optional permissions (having a
facility to not apply them when installing), along with the
appropriate UI for the app and user to manage those permissions.

Change-Id: I6571785c6bb5f6b291862b7a9be584885f88f3a5
parent b8678d76
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -6181,6 +6181,8 @@ package android.content.pm {
    method public int describeContents();
    method public void writeToParcel(android.os.Parcel, int);
    field public static final android.os.Parcelable.Creator CREATOR;
    field public static final int REQUESTED_PERMISSION_GRANTED = 2; // 0x2
    field public static final int REQUESTED_PERMISSION_REQUIRED = 1; // 0x1
    field public android.content.pm.ActivityInfo[] activities;
    field public android.content.pm.ApplicationInfo applicationInfo;
    field public android.content.pm.ConfigurationInfo[] configPreferences;
@@ -6194,6 +6196,7 @@ package android.content.pm {
    field public android.content.pm.ActivityInfo[] receivers;
    field public android.content.pm.FeatureInfo[] reqFeatures;
    field public java.lang.String[] requestedPermissions;
    field public int[] requestedPermissionsFlags;
    field public android.content.pm.ServiceInfo[] services;
    field public java.lang.String sharedUserId;
    field public int sharedUserLabel;
@@ -6416,6 +6419,10 @@ package android.content.pm {
    method public java.lang.CharSequence loadDescription(android.content.pm.PackageManager);
    field public static final android.os.Parcelable.Creator CREATOR;
    field public static final int PROTECTION_DANGEROUS = 1; // 0x1
    field public static final int PROTECTION_FLAG_DEVELOPMENT = 32; // 0x20
    field public static final int PROTECTION_FLAG_SYSTEM = 16; // 0x10
    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_NORMAL = 0; // 0x0
    field public static final int PROTECTION_SIGNATURE = 2; // 0x2
    field public static final int PROTECTION_SIGNATURE_OR_SYSTEM = 3; // 0x3
+51 −18
Original line number Diff line number Diff line
@@ -126,6 +126,16 @@ public final class Pm {
            return;
        }

        if ("grant".equals(op)) {
            runGrantRevokePermission(true);
            return;
        }

        if ("revoke".equals(op)) {
            runGrantRevokePermission(false);
            return;
        }

        if ("set-install-location".equals(op)) {
            runSetInstallLocation();
            return;
@@ -596,8 +606,9 @@ public final class Pm {
                if (groups && groupName == null && pi.group != null) {
                    continue;
                }
                if (pi.protectionLevel < startProtectionLevel
                        || pi.protectionLevel > endProtectionLevel) {
                final int base = pi.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE;
                if (base < startProtectionLevel
                        || base > endProtectionLevel) {
                    continue;
                }
                if (summary) {
@@ -627,22 +638,8 @@ public final class Pm {
                                    + loadText(pi, pi.descriptionRes,
                                            pi.nonLocalizedDescription));
                        }
                        String protLevel = "unknown";
                        switch(pi.protectionLevel) {
                            case PermissionInfo.PROTECTION_DANGEROUS:
                                protLevel = "dangerous";
                                break;
                            case PermissionInfo.PROTECTION_NORMAL:
                                protLevel = "normal";
                                break;
                            case PermissionInfo.PROTECTION_SIGNATURE:
                                protLevel = "signature";
                                break;
                            case PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM:
                                protLevel = "signatureOrSystem";
                                break;
                        }
                        System.out.println(prefix + "  protectionLevel:" + protLevel);
                        System.out.println(prefix + "  protectionLevel:"
                                + PermissionInfo.protectionToString(pi.protectionLevel));
                    }
                }
            }
@@ -1063,6 +1060,36 @@ public final class Pm {
        }
    }

    private void runGrantRevokePermission(boolean grant) {
        String pkg = nextArg();
        if (pkg == null) {
            System.err.println("Error: no package specified");
            showUsage();
            return;
        }
        String perm = nextArg();
        if (perm == null) {
            System.err.println("Error: no permission specified");
            showUsage();
            return;
        }
        try {
            if (grant) {
                mPm.grantPermission(pkg, perm);
            } else {
                mPm.revokePermission(pkg, perm);
            }
        } catch (RemoteException e) {
            System.err.println(e.toString());
            System.err.println(PM_NOT_RUNNING_ERR);
        } catch (IllegalArgumentException e) {
            System.err.println("Bad argument: " + e.toString());
            showUsage();
        } catch (SecurityException e) {
            System.err.println("Operation not allowed: " + e.toString());
        }
    }

    /**
     * Displays the package file for a package.
     * @param pckg
@@ -1158,6 +1185,8 @@ public final class Pm {
        System.err.println("       pm enable PACKAGE_OR_COMPONENT");
        System.err.println("       pm disable PACKAGE_OR_COMPONENT");
        System.err.println("       pm disable-user PACKAGE_OR_COMPONENT");
        System.err.println("       pm grant PACKAGE PERMISSION");
        System.err.println("       pm revoke PACKAGE PERMISSION");
        System.err.println("       pm set-install-location [0/auto] [1/internal] [2/external]");
        System.err.println("       pm get-install-location");
        System.err.println("       pm create-profile USER_NAME");
@@ -1208,6 +1237,10 @@ public final class Pm {
        System.err.println("pm enable, disable, disable-user: these commands change the enabled state");
        System.err.println("  of a given package or component (written as \"package/class\").");
        System.err.println("");
        System.err.println("pm grant, revoke: these commands either grant or revoke permissions");
        System.err.println("  to applications.  Only optional permissions the application has");
        System.err.println("  declared can be granted or revoked.");
        System.err.println("");
        System.err.println("pm get-install-location: returns the current install location.");
        System.err.println("    0 [auto]: Let system decide the best location");
        System.err.println("    1 [internal]: Install on internal device storage");
+18 −0
Original line number Diff line number Diff line
@@ -331,6 +331,24 @@ final class ApplicationPackageManager extends PackageManager {
        }
    }

    @Override
    public void grantPermission(String packageName, String permissionName) {
        try {
            mPM.grantPermission(packageName, permissionName);
        } catch (RemoteException e) {
            throw new RuntimeException("Package manager has died", e);
        }
    }

    @Override
    public void revokePermission(String packageName, String permissionName) {
        try {
            mPM.revokePermission(packageName, permissionName);
        } catch (RemoteException e) {
            throw new RuntimeException("Package manager has died", e);
        }
    }

    @Override
    public int checkSignatures(String pkg1, String pkg2) {
        try {
+5 −1
Original line number Diff line number Diff line
@@ -82,6 +82,10 @@ interface IPackageManager {
    
    void removePermission(String name);

    void grantPermission(String packageName, String permissionName);

    void revokePermission(String packageName, String permissionName);

    boolean isProtectedBroadcast(String actionName);
    
    int checkSignatures(String pkg1, String pkg2);
+26 −0
Original line number Diff line number Diff line
@@ -140,6 +140,30 @@ public class PackageInfo implements Parcelable {
     */
    public String[] requestedPermissions;
    
    /**
     * Array of flags of all {@link android.R.styleable#AndroidManifestUsesPermission
     * &lt;uses-permission&gt;} tags included under &lt;manifest&gt;,
     * or null if there were none.  This is only filled in if the flag
     * {@link PackageManager#GET_PERMISSIONS} was set.  Each value matches
     * the corresponding entry in {@link #requestedPermissions}, and will have
     * the flags {@link #REQUESTED_PERMISSION_REQUIRED} and
     * {@link #REQUESTED_PERMISSION_GRANTED} set as appropriate.
     */
    public int[] requestedPermissionsFlags;

    /**
     * Flag for {@link #requestedPermissionsFlags}: the requested permission
     * is required for the application to run; the user can not optionally
     * disable it.
     */
    public static final int REQUESTED_PERMISSION_REQUIRED = 1<<0;

    /**
     * Flag for {@link #requestedPermissionsFlags}: the requested permission
     * is currently granted to the application.
     */
    public static final int REQUESTED_PERMISSION_GRANTED = 1<<1;

    /**
     * Array of all signatures read from the package file.  This is only filled
     * in if the flag {@link PackageManager#GET_SIGNATURES} was set.
@@ -229,6 +253,7 @@ public class PackageInfo implements Parcelable {
        dest.writeTypedArray(instrumentation, parcelableFlags);
        dest.writeTypedArray(permissions, parcelableFlags);
        dest.writeStringArray(requestedPermissions);
        dest.writeIntArray(requestedPermissionsFlags);
        dest.writeTypedArray(signatures, parcelableFlags);
        dest.writeTypedArray(configPreferences, parcelableFlags);
        dest.writeTypedArray(reqFeatures, parcelableFlags);
@@ -266,6 +291,7 @@ public class PackageInfo implements Parcelable {
        instrumentation = source.createTypedArray(InstrumentationInfo.CREATOR);
        permissions = source.createTypedArray(PermissionInfo.CREATOR);
        requestedPermissions = source.createStringArray();
        requestedPermissionsFlags = source.createIntArray();
        signatures = source.createTypedArray(Signature.CREATOR);
        configPreferences = source.createTypedArray(ConfigurationInfo.CREATOR);
        reqFeatures = source.createTypedArray(FeatureInfo.CREATOR);
Loading