diff --git a/Android.bp b/Android.bp index cd0720dd20651..eb9cbbb136f9c 100644 --- a/Android.bp +++ b/Android.bp @@ -269,7 +269,7 @@ java_defaults { "core/java/android/os/storage/IStorageEventListener.aidl", "core/java/android/os/storage/IStorageShutdownObserver.aidl", "core/java/android/os/storage/IObbActionListener.aidl", - "core/java/android/permission/IRuntimePermissionPresenter.aidl", + "core/java/android/permission/IPermissionController.aidl", "core/java/android/rolecontrollerservice/IRoleControllerService.aidl", ":keystore_aidl", "core/java/android/security/keymaster/IKeyAttestationApplicationIdProvider.aidl", diff --git a/api/system-current.txt b/api/system-current.txt index 01304a6ca79e7..10d483d1bfcec 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -62,6 +62,7 @@ package android { field public static final java.lang.String FORCE_STOP_PACKAGES = "android.permission.FORCE_STOP_PACKAGES"; field public static final java.lang.String GET_APP_OPS_STATS = "android.permission.GET_APP_OPS_STATS"; field public static final java.lang.String GET_PROCESS_STATE_AND_OOM_SCORE = "android.permission.GET_PROCESS_STATE_AND_OOM_SCORE"; + field public static final java.lang.String GET_RUNTIME_PERMISSIONS = "android.permission.GET_RUNTIME_PERMISSIONS"; field public static final java.lang.String GET_TOP_ACTIVITY_INFO = "android.permission.GET_TOP_ACTIVITY_INFO"; field public static final java.lang.String GRANT_PROFILE_OWNER_DEVICE_IDS_ACCESS = "android.permission.GRANT_PROFILE_OWNER_DEVICE_IDS_ACCESS"; field public static final java.lang.String GRANT_RUNTIME_PERMISSIONS = "android.permission.GRANT_RUNTIME_PERMISSIONS"; @@ -4608,6 +4609,16 @@ package android.os.storage { package android.permission { + public abstract class PermissionControllerService extends android.app.Service { + ctor public PermissionControllerService(); + method public final void attachBaseContext(android.content.Context); + method public final android.os.IBinder onBind(android.content.Intent); + method public abstract int onCountPermissionApps(java.util.List, boolean, boolean); + method public abstract java.util.List onGetAppPermissions(java.lang.String); + method public abstract void onRevokeRuntimePermission(java.lang.String, java.lang.String); + field public static final java.lang.String SERVICE_INTERFACE = "android.permission.PermissionControllerService"; + } + public final class PermissionManager { method public java.util.List getSplitPermissions(); } @@ -4628,16 +4639,6 @@ package android.permission { field public static final android.os.Parcelable.Creator CREATOR; } - public abstract class RuntimePermissionPresenterService extends android.app.Service { - ctor public RuntimePermissionPresenterService(); - method public final void attachBaseContext(android.content.Context); - method public final android.os.IBinder onBind(android.content.Intent); - method public abstract int onCountPermissionApps(java.util.List, boolean, boolean); - method public abstract java.util.List onGetAppPermissions(java.lang.String); - method public abstract void onRevokeRuntimePermission(java.lang.String, java.lang.String); - field public static final java.lang.String SERVICE_INTERFACE = "android.permission.RuntimePermissionPresenterService"; - } - } package android.permissionpresenterservice { diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java index 3f6ebc8e63e92..9ddf4bd0870c8 100644 --- a/core/java/android/app/SystemServiceRegistry.java +++ b/core/java/android/app/SystemServiceRegistry.java @@ -144,6 +144,7 @@ import android.os.UserManager; import android.os.Vibrator; import android.os.health.SystemHealthManager; import android.os.storage.StorageManager; +import android.permission.PermissionControllerManager; import android.permission.PermissionManager; import android.print.IPrintManager; import android.print.PrintManager; @@ -1164,6 +1165,13 @@ final class SystemServiceRegistry { return new PermissionManager(ctx.getOuterContext()); }}); + registerService(Context.PERMISSION_CONTROLLER_SERVICE, PermissionControllerManager.class, + new CachedServiceFetcher() { + @Override + public PermissionControllerManager createService(ContextImpl ctx) { + return new PermissionControllerManager(ctx.getOuterContext()); + }}); + registerService(Context.ROLE_SERVICE, RoleManager.class, new CachedServiceFetcher() { @Override diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index 0aa6a8ca461ec..eb7be6f8a6b06 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -3992,6 +3992,14 @@ public abstract class Context { @SystemApi public static final String PERMISSION_SERVICE = "permission"; + /** + * Official published name of the (internal) permission controller service. + * + * @see #getSystemService(String) + * @hide + */ + public static final String PERMISSION_CONTROLLER_SERVICE = "permission_controller"; + /** * Use with {@link #getSystemService(String)} to retrieve an * {@link android.app.backup.IBackupManager IBackupManager} for communicating diff --git a/core/java/android/permission/IRuntimePermissionPresenter.aidl b/core/java/android/permission/IPermissionController.aidl similarity index 89% rename from core/java/android/permission/IRuntimePermissionPresenter.aidl rename to core/java/android/permission/IPermissionController.aidl index e95428ab2b026..38951d5466c76 100644 --- a/core/java/android/permission/IRuntimePermissionPresenter.aidl +++ b/core/java/android/permission/IPermissionController.aidl @@ -19,11 +19,11 @@ package android.permission; import android.os.RemoteCallback; /** - * Interface for communication with the permission presenter service. + * Interface for system apps to communication with the permission controller. * * @hide */ -oneway interface IRuntimePermissionPresenter { +oneway interface IPermissionController { void getAppPermissions(String packageName, in RemoteCallback callback); void revokeRuntimePermission(String packageName, String permissionName); void countPermissionApps(in List permissionNames, boolean countOnlyGranted, diff --git a/core/java/android/permission/RuntimePermissionPresenter.java b/core/java/android/permission/PermissionControllerManager.java similarity index 83% rename from core/java/android/permission/RuntimePermissionPresenter.java rename to core/java/android/permission/PermissionControllerManager.java index c607e3fb309c6..66e8666a8a705 100644 --- a/core/java/android/permission/RuntimePermissionPresenter.java +++ b/core/java/android/permission/PermissionControllerManager.java @@ -16,13 +16,16 @@ package android.permission; -import static android.permission.RuntimePermissionPresenterService.SERVICE_INTERFACE; +import static android.permission.PermissionControllerService.SERVICE_INTERFACE; import static com.android.internal.util.Preconditions.checkCollectionElementsNotNull; import static com.android.internal.util.Preconditions.checkNotNull; +import android.Manifest; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.RequiresPermission; +import android.annotation.SystemService; import android.content.ComponentName; import android.content.Context; import android.content.Intent; @@ -34,7 +37,6 @@ import android.os.RemoteException; import android.os.UserHandle; import android.util.Log; -import com.android.internal.annotations.GuardedBy; import com.android.internal.infra.AbstractMultiplePendingRequestsRemoteService; import com.android.internal.infra.AbstractRemoteService; @@ -42,29 +44,24 @@ import java.util.Collections; import java.util.List; /** - * This class provides information about runtime permissions for a specific - * app or all apps. This information is dedicated for presentation purposes - * and does not necessarily reflect the individual permissions requested/ - * granted to an app as the platform may be grouping permissions to improve - * presentation and help the user make an informed choice. For example, all - * runtime permissions in the same permission group may be presented as a - * single permission in the UI. + * Interface for communicating with the permission controller from system apps. All UI operations + * regarding permissions and any changes to the permission state should flow through this + * interface. * * @hide */ -public final class RuntimePermissionPresenter { - private static final String TAG = "RuntimePermPresenter"; +@SystemService(Context.PERMISSION_CONTROLLER_SERVICE) +public final class PermissionControllerManager { + private static final String TAG = PermissionControllerManager.class.getSimpleName(); /** * The key for retrieving the result from the returned bundle. - * - * @hide */ public static final String KEY_RESULT = - "android.permission.RuntimePermissionPresenter.key.result"; + "android.permission.PermissionControllerManager.key.result"; /** - * Listener for delivering the result of {@link #getAppPermissions}. + * Callback for delivering the result of {@link #getAppPermissions}. */ public interface OnGetAppPermissionResultCallback { /** @@ -77,7 +74,7 @@ public final class RuntimePermissionPresenter { } /** - * Listener for delivering the result of {@link #countPermissionApps}. + * Callback for delivering the result of {@link #countPermissionApps}. */ public interface OnCountPermissionAppsResultCallback { /** @@ -89,29 +86,9 @@ public final class RuntimePermissionPresenter { void onCountPermissionApps(int numApps); } - private static final Object sLock = new Object(); - - @GuardedBy("sLock") - private static RuntimePermissionPresenter sInstance; - private final RemoteService mRemoteService; - /** - * Gets the singleton runtime permission presenter. - * - * @param context Context for accessing resources. - * @return The singleton instance. - */ - public static RuntimePermissionPresenter getInstance(@NonNull Context context) { - synchronized (sLock) { - if (sInstance == null) { - sInstance = new RuntimePermissionPresenter(context.getApplicationContext()); - } - return sInstance; - } - } - - private RuntimePermissionPresenter(@NonNull Context context) { + public PermissionControllerManager(@NonNull Context context) { Intent intent = new Intent(SERVICE_INTERFACE); intent.setPackage(context.getPackageManager().getPermissionControllerPackageName()); ResolveInfo serviceInfo = context.getPackageManager().resolveService(intent, 0); @@ -127,6 +104,7 @@ public final class RuntimePermissionPresenter { * @param callback Callback to receive the result. * @param handler Handler on which to invoke the callback. */ + @RequiresPermission(Manifest.permission.GET_RUNTIME_PERMISSIONS) public void getAppPermissions(@NonNull String packageName, @NonNull OnGetAppPermissionResultCallback callback, @Nullable Handler handler) { checkNotNull(packageName); @@ -142,6 +120,7 @@ public final class RuntimePermissionPresenter { * @param packageName The package for which to revoke * @param permissionName The permission to revoke */ + @RequiresPermission(Manifest.permission.REVOKE_RUNTIME_PERMISSIONS) public void revokeRuntimePermission(@NonNull String packageName, @NonNull String permissionName) { checkNotNull(packageName); @@ -160,6 +139,7 @@ public final class RuntimePermissionPresenter { * @param callback Callback to receive the result * @param handler Handler on which to invoke the callback */ + @RequiresPermission(Manifest.permission.GET_RUNTIME_PERMISSIONS) public void countPermissionApps(@NonNull List permissionNames, boolean countOnlyGranted, boolean countSystem, @NonNull OnCountPermissionAppsResultCallback callback, @Nullable Handler handler) { @@ -175,8 +155,7 @@ public final class RuntimePermissionPresenter { * A connection to the remote service */ static final class RemoteService extends - AbstractMultiplePendingRequestsRemoteService { + AbstractMultiplePendingRequestsRemoteService { private static final long UNBIND_TIMEOUT_MILLIS = 10000; private static final long MESSAGE_TIMEOUT_MILLIS = 30000; @@ -200,9 +179,8 @@ public final class RuntimePermissionPresenter { } @Override - protected @NonNull IRuntimePermissionPresenter getServiceInterface( - @NonNull IBinder binder) { - return IRuntimePermissionPresenter.Stub.asInterface(binder); + protected @NonNull IPermissionController getServiceInterface(@NonNull IBinder binder) { + return IPermissionController.Stub.asInterface(binder); } @Override @@ -217,13 +195,12 @@ public final class RuntimePermissionPresenter { @Override public void scheduleRequest(@NonNull PendingRequest pendingRequest) { + IPermissionController> pendingRequest) { super.scheduleRequest(pendingRequest); } @Override - public void scheduleAsyncRequest( - @NonNull AsyncRequest request) { + public void scheduleAsyncRequest(@NonNull AsyncRequest request) { super.scheduleAsyncRequest(request); } } @@ -232,7 +209,7 @@ public final class RuntimePermissionPresenter { * Request for {@link #getAppPermissions} */ private static final class PendingGetAppPermissionRequest extends - AbstractRemoteService.PendingRequest { + AbstractRemoteService.PendingRequest { private final @NonNull String mPackageName; private final @NonNull OnGetAppPermissionResultCallback mCallback; @@ -282,7 +259,7 @@ public final class RuntimePermissionPresenter { * Request for {@link #revokeRuntimePermission} */ private static final class PendingRevokeAppPermissionRequest - implements AbstractRemoteService.AsyncRequest { + implements AbstractRemoteService.AsyncRequest { private final @NonNull String mPackageName; private final @NonNull String mPermissionName; @@ -293,7 +270,7 @@ public final class RuntimePermissionPresenter { } @Override - public void run(IRuntimePermissionPresenter remoteInterface) { + public void run(IPermissionController remoteInterface) { try { remoteInterface.revokeRuntimePermission(mPackageName, mPermissionName); } catch (RemoteException e) { @@ -306,7 +283,7 @@ public final class RuntimePermissionPresenter { * Request for {@link #countPermissionApps} */ private static final class PendingCountPermissionAppsRequest extends - AbstractRemoteService.PendingRequest { + AbstractRemoteService.PendingRequest { private final @NonNull List mPermissionNames; private final @NonNull OnCountPermissionAppsResultCallback mCallback; private final boolean mCountOnlyGranted; diff --git a/core/java/android/permission/RuntimePermissionPresenterService.java b/core/java/android/permission/PermissionControllerService.java similarity index 76% rename from core/java/android/permission/RuntimePermissionPresenterService.java rename to core/java/android/permission/PermissionControllerService.java index 81ec7bed19afd..5dad07178e53d 100644 --- a/core/java/android/permission/RuntimePermissionPresenterService.java +++ b/core/java/android/permission/PermissionControllerService.java @@ -20,6 +20,7 @@ import static com.android.internal.util.Preconditions.checkCollectionElementsNot import static com.android.internal.util.Preconditions.checkNotNull; import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage; +import android.Manifest; import android.annotation.NonNull; import android.annotation.SystemApi; import android.app.Service; @@ -33,26 +34,21 @@ import android.os.RemoteCallback; import java.util.List; /** - * This service presents information regarding runtime permissions that is - * used for presenting them in the UI. Runtime permissions are presented as - * a single permission in the UI but may be composed of several individual - * permissions. + * This service is meant to be implemented by the app controlling permissions. * - * @see RuntimePermissionPresenter - * @see RuntimePermissionPresentationInfo + * @see PermissionController * * @hide */ @SystemApi -public abstract class RuntimePermissionPresenterService extends Service { +public abstract class PermissionControllerService extends Service { /** * The {@link Intent} action that must be declared as handled by a service * in its manifest for the system to recognize it as a runtime permission * presenter service. */ - public static final String SERVICE_INTERFACE = - "android.permission.RuntimePermissionPresenterService"; + public static final String SERVICE_INTERFACE = "android.permission.PermissionControllerService"; // No need for locking - always set first and never modified private Handler mHandler; @@ -96,16 +92,17 @@ public abstract class RuntimePermissionPresenterService extends Service { @Override public final IBinder onBind(Intent intent) { - return new IRuntimePermissionPresenter.Stub() { + return new IPermissionController.Stub() { @Override public void getAppPermissions(String packageName, RemoteCallback callback) { checkNotNull(packageName, "packageName"); checkNotNull(callback, "callback"); + enforceCallingPermission(Manifest.permission.GET_RUNTIME_PERMISSIONS, null); + mHandler.sendMessage( - obtainMessage( - RuntimePermissionPresenterService::getAppPermissions, - RuntimePermissionPresenterService.this, packageName, callback)); + obtainMessage(PermissionControllerService::getAppPermissions, + PermissionControllerService.this, packageName, callback)); } @Override @@ -113,11 +110,11 @@ public abstract class RuntimePermissionPresenterService extends Service { checkNotNull(packageName, "packageName"); checkNotNull(permissionName, "permissionName"); + enforceCallingPermission(Manifest.permission.REVOKE_RUNTIME_PERMISSIONS, null); + mHandler.sendMessage( - obtainMessage( - RuntimePermissionPresenterService::onRevokeRuntimePermission, - RuntimePermissionPresenterService.this, packageName, - permissionName)); + obtainMessage(PermissionControllerService::onRevokeRuntimePermission, + PermissionControllerService.this, packageName, permissionName)); } @Override @@ -126,11 +123,12 @@ public abstract class RuntimePermissionPresenterService extends Service { checkCollectionElementsNotNull(permissionNames, "permissionNames"); checkNotNull(callback, "callback"); + enforceCallingPermission(Manifest.permission.GET_RUNTIME_PERMISSIONS, null); + mHandler.sendMessage( - obtainMessage( - RuntimePermissionPresenterService::countPermissionApps, - RuntimePermissionPresenterService.this, permissionNames, - countOnlyGranted, countSystem, callback)); + obtainMessage(PermissionControllerService::countPermissionApps, + PermissionControllerService.this, permissionNames, countOnlyGranted, + countSystem, callback)); } }; } @@ -139,7 +137,7 @@ public abstract class RuntimePermissionPresenterService extends Service { List permissions = onGetAppPermissions(packageName); if (permissions != null && !permissions.isEmpty()) { Bundle result = new Bundle(); - result.putParcelableList(RuntimePermissionPresenter.KEY_RESULT, permissions); + result.putParcelableList(PermissionControllerManager.KEY_RESULT, permissions); callback.sendResult(result); } else { callback.sendResult(null); @@ -151,7 +149,7 @@ public abstract class RuntimePermissionPresenterService extends Service { int numApps = onCountPermissionApps(permissionNames, countOnlyGranted, countSystem); Bundle result = new Bundle(); - result.putInt(RuntimePermissionPresenter.KEY_RESULT, numApps); + result.putInt(PermissionControllerManager.KEY_RESULT, numApps); callback.sendResult(result); } } diff --git a/core/java/android/permissionpresenterservice/RuntimePermissionPresenterService.java b/core/java/android/permissionpresenterservice/RuntimePermissionPresenterService.java index 2b3f0f525904f..8d568c84b915d 100644 --- a/core/java/android/permissionpresenterservice/RuntimePermissionPresenterService.java +++ b/core/java/android/permissionpresenterservice/RuntimePermissionPresenterService.java @@ -30,6 +30,7 @@ import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.RemoteCallback; +import android.permission.PermissionControllerService; import java.util.List; @@ -43,7 +44,7 @@ import java.util.List; * * @hide * - * @deprecated use {@link android.permission.RuntimePermissionPresenterService} instead + * @deprecated use {@link PermissionControllerService} instead */ @Deprecated @SystemApi diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index be37ca9771e6e..0778304d26aa4 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -3379,6 +3379,11 @@ + + + diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/PermissionsSummaryHelper.java b/packages/SettingsLib/src/com/android/settingslib/applications/PermissionsSummaryHelper.java index 2387b01d341d0..5e5c22a403d2f 100644 --- a/packages/SettingsLib/src/com/android/settingslib/applications/PermissionsSummaryHelper.java +++ b/packages/SettingsLib/src/com/android/settingslib/applications/PermissionsSummaryHelper.java @@ -16,8 +16,8 @@ package com.android.settingslib.applications; import android.content.Context; +import android.permission.PermissionControllerManager; import android.permission.RuntimePermissionPresentationInfo; -import android.permission.RuntimePermissionPresenter; import java.text.Collator; import java.util.ArrayList; @@ -28,9 +28,9 @@ public class PermissionsSummaryHelper { public static void getPermissionSummary(Context context, String pkg, final PermissionsResultCallback callback) { - final RuntimePermissionPresenter presenter = - RuntimePermissionPresenter.getInstance(context); - presenter.getAppPermissions(pkg, permissions -> { + final PermissionControllerManager permController = + context.getSystemService(PermissionControllerManager.class); + permController.getAppPermissions(pkg, permissions -> { final int permissionCount = permissions.size(); int grantedStandardCount = 0;