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

Commit 0bf8f7cc authored by Amith Yamasani's avatar Amith Yamasani
Browse files

Runtime permissions cannot be set on legacy apps by device policy

Clarify docs that runtime permissions can be granted or revoked by
a profile owner/device owner only for MNC apps and not legacy apps.

Check the targetSdkVersion and return false if legacy app.

Remove all policy flags from permissions when cleaning up
a device or profile owner.

Bug: 21835304
Bug: 21889278
Change-Id: I4271394737990983449048d112a1830f9d0f2d78
parent dd7705bb
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -4350,6 +4350,12 @@ public class DevicePolicyManager {
     * group that the runtime permission belongs to. This method can only be called
     * by a profile or device owner.
     *
     * <p/>Setting the grant state to {@link #PERMISSION_GRANT_STATE_DEFAULT default} does not
     * revoke the permission. It retains the previous grant, if any.
     *
     * <p/>Permissions can be granted or revoked only for applications built with a
     * {@code targetSdkVersion} of {@link android.os.Build.VERSION_CODES#MNC} or later.
     *
     * @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.
+2 −0
Original line number Diff line number Diff line
@@ -106,6 +106,8 @@ interface IPackageManager {
    void updatePermissionFlags(String permissionName, String packageName, int flagMask,
            int flagValues, int userId);

    void updatePermissionFlagsForAllApps(int flagMask, int flagValues, int userId);

    boolean shouldShowRequestPermissionRationale(String permissionName,
            String packageName, int userId);

+47 −5
Original line number Diff line number Diff line
@@ -3354,11 +3354,8 @@ public class PackageManagerService extends IPackageManager.Stub {
        enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false,
                "updatePermissionFlags");
        // Only the system can change policy and system fixed flags.
        // Only the system can change system fixed flags.
        if (getCallingUid() != Process.SYSTEM_UID) {
            flagMask &= ~PackageManager.FLAG_PERMISSION_POLICY_FIXED;
            flagValues &= ~PackageManager.FLAG_PERMISSION_POLICY_FIXED;
            flagMask &= ~PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
            flagValues &= ~PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
        }
@@ -3387,18 +3384,63 @@ public class PackageManagerService extends IPackageManager.Stub {
                return;
            }
            boolean hadState = permissionsState.getRuntimePermissionState(name, userId) != null;
            if (permissionsState.updatePermissionFlags(bp, userId, flagMask, flagValues)) {
                // Install and runtime permissions are stored in different places,
                // so figure out what permission changed and persist the change.
                if (permissionsState.getInstallPermissionState(name) != null) {
                    scheduleWriteSettingsLocked();
                } else if (permissionsState.getRuntimePermissionState(name, userId) != null) {
                } else if (permissionsState.getRuntimePermissionState(name, userId) != null
                        || hadState) {
                    mSettings.writeRuntimePermissionsForUserLPr(userId, false);
                }
            }
        }
    }
    /**
     * Update the permission flags for all packages and runtime permissions of a user in order
     * to allow device or profile owner to remove POLICY_FIXED.
     */
    @Override
    public void updatePermissionFlagsForAllApps(int flagMask, int flagValues, int userId) {
        if (!sUserManager.exists(userId)) {
            return;
        }
        mContext.enforceCallingOrSelfPermission(
                android.Manifest.permission.GRANT_REVOKE_PERMISSIONS,
                "updatePermissionFlagsForAllApps");
        enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false,
                "updatePermissionFlagsForAllApps");
        // Only the system can change system fixed flags.
        if (getCallingUid() != Process.SYSTEM_UID) {
            flagMask &= ~PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
            flagValues &= ~PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
        }
        synchronized (mPackages) {
            boolean changed = false;
            final int packageCount = mPackages.size();
            for (int pkgIndex = 0; pkgIndex < packageCount; pkgIndex++) {
                final PackageParser.Package pkg = mPackages.valueAt(pkgIndex);
                SettingBase sb = (SettingBase) pkg.mExtras;
                if (sb == null) {
                    continue;
                }
                PermissionsState permissionsState = sb.getPermissionsState();
                changed |= permissionsState.updatePermissionFlagsForAllPermissions(
                        userId, flagMask, flagValues);
            }
            if (changed) {
                mSettings.writeRuntimePermissionsForUserLPr(userId, false);
            }
        }
    }
    @Override
    public boolean shouldShowRequestPermissionRationale(String permissionName,
            String packageName, int userId) {
+16 −0
Original line number Diff line number Diff line
@@ -344,6 +344,22 @@ public final class PermissionsState {
        return permissionData.updateFlags(userId, flagMask, flagValues);
    }

    public boolean updatePermissionFlagsForAllPermissions(
            int userId, int flagMask, int flagValues) {
        enforceValidUserId(userId);

        if (mPermissions == null) {
            return false;
        }
        boolean changed = false;
        final int permissionCount = mPermissions.size();
        for (int i = 0; i < permissionCount; i++) {
            PermissionData permissionData = mPermissions.valueAt(i);
            changed |= permissionData.updateFlags(userId, flagMask, flagValues);
        }
        return changed;
    }

    /**
     * Compute the Linux gids for a given device user from the permissions
     * granted to this user. Note that these are computed to avoid additional
+18 −4
Original line number Diff line number Diff line
@@ -4217,11 +4217,15 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
            long ident = Binder.clearCallingIdentity();
            try {
                clearUserRestrictions(new UserHandle(UserHandle.USER_OWNER));
                AppGlobals.getPackageManager().updatePermissionFlagsForAllApps(
                        PackageManager.FLAG_PERMISSION_POLICY_FIXED,
                        0, UserHandle.USER_OWNER);
                if (mDeviceOwner != null) {
                    mDeviceOwner.clearDeviceOwner();
                    mDeviceOwner.writeOwnerFile();
                    updateDeviceOwnerLocked();
                }
            } catch (RemoteException re) {
            } finally {
                Binder.restoreCallingIdentity(ident);
            }
@@ -4388,10 +4392,14 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
            long ident = Binder.clearCallingIdentity();
            try {
                clearUserRestrictions(callingUser);
                AppGlobals.getPackageManager().updatePermissionFlagsForAllApps(
                        PackageManager.FLAG_PERMISSION_POLICY_FIXED,
                        0, callingUser.getIdentifier());
                if (mDeviceOwner != null) {
                    mDeviceOwner.removeProfileOwner(userId);
                    mDeviceOwner.writeOwnerFile();
                }
            } catch (RemoteException re) {
            } finally {
                Binder.restoreCallingIdentity(ident);
            }
@@ -6390,21 +6398,27 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
            getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
            long ident = Binder.clearCallingIdentity();
            try {
                PackageManager packageManager = mContext.getPackageManager();
                final ApplicationInfo ai = AppGlobals.getPackageManager()
                        .getApplicationInfo(packageName, 0, user.getIdentifier());
                final int targetSdkVersion = ai == null ? 0 : ai.targetSdkVersion;
                if (targetSdkVersion < android.os.Build.VERSION_CODES.MNC) {
                    return false;
                }
                final PackageManager packageManager = mContext.getPackageManager();
                switch (grantState) {
                    case DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED: {
                        packageManager.grantRuntimePermission(packageName, permission, user);
                        packageManager.updatePermissionFlags(permission, packageName,
                                PackageManager.FLAG_PERMISSION_POLICY_FIXED,
                                PackageManager.FLAG_PERMISSION_POLICY_FIXED, user);
                        packageManager.grantRuntimePermission(packageName, permission, user);
                    } break;

                    case DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED: {
                        packageManager.revokeRuntimePermission(packageName,
                                permission, user);
                        packageManager.updatePermissionFlags(permission, packageName,
                                PackageManager.FLAG_PERMISSION_POLICY_FIXED,
                                PackageManager.FLAG_PERMISSION_POLICY_FIXED, user);
                        packageManager.revokeRuntimePermission(packageName,
                                permission, user);
                    } break;

                    case DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT: {