diff options
author | Sandeep Siddhartha <sansid@google.com> | 2014-07-17 16:21:54 -0700 |
---|---|---|
committer | Sandeep Siddhartha <sansid@google.com> | 2014-07-20 11:22:55 -0700 |
commit | 055897208d659e9734a82def88be4a806ff55448 (patch) | |
tree | 4540186364f0a3fc3a3675119846448215696f68 /core/java/android/hardware/soundtrigger | |
parent | 6eb262c3515c927df19340b3eee8c74bc9478d16 (diff) | |
download | frameworks_base-055897208d659e9734a82def88be4a806ff55448.zip frameworks_base-055897208d659e9734a82def88be4a806ff55448.tar.gz frameworks_base-055897208d659e9734a82def88be4a806ff55448.tar.bz2 |
Move sound trigger calls to VoiceInteractionManagerService
- This ensures that any data being loaded on the DSP comes from the framework
Change-Id: Ie15f0994850ba8f298ca07c49fe0b89e066d9e2b
Diffstat (limited to 'core/java/android/hardware/soundtrigger')
9 files changed, 366 insertions, 535 deletions
diff --git a/core/java/android/hardware/soundtrigger/DspInfo.java b/core/java/android/hardware/soundtrigger/DspInfo.java deleted file mode 100644 index 517159d..0000000 --- a/core/java/android/hardware/soundtrigger/DspInfo.java +++ /dev/null @@ -1,57 +0,0 @@ -/** - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.hardware.soundtrigger; - -import java.util.UUID; - -/** - * Properties of the DSP hardware on the device. - * - * @hide - */ -public class DspInfo { - /** - * Unique voice engine Id (changes with each version). - */ - public final UUID voiceEngineId; - - /** - * Human readable voice detection engine implementor. - */ - public final String voiceEngineImplementor; - /** - * Human readable voice detection engine description. - */ - public final String voiceEngineDescription; - /** - * Human readable voice detection engine version - */ - public final int voiceEngineVersion; - /** - * Rated power consumption when detection is active. - */ - public final int powerConsumptionMw; - - public DspInfo(UUID voiceEngineId, String voiceEngineImplementor, - String voiceEngineDescription, int version, int powerConsumptionMw) { - this.voiceEngineId = voiceEngineId; - this.voiceEngineImplementor = voiceEngineImplementor; - this.voiceEngineDescription = voiceEngineDescription; - this.voiceEngineVersion = version; - this.powerConsumptionMw = powerConsumptionMw; - } -} diff --git a/core/java/android/hardware/soundtrigger/IRecognitionStatusCallback.aidl b/core/java/android/hardware/soundtrigger/IRecognitionStatusCallback.aidl new file mode 100644 index 0000000..5738909 --- /dev/null +++ b/core/java/android/hardware/soundtrigger/IRecognitionStatusCallback.aidl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.soundtrigger; + +/** + * @hide + */ +oneway interface IRecognitionStatusCallback { + /** + * Called when the keyphrase is spoken. + * + * @param data Optional trigger audio data, if it was requested and is available. + * TODO: See if the data being passed in works well, if not use shared memory. + * This *MUST* not exceed 100K. + */ + void onDetected(in byte[] data); + /** + * Called when the detection for the associated keyphrase starts. + */ + void onDetectionStarted(); + /** + * Called when the detection for the associated keyphrase stops. + */ + void onDetectionStopped(); +}
\ No newline at end of file diff --git a/core/java/android/hardware/soundtrigger/Keyphrase.aidl b/core/java/android/hardware/soundtrigger/Keyphrase.aidl deleted file mode 100644 index d9853a7..0000000 --- a/core/java/android/hardware/soundtrigger/Keyphrase.aidl +++ /dev/null @@ -1,4 +0,0 @@ -package android.hardware.soundtrigger; - -// @hide -parcelable Keyphrase;
\ No newline at end of file diff --git a/core/java/android/hardware/soundtrigger/Keyphrase.java b/core/java/android/hardware/soundtrigger/Keyphrase.java deleted file mode 100644 index 51311bb..0000000 --- a/core/java/android/hardware/soundtrigger/Keyphrase.java +++ /dev/null @@ -1,135 +0,0 @@ -/** - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.hardware.soundtrigger; - -import android.os.Parcel; -import android.os.Parcelable; - -/** - * A Voice Keyphrase. - * - * @hide - */ -public class Keyphrase implements Parcelable { - /** A unique identifier for this keyphrase */ - public final int id; - /** 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 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>() { - public Keyphrase createFromParcel(Parcel in) { - return Keyphrase.fromParcel(in); - } - - public Keyphrase[] newArray(int size) { - return new Keyphrase[size]; - } - }; - - private static Keyphrase fromParcel(Parcel in) { - 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, int recognitionModeFlags, - int[] users) { - this.id = id; - this.hintText = hintText; - this.locale = locale; - this.recognitionModeFlags = recognitionModeFlags; - this.users = users; - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - 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 - public int describeContents() { - return 0; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((hintText == null) ? 0 : hintText.hashCode()); - result = prime * result + id; - result = prime * result + ((locale == null) ? 0 : locale.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - Keyphrase other = (Keyphrase) obj; - if (hintText == null) { - if (other.hintText != null) - return false; - } else if (!hintText.equals(other.hintText)) - return false; - if (id != other.id) - return false; - if (locale == null) { - if (other.locale != null) - return false; - } else if (!locale.equals(other.locale)) - 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/KeyphraseSoundModel.aidl b/core/java/android/hardware/soundtrigger/KeyphraseSoundModel.aidl deleted file mode 100644 index 39b33cc..0000000 --- a/core/java/android/hardware/soundtrigger/KeyphraseSoundModel.aidl +++ /dev/null @@ -1,4 +0,0 @@ -package android.hardware.soundtrigger; - -// @hide -parcelable KeyphraseSoundModel;
\ No newline at end of file diff --git a/core/java/android/hardware/soundtrigger/KeyphraseSoundModel.java b/core/java/android/hardware/soundtrigger/KeyphraseSoundModel.java deleted file mode 100644 index a5ab0d2..0000000 --- a/core/java/android/hardware/soundtrigger/KeyphraseSoundModel.java +++ /dev/null @@ -1,79 +0,0 @@ -package android.hardware.soundtrigger; - -import android.os.Parcel; -import android.os.Parcelable; - -import java.util.UUID; - -/** - * A KeyphraseSoundModel is a sound model capable of detecting voice keyphrases. - * It contains data needed by the hardware to detect a given number of key phrases - * and the list of corresponding {@link Keyphrase}s. - * - * @hide - */ -public class KeyphraseSoundModel implements Parcelable { - - /** Key phrases in this sound model */ - public final Keyphrase[] keyphrases; - public final byte[] data; - public final UUID uuid; - - public static final Parcelable.Creator<KeyphraseSoundModel> CREATOR - = new Parcelable.Creator<KeyphraseSoundModel>() { - public KeyphraseSoundModel createFromParcel(Parcel in) { - return KeyphraseSoundModel.fromParcel(in); - } - - public KeyphraseSoundModel[] newArray(int size) { - return new KeyphraseSoundModel[size]; - } - }; - - public KeyphraseSoundModel(UUID uuid, byte[] data,Keyphrase[] keyPhrases) { - this.uuid = uuid; - this.data = data; - this.keyphrases = keyPhrases; - } - - private static KeyphraseSoundModel fromParcel(Parcel in) { - UUID uuid = UUID.fromString(in.readString()); - int dataLength = in.readInt(); - byte[] data = null; - if (dataLength > 0) { - data = new byte[in.readInt()]; - in.readByteArray(data); - } - Keyphrase[] keyphrases = - (Keyphrase[]) in.readParcelableArray(Keyphrase.class.getClassLoader()); - return new KeyphraseSoundModel(uuid, data, keyphrases); - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeString(uuid.toString()); - if (data != null) { - dest.writeInt(data.length); - dest.writeByteArray(data); - } else { - dest.writeInt(0); - } - 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/SoundTrigger.aidl b/core/java/android/hardware/soundtrigger/SoundTrigger.aidl new file mode 100644 index 0000000..837691a --- /dev/null +++ b/core/java/android/hardware/soundtrigger/SoundTrigger.aidl @@ -0,0 +1,24 @@ +/** + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.soundtrigger; + +parcelable SoundTrigger.ConfidenceLevel; +parcelable SoundTrigger.Keyphrase; +parcelable SoundTrigger.KeyphraseRecognitionExtra; +parcelable SoundTrigger.KeyphraseSoundModel; +parcelable SoundTrigger.ModuleProperties; +parcelable SoundTrigger.RecognitionConfig;
\ No newline at end of file diff --git a/core/java/android/hardware/soundtrigger/SoundTrigger.java b/core/java/android/hardware/soundtrigger/SoundTrigger.java index 1f48a92..7b0a678 100644 --- a/core/java/android/hardware/soundtrigger/SoundTrigger.java +++ b/core/java/android/hardware/soundtrigger/SoundTrigger.java @@ -17,8 +17,11 @@ package android.hardware.soundtrigger; import android.os.Handler; +import android.os.Parcel; +import android.os.Parcelable; import java.util.ArrayList; +import java.util.Arrays; import java.util.UUID; /** @@ -43,7 +46,7 @@ public class SoundTrigger { * ID used to target any API call to this paricular module. Module * properties are returned by listModules() method. ****************************************************************************/ - public static class ModuleProperties { + public static class ModuleProperties implements Parcelable { /** Unique module ID provided by the native service */ public final int id; @@ -102,6 +105,70 @@ public class SoundTrigger { this.supportsConcurrentCapture = supportsConcurrentCapture; this.powerConsumptionMw = powerConsumptionMw; } + + public static final Parcelable.Creator<ModuleProperties> CREATOR + = new Parcelable.Creator<ModuleProperties>() { + public ModuleProperties createFromParcel(Parcel in) { + return ModuleProperties.fromParcel(in); + } + + public ModuleProperties[] newArray(int size) { + return new ModuleProperties[size]; + } + }; + + private static ModuleProperties fromParcel(Parcel in) { + int id = in.readInt(); + String implementor = in.readString(); + String description = in.readString(); + String uuid = in.readString(); + int version = in.readInt(); + int maxSoundModels = in.readInt(); + int maxKeyphrases = in.readInt(); + int maxUsers = in.readInt(); + int recognitionModes = in.readInt(); + boolean supportsCaptureTransition = in.readByte() == 1; + int maxBufferMs = in.readInt(); + boolean supportsConcurrentCapture = in.readByte() == 1; + int powerConsumptionMw = in.readInt(); + return new ModuleProperties(id, implementor, description, uuid, version, + maxSoundModels, maxKeyphrases, maxUsers, recognitionModes, + supportsCaptureTransition, maxBufferMs, supportsConcurrentCapture, + powerConsumptionMw); + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(id); + dest.writeString(implementor); + dest.writeString(description); + dest.writeString(uuid.toString()); + dest.writeInt(version); + dest.writeInt(maxSoundModels); + dest.writeInt(maxKeyphrases); + dest.writeInt(maxUsers); + dest.writeInt(recognitionModes); + dest.writeByte((byte) (supportsCaptureTransition ? 1 : 0)); + dest.writeInt(maxBufferMs); + dest.writeByte((byte) (supportsConcurrentCapture ? 1 : 0)); + dest.writeInt(powerConsumptionMw); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public String toString() { + return "ModuleProperties [id=" + id + ", implementor=" + implementor + ", description=" + + description + ", uuid=" + uuid + ", version=" + version + ", maxSoundModels=" + + maxSoundModels + ", maxKeyphrases=" + maxKeyphrases + ", maxUsers=" + + maxUsers + ", recognitionModes=" + recognitionModes + + ", supportsCaptureTransition=" + supportsCaptureTransition + ", maxBufferMs=" + + maxBufferMs + ", supportsConcurrentCapture=" + supportsConcurrentCapture + + ", powerConsumptionMw=" + powerConsumptionMw + "]"; + } } /***************************************************************************** @@ -137,7 +204,7 @@ public class SoundTrigger { * A Keyphrase describes a key phrase that can be detected by a * {@link KeyphraseSoundModel} ****************************************************************************/ - public static class Keyphrase { + public static class Keyphrase implements Parcelable { /** Unique identifier for this keyphrase */ public final int id; @@ -161,6 +228,96 @@ public class SoundTrigger { this.text = text; this.users = users; } + + public static final Parcelable.Creator<Keyphrase> CREATOR + = new Parcelable.Creator<Keyphrase>() { + public Keyphrase createFromParcel(Parcel in) { + return Keyphrase.fromParcel(in); + } + + public Keyphrase[] newArray(int size) { + return new Keyphrase[size]; + } + }; + + private static Keyphrase fromParcel(Parcel in) { + int id = in.readInt(); + int recognitionModes = in.readInt(); + String locale = in.readString(); + String text = in.readString(); + int[] users = null; + int numUsers = in.readInt(); + if (numUsers > 0) { + users = new int[numUsers]; + in.readIntArray(users); + } + return new Keyphrase(id, recognitionModes, locale, text, users); + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(id); + dest.writeInt(recognitionModes); + dest.writeString(locale); + dest.writeString(text); + if (users != null) { + dest.writeInt(users.length); + dest.writeIntArray(users); + } else { + dest.writeInt(0); + } + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((text == null) ? 0 : text.hashCode()); + result = prime * result + id; + result = prime * result + ((locale == null) ? 0 : locale.hashCode()); + result = prime * result + recognitionModes; + result = prime * result + Arrays.hashCode(users); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Keyphrase other = (Keyphrase) obj; + if (text == null) { + if (other.text != null) + return false; + } else if (!text.equals(other.text)) + return false; + if (id != other.id) + return false; + if (locale == null) { + if (other.locale != null) + return false; + } else if (!locale.equals(other.locale)) + return false; + if (recognitionModes != other.recognitionModes) + return false; + if (!Arrays.equals(users, other.users)) + return false; + return true; + } + + @Override + public String toString() { + return "Keyphrase [id=" + id + ", recognitionModes=" + recognitionModes + ", locale=" + + locale + ", text=" + text + ", users=" + Arrays.toString(users) + "]"; + } } /***************************************************************************** @@ -168,7 +325,7 @@ public class SoundTrigger { * It contains data needed by the hardware to detect a certain number of key phrases * and the list of corresponding {@link Keyphrase} descriptors. ****************************************************************************/ - public static class KeyphraseSoundModel extends SoundModel { + public static class KeyphraseSoundModel extends SoundModel implements Parcelable { /** Key phrases in this sound model */ public final Keyphrase[] keyphrases; // keyword phrases in model @@ -176,6 +333,46 @@ public class SoundTrigger { super(id, TYPE_KEYPHRASE, data); this.keyphrases = keyphrases; } + + public static final Parcelable.Creator<KeyphraseSoundModel> CREATOR + = new Parcelable.Creator<KeyphraseSoundModel>() { + public KeyphraseSoundModel createFromParcel(Parcel in) { + return KeyphraseSoundModel.fromParcel(in); + } + + public KeyphraseSoundModel[] newArray(int size) { + return new KeyphraseSoundModel[size]; + } + }; + + private static KeyphraseSoundModel fromParcel(Parcel in) { + UUID uuid = UUID.fromString(in.readString()); + byte[] data = null; + int dataLength = in.readInt(); + if (dataLength > 0) { + data = new byte[dataLength]; + in.readByteArray(data); + } + Keyphrase[] keyphrases = in.createTypedArray(Keyphrase.CREATOR); + return new KeyphraseSoundModel(uuid, data, keyphrases); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(uuid.toString()); + if (data != null) { + dest.writeInt(data.length); + dest.writeByteArray(data); + } else { + dest.writeInt(0); + } + dest.writeTypedArray(keyphrases, 0); + } } /** @@ -239,7 +436,7 @@ public class SoundTrigger { * {@link SoundTriggerModule#startRecognition(int, RecognitionConfig)} to configure the * recognition request. */ - public static class RecognitionConfig { + public static class RecognitionConfig implements Parcelable { /** True if the DSP should capture the trigger sound and make it available for further * capture. */ public final boolean captureRequested; @@ -256,6 +453,47 @@ public class SoundTrigger { this.keyphrases = keyphrases; this.data = data; } + + public static final Parcelable.Creator<RecognitionConfig> CREATOR + = new Parcelable.Creator<RecognitionConfig>() { + public RecognitionConfig createFromParcel(Parcel in) { + return RecognitionConfig.fromParcel(in); + } + + public RecognitionConfig[] newArray(int size) { + return new RecognitionConfig[size]; + } + }; + + private static RecognitionConfig fromParcel(Parcel in) { + boolean captureRequested = in.readByte() == 1; + KeyphraseRecognitionExtra[] keyphrases = + in.createTypedArray(KeyphraseRecognitionExtra.CREATOR); + byte[] data = null; + int dataLength = in.readInt(); + if (dataLength > 0) { + data = new byte[dataLength]; + in.readByteArray(data); + } + return new RecognitionConfig(captureRequested, keyphrases, data); + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeByte((byte) (captureRequested ? 1 : 0)); + dest.writeTypedArray(keyphrases, 0); + if (data != null) { + dest.writeInt(data.length); + dest.writeByteArray(data); + } else { + dest.writeInt(0); + } + } + + @Override + public int describeContents() { + return 0; + } } /** @@ -266,7 +504,7 @@ public class SoundTrigger { * should trigger a recognition. * - The user ID is derived from the system ID {@link android.os.UserHandle#getIdentifier()}. */ - public static class ConfidenceLevel { + public static class ConfidenceLevel implements Parcelable { public final int userId; public final int confidenceLevel; @@ -274,14 +512,42 @@ public class SoundTrigger { this.userId = userId; this.confidenceLevel = confidenceLevel; } + + public static final Parcelable.Creator<ConfidenceLevel> CREATOR + = new Parcelable.Creator<ConfidenceLevel>() { + public ConfidenceLevel createFromParcel(Parcel in) { + return ConfidenceLevel.fromParcel(in); + } + + public ConfidenceLevel[] newArray(int size) { + return new ConfidenceLevel[size]; + } + }; + + private static ConfidenceLevel fromParcel(Parcel in) { + int userId = in.readInt(); + int confidenceLevel = in.readInt(); + return new ConfidenceLevel(userId, confidenceLevel); + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(userId); + dest.writeInt(confidenceLevel); + } + + @Override + public int describeContents() { + return 0; + } } /** * Additional data conveyed by a {@link KeyphraseRecognitionEvent} * for a key phrase detection. */ - public static class KeyphraseRecognitionExtra { - /** The keyphrse ID */ + public static class KeyphraseRecognitionExtra implements Parcelable { + /** The keyphrase ID */ public final int id; /** Recognition modes matched for this event */ @@ -297,6 +563,36 @@ public class SoundTrigger { this.recognitionModes = recognitionModes; this.confidenceLevels = confidenceLevels; } + + public static final Parcelable.Creator<KeyphraseRecognitionExtra> CREATOR + = new Parcelable.Creator<KeyphraseRecognitionExtra>() { + public KeyphraseRecognitionExtra createFromParcel(Parcel in) { + return KeyphraseRecognitionExtra.fromParcel(in); + } + + public KeyphraseRecognitionExtra[] newArray(int size) { + return new KeyphraseRecognitionExtra[size]; + } + }; + + private static KeyphraseRecognitionExtra fromParcel(Parcel in) { + int id = in.readInt(); + int recognitionModes = in.readInt(); + ConfidenceLevel[] confidenceLevels = in.createTypedArray(ConfidenceLevel.CREATOR); + return new KeyphraseRecognitionExtra(id, recognitionModes, confidenceLevels); + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(id); + dest.writeInt(recognitionModes); + dest.writeTypedArray(confidenceLevels, 0); + } + + @Override + public int describeContents() { + return 0; + } } /** diff --git a/core/java/android/hardware/soundtrigger/SoundTriggerHelper.java b/core/java/android/hardware/soundtrigger/SoundTriggerHelper.java deleted file mode 100644 index 431d550..0000000 --- a/core/java/android/hardware/soundtrigger/SoundTriggerHelper.java +++ /dev/null @@ -1,249 +0,0 @@ -/** - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -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; - -import java.util.ArrayList; - -/** - * Helper for {@link SoundTrigger} APIs. - * Currently this just acts as an abstraction over all SoundTrigger API calls. - * - * @hide - */ -public class SoundTriggerHelper implements SoundTrigger.StatusListener { - static final String TAG = "SoundTriggerHelper"; - // TODO: Remove this. - static final int TEMP_KEYPHRASE_ID = 1; - - /** - * Return codes for {@link #startRecognition(Keyphrase)}, {@link #stopRecognition(Keyphrase)} - * Note: Keep in sync with AlwaysOnKeyphraseInteractor.java - */ - public static final int STATUS_ERROR = Integer.MIN_VALUE; - public static final int STATUS_OK = 1; - - /** - * States for {@link Listener#onListeningStateChanged(int, int)}. - */ - public static final int STATE_STOPPED = 0; - public static final int STATE_STARTED = 1; - - private static final int INVALID_SOUND_MODEL_HANDLE = -1; - - /** The {@link DspInfo} for the system, or null if none exists. */ - public final DspInfo dspInfo; - - /** The properties for the DSP module */ - private final ModuleProperties mModuleProperties; - private final SoundTriggerModule mModule; - - private final SparseArray<Listener> mActiveListeners; - - private int mCurrentSoundModelHandle = INVALID_SOUND_MODEL_HANDLE; - - /** - * The callback for sound trigger events. - */ - public interface Listener { - /** - * Called when the given keyphrase is spoken. - * - * @param data The captured audio, may be null. - */ - void onKeyphraseSpoken(byte[] data); - - /** - * Called when the listening state for the given keyphrase changes. - * @param state Indicates the current state. - */ - void onListeningStateChanged(int state); - } - - public SoundTriggerHelper() { - ArrayList <ModuleProperties> modules = new ArrayList<>(); - int status = SoundTrigger.listModules(modules); - mActiveListeners = new SparseArray<>(1); - if (status != SoundTrigger.STATUS_OK || modules.size() == 0) { - Slog.w(TAG, "listModules status=" + status + ", # of modules=" + modules.size()); - dspInfo = null; - mModuleProperties = null; - mModule = null; - } else { - // TODO: Figure out how to determine which module corresponds to the DSP hardware. - mModuleProperties = modules.get(0); - dspInfo = new DspInfo(mModuleProperties.uuid, mModuleProperties.implementor, - mModuleProperties.description, mModuleProperties.version, - mModuleProperties.powerConsumptionMw); - mModule = SoundTrigger.attachModule(mModuleProperties.id, this, null); - } - } - - /** - * @return True, if a recognition for the given {@link Keyphrase} is active. - */ - public synchronized boolean isKeyphraseActive(Keyphrase keyphrase) { - if (keyphrase == null) { - Slog.w(TAG, "isKeyphraseActive requires a non-null keyphrase"); - return false; - } - return mActiveListeners.get(keyphrase.id) != null; - } - - /** - * Starts recognition for the given {@link Keyphrase}. - * - * @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 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; - } - - 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); - } - 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. - 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 synchronized int stopRecognition(int keyphraseId, Listener listener) { - if (dspInfo == null || mModule == null) { - Slog.w(TAG, "Attempting stopRecognition without the capability"); - return STATUS_ERROR; - } - - 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. - 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; - } - } - - //---- SoundTrigger.StatusListener methods - @Override - public void onRecognition(RecognitionEvent event) { - // Check which keyphrase triggered, and fire the appropriate event. - // 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: Pass the captured audio back. - listener.onKeyphraseSpoken(null); - break; - case SoundTrigger.RECOGNITION_STATUS_ABORT: - listener.onListeningStateChanged(STATE_STOPPED); - break; - case SoundTrigger.RECOGNITION_STATUS_FAILURE: - listener.onListeningStateChanged(STATE_STOPPED); - break; - } - } - - @Override - public void onServiceDied() { - // TODO: Figure out how to restart the recognition here. - } -} |