diff options
author | Sandeep Siddhartha <sansid@google.com> | 2014-07-10 19:38:18 -0700 |
---|---|---|
committer | Sandeep Siddhartha <sansid@google.com> | 2014-07-15 18:36:09 -0700 |
commit | 8ecaf5f5cfd18e0436db1a27ccf46a063e9aacd7 (patch) | |
tree | b786dc7534b41760f8330e9cecd84a6e8e65c3d5 /core/java/android/hardware/soundtrigger | |
parent | d1f113d0f0ce5099f8efba40a88398f7945bb5e0 (diff) | |
download | frameworks_base-8ecaf5f5cfd18e0436db1a27ccf46a063e9aacd7.zip frameworks_base-8ecaf5f5cfd18e0436db1a27ccf46a063e9aacd7.tar.gz frameworks_base-8ecaf5f5cfd18e0436db1a27ccf46a063e9aacd7.tar.bz2 |
Hook in startRecogniton call
Add required info to the sound model database: users & recognition modes
Change-Id: I6e12cbc6342a2767c0e3d8328c0a3be899ac9952
Diffstat (limited to 'core/java/android/hardware/soundtrigger')
4 files changed, 123 insertions, 53 deletions
diff --git a/core/java/android/hardware/soundtrigger/Keyphrase.java b/core/java/android/hardware/soundtrigger/Keyphrase.java index 42fd350..51311bb 100644 --- a/core/java/android/hardware/soundtrigger/Keyphrase.java +++ b/core/java/android/hardware/soundtrigger/Keyphrase.java @@ -30,7 +30,11 @@ public class Keyphrase implements Parcelable { /** A hint text to display corresponding to this keyphrase, e.g. "Hello There". */ public final String hintText; /** The locale of interest when using this Keyphrase. */ - public String locale; + public final String locale; + /** The various recognition modes supported by this keyphrase */ + public final int recognitionModeFlags; + /** The users associated with this keyphrase */ + public final int[] users; public static final Parcelable.Creator<Keyphrase> CREATOR = new Parcelable.Creator<Keyphrase>() { @@ -44,13 +48,26 @@ public class Keyphrase implements Parcelable { }; private static Keyphrase fromParcel(Parcel in) { - return new Keyphrase(in.readInt(), in.readString(), in.readString()); + int id = in.readInt(); + String hintText = in.readString(); + String locale = in.readString(); + int recognitionModeFlags = in.readInt(); + int numUsers = in.readInt(); + int[] users = null; + if (numUsers > 0) { + users = new int[numUsers]; + in.readIntArray(users); + } + return new Keyphrase(id, hintText, locale, recognitionModeFlags, users); } - public Keyphrase(int id, String hintText, String locale) { + public Keyphrase(int id, String hintText, String locale, int recognitionModeFlags, + int[] users) { this.id = id; this.hintText = hintText; this.locale = locale; + this.recognitionModeFlags = recognitionModeFlags; + this.users = users; } @Override @@ -58,6 +75,13 @@ public class Keyphrase implements Parcelable { dest.writeInt(id); dest.writeString(hintText); dest.writeString(locale); + dest.writeInt(recognitionModeFlags); + if (users != null) { + dest.writeInt(users.length); + dest.writeIntArray(users); + } else { + dest.writeInt(0); + } } @Override @@ -98,4 +122,14 @@ public class Keyphrase implements Parcelable { return false; return true; } + + @Override + public String toString() { + return "Keyphrase[id=" + id + ", text=" + hintText + ", locale=" + locale + + ", recognitionModes=" + recognitionModeFlags + "]"; + } + + protected SoundTrigger.Keyphrase convertToSoundTriggerKeyphrase() { + return new SoundTrigger.Keyphrase(id, recognitionModeFlags, locale, hintText, users); + } } diff --git a/core/java/android/hardware/soundtrigger/KeyphraseEnrollmentInfo.java b/core/java/android/hardware/soundtrigger/KeyphraseEnrollmentInfo.java index 2f5de6a..c74134a 100644 --- a/core/java/android/hardware/soundtrigger/KeyphraseEnrollmentInfo.java +++ b/core/java/android/hardware/soundtrigger/KeyphraseEnrollmentInfo.java @@ -239,7 +239,8 @@ public class KeyphraseEnrollmentInfo { * @param keyphrase The keyphrase that the user needs to be enrolled to. * @param locale The locale for which the enrollment needs to be performed. * This is a Java locale, for example "en_US". - * @return true, if an enrollment client supports the given keyphrase and the given locale. + * @return The metadata, if an enrollment client supports the given keyphrase + * and the given locale, null otherwise. */ public KeyphraseMetadata getKeyphraseMetadata(String keyphrase, String locale) { if (mKeyphrases == null || mKeyphrases.length == 0) { diff --git a/core/java/android/hardware/soundtrigger/KeyphraseSoundModel.java b/core/java/android/hardware/soundtrigger/KeyphraseSoundModel.java index 4ddba6a..a5ab0d2 100644 --- a/core/java/android/hardware/soundtrigger/KeyphraseSoundModel.java +++ b/core/java/android/hardware/soundtrigger/KeyphraseSoundModel.java @@ -65,4 +65,15 @@ public class KeyphraseSoundModel implements Parcelable { } dest.writeParcelableArray(keyphrases, 0); } + + public SoundTrigger.KeyphraseSoundModel convertToSoundTriggerKeyphraseSoundModel() { + SoundTrigger.Keyphrase[] stKeyphrases = null; + if (keyphrases != null) { + stKeyphrases = new SoundTrigger.Keyphrase[keyphrases.length]; + for (int i = 0; i < keyphrases.length; i++) { + stKeyphrases[i] = keyphrases[i].convertToSoundTriggerKeyphrase(); + } + } + return new SoundTrigger.KeyphraseSoundModel(uuid, data, stKeyphrases); + } } diff --git a/core/java/android/hardware/soundtrigger/SoundTriggerHelper.java b/core/java/android/hardware/soundtrigger/SoundTriggerHelper.java index 0be068d..3659621 100644 --- a/core/java/android/hardware/soundtrigger/SoundTriggerHelper.java +++ b/core/java/android/hardware/soundtrigger/SoundTriggerHelper.java @@ -17,6 +17,7 @@ package android.hardware.soundtrigger; import android.hardware.soundtrigger.SoundTrigger.ModuleProperties; +import android.hardware.soundtrigger.SoundTrigger.RecognitionConfig; import android.hardware.soundtrigger.SoundTrigger.RecognitionEvent; import android.util.Slog; import android.util.SparseArray; @@ -56,7 +57,7 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { private final ModuleProperties mModuleProperties; private final SoundTriggerModule mModule; - private final SparseArray<Listener> mListeners; + private final SparseArray<Listener> mActiveListeners; private int mCurrentSoundModelHandle = INVALID_SOUND_MODEL_HANDLE; @@ -77,7 +78,7 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { public SoundTriggerHelper() { ArrayList <ModuleProperties> modules = new ArrayList<>(); int status = SoundTrigger.listModules(modules); - mListeners = new SparseArray<>(1); + mActiveListeners = new SparseArray<>(1); if (status != SoundTrigger.STATUS_OK || modules.size() == 0) { // TODO: Figure out how to handle errors in listing the modules here. dspInfo = null; @@ -94,27 +95,9 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { } /** - * @return True, if the given {@link Keyphrase} is supported on DSP. - */ - public boolean isKeyphraseSupported(Keyphrase keyphrase) { - // TODO: We also need to look into a SoundTrigger API that let's us - // query this. For now just return true. - return true; - } - - /** - * @return True, if the given {@link Keyphrase} has been enrolled. - */ - public boolean isKeyphraseEnrolled(Keyphrase keyphrase) { - // TODO: Query VoiceInteractionManagerService - // to list registered sound models. - return false; - } - - /** * @return True, if a recognition for the given {@link Keyphrase} is active. */ - public boolean isKeyphraseActive(Keyphrase keyphrase) { + public synchronized boolean isKeyphraseActive(Keyphrase keyphrase) { // TODO: Check if the recognition for the keyphrase is currently active. return false; } @@ -124,55 +107,98 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { * * @param keyphraseId The identifier of the keyphrase for which * the recognition is to be started. + * @param soundModel The sound model to use for recognition. * @param listener The listener for the recognition events related to the given keyphrase. * @return One of {@link #STATUS_ERROR} or {@link #STATUS_OK}. */ - public int startRecognition(int keyphraseId, Listener listener) { + public synchronized int startRecognition(int keyphraseId, + SoundTrigger.KeyphraseSoundModel soundModel, + Listener listener, RecognitionConfig recognitionConfig) { if (dspInfo == null || mModule == null) { Slog.w(TAG, "Attempting startRecognition without the capability"); return STATUS_ERROR; } - if (mListeners.get(keyphraseId) != listener) { + Listener oldListener = mActiveListeners.get(keyphraseId); + if (oldListener != null && oldListener != listener) { if (mCurrentSoundModelHandle != INVALID_SOUND_MODEL_HANDLE) { Slog.w(TAG, "Canceling previous recognition"); // TODO: Inspect the return codes here. mModule.unloadSoundModel(mCurrentSoundModelHandle); } - mListeners.get(keyphraseId).onListeningStateChanged(STATE_STOPPED); + mActiveListeners.get(keyphraseId).onListeningStateChanged(STATE_STOPPED); + mActiveListeners.remove(keyphraseId); + } + + int[] handle = new int[] { INVALID_SOUND_MODEL_HANDLE }; + int status = mModule.loadSoundModel(soundModel, handle); + if (status != SoundTrigger.STATUS_OK) { + Slog.w(TAG, "loadSoundModel call failed with " + status); + return STATUS_ERROR; + } + if (handle[0] == INVALID_SOUND_MODEL_HANDLE) { + Slog.w(TAG, "loadSoundModel call returned invalid sound model handle"); + return STATUS_ERROR; + } + + // Start the recognition. + status = mModule.startRecognition(handle[0], recognitionConfig); + if (status != SoundTrigger.STATUS_OK) { + Slog.w(TAG, "startRecognition failed with " + status); + return STATUS_ERROR; } + // Everything went well! + mCurrentSoundModelHandle = handle[0]; // 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. - mListeners.put(keyphraseId, listener); - // TODO: Get the sound model for the given keyphrase here. - // mModule.loadSoundModel(model, soundModelHandle); - // mModule.startRecognition(soundModelHandle, data); - // mCurrentSoundModelHandle = soundModelHandle; - return STATUS_ERROR; + mActiveListeners.put(keyphraseId, listener); + return STATUS_OK; } /** * Stops recognition for the given {@link Keyphrase} if a recognition is currently active. * + * @param keyphraseId The identifier of the keyphrase for which + * the recognition is to be stopped. + * @param listener The listener for the recognition events related to the given keyphrase. + * * @return One of {@link #STATUS_ERROR} or {@link #STATUS_OK}. */ - public int stopRecognition(int id, Listener listener) { + public synchronized int stopRecognition(int keyphraseId, Listener listener) { if (dspInfo == null || mModule == null) { Slog.w(TAG, "Attempting stopRecognition without the capability"); return STATUS_ERROR; } - if (mListeners.get(id) != listener) { + Listener currentListener = mActiveListeners.get(keyphraseId); + if (currentListener == null) { + // startRecognition hasn't been called or it failed. + Slog.w(TAG, "Attempting stopRecognition without a successful startRecognition"); + return STATUS_ERROR; + } else if (currentListener != listener) { + // TODO: Figure out if this should match the listener that was passed in during + // startRecognition, or should we allow a different listener to stop the recognition, + // in which case we don't need to pass in a listener here. Slog.w(TAG, "Attempting stopRecognition for another recognition"); return STATUS_ERROR; } else { // Stop recognition if it's the current one, ignore otherwise. // TODO: Inspect the return codes here. - mModule.stopRecognition(mCurrentSoundModelHandle); - mModule.unloadSoundModel(mCurrentSoundModelHandle); + int status = mModule.stopRecognition(mCurrentSoundModelHandle); + if (status != SoundTrigger.STATUS_OK) { + Slog.w(TAG, "stopRecognition call failed with " + status); + return STATUS_ERROR; + } + status = mModule.unloadSoundModel(mCurrentSoundModelHandle); + if (status != SoundTrigger.STATUS_OK) { + Slog.w(TAG, "unloadSoundModel call failed with " + status); + return STATUS_ERROR; + } + mCurrentSoundModelHandle = INVALID_SOUND_MODEL_HANDLE; + mActiveListeners.remove(keyphraseId); return STATUS_OK; } } @@ -184,28 +210,26 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { // TODO: Get the keyphrase out of the event and fire events on it. // For now, as a nasty workaround, we fire all events to the listener for // keyphrase with TEMP_KEYPHRASE_ID. + Listener listener = null; + synchronized(this) { + // TODO: The keyphrase should come from the recognition event + // as it may be for a different keyphrase than the current one. + listener = mActiveListeners.get(TEMP_KEYPHRASE_ID); + } + if (listener == null) { + Slog.w(TAG, "received onRecognition event without any listener for it"); + return; + } switch (event.status) { case SoundTrigger.RECOGNITION_STATUS_SUCCESS: - // TODO: The keyphrase should come from the recognition event - // as it may be for a different keyphrase than the current one. - if (mListeners.get(TEMP_KEYPHRASE_ID) != null) { - mListeners.get(TEMP_KEYPHRASE_ID).onKeyphraseSpoken(); - } + listener.onKeyphraseSpoken(); break; case SoundTrigger.RECOGNITION_STATUS_ABORT: - // TODO: The keyphrase should come from the recognition event - // as it may be for a different keyphrase than the current one. - if (mListeners.get(TEMP_KEYPHRASE_ID) != null) { - mListeners.get(TEMP_KEYPHRASE_ID).onListeningStateChanged(STATE_STOPPED); - } + listener.onListeningStateChanged(STATE_STOPPED); break; case SoundTrigger.RECOGNITION_STATUS_FAILURE: - // TODO: The keyphrase should come from the recognition event - // as it may be for a different keyphrase than the current one. - if (mListeners.get(TEMP_KEYPHRASE_ID) != null) { - mListeners.get(TEMP_KEYPHRASE_ID).onListeningStateChanged(STATE_STOPPED); - } + listener.onListeningStateChanged(STATE_STOPPED); break; } } |