diff --git a/api/current.txt b/api/current.txt index 636ac72aa5449..d9a89b1982a81 100644 --- a/api/current.txt +++ b/api/current.txt @@ -12253,12 +12253,14 @@ package android.content.pm { field public static final int FLAG_SINGLE_USER = 1073741824; // 0x40000000 field public static final int FLAG_STOP_WITH_TASK = 1; // 0x1 field public static final int FLAG_USE_APP_ZYGOTE = 8; // 0x8 + field public static final int FOREGROUND_SERVICE_TYPE_CAMERA = 64; // 0x40 field public static final int FOREGROUND_SERVICE_TYPE_CONNECTED_DEVICE = 16; // 0x10 field public static final int FOREGROUND_SERVICE_TYPE_DATA_SYNC = 1; // 0x1 field public static final int FOREGROUND_SERVICE_TYPE_LOCATION = 8; // 0x8 field public static final int FOREGROUND_SERVICE_TYPE_MANIFEST = -1; // 0xffffffff field public static final int FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK = 2; // 0x2 field public static final int FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION = 32; // 0x20 + field public static final int FOREGROUND_SERVICE_TYPE_MICROPHONE = 128; // 0x80 field public static final int FOREGROUND_SERVICE_TYPE_NONE = 0; // 0x0 field public static final int FOREGROUND_SERVICE_TYPE_PHONE_CALL = 4; // 0x4 field public int flags; diff --git a/api/test-current.txt b/api/test-current.txt index e4304e757a305..d4b799dd405e3 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -75,8 +75,10 @@ package android.app { method public static void resumeAppSwitches() throws android.os.RemoteException; method @RequiresPermission(android.Manifest.permission.CHANGE_CONFIGURATION) public void scheduleApplicationInfoChanged(java.util.List, int); method @RequiresPermission("android.permission.MANAGE_USERS") public boolean switchUser(@NonNull android.os.UserHandle); - field public static final int PROCESS_CAPABILITY_ALL = 1; // 0x1 + field public static final int PROCESS_CAPABILITY_ALL = 7; // 0x7 + field public static final int PROCESS_CAPABILITY_FOREGROUND_CAMERA = 2; // 0x2 field public static final int PROCESS_CAPABILITY_FOREGROUND_LOCATION = 1; // 0x1 + field public static final int PROCESS_CAPABILITY_FOREGROUND_MICROPHONE = 4; // 0x4 field public static final int PROCESS_CAPABILITY_NONE = 0; // 0x0 } diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index 67a59f1975d51..96029c92b0f2d 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -573,6 +573,8 @@ public class ActivityManager { @IntDef(flag = true, prefix = { "PROCESS_CAPABILITY_" }, value = { PROCESS_CAPABILITY_NONE, PROCESS_CAPABILITY_FOREGROUND_LOCATION, + PROCESS_CAPABILITY_FOREGROUND_CAMERA, + PROCESS_CAPABILITY_FOREGROUND_MICROPHONE, }) @Retention(RetentionPolicy.SOURCE) public @interface ProcessCapability {} @@ -585,9 +587,19 @@ public class ActivityManager { @TestApi public static final int PROCESS_CAPABILITY_FOREGROUND_LOCATION = 1 << 0; + /** @hide Process can access camera while in foreground */ + @TestApi + public static final int PROCESS_CAPABILITY_FOREGROUND_CAMERA = 1 << 1; + + /** @hide Process can access microphone while in foreground */ + @TestApi + public static final int PROCESS_CAPABILITY_FOREGROUND_MICROPHONE = 1 << 2; + /** @hide all capabilities, the ORing of all flags in {@link ProcessCapability}*/ @TestApi - public static final int PROCESS_CAPABILITY_ALL = PROCESS_CAPABILITY_FOREGROUND_LOCATION; + public static final int PROCESS_CAPABILITY_ALL = PROCESS_CAPABILITY_FOREGROUND_LOCATION + | PROCESS_CAPABILITY_FOREGROUND_CAMERA + | PROCESS_CAPABILITY_FOREGROUND_MICROPHONE; // NOTE: If PROCESS_STATEs are added, then new fields must be added // to frameworks/base/core/proto/android/app/enums.proto and the following method must diff --git a/core/java/android/content/pm/ServiceInfo.java b/core/java/android/content/pm/ServiceInfo.java index 00507e1548a6b..5f90b6c43c609 100644 --- a/core/java/android/content/pm/ServiceInfo.java +++ b/core/java/android/content/pm/ServiceInfo.java @@ -146,6 +146,28 @@ public class ServiceInfo extends ComponentInfo */ public static final int FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION = 1 << 5; + /** + * Constant corresponding to {@code camera} in + * the {@link android.R.attr#foregroundServiceType} attribute. + * Use the camera device or record video. + * For apps with targetSdkVersion {@link android.os.Build.VERSION_CODES#R} and + * above, a foreground service will not be able to access the camera if this type is not + * specified in the manifest and in + * {@link android.app.Service#startForeground(int, android.app.Notification, int)}. + */ + public static final int FOREGROUND_SERVICE_TYPE_CAMERA = 1 << 6; + + /** + * Constant corresponding to {@code microphone} in + * the {@link android.R.attr#foregroundServiceType} attribute. + * Use the microphone device or record audio. + * For apps with targetSdkVersion {@link android.os.Build.VERSION_CODES#R} and + * above, a foreground service will not be able to access the microphone if this type is not + * specified in the manifest and in + * {@link android.app.Service#startForeground(int, android.app.Notification, int)}. + */ + public static final int FOREGROUND_SERVICE_TYPE_MICROPHONE = 1 << 7; + /** * A special value indicates to use all types set in manifest file. */ @@ -166,6 +188,8 @@ public class ServiceInfo extends ComponentInfo FOREGROUND_SERVICE_TYPE_LOCATION, FOREGROUND_SERVICE_TYPE_CONNECTED_DEVICE, FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION, + FOREGROUND_SERVICE_TYPE_CAMERA, + FOREGROUND_SERVICE_TYPE_MICROPHONE }) @Retention(RetentionPolicy.SOURCE) public @interface ForegroundServiceType {} diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml index 94f3b8ae67140..0895edc1da707 100644 --- a/core/res/res/values/attrs_manifest.xml +++ b/core/res/res/values/attrs_manifest.xml @@ -1520,6 +1520,22 @@ + + + + diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java index 0b115ea5ca5af..be14b3b03923e 100644 --- a/services/core/java/com/android/server/am/OomAdjuster.java +++ b/services/core/java/com/android/server/am/OomAdjuster.java @@ -17,7 +17,9 @@ package com.android.server.am; import static android.app.ActivityManager.PROCESS_CAPABILITY_ALL; +import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_CAMERA; import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION; +import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_MICROPHONE; import static android.app.ActivityManager.PROCESS_CAPABILITY_NONE; import static android.app.ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE; import static android.app.ActivityManager.PROCESS_STATE_BOUND_TOP; @@ -33,6 +35,9 @@ import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT; import static android.app.ActivityManager.PROCESS_STATE_SERVICE; import static android.app.ActivityManager.PROCESS_STATE_TOP; import static android.app.ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND; +import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_CAMERA; +import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION; +import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_MICROPHONE; import static android.os.Process.SCHED_OTHER; import static android.os.Process.THREAD_GROUP_BACKGROUND; import static android.os.Process.THREAD_GROUP_DEFAULT; @@ -1230,10 +1235,6 @@ public final class OomAdjuster { } } - if (app.hasLocationForegroundServices()) { - capability |= PROCESS_CAPABILITY_FOREGROUND_LOCATION; - } - if (adj > ProcessList.PERCEPTIBLE_APP_ADJ || procState > PROCESS_STATE_FOREGROUND_SERVICE) { if (app.hasForegroundServices()) { @@ -1397,6 +1398,7 @@ public final class OomAdjuster { } } + int capabilityFromFGS = 0; // capability from foreground service. for (int is = app.services.size() - 1; is >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ || schedGroup == ProcessList.SCHED_GROUP_BACKGROUND @@ -1445,6 +1447,24 @@ public final class OomAdjuster { } } + if (s.isForeground) { + final int fgsType = s.foregroundServiceType; + capabilityFromFGS |= + (fgsType & FOREGROUND_SERVICE_TYPE_LOCATION) + != 0 ? PROCESS_CAPABILITY_FOREGROUND_LOCATION : 0; + if (s.appInfo.targetSdkVersion < Build.VERSION_CODES.R) { + capabilityFromFGS |= PROCESS_CAPABILITY_FOREGROUND_CAMERA + | PROCESS_CAPABILITY_FOREGROUND_MICROPHONE; + } else { + capabilityFromFGS |= + (fgsType & FOREGROUND_SERVICE_TYPE_CAMERA) + != 0 ? PROCESS_CAPABILITY_FOREGROUND_CAMERA : 0; + capabilityFromFGS |= + (fgsType & FOREGROUND_SERVICE_TYPE_MICROPHONE) + != 0 ? PROCESS_CAPABILITY_FOREGROUND_MICROPHONE : 0; + } + } + ArrayMap> serviceConnections = s.getConnections(); for (int conni = serviceConnections.size() - 1; conni >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ @@ -1905,6 +1925,10 @@ public final class OomAdjuster { } } + // apply capability from FGS. + if (app.hasForegroundServices()) { + capability |= capabilityFromFGS; + } // TOP process has all capabilities. if (procState <= PROCESS_STATE_TOP) { capability = PROCESS_CAPABILITY_ALL; diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java index e3b761e0773d4..08136a3cb9e5a 100644 --- a/services/core/java/com/android/server/appop/AppOpsService.java +++ b/services/core/java/com/android/server/appop/AppOpsService.java @@ -16,7 +16,9 @@ package com.android.server.appop; +import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_CAMERA; import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION; +import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_MICROPHONE; import static android.app.AppOpsManager.FILTER_BY_FEATURE_ID; import static android.app.AppOpsManager.FILTER_BY_OP_NAMES; import static android.app.AppOpsManager.FILTER_BY_PACKAGE_NAME; @@ -467,6 +469,12 @@ public class AppOpsService extends IAppOpsService.Stub { case AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION: return ((capability & PROCESS_CAPABILITY_FOREGROUND_LOCATION) != 0) ? AppOpsManager.MODE_ALLOWED : AppOpsManager.MODE_IGNORED; + case OP_CAMERA: + return ((capability & PROCESS_CAPABILITY_FOREGROUND_CAMERA) != 0) + ? AppOpsManager.MODE_ALLOWED : AppOpsManager.MODE_IGNORED; + case OP_RECORD_AUDIO: + return ((capability & PROCESS_CAPABILITY_FOREGROUND_MICROPHONE) != 0) + ? AppOpsManager.MODE_ALLOWED : AppOpsManager.MODE_IGNORED; default: return AppOpsManager.MODE_ALLOWED; }