blob: 7390e2b6b7de4cdd78f41c92ce5498a17161f5b6 [file] [log] [blame]
Sandeepd7018202014-07-10 15:15:39 -07001/**
Eric Laurente48188c2014-04-18 17:44:11 -07002 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.hardware.soundtrigger;
18
Eric Laurentd3b82232014-07-30 08:57:39 -070019import android.media.AudioFormat;
Eric Laurente48188c2014-04-18 17:44:11 -070020import android.os.Handler;
Sandeep Siddhartha05589722014-07-17 16:21:54 -070021import android.os.Parcel;
22import android.os.Parcelable;
Eric Laurente48188c2014-04-18 17:44:11 -070023
24import java.util.ArrayList;
Sandeep Siddhartha05589722014-07-17 16:21:54 -070025import java.util.Arrays;
Eric Laurente48188c2014-04-18 17:44:11 -070026import java.util.UUID;
27
28/**
29 * The SoundTrigger class provides access via JNI to the native service managing
30 * the sound trigger HAL.
31 *
32 * @hide
33 */
34public class SoundTrigger {
35
36 public static final int STATUS_OK = 0;
37 public static final int STATUS_ERROR = Integer.MIN_VALUE;
38 public static final int STATUS_PERMISSION_DENIED = -1;
39 public static final int STATUS_NO_INIT = -19;
40 public static final int STATUS_BAD_VALUE = -22;
41 public static final int STATUS_DEAD_OBJECT = -32;
42 public static final int STATUS_INVALID_OPERATION = -38;
43
44 /*****************************************************************************
45 * A ModuleProperties describes a given sound trigger hardware module
46 * managed by the native sound trigger service. Each module has a unique
47 * ID used to target any API call to this paricular module. Module
48 * properties are returned by listModules() method.
49 ****************************************************************************/
Sandeep Siddhartha05589722014-07-17 16:21:54 -070050 public static class ModuleProperties implements Parcelable {
Eric Laurente48188c2014-04-18 17:44:11 -070051 /** Unique module ID provided by the native service */
52 public final int id;
53
54 /** human readable voice detection engine implementor */
55 public final String implementor;
56
57 /** human readable voice detection engine description */
58 public final String description;
59
60 /** Unique voice engine Id (changes with each version) */
61 public final UUID uuid;
62
63 /** Voice detection engine version */
64 public final int version;
65
66 /** Maximum number of active sound models */
67 public final int maxSoundModels;
68
69 /** Maximum number of key phrases */
Sandeep Siddharthad4233c62014-06-12 18:31:19 -070070 public final int maxKeyphrases;
Eric Laurente48188c2014-04-18 17:44:11 -070071
72 /** Maximum number of users per key phrase */
73 public final int maxUsers;
74
75 /** Supported recognition modes (bit field, RECOGNITION_MODE_VOICE_TRIGGER ...) */
76 public final int recognitionModes;
77
78 /** Supports seamless transition to capture mode after recognition */
79 public final boolean supportsCaptureTransition;
80
81 /** Maximum buffering capacity in ms if supportsCaptureTransition() is true */
82 public final int maxBufferMs;
83
84 /** Supports capture by other use cases while detection is active */
85 public final boolean supportsConcurrentCapture;
86
87 /** Rated power consumption when detection is active with TDB silence/sound/speech ratio */
88 public final int powerConsumptionMw;
89
Eric Laurentd3b82232014-07-30 08:57:39 -070090 /** Returns the trigger (key phrase) capture in the binary data of the
91 * recognition callback event */
92 public final boolean returnsTriggerInEvent;
93
Eric Laurente48188c2014-04-18 17:44:11 -070094 ModuleProperties(int id, String implementor, String description,
Sandeep Siddharthad4233c62014-06-12 18:31:19 -070095 String uuid, int version, int maxSoundModels, int maxKeyphrases,
Eric Laurente48188c2014-04-18 17:44:11 -070096 int maxUsers, int recognitionModes, boolean supportsCaptureTransition,
97 int maxBufferMs, boolean supportsConcurrentCapture,
Eric Laurentd3b82232014-07-30 08:57:39 -070098 int powerConsumptionMw, boolean returnsTriggerInEvent) {
Eric Laurente48188c2014-04-18 17:44:11 -070099 this.id = id;
100 this.implementor = implementor;
101 this.description = description;
102 this.uuid = UUID.fromString(uuid);
103 this.version = version;
104 this.maxSoundModels = maxSoundModels;
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700105 this.maxKeyphrases = maxKeyphrases;
Eric Laurente48188c2014-04-18 17:44:11 -0700106 this.maxUsers = maxUsers;
107 this.recognitionModes = recognitionModes;
108 this.supportsCaptureTransition = supportsCaptureTransition;
109 this.maxBufferMs = maxBufferMs;
110 this.supportsConcurrentCapture = supportsConcurrentCapture;
111 this.powerConsumptionMw = powerConsumptionMw;
Eric Laurentd3b82232014-07-30 08:57:39 -0700112 this.returnsTriggerInEvent = returnsTriggerInEvent;
Eric Laurente48188c2014-04-18 17:44:11 -0700113 }
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700114
115 public static final Parcelable.Creator<ModuleProperties> CREATOR
116 = new Parcelable.Creator<ModuleProperties>() {
117 public ModuleProperties createFromParcel(Parcel in) {
118 return ModuleProperties.fromParcel(in);
119 }
120
121 public ModuleProperties[] newArray(int size) {
122 return new ModuleProperties[size];
123 }
124 };
125
126 private static ModuleProperties fromParcel(Parcel in) {
127 int id = in.readInt();
128 String implementor = in.readString();
129 String description = in.readString();
130 String uuid = in.readString();
131 int version = in.readInt();
132 int maxSoundModels = in.readInt();
133 int maxKeyphrases = in.readInt();
134 int maxUsers = in.readInt();
135 int recognitionModes = in.readInt();
136 boolean supportsCaptureTransition = in.readByte() == 1;
137 int maxBufferMs = in.readInt();
138 boolean supportsConcurrentCapture = in.readByte() == 1;
139 int powerConsumptionMw = in.readInt();
Eric Laurentd3b82232014-07-30 08:57:39 -0700140 boolean returnsTriggerInEvent = in.readByte() == 1;
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700141 return new ModuleProperties(id, implementor, description, uuid, version,
142 maxSoundModels, maxKeyphrases, maxUsers, recognitionModes,
143 supportsCaptureTransition, maxBufferMs, supportsConcurrentCapture,
Eric Laurentd3b82232014-07-30 08:57:39 -0700144 powerConsumptionMw, returnsTriggerInEvent);
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700145 }
146
147 @Override
148 public void writeToParcel(Parcel dest, int flags) {
149 dest.writeInt(id);
150 dest.writeString(implementor);
151 dest.writeString(description);
152 dest.writeString(uuid.toString());
153 dest.writeInt(version);
154 dest.writeInt(maxSoundModels);
155 dest.writeInt(maxKeyphrases);
156 dest.writeInt(maxUsers);
157 dest.writeInt(recognitionModes);
158 dest.writeByte((byte) (supportsCaptureTransition ? 1 : 0));
159 dest.writeInt(maxBufferMs);
160 dest.writeByte((byte) (supportsConcurrentCapture ? 1 : 0));
161 dest.writeInt(powerConsumptionMw);
Eric Laurentd3b82232014-07-30 08:57:39 -0700162 dest.writeByte((byte) (returnsTriggerInEvent ? 1 : 0));
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700163 }
164
165 @Override
166 public int describeContents() {
167 return 0;
168 }
169
170 @Override
171 public String toString() {
172 return "ModuleProperties [id=" + id + ", implementor=" + implementor + ", description="
173 + description + ", uuid=" + uuid + ", version=" + version + ", maxSoundModels="
174 + maxSoundModels + ", maxKeyphrases=" + maxKeyphrases + ", maxUsers="
175 + maxUsers + ", recognitionModes=" + recognitionModes
176 + ", supportsCaptureTransition=" + supportsCaptureTransition + ", maxBufferMs="
177 + maxBufferMs + ", supportsConcurrentCapture=" + supportsConcurrentCapture
Eric Laurentd3b82232014-07-30 08:57:39 -0700178 + ", powerConsumptionMw=" + powerConsumptionMw
179 + ", returnsTriggerInEvent=" + returnsTriggerInEvent + "]";
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700180 }
Eric Laurente48188c2014-04-18 17:44:11 -0700181 }
182
183 /*****************************************************************************
184 * A SoundModel describes the attributes and contains the binary data used by the hardware
185 * implementation to detect a particular sound pattern.
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700186 * A specialized version {@link KeyphraseSoundModel} is defined for key phrase
Eric Laurente48188c2014-04-18 17:44:11 -0700187 * sound models.
188 ****************************************************************************/
189 public static class SoundModel {
190 /** Undefined sound model type */
191 public static final int TYPE_UNKNOWN = -1;
192
193 /** Keyphrase sound model */
194 public static final int TYPE_KEYPHRASE = 0;
195
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700196 /** Unique sound model identifier */
197 public final UUID uuid;
198
Eric Laurente48188c2014-04-18 17:44:11 -0700199 /** Sound model type (e.g. TYPE_KEYPHRASE); */
200 public final int type;
201
Eric Laurentd3b82232014-07-30 08:57:39 -0700202 /** Unique sound model vendor identifier */
203 public final UUID vendorUuid;
204
Eric Laurente48188c2014-04-18 17:44:11 -0700205 /** Opaque data. For use by vendor implementation and enrollment application */
206 public final byte[] data;
207
Eric Laurentd3b82232014-07-30 08:57:39 -0700208 public SoundModel(UUID uuid, UUID vendorUuid, int type, byte[] data) {
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700209 this.uuid = uuid;
Eric Laurentd3b82232014-07-30 08:57:39 -0700210 this.vendorUuid = vendorUuid;
Eric Laurente48188c2014-04-18 17:44:11 -0700211 this.type = type;
212 this.data = data;
213 }
214 }
215
216 /*****************************************************************************
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700217 * A Keyphrase describes a key phrase that can be detected by a
218 * {@link KeyphraseSoundModel}
Eric Laurente48188c2014-04-18 17:44:11 -0700219 ****************************************************************************/
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700220 public static class Keyphrase implements Parcelable {
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700221 /** Unique identifier for this keyphrase */
222 public final int id;
223
Eric Laurente48188c2014-04-18 17:44:11 -0700224 /** Recognition modes supported for this key phrase in the model */
225 public final int recognitionModes;
226
227 /** Locale of the keyphrase. JAVA Locale string e.g en_US */
228 public final String locale;
229
230 /** Key phrase text */
231 public final String text;
232
Eric Laurent013f66b2014-07-06 16:35:00 -0700233 /** Users this key phrase has been trained for. countains sound trigger specific user IDs
234 * derived from system user IDs {@link android.os.UserHandle#getIdentifier()}. */
235 public final int[] users;
Eric Laurente48188c2014-04-18 17:44:11 -0700236
Eric Laurent013f66b2014-07-06 16:35:00 -0700237 public Keyphrase(int id, int recognitionModes, String locale, String text, int[] users) {
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700238 this.id = id;
Eric Laurente48188c2014-04-18 17:44:11 -0700239 this.recognitionModes = recognitionModes;
240 this.locale = locale;
241 this.text = text;
Eric Laurent013f66b2014-07-06 16:35:00 -0700242 this.users = users;
Eric Laurente48188c2014-04-18 17:44:11 -0700243 }
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700244
245 public static final Parcelable.Creator<Keyphrase> CREATOR
246 = new Parcelable.Creator<Keyphrase>() {
247 public Keyphrase createFromParcel(Parcel in) {
248 return Keyphrase.fromParcel(in);
249 }
250
251 public Keyphrase[] newArray(int size) {
252 return new Keyphrase[size];
253 }
254 };
255
256 private static Keyphrase fromParcel(Parcel in) {
257 int id = in.readInt();
258 int recognitionModes = in.readInt();
259 String locale = in.readString();
260 String text = in.readString();
261 int[] users = null;
262 int numUsers = in.readInt();
Sandeep Siddhartha110f5692014-07-20 12:22:56 -0700263 if (numUsers >= 0) {
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700264 users = new int[numUsers];
265 in.readIntArray(users);
266 }
267 return new Keyphrase(id, recognitionModes, locale, text, users);
268 }
269
270 @Override
271 public void writeToParcel(Parcel dest, int flags) {
272 dest.writeInt(id);
273 dest.writeInt(recognitionModes);
274 dest.writeString(locale);
275 dest.writeString(text);
276 if (users != null) {
277 dest.writeInt(users.length);
278 dest.writeIntArray(users);
279 } else {
Sandeep Siddhartha110f5692014-07-20 12:22:56 -0700280 dest.writeInt(-1);
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700281 }
282 }
283
284 @Override
285 public int describeContents() {
286 return 0;
287 }
288
289 @Override
290 public int hashCode() {
291 final int prime = 31;
292 int result = 1;
293 result = prime * result + ((text == null) ? 0 : text.hashCode());
294 result = prime * result + id;
295 result = prime * result + ((locale == null) ? 0 : locale.hashCode());
296 result = prime * result + recognitionModes;
297 result = prime * result + Arrays.hashCode(users);
298 return result;
299 }
300
301 @Override
302 public boolean equals(Object obj) {
303 if (this == obj)
304 return true;
305 if (obj == null)
306 return false;
307 if (getClass() != obj.getClass())
308 return false;
309 Keyphrase other = (Keyphrase) obj;
310 if (text == null) {
311 if (other.text != null)
312 return false;
313 } else if (!text.equals(other.text))
314 return false;
315 if (id != other.id)
316 return false;
317 if (locale == null) {
318 if (other.locale != null)
319 return false;
320 } else if (!locale.equals(other.locale))
321 return false;
322 if (recognitionModes != other.recognitionModes)
323 return false;
324 if (!Arrays.equals(users, other.users))
325 return false;
326 return true;
327 }
328
329 @Override
330 public String toString() {
331 return "Keyphrase [id=" + id + ", recognitionModes=" + recognitionModes + ", locale="
332 + locale + ", text=" + text + ", users=" + Arrays.toString(users) + "]";
333 }
Eric Laurente48188c2014-04-18 17:44:11 -0700334 }
335
336 /*****************************************************************************
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700337 * A KeyphraseSoundModel is a specialized {@link SoundModel} for key phrases.
Eric Laurente48188c2014-04-18 17:44:11 -0700338 * It contains data needed by the hardware to detect a certain number of key phrases
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700339 * and the list of corresponding {@link Keyphrase} descriptors.
Eric Laurente48188c2014-04-18 17:44:11 -0700340 ****************************************************************************/
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700341 public static class KeyphraseSoundModel extends SoundModel implements Parcelable {
Eric Laurente48188c2014-04-18 17:44:11 -0700342 /** Key phrases in this sound model */
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700343 public final Keyphrase[] keyphrases; // keyword phrases in model
Eric Laurente48188c2014-04-18 17:44:11 -0700344
Eric Laurentd3b82232014-07-30 08:57:39 -0700345 public KeyphraseSoundModel(
346 UUID uuid, UUID vendorUuid, byte[] data, Keyphrase[] keyphrases) {
347 super(uuid, vendorUuid, TYPE_KEYPHRASE, data);
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700348 this.keyphrases = keyphrases;
Eric Laurente48188c2014-04-18 17:44:11 -0700349 }
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700350
351 public static final Parcelable.Creator<KeyphraseSoundModel> CREATOR
352 = new Parcelable.Creator<KeyphraseSoundModel>() {
353 public KeyphraseSoundModel createFromParcel(Parcel in) {
354 return KeyphraseSoundModel.fromParcel(in);
355 }
356
357 public KeyphraseSoundModel[] newArray(int size) {
358 return new KeyphraseSoundModel[size];
359 }
360 };
361
362 private static KeyphraseSoundModel fromParcel(Parcel in) {
363 UUID uuid = UUID.fromString(in.readString());
Eric Laurentd3b82232014-07-30 08:57:39 -0700364 UUID vendorUuid = null;
365 int length = in.readInt();
366 if (length >= 0) {
367 vendorUuid = UUID.fromString(in.readString());
368 }
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -0700369 byte[] data = in.readBlob();
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700370 Keyphrase[] keyphrases = in.createTypedArray(Keyphrase.CREATOR);
Eric Laurentd3b82232014-07-30 08:57:39 -0700371 return new KeyphraseSoundModel(uuid, vendorUuid, data, keyphrases);
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700372 }
373
374 @Override
375 public int describeContents() {
376 return 0;
377 }
378
379 @Override
380 public void writeToParcel(Parcel dest, int flags) {
381 dest.writeString(uuid.toString());
Eric Laurentd3b82232014-07-30 08:57:39 -0700382 if (vendorUuid == null) {
383 dest.writeInt(-1);
384 } else {
385 dest.writeInt(vendorUuid.toString().length());
386 dest.writeString(vendorUuid.toString());
387 }
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -0700388 dest.writeBlob(data);
Sandeep Siddhartha68173372014-07-28 13:25:30 -0700389 dest.writeTypedArray(keyphrases, flags);
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700390 }
Sandeep Siddhartha110f5692014-07-20 12:22:56 -0700391
392 @Override
393 public String toString() {
Eric Laurentd3b82232014-07-30 08:57:39 -0700394 return "KeyphraseSoundModel [keyphrases=" + Arrays.toString(keyphrases)
395 + ", uuid=" + uuid + ", vendorUuid=" + vendorUuid
396 + ", type=" + type + ", data=" + (data == null ? 0 : data.length) + "]";
Sandeep Siddhartha110f5692014-07-20 12:22:56 -0700397 }
Eric Laurente48188c2014-04-18 17:44:11 -0700398 }
399
400 /**
401 * Modes for key phrase recognition
402 */
403 /** Simple recognition of the key phrase */
404 public static final int RECOGNITION_MODE_VOICE_TRIGGER = 0x1;
405 /** Trigger only if one user is identified */
406 public static final int RECOGNITION_MODE_USER_IDENTIFICATION = 0x2;
407 /** Trigger only if one user is authenticated */
408 public static final int RECOGNITION_MODE_USER_AUTHENTICATION = 0x4;
409
410 /**
411 * Status codes for {@link RecognitionEvent}
412 */
413 /** Recognition success */
414 public static final int RECOGNITION_STATUS_SUCCESS = 0;
415 /** Recognition aborted (e.g. capture preempted by anotehr use case */
416 public static final int RECOGNITION_STATUS_ABORT = 1;
417 /** Recognition failure */
418 public static final int RECOGNITION_STATUS_FAILURE = 2;
419
420 /**
421 * A RecognitionEvent is provided by the
422 * {@link StatusListener#onRecognition(RecognitionEvent)}
423 * callback upon recognition success or failure.
424 */
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -0700425 public static class RecognitionEvent implements Parcelable {
Eric Laurente48188c2014-04-18 17:44:11 -0700426 /** Recognition status e.g {@link #RECOGNITION_STATUS_SUCCESS} */
427 public final int status;
428 /** Sound Model corresponding to this event callback */
429 public final int soundModelHandle;
430 /** True if it is possible to capture audio from this utterance buffered by the hardware */
431 public final boolean captureAvailable;
432 /** Audio session ID to be used when capturing the utterance with an AudioRecord
433 * if captureAvailable() is true. */
434 public final int captureSession;
435 /** Delay in ms between end of model detection and start of audio available for capture.
436 * A negative value is possible (e.g. if keyphrase is also available for capture) */
437 public final int captureDelayMs;
Eric Laurent013f66b2014-07-06 16:35:00 -0700438 /** Duration in ms of audio captured before the start of the trigger. 0 if none. */
439 public final int capturePreambleMs;
Eric Laurentd3b82232014-07-30 08:57:39 -0700440 /** True if the trigger (key phrase capture is present in binary data */
441 public final boolean triggerInData;
442 /** Audio format of either the trigger in event data or to use for capture of the
443 * rest of the utterance */
444 public AudioFormat captureFormat;
Eric Laurente48188c2014-04-18 17:44:11 -0700445 /** Opaque data for use by system applications who know about voice engine internals,
446 * typically during enrollment. */
447 public final byte[] data;
448
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -0700449 public RecognitionEvent(int status, int soundModelHandle, boolean captureAvailable,
Eric Laurentd3b82232014-07-30 08:57:39 -0700450 int captureSession, int captureDelayMs, int capturePreambleMs,
451 boolean triggerInData, AudioFormat captureFormat, byte[] data) {
Eric Laurente48188c2014-04-18 17:44:11 -0700452 this.status = status;
453 this.soundModelHandle = soundModelHandle;
454 this.captureAvailable = captureAvailable;
455 this.captureSession = captureSession;
456 this.captureDelayMs = captureDelayMs;
Eric Laurent013f66b2014-07-06 16:35:00 -0700457 this.capturePreambleMs = capturePreambleMs;
Eric Laurentd3b82232014-07-30 08:57:39 -0700458 this.triggerInData = triggerInData;
459 this.captureFormat = captureFormat;
Eric Laurente48188c2014-04-18 17:44:11 -0700460 this.data = data;
461 }
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -0700462
463 public static final Parcelable.Creator<RecognitionEvent> CREATOR
464 = new Parcelable.Creator<RecognitionEvent>() {
465 public RecognitionEvent createFromParcel(Parcel in) {
466 return RecognitionEvent.fromParcel(in);
467 }
468
469 public RecognitionEvent[] newArray(int size) {
470 return new RecognitionEvent[size];
471 }
472 };
473
474 private static RecognitionEvent fromParcel(Parcel in) {
475 int status = in.readInt();
476 int soundModelHandle = in.readInt();
477 boolean captureAvailable = in.readByte() == 1;
478 int captureSession = in.readInt();
479 int captureDelayMs = in.readInt();
480 int capturePreambleMs = in.readInt();
Eric Laurentd3b82232014-07-30 08:57:39 -0700481 boolean triggerInData = in.readByte() == 1;
482 AudioFormat captureFormat = null;
Eric Laurent39fcca02014-09-05 16:44:19 -0700483 if (in.readByte() == 1) {
Eric Laurentd3b82232014-07-30 08:57:39 -0700484 int sampleRate = in.readInt();
485 int encoding = in.readInt();
486 int channelMask = in.readInt();
487 captureFormat = (new AudioFormat.Builder())
488 .setChannelMask(channelMask)
489 .setEncoding(encoding)
490 .setSampleRate(sampleRate)
491 .build();
492 }
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -0700493 byte[] data = in.readBlob();
494 return new RecognitionEvent(status, soundModelHandle, captureAvailable, captureSession,
Eric Laurentd3b82232014-07-30 08:57:39 -0700495 captureDelayMs, capturePreambleMs, triggerInData, captureFormat, data);
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -0700496 }
497
498 @Override
499 public int describeContents() {
500 return 0;
501 }
502
503 @Override
504 public void writeToParcel(Parcel dest, int flags) {
505 dest.writeInt(status);
506 dest.writeInt(soundModelHandle);
507 dest.writeByte((byte) (captureAvailable ? 1 : 0));
508 dest.writeInt(captureSession);
509 dest.writeInt(captureDelayMs);
510 dest.writeInt(capturePreambleMs);
Eric Laurent39fcca02014-09-05 16:44:19 -0700511 dest.writeByte((byte) (triggerInData ? 1 : 0));
512 if (captureFormat != null) {
Eric Laurentd3b82232014-07-30 08:57:39 -0700513 dest.writeByte((byte)1);
514 dest.writeInt(captureFormat.getSampleRate());
515 dest.writeInt(captureFormat.getEncoding());
516 dest.writeInt(captureFormat.getChannelMask());
517 } else {
518 dest.writeByte((byte)0);
519 }
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -0700520 dest.writeBlob(data);
521 }
522
523 @Override
524 public int hashCode() {
525 final int prime = 31;
526 int result = 1;
527 result = prime * result + (captureAvailable ? 1231 : 1237);
528 result = prime * result + captureDelayMs;
529 result = prime * result + capturePreambleMs;
530 result = prime * result + captureSession;
Eric Laurentd3b82232014-07-30 08:57:39 -0700531 result = prime * result + (triggerInData ? 1231 : 1237);
532 if (captureFormat != null) {
533 result = prime * result + captureFormat.getSampleRate();
534 result = prime * result + captureFormat.getEncoding();
535 result = prime * result + captureFormat.getChannelMask();
536 }
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -0700537 result = prime * result + Arrays.hashCode(data);
538 result = prime * result + soundModelHandle;
539 result = prime * result + status;
540 return result;
541 }
542
543 @Override
544 public boolean equals(Object obj) {
545 if (this == obj)
546 return true;
547 if (obj == null)
548 return false;
549 if (getClass() != obj.getClass())
550 return false;
551 RecognitionEvent other = (RecognitionEvent) obj;
552 if (captureAvailable != other.captureAvailable)
553 return false;
554 if (captureDelayMs != other.captureDelayMs)
555 return false;
556 if (capturePreambleMs != other.capturePreambleMs)
557 return false;
558 if (captureSession != other.captureSession)
559 return false;
560 if (!Arrays.equals(data, other.data))
561 return false;
562 if (soundModelHandle != other.soundModelHandle)
563 return false;
564 if (status != other.status)
565 return false;
Eric Laurentd3b82232014-07-30 08:57:39 -0700566 if (triggerInData != other.triggerInData)
567 return false;
568 if (captureFormat.getSampleRate() != other.captureFormat.getSampleRate())
569 return false;
570 if (captureFormat.getEncoding() != other.captureFormat.getEncoding())
571 return false;
572 if (captureFormat.getChannelMask() != other.captureFormat.getChannelMask())
573 return false;
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -0700574 return true;
575 }
Sandeep Siddhartha68173372014-07-28 13:25:30 -0700576
577 @Override
578 public String toString() {
579 return "RecognitionEvent [status=" + status + ", soundModelHandle=" + soundModelHandle
580 + ", captureAvailable=" + captureAvailable + ", captureSession="
581 + captureSession + ", captureDelayMs=" + captureDelayMs
582 + ", capturePreambleMs=" + capturePreambleMs
Eric Laurentd3b82232014-07-30 08:57:39 -0700583 + ", triggerInData=" + triggerInData
584 + ((captureFormat == null) ? "" :
585 (", sampleRate=" + captureFormat.getSampleRate()))
586 + ((captureFormat == null) ? "" :
587 (", encoding=" + captureFormat.getEncoding()))
588 + ((captureFormat == null) ? "" :
589 (", channelMask=" + captureFormat.getChannelMask()))
Sandeep Siddhartha68173372014-07-28 13:25:30 -0700590 + ", data=" + (data == null ? 0 : data.length) + "]";
591 }
Eric Laurente48188c2014-04-18 17:44:11 -0700592 }
593
594 /**
Eric Laurent013f66b2014-07-06 16:35:00 -0700595 * A RecognitionConfig is provided to
596 * {@link SoundTriggerModule#startRecognition(int, RecognitionConfig)} to configure the
597 * recognition request.
598 */
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700599 public static class RecognitionConfig implements Parcelable {
Eric Laurent013f66b2014-07-06 16:35:00 -0700600 /** True if the DSP should capture the trigger sound and make it available for further
601 * capture. */
602 public final boolean captureRequested;
Sandeep Siddhartha2c0273e2014-08-01 11:32:03 -0700603 /**
604 * True if the service should restart listening after the DSP triggers.
605 * Note: This config flag is currently used at the service layer rather than by the DSP.
606 */
607 public final boolean allowMultipleTriggers;
Eric Laurent013f66b2014-07-06 16:35:00 -0700608 /** List of all keyphrases in the sound model for which recognition should be performed with
609 * options for each keyphrase. */
610 public final KeyphraseRecognitionExtra keyphrases[];
611 /** Opaque data for use by system applications who know about voice engine internals,
612 * typically during enrollment. */
613 public final byte[] data;
614
Sandeep Siddhartha2c0273e2014-08-01 11:32:03 -0700615 public RecognitionConfig(boolean captureRequested, boolean allowMultipleTriggers,
Eric Laurent013f66b2014-07-06 16:35:00 -0700616 KeyphraseRecognitionExtra keyphrases[], byte[] data) {
617 this.captureRequested = captureRequested;
Sandeep Siddhartha2c0273e2014-08-01 11:32:03 -0700618 this.allowMultipleTriggers = allowMultipleTriggers;
Eric Laurent013f66b2014-07-06 16:35:00 -0700619 this.keyphrases = keyphrases;
620 this.data = data;
621 }
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700622
623 public static final Parcelable.Creator<RecognitionConfig> CREATOR
624 = new Parcelable.Creator<RecognitionConfig>() {
625 public RecognitionConfig createFromParcel(Parcel in) {
626 return RecognitionConfig.fromParcel(in);
627 }
628
629 public RecognitionConfig[] newArray(int size) {
630 return new RecognitionConfig[size];
631 }
632 };
633
634 private static RecognitionConfig fromParcel(Parcel in) {
635 boolean captureRequested = in.readByte() == 1;
Sandeep Siddhartha2c0273e2014-08-01 11:32:03 -0700636 boolean allowMultipleTriggers = in.readByte() == 1;
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700637 KeyphraseRecognitionExtra[] keyphrases =
638 in.createTypedArray(KeyphraseRecognitionExtra.CREATOR);
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -0700639 byte[] data = in.readBlob();
Sandeep Siddhartha2c0273e2014-08-01 11:32:03 -0700640 return new RecognitionConfig(captureRequested, allowMultipleTriggers, keyphrases, data);
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700641 }
642
643 @Override
644 public void writeToParcel(Parcel dest, int flags) {
645 dest.writeByte((byte) (captureRequested ? 1 : 0));
Sandeep Siddhartha2c0273e2014-08-01 11:32:03 -0700646 dest.writeByte((byte) (allowMultipleTriggers ? 1 : 0));
Sandeep Siddhartha68173372014-07-28 13:25:30 -0700647 dest.writeTypedArray(keyphrases, flags);
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -0700648 dest.writeBlob(data);
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700649 }
650
651 @Override
652 public int describeContents() {
653 return 0;
654 }
Sandeep Siddhartha110f5692014-07-20 12:22:56 -0700655
656 @Override
657 public String toString() {
Sandeep Siddhartha2c0273e2014-08-01 11:32:03 -0700658 return "RecognitionConfig [captureRequested=" + captureRequested
659 + ", allowMultipleTriggers=" + allowMultipleTriggers + ", keyphrases="
660 + Arrays.toString(keyphrases) + ", data=" + Arrays.toString(data) + "]";
Sandeep Siddhartha110f5692014-07-20 12:22:56 -0700661 }
Eric Laurent013f66b2014-07-06 16:35:00 -0700662 }
663
664 /**
665 * Confidence level for users defined in a keyphrase.
666 * - The confidence level is expressed in percent (0% -100%).
667 * When used in a {@link KeyphraseRecognitionEvent} it indicates the detected confidence level
668 * When used in a {@link RecognitionConfig} it indicates the minimum confidence level that
669 * should trigger a recognition.
670 * - The user ID is derived from the system ID {@link android.os.UserHandle#getIdentifier()}.
671 */
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700672 public static class ConfidenceLevel implements Parcelable {
Eric Laurent013f66b2014-07-06 16:35:00 -0700673 public final int userId;
674 public final int confidenceLevel;
675
676 public ConfidenceLevel(int userId, int confidenceLevel) {
677 this.userId = userId;
678 this.confidenceLevel = confidenceLevel;
679 }
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700680
681 public static final Parcelable.Creator<ConfidenceLevel> CREATOR
682 = new Parcelable.Creator<ConfidenceLevel>() {
683 public ConfidenceLevel createFromParcel(Parcel in) {
684 return ConfidenceLevel.fromParcel(in);
685 }
686
687 public ConfidenceLevel[] newArray(int size) {
688 return new ConfidenceLevel[size];
689 }
690 };
691
692 private static ConfidenceLevel fromParcel(Parcel in) {
693 int userId = in.readInt();
694 int confidenceLevel = in.readInt();
695 return new ConfidenceLevel(userId, confidenceLevel);
696 }
697
698 @Override
699 public void writeToParcel(Parcel dest, int flags) {
700 dest.writeInt(userId);
701 dest.writeInt(confidenceLevel);
702 }
703
704 @Override
705 public int describeContents() {
706 return 0;
707 }
Sandeep Siddhartha68173372014-07-28 13:25:30 -0700708
709 @Override
710 public int hashCode() {
711 final int prime = 31;
712 int result = 1;
713 result = prime * result + confidenceLevel;
714 result = prime * result + userId;
715 return result;
716 }
717
718 @Override
719 public boolean equals(Object obj) {
720 if (this == obj)
721 return true;
722 if (obj == null)
723 return false;
724 if (getClass() != obj.getClass())
725 return false;
726 ConfidenceLevel other = (ConfidenceLevel) obj;
727 if (confidenceLevel != other.confidenceLevel)
728 return false;
729 if (userId != other.userId)
730 return false;
731 return true;
732 }
733
734 @Override
735 public String toString() {
736 return "ConfidenceLevel [userId=" + userId
737 + ", confidenceLevel=" + confidenceLevel + "]";
738 }
Eric Laurent013f66b2014-07-06 16:35:00 -0700739 }
740
741 /**
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700742 * Additional data conveyed by a {@link KeyphraseRecognitionEvent}
Eric Laurente48188c2014-04-18 17:44:11 -0700743 * for a key phrase detection.
744 */
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700745 public static class KeyphraseRecognitionExtra implements Parcelable {
746 /** The keyphrase ID */
Eric Laurent013f66b2014-07-06 16:35:00 -0700747 public final int id;
Eric Laurente48188c2014-04-18 17:44:11 -0700748
749 /** Recognition modes matched for this event */
750 public final int recognitionModes;
751
Eric Laurentd3b82232014-07-30 08:57:39 -0700752 /** Confidence level for mode RECOGNITION_MODE_VOICE_TRIGGER when user identification
753 * is not performed */
754 public final int coarseConfidenceLevel;
755
Eric Laurent013f66b2014-07-06 16:35:00 -0700756 /** Confidence levels for all users recognized (KeyphraseRecognitionEvent) or to
757 * be recognized (RecognitionConfig) */
758 public final ConfidenceLevel[] confidenceLevels;
759
Eric Laurentd3b82232014-07-30 08:57:39 -0700760 public KeyphraseRecognitionExtra(int id, int recognitionModes, int coarseConfidenceLevel,
761 ConfidenceLevel[] confidenceLevels) {
Eric Laurent013f66b2014-07-06 16:35:00 -0700762 this.id = id;
Eric Laurente48188c2014-04-18 17:44:11 -0700763 this.recognitionModes = recognitionModes;
Eric Laurentd3b82232014-07-30 08:57:39 -0700764 this.coarseConfidenceLevel = coarseConfidenceLevel;
Eric Laurent013f66b2014-07-06 16:35:00 -0700765 this.confidenceLevels = confidenceLevels;
Eric Laurente48188c2014-04-18 17:44:11 -0700766 }
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700767
768 public static final Parcelable.Creator<KeyphraseRecognitionExtra> CREATOR
769 = new Parcelable.Creator<KeyphraseRecognitionExtra>() {
770 public KeyphraseRecognitionExtra createFromParcel(Parcel in) {
771 return KeyphraseRecognitionExtra.fromParcel(in);
772 }
773
774 public KeyphraseRecognitionExtra[] newArray(int size) {
775 return new KeyphraseRecognitionExtra[size];
776 }
777 };
778
779 private static KeyphraseRecognitionExtra fromParcel(Parcel in) {
780 int id = in.readInt();
781 int recognitionModes = in.readInt();
Eric Laurentd3b82232014-07-30 08:57:39 -0700782 int coarseConfidenceLevel = in.readInt();
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700783 ConfidenceLevel[] confidenceLevels = in.createTypedArray(ConfidenceLevel.CREATOR);
Eric Laurentd3b82232014-07-30 08:57:39 -0700784 return new KeyphraseRecognitionExtra(id, recognitionModes, coarseConfidenceLevel,
785 confidenceLevels);
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700786 }
787
788 @Override
789 public void writeToParcel(Parcel dest, int flags) {
790 dest.writeInt(id);
791 dest.writeInt(recognitionModes);
Eric Laurentd3b82232014-07-30 08:57:39 -0700792 dest.writeInt(coarseConfidenceLevel);
Sandeep Siddhartha68173372014-07-28 13:25:30 -0700793 dest.writeTypedArray(confidenceLevels, flags);
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700794 }
795
796 @Override
797 public int describeContents() {
798 return 0;
799 }
Sandeep Siddhartha68173372014-07-28 13:25:30 -0700800
801 @Override
802 public int hashCode() {
803 final int prime = 31;
804 int result = 1;
805 result = prime * result + Arrays.hashCode(confidenceLevels);
806 result = prime * result + id;
807 result = prime * result + recognitionModes;
Eric Laurentd3b82232014-07-30 08:57:39 -0700808 result = prime * result + coarseConfidenceLevel;
Sandeep Siddhartha68173372014-07-28 13:25:30 -0700809 return result;
810 }
811
812 @Override
813 public boolean equals(Object obj) {
814 if (this == obj)
815 return true;
816 if (obj == null)
817 return false;
818 if (getClass() != obj.getClass())
819 return false;
820 KeyphraseRecognitionExtra other = (KeyphraseRecognitionExtra) obj;
821 if (!Arrays.equals(confidenceLevels, other.confidenceLevels))
822 return false;
823 if (id != other.id)
824 return false;
825 if (recognitionModes != other.recognitionModes)
826 return false;
Eric Laurentd3b82232014-07-30 08:57:39 -0700827 if (coarseConfidenceLevel != other.coarseConfidenceLevel)
828 return false;
Sandeep Siddhartha68173372014-07-28 13:25:30 -0700829 return true;
830 }
831
832 @Override
833 public String toString() {
834 return "KeyphraseRecognitionExtra [id=" + id + ", recognitionModes=" + recognitionModes
Eric Laurentd3b82232014-07-30 08:57:39 -0700835 + ", coarseConfidenceLevel=" + coarseConfidenceLevel
Sandeep Siddhartha68173372014-07-28 13:25:30 -0700836 + ", confidenceLevels=" + Arrays.toString(confidenceLevels) + "]";
837 }
Eric Laurente48188c2014-04-18 17:44:11 -0700838 }
839
840 /**
841 * Specialized {@link RecognitionEvent} for a key phrase detection.
842 */
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700843 public static class KeyphraseRecognitionEvent extends RecognitionEvent {
Eric Laurente48188c2014-04-18 17:44:11 -0700844 /** Indicates if the key phrase is present in the buffered audio available for capture */
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700845 public final KeyphraseRecognitionExtra[] keyphraseExtras;
Eric Laurente48188c2014-04-18 17:44:11 -0700846
Sandeep Siddhartha68173372014-07-28 13:25:30 -0700847 public KeyphraseRecognitionEvent(int status, int soundModelHandle, boolean captureAvailable,
Eric Laurentd3b82232014-07-30 08:57:39 -0700848 int captureSession, int captureDelayMs, int capturePreambleMs,
849 boolean triggerInData, AudioFormat captureFormat, byte[] data,
850 KeyphraseRecognitionExtra[] keyphraseExtras) {
Eric Laurent013f66b2014-07-06 16:35:00 -0700851 super(status, soundModelHandle, captureAvailable, captureSession, captureDelayMs,
Eric Laurentd3b82232014-07-30 08:57:39 -0700852 capturePreambleMs, triggerInData, captureFormat, data);
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700853 this.keyphraseExtras = keyphraseExtras;
Eric Laurente48188c2014-04-18 17:44:11 -0700854 }
Sandeep Siddhartha68173372014-07-28 13:25:30 -0700855
856 public static final Parcelable.Creator<KeyphraseRecognitionEvent> CREATOR
857 = new Parcelable.Creator<KeyphraseRecognitionEvent>() {
858 public KeyphraseRecognitionEvent createFromParcel(Parcel in) {
859 return KeyphraseRecognitionEvent.fromParcel(in);
860 }
861
862 public KeyphraseRecognitionEvent[] newArray(int size) {
863 return new KeyphraseRecognitionEvent[size];
864 }
865 };
866
867 private static KeyphraseRecognitionEvent fromParcel(Parcel in) {
868 int status = in.readInt();
869 int soundModelHandle = in.readInt();
870 boolean captureAvailable = in.readByte() == 1;
871 int captureSession = in.readInt();
872 int captureDelayMs = in.readInt();
873 int capturePreambleMs = in.readInt();
Eric Laurentd3b82232014-07-30 08:57:39 -0700874 boolean triggerInData = in.readByte() == 1;
875 AudioFormat captureFormat = null;
876 if (triggerInData) {
877 int sampleRate = in.readInt();
878 int encoding = in.readInt();
879 int channelMask = in.readInt();
880 captureFormat = (new AudioFormat.Builder())
881 .setChannelMask(channelMask)
882 .setEncoding(encoding)
883 .setSampleRate(sampleRate)
884 .build();
885 }
Sandeep Siddhartha68173372014-07-28 13:25:30 -0700886 byte[] data = in.readBlob();
Sandeep Siddhartha68173372014-07-28 13:25:30 -0700887 KeyphraseRecognitionExtra[] keyphraseExtras =
888 in.createTypedArray(KeyphraseRecognitionExtra.CREATOR);
889 return new KeyphraseRecognitionEvent(status, soundModelHandle, captureAvailable,
Eric Laurentd3b82232014-07-30 08:57:39 -0700890 captureSession, captureDelayMs, capturePreambleMs, triggerInData,
891 captureFormat, data, keyphraseExtras);
Sandeep Siddhartha68173372014-07-28 13:25:30 -0700892 }
893
894 @Override
895 public void writeToParcel(Parcel dest, int flags) {
896 dest.writeInt(status);
897 dest.writeInt(soundModelHandle);
898 dest.writeByte((byte) (captureAvailable ? 1 : 0));
899 dest.writeInt(captureSession);
900 dest.writeInt(captureDelayMs);
901 dest.writeInt(capturePreambleMs);
Eric Laurentd3b82232014-07-30 08:57:39 -0700902 if (triggerInData && (captureFormat != null)) {
903 dest.writeByte((byte)1);
904 dest.writeInt(captureFormat.getSampleRate());
905 dest.writeInt(captureFormat.getEncoding());
906 dest.writeInt(captureFormat.getChannelMask());
907 } else {
908 dest.writeByte((byte)0);
909 }
Sandeep Siddhartha68173372014-07-28 13:25:30 -0700910 dest.writeBlob(data);
Sandeep Siddhartha68173372014-07-28 13:25:30 -0700911 dest.writeTypedArray(keyphraseExtras, flags);
912 }
913
914 @Override
915 public int describeContents() {
916 return 0;
917 }
918
919 @Override
920 public int hashCode() {
921 final int prime = 31;
922 int result = super.hashCode();
923 result = prime * result + Arrays.hashCode(keyphraseExtras);
Sandeep Siddhartha68173372014-07-28 13:25:30 -0700924 return result;
925 }
926
927 @Override
928 public boolean equals(Object obj) {
929 if (this == obj)
930 return true;
931 if (!super.equals(obj))
932 return false;
933 if (getClass() != obj.getClass())
934 return false;
935 KeyphraseRecognitionEvent other = (KeyphraseRecognitionEvent) obj;
936 if (!Arrays.equals(keyphraseExtras, other.keyphraseExtras))
937 return false;
Sandeep Siddhartha68173372014-07-28 13:25:30 -0700938 return true;
939 }
940
941 @Override
942 public String toString() {
943 return "KeyphraseRecognitionEvent [keyphraseExtras=" + Arrays.toString(keyphraseExtras)
Eric Laurentd3b82232014-07-30 08:57:39 -0700944 + ", status=" + status
Sandeep Siddhartha68173372014-07-28 13:25:30 -0700945 + ", soundModelHandle=" + soundModelHandle + ", captureAvailable="
946 + captureAvailable + ", captureSession=" + captureSession + ", captureDelayMs="
947 + captureDelayMs + ", capturePreambleMs=" + capturePreambleMs
Eric Laurentd3b82232014-07-30 08:57:39 -0700948 + ", triggerInData=" + triggerInData
949 + ((captureFormat == null) ? "" :
950 (", sampleRate=" + captureFormat.getSampleRate()))
951 + ((captureFormat == null) ? "" :
952 (", encoding=" + captureFormat.getEncoding()))
953 + ((captureFormat == null) ? "" :
954 (", channelMask=" + captureFormat.getChannelMask()))
Sandeep Siddhartha68173372014-07-28 13:25:30 -0700955 + ", data=" + (data == null ? 0 : data.length) + "]";
956 }
Eric Laurente48188c2014-04-18 17:44:11 -0700957 }
958
959 /**
Eric Laurentd3b82232014-07-30 08:57:39 -0700960 * Status codes for {@link SoundModelEvent}
961 */
962 /** Sound Model was updated */
963 public static final int SOUNDMODEL_STATUS_UPDATED = 0;
964
965 /**
966 * A SoundModelEvent is provided by the
967 * {@link StatusListener#onSoundModelUpdate(SoundModelEvent)}
968 * callback when a sound model has been updated by the implementation
969 */
970 public static class SoundModelEvent implements Parcelable {
971 /** Status e.g {@link #SOUNDMODEL_STATUS_UPDATED} */
972 public final int status;
973 /** The updated sound model handle */
974 public final int soundModelHandle;
975 /** New sound model data */
976 public final byte[] data;
977
978 SoundModelEvent(int status, int soundModelHandle, byte[] data) {
979 this.status = status;
980 this.soundModelHandle = soundModelHandle;
981 this.data = data;
982 }
983
984 public static final Parcelable.Creator<SoundModelEvent> CREATOR
985 = new Parcelable.Creator<SoundModelEvent>() {
986 public SoundModelEvent createFromParcel(Parcel in) {
987 return SoundModelEvent.fromParcel(in);
988 }
989
990 public SoundModelEvent[] newArray(int size) {
991 return new SoundModelEvent[size];
992 }
993 };
994
995 private static SoundModelEvent fromParcel(Parcel in) {
996 int status = in.readInt();
997 int soundModelHandle = in.readInt();
998 byte[] data = in.readBlob();
999 return new SoundModelEvent(status, soundModelHandle, data);
1000 }
1001
1002 @Override
1003 public int describeContents() {
1004 return 0;
1005 }
1006
1007 @Override
1008 public void writeToParcel(Parcel dest, int flags) {
1009 dest.writeInt(status);
1010 dest.writeInt(soundModelHandle);
1011 dest.writeBlob(data);
1012 }
1013
1014 @Override
1015 public int hashCode() {
1016 final int prime = 31;
1017 int result = 1;
1018 result = prime * result + Arrays.hashCode(data);
1019 result = prime * result + soundModelHandle;
1020 result = prime * result + status;
1021 return result;
1022 }
1023
1024 @Override
1025 public boolean equals(Object obj) {
1026 if (this == obj)
1027 return true;
1028 if (obj == null)
1029 return false;
1030 if (getClass() != obj.getClass())
1031 return false;
1032 SoundModelEvent other = (SoundModelEvent) obj;
1033 if (!Arrays.equals(data, other.data))
1034 return false;
1035 if (soundModelHandle != other.soundModelHandle)
1036 return false;
1037 if (status != other.status)
1038 return false;
1039 return true;
1040 }
1041
1042 @Override
1043 public String toString() {
1044 return "SoundModelEvent [status=" + status + ", soundModelHandle=" + soundModelHandle
1045 + ", data=" + (data == null ? 0 : data.length) + "]";
1046 }
1047 }
1048
1049 /**
1050 * Native service state. {@link StatusListener#onServiceStateChange(int)}
1051 */
1052 // Keep in sync with system/core/include/system/sound_trigger.h
1053 /** Sound trigger service is enabled */
1054 public static final int SERVICE_STATE_ENABLED = 0;
1055 /** Sound trigger service is disabled */
1056 public static final int SERVICE_STATE_DISABLED = 1;
1057
1058 /**
Eric Laurente48188c2014-04-18 17:44:11 -07001059 * Returns a list of descriptors for all harware modules loaded.
1060 * @param modules A ModuleProperties array where the list will be returned.
1061 * @return - {@link #STATUS_OK} in case of success
1062 * - {@link #STATUS_ERROR} in case of unspecified error
1063 * - {@link #STATUS_PERMISSION_DENIED} if the caller does not have system permission
1064 * - {@link #STATUS_NO_INIT} if the native service cannot be reached
1065 * - {@link #STATUS_BAD_VALUE} if modules is null
1066 * - {@link #STATUS_DEAD_OBJECT} if the binder transaction to the native service fails
1067 */
1068 public static native int listModules(ArrayList <ModuleProperties> modules);
1069
1070 /**
1071 * Get an interface on a hardware module to control sound models and recognition on
1072 * this module.
1073 * @param moduleId Sound module system identifier {@link ModuleProperties#id}. mandatory.
1074 * @param listener {@link StatusListener} interface. Mandatory.
1075 * @param handler the Handler that will receive the callabcks. Can be null if default handler
1076 * is OK.
1077 * @return a valid sound module in case of success or null in case of error.
1078 */
1079 public static SoundTriggerModule attachModule(int moduleId,
1080 StatusListener listener,
1081 Handler handler) {
1082 if (listener == null) {
1083 return null;
1084 }
1085 SoundTriggerModule module = new SoundTriggerModule(moduleId, listener, handler);
1086 return module;
1087 }
1088
1089 /**
1090 * Interface provided by the client application when attaching to a {@link SoundTriggerModule}
1091 * to received recognition and error notifications.
1092 */
1093 public static interface StatusListener {
1094 /**
1095 * Called when recognition succeeds of fails
1096 */
1097 public abstract void onRecognition(RecognitionEvent event);
1098
1099 /**
Eric Laurentd3b82232014-07-30 08:57:39 -07001100 * Called when a sound model has been updated
1101 */
1102 public abstract void onSoundModelUpdate(SoundModelEvent event);
1103
1104 /**
1105 * Called when the sound trigger native service state changes.
1106 * @param state Native service state. One of {@link SoundTrigger#SERVICE_STATE_ENABLED},
1107 * {@link SoundTrigger#SERVICE_STATE_DISABLED}
1108 */
1109 public abstract void onServiceStateChange(int state);
1110
1111 /**
Eric Laurente48188c2014-04-18 17:44:11 -07001112 * Called when the sound trigger native service dies
1113 */
1114 public abstract void onServiceDied();
1115 }
1116}