Loading core/java/android/service/voice/AbstractHotwordDetector.java +9 −0 Original line number Diff line number Diff line Loading @@ -189,5 +189,14 @@ abstract class AbstractHotwordDetector implements HotwordDetector { .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)); } } } core/java/android/service/voice/IMicrophoneHotwordDetectionVoiceInteractionCallback.aidl +5 −0 Original line number Diff line number Diff line Loading @@ -33,4 +33,9 @@ oneway interface IMicrophoneHotwordDetectionVoiceInteractionCallback { in HotwordDetectedResult hotwordDetectedResult, in AudioFormat audioFormat, in ParcelFileDescriptor audioStream); /** * Called when the detection fails due to an error. */ void onError(); } core/java/android/service/voice/SoftwareHotwordDetector.java +9 −0 Original line number Diff line number Diff line Loading @@ -155,6 +155,15 @@ class SoftwareHotwordDetector extends AbstractHotwordDetector { .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 Loading services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java +46 −25 Original line number Diff line number Diff line Loading @@ -124,6 +124,10 @@ final class HotwordDetectionConnection { 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; Loading Loading @@ -420,10 +424,18 @@ final class HotwordDetectionConnection { Slog.d(TAG, "onDetected"); } synchronized (mLock) { if (mPerformingSoftwareHotwordDetection) { 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); mPerformingSoftwareHotwordDetection = false; if (result != null) { Slog.i(TAG, "Egressed " + HotwordDetectedResult.getUsageSize(result) + " bits from hotword trusted process"); Loading @@ -431,9 +443,6 @@ final class HotwordDetectionConnection { Slog.i(TAG, "Egressed detected result: " + result); } } } else { Slog.i(TAG, "Hotword detection has already completed"); } } } Loading Loading @@ -513,9 +522,17 @@ final class HotwordDetectionConnection { public void onDetected(HotwordDetectedResult result) throws RemoteException { Slog.v(TAG, "onDetected"); synchronized (mLock) { if (mValidatingDspTrigger) { if (!mValidatingDspTrigger) { Slog.i(TAG, "Ignored hotword detected since trigger has been handled"); return; } mValidatingDspTrigger = false; try { enforcePermissionsForDataDelivery(); } 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) Loading @@ -524,9 +541,6 @@ final class HotwordDetectionConnection { Slog.i(TAG, "Egressed detected result: " + result); } } } else { Slog.i(TAG, "Ignored hotword detected since trigger has been handled"); } } } Loading Loading @@ -595,7 +609,8 @@ final class HotwordDetectionConnection { 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) { Loading Loading @@ -885,7 +900,13 @@ final class HotwordDetectionConnection { throws RemoteException { bestEffortClose(serviceAudioSink); bestEffortClose(serviceAudioSource); try { enforcePermissionsForDataDelivery(); } catch (SecurityException e) { bestEffortClose(audioSource); callback.onError(); return; } callback.onDetected(triggerResult, null /* audioFormat */, null /* audioStream */); if (triggerResult != null) { Loading Loading @@ -984,7 +1005,7 @@ final class HotwordDetectionConnection { 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); } Loading Loading
core/java/android/service/voice/AbstractHotwordDetector.java +9 −0 Original line number Diff line number Diff line Loading @@ -189,5 +189,14 @@ abstract class AbstractHotwordDetector implements HotwordDetector { .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)); } } }
core/java/android/service/voice/IMicrophoneHotwordDetectionVoiceInteractionCallback.aidl +5 −0 Original line number Diff line number Diff line Loading @@ -33,4 +33,9 @@ oneway interface IMicrophoneHotwordDetectionVoiceInteractionCallback { in HotwordDetectedResult hotwordDetectedResult, in AudioFormat audioFormat, in ParcelFileDescriptor audioStream); /** * Called when the detection fails due to an error. */ void onError(); }
core/java/android/service/voice/SoftwareHotwordDetector.java +9 −0 Original line number Diff line number Diff line Loading @@ -155,6 +155,15 @@ class SoftwareHotwordDetector extends AbstractHotwordDetector { .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 Loading
services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java +46 −25 Original line number Diff line number Diff line Loading @@ -124,6 +124,10 @@ final class HotwordDetectionConnection { 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; Loading Loading @@ -420,10 +424,18 @@ final class HotwordDetectionConnection { Slog.d(TAG, "onDetected"); } synchronized (mLock) { if (mPerformingSoftwareHotwordDetection) { 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); mPerformingSoftwareHotwordDetection = false; if (result != null) { Slog.i(TAG, "Egressed " + HotwordDetectedResult.getUsageSize(result) + " bits from hotword trusted process"); Loading @@ -431,9 +443,6 @@ final class HotwordDetectionConnection { Slog.i(TAG, "Egressed detected result: " + result); } } } else { Slog.i(TAG, "Hotword detection has already completed"); } } } Loading Loading @@ -513,9 +522,17 @@ final class HotwordDetectionConnection { public void onDetected(HotwordDetectedResult result) throws RemoteException { Slog.v(TAG, "onDetected"); synchronized (mLock) { if (mValidatingDspTrigger) { if (!mValidatingDspTrigger) { Slog.i(TAG, "Ignored hotword detected since trigger has been handled"); return; } mValidatingDspTrigger = false; try { enforcePermissionsForDataDelivery(); } 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) Loading @@ -524,9 +541,6 @@ final class HotwordDetectionConnection { Slog.i(TAG, "Egressed detected result: " + result); } } } else { Slog.i(TAG, "Ignored hotword detected since trigger has been handled"); } } } Loading Loading @@ -595,7 +609,8 @@ final class HotwordDetectionConnection { 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) { Loading Loading @@ -885,7 +900,13 @@ final class HotwordDetectionConnection { throws RemoteException { bestEffortClose(serviceAudioSink); bestEffortClose(serviceAudioSource); try { enforcePermissionsForDataDelivery(); } catch (SecurityException e) { bestEffortClose(audioSource); callback.onError(); return; } callback.onDetected(triggerResult, null /* audioFormat */, null /* audioStream */); if (triggerResult != null) { Loading Loading @@ -984,7 +1005,7 @@ final class HotwordDetectionConnection { 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); } Loading