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

Commit d49489b3 authored by Amith Yamasani's avatar Amith Yamasani
Browse files

Permissions control via profile/device owner admin

Profile owners and Device owners can set policies for runtime
permissions. Blanket grant/deny policy can be set for a user.
They can also explicitly grant/revoke permissions for specific apps
which cannot be overridden by the user and will not be prompted.

[More implementation required in PackageManagerService and
 PackageInstaller]

Bug: 20666663
Change-Id: I2c25c18c2a195db9023a17716d5896970848bb45
parent 50ea9422
Loading
Loading
Loading
Loading
+7 −1
Original line number Diff line number Diff line
@@ -5729,6 +5729,7 @@ package android.app.admin {
    method public int getPasswordMinimumSymbols(android.content.ComponentName);
    method public int getPasswordMinimumUpperCase(android.content.ComponentName);
    method public int getPasswordQuality(android.content.ComponentName);
    method public int getPermissionPolicy(android.content.ComponentName);
    method public java.util.List<java.lang.String> getPermittedAccessibilityServices(android.content.ComponentName);
    method public java.util.List<java.lang.String> getPermittedInputMethods(android.content.ComponentName);
    method public boolean getScreenCaptureDisabled(android.content.ComponentName);
@@ -5781,6 +5782,8 @@ package android.app.admin {
    method public void setPasswordMinimumSymbols(android.content.ComponentName, int);
    method public void setPasswordMinimumUpperCase(android.content.ComponentName, int);
    method public void setPasswordQuality(android.content.ComponentName, int);
    method public boolean setPermissionGranted(android.content.ComponentName, java.lang.String, java.lang.String, boolean);
    method public void setPermissionPolicy(android.content.ComponentName, int);
    method public boolean setPermittedAccessibilityServices(android.content.ComponentName, java.util.List<java.lang.String>);
    method public boolean setPermittedInputMethods(android.content.ComponentName, java.util.List<java.lang.String>);
    method public void setPreferredSetupActivity(android.content.ComponentName, android.content.ComponentName);
@@ -5869,6 +5872,9 @@ package android.app.admin {
    field public static final int PASSWORD_QUALITY_NUMERIC_COMPLEX = 196608; // 0x30000
    field public static final int PASSWORD_QUALITY_SOMETHING = 65536; // 0x10000
    field public static final int PASSWORD_QUALITY_UNSPECIFIED = 0; // 0x0
    field public static final int PERMISSION_POLICY_AUTO_DENY = 2; // 0x2
    field public static final int PERMISSION_POLICY_AUTO_GRANT = 1; // 0x1
    field public static final int PERMISSION_POLICY_PROMPT = 0; // 0x0
    field public static final int RESET_PASSWORD_REQUIRE_ENTRY = 1; // 0x1
    field public static final int WIPE_EXTERNAL_STORAGE = 1; // 0x1
    field public static final int WIPE_RESET_PROTECTION_DATA = 2; // 0x2
@@ -30433,7 +30439,6 @@ package android.telecom {
  public static abstract class InCallService.VideoCall {
    ctor public InCallService.VideoCall();
    method public abstract void registerCallback(android.telecom.InCallService.VideoCall.Callback);
    method public abstract void unregisterCallback();
    method public abstract void requestCallDataUsage();
    method public abstract void requestCameraCapabilities();
    method public abstract void sendSessionModifyRequest(android.telecom.VideoProfile);
@@ -30444,6 +30449,7 @@ package android.telecom {
    method public abstract void setPauseImage(java.lang.String);
    method public abstract void setPreviewSurface(android.view.Surface);
    method public abstract void setZoom(float);
    method public abstract void unregisterCallback();
  }
  public static abstract class InCallService.VideoCall.Callback {
+7 −1
Original line number Diff line number Diff line
@@ -5828,6 +5828,7 @@ package android.app.admin {
    method public int getPasswordMinimumSymbols(android.content.ComponentName);
    method public int getPasswordMinimumUpperCase(android.content.ComponentName);
    method public int getPasswordQuality(android.content.ComponentName);
    method public int getPermissionPolicy(android.content.ComponentName);
    method public java.util.List<java.lang.String> getPermittedAccessibilityServices(android.content.ComponentName);
    method public java.util.List<java.lang.String> getPermittedAccessibilityServices(int);
    method public java.util.List<java.lang.String> getPermittedInputMethods(android.content.ComponentName);
@@ -5886,6 +5887,8 @@ package android.app.admin {
    method public void setPasswordMinimumSymbols(android.content.ComponentName, int);
    method public void setPasswordMinimumUpperCase(android.content.ComponentName, int);
    method public void setPasswordQuality(android.content.ComponentName, int);
    method public boolean setPermissionGranted(android.content.ComponentName, java.lang.String, java.lang.String, boolean);
    method public void setPermissionPolicy(android.content.ComponentName, int);
    method public boolean setPermittedAccessibilityServices(android.content.ComponentName, java.util.List<java.lang.String>);
    method public boolean setPermittedInputMethods(android.content.ComponentName, java.util.List<java.lang.String>);
    method public void setPreferredSetupActivity(android.content.ComponentName, android.content.ComponentName);
@@ -5979,6 +5982,9 @@ package android.app.admin {
    field public static final int PASSWORD_QUALITY_NUMERIC_COMPLEX = 196608; // 0x30000
    field public static final int PASSWORD_QUALITY_SOMETHING = 65536; // 0x10000
    field public static final int PASSWORD_QUALITY_UNSPECIFIED = 0; // 0x0
    field public static final int PERMISSION_POLICY_AUTO_DENY = 2; // 0x2
    field public static final int PERMISSION_POLICY_AUTO_GRANT = 1; // 0x1
    field public static final int PERMISSION_POLICY_PROMPT = 0; // 0x0
    field public static final int RESET_PASSWORD_REQUIRE_ENTRY = 1; // 0x1
    field public static final int WIPE_EXTERNAL_STORAGE = 1; // 0x1
    field public static final int WIPE_RESET_PROTECTION_DATA = 2; // 0x2
@@ -32550,7 +32556,6 @@ package android.telecom {
  public static abstract class InCallService.VideoCall {
    ctor public InCallService.VideoCall();
    method public abstract void registerCallback(android.telecom.InCallService.VideoCall.Callback);
    method public abstract void unregisterCallback();
    method public abstract void requestCallDataUsage();
    method public abstract void requestCameraCapabilities();
    method public abstract void sendSessionModifyRequest(android.telecom.VideoProfile);
@@ -32561,6 +32566,7 @@ package android.telecom {
    method public abstract void setPauseImage(java.lang.String);
    method public abstract void setPreviewSurface(android.view.Surface);
    method public abstract void setZoom(float);
    method public abstract void unregisterCallback();
  }
  public static abstract class InCallService.VideoCall.Callback {
+72 −0
Original line number Diff line number Diff line
@@ -807,6 +807,24 @@ public class DevicePolicyManager {
    public static final String ACTION_SYSTEM_UPDATE_POLICY_CHANGED
            = "android.app.action.SYSTEM_UPDATE_POLICY_CHANGED";

    /**
     * Permission policy to prompt user for new permission requests for runtime permissions.
     * Already granted or denied permissions are not affected by this.
     */
    public static final int PERMISSION_POLICY_PROMPT = 0;

    /**
     * Permission policy to always grant new permission requests for runtime permissions.
     * Already granted or denied permissions are not affected by this.
     */
    public static final int PERMISSION_POLICY_AUTO_GRANT = 1;

    /**
     * Permission policy to always deny new permission requests for runtime permissions.
     * Already granted or denied permissions are not affected by this.
     */
    public static final int PERMISSION_POLICY_AUTO_DENY = 2;


    /**
     * Return true if the given administrator component is currently
@@ -4342,4 +4360,58 @@ public class DevicePolicyManager {
            Log.w(TAG, "Failed talking with device policy service", re);
        }
    }

    /**
     * Called by profile or device owners to set the default response for future runtime permission
     * requests by applications. The policy can allow for normal operation which prompts the
     * user to grant a permission, or can allow automatic granting or denying of runtime
     * permission requests by an application. This also applies to new permissions declared by app
     * updates.
     * @param admin Which profile or device owner this request is associated with.
     * @param policy One of the policy constants {@link #PERMISSION_POLICY_PROMPT},
     * {@link #PERMISSION_POLICY_AUTO_GRANT} and {@link #PERMISSION_POLICY_AUTO_DENY}.
     */
    public void setPermissionPolicy(ComponentName admin, int policy) {
        try {
            mService.setPermissionPolicy(admin, policy);
        } catch (RemoteException re) {
            Log.w(TAG, "Failed talking with device policy service", re);
        }
    }

    /**
     * Returns the current runtime permission policy set by the device or profile owner. The
     * default is {@link #PERMISSION_POLICY_PROMPT}.
     * @param admin Which profile or device owner this request is associated with.
     * @return the current policy for future permission requests.
     */
    public int getPermissionPolicy(ComponentName admin) {
        try {
            return mService.getPermissionPolicy(admin);
        } catch (RemoteException re) {
            return PERMISSION_POLICY_PROMPT;
        }
    }

    /**
     * Grants or revokes a runtime permission to a specific application so that the user
     * does not have to be prompted. This might affect all permissions in a group that the
     * runtime permission belongs to. This method can only be called by a profile or device
     * owner.
     * @param admin Which profile or device owner this request is associated with.
     * @param packageName The application to grant or revoke a permission to.
     * @param permission The permission to grant or revoke.
     * @param granted Whether or not to grant the permission. If false, all permissions in the
     * associated permission group will be denied.
     * @return whether the permission was successfully granted or revoked
     */
    public boolean setPermissionGranted(ComponentName admin, String packageName,
            String permission, boolean granted) {
        try {
            return mService.setPermissionGranted(admin, packageName, permission, granted);
        } catch (RemoteException re) {
            Log.w(TAG, "Failed talking with device policy service", re);
            return false;
        }
    }
}
+5 −0
Original line number Diff line number Diff line
@@ -229,4 +229,9 @@ interface IDevicePolicyManager {
    boolean getDoNotAskCredentialsOnBoot();

    void notifyPendingSystemUpdate(in long updateReceivedTime);

    void setPermissionPolicy(in ComponentName admin, int policy);
    int  getPermissionPolicy(in ComponentName admin);
    boolean setPermissionGranted(in ComponentName admin, String packageName, String permission,
            boolean granted);
}
+63 −1
Original line number Diff line number Diff line
@@ -182,6 +182,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
    private static final String ATTR_PERMISSION_PROVIDER = "permission-provider";
    private static final String ATTR_SETUP_COMPLETE = "setup-complete";
    private static final String ATTR_PREFERRED_SETUP_ACTIVITY = "setup-activity";
    private static final String ATTR_PERMISSION_POLICY = "permission-policy";

    private static final String ATTR_DELEGATED_CERT_INSTALLER = "delegated-cert-installer";

@@ -300,6 +301,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
        int mPasswordOwner = -1;
        long mLastMaximumTimeToLock = -1;
        boolean mUserSetupComplete = false;
        int mPermissionPolicy;

        final HashMap<ComponentName, ActiveAdmin> mAdminMap = new HashMap<>();
        final ArrayList<ActiveAdmin> mAdminList = new ArrayList<>();
@@ -1409,6 +1411,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
                out.attribute(null, ATTR_SETUP_COMPLETE,
                        Boolean.toString(true));
            }
            if (policy.mPermissionPolicy != DevicePolicyManager.PERMISSION_POLICY_PROMPT) {
                out.attribute(null, ATTR_PERMISSION_POLICY,
                        Integer.toString(policy.mPermissionPolicy));
            }
            if (policy.mDelegatedCertInstallerPackage != null) {
                out.attribute(null, ATTR_DELEGATED_CERT_INSTALLER,
                        policy.mDelegatedCertInstallerPackage);
@@ -1537,6 +1543,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
            if (userSetupComplete != null && Boolean.toString(true).equals(userSetupComplete)) {
                policy.mUserSetupComplete = true;
            }
            String permissionPolicy = parser.getAttributeValue(null, ATTR_PERMISSION_POLICY);
            if (!TextUtils.isEmpty(permissionPolicy)) {
                policy.mPermissionPolicy = Integer.parseInt(permissionPolicy);
            }
            policy.mDelegatedCertInstallerPackage = parser.getAttributeValue(null,
                    ATTR_DELEGATED_CERT_INSTALLER);
            String preferredSetupActivity =
@@ -4253,14 +4263,22 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
            return;
        }
        UserHandle callingUser = Binder.getCallingUserHandle();
        int userId = callingUser.getIdentifier();
        // Check if this is the profile owner who is calling
        getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
        synchronized (this) {
            // Reset some of the profile-owner policies
            DevicePolicyData policy = getUserData(userId);
            policy.mPermissionPolicy = DevicePolicyManager.PERMISSION_POLICY_PROMPT;
            policy.mDelegatedCertInstallerPackage = null;
            policy.mStatusBarEnabledState = true;
            saveSettingsLocked(userId);

            long ident = Binder.clearCallingIdentity();
            try {
                clearUserRestrictions(callingUser);
                if (mDeviceOwner != null) {
                    mDeviceOwner.removeProfileOwner(callingUser.getIdentifier());
                    mDeviceOwner.removeProfileOwner(userId);
                    mDeviceOwner.writeOwnerFile();
                }
            } finally {
@@ -6261,4 +6279,48 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
            }
        }
    }

    @Override
    public void setPermissionPolicy(ComponentName admin, int policy) throws RemoteException {
        int userId = UserHandle.getCallingUserId();
        synchronized (this) {
            getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
            DevicePolicyData userPolicy = getUserData(userId);
            if (userPolicy.mPermissionPolicy != policy) {
                userPolicy.mPermissionPolicy = policy;
                saveSettingsLocked(userId);
            }
        }
    }

    @Override
    public int getPermissionPolicy(ComponentName admin) throws RemoteException {
        int userId = UserHandle.getCallingUserId();
        synchronized (this) {
            DevicePolicyData userPolicy = getUserData(userId);
            return userPolicy.mPermissionPolicy;
        }
    }

    @Override
    public boolean setPermissionGranted(ComponentName admin, String packageName,
            String permission, boolean granted) throws RemoteException {
        UserHandle user = Binder.getCallingUserHandle();
        synchronized (this) {
            getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
            long ident = Binder.clearCallingIdentity();
            try {
                if (granted) {
                    mContext.getPackageManager().grantPermission(packageName, permission, user);
                } else {
                    mContext.getPackageManager().revokePermission(packageName, permission, user);
                }
                return true;
            } catch (SecurityException se) {
                return false;
            } finally {
                Binder.restoreCallingIdentity(ident);
            }
        }
    }
}