Merge "Inform Assistant when security exception occurs during onDetected"
diff --git a/core/java/android/service/voice/AbstractHotwordDetector.java b/core/java/android/service/voice/AbstractHotwordDetector.java
index 5b3b78b..84d6711 100644
--- a/core/java/android/service/voice/AbstractHotwordDetector.java
+++ b/core/java/android/service/voice/AbstractHotwordDetector.java
@@ -204,5 +204,14 @@
.setHotwordDetectedResult(hotwordDetectedResult)
.build()));
}
+
+ /** Called when the detection fails due to an error. */
+ @Override
+ public void onError() {
+ Slog.v(TAG, "BinderCallback#onError");
+ mHandler.sendMessage(obtainMessage(
+ HotwordDetector.Callback::onError,
+ mCallback));
+ }
}
}
diff --git a/core/java/android/service/voice/IMicrophoneHotwordDetectionVoiceInteractionCallback.aidl b/core/java/android/service/voice/IMicrophoneHotwordDetectionVoiceInteractionCallback.aidl
index 80f20fe..e865089 100644
--- a/core/java/android/service/voice/IMicrophoneHotwordDetectionVoiceInteractionCallback.aidl
+++ b/core/java/android/service/voice/IMicrophoneHotwordDetectionVoiceInteractionCallback.aidl
@@ -33,4 +33,9 @@
in HotwordDetectedResult hotwordDetectedResult,
in AudioFormat audioFormat,
in ParcelFileDescriptor audioStream);
+
+ /**
+ * Called when the detection fails due to an error.
+ */
+ void onError();
}
diff --git a/core/java/android/service/voice/SoftwareHotwordDetector.java b/core/java/android/service/voice/SoftwareHotwordDetector.java
index 36ea91e..6600fb7 100644
--- a/core/java/android/service/voice/SoftwareHotwordDetector.java
+++ b/core/java/android/service/voice/SoftwareHotwordDetector.java
@@ -166,6 +166,15 @@
.setHotwordDetectedResult(hotwordDetectedResult)
.build()));
}
+
+ /** Called when the detection fails due to an error. */
+ @Override
+ public void onError() {
+ Slog.v(TAG, "BinderCallback#onError");
+ mHandler.sendMessage(obtainMessage(
+ HotwordDetector.Callback::onError,
+ mCallback));
+ }
}
private static class InitializationStateListener
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
index 99fcbc7..f5b5e1a 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
@@ -125,6 +125,10 @@
private static final long RESET_DEBUG_HOTWORD_LOGGING_TIMEOUT_MILLIS = 60 * 60 * 1000; // 1 hour
private static final int MAX_ISOLATED_PROCESS_NUMBER = 10;
+ // The error codes are used for onError callback
+ private static final int HOTWORD_DETECTION_SERVICE_DIED = -1;
+ private static final int CALLBACK_ONDETECTED_GOT_SECURITY_EXCEPTION = -2;
+
// Hotword metrics
private static final int METRICS_INIT_UNKNOWN_TIMEOUT =
HOTWORD_DETECTION_SERVICE_INIT_RESULT_REPORTED__RESULT__CALLBACK_INIT_STATE_UNKNOWN_TIMEOUT;
@@ -421,19 +425,24 @@
Slog.d(TAG, "onDetected");
}
synchronized (mLock) {
- if (mPerformingSoftwareHotwordDetection) {
- enforcePermissionsForDataDelivery();
- mSoftwareCallback.onDetected(result, null, null);
- mPerformingSoftwareHotwordDetection = false;
- if (result != null) {
- Slog.i(TAG, "Egressed " + HotwordDetectedResult.getUsageSize(result)
- + " bits from hotword trusted process");
- if (mDebugHotwordLogging) {
- Slog.i(TAG, "Egressed detected result: " + result);
- }
- }
- } else {
+ if (!mPerformingSoftwareHotwordDetection) {
Slog.i(TAG, "Hotword detection has already completed");
+ return;
+ }
+ mPerformingSoftwareHotwordDetection = false;
+ try {
+ enforcePermissionsForDataDelivery();
+ } catch (SecurityException e) {
+ mSoftwareCallback.onError();
+ return;
+ }
+ mSoftwareCallback.onDetected(result, null, null);
+ if (result != null) {
+ Slog.i(TAG, "Egressed " + HotwordDetectedResult.getUsageSize(result)
+ + " bits from hotword trusted process");
+ if (mDebugHotwordLogging) {
+ Slog.i(TAG, "Egressed detected result: " + result);
+ }
}
}
}
@@ -514,20 +523,25 @@
public void onDetected(HotwordDetectedResult result) throws RemoteException {
Slog.v(TAG, "onDetected");
synchronized (mLock) {
- if (mValidatingDspTrigger) {
- mValidatingDspTrigger = false;
+ if (!mValidatingDspTrigger) {
+ Slog.i(TAG, "Ignored hotword detected since trigger has been handled");
+ return;
+ }
+ mValidatingDspTrigger = false;
+ try {
enforcePermissionsForDataDelivery();
enforceExtraKeyphraseIdNotLeaked(result, recognitionEvent);
- externalCallback.onKeyphraseDetected(recognitionEvent, result);
- if (result != null) {
- Slog.i(TAG, "Egressed " + HotwordDetectedResult.getUsageSize(result)
- + " bits from hotword trusted process");
- if (mDebugHotwordLogging) {
- Slog.i(TAG, "Egressed detected result: " + result);
- }
+ } catch (SecurityException e) {
+ externalCallback.onError(CALLBACK_ONDETECTED_GOT_SECURITY_EXCEPTION);
+ return;
+ }
+ externalCallback.onKeyphraseDetected(recognitionEvent, result);
+ if (result != null) {
+ Slog.i(TAG, "Egressed " + HotwordDetectedResult.getUsageSize(result)
+ + " bits from hotword trusted process");
+ if (mDebugHotwordLogging) {
+ Slog.i(TAG, "Egressed detected result: " + result);
}
- } else {
- Slog.i(TAG, "Ignored hotword detected since trigger has been handled");
}
}
}
@@ -598,7 +612,8 @@
HotwordMetricsLogger.writeKeyphraseTriggerEvent(
mDetectorType,
METRICS_KEYPHRASE_TRIGGERED_DETECT_SECURITY_EXCEPTION);
- throw e;
+ externalCallback.onError(CALLBACK_ONDETECTED_GOT_SECURITY_EXCEPTION);
+ return;
}
externalCallback.onKeyphraseDetected(recognitionEvent, result);
if (result != null) {
@@ -888,7 +903,13 @@
throws RemoteException {
bestEffortClose(serviceAudioSink);
bestEffortClose(serviceAudioSource);
- enforcePermissionsForDataDelivery();
+ try {
+ enforcePermissionsForDataDelivery();
+ } catch (SecurityException e) {
+ bestEffortClose(audioSource);
+ callback.onError();
+ return;
+ }
callback.onDetected(triggerResult, null /* audioFormat */,
null /* audioStream */);
if (triggerResult != null) {
@@ -988,7 +1009,7 @@
Slog.w(TAG, "binderDied");
try {
- mCallback.onError(-1);
+ mCallback.onError(HOTWORD_DETECTION_SERVICE_DIED);
} catch (RemoteException e) {
Slog.w(TAG, "Failed to report onError status: " + e);
}