Loading core/java/android/service/voice/AbstractHotwordDetector.java +9 −0 Original line number Original line Diff line number Diff line Loading @@ -189,5 +189,14 @@ abstract class AbstractHotwordDetector implements HotwordDetector { .setHotwordDetectedResult(hotwordDetectedResult) .setHotwordDetectedResult(hotwordDetectedResult) .build())); .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 Original line Diff line number Diff line Loading @@ -33,4 +33,9 @@ oneway interface IMicrophoneHotwordDetectionVoiceInteractionCallback { in HotwordDetectedResult hotwordDetectedResult, in HotwordDetectedResult hotwordDetectedResult, in AudioFormat audioFormat, in AudioFormat audioFormat, in ParcelFileDescriptor audioStream); 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 Original line Diff line number Diff line Loading @@ -155,6 +155,15 @@ class SoftwareHotwordDetector extends AbstractHotwordDetector { .setHotwordDetectedResult(hotwordDetectedResult) .setHotwordDetectedResult(hotwordDetectedResult) .build())); .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 private static class InitializationStateListener Loading services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java +46 −25 Original line number Original line 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 long RESET_DEBUG_HOTWORD_LOGGING_TIMEOUT_MILLIS = 60 * 60 * 1000; // 1 hour private static final int MAX_ISOLATED_PROCESS_NUMBER = 10; 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 // Hotword metrics private static final int METRICS_INIT_UNKNOWN_TIMEOUT = private static final int METRICS_INIT_UNKNOWN_TIMEOUT = HOTWORD_DETECTION_SERVICE_INIT_RESULT_REPORTED__RESULT__CALLBACK_INIT_STATE_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"); Slog.d(TAG, "onDetected"); } } synchronized (mLock) { synchronized (mLock) { if (mPerformingSoftwareHotwordDetection) { if (!mPerformingSoftwareHotwordDetection) { Slog.i(TAG, "Hotword detection has already completed"); return; } mPerformingSoftwareHotwordDetection = false; try { enforcePermissionsForDataDelivery(); enforcePermissionsForDataDelivery(); } catch (SecurityException e) { mSoftwareCallback.onError(); return; } mSoftwareCallback.onDetected(result, null, null); mSoftwareCallback.onDetected(result, null, null); mPerformingSoftwareHotwordDetection = false; if (result != null) { if (result != null) { Slog.i(TAG, "Egressed " + HotwordDetectedResult.getUsageSize(result) Slog.i(TAG, "Egressed " + HotwordDetectedResult.getUsageSize(result) + " bits from hotword trusted process"); + " bits from hotword trusted process"); Loading @@ -431,9 +443,6 @@ final class HotwordDetectionConnection { Slog.i(TAG, "Egressed detected result: " + result); 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 { public void onDetected(HotwordDetectedResult result) throws RemoteException { Slog.v(TAG, "onDetected"); Slog.v(TAG, "onDetected"); synchronized (mLock) { synchronized (mLock) { if (mValidatingDspTrigger) { if (!mValidatingDspTrigger) { Slog.i(TAG, "Ignored hotword detected since trigger has been handled"); return; } mValidatingDspTrigger = false; mValidatingDspTrigger = false; try { enforcePermissionsForDataDelivery(); enforcePermissionsForDataDelivery(); } catch (SecurityException e) { externalCallback.onError(CALLBACK_ONDETECTED_GOT_SECURITY_EXCEPTION); return; } externalCallback.onKeyphraseDetected(recognitionEvent, result); externalCallback.onKeyphraseDetected(recognitionEvent, result); if (result != null) { if (result != null) { Slog.i(TAG, "Egressed " + HotwordDetectedResult.getUsageSize(result) Slog.i(TAG, "Egressed " + HotwordDetectedResult.getUsageSize(result) Loading @@ -524,9 +541,6 @@ final class HotwordDetectionConnection { Slog.i(TAG, "Egressed detected result: " + result); 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( HotwordMetricsLogger.writeKeyphraseTriggerEvent( mDetectorType, mDetectorType, METRICS_KEYPHRASE_TRIGGERED_DETECT_SECURITY_EXCEPTION); METRICS_KEYPHRASE_TRIGGERED_DETECT_SECURITY_EXCEPTION); throw e; externalCallback.onError(CALLBACK_ONDETECTED_GOT_SECURITY_EXCEPTION); return; } } externalCallback.onKeyphraseDetected(recognitionEvent, result); externalCallback.onKeyphraseDetected(recognitionEvent, result); if (result != null) { if (result != null) { Loading Loading @@ -885,7 +900,13 @@ final class HotwordDetectionConnection { throws RemoteException { throws RemoteException { bestEffortClose(serviceAudioSink); bestEffortClose(serviceAudioSink); bestEffortClose(serviceAudioSource); bestEffortClose(serviceAudioSource); try { enforcePermissionsForDataDelivery(); enforcePermissionsForDataDelivery(); } catch (SecurityException e) { bestEffortClose(audioSource); callback.onError(); return; } callback.onDetected(triggerResult, null /* audioFormat */, callback.onDetected(triggerResult, null /* audioFormat */, null /* audioStream */); null /* audioStream */); if (triggerResult != null) { if (triggerResult != null) { Loading Loading @@ -984,7 +1005,7 @@ final class HotwordDetectionConnection { Slog.w(TAG, "binderDied"); Slog.w(TAG, "binderDied"); try { try { mCallback.onError(-1); mCallback.onError(HOTWORD_DETECTION_SERVICE_DIED); } catch (RemoteException e) { } catch (RemoteException e) { Slog.w(TAG, "Failed to report onError status: " + e); Slog.w(TAG, "Failed to report onError status: " + e); } } Loading Loading
core/java/android/service/voice/AbstractHotwordDetector.java +9 −0 Original line number Original line Diff line number Diff line Loading @@ -189,5 +189,14 @@ abstract class AbstractHotwordDetector implements HotwordDetector { .setHotwordDetectedResult(hotwordDetectedResult) .setHotwordDetectedResult(hotwordDetectedResult) .build())); .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 Original line Diff line number Diff line Loading @@ -33,4 +33,9 @@ oneway interface IMicrophoneHotwordDetectionVoiceInteractionCallback { in HotwordDetectedResult hotwordDetectedResult, in HotwordDetectedResult hotwordDetectedResult, in AudioFormat audioFormat, in AudioFormat audioFormat, in ParcelFileDescriptor audioStream); 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 Original line Diff line number Diff line Loading @@ -155,6 +155,15 @@ class SoftwareHotwordDetector extends AbstractHotwordDetector { .setHotwordDetectedResult(hotwordDetectedResult) .setHotwordDetectedResult(hotwordDetectedResult) .build())); .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 private static class InitializationStateListener Loading
services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java +46 −25 Original line number Original line 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 long RESET_DEBUG_HOTWORD_LOGGING_TIMEOUT_MILLIS = 60 * 60 * 1000; // 1 hour private static final int MAX_ISOLATED_PROCESS_NUMBER = 10; 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 // Hotword metrics private static final int METRICS_INIT_UNKNOWN_TIMEOUT = private static final int METRICS_INIT_UNKNOWN_TIMEOUT = HOTWORD_DETECTION_SERVICE_INIT_RESULT_REPORTED__RESULT__CALLBACK_INIT_STATE_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"); Slog.d(TAG, "onDetected"); } } synchronized (mLock) { synchronized (mLock) { if (mPerformingSoftwareHotwordDetection) { if (!mPerformingSoftwareHotwordDetection) { Slog.i(TAG, "Hotword detection has already completed"); return; } mPerformingSoftwareHotwordDetection = false; try { enforcePermissionsForDataDelivery(); enforcePermissionsForDataDelivery(); } catch (SecurityException e) { mSoftwareCallback.onError(); return; } mSoftwareCallback.onDetected(result, null, null); mSoftwareCallback.onDetected(result, null, null); mPerformingSoftwareHotwordDetection = false; if (result != null) { if (result != null) { Slog.i(TAG, "Egressed " + HotwordDetectedResult.getUsageSize(result) Slog.i(TAG, "Egressed " + HotwordDetectedResult.getUsageSize(result) + " bits from hotword trusted process"); + " bits from hotword trusted process"); Loading @@ -431,9 +443,6 @@ final class HotwordDetectionConnection { Slog.i(TAG, "Egressed detected result: " + result); 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 { public void onDetected(HotwordDetectedResult result) throws RemoteException { Slog.v(TAG, "onDetected"); Slog.v(TAG, "onDetected"); synchronized (mLock) { synchronized (mLock) { if (mValidatingDspTrigger) { if (!mValidatingDspTrigger) { Slog.i(TAG, "Ignored hotword detected since trigger has been handled"); return; } mValidatingDspTrigger = false; mValidatingDspTrigger = false; try { enforcePermissionsForDataDelivery(); enforcePermissionsForDataDelivery(); } catch (SecurityException e) { externalCallback.onError(CALLBACK_ONDETECTED_GOT_SECURITY_EXCEPTION); return; } externalCallback.onKeyphraseDetected(recognitionEvent, result); externalCallback.onKeyphraseDetected(recognitionEvent, result); if (result != null) { if (result != null) { Slog.i(TAG, "Egressed " + HotwordDetectedResult.getUsageSize(result) Slog.i(TAG, "Egressed " + HotwordDetectedResult.getUsageSize(result) Loading @@ -524,9 +541,6 @@ final class HotwordDetectionConnection { Slog.i(TAG, "Egressed detected result: " + result); 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( HotwordMetricsLogger.writeKeyphraseTriggerEvent( mDetectorType, mDetectorType, METRICS_KEYPHRASE_TRIGGERED_DETECT_SECURITY_EXCEPTION); METRICS_KEYPHRASE_TRIGGERED_DETECT_SECURITY_EXCEPTION); throw e; externalCallback.onError(CALLBACK_ONDETECTED_GOT_SECURITY_EXCEPTION); return; } } externalCallback.onKeyphraseDetected(recognitionEvent, result); externalCallback.onKeyphraseDetected(recognitionEvent, result); if (result != null) { if (result != null) { Loading Loading @@ -885,7 +900,13 @@ final class HotwordDetectionConnection { throws RemoteException { throws RemoteException { bestEffortClose(serviceAudioSink); bestEffortClose(serviceAudioSink); bestEffortClose(serviceAudioSource); bestEffortClose(serviceAudioSource); try { enforcePermissionsForDataDelivery(); enforcePermissionsForDataDelivery(); } catch (SecurityException e) { bestEffortClose(audioSource); callback.onError(); return; } callback.onDetected(triggerResult, null /* audioFormat */, callback.onDetected(triggerResult, null /* audioFormat */, null /* audioStream */); null /* audioStream */); if (triggerResult != null) { if (triggerResult != null) { Loading Loading @@ -984,7 +1005,7 @@ final class HotwordDetectionConnection { Slog.w(TAG, "binderDied"); Slog.w(TAG, "binderDied"); try { try { mCallback.onError(-1); mCallback.onError(HOTWORD_DETECTION_SERVICE_DIED); } catch (RemoteException e) { } catch (RemoteException e) { Slog.w(TAG, "Failed to report onError status: " + e); Slog.w(TAG, "Failed to report onError status: " + e); } } Loading