diff options
author | Sandeep Siddhartha <sansid@google.com> | 2014-07-21 10:31:34 -0700 |
---|---|---|
committer | Sandeep Siddhartha <sansid@google.com> | 2014-07-22 09:16:18 -0700 |
commit | 6daae9622672e0b38fc2efed29f68061d749cacc (patch) | |
tree | 94943fab0e4ab27952fffb07141456cfec65fbed | |
parent | 70441467f4dc232cd8e6142f0afc117787dc979b (diff) | |
download | frameworks_base-6daae9622672e0b38fc2efed29f68061d749cacc.zip frameworks_base-6daae9622672e0b38fc2efed29f68061d749cacc.tar.gz frameworks_base-6daae9622672e0b38fc2efed29f68061d749cacc.tar.bz2 |
AlwaysOnHotwordDetector needs to reflect enrollment changes
Add a callback for when any sound model change happens. This helps the VIS
to re-check the availability and either enroll the user, or start/stop recognition.
Also shut down any active recognition when VIS dies, or a different hotword detector instance is obtained from VIS.
Change-Id: I03f94e78c6ee307afe822a84aebc7e74c64de7b4
7 files changed, 247 insertions, 79 deletions
diff --git a/api/current.txt b/api/current.txt index cb54a5f..863a88b 100644 --- a/api/current.txt +++ b/api/current.txt @@ -27324,10 +27324,6 @@ package android.service.voice { method public int getSupportedRecognitionModes(); method public int startRecognition(int); method public int stopRecognition(); - field public static final int KEYPHRASE_ENROLLED = 2; // 0x2 - field public static final int KEYPHRASE_HARDWARE_UNAVAILABLE = -2; // 0xfffffffe - field public static final int KEYPHRASE_UNENROLLED = 1; // 0x1 - field public static final int KEYPHRASE_UNSUPPORTED = -1; // 0xffffffff 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 @@ -27335,6 +27331,11 @@ package android.service.voice { field public static final int RECOGNITION_FLAG_NONE = 0; // 0x0 field public static final int RECOGNITION_MODE_USER_IDENTIFICATION = 2; // 0x2 field public static final int RECOGNITION_MODE_VOICE_TRIGGER = 1; // 0x1 + field public static final int STATE_HARDWARE_UNAVAILABLE = -2; // 0xfffffffe + field public static final int STATE_INVALID = -3; // 0xfffffffd + 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 } @@ -27346,10 +27347,12 @@ package android.service.voice { public class VoiceInteractionService extends android.app.Service { ctor public VoiceInteractionService(); - method public final android.service.voice.AlwaysOnHotwordDetector getAlwaysOnHotwordDetector(java.lang.String, java.lang.String, android.service.voice.AlwaysOnHotwordDetector.Callback); + method public final android.service.voice.AlwaysOnHotwordDetector createAlwaysOnHotwordDetector(java.lang.String, java.lang.String, android.service.voice.AlwaysOnHotwordDetector.Callback); method public static boolean isActiveService(android.content.Context, android.content.ComponentName); method public android.os.IBinder onBind(android.content.Intent); method public void onReady(); + method public void onShutdown(); + method public void onSoundModelsChanged(); method public void startSession(android.os.Bundle); field public static final java.lang.String SERVICE_INTERFACE = "android.service.voice.VoiceInteractionService"; field public static final java.lang.String SERVICE_META_DATA = "android.voice_interaction"; diff --git a/core/java/android/service/voice/AlwaysOnHotwordDetector.java b/core/java/android/service/voice/AlwaysOnHotwordDetector.java index ad30f44..27a7b8e 100644 --- a/core/java/android/service/voice/AlwaysOnHotwordDetector.java +++ b/core/java/android/service/voice/AlwaysOnHotwordDetector.java @@ -41,26 +41,32 @@ import java.util.List; * always-on keyphrase detection APIs. */ public class AlwaysOnHotwordDetector { - //---- States of Keyphrase availability ----// + //---- States of Keyphrase availability. Return codes for getAvailability() ----// /** - * Indicates that the given keyphrase is not available on the system because of the - * hardware configuration. + * Indicates that this hotword detector is no longer valid for any recognition + * and should not be used anymore. */ - public static final int KEYPHRASE_HARDWARE_UNAVAILABLE = -2; + public static final int STATE_INVALID = -3; /** - * Indicates that the given keyphrase is not supported. + * Indicates that recognition for the given keyphrase is not available on the system + * because of the hardware configuration. */ - public static final int KEYPHRASE_UNSUPPORTED = -1; + public static final int STATE_HARDWARE_UNAVAILABLE = -2; + /** + * Indicates that recognition for the given keyphrase is not supported. + */ + public static final int STATE_KEYPHRASE_UNSUPPORTED = -1; /** * Indicates that the given keyphrase is not enrolled. */ - public static final int KEYPHRASE_UNENROLLED = 1; + public static final int STATE_KEYPHRASE_UNENROLLED = 1; /** - * Indicates that the given keyphrase is currently enrolled but not being actively listened for. + * Indicates that the given keyphrase is currently enrolled and it's possible to start + * recognition for it. */ - public static final int KEYPHRASE_ENROLLED = 2; + public static final int STATE_KEYPHRASE_ENROLLED = 2; - // Keyphrase management actions ----// + // Keyphrase management actions. Used in getManageIntent() ----// /** Indicates that we need to enroll. */ public static final int MANAGE_ACTION_ENROLL = 0; /** Indicates that we need to re-enroll. */ @@ -83,7 +89,7 @@ public class AlwaysOnHotwordDetector { */ public static final int RECOGNITION_FLAG_CAPTURE_TRIGGER_AUDIO = 0x1; - //---- Recognition mode flags ----// + //---- Recognition mode flags. Return codes for getSupportedRecognitionModes() ----// // Must be kept in sync with the related attribute defined as searchKeyphraseRecognitionFlags. /** @@ -109,17 +115,20 @@ public class AlwaysOnHotwordDetector { * This may be null if this keyphrase isn't supported by the enrollment application. */ private final KeyphraseMetadata mKeyphraseMetadata; - /** - * The sound model for the keyphrase, derived from the model management service - * (IVoiceInteractionManagerService). May be null if the keyphrase isn't enrolled yet. - */ - private final KeyphraseSoundModel mEnrolledSoundModel; private final KeyphraseEnrollmentInfo mKeyphraseEnrollmentInfo; private final IVoiceInteractionService mVoiceInteractionService; private final IVoiceInteractionManagerService mModelManagementService; private final SoundTriggerListener mInternalCallback; private final Callback mExternalCallback; private final boolean mDisabled; + private final Object mLock = new Object(); + + /** + * The sound model for the keyphrase, derived from the model management service + * (IVoiceInteractionManagerService). May be null if the keyphrase isn't enrolled yet. + */ + private KeyphraseSoundModel mEnrolledSoundModel; + private boolean mInvalidated; /** * Callbacks for always-on hotword detection. @@ -151,6 +160,7 @@ public class AlwaysOnHotwordDetector { KeyphraseEnrollmentInfo keyphraseEnrollmentInfo, IVoiceInteractionService voiceInteractionService, IVoiceInteractionManagerService modelManagementService) { + mInvalidated = false; mText = text; mLocale = locale; mKeyphraseEnrollmentInfo = keyphraseEnrollmentInfo; @@ -160,28 +170,34 @@ public class AlwaysOnHotwordDetector { mVoiceInteractionService = voiceInteractionService; mModelManagementService = modelManagementService; if (mKeyphraseMetadata != null) { - mEnrolledSoundModel = internalGetKeyphraseSoundModel(mKeyphraseMetadata.id); - } else { - mEnrolledSoundModel = null; + mEnrolledSoundModel = internalGetKeyphraseSoundModelLocked(mKeyphraseMetadata.id); } int initialAvailability = internalGetAvailabilityLocked(); - mDisabled = (initialAvailability == KEYPHRASE_HARDWARE_UNAVAILABLE) - || (initialAvailability == KEYPHRASE_UNSUPPORTED); + mDisabled = (initialAvailability == STATE_HARDWARE_UNAVAILABLE) + || (initialAvailability == STATE_KEYPHRASE_UNSUPPORTED); } /** * Gets the state of always-on hotword detection for the given keyphrase and locale * on this system. * Availability implies that the hardware on this system is capable of listening for - * the given keyphrase or not. + * the given keyphrase or not. <p/> + * If the return code is one of {@link #STATE_HARDWARE_UNAVAILABLE} or + * {@link #STATE_KEYPHRASE_UNSUPPORTED}, no further interaction should be performed with this + * detector. <br/> + * If the state is {@link #STATE_KEYPHRASE_UNENROLLED} the caller may choose to begin + * an enrollment flow for the keyphrase. <br/> + * For {@value #STATE_KEYPHRASE_ENROLLED} a recognition can be started as desired. <br/> + * If the return code is {@link #STATE_INVALID}, this detector is stale and must not be used. + * A new detector should be obtained and used. * * @return Indicates if always-on hotword detection is available for the given keyphrase. - * The return code is one of {@link #KEYPHRASE_HARDWARE_UNAVAILABLE}, - * {@link #KEYPHRASE_UNSUPPORTED}, {@link #KEYPHRASE_UNENROLLED} or - * {@link #KEYPHRASE_ENROLLED}. + * The return code is one of {@link #STATE_HARDWARE_UNAVAILABLE}, + * {@link #STATE_KEYPHRASE_UNSUPPORTED}, {@link #STATE_KEYPHRASE_UNENROLLED}, + * {@link #STATE_KEYPHRASE_ENROLLED}, or {@link #STATE_INVALID}. */ public int getAvailability() { - synchronized (this) { + synchronized (mLock) { return internalGetAvailabilityLocked(); } } @@ -194,7 +210,7 @@ public class AlwaysOnHotwordDetector { * before calling this method to avoid this exception. */ public int getSupportedRecognitionModes() { - synchronized (this) { + synchronized (mLock) { return getSupportedRecognitionModesLocked(); } } @@ -220,13 +236,13 @@ public class AlwaysOnHotwordDetector { * before calling this method to avoid this exception. */ public int startRecognition(int recognitionFlags) { - synchronized (this) { + synchronized (mLock) { return startRecognitionLocked(recognitionFlags); } } private int startRecognitionLocked(int recognitionFlags) { - if (internalGetAvailabilityLocked() != KEYPHRASE_ENROLLED) { + if (internalGetAvailabilityLocked() != STATE_KEYPHRASE_ENROLLED) { throw new UnsupportedOperationException( "Recognition for the given keyphrase is not supported"); } @@ -261,13 +277,13 @@ public class AlwaysOnHotwordDetector { * before calling this method to avoid this exception. */ public int stopRecognition() { - synchronized (this) { + synchronized (mLock) { return stopRecognitionLocked(); } } - private synchronized int stopRecognitionLocked() { - if (internalGetAvailabilityLocked() != KEYPHRASE_ENROLLED) { + private int stopRecognitionLocked() { + if (internalGetAvailabilityLocked() != STATE_KEYPHRASE_ENROLLED) { throw new UnsupportedOperationException( "Recognition for the given keyphrase is not supported"); } @@ -312,6 +328,10 @@ public class AlwaysOnHotwordDetector { } private int internalGetAvailabilityLocked() { + if (mInvalidated) { + return STATE_INVALID; + } + ModuleProperties dspModuleProperties = null; try { dspModuleProperties = @@ -321,23 +341,51 @@ public class AlwaysOnHotwordDetector { } // No DSP available if (dspModuleProperties == null) { - return KEYPHRASE_HARDWARE_UNAVAILABLE; + return STATE_HARDWARE_UNAVAILABLE; } // No enrollment application supports this keyphrase/locale if (mKeyphraseMetadata == null) { - return KEYPHRASE_UNSUPPORTED; + return STATE_KEYPHRASE_UNSUPPORTED; } + // This keyphrase hasn't been enrolled. if (mEnrolledSoundModel == null) { - return KEYPHRASE_UNENROLLED; + return STATE_KEYPHRASE_UNENROLLED; + } + return STATE_KEYPHRASE_ENROLLED; + } + + /** + * Invalidates this hotword detector so that any future calls to this result + * in an IllegalStateException. + * + * @hide + */ + void invalidate() { + synchronized (mLock) { + mInvalidated = true; + } + } + + /** + * Reloads the sound models from the service. + * + * @hide + */ + void onSoundModelsChanged() { + synchronized (mLock) { + // TODO: This should stop the recognition if it was using an enrolled sound model + // that's no longer available. + if (mKeyphraseMetadata != null) { + mEnrolledSoundModel = internalGetKeyphraseSoundModelLocked(mKeyphraseMetadata.id); + } } - return KEYPHRASE_ENROLLED; } /** * @return The corresponding {@link KeyphraseSoundModel} or null if none is found. */ - private KeyphraseSoundModel internalGetKeyphraseSoundModel(int keyphraseId) { + private KeyphraseSoundModel internalGetKeyphraseSoundModelLocked(int keyphraseId) { List<KeyphraseSoundModel> soundModels; try { soundModels = mModelManagementService diff --git a/core/java/android/service/voice/IVoiceInteractionService.aidl b/core/java/android/service/voice/IVoiceInteractionService.aidl index c9915a2..e8265a2 100644 --- a/core/java/android/service/voice/IVoiceInteractionService.aidl +++ b/core/java/android/service/voice/IVoiceInteractionService.aidl @@ -21,4 +21,6 @@ package android.service.voice; */ oneway interface IVoiceInteractionService { void ready(); + void soundModelsChanged(); + void shutdown(); } diff --git a/core/java/android/service/voice/VoiceInteractionService.java b/core/java/android/service/voice/VoiceInteractionService.java index 982f43d..0c2ba26 100644 --- a/core/java/android/service/voice/VoiceInteractionService.java +++ b/core/java/android/service/voice/VoiceInteractionService.java @@ -28,8 +28,8 @@ import android.os.IBinder; import android.os.Message; import android.os.RemoteException; import android.os.ServiceManager; - import android.provider.Settings; + import com.android.internal.annotations.VisibleForTesting; import com.android.internal.app.IVoiceInteractionManagerService; @@ -70,15 +70,27 @@ public class VoiceInteractionService extends Service { @Override public void ready() { mHandler.sendEmptyMessage(MSG_READY); } + @Override public void shutdown() { + mHandler.sendEmptyMessage(MSG_SHUTDOWN); + } + @Override public void soundModelsChanged() { + mHandler.sendEmptyMessage(MSG_SOUND_MODELS_CHANGED); + } }; MyHandler mHandler; IVoiceInteractionManagerService mSystemService; + private final Object mLock = new Object(); + private KeyphraseEnrollmentInfo mKeyphraseEnrollmentInfo; + private AlwaysOnHotwordDetector mHotwordDetector; + static final int MSG_READY = 1; + static final int MSG_SHUTDOWN = 2; + static final int MSG_SOUND_MODELS_CHANGED = 3; class MyHandler extends Handler { @Override @@ -87,6 +99,12 @@ public class VoiceInteractionService extends Service { case MSG_READY: onReady(); break; + case MSG_SHUTDOWN: + onShutdownInternal(); + break; + case MSG_SOUND_MODELS_CHANGED: + onSoundModelsChangedInternal(); + break; default: super.handleMessage(msg); } @@ -140,9 +158,10 @@ public class VoiceInteractionService extends Service { /** * Called during service initialization to tell you when the system is ready - * to receive interaction from it. You should generally do initialization here - * rather than in {@link #onCreate()}. Methods such as {@link #startSession} - * and {@link #getAlwaysOnHotwordDetector} will not be operational until this point. + * to receive interaction from it. You should generally do initialization here + * rather than in {@link #onCreate()}. Methods such as {@link #startSession(Bundle)} and + * {@link #createAlwaysOnHotwordDetector(String, String, android.service.voice.AlwaysOnHotwordDetector.Callback)} + * will not be operational until this point. */ public void onReady() { mSystemService = IVoiceInteractionManagerService.Stub.asInterface( @@ -150,22 +169,67 @@ public class VoiceInteractionService extends Service { mKeyphraseEnrollmentInfo = new KeyphraseEnrollmentInfo(getPackageManager()); } + private void onShutdownInternal() { + onShutdown(); + // Stop any active recognitions when shutting down. + // This ensures that if implementations forget to stop any active recognition, + // It's still guaranteed to have been stopped. + // This helps with cases where the voice interaction implementation is changed + // by the user. + safelyShutdownHotwordDetector(); + } + + /** + * Called during service de-initialization to tell you when the system is shutting the + * service down. + */ + public void onShutdown() { + } + + private void onSoundModelsChangedInternal() { + synchronized (this) { + if (mHotwordDetector != null) { + // TODO: Stop recognition if a sound model that was being recognized gets deleted. + mHotwordDetector.onSoundModelsChanged(); + } + } + onSoundModelsChanged(); + } + + /** + * Called when the sound models available for recognition change. + * This may be called if a new sound model is available or + * an existing one is updated or removed. + * Implementations must check the availability of the hotword detector if they own one + * by calling {@link AlwaysOnHotwordDetector#getAvailability()} before calling into it. + */ + public void onSoundModelsChanged() { + } + /** + * Creates an {@link AlwaysOnHotwordDetector} for the given keyphrase and locale. + * This instance must be retained and used by the client. + * Calling this a second time invalidates the previously created hotword detector + * which can no longer be used to manage recognition. + * * @param keyphrase The keyphrase that's being used, for example "Hello Android". * @param locale The locale for which the enrollment needs to be performed. * This is a Java locale, for example "en_US". * @param callback The callback to notify of detection events. * @return An always-on hotword detector for the given keyphrase and locale. */ - public final AlwaysOnHotwordDetector getAlwaysOnHotwordDetector( + public final AlwaysOnHotwordDetector createAlwaysOnHotwordDetector( String keyphrase, String locale, AlwaysOnHotwordDetector.Callback callback) { if (mSystemService == null) { throw new IllegalStateException("Not available until onReady() is called"); } - // TODO: Cache instances and return the same one instead of creating a new interactor - // for the same keyphrase/locale combination. - return new AlwaysOnHotwordDetector(keyphrase, locale, callback, - mKeyphraseEnrollmentInfo, mInterface, mSystemService); + synchronized (mLock) { + // Allow only one concurrent recognition via the APIs. + safelyShutdownHotwordDetector(); + mHotwordDetector = new AlwaysOnHotwordDetector(keyphrase, locale, callback, + mKeyphraseEnrollmentInfo, mInterface, mSystemService); + } + return mHotwordDetector; } /** @@ -176,4 +240,18 @@ public class VoiceInteractionService extends Service { protected final KeyphraseEnrollmentInfo getKeyphraseEnrollmentInfo() { return mKeyphraseEnrollmentInfo; } + + private void safelyShutdownHotwordDetector() { + try { + synchronized (mLock) { + if (mHotwordDetector != null) { + mHotwordDetector.stopRecognition(); + mHotwordDetector.invalidate(); + mHotwordDetector = null; + } + } + } catch (Exception ex) { + // Ignore. + } + } } diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java index 2ce4971..7b2e4f1 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java @@ -290,19 +290,22 @@ public class VoiceInteractionManagerService extends SystemService { final long caller = Binder.clearCallingIdentity(); try { - // If the keyphrases are not present in the model, delete the model. + boolean success = false; if (model.keyphrases == null) { - if (mDbHelper.deleteKeyphraseSoundModel(model.uuid)) { - return SoundTriggerHelper.STATUS_OK; - } else { - return SoundTriggerHelper.STATUS_ERROR; - } + // If the keyphrases are not present in the model, delete the model. + success = mDbHelper.deleteKeyphraseSoundModel(model.uuid); } else { - if (mDbHelper.addOrUpdateKeyphraseSoundModel(model)) { - return SoundTriggerHelper.STATUS_OK; - } else { - return SoundTriggerHelper.STATUS_ERROR; + // Else update the model. + success = mDbHelper.addOrUpdateKeyphraseSoundModel(model); + } + if (success) { + // Notify the voice interaction service of a change in sound models. + if (mImpl != null && mImpl.mService != null) { + mImpl.notifySoundModelsChangedLocked(); } + return SoundTriggerHelper.STATUS_OK; + } else { + return SoundTriggerHelper.STATUS_ERROR; } } finally { Binder.restoreCallingIdentity(caller); diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java index 54af5d4..94f227c 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java @@ -96,6 +96,13 @@ class VoiceInteractionManagerServiceImpl { @Override public void onServiceDisconnected(ComponentName name) { + try { + if (mService != null) { + mService.shutdown(); + } + } catch (RemoteException e) { + Slog.w(TAG, "RemoteException in shutdown", e); + } mService = null; } }; @@ -308,4 +315,15 @@ class VoiceInteractionManagerServiceImpl { mContext.unregisterReceiver(mBroadcastReceiver); } } + + void notifySoundModelsChangedLocked() { + if (mService == null) { + Slog.w(TAG, "Not bound to voice interaction service " + mComponent); + } + try { + mService.soundModelsChanged(); + } catch (RemoteException e) { + Slog.w(TAG, "RemoteException while calling soundModelsChanged", e); + } + } } diff --git a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionService.java b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionService.java index e74307f..e750bb6 100644 --- a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionService.java +++ b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionService.java @@ -50,38 +50,54 @@ public class MainInteractionService extends VoiceInteractionService { Log.i(TAG, "Keyphrase enrollment meta-data: " + Arrays.toString(getKeyphraseEnrollmentInfo().listKeyphraseMetadata())); - mHotwordDetector = getAlwaysOnHotwordDetector("Hello There", "en-US", mHotwordCallback); + mHotwordDetector = createAlwaysOnHotwordDetector("Hello There", "en-US", mHotwordCallback); + testHotwordAvailabilityStates(); + } + + @Override + public void onSoundModelsChanged() { int availability = mHotwordDetector.getAvailability(); Log.i(TAG, "Hotword availability = " + availability); + if (availability == AlwaysOnHotwordDetector.STATE_INVALID) { + mHotwordDetector = createAlwaysOnHotwordDetector("Hello There", "en-US", mHotwordCallback); + } + testHotwordAvailabilityStates(); + } + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + Bundle args = new Bundle(); + args.putParcelable("intent", new Intent(this, TestInteractionActivity.class)); + startSession(args); + stopSelf(startId); + return START_NOT_STICKY; + } + private void testHotwordAvailabilityStates() { + int availability = mHotwordDetector.getAvailability(); + Log.i(TAG, "Hotword availability = " + availability); switch (availability) { - case AlwaysOnHotwordDetector.KEYPHRASE_HARDWARE_UNAVAILABLE: - Log.i(TAG, "KEYPHRASE_HARDWARE_UNAVAILABLE"); + case AlwaysOnHotwordDetector.STATE_INVALID: + Log.i(TAG, "STATE_INVALID"); + break; + case AlwaysOnHotwordDetector.STATE_HARDWARE_UNAVAILABLE: + Log.i(TAG, "STATE_HARDWARE_UNAVAILABLE"); break; - case AlwaysOnHotwordDetector.KEYPHRASE_UNSUPPORTED: - Log.i(TAG, "KEYPHRASE_UNSUPPORTED"); + case AlwaysOnHotwordDetector.STATE_KEYPHRASE_UNSUPPORTED: + Log.i(TAG, "STATE_KEYPHRASE_UNSUPPORTED"); break; - case AlwaysOnHotwordDetector.KEYPHRASE_UNENROLLED: - Log.i(TAG, "KEYPHRASE_UNENROLLED"); + case AlwaysOnHotwordDetector.STATE_KEYPHRASE_UNENROLLED: + Log.i(TAG, "STATE_KEYPHRASE_UNENROLLED"); Intent enroll = mHotwordDetector.getManageIntent( AlwaysOnHotwordDetector.MANAGE_ACTION_ENROLL); Log.i(TAG, "Need to enroll with " + enroll); break; - case AlwaysOnHotwordDetector.KEYPHRASE_ENROLLED: - Log.i(TAG, "KEYPHRASE_ENROLLED"); + case AlwaysOnHotwordDetector.STATE_KEYPHRASE_ENROLLED: + Log.i(TAG, "STATE_KEYPHRASE_ENROLLED"); int status = mHotwordDetector.startRecognition( AlwaysOnHotwordDetector.RECOGNITION_FLAG_NONE); Log.i(TAG, "startRecognition status = " + status); break; } } - - @Override - public int onStartCommand(Intent intent, int flags, int startId) { - Bundle args = new Bundle(); - args.putParcelable("intent", new Intent(this, TestInteractionActivity.class)); - startSession(args); - stopSelf(startId); - return START_NOT_STICKY; - } } |