Hide camera and microphone indicators
Both indicators need to be hidden for VisualQueryDetectionService which does not have a designated AppOp defined for its access to the camera or audio service. Bug: 269304889 Test: Indicators are not shown Test: atest android.cts.statsdatom.appops.AppOpsTests#testAppOps Change-Id: I5a97e41f7ea4b000604e2dd47473ed7d70c81c45
This commit is contained in:
@@ -1461,9 +1461,25 @@ public class AppOpsManager {
|
||||
*/
|
||||
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 */
|
||||
@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.
|
||||
@@ -1605,6 +1621,8 @@ public class AppOpsManager {
|
||||
OPSTR_CAPTURE_CONSENTLESS_BUGREPORT_ON_USERDEBUG_BUILD,
|
||||
OPSTR_BODY_SENSORS_WRIST_TEMPERATURE,
|
||||
OPSTR_USE_FULL_SCREEN_INTENT,
|
||||
OPSTR_CAMERA_SANDBOXED,
|
||||
OPSTR_RECORD_AUDIO_SANDBOXED
|
||||
})
|
||||
public @interface AppOpString {}
|
||||
|
||||
@@ -2012,6 +2030,20 @@ public class AppOpsManager {
|
||||
*/
|
||||
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.
|
||||
*
|
||||
@@ -2738,7 +2770,11 @@ public class AppOpsManager {
|
||||
.setDefaultMode(AppOpsManager.MODE_ALLOWED).build(),
|
||||
new AppOpInfo.Builder(OP_USE_FULL_SCREEN_INTENT, OPSTR_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
|
||||
|
||||
@@ -34,6 +34,7 @@ import static android.app.AppOpsManager.MODE_ERRORED;
|
||||
import static android.app.AppOpsManager.MODE_FOREGROUND;
|
||||
import static android.app.AppOpsManager.MODE_IGNORED;
|
||||
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_FLAG_SELF;
|
||||
import static android.app.AppOpsManager.OP_FLAG_TRUSTED_PROXIED;
|
||||
@@ -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_RECORD_AUDIO;
|
||||
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.OnOpStartedListener.START_TYPE_FAILED;
|
||||
import static android.app.AppOpsManager.OnOpStartedListener.START_TYPE_STARTED;
|
||||
@@ -3027,17 +3029,29 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
packageName);
|
||||
}
|
||||
|
||||
// As a special case for OP_RECORD_AUDIO_HOTWORD, which we use only for attribution
|
||||
// purposes and not as a check, also make sure that the caller is allowed to access
|
||||
// the data gated by OP_RECORD_AUDIO.
|
||||
// As a special case for OP_RECORD_AUDIO_HOTWORD, OP_RECEIVE_AMBIENT_TRIGGER_AUDIO and
|
||||
// OP_RECORD_AUDIO_SANDBOXED which we use only for attribution purposes and not as a check,
|
||||
// also make sure that the caller is allowed to access the data gated by OP_RECORD_AUDIO.
|
||||
//
|
||||
// TODO: Revert this change before Android 12.
|
||||
if (code == OP_RECORD_AUDIO_HOTWORD || code == OP_RECEIVE_AMBIENT_TRIGGER_AUDIO) {
|
||||
int result = checkOperation(OP_RECORD_AUDIO, uid, packageName);
|
||||
int result = MODE_DEFAULT;
|
||||
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) {
|
||||
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,
|
||||
Process.INVALID_UID, null, null, OP_FLAG_SELF, startIfModeDefault,
|
||||
shouldCollectAsyncNotedOp, message, shouldCollectMessage, attributionFlags,
|
||||
|
||||
@@ -316,6 +316,7 @@ public final class AppOpsPolicy implements AppOpsManagerInternal.CheckOpsDelegat
|
||||
private int resolveDatasourceOp(int code, int uid, @NonNull String packageName,
|
||||
@Nullable String attributionTag) {
|
||||
code = resolveRecordAudioOp(code, uid);
|
||||
code = resolveSandboxedServiceOp(code, uid);
|
||||
if (attributionTag == null) {
|
||||
return code;
|
||||
}
|
||||
@@ -439,6 +440,28 @@ public final class AppOpsPolicy implements AppOpsManagerInternal.CheckOpsDelegat
|
||||
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) {
|
||||
// The HotwordDetectionService is an isolated service, which ordinarily cannot hold
|
||||
// permissions. So we allow it to assume the owning package identity for certain
|
||||
|
||||
Reference in New Issue
Block a user