diff options
| author | Philip P. Moltmann <moltmann@google.com> | 2018-12-17 20:45:40 -0800 |
|---|---|---|
| committer | Philip P. Moltmann <moltmann@google.com> | 2019-01-06 17:51:33 -0800 |
| commit | 7868952db36a35b5266bb4da4e983cc47b9c5331 (patch) | |
| tree | 2cd1e09811f9251c8248c1583aa1d46839e40d95 /core/java/android/permission/PermissionControllerService.java | |
| parent | bbb539a172db58089d93332ec28790e3b2af6018 (diff) | |
Allow apps to bulk revoke permissions with the correct semantics
Test: atest --test-mapping frameworks/base/core/java/android/permission/:presubmit
Fixes: 120269238
Change-Id: Ib9eb244f1c89c09eee1f39e3abb65c1189f7a6f4
Diffstat (limited to 'core/java/android/permission/PermissionControllerService.java')
| -rw-r--r-- | core/java/android/permission/PermissionControllerService.java | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/core/java/android/permission/PermissionControllerService.java b/core/java/android/permission/PermissionControllerService.java index 5dad07178e53..f621737e5ed4 100644 --- a/core/java/android/permission/PermissionControllerService.java +++ b/core/java/android/permission/PermissionControllerService.java @@ -16,6 +16,7 @@ package android.permission; +import static com.android.internal.util.Preconditions.checkArgument; import static com.android.internal.util.Preconditions.checkCollectionElementsNotNull; import static com.android.internal.util.Preconditions.checkNotNull; import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage; @@ -26,12 +27,19 @@ import android.annotation.SystemApi; import android.app.Service; import android.content.Context; import android.content.Intent; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.RemoteCallback; +import android.util.ArrayMap; +import com.android.internal.util.Preconditions; + +import java.util.ArrayList; import java.util.List; +import java.util.Map; /** * This service is meant to be implemented by the app controlling permissions. @@ -60,6 +68,20 @@ public abstract class PermissionControllerService extends Service { } /** + * Revoke a set of runtime permissions for various apps. + * + * @param requests The permissions to revoke as {@code Map<packageName, List<permission>>} + * @param doDryRun Compute the permissions that would be revoked, but not actually revoke them + * @param reason Why the permission should be revoked + * @param callerPackageName The package name of the calling app + * + * @return the actually removed permissions as {@code Map<packageName, List<permission>>} + */ + public abstract @NonNull Map<String, List<String>> onRevokeRuntimePermissions( + @NonNull Map<String, List<String>> requests, boolean doDryRun, + @PermissionControllerManager.Reason int reason, @NonNull String callerPackageName); + + /** * Gets the runtime permissions for an app. * * @param packageName The package for which to query. @@ -94,6 +116,41 @@ public abstract class PermissionControllerService extends Service { public final IBinder onBind(Intent intent) { return new IPermissionController.Stub() { @Override + public void revokeRuntimePermissions( + Bundle bundleizedRequest, boolean doDryRun, int reason, + String callerPackageName, RemoteCallback callback) { + checkNotNull(bundleizedRequest, "bundleizedRequest"); + checkNotNull(callerPackageName); + checkNotNull(callback); + + Map<String, List<String>> request = new ArrayMap<>(); + for (String packageName : bundleizedRequest.keySet()) { + Preconditions.checkNotNull(packageName); + + ArrayList<String> permissions = + bundleizedRequest.getStringArrayList(packageName); + Preconditions.checkCollectionElementsNotNull(permissions, "permissions"); + + request.put(packageName, permissions); + } + + enforceCallingPermission(Manifest.permission.REVOKE_RUNTIME_PERMISSIONS, null); + + // Verify callerPackageName + try { + PackageInfo pkgInfo = getPackageManager().getPackageInfo(callerPackageName, 0); + checkArgument(getCallingUid() == pkgInfo.applicationInfo.uid); + } catch (PackageManager.NameNotFoundException e) { + throw new RuntimeException(e); + } + + mHandler.sendMessage(obtainMessage( + PermissionControllerService::revokeRuntimePermissions, + PermissionControllerService.this, request, doDryRun, reason, + callerPackageName, callback)); + } + + @Override public void getAppPermissions(String packageName, RemoteCallback callback) { checkNotNull(packageName, "packageName"); checkNotNull(callback, "callback"); @@ -133,6 +190,27 @@ public abstract class PermissionControllerService extends Service { }; } + private void revokeRuntimePermissions(@NonNull Map<String, List<String>> requests, + boolean doDryRun, @PermissionControllerManager.Reason int reason, + @NonNull String callerPackageName, @NonNull RemoteCallback callback) { + Map<String, List<String>> revoked = onRevokeRuntimePermissions(requests, + doDryRun, reason, callerPackageName); + + checkNotNull(revoked); + Bundle bundledizedRevoked = new Bundle(); + for (Map.Entry<String, List<String>> appRevocation : revoked.entrySet()) { + checkNotNull(appRevocation.getKey()); + checkCollectionElementsNotNull(appRevocation.getValue(), "permissions"); + + bundledizedRevoked.putStringArrayList(appRevocation.getKey(), + new ArrayList<>(appRevocation.getValue())); + } + + Bundle result = new Bundle(); + result.putBundle(PermissionControllerManager.KEY_RESULT, bundledizedRevoked); + callback.sendResult(result); + } + private void getAppPermissions(@NonNull String packageName, @NonNull RemoteCallback callback) { List<RuntimePermissionPresentationInfo> permissions = onGetAppPermissions(packageName); if (permissions != null && !permissions.isEmpty()) { |
