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

Commit 097e1859 authored by Philip P. Moltmann's avatar Philip P. Moltmann Committed by Android (Google) Code Review
Browse files

Merge "Allow an app to drive permission backup+restore"

parents 31d98634 4a6c5de6
Loading
Loading
Loading
Loading
+8 −2
Original line number Original line Diff line number Diff line
@@ -172,6 +172,7 @@ package android {
    field public static final String REMOVE_TASKS = "android.permission.REMOVE_TASKS";
    field public static final String REMOVE_TASKS = "android.permission.REMOVE_TASKS";
    field public static final String REQUEST_NOTIFICATION_ASSISTANT_SERVICE = "android.permission.REQUEST_NOTIFICATION_ASSISTANT_SERVICE";
    field public static final String REQUEST_NOTIFICATION_ASSISTANT_SERVICE = "android.permission.REQUEST_NOTIFICATION_ASSISTANT_SERVICE";
    field public static final String RESET_PASSWORD = "android.permission.RESET_PASSWORD";
    field public static final String RESET_PASSWORD = "android.permission.RESET_PASSWORD";
    field public static final String RESTORE_RUNTIME_PERMISSIONS = "android.permission.RESTORE_RUNTIME_PERMISSIONS";
    field public static final String RESTRICTED_VR_ACCESS = "android.permission.RESTRICTED_VR_ACCESS";
    field public static final String RESTRICTED_VR_ACCESS = "android.permission.RESTRICTED_VR_ACCESS";
    field public static final String RETRIEVE_WINDOW_CONTENT = "android.permission.RETRIEVE_WINDOW_CONTENT";
    field public static final String RETRIEVE_WINDOW_CONTENT = "android.permission.RETRIEVE_WINDOW_CONTENT";
    field public static final String REVIEW_ACCESSIBILITY_SERVICES = "android.permission.REVIEW_ACCESSIBILITY_SERVICES";
    field public static final String REVIEW_ACCESSIBILITY_SERVICES = "android.permission.REVIEW_ACCESSIBILITY_SERVICES";
@@ -5701,7 +5702,10 @@ package android.os.telephony {
package android.permission {
package android.permission {
  public final class PermissionControllerManager {
  public final class PermissionControllerManager {
    method @RequiresPermission(anyOf={android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS, android.Manifest.permission.RESTORE_RUNTIME_PERMISSIONS}) public void applyStagedRuntimePermissionBackup(@NonNull String, @NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
    method @RequiresPermission(android.Manifest.permission.GET_RUNTIME_PERMISSIONS) public void getRuntimePermissionBackup(@NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<byte[]>);
    method @RequiresPermission(android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS) public void revokeRuntimePermissions(@NonNull java.util.Map<java.lang.String,java.util.List<java.lang.String>>, boolean, int, @NonNull java.util.concurrent.Executor, @NonNull android.permission.PermissionControllerManager.OnRevokeRuntimePermissionsCallback);
    method @RequiresPermission(android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS) public void revokeRuntimePermissions(@NonNull java.util.Map<java.lang.String,java.util.List<java.lang.String>>, boolean, int, @NonNull java.util.concurrent.Executor, @NonNull android.permission.PermissionControllerManager.OnRevokeRuntimePermissionsCallback);
    method @RequiresPermission(anyOf={android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS, android.Manifest.permission.RESTORE_RUNTIME_PERMISSIONS}) public void stageAndApplyRuntimePermissionsBackup(@NonNull byte[], @NonNull android.os.UserHandle);
    field public static final int COUNT_ONLY_WHEN_GRANTED = 1; // 0x1
    field public static final int COUNT_ONLY_WHEN_GRANTED = 1; // 0x1
    field public static final int COUNT_WHEN_SYSTEM = 2; // 0x2
    field public static final int COUNT_WHEN_SYSTEM = 2; // 0x2
    field public static final int REASON_INSTALLER_POLICY_VIOLATION = 2; // 0x2
    field public static final int REASON_INSTALLER_POLICY_VIOLATION = 2; // 0x2
@@ -5715,17 +5719,19 @@ package android.permission {
  public abstract class PermissionControllerService extends android.app.Service {
  public abstract class PermissionControllerService extends android.app.Service {
    ctor public PermissionControllerService();
    ctor public PermissionControllerService();
    method @BinderThread public void onApplyStagedRuntimePermissionBackup(@NonNull String, @NonNull android.os.UserHandle, @NonNull java.util.function.Consumer<java.lang.Boolean>);
    method @NonNull public final android.os.IBinder onBind(android.content.Intent);
    method @NonNull public final android.os.IBinder onBind(android.content.Intent);
    method @BinderThread public abstract void onCountPermissionApps(@NonNull java.util.List<java.lang.String>, int, @NonNull java.util.function.IntConsumer);
    method @BinderThread public abstract void onCountPermissionApps(@NonNull java.util.List<java.lang.String>, int, @NonNull java.util.function.IntConsumer);
    method @BinderThread public abstract void onGetAppPermissions(@NonNull String, @NonNull java.util.function.Consumer<java.util.List<android.permission.RuntimePermissionPresentationInfo>>);
    method @BinderThread public abstract void onGetAppPermissions(@NonNull String, @NonNull java.util.function.Consumer<java.util.List<android.permission.RuntimePermissionPresentationInfo>>);
    method @BinderThread public abstract void onGetPermissionUsages(boolean, long, @NonNull java.util.function.Consumer<java.util.List<android.permission.RuntimePermissionUsageInfo>>);
    method @BinderThread public abstract void onGetPermissionUsages(boolean, long, @NonNull java.util.function.Consumer<java.util.List<android.permission.RuntimePermissionUsageInfo>>);
    method @BinderThread public abstract void onGetRuntimePermissionsBackup(@NonNull android.os.UserHandle, @NonNull java.io.OutputStream, @NonNull Runnable);
    method @BinderThread public abstract void onGetRuntimePermissionsBackup(@NonNull android.os.UserHandle, @NonNull java.io.OutputStream, @NonNull Runnable);
    method @BinderThread public abstract void onGrantOrUpgradeDefaultRuntimePermissions(@NonNull Runnable);
    method @BinderThread public abstract void onGrantOrUpgradeDefaultRuntimePermissions(@NonNull Runnable);
    method @BinderThread public abstract void onRestoreDelayedRuntimePermissionsBackup(@NonNull String, @NonNull android.os.UserHandle, @NonNull java.util.function.Consumer<java.lang.Boolean>);
    method @Deprecated @BinderThread public void onRestoreDelayedRuntimePermissionsBackup(@NonNull String, @NonNull android.os.UserHandle, @NonNull java.util.function.Consumer<java.lang.Boolean>);
    method @BinderThread public abstract void onRestoreRuntimePermissionsBackup(@NonNull android.os.UserHandle, @NonNull java.io.InputStream, @NonNull Runnable);
    method @Deprecated @BinderThread public void onRestoreRuntimePermissionsBackup(@NonNull android.os.UserHandle, @NonNull java.io.InputStream, @NonNull Runnable);
    method @BinderThread public abstract void onRevokeRuntimePermission(@NonNull String, @NonNull String, @NonNull Runnable);
    method @BinderThread public abstract void onRevokeRuntimePermission(@NonNull String, @NonNull String, @NonNull Runnable);
    method @BinderThread public abstract void onRevokeRuntimePermissions(@NonNull java.util.Map<java.lang.String,java.util.List<java.lang.String>>, boolean, int, @NonNull String, @NonNull java.util.function.Consumer<java.util.Map<java.lang.String,java.util.List<java.lang.String>>>);
    method @BinderThread public abstract void onRevokeRuntimePermissions(@NonNull java.util.Map<java.lang.String,java.util.List<java.lang.String>>, boolean, int, @NonNull String, @NonNull java.util.function.Consumer<java.util.Map<java.lang.String,java.util.List<java.lang.String>>>);
    method @BinderThread public abstract void onSetRuntimePermissionGrantStateByDeviceAdmin(@NonNull String, @NonNull String, @NonNull String, int, @NonNull java.util.function.Consumer<java.lang.Boolean>);
    method @BinderThread public abstract void onSetRuntimePermissionGrantStateByDeviceAdmin(@NonNull String, @NonNull String, @NonNull String, int, @NonNull java.util.function.Consumer<java.lang.Boolean>);
    method @BinderThread public void onStageAndApplyRuntimePermissionsBackup(@NonNull android.os.UserHandle, @NonNull java.io.InputStream, @NonNull Runnable);
    method @BinderThread public void onUpdateUserSensitive();
    method @BinderThread public void onUpdateUserSensitive();
    field public static final String SERVICE_INTERFACE = "android.permission.PermissionControllerService";
    field public static final String SERVICE_INTERFACE = "android.permission.PermissionControllerService";
  }
  }
+3 −0
Original line number Original line Diff line number Diff line
@@ -2253,8 +2253,11 @@ package android.os.strictmode {
package android.permission {
package android.permission {


  public final class PermissionControllerManager {
  public final class PermissionControllerManager {
    method @RequiresPermission(anyOf={"android.permission.GRANT_RUNTIME_PERMISSIONS", "android.permission.RESTORE_RUNTIME_PERMISSIONS"}) public void applyStagedRuntimePermissionBackup(@NonNull String, @NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
    method @RequiresPermission("android.permission.GET_RUNTIME_PERMISSIONS") public void getAppPermissions(@NonNull String, @NonNull android.permission.PermissionControllerManager.OnGetAppPermissionResultCallback, @Nullable android.os.Handler);
    method @RequiresPermission("android.permission.GET_RUNTIME_PERMISSIONS") public void getAppPermissions(@NonNull String, @NonNull android.permission.PermissionControllerManager.OnGetAppPermissionResultCallback, @Nullable android.os.Handler);
    method @RequiresPermission("android.permission.GET_RUNTIME_PERMISSIONS") public void getRuntimePermissionBackup(@NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<byte[]>);
    method @RequiresPermission("android.permission.REVOKE_RUNTIME_PERMISSIONS") public void revokeRuntimePermissions(@NonNull java.util.Map<java.lang.String,java.util.List<java.lang.String>>, boolean, int, @NonNull java.util.concurrent.Executor, @NonNull android.permission.PermissionControllerManager.OnRevokeRuntimePermissionsCallback);
    method @RequiresPermission("android.permission.REVOKE_RUNTIME_PERMISSIONS") public void revokeRuntimePermissions(@NonNull java.util.Map<java.lang.String,java.util.List<java.lang.String>>, boolean, int, @NonNull java.util.concurrent.Executor, @NonNull android.permission.PermissionControllerManager.OnRevokeRuntimePermissionsCallback);
    method @RequiresPermission(anyOf={"android.permission.GRANT_RUNTIME_PERMISSIONS", "android.permission.RESTORE_RUNTIME_PERMISSIONS"}) public void stageAndApplyRuntimePermissionsBackup(@NonNull byte[], @NonNull android.os.UserHandle);
    field public static final int COUNT_ONLY_WHEN_GRANTED = 1; // 0x1
    field public static final int COUNT_ONLY_WHEN_GRANTED = 1; // 0x1
    field public static final int COUNT_WHEN_SYSTEM = 2; // 0x2
    field public static final int COUNT_WHEN_SYSTEM = 2; // 0x2
    field public static final int REASON_INSTALLER_POLICY_VIOLATION = 2; // 0x2
    field public static final int REASON_INSTALLER_POLICY_VIOLATION = 2; // 0x2
+2 −2
Original line number Original line Diff line number Diff line
@@ -31,8 +31,8 @@ oneway interface IPermissionController {
    void revokeRuntimePermissions(in Bundle request, boolean doDryRun, int reason,
    void revokeRuntimePermissions(in Bundle request, boolean doDryRun, int reason,
            String callerPackageName, in AndroidFuture callback);
            String callerPackageName, in AndroidFuture callback);
    void getRuntimePermissionBackup(in UserHandle user, in ParcelFileDescriptor pipe);
    void getRuntimePermissionBackup(in UserHandle user, in ParcelFileDescriptor pipe);
    void restoreRuntimePermissionBackup(in UserHandle user, in ParcelFileDescriptor pipe);
    void stageAndApplyRuntimePermissionsBackup(in UserHandle user, in ParcelFileDescriptor pipe);
    void restoreDelayedRuntimePermissionBackup(String packageName, in UserHandle user,
    void applyStagedRuntimePermissionBackup(String packageName, in UserHandle user,
            in AndroidFuture callback);
            in AndroidFuture callback);
    void getAppPermissions(String packageName, in AndroidFuture callback);
    void getAppPermissions(String packageName, in AndroidFuture callback);
    void revokeRuntimePermission(String packageName, String permissionName);
    void revokeRuntimePermission(String packageName, String permissionName);
+71 −46
Original line number Original line Diff line number Diff line
@@ -62,6 +62,7 @@ import libcore.util.EmptyArray;
import java.lang.annotation.Retention;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Collections;
import java.util.List;
import java.util.List;
import java.util.Map;
import java.util.Map;
@@ -138,20 +139,6 @@ public final class PermissionControllerManager {
        public abstract void onRevokeRuntimePermissions(@NonNull Map<String, List<String>> revoked);
        public abstract void onRevokeRuntimePermissions(@NonNull Map<String, List<String>> revoked);
    }
    }


    /**
     * Callback for delivering the result of {@link #getRuntimePermissionBackup}.
     *
     * @hide
     */
    public interface OnGetRuntimePermissionBackupCallback {
        /**
         * The result for {@link #getRuntimePermissionBackup}.
         *
         * @param backup The backup file
         */
        void onGetRuntimePermissionsBackup(@NonNull byte[] backup);
    }

    /**
    /**
     * Callback for delivering the result of {@link #getAppPermissions}.
     * Callback for delivering the result of {@link #getAppPermissions}.
     *
     *
@@ -245,6 +232,24 @@ public final class PermissionControllerManager {
        mHandler = handler;
        mHandler = handler;
    }
    }


    /**
     * Throw a {@link SecurityException} if not at least one of the permissions is granted.
     *
     * @param requiredPermissions A list of permissions. Any of of them if sufficient to pass the
     *                            check
     */
    private void enforceSomePermissionsGrantedToSelf(@NonNull String... requiredPermissions) {
        for (String requiredPermission : requiredPermissions) {
            if (mContext.checkSelfPermission(requiredPermission)
                    == PackageManager.PERMISSION_GRANTED) {
                return;
            }
        }

        throw new SecurityException("At lest one of the following permissions is required: "
                + Arrays.toString(requiredPermissions));
    }

    /**
    /**
     * Revoke a set of runtime permissions for various apps.
     * Revoke a set of runtime permissions for various apps.
     *
     *
@@ -268,11 +273,7 @@ public final class PermissionControllerManager {
        }
        }


        // Check required permission to fail immediately instead of inside the oneway binder call
        // Check required permission to fail immediately instead of inside the oneway binder call
        if (mContext.checkSelfPermission(Manifest.permission.REVOKE_RUNTIME_PERMISSIONS)
        enforceSomePermissionsGrantedToSelf(Manifest.permission.REVOKE_RUNTIME_PERMISSIONS);
                != PackageManager.PERMISSION_GRANTED) {
            throw new SecurityException(Manifest.permission.REVOKE_RUNTIME_PERMISSIONS
                    + " required");
        }


        mRemoteService.postAsync(service -> {
        mRemoteService.postAsync(service -> {
            Bundle bundledizedRequest = new Bundle();
            Bundle bundledizedRequest = new Bundle();
@@ -358,46 +359,61 @@ public final class PermissionControllerManager {
     *
     *
     * @param user The user to be backed up
     * @param user The user to be backed up
     * @param executor Executor on which to invoke the callback
     * @param executor Executor on which to invoke the callback
     * @param callback Callback to receive the result
     * @param callback Callback to receive the result. The resulting backup-file is opaque and no
     *
     *                 guarantees are made other than that the file can be send to
     * @hide
     *                 {@link #restoreRuntimePermissionBackup} in this and future versions of
     *                 Android.
     */
     */
    @RequiresPermission(Manifest.permission.GET_RUNTIME_PERMISSIONS)
    @RequiresPermission(Manifest.permission.GET_RUNTIME_PERMISSIONS)
    public void getRuntimePermissionBackup(@NonNull UserHandle user,
    public void getRuntimePermissionBackup(@NonNull UserHandle user,
            @NonNull @CallbackExecutor Executor executor,
            @NonNull @CallbackExecutor Executor executor,
            @NonNull OnGetRuntimePermissionBackupCallback callback) {
            @NonNull Consumer<byte[]> callback) {
        checkNotNull(user);
        checkNotNull(user);
        checkNotNull(executor);
        checkNotNull(executor);
        checkNotNull(callback);
        checkNotNull(callback);


        // Check required permission to fail immediately instead of inside the oneway binder call
        enforceSomePermissionsGrantedToSelf(Manifest.permission.GET_RUNTIME_PERMISSIONS);

        mRemoteService.postAsync(service -> RemoteStream.receiveBytes(remotePipe -> {
        mRemoteService.postAsync(service -> RemoteStream.receiveBytes(remotePipe -> {
            service.getRuntimePermissionBackup(user, remotePipe);
            service.getRuntimePermissionBackup(user, remotePipe);
        })).whenCompleteAsync((bytes, err) -> {
        })).whenCompleteAsync((bytes, err) -> {
            if (err != null) {
            if (err != null) {
                Log.e(TAG, "Error getting permission backup", err);
                Log.e(TAG, "Error getting permission backup", err);
                callback.onGetRuntimePermissionsBackup(EmptyArray.BYTE);
                callback.accept(EmptyArray.BYTE);
            } else {
            } else {
                callback.onGetRuntimePermissionsBackup(bytes);
                callback.accept(bytes);
            }
            }
        }, executor);
        }, executor);
    }
    }


    /**
    /**
     * Restore a backup of the runtime permissions.
     * Restore a {@link #getRuntimePermissionBackup backup-file} of the runtime permissions.
     *
     *
     * @param backup the backup to restore. The backup is sent asynchronously, hence it should not
     * <p>This might leave some part of the backup-file unapplied if an package mentioned in the
     *               be modified after calling this method.
     * backup-file is not yet installed. It is required that
     * @param user The user to be restore
     * {@link #applyStagedRuntimePermissionBackup} is called after any package is installed to
     * apply the rest of the backup-file.
     *
     *
     * @hide
     * @param backup the backup-file to restore. The backup is sent asynchronously, hence it should
     *               not be modified after calling this method.
     * @param user The user to be restore
     */
     */
    @RequiresPermission(Manifest.permission.GRANT_RUNTIME_PERMISSIONS)
    @RequiresPermission(anyOf = {
    public void restoreRuntimePermissionBackup(@NonNull byte[] backup, @NonNull UserHandle user) {
            Manifest.permission.GRANT_RUNTIME_PERMISSIONS,
            Manifest.permission.RESTORE_RUNTIME_PERMISSIONS
    })
    public void stageAndApplyRuntimePermissionsBackup(@NonNull byte[] backup,
            @NonNull UserHandle user) {
        checkNotNull(backup);
        checkNotNull(backup);
        checkNotNull(user);
        checkNotNull(user);


        // Check required permission to fail immediately instead of inside the oneway binder call
        enforceSomePermissionsGrantedToSelf(Manifest.permission.GRANT_RUNTIME_PERMISSIONS,
                Manifest.permission.RESTORE_RUNTIME_PERMISSIONS);

        mRemoteService.postAsync(service -> RemoteStream.sendBytes(remotePipe -> {
        mRemoteService.postAsync(service -> RemoteStream.sendBytes(remotePipe -> {
            service.restoreRuntimePermissionBackup(user, remotePipe);
            service.stageAndApplyRuntimePermissionsBackup(user, remotePipe);
        }, backup))
        }, backup))
                .whenComplete((nullResult, err) -> {
                .whenComplete((nullResult, err) -> {
                    if (err != null) {
                    if (err != null) {
@@ -407,17 +423,22 @@ public final class PermissionControllerManager {
    }
    }


    /**
    /**
     * Restore a backup of the runtime permissions that has been delayed.
     * Restore unapplied parts of a {@link #stageAndApplyRuntimePermissionsBackup previously staged}
     * backup-file of the runtime permissions.
     *
     * <p>This should be called every time after a package is installed until the callback
     * reports that there is no more unapplied backup left.
     *
     *
     * @param packageName The package that is ready to have it's permissions restored.
     * @param packageName The package that is ready to have it's permissions restored.
     * @param user The user to restore
     * @param user The user the package belongs to
     * @param executor Executor to execute the callback on
     * @param executor Executor to execute the callback on
     * @param callback Is called with {@code true} iff there is still more delayed backup left
     * @param callback Is called with {@code true} iff there is still more unapplied backup left
     *
     * @hide
     */
     */
    @RequiresPermission(Manifest.permission.GRANT_RUNTIME_PERMISSIONS)
    @RequiresPermission(anyOf = {
    public void restoreDelayedRuntimePermissionBackup(@NonNull String packageName,
            Manifest.permission.GRANT_RUNTIME_PERMISSIONS,
            Manifest.permission.RESTORE_RUNTIME_PERMISSIONS
    })
    public void applyStagedRuntimePermissionBackup(@NonNull String packageName,
            @NonNull UserHandle user,
            @NonNull UserHandle user,
            @NonNull @CallbackExecutor Executor executor,
            @NonNull @CallbackExecutor Executor executor,
            @NonNull Consumer<Boolean> callback) {
            @NonNull Consumer<Boolean> callback) {
@@ -426,13 +447,17 @@ public final class PermissionControllerManager {
        checkNotNull(executor);
        checkNotNull(executor);
        checkNotNull(callback);
        checkNotNull(callback);


        // Check required permission to fail immediately instead of inside the oneway binder call
        enforceSomePermissionsGrantedToSelf(Manifest.permission.GRANT_RUNTIME_PERMISSIONS,
                Manifest.permission.RESTORE_RUNTIME_PERMISSIONS);

        mRemoteService.postAsync(service -> {
        mRemoteService.postAsync(service -> {
            AndroidFuture<Boolean> restoreDelayedRuntimePermissionBackupResult =
            AndroidFuture<Boolean> applyStagedRuntimePermissionBackupResult =
                    new AndroidFuture<>();
                    new AndroidFuture<>();
            service.restoreDelayedRuntimePermissionBackup(packageName, user,
            service.applyStagedRuntimePermissionBackup(packageName, user,
                    restoreDelayedRuntimePermissionBackupResult);
                    applyStagedRuntimePermissionBackupResult);
            return restoreDelayedRuntimePermissionBackupResult;
            return applyStagedRuntimePermissionBackupResult;
        }).whenCompleteAsync((restoreDelayedRuntimePermissionBackupResult, err) -> {
        }).whenCompleteAsync((applyStagedRuntimePermissionBackupResult, err) -> {
            long token = Binder.clearCallingIdentity();
            long token = Binder.clearCallingIdentity();
            try {
            try {
                if (err != null) {
                if (err != null) {
@@ -440,7 +465,7 @@ public final class PermissionControllerManager {
                    callback.accept(true);
                    callback.accept(true);
                } else {
                } else {
                    callback.accept(
                    callback.accept(
                            Boolean.TRUE.equals(restoreDelayedRuntimePermissionBackupResult));
                            Boolean.TRUE.equals(applyStagedRuntimePermissionBackupResult));
                }
                }
            } finally {
            } finally {
                Binder.restoreCallingIdentity(token);
                Binder.restoreCallingIdentity(token);
+76 −24

File changed.

Preview size limit exceeded, changes collapsed.

Loading