Merge "Note RECEIVE_AMBIENT_TRIGGER_AUDIO in the SoundTrigger" into tm-dev
This commit is contained in:
@@ -1335,9 +1335,17 @@ public class AppOpsManager {
|
||||
public static final int 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 */
|
||||
@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. */
|
||||
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 =
|
||||
"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 */
|
||||
private static final byte SHOULD_COLLECT_NOTE_OP_NOT_INITIALIZED = 0;
|
||||
/** 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_MANAGER, // OP_ESTABLISH_VPN_MANAGER
|
||||
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_MANAGER,
|
||||
OPSTR_ACCESS_RESTRICTED_SETTINGS,
|
||||
OPSTR_RECEIVE_AMBIENT_TRIGGER_AUDIO,
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -2274,6 +2292,7 @@ public class AppOpsManager {
|
||||
"ESTABLISH_VPN_SERVICE",
|
||||
"ESTABLISH_VPN_MANAGER",
|
||||
"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_MANAGER
|
||||
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, // ESTABLISH_VPN_SERVICE
|
||||
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, // ESTABLISH_VPN_SERVICE
|
||||
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_ALLOWED, // PHONE_CALL_MICROPHONE
|
||||
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_CREDENTIALS
|
||||
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_MANAGER
|
||||
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_MANAGER
|
||||
true, // ACCESS_RESTRICTED_SETTINGS
|
||||
false, // RECEIVE_SOUNDTRIGGER_AUDIO
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -3040,6 +3064,7 @@ public class AppOpsManager {
|
||||
false, // OP_ESTABLISH_VPN_SERVICE
|
||||
false, // OP_ESTABLISH_VPN_MANAGER
|
||||
true, // ACCESS_RESTRICTED_SETTINGS
|
||||
false, // RECEIVE_SOUNDTRIGGER_AUDIO
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -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_PHONE_CALL_CAMERA;
|
||||
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.OP_CAMERA;
|
||||
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(
|
||||
OPSTR_PHONE_CALL_MICROPHONE,
|
||||
OPSTR_RECEIVE_AMBIENT_TRIGGER_AUDIO,
|
||||
OPSTR_RECORD_AUDIO
|
||||
);
|
||||
|
||||
@@ -147,6 +149,7 @@ public class PermissionUsageHelper implements AppOpsManager.OnOpActiveChangedLis
|
||||
|
||||
private static @NonNull String getGroupForOp(String op) {
|
||||
switch (op) {
|
||||
case OPSTR_RECEIVE_AMBIENT_TRIGGER_AUDIO:
|
||||
case OPSTR_RECORD_AUDIO:
|
||||
return MICROPHONE;
|
||||
case OPSTR_CAMERA:
|
||||
|
||||
@@ -102,6 +102,7 @@ public class AppOpsControllerImpl extends BroadcastReceiver implements AppOpsCon
|
||||
AppOpsManager.OP_PHONE_CALL_CAMERA,
|
||||
AppOpsManager.OP_SYSTEM_ALERT_WINDOW,
|
||||
AppOpsManager.OP_RECORD_AUDIO,
|
||||
AppOpsManager.OP_RECEIVE_AMBIENT_TRIGGER_AUDIO,
|
||||
AppOpsManager.OP_PHONE_CALL_MICROPHONE,
|
||||
AppOpsManager.OP_COARSE_LOCATION,
|
||||
AppOpsManager.OP_FINE_LOCATION
|
||||
@@ -535,7 +536,8 @@ public class AppOpsControllerImpl extends BroadcastReceiver implements AppOpsCon
|
||||
}
|
||||
|
||||
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 {
|
||||
|
||||
@@ -58,7 +58,8 @@ class PrivacyItemController @Inject constructor(
|
||||
internal companion object {
|
||||
val OPS_MIC_CAMERA = intArrayOf(AppOpsManager.OP_CAMERA,
|
||||
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(
|
||||
AppOpsManager.OP_COARSE_LOCATION,
|
||||
AppOpsManager.OP_FINE_LOCATION)
|
||||
@@ -315,6 +316,7 @@ class PrivacyItemController @Inject constructor(
|
||||
AppOpsManager.OP_COARSE_LOCATION,
|
||||
AppOpsManager.OP_FINE_LOCATION -> PrivacyType.TYPE_LOCATION
|
||||
AppOpsManager.OP_PHONE_CALL_MICROPHONE,
|
||||
AppOpsManager.OP_RECEIVE_AMBIENT_TRIGGER_AUDIO,
|
||||
AppOpsManager.OP_RECORD_AUDIO -> PrivacyType.TYPE_MICROPHONE
|
||||
else -> return null
|
||||
}
|
||||
|
||||
@@ -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_NONE;
|
||||
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.OnOpStartedListener.START_TYPE_FAILED;
|
||||
@@ -3849,7 +3850,7 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
// the data gated by OP_RECORD_AUDIO.
|
||||
//
|
||||
// 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);
|
||||
if (result != AppOpsManager.MODE_ALLOWED) {
|
||||
return new SyncNotedAppOp(result, code, attributionTag, packageName);
|
||||
|
||||
@@ -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_PHONE_CALL_CAMERA;
|
||||
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.flagsToString;
|
||||
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 DEFAULT_DISCRETE_OPS = OP_FINE_LOCATION + "," + OP_COARSE_LOCATION
|
||||
+ "," + 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 MAXIMUM_DISCRETE_HISTORY_CUTOFF = Duration.ofDays(30).toMillis();
|
||||
private static final long DEFAULT_DISCRETE_HISTORY_QUANTIZATION =
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.android.server.pm.permission;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.UserIdInt;
|
||||
|
||||
/**
|
||||
@@ -104,6 +105,20 @@ public interface LegacyPermissionManagerInternal {
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
|
||||
@@ -16,12 +16,15 @@
|
||||
|
||||
package com.android.server.pm.permission;
|
||||
|
||||
import static android.Manifest.permission.RECORD_AUDIO;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.UserIdInt;
|
||||
import android.app.AppOpsManager;
|
||||
import android.app.admin.DevicePolicyManager;
|
||||
import android.content.Context;
|
||||
import android.content.PermissionChecker;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.PackageManagerInternal;
|
||||
@@ -399,6 +402,21 @@ public class LegacyPermissionManagerService extends ILegacyPermissionManager.Stu
|
||||
public void 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;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -87,8 +87,8 @@ public final class AppOpsPolicy implements AppOpsManagerInternal.CheckOpsDelegat
|
||||
private final VoiceInteractionManagerInternal mVoiceInteractionManagerInternal;
|
||||
|
||||
/**
|
||||
* Whether this device allows only the HotwordDetectionService to use OP_RECORD_AUDIO_HOTWORD
|
||||
* which doesn't incur the privacy indicator.
|
||||
* Whether this device allows only the HotwordDetectionService to use
|
||||
* OP_RECORD_AUDIO_HOTWORD which doesn't incur the privacy indicator.
|
||||
*/
|
||||
private final boolean mIsHotwordDetectionServiceRequired;
|
||||
|
||||
@@ -428,8 +428,8 @@ public final class AppOpsPolicy implements AppOpsManagerInternal.CheckOpsDelegat
|
||||
if (!mIsHotwordDetectionServiceRequired) {
|
||||
return code;
|
||||
}
|
||||
// Only the HotwordDetectionService can use the HOTWORD op which doesn't incur the
|
||||
// privacy indicator. Downgrade to standard RECORD_AUDIO for other processes.
|
||||
// Only the HotwordDetectionService can use the RECORD_AUDIO_HOTWORD op which doesn't
|
||||
// incur the privacy indicator. Downgrade to standard RECORD_AUDIO for other processes.
|
||||
final HotwordDetectionServiceIdentity hotwordDetectionServiceIdentity =
|
||||
mVoiceInteractionManagerInternal.getHotwordDetectionServiceIdentity();
|
||||
if (hotwordDetectionServiceIdentity != null
|
||||
|
||||
@@ -25,6 +25,7 @@ import static android.app.AppOpsManager.MODE_IGNORED;
|
||||
import static android.app.AppOpsManager.OP_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_RECEIVE_AMBIENT_TRIGGER_AUDIO;
|
||||
import static android.app.AppOpsManager.OP_RECORD_AUDIO;
|
||||
import static android.content.Intent.EXTRA_PACKAGE_NAME;
|
||||
import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
|
||||
@@ -1067,6 +1068,10 @@ public final class SensorPrivacyService extends SystemService {
|
||||
mAppOpsRestrictionToken);
|
||||
mAppOpsManagerInternal.setGlobalRestriction(OP_PHONE_CALL_MICROPHONE, enabled,
|
||||
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;
|
||||
case CAMERA:
|
||||
mAppOpsManagerInternal.setGlobalRestriction(OP_CAMERA, enabled,
|
||||
|
||||
@@ -41,6 +41,9 @@ import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ServiceSpecificException;
|
||||
|
||||
import com.android.server.LocalServices;
|
||||
import com.android.server.pm.permission.LegacyPermissionManagerInternal;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.util.Objects;
|
||||
|
||||
@@ -120,8 +123,7 @@ public class SoundTriggerMiddlewarePermission implements ISoundTriggerMiddleware
|
||||
* Throws a {@link SecurityException} iff the originator has permission to receive data.
|
||||
*/
|
||||
void enforcePermissionsForDataDelivery(@NonNull Identity identity, @NonNull String reason) {
|
||||
enforcePermissionForDataDelivery(mContext, identity, RECORD_AUDIO,
|
||||
reason);
|
||||
enforceSoundTriggerRecordAudioPermissionForDataDelivery(identity, reason);
|
||||
enforcePermissionForDataDelivery(mContext, identity, CAPTURE_AUDIO_HOTWORD,
|
||||
reason);
|
||||
}
|
||||
@@ -147,6 +149,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
|
||||
* permission.
|
||||
|
||||
Reference in New Issue
Block a user