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

Commit 8c7f700a authored by Svet Ganov's avatar Svet Ganov Committed by Svetoslav
Browse files

Add permission meta-state flags to support grant/revoke permission policy.

We now maintain a mata-state with each permission in the form of flags
specyfying the policy for this permission. This enables support of the
following use cases:

1. The user denies a permission with prejudice in which case an app cannot
   request the permission at runtime. If an app requests such a permssion
   it gets a denial unless the user grants the permission from settings.

2. A legacy app with disabled app-ops being upgraded to support runtime
   permissions. The disabled app ops are converted to permission revocations.
   The app ops manager is a part of the activity manger which sits on top
   of the package manager, hence the latter cannot have a dependency on the
   former. To avoid this the package installer which is the global
   permission managment authority marks the permission as revoked on
   upgrade and the package manager revokes it on upgrade.

3. A device policy fixing a permission in a granted or revoked state. This
   additional information is folded in the meta-state flags and neither
   apps can request such permissions if revoked not the user can change
   the permission state in the UI.

Change-Id: I443e8a7bb94bfcb4ff6003d158e1408c26149811
parent 3ce72722
Loading
Loading
Loading
Loading
+16 −4
Original line number Diff line number Diff line
@@ -9505,6 +9505,7 @@ package android.content.pm {
    method public abstract android.content.pm.PackageInstaller getPackageInstaller();
    method public abstract java.lang.String[] getPackagesForUid(int);
    method public abstract java.util.List<android.content.pm.PackageInfo> getPackagesHoldingPermissions(java.lang.String[], int);
    method public abstract int getPermissionFlags(java.lang.String, java.lang.String, android.os.UserHandle);
    method public abstract android.content.pm.PermissionGroupInfo getPermissionGroupInfo(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
    method public abstract android.content.pm.PermissionInfo getPermissionInfo(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
    method public abstract int getPreferredActivities(java.util.List<android.content.IntentFilter>, java.util.List<android.content.ComponentName>, java.lang.String);
@@ -9522,7 +9523,7 @@ package android.content.pm {
    method public abstract android.graphics.drawable.Drawable getUserBadgedIcon(android.graphics.drawable.Drawable, android.os.UserHandle);
    method public abstract java.lang.CharSequence getUserBadgedLabel(java.lang.CharSequence, android.os.UserHandle);
    method public abstract android.content.res.XmlResourceParser getXml(java.lang.String, int, android.content.pm.ApplicationInfo);
    method public abstract void grantPermission(java.lang.String, java.lang.String, android.os.UserHandle);
    method public abstract void grantRuntimePermission(java.lang.String, java.lang.String, android.os.UserHandle);
    method public abstract boolean hasSystemFeature(java.lang.String);
    method public abstract boolean isSafeMode();
    method public abstract java.util.List<android.content.pm.ResolveInfo> queryBroadcastReceivers(android.content.Intent, int);
@@ -9538,10 +9539,11 @@ package android.content.pm {
    method public abstract android.content.pm.ResolveInfo resolveActivity(android.content.Intent, int);
    method public abstract android.content.pm.ProviderInfo resolveContentProvider(java.lang.String, int);
    method public abstract android.content.pm.ResolveInfo resolveService(android.content.Intent, int);
    method public abstract void revokePermission(java.lang.String, java.lang.String, android.os.UserHandle);
    method public abstract void revokeRuntimePermission(java.lang.String, java.lang.String, android.os.UserHandle);
    method public abstract void setApplicationEnabledSetting(java.lang.String, int, int);
    method public abstract void setComponentEnabledSetting(android.content.ComponentName, int, int);
    method public abstract void setInstallerPackageName(java.lang.String, java.lang.String);
    method public abstract void updatePermissionFlags(java.lang.String, java.lang.String, int, int, android.os.UserHandle);
    method public abstract void verifyPendingInstall(int, int);
    field public static final java.lang.String ACTION_REQUEST_PERMISSIONS = "android.content.pm.action.REQUEST_PERMISSIONS";
    field public static final int COMPONENT_ENABLED_STATE_DEFAULT = 0; // 0x0
@@ -9627,6 +9629,10 @@ package android.content.pm {
    field public static final java.lang.String FEATURE_WEBVIEW = "android.software.webview";
    field public static final java.lang.String FEATURE_WIFI = "android.hardware.wifi";
    field public static final java.lang.String FEATURE_WIFI_DIRECT = "android.hardware.wifi.direct";
    field public static final int FLAG_PERMISSION_POLICY_FIXED = 4; // 0x4
    field public static final int FLAG_PERMISSION_REVOKE_ON_UPGRADE = 8; // 0x8
    field public static final int FLAG_PERMISSION_USER_FIXED = 2; // 0x2
    field public static final int FLAG_PERMISSION_USER_SET = 1; // 0x1
    field public static final int GET_ACTIVITIES = 1; // 0x1
    field public static final int GET_CONFIGURATIONS = 16384; // 0x4000
    field public static final int GET_DISABLED_COMPONENTS = 512; // 0x200
@@ -9679,6 +9685,7 @@ package android.content.pm {
    field public static final int INSTALL_PARSE_FAILED_NO_CERTIFICATES = -103; // 0xffffff99
    field public static final int INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION = -102; // 0xffffff9a
    field public static final int INSTALL_SUCCEEDED = 1; // 0x1
    field public static final int MASK_PERMISSION_FLAGS = 15; // 0xf
    field public static final int MATCH_ALL = 131072; // 0x20000
    field public static final int MATCH_DEFAULT_ONLY = 65536; // 0x10000
    field public static final long MAXIMUM_VERIFICATION_TIMEOUT = 3600000L; // 0x36ee80L
@@ -9699,6 +9706,9 @@ package android.content.pm {
    ctor public PackageManager.NameNotFoundException(java.lang.String);
  }
  public static abstract class PackageManager.PermissionFlags implements java.lang.annotation.Annotation {
  }
  public class PackageStats implements android.os.Parcelable {
    ctor public PackageStats(java.lang.String);
    ctor public PackageStats(android.os.Parcel);
@@ -34042,6 +34052,7 @@ package android.test.mock {
    method public android.content.pm.PackageInstaller getPackageInstaller();
    method public java.lang.String[] getPackagesForUid(int);
    method public java.util.List<android.content.pm.PackageInfo> getPackagesHoldingPermissions(java.lang.String[], int);
    method public int getPermissionFlags(java.lang.String, java.lang.String, android.os.UserHandle);
    method public android.content.pm.PermissionGroupInfo getPermissionGroupInfo(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
    method public android.content.pm.PermissionInfo getPermissionInfo(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
    method public int getPreferredActivities(java.util.List<android.content.IntentFilter>, java.util.List<android.content.ComponentName>, java.lang.String);
@@ -34059,7 +34070,7 @@ package android.test.mock {
    method public android.graphics.drawable.Drawable getUserBadgedIcon(android.graphics.drawable.Drawable, android.os.UserHandle);
    method public java.lang.CharSequence getUserBadgedLabel(java.lang.CharSequence, android.os.UserHandle);
    method public android.content.res.XmlResourceParser getXml(java.lang.String, int, android.content.pm.ApplicationInfo);
    method public void grantPermission(java.lang.String, java.lang.String, android.os.UserHandle);
    method public void grantRuntimePermission(java.lang.String, java.lang.String, android.os.UserHandle);
    method public boolean hasSystemFeature(java.lang.String);
    method public boolean isSafeMode();
    method public java.util.List<android.content.pm.ResolveInfo> queryBroadcastReceivers(android.content.Intent, int);
@@ -34075,11 +34086,12 @@ package android.test.mock {
    method public android.content.pm.ResolveInfo resolveActivity(android.content.Intent, int);
    method public android.content.pm.ProviderInfo resolveContentProvider(java.lang.String, int);
    method public android.content.pm.ResolveInfo resolveService(android.content.Intent, int);
    method public void revokePermission(java.lang.String, java.lang.String, android.os.UserHandle);
    method public void revokeRuntimePermission(java.lang.String, java.lang.String, android.os.UserHandle);
    method public void setApplicationEnabledSetting(java.lang.String, int, int);
    method public void setComponentEnabledSetting(android.content.ComponentName, int, int);
    method public boolean setDefaultBrowserPackageName(java.lang.String, int);
    method public void setInstallerPackageName(java.lang.String, java.lang.String);
    method public void updatePermissionFlags(java.lang.String, java.lang.String, int, int, android.os.UserHandle);
    method public void verifyPendingInstall(int, int);
  }
+2 −2
Original line number Diff line number Diff line
@@ -1609,9 +1609,9 @@ public final class Pm {

        try {
            if (grant) {
                mPm.grantPermission(pkg, perm, userId);
                mPm.grantRuntimePermission(pkg, perm, userId);
            } else {
                mPm.revokePermission(pkg, perm, userId);
                mPm.revokeRuntimePermission(pkg, perm, userId);
            }
            return 0;
        } catch (RemoteException e) {
+26 −4
Original line number Diff line number Diff line
@@ -446,18 +446,40 @@ final class ApplicationPackageManager extends PackageManager {
    }

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

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

    @Override
    public int getPermissionFlags(String permissionName, String packageName, UserHandle user) {
        try {
            mPM.grantPermission(packageName, permissionName, user.getIdentifier());
            return mPM.getPermissionFlags(permissionName, packageName, user.getIdentifier());
        } catch (RemoteException e) {
            throw new RuntimeException("Package manager has died", e);
        }
    }

    @Override
    public void revokePermission(String packageName, String permissionName, UserHandle user) {
    public void updatePermissionFlags(String permissionName, String packageName,
            int flagMask, int flagValues, UserHandle user) {
        try {
            mPM.revokePermission(packageName, permissionName, user.getIdentifier());
            mPM.updatePermissionFlags(permissionName, packageName, flagMask,
                    flagValues, user.getIdentifier());
        } catch (RemoteException e) {
            throw new RuntimeException("Package manager has died", e);
        }
+7 −2
Original line number Diff line number Diff line
@@ -96,9 +96,14 @@ interface IPackageManager {

    void removePermission(String name);

    void grantPermission(String packageName, String permissionName, int userId);
    void grantRuntimePermission(String packageName, String permissionName, int userId);

    void revokePermission(String packageName, String permissionName, int userId);
    void revokeRuntimePermission(String packageName, String permissionName, int userId);

    int getPermissionFlags(String permissionName, String packageName, int userId);

    void updatePermissionFlags(String permissionName, String packageName, int flagMask,
            int flagValues, int userId);

    boolean isProtectedBroadcast(String actionName);

+105 −7
Original line number Diff line number Diff line
@@ -1888,6 +1888,57 @@ public abstract class PackageManager {
    public static final String EXTRA_FAILURE_EXISTING_PERMISSION
            = "android.content.pm.extra.FAILURE_EXISTING_PERMISSION";

   /**
    * Permission flag: The permission is set in its current state
    * by the user and apps can still request it at runtime.
    *
    * @hide
    */
    @SystemApi
    public static final int FLAG_PERMISSION_USER_SET = 1 << 0;

    /**
     * Permission flag: The permission is set in its current state
     * by the user and it is fixed, i.e. apps can no longer request
     * this permission.
     *
     * @hide
     */
    @SystemApi
    public static final int FLAG_PERMISSION_USER_FIXED =  1 << 1;

    /**
     * Permission flag: The permission is set in its current state
     * by device policy and neither apps nor the user can change
     * its state.
     *
     * @hide
     */
    @SystemApi
    public static final int FLAG_PERMISSION_POLICY_FIXED =  1 << 2;

    /**
     * Permission flag: The permission is set in a granted state but
     * access to resources it guards is restricted by other means to
     * enable revoking a permission on legacy apps that do not support
     * runtime permissions. If this permission is upgraded to runtime
     * because the app was updated to support runtime permissions, the
     * the permission will be revoked in the upgrade process.
     *
     * @hide
     */
    @SystemApi
    public static final int FLAG_PERMISSION_REVOKE_ON_UPGRADE =  1 << 3;


    /**
     * Mask for all permission flags.
     *
     * @hide
     */
    @SystemApi
    public static final int MASK_PERMISSION_FLAGS = 0xF;

    /**
     * Retrieve overall information about an application package that is
     * installed on the system.
@@ -2374,6 +2425,20 @@ public abstract class PackageManager {
     */
    public abstract void removePermission(String name);


    /**
     * Permission flags set when granting or revoking a permission.
     *
     * @hide
     */
    @SystemApi
    @IntDef({FLAG_PERMISSION_USER_SET,
            FLAG_PERMISSION_USER_FIXED,
            FLAG_PERMISSION_POLICY_FIXED,
            FLAG_PERMISSION_REVOKE_ON_UPGRADE})
    @Retention(RetentionPolicy.SOURCE)
    public @interface PermissionFlags {}

    /**
     * Grant a runtime permission to an application which the application does not
     * already have. The permission must have been requested by the application.
@@ -2389,19 +2454,20 @@ public abstract class PackageManager {
     * @param permissionName The permission name to grant.
     * @param user The user for which to grant the permission.
     *
     * @see #revokePermission(String, String, android.os.UserHandle)
     * @see #revokeRuntimePermission(String, String, android.os.UserHandle)
     * @see android.content.pm.PackageManager.PermissionFlags
     *
     * @hide
     */
    @SystemApi
    public abstract void grantPermission(@NonNull String packageName,
    public abstract void grantRuntimePermission(@NonNull String packageName,
            @NonNull String permissionName, @NonNull UserHandle user);

    /**
     * Revoke a runtime permission that was previously granted by {@link
     * #grantPermission(String, String, android.os.UserHandle)}. The permission
     * must have been requested by and granted to the application. If the
     * application is not allowed to hold the permission, a {@link
     * #grantRuntimePermission(String, String, android.os.UserHandle)}. The
     * permission must have been requested by and granted to the application.
     * If the application is not allowed to hold the permission, a {@link
     * java.lang.SecurityException} is thrown.
     * <p>
     * <strong>Note: </strong>Using this API requires holding
@@ -2413,14 +2479,46 @@ public abstract class PackageManager {
     * @param permissionName The permission name to revoke.
     * @param user The user for which to revoke the permission.
     *
     * @see #grantPermission(String, String, android.os.UserHandle)
     * @see #grantRuntimePermission(String, String, android.os.UserHandle)
     * @see android.content.pm.PackageManager.PermissionFlags
     *
     * @hide
     */
    @SystemApi
    public abstract void revokePermission(@NonNull String packageName,
    public abstract void revokeRuntimePermission(@NonNull String packageName,
            @NonNull String permissionName, @NonNull UserHandle user);

    /**
     * Gets the state flags associated with a permission.
     *
     * @param permissionName The permission for which to get the flags.
     * @param packageName The package name for which to get the flags.
     * @param user The user for which to get permission flags.
     * @return The permission flags.
     *
     * @hide
     */
    @SystemApi
    public abstract @PermissionFlags int getPermissionFlags(String permissionName,
            String packageName, @NonNull UserHandle user);

    /**
     * Updates the flags associated with a permission by replacing the flags in
     * the specified mask with the provided flag values.
     *
     * @param permissionName The permission for which to update the flags.
     * @param packageName The package name for which to update the flags.
     * @param flagMask The flags which to replace.
     * @param flagValues The flags with which to replace.
     * @param user The user for which to update the permission flags.
     *
     * @hide
     */
    @SystemApi
    public abstract void updatePermissionFlags(String permissionName,
            String packageName, @PermissionFlags int flagMask, int flagValues,
            @NonNull UserHandle user);

    /**
     * Returns an {@link android.content.Intent} suitable for passing to
     * {@link android.app.Activity#startActivityForResult(android.content.Intent, int)}
Loading