Loading api/current.txt +4 −4 Original line number Diff line number Diff line Loading @@ -27467,8 +27467,8 @@ package android.service.voice { public class AlwaysOnHotwordDetector { method public android.content.Intent getManageIntent(int); method public int getSupportedRecognitionModes(); method public int startRecognition(int); method public int stopRecognition(); method public void startRecognition(int); method public void stopRecognition(); field public static final int MANAGE_ACTION_ENROLL = 0; // 0x0 field public static final int MANAGE_ACTION_RE_ENROLL = 1; // 0x1 field public static final int MANAGE_ACTION_UN_ENROLL = 2; // 0x2 Loading @@ -27481,14 +27481,14 @@ package android.service.voice { field public static final int STATE_KEYPHRASE_ENROLLED = 2; // 0x2 field public static final int STATE_KEYPHRASE_UNENROLLED = 1; // 0x1 field public static final int STATE_KEYPHRASE_UNSUPPORTED = -1; // 0xffffffff field public static final int STATUS_ERROR = -2147483648; // 0x80000000 field public static final int STATUS_OK = 0; // 0x0 } public static abstract interface AlwaysOnHotwordDetector.Callback { method public abstract void onAvailabilityChanged(int); method public abstract void onDetected(byte[]); method public abstract void onDetectionStarted(); method public abstract void onDetectionStopped(); method public abstract void onError(); } public class VoiceInteractionService extends android.app.Service { core/java/android/hardware/soundtrigger/IRecognitionStatusCallback.aidl +4 −2 Original line number Diff line number Diff line Loading @@ -29,7 +29,9 @@ oneway interface IRecognitionStatusCallback { */ void onDetected(in SoundTrigger.KeyphraseRecognitionEvent recognitionEvent); /** * Called when the detection for the associated keyphrase stops. * Called when the detection fails due to an error. * * @param status The error code that was seen. */ void onDetectionStopped(); void onError(int status); } No newline at end of file core/java/android/service/voice/AlwaysOnHotwordDetector.java +163 −67 Original line number Diff line number Diff line Loading @@ -22,13 +22,11 @@ import android.hardware.soundtrigger.KeyphraseEnrollmentInfo; import android.hardware.soundtrigger.KeyphraseMetadata; import android.hardware.soundtrigger.SoundTrigger; import android.hardware.soundtrigger.SoundTrigger.ConfidenceLevel; import android.hardware.soundtrigger.SoundTrigger.Keyphrase; import android.hardware.soundtrigger.SoundTrigger.KeyphraseRecognitionEvent; import android.hardware.soundtrigger.SoundTrigger.KeyphraseRecognitionExtra; import android.hardware.soundtrigger.SoundTrigger.KeyphraseSoundModel; import android.hardware.soundtrigger.SoundTrigger.ModuleProperties; import android.hardware.soundtrigger.SoundTrigger.RecognitionConfig; import android.hardware.soundtrigger.SoundTrigger.RecognitionEvent; import android.os.AsyncTask; import android.os.Handler; import android.os.Message; Loading @@ -37,8 +35,6 @@ import android.util.Slog; import com.android.internal.app.IVoiceInteractionManagerService; import java.util.List; /** * A class that lets a VoiceInteractionService implementation interact with * always-on keyphrase detection APIs. Loading Loading @@ -82,12 +78,6 @@ public class AlwaysOnHotwordDetector { /** Indicates that we need to un-enroll. */ public static final int MANAGE_ACTION_UN_ENROLL = 2; /** * Return codes for {@link #startRecognition(int)}, {@link #stopRecognition()} */ public static final int STATUS_ERROR = SoundTrigger.STATUS_ERROR; public static final int STATUS_OK = SoundTrigger.STATUS_OK; //-- Flags for startRecogntion ----// /** Empty flag for {@link #startRecognition(int)}. */ public static final int RECOGNITION_FLAG_NONE = 0; Loading Loading @@ -115,9 +105,19 @@ public class AlwaysOnHotwordDetector { // TODO: Set to false. static final boolean DBG = true; private static final int STATUS_ERROR = SoundTrigger.STATUS_ERROR; private static final int STATUS_OK = SoundTrigger.STATUS_OK; private static final int MSG_STATE_CHANGED = 1; private static final int MSG_HOTWORD_DETECTED = 2; private static final int MSG_DETECTION_STOPPED = 3; private static final int MSG_DETECTION_STARTED = 3; private static final int MSG_DETECTION_STOPPED = 4; private static final int MSG_DETECTION_ERROR = 5; private static final int FLAG_REQUESTED = 0x1; private static final int FLAG_STARTED = 0x2; private static final int FLAG_CALL_ACTIVE = 0x4; private static final int FLAG_MICROPHONE_OPEN = 0x8; private final String mText; private final String mLocale; Loading @@ -135,6 +135,8 @@ public class AlwaysOnHotwordDetector { private final Handler mHandler; private int mAvailability = STATE_NOT_READY; private int mInternalState = 0; private int mRecognitionFlags = RECOGNITION_FLAG_NONE; /** * Callbacks for always-on hotword detection. Loading @@ -161,15 +163,30 @@ public class AlwaysOnHotwordDetector { void onAvailabilityChanged(int status); /** * Called when the keyphrase is spoken. * This implicitly stops listening for the keyphrase once it's detected. * Clients should start a recognition again once they are done handling this * detection. * * @param data Optional trigger audio data, if it was requested during * {@link AlwaysOnHotwordDetector#startRecognition(int)}. */ void onDetected(byte[] data); /** * Called when the detection for the associated keyphrase starts. * This is called as a result of a successful call to * {@link AlwaysOnHotwordDetector#startRecognition(int)}. */ void onDetectionStarted(); /** * Called when the detection for the associated keyphrase stops. * This is called as a result of a successful call to * {@link AlwaysOnHotwordDetector#stopRecognition()}. */ void onDetectionStopped(); /** * Called when the detection fails due to an error. */ void onError(); } /** Loading Loading @@ -227,78 +244,43 @@ public class AlwaysOnHotwordDetector { * @param recognitionFlags The flags to control the recognition properties. * The allowed flags are {@link #RECOGNITION_FLAG_NONE} and * {@link #RECOGNITION_FLAG_CAPTURE_TRIGGER_AUDIO}. * @return {@link #STATUS_OK} if the call succeeds, an error code otherwise. * @throws UnsupportedOperationException if the recognition isn't supported. * Callers should only call this method after a supported state callback on * {@link Callback#onAvailabilityChanged(int)} to avoid this exception. */ public int startRecognition(int recognitionFlags) { public void startRecognition(int recognitionFlags) { synchronized (mLock) { return startRecognitionLocked(recognitionFlags); } } private int startRecognitionLocked(int recognitionFlags) { // This method only makes sense if we can start a recognition. // Check if we can start/stop a recognition. if (mAvailability != STATE_KEYPHRASE_ENROLLED) { throw new UnsupportedOperationException( "Recognition for the given keyphrase is not supported"); } KeyphraseRecognitionExtra[] recognitionExtra = new KeyphraseRecognitionExtra[1]; // TODO: Do we need to do something about the confidence level here? recognitionExtra[0] = new KeyphraseRecognitionExtra(mKeyphraseMetadata.id, mKeyphraseMetadata.recognitionModeFlags, new ConfidenceLevel[0]); boolean captureTriggerAudio = (recognitionFlags & RECOGNITION_FLAG_CAPTURE_TRIGGER_AUDIO) != 0; int code = STATUS_ERROR; try { code = mModelManagementService.startRecognition(mVoiceInteractionService, mKeyphraseMetadata.id, mInternalCallback, new RecognitionConfig( captureTriggerAudio, recognitionExtra, null /* additional data */)); } catch (RemoteException e) { Slog.w(TAG, "RemoteException in startRecognition!"); mInternalState |= FLAG_REQUESTED; mRecognitionFlags = recognitionFlags; updateRecognitionLocked(); } if (code != STATUS_OK) { Slog.w(TAG, "startRecognition() failed with error code " + code); } return code; } /** * Stops recognition for the associated keyphrase. * * @return {@link #STATUS_OK} if the call succeeds, an error code otherwise. * @throws UnsupportedOperationException if the recognition isn't supported. * Callers should only call this method after a supported state callback on * {@link Callback#onAvailabilityChanged(int)} to avoid this exception. */ public int stopRecognition() { public void stopRecognition() { synchronized (mLock) { return stopRecognitionLocked(); } } private int stopRecognitionLocked() { // This method only makes sense if we can start a recognition. // Check if we can start/stop a recognition. if (mAvailability != STATE_KEYPHRASE_ENROLLED) { throw new UnsupportedOperationException( "Recognition for the given keyphrase is not supported"); } int code = STATUS_ERROR; try { code = mModelManagementService.stopRecognition( mVoiceInteractionService, mKeyphraseMetadata.id, mInternalCallback); } catch (RemoteException e) { Slog.w(TAG, "RemoteException in stopRecognition!"); } if (code != STATUS_OK) { Slog.w(TAG, "stopRecognition() failed with error code " + code); mInternalState &= ~FLAG_REQUESTED; mRecognitionFlags = RECOGNITION_FLAG_NONE; updateRecognitionLocked(); } return code; } /** Loading Loading @@ -362,6 +344,113 @@ public class AlwaysOnHotwordDetector { } } @SuppressWarnings("unused") private void onCallStateChanged(boolean active) { synchronized (mLock) { if (active) { mInternalState |= FLAG_CALL_ACTIVE; } else { mInternalState &= ~FLAG_CALL_ACTIVE; } updateRecognitionLocked(); } } @SuppressWarnings("unused") private void onMicrophoneStateChanged(boolean open) { synchronized (mLock) { if (open) { mInternalState |= FLAG_MICROPHONE_OPEN; } else { mInternalState &= ~FLAG_MICROPHONE_OPEN; } updateRecognitionLocked(); } } private void updateRecognitionLocked() { // Don't attempt to update the recognition state if keyphrase isn't enrolled. if (mAvailability != STATE_KEYPHRASE_ENROLLED) { return; } // Start recognition if requested and not in a call/reading from the microphone boolean start = (mInternalState&FLAG_REQUESTED) != 0 && (mInternalState&FLAG_CALL_ACTIVE) == 0 && (mInternalState&FLAG_MICROPHONE_OPEN) == 0; boolean requested = (mInternalState&FLAG_REQUESTED) != 0; if (start && (mInternalState&FLAG_STARTED) == 0) { // Start recognition. if (DBG) Slog.d(TAG, "starting recognition..."); int status = startRecognitionLocked(); if (status == STATUS_OK) { mInternalState |= FLAG_STARTED; mHandler.sendEmptyMessage(MSG_DETECTION_STARTED); } else { if (DBG) Slog.d(TAG, "failed to start recognition: " + status); mHandler.sendEmptyMessage(MSG_DETECTION_ERROR); } // Post the callback return; } if (!start && (mInternalState&FLAG_STARTED) != 0) { // Stop recognition // Only notify the callback if a recognition was *not* requested. // For internal stoppages, don't notify the callback. if (DBG) Slog.d(TAG, "stopping recognition..."); int status = stopRecognitionLocked(); if (status == STATUS_OK) { mInternalState &= ~FLAG_STARTED; if (!requested) mHandler.sendEmptyMessage(MSG_DETECTION_STOPPED); } else { if (!requested) mHandler.sendEmptyMessage(MSG_DETECTION_ERROR); if (DBG) Slog.d(TAG, "failed to stop recognition: " + status); } return; } } private int startRecognitionLocked() { KeyphraseRecognitionExtra[] recognitionExtra = new KeyphraseRecognitionExtra[1]; // TODO: Do we need to do something about the confidence level here? recognitionExtra[0] = new KeyphraseRecognitionExtra(mKeyphraseMetadata.id, mKeyphraseMetadata.recognitionModeFlags, new ConfidenceLevel[0]); boolean captureTriggerAudio = (mRecognitionFlags&RECOGNITION_FLAG_CAPTURE_TRIGGER_AUDIO) != 0; int code = STATUS_ERROR; try { code = mModelManagementService.startRecognition(mVoiceInteractionService, mKeyphraseMetadata.id, mInternalCallback, new RecognitionConfig( captureTriggerAudio, recognitionExtra, null /* additional data */)); } catch (RemoteException e) { Slog.w(TAG, "RemoteException in startRecognition!"); } if (code != STATUS_OK) { Slog.w(TAG, "startRecognition() failed with error code " + code); } return code; } private int stopRecognitionLocked() { int code = STATUS_ERROR; try { code = mModelManagementService.stopRecognition( mVoiceInteractionService, mKeyphraseMetadata.id, mInternalCallback); } catch (RemoteException e) { Slog.w(TAG, "RemoteException in stopRecognition!"); } if (code != STATUS_OK) { Slog.w(TAG, "stopRecognition() failed with error code " + code); } return code; } private void notifyStateChangedLocked() { Message message = Message.obtain(mHandler, MSG_STATE_CHANGED); message.arg1 = mAvailability; Loading @@ -385,9 +474,9 @@ public class AlwaysOnHotwordDetector { } @Override public void onDetectionStopped() { Slog.i(TAG, "onDetectionStopped"); mHandler.sendEmptyMessage(MSG_DETECTION_STOPPED); public void onError(int status) { Slog.i(TAG, "onError: " + status); mHandler.sendEmptyMessage(MSG_DETECTION_ERROR); } } Loading @@ -401,8 +490,15 @@ public class AlwaysOnHotwordDetector { case MSG_HOTWORD_DETECTED: mExternalCallback.onDetected((byte[]) msg.obj); break; case MSG_DETECTION_STARTED: mExternalCallback.onDetectionStarted(); break; case MSG_DETECTION_STOPPED: mExternalCallback.onDetectionStopped(); break; case MSG_DETECTION_ERROR: mExternalCallback.onError(); break; default: super.handleMessage(msg); } Loading services/voiceinteraction/java/com/android/server/voiceinteraction/SoundTriggerHelper.java +3 −3 Original line number Diff line number Diff line Loading @@ -129,7 +129,7 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { if (oldListener != null && oldListener.asBinder() != listener.asBinder()) { Slog.w(TAG, "Canceling previous recognition"); try { oldListener.onDetectionStopped(); oldListener.onError(STATUS_ERROR); } catch (RemoteException e) { Slog.w(TAG, "RemoteException in onDetectionStopped"); } Loading Loading @@ -235,7 +235,7 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { try { synchronized (this) { for (int i = 0; i < mActiveListeners.size(); i++) { mActiveListeners.valueAt(i).onDetectionStopped(); mActiveListeners.valueAt(i).onError(STATUS_ERROR); } } } catch (RemoteException e) { Loading Loading @@ -279,7 +279,7 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { synchronized (this) { try { for (int i = 0; i < mActiveListeners.size(); i++) { mActiveListeners.valueAt(i).onDetectionStopped(); mActiveListeners.valueAt(i).onError(SoundTrigger.STATUS_DEAD_OBJECT); } } catch (RemoteException e) { Slog.w(TAG, "RemoteException in onDetectionStopped"); Loading tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionService.java +12 −3 Original line number Diff line number Diff line Loading @@ -40,10 +40,20 @@ public class MainInteractionService extends VoiceInteractionService { Log.i(TAG, "onDetected"); } @Override public void onDetectionStarted() { Log.i(TAG, "onDetectionStarted"); } @Override public void onDetectionStopped() { Log.i(TAG, "onDetectionStopped"); } @Override public void onError() { Log.i(TAG, "onError"); } }; private AlwaysOnHotwordDetector mHotwordDetector; Loading Loading @@ -89,10 +99,9 @@ public class MainInteractionService extends VoiceInteractionService { Log.i(TAG, "Need to enroll with " + enroll); break; case AlwaysOnHotwordDetector.STATE_KEYPHRASE_ENROLLED: Log.i(TAG, "STATE_KEYPHRASE_ENROLLED"); int status = mHotwordDetector.startRecognition( Log.i(TAG, "STATE_KEYPHRASE_ENROLLED - starting recognition"); mHotwordDetector.startRecognition( AlwaysOnHotwordDetector.RECOGNITION_FLAG_NONE); Log.i(TAG, "startRecognition status = " + status); break; } } Loading Loading
api/current.txt +4 −4 Original line number Diff line number Diff line Loading @@ -27467,8 +27467,8 @@ package android.service.voice { public class AlwaysOnHotwordDetector { method public android.content.Intent getManageIntent(int); method public int getSupportedRecognitionModes(); method public int startRecognition(int); method public int stopRecognition(); method public void startRecognition(int); method public void stopRecognition(); field public static final int MANAGE_ACTION_ENROLL = 0; // 0x0 field public static final int MANAGE_ACTION_RE_ENROLL = 1; // 0x1 field public static final int MANAGE_ACTION_UN_ENROLL = 2; // 0x2 Loading @@ -27481,14 +27481,14 @@ package android.service.voice { field public static final int STATE_KEYPHRASE_ENROLLED = 2; // 0x2 field public static final int STATE_KEYPHRASE_UNENROLLED = 1; // 0x1 field public static final int STATE_KEYPHRASE_UNSUPPORTED = -1; // 0xffffffff field public static final int STATUS_ERROR = -2147483648; // 0x80000000 field public static final int STATUS_OK = 0; // 0x0 } public static abstract interface AlwaysOnHotwordDetector.Callback { method public abstract void onAvailabilityChanged(int); method public abstract void onDetected(byte[]); method public abstract void onDetectionStarted(); method public abstract void onDetectionStopped(); method public abstract void onError(); } public class VoiceInteractionService extends android.app.Service {
core/java/android/hardware/soundtrigger/IRecognitionStatusCallback.aidl +4 −2 Original line number Diff line number Diff line Loading @@ -29,7 +29,9 @@ oneway interface IRecognitionStatusCallback { */ void onDetected(in SoundTrigger.KeyphraseRecognitionEvent recognitionEvent); /** * Called when the detection for the associated keyphrase stops. * Called when the detection fails due to an error. * * @param status The error code that was seen. */ void onDetectionStopped(); void onError(int status); } No newline at end of file
core/java/android/service/voice/AlwaysOnHotwordDetector.java +163 −67 Original line number Diff line number Diff line Loading @@ -22,13 +22,11 @@ import android.hardware.soundtrigger.KeyphraseEnrollmentInfo; import android.hardware.soundtrigger.KeyphraseMetadata; import android.hardware.soundtrigger.SoundTrigger; import android.hardware.soundtrigger.SoundTrigger.ConfidenceLevel; import android.hardware.soundtrigger.SoundTrigger.Keyphrase; import android.hardware.soundtrigger.SoundTrigger.KeyphraseRecognitionEvent; import android.hardware.soundtrigger.SoundTrigger.KeyphraseRecognitionExtra; import android.hardware.soundtrigger.SoundTrigger.KeyphraseSoundModel; import android.hardware.soundtrigger.SoundTrigger.ModuleProperties; import android.hardware.soundtrigger.SoundTrigger.RecognitionConfig; import android.hardware.soundtrigger.SoundTrigger.RecognitionEvent; import android.os.AsyncTask; import android.os.Handler; import android.os.Message; Loading @@ -37,8 +35,6 @@ import android.util.Slog; import com.android.internal.app.IVoiceInteractionManagerService; import java.util.List; /** * A class that lets a VoiceInteractionService implementation interact with * always-on keyphrase detection APIs. Loading Loading @@ -82,12 +78,6 @@ public class AlwaysOnHotwordDetector { /** Indicates that we need to un-enroll. */ public static final int MANAGE_ACTION_UN_ENROLL = 2; /** * Return codes for {@link #startRecognition(int)}, {@link #stopRecognition()} */ public static final int STATUS_ERROR = SoundTrigger.STATUS_ERROR; public static final int STATUS_OK = SoundTrigger.STATUS_OK; //-- Flags for startRecogntion ----// /** Empty flag for {@link #startRecognition(int)}. */ public static final int RECOGNITION_FLAG_NONE = 0; Loading Loading @@ -115,9 +105,19 @@ public class AlwaysOnHotwordDetector { // TODO: Set to false. static final boolean DBG = true; private static final int STATUS_ERROR = SoundTrigger.STATUS_ERROR; private static final int STATUS_OK = SoundTrigger.STATUS_OK; private static final int MSG_STATE_CHANGED = 1; private static final int MSG_HOTWORD_DETECTED = 2; private static final int MSG_DETECTION_STOPPED = 3; private static final int MSG_DETECTION_STARTED = 3; private static final int MSG_DETECTION_STOPPED = 4; private static final int MSG_DETECTION_ERROR = 5; private static final int FLAG_REQUESTED = 0x1; private static final int FLAG_STARTED = 0x2; private static final int FLAG_CALL_ACTIVE = 0x4; private static final int FLAG_MICROPHONE_OPEN = 0x8; private final String mText; private final String mLocale; Loading @@ -135,6 +135,8 @@ public class AlwaysOnHotwordDetector { private final Handler mHandler; private int mAvailability = STATE_NOT_READY; private int mInternalState = 0; private int mRecognitionFlags = RECOGNITION_FLAG_NONE; /** * Callbacks for always-on hotword detection. Loading @@ -161,15 +163,30 @@ public class AlwaysOnHotwordDetector { void onAvailabilityChanged(int status); /** * Called when the keyphrase is spoken. * This implicitly stops listening for the keyphrase once it's detected. * Clients should start a recognition again once they are done handling this * detection. * * @param data Optional trigger audio data, if it was requested during * {@link AlwaysOnHotwordDetector#startRecognition(int)}. */ void onDetected(byte[] data); /** * Called when the detection for the associated keyphrase starts. * This is called as a result of a successful call to * {@link AlwaysOnHotwordDetector#startRecognition(int)}. */ void onDetectionStarted(); /** * Called when the detection for the associated keyphrase stops. * This is called as a result of a successful call to * {@link AlwaysOnHotwordDetector#stopRecognition()}. */ void onDetectionStopped(); /** * Called when the detection fails due to an error. */ void onError(); } /** Loading Loading @@ -227,78 +244,43 @@ public class AlwaysOnHotwordDetector { * @param recognitionFlags The flags to control the recognition properties. * The allowed flags are {@link #RECOGNITION_FLAG_NONE} and * {@link #RECOGNITION_FLAG_CAPTURE_TRIGGER_AUDIO}. * @return {@link #STATUS_OK} if the call succeeds, an error code otherwise. * @throws UnsupportedOperationException if the recognition isn't supported. * Callers should only call this method after a supported state callback on * {@link Callback#onAvailabilityChanged(int)} to avoid this exception. */ public int startRecognition(int recognitionFlags) { public void startRecognition(int recognitionFlags) { synchronized (mLock) { return startRecognitionLocked(recognitionFlags); } } private int startRecognitionLocked(int recognitionFlags) { // This method only makes sense if we can start a recognition. // Check if we can start/stop a recognition. if (mAvailability != STATE_KEYPHRASE_ENROLLED) { throw new UnsupportedOperationException( "Recognition for the given keyphrase is not supported"); } KeyphraseRecognitionExtra[] recognitionExtra = new KeyphraseRecognitionExtra[1]; // TODO: Do we need to do something about the confidence level here? recognitionExtra[0] = new KeyphraseRecognitionExtra(mKeyphraseMetadata.id, mKeyphraseMetadata.recognitionModeFlags, new ConfidenceLevel[0]); boolean captureTriggerAudio = (recognitionFlags & RECOGNITION_FLAG_CAPTURE_TRIGGER_AUDIO) != 0; int code = STATUS_ERROR; try { code = mModelManagementService.startRecognition(mVoiceInteractionService, mKeyphraseMetadata.id, mInternalCallback, new RecognitionConfig( captureTriggerAudio, recognitionExtra, null /* additional data */)); } catch (RemoteException e) { Slog.w(TAG, "RemoteException in startRecognition!"); mInternalState |= FLAG_REQUESTED; mRecognitionFlags = recognitionFlags; updateRecognitionLocked(); } if (code != STATUS_OK) { Slog.w(TAG, "startRecognition() failed with error code " + code); } return code; } /** * Stops recognition for the associated keyphrase. * * @return {@link #STATUS_OK} if the call succeeds, an error code otherwise. * @throws UnsupportedOperationException if the recognition isn't supported. * Callers should only call this method after a supported state callback on * {@link Callback#onAvailabilityChanged(int)} to avoid this exception. */ public int stopRecognition() { public void stopRecognition() { synchronized (mLock) { return stopRecognitionLocked(); } } private int stopRecognitionLocked() { // This method only makes sense if we can start a recognition. // Check if we can start/stop a recognition. if (mAvailability != STATE_KEYPHRASE_ENROLLED) { throw new UnsupportedOperationException( "Recognition for the given keyphrase is not supported"); } int code = STATUS_ERROR; try { code = mModelManagementService.stopRecognition( mVoiceInteractionService, mKeyphraseMetadata.id, mInternalCallback); } catch (RemoteException e) { Slog.w(TAG, "RemoteException in stopRecognition!"); } if (code != STATUS_OK) { Slog.w(TAG, "stopRecognition() failed with error code " + code); mInternalState &= ~FLAG_REQUESTED; mRecognitionFlags = RECOGNITION_FLAG_NONE; updateRecognitionLocked(); } return code; } /** Loading Loading @@ -362,6 +344,113 @@ public class AlwaysOnHotwordDetector { } } @SuppressWarnings("unused") private void onCallStateChanged(boolean active) { synchronized (mLock) { if (active) { mInternalState |= FLAG_CALL_ACTIVE; } else { mInternalState &= ~FLAG_CALL_ACTIVE; } updateRecognitionLocked(); } } @SuppressWarnings("unused") private void onMicrophoneStateChanged(boolean open) { synchronized (mLock) { if (open) { mInternalState |= FLAG_MICROPHONE_OPEN; } else { mInternalState &= ~FLAG_MICROPHONE_OPEN; } updateRecognitionLocked(); } } private void updateRecognitionLocked() { // Don't attempt to update the recognition state if keyphrase isn't enrolled. if (mAvailability != STATE_KEYPHRASE_ENROLLED) { return; } // Start recognition if requested and not in a call/reading from the microphone boolean start = (mInternalState&FLAG_REQUESTED) != 0 && (mInternalState&FLAG_CALL_ACTIVE) == 0 && (mInternalState&FLAG_MICROPHONE_OPEN) == 0; boolean requested = (mInternalState&FLAG_REQUESTED) != 0; if (start && (mInternalState&FLAG_STARTED) == 0) { // Start recognition. if (DBG) Slog.d(TAG, "starting recognition..."); int status = startRecognitionLocked(); if (status == STATUS_OK) { mInternalState |= FLAG_STARTED; mHandler.sendEmptyMessage(MSG_DETECTION_STARTED); } else { if (DBG) Slog.d(TAG, "failed to start recognition: " + status); mHandler.sendEmptyMessage(MSG_DETECTION_ERROR); } // Post the callback return; } if (!start && (mInternalState&FLAG_STARTED) != 0) { // Stop recognition // Only notify the callback if a recognition was *not* requested. // For internal stoppages, don't notify the callback. if (DBG) Slog.d(TAG, "stopping recognition..."); int status = stopRecognitionLocked(); if (status == STATUS_OK) { mInternalState &= ~FLAG_STARTED; if (!requested) mHandler.sendEmptyMessage(MSG_DETECTION_STOPPED); } else { if (!requested) mHandler.sendEmptyMessage(MSG_DETECTION_ERROR); if (DBG) Slog.d(TAG, "failed to stop recognition: " + status); } return; } } private int startRecognitionLocked() { KeyphraseRecognitionExtra[] recognitionExtra = new KeyphraseRecognitionExtra[1]; // TODO: Do we need to do something about the confidence level here? recognitionExtra[0] = new KeyphraseRecognitionExtra(mKeyphraseMetadata.id, mKeyphraseMetadata.recognitionModeFlags, new ConfidenceLevel[0]); boolean captureTriggerAudio = (mRecognitionFlags&RECOGNITION_FLAG_CAPTURE_TRIGGER_AUDIO) != 0; int code = STATUS_ERROR; try { code = mModelManagementService.startRecognition(mVoiceInteractionService, mKeyphraseMetadata.id, mInternalCallback, new RecognitionConfig( captureTriggerAudio, recognitionExtra, null /* additional data */)); } catch (RemoteException e) { Slog.w(TAG, "RemoteException in startRecognition!"); } if (code != STATUS_OK) { Slog.w(TAG, "startRecognition() failed with error code " + code); } return code; } private int stopRecognitionLocked() { int code = STATUS_ERROR; try { code = mModelManagementService.stopRecognition( mVoiceInteractionService, mKeyphraseMetadata.id, mInternalCallback); } catch (RemoteException e) { Slog.w(TAG, "RemoteException in stopRecognition!"); } if (code != STATUS_OK) { Slog.w(TAG, "stopRecognition() failed with error code " + code); } return code; } private void notifyStateChangedLocked() { Message message = Message.obtain(mHandler, MSG_STATE_CHANGED); message.arg1 = mAvailability; Loading @@ -385,9 +474,9 @@ public class AlwaysOnHotwordDetector { } @Override public void onDetectionStopped() { Slog.i(TAG, "onDetectionStopped"); mHandler.sendEmptyMessage(MSG_DETECTION_STOPPED); public void onError(int status) { Slog.i(TAG, "onError: " + status); mHandler.sendEmptyMessage(MSG_DETECTION_ERROR); } } Loading @@ -401,8 +490,15 @@ public class AlwaysOnHotwordDetector { case MSG_HOTWORD_DETECTED: mExternalCallback.onDetected((byte[]) msg.obj); break; case MSG_DETECTION_STARTED: mExternalCallback.onDetectionStarted(); break; case MSG_DETECTION_STOPPED: mExternalCallback.onDetectionStopped(); break; case MSG_DETECTION_ERROR: mExternalCallback.onError(); break; default: super.handleMessage(msg); } Loading
services/voiceinteraction/java/com/android/server/voiceinteraction/SoundTriggerHelper.java +3 −3 Original line number Diff line number Diff line Loading @@ -129,7 +129,7 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { if (oldListener != null && oldListener.asBinder() != listener.asBinder()) { Slog.w(TAG, "Canceling previous recognition"); try { oldListener.onDetectionStopped(); oldListener.onError(STATUS_ERROR); } catch (RemoteException e) { Slog.w(TAG, "RemoteException in onDetectionStopped"); } Loading Loading @@ -235,7 +235,7 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { try { synchronized (this) { for (int i = 0; i < mActiveListeners.size(); i++) { mActiveListeners.valueAt(i).onDetectionStopped(); mActiveListeners.valueAt(i).onError(STATUS_ERROR); } } } catch (RemoteException e) { Loading Loading @@ -279,7 +279,7 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { synchronized (this) { try { for (int i = 0; i < mActiveListeners.size(); i++) { mActiveListeners.valueAt(i).onDetectionStopped(); mActiveListeners.valueAt(i).onError(SoundTrigger.STATUS_DEAD_OBJECT); } } catch (RemoteException e) { Slog.w(TAG, "RemoteException in onDetectionStopped"); Loading
tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionService.java +12 −3 Original line number Diff line number Diff line Loading @@ -40,10 +40,20 @@ public class MainInteractionService extends VoiceInteractionService { Log.i(TAG, "onDetected"); } @Override public void onDetectionStarted() { Log.i(TAG, "onDetectionStarted"); } @Override public void onDetectionStopped() { Log.i(TAG, "onDetectionStopped"); } @Override public void onError() { Log.i(TAG, "onError"); } }; private AlwaysOnHotwordDetector mHotwordDetector; Loading Loading @@ -89,10 +99,9 @@ public class MainInteractionService extends VoiceInteractionService { Log.i(TAG, "Need to enroll with " + enroll); break; case AlwaysOnHotwordDetector.STATE_KEYPHRASE_ENROLLED: Log.i(TAG, "STATE_KEYPHRASE_ENROLLED"); int status = mHotwordDetector.startRecognition( Log.i(TAG, "STATE_KEYPHRASE_ENROLLED - starting recognition"); mHotwordDetector.startRecognition( AlwaysOnHotwordDetector.RECOGNITION_FLAG_NONE); Log.i(TAG, "startRecognition status = " + status); break; } } Loading