diff options
-rw-r--r-- | core/java/android/app/ForegroundServiceTypePolicy.java | 47 |
1 files changed, 41 insertions, 6 deletions
diff --git a/core/java/android/app/ForegroundServiceTypePolicy.java b/core/java/android/app/ForegroundServiceTypePolicy.java index 6efc4ef55180..3003b79435e2 100644 --- a/core/java/android/app/ForegroundServiceTypePolicy.java +++ b/core/java/android/app/ForegroundServiceTypePolicy.java @@ -49,11 +49,14 @@ import android.annotation.Nullable; import android.annotation.SuppressLint; import android.app.compat.CompatChanges; import android.app.role.RoleManager; +import android.companion.virtual.VirtualDevice; +import android.companion.virtual.VirtualDeviceManager; import android.compat.Compatibility; import android.compat.annotation.ChangeId; import android.compat.annotation.Disabled; import android.compat.annotation.EnabledAfter; import android.compat.annotation.Overridable; +import android.content.AttributionSource; import android.content.Context; import android.content.PermissionChecker; import android.content.pm.PackageManager; @@ -67,6 +70,7 @@ import android.os.RemoteException; import android.os.ServiceManager; import android.os.UserHandle; import android.permission.PermissionCheckerManager; +import android.permission.PermissionManager; import android.provider.DeviceConfig; import android.text.TextUtils; import android.util.ArrayMap; @@ -1174,17 +1178,48 @@ public abstract class ForegroundServiceTypePolicy { @PackageManager.PermissionResult public int checkPermission(@NonNull Context context, int callerUid, int callerPid, String packageName, boolean allowWhileInUse) { - return checkPermission(context, mName, callerUid, callerPid, packageName, - allowWhileInUse); + int permissionResult = checkPermission(context, mName, callerUid, callerPid, + packageName, allowWhileInUse, Context.DEVICE_ID_DEFAULT); + + if (permissionResult == PERMISSION_GRANTED + || !PermissionManager.DEVICE_AWARE_PERMISSIONS.contains(mName)) { + return permissionResult; + } + + // For device aware permissions, check if the permission is granted on any other + // active virtual device + VirtualDeviceManager vdm = context.getSystemService(VirtualDeviceManager.class); + if (vdm == null) { + return permissionResult; + } + + final List<VirtualDevice> virtualDevices = vdm.getVirtualDevices(); + for (int i = 0, size = virtualDevices.size(); i < size; i++) { + final VirtualDevice virtualDevice = virtualDevices.get(i); + int resolvedDeviceId = PermissionManager.resolveDeviceIdForPermissionCheck( + context, virtualDevice.getDeviceId(), mName); + // we already checked on the default device context + if (resolvedDeviceId == Context.DEVICE_ID_DEFAULT) { + continue; + } + permissionResult = checkPermission(context, mName, callerUid, callerPid, + packageName, allowWhileInUse, resolvedDeviceId); + if (permissionResult == PERMISSION_GRANTED) { + break; + } + } + + return permissionResult; } @SuppressLint("AndroidFrameworkRequiresPermission") @PackageManager.PermissionResult int checkPermission(@NonNull Context context, @NonNull String name, int callerUid, - int callerPid, String packageName, boolean allowWhileInUse) { + int callerPid, String packageName, boolean allowWhileInUse, int deviceId) { + final AttributionSource attributionSource = new AttributionSource(callerUid, + packageName, null /*attributionTag*/, deviceId); @PermissionCheckerManager.PermissionResult final int result = - PermissionChecker.checkPermissionForPreflight(context, name, - callerPid, callerUid, packageName); + PermissionChecker.checkPermissionForPreflight(context, name, attributionSource); if (result == PERMISSION_HARD_DENIED) { // If the user didn't grant this permission at all. return PERMISSION_DENIED; @@ -1196,7 +1231,7 @@ public abstract class ForegroundServiceTypePolicy { ? PERMISSION_GRANTED : PERMISSION_DENIED; } final AppOpsManager appOpsManager = context.getSystemService(AppOpsManager.class); - final int mode = appOpsManager.unsafeCheckOpRawNoThrow(opCode, callerUid, packageName); + final int mode = appOpsManager.unsafeCheckOpRawNoThrow(opCode, attributionSource); switch (mode) { case MODE_ALLOWED: // The appop is just allowed, plain and simple. |