diff options
12 files changed, 231 insertions, 4 deletions
diff --git a/core/api/system-current.txt b/core/api/system-current.txt index 4aae6e07e838..c10cc739c171 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -11306,6 +11306,7 @@ package android.permission { method public int checkPermissionForPreflight(@NonNull String, @NonNull android.content.AttributionSource); method @RequiresPermission(value=android.Manifest.permission.UPDATE_APP_OPS_STATS, conditional=true) public int checkPermissionForStartDataDelivery(@NonNull String, @NonNull android.content.AttributionSource, @Nullable String); method public void finishDataDelivery(@NonNull String, @NonNull android.content.AttributionSource); + method @FlaggedApi("android.permission.flags.device_aware_permission_apis_enabled") @NonNull @RequiresPermission(android.Manifest.permission.GET_RUNTIME_PERMISSIONS) public java.util.Map<java.lang.String,android.permission.PermissionManager.PermissionState> getAllPermissionStates(@NonNull String, @NonNull String); method @NonNull @RequiresPermission(android.Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY) public java.util.Set<java.lang.String> getAutoRevokeExemptionGrantedPackages(); method @NonNull @RequiresPermission(android.Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY) public java.util.Set<java.lang.String> getAutoRevokeExemptionRequestedPackages(); method @FlaggedApi("android.permission.flags.device_aware_permission_apis_enabled") @RequiresPermission(anyOf={android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS, android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS, android.Manifest.permission.GET_RUNTIME_PERMISSIONS}) public int getPermissionFlags(@NonNull String, @NonNull String, @NonNull String); @@ -11325,6 +11326,14 @@ package android.permission { field public static final int PERMISSION_SOFT_DENIED = 1; // 0x1 } + @FlaggedApi("android.permission.flags.device_aware_permission_apis_enabled") public static final class PermissionManager.PermissionState implements android.os.Parcelable { + method @FlaggedApi("android.permission.flags.device_aware_permission_apis_enabled") public int describeContents(); + method @FlaggedApi("android.permission.flags.device_aware_permission_apis_enabled") public int getFlags(); + method @FlaggedApi("android.permission.flags.device_aware_permission_apis_enabled") public boolean isGranted(); + method @FlaggedApi("android.permission.flags.device_aware_permission_apis_enabled") public void writeToParcel(@NonNull android.os.Parcel, int); + field @FlaggedApi("android.permission.flags.device_aware_permission_apis_enabled") @NonNull public static final android.os.Parcelable.Creator<android.permission.PermissionManager.PermissionState> CREATOR; + } + public static final class PermissionManager.SplitPermissionInfo { method @NonNull public java.util.List<java.lang.String> getNewPermissions(); method @NonNull public String getSplitPermission(); diff --git a/core/java/android/permission/IPermissionManager.aidl b/core/java/android/permission/IPermissionManager.aidl index 380962cbc766..4ae0a5733f08 100644 --- a/core/java/android/permission/IPermissionManager.aidl +++ b/core/java/android/permission/IPermissionManager.aidl @@ -23,6 +23,7 @@ import android.content.pm.PermissionInfo; import android.content.pm.permission.SplitPermissionInfoParcelable; import android.os.UserHandle; import android.permission.IOnPermissionsChangeListener; +import android.permission.PermissionManager.PermissionState; /** * Interface to communicate directly with the permission manager service. @@ -103,4 +104,12 @@ interface IPermissionManager { int userId); int checkUidPermission(int uid, String permissionName, int deviceId); + + Map<String, PermissionState> getAllPermissionStates(String packageName, String persistentDeviceId, int userId); } + +/** + * Data class for the state of a permission requested by a package + * @hide + */ +parcelable PermissionManager.PermissionState; diff --git a/core/java/android/permission/PermissionManager.java b/core/java/android/permission/PermissionManager.java index d6e8ce701b39..e6b8102764eb 100644 --- a/core/java/android/permission/PermissionManager.java +++ b/core/java/android/permission/PermissionManager.java @@ -66,6 +66,8 @@ import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.Message; +import android.os.Parcel; +import android.os.Parcelable; import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; @@ -89,6 +91,7 @@ import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.Set; @@ -1785,6 +1788,29 @@ public final class PermissionManager { } /** + * Gets the permission states for requested package and persistent device. + * + * @param packageName name of the package you are checking against + * @param persistentDeviceId id of the persistent device you are checking against + * @return mapping of all permission states keyed by their permission names + * + * @hide + */ + @SystemApi + @NonNull + @RequiresPermission(android.Manifest.permission.GET_RUNTIME_PERMISSIONS) + @FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED) + public Map<String, PermissionState> getAllPermissionStates(@NonNull String packageName, + @NonNull String persistentDeviceId) { + try { + return mPermissionManager.getAllPermissionStates(packageName, persistentDeviceId, + mContext.getUserId()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** * Make checkPermission() above bypass the permission cache in this process. * * @hide @@ -1979,4 +2005,68 @@ public final class PermissionManager { } } } + + /** + * Data class for the state of a permission requested by a package + * + * @hide + */ + @SystemApi + @FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED) + public static final class PermissionState implements Parcelable { + private final boolean mGranted; + private final int mFlags; + + /** @hide */ + @FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED) + public PermissionState(boolean granted, int flags) { + mGranted = granted; + mFlags = flags; + } + + /** + * Returns whether this permission is granted + */ + @FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED) + public boolean isGranted() { + return mGranted; + } + + /** + * Returns the flags associated with this permission state + * @see PackageManager#getPermissionFlags + */ + @FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED) + public int getFlags() { + return mFlags; + } + + @FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED) + @Override + public int describeContents() { + return 0; + } + + @FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED) + @Override + public void writeToParcel(@NonNull Parcel parcel, int flags) { + parcel.writeBoolean(mGranted); + parcel.writeInt(mFlags); + } + + private PermissionState(Parcel parcel) { + this(parcel.readBoolean(), parcel.readInt()); + } + + @FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED) + public static final @NonNull Creator<PermissionState> CREATOR = new Creator<>() { + public PermissionState createFromParcel(Parcel source) { + return new PermissionState(source); + } + + public PermissionState[] newArray(int size) { + return new PermissionState[size]; + } + }; + } } diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java index f1dca77fcc7a..f44fcf002a62 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java @@ -65,6 +65,7 @@ import android.permission.IPermissionChecker; import android.permission.IPermissionManager; import android.permission.PermissionCheckerManager; import android.permission.PermissionManager; +import android.permission.PermissionManager.PermissionState; import android.permission.PermissionManagerInternal; import android.service.voice.VoiceInteractionManagerInternal; import android.util.ArrayMap; @@ -258,6 +259,13 @@ public class PermissionManagerService extends IPermissionManager.Stub { } @Override + public Map<String, PermissionState> getAllPermissionStates(@NonNull String packageName, + @NonNull String persistentDeviceId, int userId) { + return mPermissionManagerServiceImpl.getAllPermissionStates(packageName, + persistentDeviceId, userId); + } + + @Override public boolean setAutoRevokeExempted( @NonNull String packageName, boolean exempted, int userId) { Objects.requireNonNull(packageName); diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java index 9afd36f8f0de..c5b637d8b48b 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java @@ -999,6 +999,13 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt return checkUidPermissionInternal(pkg, uid, permName); } + @Override + public Map<String, PermissionManager.PermissionState> getAllPermissionStates( + @NonNull String packageName, @NonNull String persistentDeviceId, int userId) { + throw new UnsupportedOperationException( + "This method is supported in newer implementation only"); + } + /** * Checks whether or not the given package has been granted the specified * permission. If the given package is {@code null}, we instead check the diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInterface.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInterface.java index b12d8acc11b4..7c1042535973 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInterface.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInterface.java @@ -25,6 +25,7 @@ import android.content.pm.PermissionGroupInfo; import android.content.pm.PermissionInfo; import android.content.pm.permission.SplitPermissionInfoParcelable; import android.permission.IOnPermissionsChangeListener; +import android.permission.PermissionManager.PermissionState; import android.permission.PermissionManagerInternal; import com.android.server.pm.pkg.AndroidPackage; @@ -406,6 +407,19 @@ public interface PermissionManagerServiceInterface extends PermissionManagerInte int checkUidPermission(int uid, String permName, int deviceId); /** + * Gets the permission states for requested package, persistent device and user. + * + * @param packageName name of the package you are checking against + * @param persistentDeviceId id of the persistent device you are checking against + * @param userId id of the user for which to get permission flags + * @return mapping of all permission states keyed by their permission names + * + * @hide + */ + Map<String, PermissionState> getAllPermissionStates(@NonNull String packageName, + @NonNull String persistentDeviceId, @UserIdInt int userId); + + /** * Get all the package names requesting app op permissions. * * @return a map of app op permission names to package names requesting them diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceLoggingDecorator.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceLoggingDecorator.java index 835ddcbfc2ba..91a778d49d61 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceLoggingDecorator.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceLoggingDecorator.java @@ -22,6 +22,7 @@ import android.content.pm.PermissionGroupInfo; import android.content.pm.PermissionInfo; import android.content.pm.permission.SplitPermissionInfoParcelable; import android.permission.IOnPermissionsChangeListener; +import android.permission.PermissionManager.PermissionState; import android.util.Log; import com.android.server.pm.pkg.AndroidPackage; @@ -243,12 +244,20 @@ public class PermissionManagerServiceLoggingDecorator implements PermissionManag @Override public int checkUidPermission(int uid, String permName, int deviceId) { - Log.i(LOG_TAG, "checkUidPermission(uid = " + uid + ", permName = " + permName - + ", deviceId = " + deviceId + ")"); + Log.i(LOG_TAG, "checkUidPermission(uid = " + uid + ", permName = " + + permName + ", deviceId = " + deviceId + ")"); return mService.checkUidPermission(uid, permName, deviceId); } @Override + public Map<String, PermissionState> getAllPermissionStates(@NonNull String packageName, + @NonNull String persistentDeviceId, int userId) { + Log.i(LOG_TAG, "getAllPermissionStates(packageName = " + packageName + + ", persistentDeviceId = " + persistentDeviceId + ", userId = " + userId + ")"); + return mService.getAllPermissionStates(packageName, persistentDeviceId, userId); + } + + @Override public Map<String, Set<String>> getAllAppOpPermissionPackages() { Log.i(LOG_TAG, "getAllAppOpPermissionPackages()"); return mService.getAllAppOpPermissionPackages(); diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceTestingShim.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceTestingShim.java index 66a6f3cf39dc..0a4ff0797c97 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceTestingShim.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceTestingShim.java @@ -24,6 +24,7 @@ import android.content.pm.PermissionInfo; import android.content.pm.permission.SplitPermissionInfoParcelable; import android.os.Build; import android.permission.IOnPermissionsChangeListener; +import android.permission.PermissionManager.PermissionState; import com.android.server.pm.pkg.AndroidPackage; import com.android.server.pm.pkg.PackageState; @@ -327,6 +328,12 @@ public class PermissionManagerServiceTestingShim implements PermissionManagerSer } @Override + public Map<String, PermissionState> getAllPermissionStates(@NonNull String packageName, + @NonNull String persistentDeviceId, int userId) { + return mNewImplementation.getAllPermissionStates(packageName, persistentDeviceId, userId); + } + + @Override public Map<String, Set<String>> getAllAppOpPermissionPackages() { Map<String, Set<String>> oldVal = mOldImplementation.getAllAppOpPermissionPackages(); Map<String, Set<String>> newVal = mNewImplementation.getAllAppOpPermissionPackages(); diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceTracingDecorator.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceTracingDecorator.java index f21993ca97cf..bc29e6773bca 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceTracingDecorator.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceTracingDecorator.java @@ -23,6 +23,7 @@ import android.content.pm.PermissionInfo; import android.content.pm.permission.SplitPermissionInfoParcelable; import android.os.Trace; import android.permission.IOnPermissionsChangeListener; +import android.permission.PermissionManager.PermissionState; import com.android.server.pm.pkg.AndroidPackage; import com.android.server.pm.pkg.PackageState; @@ -348,6 +349,18 @@ public class PermissionManagerServiceTracingDecorator implements PermissionManag } @Override + public Map<String, PermissionState> getAllPermissionStates(@NonNull String packageName, + @NonNull String persistentDeviceId, int userId) { + Trace.traceBegin(TRACE_TAG, "TaggedTracingPermissionManagerServiceImpl" + + "#getAllPermissionStates"); + try { + return mService.getAllPermissionStates(packageName, persistentDeviceId, userId); + } finally { + Trace.traceEnd(TRACE_TAG); + } + } + + @Override public Map<String, Set<String>> getAllAppOpPermissionPackages() { Trace.traceBegin(TRACE_TAG, "TaggedTracingPermissionManagerServiceImpl#getAllAppOpPermissionPackages"); diff --git a/services/permission/java/com/android/server/permission/access/permission/AppIdPermissionPolicy.kt b/services/permission/java/com/android/server/permission/access/permission/AppIdPermissionPolicy.kt index 4c74878dab70..558827631dfe 100644 --- a/services/permission/java/com/android/server/permission/access/permission/AppIdPermissionPolicy.kt +++ b/services/permission/java/com/android/server/permission/access/permission/AppIdPermissionPolicy.kt @@ -1662,6 +1662,9 @@ class AppIdPermissionPolicy : SchemePolicy() { ): Int = state.userStates[userId]?.appIdPermissionFlags?.get(appId).getWithDefault(permissionName, 0) + fun GetStateScope.getAllPermissionFlags(appId: Int, userId: Int): IndexedMap<String, Int>? = + state.userStates[userId]?.appIdPermissionFlags?.get(appId) + fun MutateStateScope.setPermissionFlags( appId: Int, userId: Int, diff --git a/services/permission/java/com/android/server/permission/access/permission/DevicePermissionPolicy.kt b/services/permission/java/com/android/server/permission/access/permission/DevicePermissionPolicy.kt index 3284cf19db43..3e3047c97c88 100644 --- a/services/permission/java/com/android/server/permission/access/permission/DevicePermissionPolicy.kt +++ b/services/permission/java/com/android/server/permission/access/permission/DevicePermissionPolicy.kt @@ -95,8 +95,8 @@ class DevicePermissionPolicy : SchemePolicy() { ) { packageNames.forEachIndexed { _, packageName -> // The package may still be removed even if it was once notified as installed. - val packageState = newState.externalState.packageStates[packageName] - ?: return@forEachIndexed + val packageState = + newState.externalState.packageStates[packageName] ?: return@forEachIndexed trimPermissionStates(packageState.appId) } } @@ -226,6 +226,16 @@ class DevicePermissionPolicy : SchemePolicy() { return flags } + fun GetStateScope.getAllPermissionFlags( + appId: Int, + persistentDeviceId: String, + userId: Int + ): IndexedMap<String, Int>? = + state.userStates[userId] + ?.appIdDevicePermissionFlags + ?.get(appId) + ?.get(persistentDeviceId) + fun MutateStateScope.setPermissionFlags( appId: Int, deviceId: String, diff --git a/services/permission/java/com/android/server/permission/access/permission/PermissionService.kt b/services/permission/java/com/android/server/permission/access/permission/PermissionService.kt index 1241ce60af12..2f5c1092e67b 100644 --- a/services/permission/java/com/android/server/permission/access/permission/PermissionService.kt +++ b/services/permission/java/com/android/server/permission/access/permission/PermissionService.kt @@ -45,6 +45,7 @@ import android.os.UserManager import android.permission.IOnPermissionsChangeListener import android.permission.PermissionControllerManager import android.permission.PermissionManager +import android.permission.PermissionManager.PermissionState import android.permission.flags.Flags import android.provider.Settings import android.util.ArrayMap @@ -1135,6 +1136,53 @@ class PermissionService(private val service: AccessCheckingService) : } } + override fun getAllPermissionStates( + packageName: String, + persistentDeviceId: String, + userId: Int + ): Map<String, PermissionState> { + if (!userManagerInternal.exists(userId)) { + Slog.w(LOG_TAG, "getAllPermissionStates: Unknown user $userId") + return emptyMap() + } + enforceCallingOrSelfCrossUserPermission( + userId, + enforceFullPermission = true, + enforceShellRestriction = false, + "getAllPermissionStates" + ) + enforceCallingOrSelfAnyPermission( + "getAllPermissionStates", + Manifest.permission.GET_RUNTIME_PERMISSIONS + ) + + val packageState = + packageManagerLocal.withFilteredSnapshot().use { it.getPackageState(packageName) } + if (packageState == null) { + Slog.w(LOG_TAG, "getAllPermissionStates: Unknown package $packageName") + return emptyMap() + } + + val permissionFlagsMap = + service.getState { + if (persistentDeviceId == VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT) { + with(policy) { getAllPermissionFlags(packageState.appId, userId) } + } else { + with(devicePolicy) { + getAllPermissionFlags(packageState.appId, persistentDeviceId, userId) + } + } + } ?: return emptyMap() + + val permissionStates = ArrayMap<String, PermissionState>() + permissionFlagsMap.forEachIndexed { _, permissionName, flags -> + val granted = PermissionFlags.isPermissionGranted(flags) + val apiFlags = PermissionFlags.toApiFlags(flags) + permissionStates[permissionName] = PermissionState(granted, apiFlags) + } + return permissionStates + } + override fun isPermissionRevokedByPolicy( packageName: String, permissionName: String, |