diff --git a/core/java/android/app/ForegroundServiceTypePolicy.java b/core/java/android/app/ForegroundServiceTypePolicy.java index e419e0602f2a0..fbc11e930a602 100644 --- a/core/java/android/app/ForegroundServiceTypePolicy.java +++ b/core/java/android/app/ForegroundServiceTypePolicy.java @@ -53,6 +53,7 @@ import android.content.pm.ServiceInfo.ForegroundServiceType; import android.hardware.usb.UsbAccessory; import android.hardware.usb.UsbDevice; import android.hardware.usb.UsbManager; +import android.healthconnect.HealthConnectManager; import android.os.RemoteException; import android.os.ServiceManager; import android.util.ArraySet; @@ -65,8 +66,10 @@ import com.android.internal.util.ArrayUtils; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.util.ArrayList; import java.util.HashMap; import java.util.Optional; +import java.util.Set; /** * This class enforces the policies around the foreground service types. @@ -640,11 +643,12 @@ public abstract class ForegroundServiceTypePolicy { * * For test only. */ - public @NonNull Optional getRequiredAllOfPermissionsForTest() { + public @NonNull Optional getRequiredAllOfPermissionsForTest( + @NonNull Context context) { if (mAllOfPermissions == null) { return Optional.empty(); } - return Optional.of(mAllOfPermissions.toStringArray()); + return Optional.of(mAllOfPermissions.toStringArray(context)); } /** @@ -653,11 +657,12 @@ public abstract class ForegroundServiceTypePolicy { * * For test only. */ - public @NonNull Optional getRequiredAnyOfPermissionsForTest() { + public @NonNull Optional getRequiredAnyOfPermissionsForTest( + @NonNull Context context) { if (mAnyOfPermissions == null) { return Optional.empty(); } - return Optional.of(mAnyOfPermissions.toStringArray()); + return Optional.of(mAnyOfPermissions.toStringArray(context)); } /** @@ -793,12 +798,12 @@ public abstract class ForegroundServiceTypePolicy { return sb.toString(); } - @NonNull String[] toStringArray() { - final String[] names = new String[mPermissions.length]; + @NonNull String[] toStringArray(Context context) { + final ArrayList list = new ArrayList<>(); for (int i = 0; i < mPermissions.length; i++) { - names[i] = mPermissions[i].mName; + mPermissions[i].addToList(context, list); } - return names; + return list.toArray(new String[list.size()]); } } @@ -811,7 +816,7 @@ public abstract class ForegroundServiceTypePolicy { /** * The name of this permission. */ - final @NonNull String mName; + protected final @NonNull String mName; /** * Constructor. @@ -831,6 +836,10 @@ public abstract class ForegroundServiceTypePolicy { public String toString() { return mName; } + + void addToList(@NonNull Context context, @NonNull ArrayList list) { + list.add(mName); + } } /** @@ -844,15 +853,23 @@ public abstract class ForegroundServiceTypePolicy { @Override @SuppressLint("AndroidFrameworkRequiresPermission") @PackageManager.PermissionResult - public int checkPermission(Context context, int callerUid, int callerPid, + public int checkPermission(@NonNull Context context, int callerUid, int callerPid, String packageName, boolean allowWhileInUse) { + return checkPermission(context, mName, callerUid, callerPid, packageName, + allowWhileInUse); + } + + @SuppressLint("AndroidFrameworkRequiresPermission") + @PackageManager.PermissionResult + int checkPermission(@NonNull Context context, @NonNull String name, int callerUid, + int callerPid, String packageName, boolean allowWhileInUse) { // Simple case, check if it's already granted. - if (context.checkPermission(mName, callerPid, callerUid) == PERMISSION_GRANTED) { + if (context.checkPermission(name, callerPid, callerUid) == PERMISSION_GRANTED) { return PERMISSION_GRANTED; } if (allowWhileInUse) { // Check its appops - final int opCode = AppOpsManager.permissionToOpCode(mName); + final int opCode = AppOpsManager.permissionToOpCode(name); final AppOpsManager appOpsManager = context.getSystemService(AppOpsManager.class); if (opCode != AppOpsManager.OP_NONE) { final int currentMode = appOpsManager.unsafeCheckOpRawNoThrow(opCode, callerUid, @@ -880,7 +897,7 @@ public abstract class ForegroundServiceTypePolicy { @Override @PackageManager.PermissionResult - public int checkPermission(Context context, int callerUid, int callerPid, + public int checkPermission(@NonNull Context context, int callerUid, int callerPid, String packageName, boolean allowWhileInUse) { final AppOpsManager appOpsManager = context.getSystemService(AppOpsManager.class); final int mode = appOpsManager.unsafeCheckOpRawNoThrow(mOpCode, callerUid, packageName); @@ -900,7 +917,7 @@ public abstract class ForegroundServiceTypePolicy { @Override @SuppressLint("AndroidFrameworkRequiresPermission") @PackageManager.PermissionResult - public int checkPermission(Context context, int callerUid, int callerPid, + public int checkPermission(@NonNull Context context, int callerUid, int callerPid, String packageName, boolean allowWhileInUse) { final UsbManager usbManager = context.getSystemService(UsbManager.class); final HashMap devices = usbManager.getDeviceList(); @@ -926,7 +943,7 @@ public abstract class ForegroundServiceTypePolicy { @Override @SuppressLint("AndroidFrameworkRequiresPermission") @PackageManager.PermissionResult - public int checkPermission(Context context, int callerUid, int callerPid, + public int checkPermission(@NonNull Context context, int callerUid, int callerPid, String packageName, boolean allowWhileInUse) { final UsbManager usbManager = context.getSystemService(UsbManager.class); final UsbAccessory[] accessories = usbManager.getAccessoryList(); @@ -941,6 +958,45 @@ public abstract class ForegroundServiceTypePolicy { } } + static class HealthConnectPermission extends RegularPermission { + private @Nullable String[] mPermissionNames; + + HealthConnectPermission() { + super("Health Connect"); + } + + @Override + @SuppressLint("AndroidFrameworkRequiresPermission") + @PackageManager.PermissionResult + public int checkPermission(@NonNull Context context, int callerUid, int callerPid, + String packageName, boolean allowWhileInUse) { + final String[] perms = getPermissions(context); + for (String perm : perms) { + if (checkPermission(context, perm, callerUid, callerPid, + packageName, allowWhileInUse) == PERMISSION_GRANTED) { + return PERMISSION_GRANTED; + } + } + return PERMISSION_DENIED; + } + + @Override + void addToList(@NonNull Context context, @NonNull ArrayList list) { + final String[] perms = getPermissions(context); + for (String perm : perms) { + list.add(perm); + } + } + + private @NonNull String[] getPermissions(@NonNull Context context) { + if (mPermissionNames != null) { + return mPermissionNames; + } + final Set healthPerms = HealthConnectManager.getHealthPermissions(context); + return mPermissionNames = healthPerms.toArray(new String[healthPerms.size()]); + } + } + /** * The default policy for the foreground service types. * diff --git a/core/java/android/content/pm/ServiceInfo.java b/core/java/android/content/pm/ServiceInfo.java index 14f03eae8bf15..c2c61302df591 100644 --- a/core/java/android/content/pm/ServiceInfo.java +++ b/core/java/android/content/pm/ServiceInfo.java @@ -308,7 +308,9 @@ public class ServiceInfo extends ComponentInfo * permissions: * {@link android.Manifest.permission#ACTIVITY_RECOGNITION}, * {@link android.Manifest.permission#BODY_SENSORS}, - * {@link android.Manifest.permission#HIGH_SAMPLING_RATE_SENSORS}. + * {@link android.Manifest.permission#HIGH_SAMPLING_RATE_SENSORS}, + * or one of the {@code "android.permission.health.*"} permissions defined in the + * {@link android.healthconnect.HealthPermissions}. */ @RequiresPermission( allOf = { @@ -424,7 +426,7 @@ public class ServiceInfo extends ComponentInfo * android:name=".MySpecialForegroundService" * android:foregroundServiceType="specialUse|foo"> * <property - * android:name="android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE"" + * android:name="android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE" * android:value="foo" * /> * </service> diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml index 01c080990cfd1..680a0a17dca82 100644 --- a/packages/Shell/AndroidManifest.xml +++ b/packages/Shell/AndroidManifest.xml @@ -771,6 +771,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +