summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTreeHugger Robot <treehugger-gerrit@google.com>2022-09-07 03:10:24 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2022-09-07 03:10:24 +0000
commitcef7f19369d1897f3466c8164ac820d1fda4f925 (patch)
treeddfdca0524e49a496cd27f6e7187fe355dd35b7c
parent380ec03dee699c138d16fb734d56ab19ad581bf8 (diff)
parente4e77f45700bcbc56aa6d6ffc094e0e0ae78190a (diff)
downloadbase-cef7f19369d1897f3466c8164ac820d1fda4f925.tar.gz
Merge "[RESTRICT AUTOMERGE] Check permission for VoiceInteraction" into qt-dev
-rw-r--r--core/java/android/service/voice/AlwaysOnHotwordDetector.java40
-rw-r--r--core/java/android/service/voice/VoiceInteractionService.java2
-rw-r--r--services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java14
3 files changed, 53 insertions, 3 deletions
diff --git a/core/java/android/service/voice/AlwaysOnHotwordDetector.java b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
index bd953cad2b75..ca250691aa7a 100644
--- a/core/java/android/service/voice/AlwaysOnHotwordDetector.java
+++ b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
@@ -16,12 +16,15 @@
package android.service.voice;
+import android.Manifest;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UnsupportedAppUsage;
import android.app.Activity;
+import android.content.Context;
import android.content.Intent;
+import android.content.pm.PackageManager;
import android.hardware.soundtrigger.IRecognitionStatusCallback;
import android.hardware.soundtrigger.KeyphraseEnrollmentInfo;
import android.hardware.soundtrigger.KeyphraseMetadata;
@@ -195,8 +198,10 @@ public class AlwaysOnHotwordDetector {
private final Callback mExternalCallback;
private final Object mLock = new Object();
private final Handler mHandler;
+ private final Context mContext;
private int mAvailability = STATE_NOT_READY;
+ private boolean mIsGrantedHotwordPermission;
/**
* Additional payload for {@link Callback#onDetected}.
@@ -324,19 +329,32 @@ public class AlwaysOnHotwordDetector {
public abstract void onRecognitionResumed();
}
+ private static boolean hasHotwordPermission(Context context) {
+ return context.checkSelfPermission(Manifest.permission.CAPTURE_AUDIO_HOTWORD)
+ == PackageManager.PERMISSION_GRANTED;
+ }
+
+ private static boolean hasRecordAudioPermission(Context context) {
+ return context.checkSelfPermission(Manifest.permission.RECORD_AUDIO)
+ == PackageManager.PERMISSION_GRANTED;
+ }
+
/**
+ * @param context The context to check permission
* @param text The keyphrase text to get the detector for.
* @param locale The java locale for the detector.
* @param callback A non-null Callback for receiving the recognition events.
+ * @param keyphraseEnrollmentInfo The Enrollment info of key phrase
* @param voiceInteractionService The current voice interaction service.
* @param modelManagementService A service that allows management of sound models.
*
* @hide
*/
- public AlwaysOnHotwordDetector(String text, Locale locale, Callback callback,
+ public AlwaysOnHotwordDetector(Context context, String text, Locale locale, Callback callback,
KeyphraseEnrollmentInfo keyphraseEnrollmentInfo,
IVoiceInteractionService voiceInteractionService,
IVoiceInteractionManagerService modelManagementService) {
+ mContext = context;
mText = text;
mLocale = locale;
mKeyphraseEnrollmentInfo = keyphraseEnrollmentInfo;
@@ -346,6 +364,7 @@ public class AlwaysOnHotwordDetector {
mInternalCallback = new SoundTriggerListener(mHandler);
mVoiceInteractionService = voiceInteractionService;
mModelManagementService = modelManagementService;
+ mIsGrantedHotwordPermission = hasHotwordPermission(mContext);
new RefreshAvailabiltyTask().execute();
}
@@ -402,6 +421,12 @@ public class AlwaysOnHotwordDetector {
*/
public boolean startRecognition(@RecognitionFlags int recognitionFlags) {
if (DBG) Slog.d(TAG, "startRecognition(" + recognitionFlags + ")");
+
+ if (!mIsGrantedHotwordPermission || !hasRecordAudioPermission(mContext)) {
+ throw new IllegalStateException("Must have the RECORD_AUDIO and CAPTURE_AUDIO_HOTWORD "
+ + "permissions to access the detector.");
+ }
+
synchronized (mLock) {
if (mAvailability == STATE_INVALID) {
throw new IllegalStateException("startRecognition called on an invalid detector");
@@ -430,6 +455,12 @@ public class AlwaysOnHotwordDetector {
*/
public boolean stopRecognition() {
if (DBG) Slog.d(TAG, "stopRecognition()");
+
+ if (!mIsGrantedHotwordPermission || !hasRecordAudioPermission(mContext)) {
+ throw new IllegalStateException("Must have the RECORD_AUDIO and CAPTURE_AUDIO_HOTWORD "
+ + "permissions to access the detector.");
+ }
+
synchronized (mLock) {
if (mAvailability == STATE_INVALID) {
throw new IllegalStateException("stopRecognition called on an invalid detector");
@@ -546,7 +577,8 @@ public class AlwaysOnHotwordDetector {
synchronized (mLock) {
if (mAvailability == STATE_INVALID
|| mAvailability == STATE_HARDWARE_UNAVAILABLE
- || mAvailability == STATE_KEYPHRASE_UNSUPPORTED) {
+ || mAvailability == STATE_KEYPHRASE_UNSUPPORTED
+ || !hasRecordAudioPermission(mContext)) {
Slog.w(TAG, "Received onSoundModelsChanged for an unsupported keyphrase/config");
return;
}
@@ -717,6 +749,10 @@ public class AlwaysOnHotwordDetector {
* @return The initial availability without checking the enrollment status.
*/
private int internalGetInitialAvailability() {
+ if (!mIsGrantedHotwordPermission) {
+ return STATE_HARDWARE_UNAVAILABLE;
+ }
+
synchronized (mLock) {
// This detector has already been invalidated.
if (mAvailability == STATE_INVALID) {
diff --git a/core/java/android/service/voice/VoiceInteractionService.java b/core/java/android/service/voice/VoiceInteractionService.java
index 0de17ca3b960..3d85ad7935c6 100644
--- a/core/java/android/service/voice/VoiceInteractionService.java
+++ b/core/java/android/service/voice/VoiceInteractionService.java
@@ -297,7 +297,7 @@ public class VoiceInteractionService extends Service {
synchronized (mLock) {
// Allow only one concurrent recognition via the APIs.
safelyShutdownHotwordDetector();
- mHotwordDetector = new AlwaysOnHotwordDetector(keyphrase, locale, callback,
+ mHotwordDetector = new AlwaysOnHotwordDetector(this, keyphrase, locale, callback,
mKeyphraseEnrollmentInfo, mInterface, mSystemService);
}
return mHotwordDetector;
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index e1ffb0f179f8..bd8ba1fa5876 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -956,6 +956,9 @@ public class VoiceInteractionManagerService extends SystemService {
@Override
public ModuleProperties getDspModuleProperties(IVoiceInteractionService service) {
+ // Allow the call if it is granted CAPTURE_AUDIO_HOTWORD.
+ enforceCallingPermission(Manifest.permission.CAPTURE_AUDIO_HOTWORD);
+
// Allow the call if this is the current voice interaction service.
synchronized (this) {
enforceIsCurrentVoiceInteractionService(service);
@@ -973,6 +976,9 @@ public class VoiceInteractionManagerService extends SystemService {
public int startRecognition(IVoiceInteractionService service, int keyphraseId,
String bcp47Locale, IRecognitionStatusCallback callback,
RecognitionConfig recognitionConfig) {
+ // Allow the call if it is granted RECORD_AUDIO and CAPTURE_AUDIO_HOTWORD.
+ enforceAlwaysOnHotwordPermissions();
+
// Allow the call if this is the current voice interaction service.
synchronized (this) {
enforceIsCurrentVoiceInteractionService(service);
@@ -1009,6 +1015,9 @@ public class VoiceInteractionManagerService extends SystemService {
@Override
public int stopRecognition(IVoiceInteractionService service, int keyphraseId,
IRecognitionStatusCallback callback) {
+ // Allow the call if it is granted RECORD_AUDIO and CAPTURE_AUDIO_HOTWORD.
+ enforceAlwaysOnHotwordPermissions();
+
// Allow the call if this is the current voice interaction service.
synchronized (this) {
enforceIsCurrentVoiceInteractionService(service);
@@ -1254,6 +1263,11 @@ public class VoiceInteractionManagerService extends SystemService {
}
}
+ private void enforceAlwaysOnHotwordPermissions() {
+ enforceCallingPermission(Manifest.permission.RECORD_AUDIO);
+ enforceCallingPermission(Manifest.permission.CAPTURE_AUDIO_HOTWORD);
+ }
+
private void enforceCallingPermission(String permission) {
if (mContext.checkCallingOrSelfPermission(permission)
!= PackageManager.PERMISSION_GRANTED) {