RESTRICT AUTOMERGE Note RECEIVE_AMBIENT_TRIGGER_AUDIO in the SoundTrigger

In addition, moves the precise logic for soundtrigger RECORD_AUDIO
checks out of the soundtrigger system

Fixes: 230430779
Test: manual
Change-Id: I6d63c99e2d31e3f668070ac82afed71ff6672c9e
This commit is contained in:
Nate Myren
2022-05-04 15:41:10 -07:00
parent 03ffb3babe
commit 8c42b13518
11 changed files with 102 additions and 25 deletions

View File

@@ -1335,9 +1335,17 @@ public class AppOpsManager {
public static final int OP_ACCESS_RESTRICTED_SETTINGS = public static final int OP_ACCESS_RESTRICTED_SETTINGS =
AppProtoEnums.APP_OP_ACCESS_RESTRICTED_SETTINGS; AppProtoEnums.APP_OP_ACCESS_RESTRICTED_SETTINGS;
/**
* Receive microphone audio from an ambient sound detection event
*
* @hide
*/
public static final int OP_RECEIVE_AMBIENT_TRIGGER_AUDIO =
AppProtoEnums.APP_OP_RECEIVE_AMBIENT_TRIGGER_AUDIO;
/** @hide */ /** @hide */
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public static final int _NUM_OP = 120; public static final int _NUM_OP = 121;
/** Access to coarse location information. */ /** Access to coarse location information. */
public static final String OPSTR_COARSE_LOCATION = "android:coarse_location"; public static final String OPSTR_COARSE_LOCATION = "android:coarse_location";
@@ -1800,6 +1808,14 @@ public class AppOpsManager {
public static final String OPSTR_ACCESS_RESTRICTED_SETTINGS = public static final String OPSTR_ACCESS_RESTRICTED_SETTINGS =
"android:access_restricted_settings"; "android:access_restricted_settings";
/**
* Receive microphone audio from an ambient sound detection event
*
* @hide
*/
public static final String OPSTR_RECEIVE_AMBIENT_TRIGGER_AUDIO =
"android:receive_ambient_trigger_audio";
/** {@link #sAppOpsToNote} not initialized yet for this op */ /** {@link #sAppOpsToNote} not initialized yet for this op */
private static final byte SHOULD_COLLECT_NOTE_OP_NOT_INITIALIZED = 0; private static final byte SHOULD_COLLECT_NOTE_OP_NOT_INITIALIZED = 0;
/** Should not collect noting of this app-op in {@link #sAppOpsToNote} */ /** Should not collect noting of this app-op in {@link #sAppOpsToNote} */
@@ -2021,6 +2037,7 @@ public class AppOpsManager {
OP_ESTABLISH_VPN_SERVICE, // OP_ESTABLISH_VPN_SERVICE OP_ESTABLISH_VPN_SERVICE, // OP_ESTABLISH_VPN_SERVICE
OP_ESTABLISH_VPN_MANAGER, // OP_ESTABLISH_VPN_MANAGER OP_ESTABLISH_VPN_MANAGER, // OP_ESTABLISH_VPN_MANAGER
OP_ACCESS_RESTRICTED_SETTINGS, // OP_ACCESS_RESTRICTED_SETTINGS OP_ACCESS_RESTRICTED_SETTINGS, // OP_ACCESS_RESTRICTED_SETTINGS
OP_RECEIVE_AMBIENT_TRIGGER_AUDIO, // RECEIVE_SOUNDTRIGGER_AUDIO
}; };
/** /**
@@ -2147,6 +2164,7 @@ public class AppOpsManager {
OPSTR_ESTABLISH_VPN_SERVICE, OPSTR_ESTABLISH_VPN_SERVICE,
OPSTR_ESTABLISH_VPN_MANAGER, OPSTR_ESTABLISH_VPN_MANAGER,
OPSTR_ACCESS_RESTRICTED_SETTINGS, OPSTR_ACCESS_RESTRICTED_SETTINGS,
OPSTR_RECEIVE_AMBIENT_TRIGGER_AUDIO,
}; };
/** /**
@@ -2274,6 +2292,7 @@ public class AppOpsManager {
"ESTABLISH_VPN_SERVICE", "ESTABLISH_VPN_SERVICE",
"ESTABLISH_VPN_MANAGER", "ESTABLISH_VPN_MANAGER",
"ACCESS_RESTRICTED_SETTINGS", "ACCESS_RESTRICTED_SETTINGS",
"RECEIVE_SOUNDTRIGGER_AUDIO",
}; };
/** /**
@@ -2402,6 +2421,7 @@ public class AppOpsManager {
null, // no permission for OP_ESTABLISH_VPN_SERVICE null, // no permission for OP_ESTABLISH_VPN_SERVICE
null, // no permission for OP_ESTABLISH_VPN_MANAGER null, // no permission for OP_ESTABLISH_VPN_MANAGER
null, // no permission for OP_ACCESS_RESTRICTED_SETTINGS, null, // no permission for OP_ACCESS_RESTRICTED_SETTINGS,
null, // no permission for OP_RECEIVE_SOUNDTRIGGER_AUDIO
}; };
/** /**
@@ -2529,7 +2549,8 @@ public class AppOpsManager {
null, // NEARBY_WIFI_DEVICES null, // NEARBY_WIFI_DEVICES
null, // ESTABLISH_VPN_SERVICE null, // ESTABLISH_VPN_SERVICE
null, // ESTABLISH_VPN_MANAGER null, // ESTABLISH_VPN_MANAGER
null, // ACCESS_RESTRICTED_SETTINGS, null, // ACCESS_RESTRICTED_SETTINGS
null, // RECEIVE_SOUNDTRIGGER_AUDIO
}; };
/** /**
@@ -2656,7 +2677,8 @@ public class AppOpsManager {
null, // NEARBY_WIFI_DEVICES null, // NEARBY_WIFI_DEVICES
null, // ESTABLISH_VPN_SERVICE null, // ESTABLISH_VPN_SERVICE
null, // ESTABLISH_VPN_MANAGER null, // ESTABLISH_VPN_MANAGER
null, // ACCESS_RESTRICTED_SETTINGS, null, // ACCESS_RESTRICTED_SETTINGS
null, // RECEIVE_SOUNDTRIGGER_AUDIO
}; };
/** /**
@@ -2765,7 +2787,7 @@ public class AppOpsManager {
AppOpsManager.MODE_ERRORED, // OP_NO_ISOLATED_STORAGE AppOpsManager.MODE_ERRORED, // OP_NO_ISOLATED_STORAGE
AppOpsManager.MODE_ALLOWED, // PHONE_CALL_MICROPHONE AppOpsManager.MODE_ALLOWED, // PHONE_CALL_MICROPHONE
AppOpsManager.MODE_ALLOWED, // PHONE_CALL_CAMERA AppOpsManager.MODE_ALLOWED, // PHONE_CALL_CAMERA
AppOpsManager.MODE_ALLOWED, // OP_RECORD_AUDIO_HOTWORD AppOpsManager.MODE_ALLOWED, // RECORD_AUDIO_HOTWORD
AppOpsManager.MODE_DEFAULT, // MANAGE_ONGOING_CALLS AppOpsManager.MODE_DEFAULT, // MANAGE_ONGOING_CALLS
AppOpsManager.MODE_DEFAULT, // MANAGE_CREDENTIALS AppOpsManager.MODE_DEFAULT, // MANAGE_CREDENTIALS
AppOpsManager.MODE_DEFAULT, // USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER AppOpsManager.MODE_DEFAULT, // USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER
@@ -2783,6 +2805,7 @@ public class AppOpsManager {
AppOpsManager.MODE_ALLOWED, // ESTABLISH_VPN_SERVICE AppOpsManager.MODE_ALLOWED, // ESTABLISH_VPN_SERVICE
AppOpsManager.MODE_ALLOWED, // ESTABLISH_VPN_MANAGER AppOpsManager.MODE_ALLOWED, // ESTABLISH_VPN_MANAGER
AppOpsManager.MODE_ALLOWED, // ACCESS_RESTRICTED_SETTINGS, AppOpsManager.MODE_ALLOWED, // ACCESS_RESTRICTED_SETTINGS,
AppOpsManager.MODE_ALLOWED, // RECEIVE_SOUNDTRIGGER_AUDIO
}; };
/** /**
@@ -2913,6 +2936,7 @@ public class AppOpsManager {
false, // OP_ESTABLISH_VPN_SERVICE false, // OP_ESTABLISH_VPN_SERVICE
false, // OP_ESTABLISH_VPN_MANAGER false, // OP_ESTABLISH_VPN_MANAGER
true, // ACCESS_RESTRICTED_SETTINGS true, // ACCESS_RESTRICTED_SETTINGS
false, // RECEIVE_SOUNDTRIGGER_AUDIO
}; };
/** /**
@@ -3040,6 +3064,7 @@ public class AppOpsManager {
false, // OP_ESTABLISH_VPN_SERVICE false, // OP_ESTABLISH_VPN_SERVICE
false, // OP_ESTABLISH_VPN_MANAGER false, // OP_ESTABLISH_VPN_MANAGER
true, // ACCESS_RESTRICTED_SETTINGS true, // ACCESS_RESTRICTED_SETTINGS
false, // RECEIVE_SOUNDTRIGGER_AUDIO
}; };
/** /**

View File

@@ -30,6 +30,7 @@ import static android.app.AppOpsManager.OPSTR_COARSE_LOCATION;
import static android.app.AppOpsManager.OPSTR_FINE_LOCATION; import static android.app.AppOpsManager.OPSTR_FINE_LOCATION;
import static android.app.AppOpsManager.OPSTR_PHONE_CALL_CAMERA; import static android.app.AppOpsManager.OPSTR_PHONE_CALL_CAMERA;
import static android.app.AppOpsManager.OPSTR_PHONE_CALL_MICROPHONE; import static android.app.AppOpsManager.OPSTR_PHONE_CALL_MICROPHONE;
import static android.app.AppOpsManager.OPSTR_RECEIVE_AMBIENT_TRIGGER_AUDIO;
import static android.app.AppOpsManager.OPSTR_RECORD_AUDIO; import static android.app.AppOpsManager.OPSTR_RECORD_AUDIO;
import static android.app.AppOpsManager.OP_CAMERA; import static android.app.AppOpsManager.OP_CAMERA;
import static android.app.AppOpsManager.OP_FLAGS_ALL_TRUSTED; import static android.app.AppOpsManager.OP_FLAGS_ALL_TRUSTED;
@@ -137,6 +138,7 @@ public class PermissionUsageHelper implements AppOpsManager.OnOpActiveChangedLis
private static final List<String> MIC_OPS = List.of( private static final List<String> MIC_OPS = List.of(
OPSTR_PHONE_CALL_MICROPHONE, OPSTR_PHONE_CALL_MICROPHONE,
OPSTR_RECEIVE_AMBIENT_TRIGGER_AUDIO,
OPSTR_RECORD_AUDIO OPSTR_RECORD_AUDIO
); );
@@ -147,6 +149,7 @@ public class PermissionUsageHelper implements AppOpsManager.OnOpActiveChangedLis
private static @NonNull String getGroupForOp(String op) { private static @NonNull String getGroupForOp(String op) {
switch (op) { switch (op) {
case OPSTR_RECEIVE_AMBIENT_TRIGGER_AUDIO:
case OPSTR_RECORD_AUDIO: case OPSTR_RECORD_AUDIO:
return MICROPHONE; return MICROPHONE;
case OPSTR_CAMERA: case OPSTR_CAMERA:

View File

@@ -102,6 +102,7 @@ public class AppOpsControllerImpl extends BroadcastReceiver implements AppOpsCon
AppOpsManager.OP_PHONE_CALL_CAMERA, AppOpsManager.OP_PHONE_CALL_CAMERA,
AppOpsManager.OP_SYSTEM_ALERT_WINDOW, AppOpsManager.OP_SYSTEM_ALERT_WINDOW,
AppOpsManager.OP_RECORD_AUDIO, AppOpsManager.OP_RECORD_AUDIO,
AppOpsManager.OP_RECEIVE_AMBIENT_TRIGGER_AUDIO,
AppOpsManager.OP_PHONE_CALL_MICROPHONE, AppOpsManager.OP_PHONE_CALL_MICROPHONE,
AppOpsManager.OP_COARSE_LOCATION, AppOpsManager.OP_COARSE_LOCATION,
AppOpsManager.OP_FINE_LOCATION AppOpsManager.OP_FINE_LOCATION
@@ -535,7 +536,8 @@ public class AppOpsControllerImpl extends BroadcastReceiver implements AppOpsCon
} }
private boolean isOpMicrophone(int op) { private boolean isOpMicrophone(int op) {
return op == AppOpsManager.OP_RECORD_AUDIO || op == AppOpsManager.OP_PHONE_CALL_MICROPHONE; return op == AppOpsManager.OP_RECORD_AUDIO || op == AppOpsManager.OP_PHONE_CALL_MICROPHONE
|| op == AppOpsManager.OP_RECEIVE_AMBIENT_TRIGGER_AUDIO;
} }
protected class H extends Handler { protected class H extends Handler {

View File

@@ -58,7 +58,8 @@ class PrivacyItemController @Inject constructor(
internal companion object { internal companion object {
val OPS_MIC_CAMERA = intArrayOf(AppOpsManager.OP_CAMERA, val OPS_MIC_CAMERA = intArrayOf(AppOpsManager.OP_CAMERA,
AppOpsManager.OP_PHONE_CALL_CAMERA, AppOpsManager.OP_RECORD_AUDIO, AppOpsManager.OP_PHONE_CALL_CAMERA, AppOpsManager.OP_RECORD_AUDIO,
AppOpsManager.OP_PHONE_CALL_MICROPHONE) AppOpsManager.OP_PHONE_CALL_MICROPHONE,
AppOpsManager.OP_RECEIVE_AMBIENT_TRIGGER_AUDIO)
val OPS_LOCATION = intArrayOf( val OPS_LOCATION = intArrayOf(
AppOpsManager.OP_COARSE_LOCATION, AppOpsManager.OP_COARSE_LOCATION,
AppOpsManager.OP_FINE_LOCATION) AppOpsManager.OP_FINE_LOCATION)
@@ -315,6 +316,7 @@ class PrivacyItemController @Inject constructor(
AppOpsManager.OP_COARSE_LOCATION, AppOpsManager.OP_COARSE_LOCATION,
AppOpsManager.OP_FINE_LOCATION -> PrivacyType.TYPE_LOCATION AppOpsManager.OP_FINE_LOCATION -> PrivacyType.TYPE_LOCATION
AppOpsManager.OP_PHONE_CALL_MICROPHONE, AppOpsManager.OP_PHONE_CALL_MICROPHONE,
AppOpsManager.OP_RECEIVE_AMBIENT_TRIGGER_AUDIO,
AppOpsManager.OP_RECORD_AUDIO -> PrivacyType.TYPE_MICROPHONE AppOpsManager.OP_RECORD_AUDIO -> PrivacyType.TYPE_MICROPHONE
else -> return null else -> return null
} }

View File

@@ -43,6 +43,7 @@ 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;
import static android.app.AppOpsManager.OP_NONE; import static android.app.AppOpsManager.OP_NONE;
import static android.app.AppOpsManager.OP_PLAY_AUDIO; 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;
import static android.app.AppOpsManager.OP_RECORD_AUDIO_HOTWORD; import static android.app.AppOpsManager.OP_RECORD_AUDIO_HOTWORD;
import static android.app.AppOpsManager.OnOpStartedListener.START_TYPE_FAILED; import static android.app.AppOpsManager.OnOpStartedListener.START_TYPE_FAILED;
@@ -3848,7 +3849,7 @@ public class AppOpsService extends IAppOpsService.Stub {
// the data gated by OP_RECORD_AUDIO. // 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) { if (code == OP_RECORD_AUDIO_HOTWORD || code == OP_RECEIVE_AMBIENT_TRIGGER_AUDIO) {
int result = checkOperation(OP_RECORD_AUDIO, uid, packageName); int result = checkOperation(OP_RECORD_AUDIO, uid, packageName);
if (result != AppOpsManager.MODE_ALLOWED) { if (result != AppOpsManager.MODE_ALLOWED) {
return new SyncNotedAppOp(result, code, attributionTag, packageName); return new SyncNotedAppOp(result, code, attributionTag, packageName);

View File

@@ -34,6 +34,7 @@ import static android.app.AppOpsManager.OP_FLAG_TRUSTED_PROXY;
import static android.app.AppOpsManager.OP_NONE; import static android.app.AppOpsManager.OP_NONE;
import static android.app.AppOpsManager.OP_PHONE_CALL_CAMERA; import static android.app.AppOpsManager.OP_PHONE_CALL_CAMERA;
import static android.app.AppOpsManager.OP_PHONE_CALL_MICROPHONE; import static android.app.AppOpsManager.OP_PHONE_CALL_MICROPHONE;
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.flagsToString; import static android.app.AppOpsManager.flagsToString;
import static android.app.AppOpsManager.getUidStateName; import static android.app.AppOpsManager.getUidStateName;
@@ -133,7 +134,7 @@ final class DiscreteRegistry {
private static final String PROPERTY_DISCRETE_OPS_LIST = "discrete_history_ops_cslist"; private static final String PROPERTY_DISCRETE_OPS_LIST = "discrete_history_ops_cslist";
private static final String DEFAULT_DISCRETE_OPS = OP_FINE_LOCATION + "," + OP_COARSE_LOCATION private static final String DEFAULT_DISCRETE_OPS = OP_FINE_LOCATION + "," + OP_COARSE_LOCATION
+ "," + OP_CAMERA + "," + OP_RECORD_AUDIO + "," + OP_PHONE_CALL_MICROPHONE + "," + "," + OP_CAMERA + "," + OP_RECORD_AUDIO + "," + OP_PHONE_CALL_MICROPHONE + ","
+ OP_PHONE_CALL_CAMERA; + OP_PHONE_CALL_CAMERA + "," + OP_RECEIVE_AMBIENT_TRIGGER_AUDIO;
private static final long DEFAULT_DISCRETE_HISTORY_CUTOFF = Duration.ofDays(7).toMillis(); private static final long DEFAULT_DISCRETE_HISTORY_CUTOFF = Duration.ofDays(7).toMillis();
private static final long MAXIMUM_DISCRETE_HISTORY_CUTOFF = Duration.ofDays(30).toMillis(); private static final long MAXIMUM_DISCRETE_HISTORY_CUTOFF = Duration.ofDays(30).toMillis();
private static final long DEFAULT_DISCRETE_HISTORY_QUANTIZATION = private static final long DEFAULT_DISCRETE_HISTORY_QUANTIZATION =

View File

@@ -17,6 +17,7 @@
package com.android.server.pm.permission; package com.android.server.pm.permission;
import android.annotation.NonNull; import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt; import android.annotation.UserIdInt;
/** /**
@@ -104,6 +105,20 @@ public interface LegacyPermissionManagerInternal {
*/ */
void scheduleReadDefaultPermissionExceptions(); void scheduleReadDefaultPermissionExceptions();
/**
* Check whether a particular package should have access to the microphone data from the
* SoundTrigger.
*
* @param uid the uid of the package you are checking against
* @param packageName the name of the package you are checking against
* @param attributionTag the attributionTag to attach to the app op transaction
* @param reason the reason to attach to the app op transaction
* @return {@code PERMISSION_GRANTED} if the permission is granted,
* or {@code PERMISSION_SOFT/HARD DENIED otherwise
*/
int checkSoundTriggerRecordAudioPermissionForDataDelivery(int uid,
@NonNull String packageName, @Nullable String attributionTag, @NonNull String reason);
/** /**
* Provider for package names. * Provider for package names.
*/ */

View File

@@ -16,12 +16,15 @@
package com.android.server.pm.permission; package com.android.server.pm.permission;
import static android.Manifest.permission.RECORD_AUDIO;
import android.annotation.NonNull; import android.annotation.NonNull;
import android.annotation.Nullable; import android.annotation.Nullable;
import android.annotation.UserIdInt; import android.annotation.UserIdInt;
import android.app.AppOpsManager; import android.app.AppOpsManager;
import android.app.admin.DevicePolicyManager; import android.app.admin.DevicePolicyManager;
import android.content.Context; import android.content.Context;
import android.content.PermissionChecker;
import android.content.pm.ApplicationInfo; import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal; import android.content.pm.PackageManagerInternal;
@@ -399,6 +402,21 @@ public class LegacyPermissionManagerService extends ILegacyPermissionManager.Stu
public void scheduleReadDefaultPermissionExceptions() { public void scheduleReadDefaultPermissionExceptions() {
mDefaultPermissionGrantPolicy.scheduleReadDefaultPermissionExceptions(); mDefaultPermissionGrantPolicy.scheduleReadDefaultPermissionExceptions();
} }
@Override
public int checkSoundTriggerRecordAudioPermissionForDataDelivery(int uid,
@NonNull String packageName, @Nullable String attributionTag,
@NonNull String reason) {
int result = PermissionChecker.checkPermissionForPreflight(mContext, RECORD_AUDIO, -1,
uid, packageName);
if (result != PermissionChecker.PERMISSION_GRANTED) {
return result;
}
mContext.getSystemService(AppOpsManager.class).noteOpNoThrow(
AppOpsManager.OP_RECEIVE_AMBIENT_TRIGGER_AUDIO, uid, packageName,
attributionTag, reason);
return result;
}
} }
/** /**

View File

@@ -87,8 +87,8 @@ public final class AppOpsPolicy implements AppOpsManagerInternal.CheckOpsDelegat
private final VoiceInteractionManagerInternal mVoiceInteractionManagerInternal; private final VoiceInteractionManagerInternal mVoiceInteractionManagerInternal;
/** /**
* Whether this device allows only the HotwordDetectionService to use OP_RECORD_AUDIO_HOTWORD * Whether this device allows only the HotwordDetectionService to use
* which doesn't incur the privacy indicator. * OP_RECORD_AUDIO_HOTWORD which doesn't incur the privacy indicator.
*/ */
private final boolean mIsHotwordDetectionServiceRequired; private final boolean mIsHotwordDetectionServiceRequired;
@@ -427,8 +427,8 @@ public final class AppOpsPolicy implements AppOpsManagerInternal.CheckOpsDelegat
if (!mIsHotwordDetectionServiceRequired) { if (!mIsHotwordDetectionServiceRequired) {
return code; return code;
} }
// Only the HotwordDetectionService can use the HOTWORD op which doesn't incur the // Only the HotwordDetectionService can use the RECORD_AUDIO_HOTWORD op which doesn't
// privacy indicator. Downgrade to standard RECORD_AUDIO for other processes. // incur the privacy indicator. Downgrade to standard RECORD_AUDIO for other processes.
final HotwordDetectionServiceIdentity hotwordDetectionServiceIdentity = final HotwordDetectionServiceIdentity hotwordDetectionServiceIdentity =
mVoiceInteractionManagerInternal.getHotwordDetectionServiceIdentity(); mVoiceInteractionManagerInternal.getHotwordDetectionServiceIdentity();
if (hotwordDetectionServiceIdentity != null if (hotwordDetectionServiceIdentity != null

View File

@@ -25,6 +25,7 @@ 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_PHONE_CALL_CAMERA; import static android.app.AppOpsManager.OP_PHONE_CALL_CAMERA;
import static android.app.AppOpsManager.OP_PHONE_CALL_MICROPHONE; import static android.app.AppOpsManager.OP_PHONE_CALL_MICROPHONE;
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.content.Intent.EXTRA_PACKAGE_NAME; import static android.content.Intent.EXTRA_PACKAGE_NAME;
import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS; import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
@@ -1067,6 +1068,10 @@ public final class SensorPrivacyService extends SystemService {
mAppOpsRestrictionToken); mAppOpsRestrictionToken);
mAppOpsManagerInternal.setGlobalRestriction(OP_PHONE_CALL_MICROPHONE, enabled, mAppOpsManagerInternal.setGlobalRestriction(OP_PHONE_CALL_MICROPHONE, enabled,
mAppOpsRestrictionToken); mAppOpsRestrictionToken);
// We don't show the dialog for RECEIVE_SOUNDTRIGGER_AUDIO, but still want to
// restrict it when the microphone is disabled
mAppOpsManagerInternal.setGlobalRestriction(OP_RECEIVE_AMBIENT_TRIGGER_AUDIO,
enabled, mAppOpsRestrictionToken);
break; break;
case CAMERA: case CAMERA:
mAppOpsManagerInternal.setGlobalRestriction(OP_CAMERA, enabled, mAppOpsManagerInternal.setGlobalRestriction(OP_CAMERA, enabled,

View File

@@ -42,6 +42,9 @@ import android.os.IBinder;
import android.os.RemoteException; import android.os.RemoteException;
import android.os.ServiceSpecificException; import android.os.ServiceSpecificException;
import com.android.server.LocalServices;
import com.android.server.pm.permission.LegacyPermissionManagerInternal;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.util.Objects; import java.util.Objects;
@@ -123,19 +126,8 @@ public class SoundTriggerMiddlewarePermission implements ISoundTriggerMiddleware
* Throws a {@link SecurityException} iff the originator has permission to receive data. * Throws a {@link SecurityException} iff the originator has permission to receive data.
*/ */
void enforcePermissionsForDataDelivery(@NonNull Identity identity, @NonNull String reason) { void enforcePermissionsForDataDelivery(@NonNull Identity identity, @NonNull String reason) {
// SoundTrigger data is treated the same as Hotword-source audio. This should incur the enforceSoundTriggerRecordAudioPermissionForDataDelivery(identity, reason);
// HOTWORD op instead of the RECORD_AUDIO op. The RECORD_AUDIO permission is still required, enforcePermissionForDataDelivery(mContext, identity, CAPTURE_AUDIO_HOTWORD, reason);
// and since this is a data delivery check, soft denials aren't accepted.
// TODO(b/212458940): Find a better approach for checking the permission that doesn't
// require the client to know such details about the permissions logic.
enforcePermissionForPreflight(mContext, identity, RECORD_AUDIO,
/* allowSoftDenial= */ false);
int hotwordOp = AppOpsManager.strOpToOp(AppOpsManager.OPSTR_RECORD_AUDIO_HOTWORD);
mContext.getSystemService(AppOpsManager.class).noteOpNoThrow(hotwordOp, identity.uid,
identity.packageName, identity.attributionTag, reason);
enforcePermissionForDataDelivery(mContext, identity, CAPTURE_AUDIO_HOTWORD,
reason);
} }
/** /**
@@ -159,6 +151,19 @@ public class SoundTriggerMiddlewarePermission implements ISoundTriggerMiddleware
} }
} }
private static void enforceSoundTriggerRecordAudioPermissionForDataDelivery(
@NonNull Identity identity, @NonNull String reason) {
LegacyPermissionManagerInternal lpmi =
LocalServices.getService(LegacyPermissionManagerInternal.class);
final int status = lpmi.checkSoundTriggerRecordAudioPermissionForDataDelivery(identity.uid,
identity.packageName, identity.attributionTag, reason);
if (status != PermissionChecker.PERMISSION_GRANTED) {
throw new SecurityException(
String.format("Failed to obtain permission RECORD_AUDIO for identity %s",
ObjectPrinter.print(identity, 16)));
}
}
/** /**
* Throws a {@link SecurityException} if originator permanently doesn't have the given * Throws a {@link SecurityException} if originator permanently doesn't have the given
* permission. * permission.