summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/current.txt14
-rw-r--r--core/java/android/hardware/soundtrigger/SoundTrigger.java18
-rw-r--r--core/java/android/service/voice/AlwaysOnHotwordDetector.java236
-rw-r--r--services/voiceinteraction/java/com/android/server/voiceinteraction/SoundTriggerHelper.java18
-rw-r--r--tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionService.java21
5 files changed, 146 insertions, 161 deletions
diff --git a/api/current.txt b/api/current.txt
index 031c6b7..851d20f 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -27493,11 +27493,12 @@ package android.service.voice {
public class AlwaysOnHotwordDetector {
method public android.content.Intent getManageIntent(int);
method public int getSupportedRecognitionModes();
- method public void startRecognition(int);
- method public void stopRecognition();
+ method public boolean startRecognition(int);
+ method public boolean 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
+ field public static final int RECOGNITION_FLAG_ALLOW_MULTIPLE_TRIGGERS = 2; // 0x2
field public static final int RECOGNITION_FLAG_CAPTURE_TRIGGER_AUDIO = 1; // 0x1
field public static final int RECOGNITION_FLAG_NONE = 0; // 0x0
field public static final int RECOGNITION_MODE_USER_IDENTIFICATION = 2; // 0x2
@@ -27510,12 +27511,15 @@ package android.service.voice {
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 onDetected(android.service.voice.AlwaysOnHotwordDetector.TriggerAudio);
method public abstract void onError();
}
+ public static class AlwaysOnHotwordDetector.TriggerAudio {
+ field public final android.media.AudioFormat audioFormat;
+ field public final byte[] data;
+ }
+
public class VoiceInteractionService extends android.app.Service {
ctor public VoiceInteractionService();
method public final android.service.voice.AlwaysOnHotwordDetector createAlwaysOnHotwordDetector(java.lang.String, java.lang.String, android.service.voice.AlwaysOnHotwordDetector.Callback);
diff --git a/core/java/android/hardware/soundtrigger/SoundTrigger.java b/core/java/android/hardware/soundtrigger/SoundTrigger.java
index 4498789..adee740 100644
--- a/core/java/android/hardware/soundtrigger/SoundTrigger.java
+++ b/core/java/android/hardware/soundtrigger/SoundTrigger.java
@@ -524,6 +524,11 @@ public class SoundTrigger {
/** True if the DSP should capture the trigger sound and make it available for further
* capture. */
public final boolean captureRequested;
+ /**
+ * True if the service should restart listening after the DSP triggers.
+ * Note: This config flag is currently used at the service layer rather than by the DSP.
+ */
+ public final boolean allowMultipleTriggers;
/** List of all keyphrases in the sound model for which recognition should be performed with
* options for each keyphrase. */
public final KeyphraseRecognitionExtra keyphrases[];
@@ -531,9 +536,10 @@ public class SoundTrigger {
* typically during enrollment. */
public final byte[] data;
- public RecognitionConfig(boolean captureRequested,
+ public RecognitionConfig(boolean captureRequested, boolean allowMultipleTriggers,
KeyphraseRecognitionExtra keyphrases[], byte[] data) {
this.captureRequested = captureRequested;
+ this.allowMultipleTriggers = allowMultipleTriggers;
this.keyphrases = keyphrases;
this.data = data;
}
@@ -551,15 +557,17 @@ public class SoundTrigger {
private static RecognitionConfig fromParcel(Parcel in) {
boolean captureRequested = in.readByte() == 1;
+ boolean allowMultipleTriggers = in.readByte() == 1;
KeyphraseRecognitionExtra[] keyphrases =
in.createTypedArray(KeyphraseRecognitionExtra.CREATOR);
byte[] data = in.readBlob();
- return new RecognitionConfig(captureRequested, keyphrases, data);
+ return new RecognitionConfig(captureRequested, allowMultipleTriggers, keyphrases, data);
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeByte((byte) (captureRequested ? 1 : 0));
+ dest.writeByte((byte) (allowMultipleTriggers ? 1 : 0));
dest.writeTypedArray(keyphrases, flags);
dest.writeBlob(data);
}
@@ -571,9 +579,9 @@ public class SoundTrigger {
@Override
public String toString() {
- return "RecognitionConfig [captureRequested=" + captureRequested + ", keyphrases="
- + Arrays.toString(keyphrases)
- + ", data=" + (data == null ? 0 : data.length) + "]";
+ return "RecognitionConfig [captureRequested=" + captureRequested
+ + ", allowMultipleTriggers=" + allowMultipleTriggers + ", keyphrases="
+ + Arrays.toString(keyphrases) + ", data=" + Arrays.toString(data) + "]";
}
}
diff --git a/core/java/android/service/voice/AlwaysOnHotwordDetector.java b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
index 5248131..279bf40 100644
--- a/core/java/android/service/voice/AlwaysOnHotwordDetector.java
+++ b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
@@ -16,6 +16,9 @@
package android.service.voice;
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.content.Intent;
import android.hardware.soundtrigger.IRecognitionStatusCallback;
import android.hardware.soundtrigger.KeyphraseEnrollmentInfo;
@@ -27,6 +30,7 @@ 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.media.AudioFormat;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.Message;
@@ -35,6 +39,9 @@ import android.util.Slog;
import com.android.internal.app.IVoiceInteractionManagerService;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
/**
* A class that lets a VoiceInteractionService implementation interact with
* always-on keyphrase detection APIs.
@@ -82,7 +89,17 @@ public class AlwaysOnHotwordDetector {
/** Indicates that we need to un-enroll. */
public static final int MANAGE_ACTION_UN_ENROLL = 2;
- //-- Flags for startRecogntion ----//
+ //-- Flags for startRecognition ----//
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(flag = true,
+ value = {
+ RECOGNITION_FLAG_NONE,
+ RECOGNITION_FLAG_CAPTURE_TRIGGER_AUDIO,
+ RECOGNITION_FLAG_ALLOW_MULTIPLE_TRIGGERS
+ })
+ public @interface RecognitionFlags {}
+
/** Empty flag for {@link #startRecognition(int)}. */
public static final int RECOGNITION_FLAG_NONE = 0;
/**
@@ -90,10 +107,28 @@ public class AlwaysOnHotwordDetector {
* whether the trigger audio for hotword needs to be captured.
*/
public static final int RECOGNITION_FLAG_CAPTURE_TRIGGER_AUDIO = 0x1;
+ /**
+ * Recognition flag for {@link #startRecognition(int)} that indicates
+ * whether the recognition should keep going on even after the keyphrase triggers.
+ * If this flag is specified, it's possible to get multiple triggers after a
+ * call to {@link #startRecognition(int)} if the user speaks the keyphrase multiple times.
+ * When this isn't specified, the default behavior is to stop recognition once the
+ * keyphrase is spoken, till the caller starts recognition again.
+ */
+ public static final int RECOGNITION_FLAG_ALLOW_MULTIPLE_TRIGGERS = 0x2;
//---- Recognition mode flags. Return codes for getSupportedRecognitionModes() ----//
// Must be kept in sync with the related attribute defined as searchKeyphraseRecognitionFlags.
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(flag = true,
+ value = {
+ RECOGNITION_MODE_VOICE_TRIGGER,
+ RECOGNITION_MODE_USER_IDENTIFICATION,
+ })
+ public @interface RecognitionModes {}
+
/**
* Simple recognition of the key phrase.
* Returned by {@link #getSupportedRecognitionModes()}
@@ -114,16 +149,9 @@ public class AlwaysOnHotwordDetector {
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_AVAILABILITY_CHANGED = 1;
private static final int MSG_HOTWORD_DETECTED = 2;
- 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 static final int MSG_DETECTION_ERROR = 3;
private final String mText;
private final String mLocale;
@@ -141,8 +169,27 @@ public class AlwaysOnHotwordDetector {
private final Handler mHandler;
private int mAvailability = STATE_NOT_READY;
- private int mInternalState = 0;
- private int mRecognitionFlags = RECOGNITION_FLAG_NONE;
+
+ /**
+ * Details of the audio that triggered the keyphrase.
+ */
+ public static class TriggerAudio {
+ /**
+ * Format of {@code data}.
+ */
+ @NonNull
+ public final AudioFormat audioFormat;
+ /**
+ * Raw audio data that triggered they keyphrase.
+ */
+ @NonNull
+ public final byte[] data;
+
+ private TriggerAudio(AudioFormat _audioFormat, byte[] _data) {
+ audioFormat = _audioFormat;
+ data = _data;
+ }
+ }
/**
* Callbacks for always-on hotword detection.
@@ -168,22 +215,10 @@ public class AlwaysOnHotwordDetector {
* Clients should start a recognition again once they are done handling this
* detection.
*
- * @param data Optional trigger audio data, if it was requested during
+ * @param triggerAudio 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();
+ void onDetected(@Nullable TriggerAudio triggerAudio);
/**
* Called when the detection fails due to an error.
*/
@@ -228,7 +263,8 @@ public class AlwaysOnHotwordDetector {
* This may happen if another detector has been instantiated or the
* {@link VoiceInteractionService} hosting this detector has been shut down.
*/
- public int getSupportedRecognitionModes() {
+ public @RecognitionModes int getSupportedRecognitionModes() {
+ if (DBG) Slog.d(TAG, "getSupportedRecognitionModes()");
synchronized (mLock) {
return getSupportedRecognitionModesLocked();
}
@@ -254,8 +290,10 @@ public class AlwaysOnHotwordDetector {
* Starts recognition for the associated keyphrase.
*
* @param recognitionFlags The flags to control the recognition properties.
- * The allowed flags are {@link #RECOGNITION_FLAG_NONE} and
- * {@link #RECOGNITION_FLAG_CAPTURE_TRIGGER_AUDIO}.
+ * The allowed flags are {@link #RECOGNITION_FLAG_NONE},
+ * {@link #RECOGNITION_FLAG_CAPTURE_TRIGGER_AUDIO} and
+ * {@link #RECOGNITION_FLAG_ALLOW_MULTIPLE_TRIGGERS}.
+ * @return Indicates whether the call succeeded or not.
* @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.
@@ -263,7 +301,8 @@ public class AlwaysOnHotwordDetector {
* This may happen if another detector has been instantiated or the
* {@link VoiceInteractionService} hosting this detector has been shut down.
*/
- public void startRecognition(int recognitionFlags) {
+ public boolean startRecognition(@RecognitionFlags int recognitionFlags) {
+ if (DBG) Slog.d(TAG, "startRecognition(" + recognitionFlags + ")");
synchronized (mLock) {
if (mAvailability == STATE_INVALID) {
throw new IllegalStateException("startRecognition called on an invalid detector");
@@ -275,15 +314,14 @@ public class AlwaysOnHotwordDetector {
"Recognition for the given keyphrase is not supported");
}
- mInternalState |= FLAG_REQUESTED;
- mRecognitionFlags = recognitionFlags;
- updateRecognitionLocked();
+ return startRecognitionLocked(recognitionFlags) == STATUS_OK;
}
}
/**
* Stops recognition for the associated keyphrase.
*
+ * @return Indicates whether the call succeeded or not.
* @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.
@@ -291,7 +329,8 @@ public class AlwaysOnHotwordDetector {
* This may happen if another detector has been instantiated or the
* {@link VoiceInteractionService} hosting this detector has been shut down.
*/
- public void stopRecognition() {
+ public boolean stopRecognition() {
+ if (DBG) Slog.d(TAG, "stopRecognition()");
synchronized (mLock) {
if (mAvailability == STATE_INVALID) {
throw new IllegalStateException("stopRecognition called on an invalid detector");
@@ -303,9 +342,7 @@ public class AlwaysOnHotwordDetector {
"Recognition for the given keyphrase is not supported");
}
- mInternalState &= ~FLAG_REQUESTED;
- mRecognitionFlags = RECOGNITION_FLAG_NONE;
- updateRecognitionLocked();
+ return stopRecognitionLocked() == STATUS_OK;
}
}
@@ -324,6 +361,7 @@ public class AlwaysOnHotwordDetector {
* {@link VoiceInteractionService} hosting this detector has been shut down.
*/
public Intent getManageIntent(int action) {
+ if (DBG) Slog.d(TAG, "getManageIntent(" + action + ")");
synchronized (mLock) {
return getManageIntentLocked(action);
}
@@ -370,7 +408,7 @@ public class AlwaysOnHotwordDetector {
*/
void onSoundModelsChanged() {
synchronized (mLock) {
- // TODO: This should stop the recognition if it was using an enrolled sound model
+ // FIXME: This should stop the recognition if it was using an enrolled sound model
// that's no longer available.
if (mAvailability == STATE_INVALID
|| mAvailability == STATE_HARDWARE_UNAVAILABLE
@@ -384,87 +422,21 @@ 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) {
- 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) {
- 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() {
+ private int startRecognitionLocked(int recognitionFlags) {
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;
+ (recognitionFlags&RECOGNITION_FLAG_CAPTURE_TRIGGER_AUDIO) != 0;
+ boolean allowMultipleTriggers =
+ (recognitionFlags&RECOGNITION_FLAG_ALLOW_MULTIPLE_TRIGGERS) != 0;
int code = STATUS_ERROR;
try {
code = mModelManagementService.startRecognition(mVoiceInteractionService,
mKeyphraseMetadata.id, mInternalCallback,
- new RecognitionConfig(
- captureTriggerAudio, recognitionExtra, null /* additional data */));
+ new RecognitionConfig(captureTriggerAudio, allowMultipleTriggers,
+ recognitionExtra, null /* additional data */));
} catch (RemoteException e) {
Slog.w(TAG, "RemoteException in startRecognition!");
}
@@ -490,7 +462,7 @@ public class AlwaysOnHotwordDetector {
}
private void notifyStateChangedLocked() {
- Message message = Message.obtain(mHandler, MSG_STATE_CHANGED);
+ Message message = Message.obtain(mHandler, MSG_AVAILABILITY_CHANGED);
message.arg1 = mAvailability;
message.sendToTarget();
}
@@ -505,9 +477,22 @@ public class AlwaysOnHotwordDetector {
@Override
public void onDetected(KeyphraseRecognitionEvent event) {
- Slog.i(TAG, "onDetected");
+ if (DBG) {
+ Slog.d(TAG, "OnDetected(" + event + ")");
+ } else {
+ Slog.i(TAG, "onDetected");
+ }
Message message = Message.obtain(mHandler, MSG_HOTWORD_DETECTED);
- message.obj = event.data;
+ // FIXME: Check whether the event contains trigger data or not.
+ // FIXME: Read the audio format from the event.
+ if (event.data != null) {
+ AudioFormat audioFormat = new AudioFormat.Builder()
+ .setChannelMask(AudioFormat.CHANNEL_IN_MONO)
+ .setEncoding(AudioFormat.ENCODING_PCM_16BIT)
+ .setSampleRate(16000)
+ .build();
+ message.obj = new TriggerAudio(audioFormat, event.data);
+ }
message.sendToTarget();
}
@@ -529,34 +514,13 @@ public class AlwaysOnHotwordDetector {
}
switch (msg.what) {
- case MSG_STATE_CHANGED:
+ case MSG_AVAILABILITY_CHANGED:
mExternalCallback.onAvailabilityChanged(msg.arg1);
break;
case MSG_HOTWORD_DETECTED:
- synchronized (mLock) {
- mInternalState &= ~FLAG_REQUESTED;
- mInternalState &= ~FLAG_STARTED;
- }
- mExternalCallback.onDetected((byte[]) msg.obj);
- break;
- case MSG_DETECTION_STARTED:
- synchronized (mLock) {
- mInternalState |= FLAG_STARTED;
- }
- mExternalCallback.onDetectionStarted();
- break;
- case MSG_DETECTION_STOPPED:
- synchronized (mLock) {
- mInternalState &= ~FLAG_REQUESTED;
- mInternalState &= ~FLAG_STARTED;
- }
- mExternalCallback.onDetectionStopped();
+ mExternalCallback.onDetected((TriggerAudio) msg.obj);
break;
case MSG_DETECTION_ERROR:
- synchronized (mLock) {
- mInternalState &= ~FLAG_REQUESTED;
- mInternalState &= ~FLAG_STARTED;
- }
mExternalCallback.onError();
break;
default:
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/SoundTriggerHelper.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/SoundTriggerHelper.java
index 0eac1c4..938efaa 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/SoundTriggerHelper.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/SoundTriggerHelper.java
@@ -65,6 +65,8 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
private int mCurrentSoundModelHandle = INVALID_SOUND_MODEL_HANDLE;
private UUID mCurrentSoundModelUuid = null;
+ // FIXME: Ideally this should not be stored if allowMultipleTriggers happens at a lower layer.
+ private RecognitionConfig mRecognitionConfig = null;
SoundTriggerHelper() {
ArrayList <ModuleProperties> modules = new ArrayList<>();
@@ -174,6 +176,7 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
// Everything went well!
mCurrentSoundModelHandle = soundModelHandle;
mCurrentSoundModelUuid = soundModel.uuid;
+ mRecognitionConfig = recognitionConfig;
// Register the new listener. This replaces the old one.
// There can only be a maximum of one active listener for a keyphrase
// at any given time.
@@ -221,12 +224,12 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
int status = mModule.stopRecognition(mCurrentSoundModelHandle);
if (status != SoundTrigger.STATUS_OK) {
Slog.w(TAG, "stopRecognition call failed with " + status);
- return STATUS_ERROR;
+ return status;
}
status = mModule.unloadSoundModel(mCurrentSoundModelHandle);
if (status != SoundTrigger.STATUS_OK) {
Slog.w(TAG, "unloadSoundModel call failed with " + status);
- return STATUS_ERROR;
+ return status;
}
mCurrentSoundModelHandle = INVALID_SOUND_MODEL_HANDLE;
@@ -284,6 +287,17 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
Slog.w(TAG, "received onRecognition event without any listener for it");
return;
}
+
+ // FIXME: Remove this block if the lower layer supports multiple triggers.
+ if (mRecognitionConfig != null
+ && mRecognitionConfig.allowMultipleTriggers) {
+ int status = mModule.startRecognition(
+ mCurrentSoundModelHandle, mRecognitionConfig);
+ if (status != STATUS_OK) {
+ Slog.w(TAG, "Error in restarting recognition after a trigger");
+ listener.onError(status);
+ }
+ }
}
} catch (RemoteException e) {
Slog.w(TAG, "RemoteException in onDetectionStopped");
diff --git a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionService.java b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionService.java
index b43ad6f..02610f8 100644
--- a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionService.java
+++ b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionService.java
@@ -20,6 +20,7 @@ import android.content.Intent;
import android.os.Bundle;
import android.service.voice.AlwaysOnHotwordDetector;
import android.service.voice.AlwaysOnHotwordDetector.Callback;
+import android.service.voice.AlwaysOnHotwordDetector.TriggerAudio;
import android.service.voice.VoiceInteractionService;
import android.util.Log;
@@ -36,21 +37,11 @@ public class MainInteractionService extends VoiceInteractionService {
}
@Override
- public void onDetected(byte[] data) {
+ public void onDetected(TriggerAudio triggerAudio) {
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");
}
@@ -95,8 +86,12 @@ public class MainInteractionService extends VoiceInteractionService {
break;
case AlwaysOnHotwordDetector.STATE_KEYPHRASE_ENROLLED:
Log.i(TAG, "STATE_KEYPHRASE_ENROLLED - starting recognition");
- mHotwordDetector.startRecognition(
- AlwaysOnHotwordDetector.RECOGNITION_FLAG_NONE);
+ if (mHotwordDetector.startRecognition(
+ AlwaysOnHotwordDetector.RECOGNITION_FLAG_NONE)) {
+ Log.i(TAG, "startRecognition succeeded");
+ } else {
+ Log.i(TAG, "startRecognition failed");
+ }
break;
}
}