diff options
8 files changed, 75 insertions, 34 deletions
diff --git a/core/api/system-current.txt b/core/api/system-current.txt index f3d10614123c..6ac8450d607b 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -4116,6 +4116,7 @@ package android.content.pm { public static interface PackageManager.OnPermissionsChangedListener { method public void onPermissionsChanged(int); + method @FlaggedApi("android.permission.flags.device_aware_permission_apis") public default void onPermissionsChanged(int, @NonNull String); } @IntDef(prefix={"FLAG_PERMISSION_"}, value={android.content.pm.PackageManager.FLAG_PERMISSION_USER_SET, android.content.pm.PackageManager.FLAG_PERMISSION_USER_FIXED, android.content.pm.PackageManager.FLAG_PERMISSION_POLICY_FIXED, android.content.pm.PackageManager.FLAG_PERMISSION_REVOKE_ON_UPGRADE, android.content.pm.PackageManager.FLAG_PERMISSION_SYSTEM_FIXED, android.content.pm.PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT, android.content.pm.PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED, android.content.pm.PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_DENIED, android.content.pm.PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT, android.content.pm.PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT, android.content.pm.PackageManager.FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT, android.content.pm.PackageManager.FLAG_PERMISSION_APPLY_RESTRICTION, android.content.pm.PackageManager.FLAG_PERMISSION_GRANTED_BY_ROLE, android.content.pm.PackageManager.FLAG_PERMISSION_REVOKED_COMPAT, android.content.pm.PackageManager.FLAG_PERMISSION_ONE_TIME, android.content.pm.PackageManager.FLAG_PERMISSION_AUTO_REVOKED}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface PackageManager.PermissionFlags { diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index f87c8d045d05..b5d239beaba9 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -43,6 +43,7 @@ import android.app.PackageInstallObserver; import android.app.PropertyInvalidatedCache; import android.app.admin.DevicePolicyManager; import android.app.usage.StorageStatsManager; +import android.companion.virtual.VirtualDeviceManager; import android.compat.annotation.ChangeId; import android.compat.annotation.EnabledSince; import android.compat.annotation.UnsupportedAppUsage; @@ -710,12 +711,31 @@ public abstract class PackageManager { */ @SystemApi public interface OnPermissionsChangedListener { - /** - * Called when the permissions for a UID change. + * Called when the permissions for a UID change for the default device. + * * @param uid The UID with a change. + * @see Context#DEVICE_ID_DEFAULT */ - public void onPermissionsChanged(int uid); + void onPermissionsChanged(int uid); + + /** + * Called when the permissions for a UID change for a device, including virtual devices. + * + * @param uid The UID of permission change event. + * @param persistentDeviceId The persistent device ID of permission change event. + * + * @see VirtualDeviceManager.VirtualDevice#getPersistentDeviceId() + * @see VirtualDeviceManager#PERSISTENT_DEVICE_ID_DEFAULT + */ + @FlaggedApi(android.permission.flags.Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS) + default void onPermissionsChanged(int uid, @NonNull String persistentDeviceId) { + Objects.requireNonNull(persistentDeviceId); + if (Objects.equals(persistentDeviceId, + VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT)) { + onPermissionsChanged(uid); + } + } } /** @hide */ diff --git a/core/java/android/permission/IOnPermissionsChangeListener.aidl b/core/java/android/permission/IOnPermissionsChangeListener.aidl index cc52a7210737..afacf1a74ca6 100644 --- a/core/java/android/permission/IOnPermissionsChangeListener.aidl +++ b/core/java/android/permission/IOnPermissionsChangeListener.aidl @@ -21,5 +21,5 @@ package android.permission; * {@hide} */ oneway interface IOnPermissionsChangeListener { - void onPermissionsChanged(int uid); + void onPermissionsChanged(int uid, String deviceId); } diff --git a/core/java/android/permission/PermissionManager.java b/core/java/android/permission/PermissionManager.java index e10ea10e2a29..7a158c548a38 100644 --- a/core/java/android/permission/PermissionManager.java +++ b/core/java/android/permission/PermissionManager.java @@ -1725,7 +1725,7 @@ public final class PermissionManager { } private final class OnPermissionsChangeListenerDelegate - extends IOnPermissionsChangeListener.Stub implements Handler.Callback{ + extends IOnPermissionsChangeListener.Stub implements Handler.Callback { private static final int MSG_PERMISSIONS_CHANGED = 1; private final PackageManager.OnPermissionsChangedListener mListener; @@ -1738,8 +1738,8 @@ public final class PermissionManager { } @Override - public void onPermissionsChanged(int uid) { - mHandler.obtainMessage(MSG_PERMISSIONS_CHANGED, uid, 0).sendToTarget(); + public void onPermissionsChanged(int uid, String deviceId) { + mHandler.obtainMessage(MSG_PERMISSIONS_CHANGED, uid, 0, deviceId).sendToTarget(); } @Override @@ -1747,7 +1747,8 @@ public final class PermissionManager { switch (msg.what) { case MSG_PERMISSIONS_CHANGED: { final int uid = msg.arg1; - mListener.onPermissionsChanged(uid); + final String deviceId = msg.obj.toString(); + mListener.onPermissionsChanged(uid, deviceId); return true; } default: 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 883b0666f979..8bd2d94667f9 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java @@ -70,6 +70,7 @@ import android.app.ActivityManager; import android.app.AppOpsManager; import android.app.IActivityManager; import android.app.admin.DevicePolicyManagerInternal; +import android.companion.virtual.VirtualDeviceManager; import android.compat.annotation.ChangeId; import android.compat.annotation.EnabledAfter; import android.content.Context; @@ -5327,7 +5328,8 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt IOnPermissionsChangeListener callback = mPermissionListeners .getBroadcastItem(i); try { - callback.onPermissionsChanged(uid); + callback.onPermissionsChanged(uid, + VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT); } catch (RemoteException e) { Log.e(TAG, "Permission listener is dead", e); } 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 010604f9aaaa..02032c786563 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 @@ -1706,7 +1706,7 @@ class AppIdPermissionPolicy : SchemePolicy() { } /** Listener for permission flags changes. */ - abstract class OnPermissionFlagsChangedListener { + interface OnPermissionFlagsChangedListener { /** * Called when a permission flags change has been made to the upcoming new state. * @@ -1714,7 +1714,7 @@ class AppIdPermissionPolicy : SchemePolicy() { * and only call external code after [onStateMutated] when the new state has actually become * the current state visible to external code. */ - abstract fun onPermissionFlagsChanged( + fun onPermissionFlagsChanged( appId: Int, userId: Int, permissionName: String, @@ -1727,6 +1727,6 @@ class AppIdPermissionPolicy : SchemePolicy() { * * Implementations should keep this method fast to avoid stalling the locked state mutation. */ - abstract fun onStateMutated() + fun onStateMutated() } } 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 7db09f9125de..bb68bc5c791d 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 @@ -263,10 +263,6 @@ class DevicePermissionPolicy : SchemePolicy() { synchronized(listenersLock) { listeners = listeners + listener } } - fun removeOnPermissionFlagsChangedListener(listener: OnDevicePermissionFlagsChangedListener) { - synchronized(listenersLock) { listeners = listeners - listener } - } - private fun isDeviceAwarePermission(permissionName: String): Boolean = DEVICE_AWARE_PERMISSIONS.contains(permissionName) @@ -283,11 +279,8 @@ class DevicePermissionPolicy : SchemePolicy() { } } - /** - * TODO: b/289355341 - implement listener for permission changes Listener for permission flags - * changes. - */ - abstract class OnDevicePermissionFlagsChangedListener { + /** Listener for permission flags changes. */ + interface OnDevicePermissionFlagsChangedListener { /** * Called when a permission flags change has been made to the upcoming new state. * @@ -295,7 +288,7 @@ class DevicePermissionPolicy : SchemePolicy() { * and only call external code after [onStateMutated] when the new state has actually become * the current state visible to external code. */ - abstract fun onDevicePermissionFlagsChanged( + fun onDevicePermissionFlagsChanged( appId: Int, userId: Int, deviceId: String, @@ -309,6 +302,6 @@ class DevicePermissionPolicy : SchemePolicy() { * * Implementations should keep this method fast to avoid stalling the locked state mutation. */ - abstract fun onStateMutated() + fun onStateMutated() } } 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 ab3d78c9958c..0d196b48b3f2 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 @@ -19,6 +19,7 @@ package com.android.server.permission.access.permission import android.Manifest import android.app.ActivityManager import android.app.AppOpsManager +import android.companion.virtual.VirtualDeviceManager import android.compat.annotation.ChangeId import android.compat.annotation.EnabledAfter import android.content.Context @@ -169,6 +170,7 @@ class PermissionService(private val service: AccessCheckingService) : onPermissionsChangeListeners = OnPermissionsChangeListeners(FgThread.get().looper) onPermissionFlagsChangedListener = OnPermissionFlagsChangedListener() policy.addOnPermissionFlagsChangedListener(onPermissionFlagsChangedListener) + devicePolicy.addOnPermissionFlagsChangedListener(onPermissionFlagsChangedListener) } override fun getAllPermissionGroups(flags: Int): List<PermissionGroupInfo> { @@ -2616,10 +2618,11 @@ class PermissionService(private val service: AccessCheckingService) : /** Callback invoked when interesting actions have been taken on a permission. */ private inner class OnPermissionFlagsChangedListener : - AppIdPermissionPolicy.OnPermissionFlagsChangedListener() { + AppIdPermissionPolicy.OnPermissionFlagsChangedListener, + DevicePermissionPolicy.OnDevicePermissionFlagsChangedListener { private var isPermissionFlagsChanged = false - private val runtimePermissionChangedUids = MutableIntSet() + private val runtimePermissionChangedUidDevices = MutableIntMap<MutableSet<String>>() // Mapping from UID to whether only notifications permissions are revoked. private val runtimePermissionRevokedUids = SparseBooleanArray() private val gidsChangedUids = MutableIntSet() @@ -2642,6 +2645,24 @@ class PermissionService(private val service: AccessCheckingService) : oldFlags: Int, newFlags: Int ) { + onDevicePermissionFlagsChanged( + appId, + userId, + VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT, + permissionName, + oldFlags, + newFlags + ) + } + + override fun onDevicePermissionFlagsChanged( + appId: Int, + userId: Int, + deviceId: String, + permissionName: String, + oldFlags: Int, + newFlags: Int + ) { isPermissionFlagsChanged = true val uid = UserHandle.getUid(userId, appId) @@ -2655,12 +2676,12 @@ class PermissionService(private val service: AccessCheckingService) : // permission flags have changed for a non-runtime permission, now we no longer do // that because permission flags are only for runtime permissions and the listeners // aren't being notified of non-runtime permission grant state changes anyway. - runtimePermissionChangedUids += uid if (wasPermissionGranted && !isPermissionGranted) { runtimePermissionRevokedUids[uid] = permissionName in NOTIFICATIONS_PERMISSIONS && runtimePermissionRevokedUids.get(uid, true) } + runtimePermissionChangedUidDevices.getOrPut(uid) { mutableSetOf() } += deviceId } if (permission.hasGids && !wasPermissionGranted && isPermissionGranted) { @@ -2674,10 +2695,12 @@ class PermissionService(private val service: AccessCheckingService) : isPermissionFlagsChanged = false } - runtimePermissionChangedUids.forEachIndexed { _, uid -> - onPermissionsChangeListeners.onPermissionsChanged(uid) + runtimePermissionChangedUidDevices.forEachIndexed { _, uid, deviceIds -> + deviceIds.forEach { deviceId -> + onPermissionsChangeListeners.onPermissionsChanged(uid, deviceId) + } } - runtimePermissionChangedUids.clear() + runtimePermissionChangedUidDevices.clear() if (!isKillRuntimePermissionRevokedUidsSkipped) { val reason = @@ -2749,15 +2772,16 @@ class PermissionService(private val service: AccessCheckingService) : when (msg.what) { MSG_ON_PERMISSIONS_CHANGED -> { val uid = msg.arg1 - handleOnPermissionsChanged(uid) + val deviceId = msg.obj as String + handleOnPermissionsChanged(uid, deviceId) } } } - private fun handleOnPermissionsChanged(uid: Int) { + private fun handleOnPermissionsChanged(uid: Int, deviceId: String) { listeners.broadcast { listener -> try { - listener.onPermissionsChanged(uid) + listener.onPermissionsChanged(uid, deviceId) } catch (e: RemoteException) { Slog.e(LOG_TAG, "Error when calling OnPermissionsChangeListener", e) } @@ -2772,9 +2796,9 @@ class PermissionService(private val service: AccessCheckingService) : listeners.unregister(listener) } - fun onPermissionsChanged(uid: Int) { + fun onPermissionsChanged(uid: Int, deviceId: String) { if (listeners.registeredCallbackCount > 0) { - obtainMessage(MSG_ON_PERMISSIONS_CHANGED, uid, 0).sendToTarget() + obtainMessage(MSG_ON_PERMISSIONS_CHANGED, uid, 0, deviceId).sendToTarget() } } |