Loading core/java/android/app/AppOpsManager.java +38 −2 Original line number Original line Diff line number Diff line Loading @@ -1461,9 +1461,25 @@ public class AppOpsManager { */ */ public static final int OP_USE_FULL_SCREEN_INTENT = AppProtoEnums.APP_OP_USE_FULL_SCREEN_INTENT; public static final int OP_USE_FULL_SCREEN_INTENT = AppProtoEnums.APP_OP_USE_FULL_SCREEN_INTENT; /** * Hides camera indicator for sandboxed detection apps that directly access the service. * * @hide */ public static final int OP_CAMERA_SANDBOXED = AppProtoEnums.APP_OP_CAMERA_SANDBOXED; /** * Hides microphone indicator for sandboxed detection apps that directly access the service. * * @hide */ public static final int OP_RECORD_AUDIO_SANDBOXED = AppProtoEnums.APP_OP_RECORD_AUDIO_SANDBOXED; /** @hide */ /** @hide */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public static final int _NUM_OP = 134; public static final int _NUM_OP = 136; /** /** * All app ops represented as strings. * All app ops represented as strings. Loading Loading @@ -1605,6 +1621,8 @@ public class AppOpsManager { OPSTR_CAPTURE_CONSENTLESS_BUGREPORT_ON_USERDEBUG_BUILD, OPSTR_CAPTURE_CONSENTLESS_BUGREPORT_ON_USERDEBUG_BUILD, OPSTR_BODY_SENSORS_WRIST_TEMPERATURE, OPSTR_BODY_SENSORS_WRIST_TEMPERATURE, OPSTR_USE_FULL_SCREEN_INTENT, OPSTR_USE_FULL_SCREEN_INTENT, OPSTR_CAMERA_SANDBOXED, OPSTR_RECORD_AUDIO_SANDBOXED }) }) public @interface AppOpString {} public @interface AppOpString {} Loading Loading @@ -2012,6 +2030,20 @@ public class AppOpsManager { */ */ public static final String OPSTR_COARSE_LOCATION_SOURCE = "android:coarse_location_source"; public static final String OPSTR_COARSE_LOCATION_SOURCE = "android:coarse_location_source"; /** * Camera is being recorded in sandboxed detection process. * * @hide */ public static final String OPSTR_CAMERA_SANDBOXED = "android:camera_sandboxed"; /** * Audio is being recorded in sandboxed detection process. * * @hide */ public static final String OPSTR_RECORD_AUDIO_SANDBOXED = "android:record_audio_sandboxed"; /** /** * Allow apps to create the requests to manage the media files without user confirmation. * Allow apps to create the requests to manage the media files without user confirmation. * * Loading Loading @@ -2738,7 +2770,11 @@ public class AppOpsManager { .setDefaultMode(AppOpsManager.MODE_ALLOWED).build(), .setDefaultMode(AppOpsManager.MODE_ALLOWED).build(), new AppOpInfo.Builder(OP_USE_FULL_SCREEN_INTENT, OPSTR_USE_FULL_SCREEN_INTENT, new AppOpInfo.Builder(OP_USE_FULL_SCREEN_INTENT, OPSTR_USE_FULL_SCREEN_INTENT, "USE_FULL_SCREEN_INTENT").setPermission(Manifest.permission.USE_FULL_SCREEN_INTENT) "USE_FULL_SCREEN_INTENT").setPermission(Manifest.permission.USE_FULL_SCREEN_INTENT) .build() .build(), new AppOpInfo.Builder(OP_CAMERA_SANDBOXED, OPSTR_CAMERA_SANDBOXED, "CAMERA_SANDBOXED").setDefaultMode(AppOpsManager.MODE_ALLOWED).build(), new AppOpInfo.Builder(OP_RECORD_AUDIO_SANDBOXED, OPSTR_RECORD_AUDIO_SANDBOXED, "RECORD_AUDIO_SANDBOXED").setDefaultMode(AppOpsManager.MODE_ALLOWED).build() }; }; // The number of longs needed to form a full bitmask of app ops // The number of longs needed to form a full bitmask of app ops Loading services/core/java/com/android/server/appop/AppOpsService.java +19 −5 Original line number Original line Diff line number Diff line Loading @@ -34,6 +34,7 @@ import static android.app.AppOpsManager.MODE_ERRORED; import static android.app.AppOpsManager.MODE_FOREGROUND; import static android.app.AppOpsManager.MODE_FOREGROUND; import static android.app.AppOpsManager.MODE_IGNORED; import static android.app.AppOpsManager.MODE_IGNORED; import static android.app.AppOpsManager.OP_CAMERA; import static android.app.AppOpsManager.OP_CAMERA; import static android.app.AppOpsManager.OP_CAMERA_SANDBOXED; import static android.app.AppOpsManager.OP_FLAGS_ALL; import static android.app.AppOpsManager.OP_FLAGS_ALL; import static android.app.AppOpsManager.OP_FLAG_SELF; import static android.app.AppOpsManager.OP_FLAG_SELF; import static android.app.AppOpsManager.OP_FLAG_TRUSTED_PROXIED; import static android.app.AppOpsManager.OP_FLAG_TRUSTED_PROXIED; Loading @@ -42,6 +43,7 @@ import static android.app.AppOpsManager.OP_PLAY_AUDIO; import static android.app.AppOpsManager.OP_RECEIVE_AMBIENT_TRIGGER_AUDIO; import static android.app.AppOpsManager.OP_RECEIVE_AMBIENT_TRIGGER_AUDIO; import static android.app.AppOpsManager.OP_RECORD_AUDIO; import static android.app.AppOpsManager.OP_RECORD_AUDIO; import static android.app.AppOpsManager.OP_RECORD_AUDIO_HOTWORD; import static android.app.AppOpsManager.OP_RECORD_AUDIO_HOTWORD; import static android.app.AppOpsManager.OP_RECORD_AUDIO_SANDBOXED; import static android.app.AppOpsManager.OP_VIBRATE; import static android.app.AppOpsManager.OP_VIBRATE; import static android.app.AppOpsManager.OnOpStartedListener.START_TYPE_FAILED; import static android.app.AppOpsManager.OnOpStartedListener.START_TYPE_FAILED; import static android.app.AppOpsManager.OnOpStartedListener.START_TYPE_STARTED; import static android.app.AppOpsManager.OnOpStartedListener.START_TYPE_STARTED; Loading Loading @@ -3027,17 +3029,29 @@ public class AppOpsService extends IAppOpsService.Stub { packageName); packageName); } } // As a special case for OP_RECORD_AUDIO_HOTWORD, which we use only for attribution // As a special case for OP_RECORD_AUDIO_HOTWORD, OP_RECEIVE_AMBIENT_TRIGGER_AUDIO and // purposes and not as a check, also make sure that the caller is allowed to access // OP_RECORD_AUDIO_SANDBOXED which we use only for attribution purposes and not as a check, // the data gated by OP_RECORD_AUDIO. // also make sure that the caller is allowed to access the data gated by OP_RECORD_AUDIO. // // // TODO: Revert this change before Android 12. // TODO: Revert this change before Android 12. if (code == OP_RECORD_AUDIO_HOTWORD || code == OP_RECEIVE_AMBIENT_TRIGGER_AUDIO) { int result = MODE_DEFAULT; int result = checkOperation(OP_RECORD_AUDIO, uid, packageName); if (code == OP_RECORD_AUDIO_HOTWORD || code == OP_RECEIVE_AMBIENT_TRIGGER_AUDIO || code == OP_RECORD_AUDIO_SANDBOXED) { result = checkOperation(OP_RECORD_AUDIO, uid, packageName); // Check result if (result != AppOpsManager.MODE_ALLOWED) { if (result != AppOpsManager.MODE_ALLOWED) { return new SyncNotedAppOp(result, code, attributionTag, packageName); return new SyncNotedAppOp(result, code, attributionTag, packageName); } } } } // As a special case for OP_CAMERA_SANDBOXED. if (code == OP_CAMERA_SANDBOXED) { result = checkOperation(OP_CAMERA, uid, packageName); // Check result if (result != AppOpsManager.MODE_ALLOWED) { return new SyncNotedAppOp(result, code, attributionTag, packageName); } } return startOperationUnchecked(clientId, code, uid, packageName, attributionTag, return startOperationUnchecked(clientId, code, uid, packageName, attributionTag, Process.INVALID_UID, null, null, OP_FLAG_SELF, startIfModeDefault, Process.INVALID_UID, null, null, OP_FLAG_SELF, startIfModeDefault, shouldCollectAsyncNotedOp, message, shouldCollectMessage, attributionFlags, shouldCollectAsyncNotedOp, message, shouldCollectMessage, attributionFlags, Loading services/core/java/com/android/server/policy/AppOpsPolicy.java +23 −0 Original line number Original line Diff line number Diff line Loading @@ -316,6 +316,7 @@ public final class AppOpsPolicy implements AppOpsManagerInternal.CheckOpsDelegat private int resolveDatasourceOp(int code, int uid, @NonNull String packageName, private int resolveDatasourceOp(int code, int uid, @NonNull String packageName, @Nullable String attributionTag) { @Nullable String attributionTag) { code = resolveRecordAudioOp(code, uid); code = resolveRecordAudioOp(code, uid); code = resolveSandboxedServiceOp(code, uid); if (attributionTag == null) { if (attributionTag == null) { return code; return code; } } Loading Loading @@ -439,6 +440,28 @@ public final class AppOpsPolicy implements AppOpsManagerInternal.CheckOpsDelegat return code; return code; } } private int resolveSandboxedServiceOp(int code, int uid) { if (!Process.isIsolated(uid) // simple check which fails-fast for the common case || !(code == AppOpsManager.OP_RECORD_AUDIO || code == AppOpsManager.OP_CAMERA)) { return code; } final HotwordDetectionServiceIdentity hotwordDetectionServiceIdentity = mVoiceInteractionManagerInternal.getHotwordDetectionServiceIdentity(); if (hotwordDetectionServiceIdentity != null && uid == hotwordDetectionServiceIdentity.getIsolatedUid()) { // Upgrade the op such that no indicators is shown for camera or audio service. This // will bypass the permission checking for the original OP_RECORD_AUDIO and OP_CAMERA. switch (code) { case AppOpsManager.OP_RECORD_AUDIO: return AppOpsManager.OP_RECORD_AUDIO_SANDBOXED; case AppOpsManager.OP_CAMERA: return AppOpsManager.OP_CAMERA_SANDBOXED; } } return code; } private int resolveUid(int code, int uid) { private int resolveUid(int code, int uid) { // The HotwordDetectionService is an isolated service, which ordinarily cannot hold // The HotwordDetectionService is an isolated service, which ordinarily cannot hold // permissions. So we allow it to assume the owning package identity for certain // permissions. So we allow it to assume the owning package identity for certain Loading Loading
core/java/android/app/AppOpsManager.java +38 −2 Original line number Original line Diff line number Diff line Loading @@ -1461,9 +1461,25 @@ public class AppOpsManager { */ */ public static final int OP_USE_FULL_SCREEN_INTENT = AppProtoEnums.APP_OP_USE_FULL_SCREEN_INTENT; public static final int OP_USE_FULL_SCREEN_INTENT = AppProtoEnums.APP_OP_USE_FULL_SCREEN_INTENT; /** * Hides camera indicator for sandboxed detection apps that directly access the service. * * @hide */ public static final int OP_CAMERA_SANDBOXED = AppProtoEnums.APP_OP_CAMERA_SANDBOXED; /** * Hides microphone indicator for sandboxed detection apps that directly access the service. * * @hide */ public static final int OP_RECORD_AUDIO_SANDBOXED = AppProtoEnums.APP_OP_RECORD_AUDIO_SANDBOXED; /** @hide */ /** @hide */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public static final int _NUM_OP = 134; public static final int _NUM_OP = 136; /** /** * All app ops represented as strings. * All app ops represented as strings. Loading Loading @@ -1605,6 +1621,8 @@ public class AppOpsManager { OPSTR_CAPTURE_CONSENTLESS_BUGREPORT_ON_USERDEBUG_BUILD, OPSTR_CAPTURE_CONSENTLESS_BUGREPORT_ON_USERDEBUG_BUILD, OPSTR_BODY_SENSORS_WRIST_TEMPERATURE, OPSTR_BODY_SENSORS_WRIST_TEMPERATURE, OPSTR_USE_FULL_SCREEN_INTENT, OPSTR_USE_FULL_SCREEN_INTENT, OPSTR_CAMERA_SANDBOXED, OPSTR_RECORD_AUDIO_SANDBOXED }) }) public @interface AppOpString {} public @interface AppOpString {} Loading Loading @@ -2012,6 +2030,20 @@ public class AppOpsManager { */ */ public static final String OPSTR_COARSE_LOCATION_SOURCE = "android:coarse_location_source"; public static final String OPSTR_COARSE_LOCATION_SOURCE = "android:coarse_location_source"; /** * Camera is being recorded in sandboxed detection process. * * @hide */ public static final String OPSTR_CAMERA_SANDBOXED = "android:camera_sandboxed"; /** * Audio is being recorded in sandboxed detection process. * * @hide */ public static final String OPSTR_RECORD_AUDIO_SANDBOXED = "android:record_audio_sandboxed"; /** /** * Allow apps to create the requests to manage the media files without user confirmation. * Allow apps to create the requests to manage the media files without user confirmation. * * Loading Loading @@ -2738,7 +2770,11 @@ public class AppOpsManager { .setDefaultMode(AppOpsManager.MODE_ALLOWED).build(), .setDefaultMode(AppOpsManager.MODE_ALLOWED).build(), new AppOpInfo.Builder(OP_USE_FULL_SCREEN_INTENT, OPSTR_USE_FULL_SCREEN_INTENT, new AppOpInfo.Builder(OP_USE_FULL_SCREEN_INTENT, OPSTR_USE_FULL_SCREEN_INTENT, "USE_FULL_SCREEN_INTENT").setPermission(Manifest.permission.USE_FULL_SCREEN_INTENT) "USE_FULL_SCREEN_INTENT").setPermission(Manifest.permission.USE_FULL_SCREEN_INTENT) .build() .build(), new AppOpInfo.Builder(OP_CAMERA_SANDBOXED, OPSTR_CAMERA_SANDBOXED, "CAMERA_SANDBOXED").setDefaultMode(AppOpsManager.MODE_ALLOWED).build(), new AppOpInfo.Builder(OP_RECORD_AUDIO_SANDBOXED, OPSTR_RECORD_AUDIO_SANDBOXED, "RECORD_AUDIO_SANDBOXED").setDefaultMode(AppOpsManager.MODE_ALLOWED).build() }; }; // The number of longs needed to form a full bitmask of app ops // The number of longs needed to form a full bitmask of app ops Loading
services/core/java/com/android/server/appop/AppOpsService.java +19 −5 Original line number Original line Diff line number Diff line Loading @@ -34,6 +34,7 @@ import static android.app.AppOpsManager.MODE_ERRORED; import static android.app.AppOpsManager.MODE_FOREGROUND; import static android.app.AppOpsManager.MODE_FOREGROUND; import static android.app.AppOpsManager.MODE_IGNORED; import static android.app.AppOpsManager.MODE_IGNORED; import static android.app.AppOpsManager.OP_CAMERA; import static android.app.AppOpsManager.OP_CAMERA; import static android.app.AppOpsManager.OP_CAMERA_SANDBOXED; import static android.app.AppOpsManager.OP_FLAGS_ALL; import static android.app.AppOpsManager.OP_FLAGS_ALL; import static android.app.AppOpsManager.OP_FLAG_SELF; import static android.app.AppOpsManager.OP_FLAG_SELF; import static android.app.AppOpsManager.OP_FLAG_TRUSTED_PROXIED; import static android.app.AppOpsManager.OP_FLAG_TRUSTED_PROXIED; Loading @@ -42,6 +43,7 @@ import static android.app.AppOpsManager.OP_PLAY_AUDIO; import static android.app.AppOpsManager.OP_RECEIVE_AMBIENT_TRIGGER_AUDIO; import static android.app.AppOpsManager.OP_RECEIVE_AMBIENT_TRIGGER_AUDIO; import static android.app.AppOpsManager.OP_RECORD_AUDIO; import static android.app.AppOpsManager.OP_RECORD_AUDIO; import static android.app.AppOpsManager.OP_RECORD_AUDIO_HOTWORD; import static android.app.AppOpsManager.OP_RECORD_AUDIO_HOTWORD; import static android.app.AppOpsManager.OP_RECORD_AUDIO_SANDBOXED; import static android.app.AppOpsManager.OP_VIBRATE; import static android.app.AppOpsManager.OP_VIBRATE; import static android.app.AppOpsManager.OnOpStartedListener.START_TYPE_FAILED; import static android.app.AppOpsManager.OnOpStartedListener.START_TYPE_FAILED; import static android.app.AppOpsManager.OnOpStartedListener.START_TYPE_STARTED; import static android.app.AppOpsManager.OnOpStartedListener.START_TYPE_STARTED; Loading Loading @@ -3027,17 +3029,29 @@ public class AppOpsService extends IAppOpsService.Stub { packageName); packageName); } } // As a special case for OP_RECORD_AUDIO_HOTWORD, which we use only for attribution // As a special case for OP_RECORD_AUDIO_HOTWORD, OP_RECEIVE_AMBIENT_TRIGGER_AUDIO and // purposes and not as a check, also make sure that the caller is allowed to access // OP_RECORD_AUDIO_SANDBOXED which we use only for attribution purposes and not as a check, // the data gated by OP_RECORD_AUDIO. // also make sure that the caller is allowed to access the data gated by OP_RECORD_AUDIO. // // // TODO: Revert this change before Android 12. // TODO: Revert this change before Android 12. if (code == OP_RECORD_AUDIO_HOTWORD || code == OP_RECEIVE_AMBIENT_TRIGGER_AUDIO) { int result = MODE_DEFAULT; int result = checkOperation(OP_RECORD_AUDIO, uid, packageName); if (code == OP_RECORD_AUDIO_HOTWORD || code == OP_RECEIVE_AMBIENT_TRIGGER_AUDIO || code == OP_RECORD_AUDIO_SANDBOXED) { result = checkOperation(OP_RECORD_AUDIO, uid, packageName); // Check result if (result != AppOpsManager.MODE_ALLOWED) { if (result != AppOpsManager.MODE_ALLOWED) { return new SyncNotedAppOp(result, code, attributionTag, packageName); return new SyncNotedAppOp(result, code, attributionTag, packageName); } } } } // As a special case for OP_CAMERA_SANDBOXED. if (code == OP_CAMERA_SANDBOXED) { result = checkOperation(OP_CAMERA, uid, packageName); // Check result if (result != AppOpsManager.MODE_ALLOWED) { return new SyncNotedAppOp(result, code, attributionTag, packageName); } } return startOperationUnchecked(clientId, code, uid, packageName, attributionTag, return startOperationUnchecked(clientId, code, uid, packageName, attributionTag, Process.INVALID_UID, null, null, OP_FLAG_SELF, startIfModeDefault, Process.INVALID_UID, null, null, OP_FLAG_SELF, startIfModeDefault, shouldCollectAsyncNotedOp, message, shouldCollectMessage, attributionFlags, shouldCollectAsyncNotedOp, message, shouldCollectMessage, attributionFlags, Loading
services/core/java/com/android/server/policy/AppOpsPolicy.java +23 −0 Original line number Original line Diff line number Diff line Loading @@ -316,6 +316,7 @@ public final class AppOpsPolicy implements AppOpsManagerInternal.CheckOpsDelegat private int resolveDatasourceOp(int code, int uid, @NonNull String packageName, private int resolveDatasourceOp(int code, int uid, @NonNull String packageName, @Nullable String attributionTag) { @Nullable String attributionTag) { code = resolveRecordAudioOp(code, uid); code = resolveRecordAudioOp(code, uid); code = resolveSandboxedServiceOp(code, uid); if (attributionTag == null) { if (attributionTag == null) { return code; return code; } } Loading Loading @@ -439,6 +440,28 @@ public final class AppOpsPolicy implements AppOpsManagerInternal.CheckOpsDelegat return code; return code; } } private int resolveSandboxedServiceOp(int code, int uid) { if (!Process.isIsolated(uid) // simple check which fails-fast for the common case || !(code == AppOpsManager.OP_RECORD_AUDIO || code == AppOpsManager.OP_CAMERA)) { return code; } final HotwordDetectionServiceIdentity hotwordDetectionServiceIdentity = mVoiceInteractionManagerInternal.getHotwordDetectionServiceIdentity(); if (hotwordDetectionServiceIdentity != null && uid == hotwordDetectionServiceIdentity.getIsolatedUid()) { // Upgrade the op such that no indicators is shown for camera or audio service. This // will bypass the permission checking for the original OP_RECORD_AUDIO and OP_CAMERA. switch (code) { case AppOpsManager.OP_RECORD_AUDIO: return AppOpsManager.OP_RECORD_AUDIO_SANDBOXED; case AppOpsManager.OP_CAMERA: return AppOpsManager.OP_CAMERA_SANDBOXED; } } return code; } private int resolveUid(int code, int uid) { private int resolveUid(int code, int uid) { // The HotwordDetectionService is an isolated service, which ordinarily cannot hold // The HotwordDetectionService is an isolated service, which ordinarily cannot hold // permissions. So we allow it to assume the owning package identity for certain // permissions. So we allow it to assume the owning package identity for certain Loading