blob: 4498789cd69c8bc20d048d79f1c9a8a32586e487 [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 Laurente48188c2014-04-18 17:44:11 -070019import android.os.Handler;
Sandeep Siddhartha05589722014-07-17 16:21:54 -070020import android.os.Parcel;
21import android.os.Parcelable;
Eric Laurente48188c2014-04-18 17:44:11 -070022
23import java.util.ArrayList;
Sandeep Siddhartha05589722014-07-17 16:21:54 -070024import java.util.Arrays;
Eric Laurente48188c2014-04-18 17:44:11 -070025import java.util.UUID;
26
27/**
28 * The SoundTrigger class provides access via JNI to the native service managing
29 * the sound trigger HAL.
30 *
31 * @hide
32 */
33public class SoundTrigger {
34
35 public static final int STATUS_OK = 0;
36 public static final int STATUS_ERROR = Integer.MIN_VALUE;
37 public static final int STATUS_PERMISSION_DENIED = -1;
38 public static final int STATUS_NO_INIT = -19;
39 public static final int STATUS_BAD_VALUE = -22;
40 public static final int STATUS_DEAD_OBJECT = -32;
41 public static final int STATUS_INVALID_OPERATION = -38;
42
43 /*****************************************************************************
44 * A ModuleProperties describes a given sound trigger hardware module
45 * managed by the native sound trigger service. Each module has a unique
46 * ID used to target any API call to this paricular module. Module
47 * properties are returned by listModules() method.
48 ****************************************************************************/
Sandeep Siddhartha05589722014-07-17 16:21:54 -070049 public static class ModuleProperties implements Parcelable {
Eric Laurente48188c2014-04-18 17:44:11 -070050 /** Unique module ID provided by the native service */
51 public final int id;
52
53 /** human readable voice detection engine implementor */
54 public final String implementor;
55
56 /** human readable voice detection engine description */
57 public final String description;
58
59 /** Unique voice engine Id (changes with each version) */
60 public final UUID uuid;
61
62 /** Voice detection engine version */
63 public final int version;
64
65 /** Maximum number of active sound models */
66 public final int maxSoundModels;
67
68 /** Maximum number of key phrases */
Sandeep Siddharthad4233c62014-06-12 18:31:19 -070069 public final int maxKeyphrases;
Eric Laurente48188c2014-04-18 17:44:11 -070070
71 /** Maximum number of users per key phrase */
72 public final int maxUsers;
73
74 /** Supported recognition modes (bit field, RECOGNITION_MODE_VOICE_TRIGGER ...) */
75 public final int recognitionModes;
76
77 /** Supports seamless transition to capture mode after recognition */
78 public final boolean supportsCaptureTransition;
79
80 /** Maximum buffering capacity in ms if supportsCaptureTransition() is true */
81 public final int maxBufferMs;
82
83 /** Supports capture by other use cases while detection is active */
84 public final boolean supportsConcurrentCapture;
85
86 /** Rated power consumption when detection is active with TDB silence/sound/speech ratio */
87 public final int powerConsumptionMw;
88
89 ModuleProperties(int id, String implementor, String description,
Sandeep Siddharthad4233c62014-06-12 18:31:19 -070090 String uuid, int version, int maxSoundModels, int maxKeyphrases,
Eric Laurente48188c2014-04-18 17:44:11 -070091 int maxUsers, int recognitionModes, boolean supportsCaptureTransition,
92 int maxBufferMs, boolean supportsConcurrentCapture,
93 int powerConsumptionMw) {
94 this.id = id;
95 this.implementor = implementor;
96 this.description = description;
97 this.uuid = UUID.fromString(uuid);
98 this.version = version;
99 this.maxSoundModels = maxSoundModels;
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700100 this.maxKeyphrases = maxKeyphrases;
Eric Laurente48188c2014-04-18 17:44:11 -0700101 this.maxUsers = maxUsers;
102 this.recognitionModes = recognitionModes;
103 this.supportsCaptureTransition = supportsCaptureTransition;
104 this.maxBufferMs = maxBufferMs;
105 this.supportsConcurrentCapture = supportsConcurrentCapture;
106 this.powerConsumptionMw = powerConsumptionMw;
107 }
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700108
109 public static final Parcelable.Creator<ModuleProperties> CREATOR
110 = new Parcelable.Creator<ModuleProperties>() {
111 public ModuleProperties createFromParcel(Parcel in) {
112 return ModuleProperties.fromParcel(in);
113 }
114
115 public ModuleProperties[] newArray(int size) {
116 return new ModuleProperties[size];
117 }
118 };
119
120 private static ModuleProperties fromParcel(Parcel in) {
121 int id = in.readInt();
122 String implementor = in.readString();
123 String description = in.readString();
124 String uuid = in.readString();
125 int version = in.readInt();
126 int maxSoundModels = in.readInt();
127 int maxKeyphrases = in.readInt();
128 int maxUsers = in.readInt();
129 int recognitionModes = in.readInt();
130 boolean supportsCaptureTransition = in.readByte() == 1;
131 int maxBufferMs = in.readInt();
132 boolean supportsConcurrentCapture = in.readByte() == 1;
133 int powerConsumptionMw = in.readInt();
134 return new ModuleProperties(id, implementor, description, uuid, version,
135 maxSoundModels, maxKeyphrases, maxUsers, recognitionModes,
136 supportsCaptureTransition, maxBufferMs, supportsConcurrentCapture,
137 powerConsumptionMw);
138 }
139
140 @Override
141 public void writeToParcel(Parcel dest, int flags) {
142 dest.writeInt(id);
143 dest.writeString(implementor);
144 dest.writeString(description);
145 dest.writeString(uuid.toString());
146 dest.writeInt(version);
147 dest.writeInt(maxSoundModels);
148 dest.writeInt(maxKeyphrases);
149 dest.writeInt(maxUsers);
150 dest.writeInt(recognitionModes);
151 dest.writeByte((byte) (supportsCaptureTransition ? 1 : 0));
152 dest.writeInt(maxBufferMs);
153 dest.writeByte((byte) (supportsConcurrentCapture ? 1 : 0));
154 dest.writeInt(powerConsumptionMw);
155 }
156
157 @Override
158 public int describeContents() {
159 return 0;
160 }
161
162 @Override
163 public String toString() {
164 return "ModuleProperties [id=" + id + ", implementor=" + implementor + ", description="
165 + description + ", uuid=" + uuid + ", version=" + version + ", maxSoundModels="
166 + maxSoundModels + ", maxKeyphrases=" + maxKeyphrases + ", maxUsers="
167 + maxUsers + ", recognitionModes=" + recognitionModes
168 + ", supportsCaptureTransition=" + supportsCaptureTransition + ", maxBufferMs="
169 + maxBufferMs + ", supportsConcurrentCapture=" + supportsConcurrentCapture
170 + ", powerConsumptionMw=" + powerConsumptionMw + "]";
171 }
Eric Laurente48188c2014-04-18 17:44:11 -0700172 }
173
174 /*****************************************************************************
175 * A SoundModel describes the attributes and contains the binary data used by the hardware
176 * implementation to detect a particular sound pattern.
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700177 * A specialized version {@link KeyphraseSoundModel} is defined for key phrase
Eric Laurente48188c2014-04-18 17:44:11 -0700178 * sound models.
179 ****************************************************************************/
180 public static class SoundModel {
181 /** Undefined sound model type */
182 public static final int TYPE_UNKNOWN = -1;
183
184 /** Keyphrase sound model */
185 public static final int TYPE_KEYPHRASE = 0;
186
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700187 /** Unique sound model identifier */
188 public final UUID uuid;
189
Eric Laurente48188c2014-04-18 17:44:11 -0700190 /** Sound model type (e.g. TYPE_KEYPHRASE); */
191 public final int type;
192
193 /** Opaque data. For use by vendor implementation and enrollment application */
194 public final byte[] data;
195
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700196 public SoundModel(UUID uuid, int type, byte[] data) {
197 this.uuid = uuid;
Eric Laurente48188c2014-04-18 17:44:11 -0700198 this.type = type;
199 this.data = data;
200 }
201 }
202
203 /*****************************************************************************
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700204 * A Keyphrase describes a key phrase that can be detected by a
205 * {@link KeyphraseSoundModel}
Eric Laurente48188c2014-04-18 17:44:11 -0700206 ****************************************************************************/
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700207 public static class Keyphrase implements Parcelable {
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700208 /** Unique identifier for this keyphrase */
209 public final int id;
210
Eric Laurente48188c2014-04-18 17:44:11 -0700211 /** Recognition modes supported for this key phrase in the model */
212 public final int recognitionModes;
213
214 /** Locale of the keyphrase. JAVA Locale string e.g en_US */
215 public final String locale;
216
217 /** Key phrase text */
218 public final String text;
219
Eric Laurent013f66b2014-07-06 16:35:00 -0700220 /** Users this key phrase has been trained for. countains sound trigger specific user IDs
221 * derived from system user IDs {@link android.os.UserHandle#getIdentifier()}. */
222 public final int[] users;
Eric Laurente48188c2014-04-18 17:44:11 -0700223
Eric Laurent013f66b2014-07-06 16:35:00 -0700224 public Keyphrase(int id, int recognitionModes, String locale, String text, int[] users) {
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700225 this.id = id;
Eric Laurente48188c2014-04-18 17:44:11 -0700226 this.recognitionModes = recognitionModes;
227 this.locale = locale;
228 this.text = text;
Eric Laurent013f66b2014-07-06 16:35:00 -0700229 this.users = users;
Eric Laurente48188c2014-04-18 17:44:11 -0700230 }
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700231
232 public static final Parcelable.Creator<Keyphrase> CREATOR
233 = new Parcelable.Creator<Keyphrase>() {
234 public Keyphrase createFromParcel(Parcel in) {
235 return Keyphrase.fromParcel(in);
236 }
237
238 public Keyphrase[] newArray(int size) {
239 return new Keyphrase[size];
240 }
241 };
242
243 private static Keyphrase fromParcel(Parcel in) {
244 int id = in.readInt();
245 int recognitionModes = in.readInt();
246 String locale = in.readString();
247 String text = in.readString();
248 int[] users = null;
249 int numUsers = in.readInt();
Sandeep Siddhartha110f5692014-07-20 12:22:56 -0700250 if (numUsers >= 0) {
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700251 users = new int[numUsers];
252 in.readIntArray(users);
253 }
254 return new Keyphrase(id, recognitionModes, locale, text, users);
255 }
256
257 @Override
258 public void writeToParcel(Parcel dest, int flags) {
259 dest.writeInt(id);
260 dest.writeInt(recognitionModes);
261 dest.writeString(locale);
262 dest.writeString(text);
263 if (users != null) {
264 dest.writeInt(users.length);
265 dest.writeIntArray(users);
266 } else {
Sandeep Siddhartha110f5692014-07-20 12:22:56 -0700267 dest.writeInt(-1);
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700268 }
269 }
270
271 @Override
272 public int describeContents() {
273 return 0;
274 }
275
276 @Override
277 public int hashCode() {
278 final int prime = 31;
279 int result = 1;
280 result = prime * result + ((text == null) ? 0 : text.hashCode());
281 result = prime * result + id;
282 result = prime * result + ((locale == null) ? 0 : locale.hashCode());
283 result = prime * result + recognitionModes;
284 result = prime * result + Arrays.hashCode(users);
285 return result;
286 }
287
288 @Override
289 public boolean equals(Object obj) {
290 if (this == obj)
291 return true;
292 if (obj == null)
293 return false;
294 if (getClass() != obj.getClass())
295 return false;
296 Keyphrase other = (Keyphrase) obj;
297 if (text == null) {
298 if (other.text != null)
299 return false;
300 } else if (!text.equals(other.text))
301 return false;
302 if (id != other.id)
303 return false;
304 if (locale == null) {
305 if (other.locale != null)
306 return false;
307 } else if (!locale.equals(other.locale))
308 return false;
309 if (recognitionModes != other.recognitionModes)
310 return false;
311 if (!Arrays.equals(users, other.users))
312 return false;
313 return true;
314 }
315
316 @Override
317 public String toString() {
318 return "Keyphrase [id=" + id + ", recognitionModes=" + recognitionModes + ", locale="
319 + locale + ", text=" + text + ", users=" + Arrays.toString(users) + "]";
320 }
Eric Laurente48188c2014-04-18 17:44:11 -0700321 }
322
323 /*****************************************************************************
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700324 * A KeyphraseSoundModel is a specialized {@link SoundModel} for key phrases.
Eric Laurente48188c2014-04-18 17:44:11 -0700325 * It contains data needed by the hardware to detect a certain number of key phrases
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700326 * and the list of corresponding {@link Keyphrase} descriptors.
Eric Laurente48188c2014-04-18 17:44:11 -0700327 ****************************************************************************/
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700328 public static class KeyphraseSoundModel extends SoundModel implements Parcelable {
Eric Laurente48188c2014-04-18 17:44:11 -0700329 /** Key phrases in this sound model */
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700330 public final Keyphrase[] keyphrases; // keyword phrases in model
Eric Laurente48188c2014-04-18 17:44:11 -0700331
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700332 public KeyphraseSoundModel(UUID id, byte[] data, Keyphrase[] keyphrases) {
333 super(id, TYPE_KEYPHRASE, data);
334 this.keyphrases = keyphrases;
Eric Laurente48188c2014-04-18 17:44:11 -0700335 }
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700336
337 public static final Parcelable.Creator<KeyphraseSoundModel> CREATOR
338 = new Parcelable.Creator<KeyphraseSoundModel>() {
339 public KeyphraseSoundModel createFromParcel(Parcel in) {
340 return KeyphraseSoundModel.fromParcel(in);
341 }
342
343 public KeyphraseSoundModel[] newArray(int size) {
344 return new KeyphraseSoundModel[size];
345 }
346 };
347
348 private static KeyphraseSoundModel fromParcel(Parcel in) {
349 UUID uuid = UUID.fromString(in.readString());
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -0700350 byte[] data = in.readBlob();
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700351 Keyphrase[] keyphrases = in.createTypedArray(Keyphrase.CREATOR);
352 return new KeyphraseSoundModel(uuid, data, keyphrases);
353 }
354
355 @Override
356 public int describeContents() {
357 return 0;
358 }
359
360 @Override
361 public void writeToParcel(Parcel dest, int flags) {
362 dest.writeString(uuid.toString());
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -0700363 dest.writeBlob(data);
Sandeep Siddhartha68173372014-07-28 13:25:30 -0700364 dest.writeTypedArray(keyphrases, flags);
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700365 }
Sandeep Siddhartha110f5692014-07-20 12:22:56 -0700366
367 @Override
368 public String toString() {
369 return "KeyphraseSoundModel [keyphrases=" + Arrays.toString(keyphrases) + ", uuid="
Sandeep Siddhartha68173372014-07-28 13:25:30 -0700370 + uuid + ", type=" + type + ", data=" + (data == null ? 0 : data.length) + "]";
Sandeep Siddhartha110f5692014-07-20 12:22:56 -0700371 }
Eric Laurente48188c2014-04-18 17:44:11 -0700372 }
373
374 /**
375 * Modes for key phrase recognition
376 */
377 /** Simple recognition of the key phrase */
378 public static final int RECOGNITION_MODE_VOICE_TRIGGER = 0x1;
379 /** Trigger only if one user is identified */
380 public static final int RECOGNITION_MODE_USER_IDENTIFICATION = 0x2;
381 /** Trigger only if one user is authenticated */
382 public static final int RECOGNITION_MODE_USER_AUTHENTICATION = 0x4;
383
384 /**
385 * Status codes for {@link RecognitionEvent}
386 */
387 /** Recognition success */
388 public static final int RECOGNITION_STATUS_SUCCESS = 0;
389 /** Recognition aborted (e.g. capture preempted by anotehr use case */
390 public static final int RECOGNITION_STATUS_ABORT = 1;
391 /** Recognition failure */
392 public static final int RECOGNITION_STATUS_FAILURE = 2;
393
394 /**
395 * A RecognitionEvent is provided by the
396 * {@link StatusListener#onRecognition(RecognitionEvent)}
397 * callback upon recognition success or failure.
398 */
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -0700399 public static class RecognitionEvent implements Parcelable {
Eric Laurente48188c2014-04-18 17:44:11 -0700400 /** Recognition status e.g {@link #RECOGNITION_STATUS_SUCCESS} */
401 public final int status;
402 /** Sound Model corresponding to this event callback */
403 public final int soundModelHandle;
404 /** True if it is possible to capture audio from this utterance buffered by the hardware */
405 public final boolean captureAvailable;
406 /** Audio session ID to be used when capturing the utterance with an AudioRecord
407 * if captureAvailable() is true. */
408 public final int captureSession;
409 /** Delay in ms between end of model detection and start of audio available for capture.
410 * A negative value is possible (e.g. if keyphrase is also available for capture) */
411 public final int captureDelayMs;
Eric Laurent013f66b2014-07-06 16:35:00 -0700412 /** Duration in ms of audio captured before the start of the trigger. 0 if none. */
413 public final int capturePreambleMs;
Eric Laurente48188c2014-04-18 17:44:11 -0700414 /** Opaque data for use by system applications who know about voice engine internals,
415 * typically during enrollment. */
416 public final byte[] data;
417
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -0700418 public RecognitionEvent(int status, int soundModelHandle, boolean captureAvailable,
Eric Laurent013f66b2014-07-06 16:35:00 -0700419 int captureSession, int captureDelayMs, int capturePreambleMs, byte[] data) {
Eric Laurente48188c2014-04-18 17:44:11 -0700420 this.status = status;
421 this.soundModelHandle = soundModelHandle;
422 this.captureAvailable = captureAvailable;
423 this.captureSession = captureSession;
424 this.captureDelayMs = captureDelayMs;
Eric Laurent013f66b2014-07-06 16:35:00 -0700425 this.capturePreambleMs = capturePreambleMs;
Eric Laurente48188c2014-04-18 17:44:11 -0700426 this.data = data;
427 }
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -0700428
429 public static final Parcelable.Creator<RecognitionEvent> CREATOR
430 = new Parcelable.Creator<RecognitionEvent>() {
431 public RecognitionEvent createFromParcel(Parcel in) {
432 return RecognitionEvent.fromParcel(in);
433 }
434
435 public RecognitionEvent[] newArray(int size) {
436 return new RecognitionEvent[size];
437 }
438 };
439
440 private static RecognitionEvent fromParcel(Parcel in) {
441 int status = in.readInt();
442 int soundModelHandle = in.readInt();
443 boolean captureAvailable = in.readByte() == 1;
444 int captureSession = in.readInt();
445 int captureDelayMs = in.readInt();
446 int capturePreambleMs = in.readInt();
447 byte[] data = in.readBlob();
448 return new RecognitionEvent(status, soundModelHandle, captureAvailable, captureSession,
449 captureDelayMs, capturePreambleMs, data);
450 }
451
452 @Override
453 public int describeContents() {
454 return 0;
455 }
456
457 @Override
458 public void writeToParcel(Parcel dest, int flags) {
459 dest.writeInt(status);
460 dest.writeInt(soundModelHandle);
461 dest.writeByte((byte) (captureAvailable ? 1 : 0));
462 dest.writeInt(captureSession);
463 dest.writeInt(captureDelayMs);
464 dest.writeInt(capturePreambleMs);
465 dest.writeBlob(data);
466 }
467
468 @Override
469 public int hashCode() {
470 final int prime = 31;
471 int result = 1;
472 result = prime * result + (captureAvailable ? 1231 : 1237);
473 result = prime * result + captureDelayMs;
474 result = prime * result + capturePreambleMs;
475 result = prime * result + captureSession;
476 result = prime * result + Arrays.hashCode(data);
477 result = prime * result + soundModelHandle;
478 result = prime * result + status;
479 return result;
480 }
481
482 @Override
483 public boolean equals(Object obj) {
484 if (this == obj)
485 return true;
486 if (obj == null)
487 return false;
488 if (getClass() != obj.getClass())
489 return false;
490 RecognitionEvent other = (RecognitionEvent) obj;
491 if (captureAvailable != other.captureAvailable)
492 return false;
493 if (captureDelayMs != other.captureDelayMs)
494 return false;
495 if (capturePreambleMs != other.capturePreambleMs)
496 return false;
497 if (captureSession != other.captureSession)
498 return false;
499 if (!Arrays.equals(data, other.data))
500 return false;
501 if (soundModelHandle != other.soundModelHandle)
502 return false;
503 if (status != other.status)
504 return false;
505 return true;
506 }
Sandeep Siddhartha68173372014-07-28 13:25:30 -0700507
508 @Override
509 public String toString() {
510 return "RecognitionEvent [status=" + status + ", soundModelHandle=" + soundModelHandle
511 + ", captureAvailable=" + captureAvailable + ", captureSession="
512 + captureSession + ", captureDelayMs=" + captureDelayMs
513 + ", capturePreambleMs=" + capturePreambleMs
514 + ", data=" + (data == null ? 0 : data.length) + "]";
515 }
Eric Laurente48188c2014-04-18 17:44:11 -0700516 }
517
518 /**
Eric Laurent013f66b2014-07-06 16:35:00 -0700519 * A RecognitionConfig is provided to
520 * {@link SoundTriggerModule#startRecognition(int, RecognitionConfig)} to configure the
521 * recognition request.
522 */
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700523 public static class RecognitionConfig implements Parcelable {
Eric Laurent013f66b2014-07-06 16:35:00 -0700524 /** True if the DSP should capture the trigger sound and make it available for further
525 * capture. */
526 public final boolean captureRequested;
527 /** List of all keyphrases in the sound model for which recognition should be performed with
528 * options for each keyphrase. */
529 public final KeyphraseRecognitionExtra keyphrases[];
530 /** Opaque data for use by system applications who know about voice engine internals,
531 * typically during enrollment. */
532 public final byte[] data;
533
534 public RecognitionConfig(boolean captureRequested,
535 KeyphraseRecognitionExtra keyphrases[], byte[] data) {
536 this.captureRequested = captureRequested;
537 this.keyphrases = keyphrases;
538 this.data = data;
539 }
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700540
541 public static final Parcelable.Creator<RecognitionConfig> CREATOR
542 = new Parcelable.Creator<RecognitionConfig>() {
543 public RecognitionConfig createFromParcel(Parcel in) {
544 return RecognitionConfig.fromParcel(in);
545 }
546
547 public RecognitionConfig[] newArray(int size) {
548 return new RecognitionConfig[size];
549 }
550 };
551
552 private static RecognitionConfig fromParcel(Parcel in) {
553 boolean captureRequested = in.readByte() == 1;
554 KeyphraseRecognitionExtra[] keyphrases =
555 in.createTypedArray(KeyphraseRecognitionExtra.CREATOR);
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -0700556 byte[] data = in.readBlob();
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700557 return new RecognitionConfig(captureRequested, keyphrases, data);
558 }
559
560 @Override
561 public void writeToParcel(Parcel dest, int flags) {
562 dest.writeByte((byte) (captureRequested ? 1 : 0));
Sandeep Siddhartha68173372014-07-28 13:25:30 -0700563 dest.writeTypedArray(keyphrases, flags);
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -0700564 dest.writeBlob(data);
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700565 }
566
567 @Override
568 public int describeContents() {
569 return 0;
570 }
Sandeep Siddhartha110f5692014-07-20 12:22:56 -0700571
572 @Override
573 public String toString() {
574 return "RecognitionConfig [captureRequested=" + captureRequested + ", keyphrases="
Sandeep Siddhartha68173372014-07-28 13:25:30 -0700575 + Arrays.toString(keyphrases)
576 + ", data=" + (data == null ? 0 : data.length) + "]";
Sandeep Siddhartha110f5692014-07-20 12:22:56 -0700577 }
Eric Laurent013f66b2014-07-06 16:35:00 -0700578 }
579
580 /**
581 * Confidence level for users defined in a keyphrase.
582 * - The confidence level is expressed in percent (0% -100%).
583 * When used in a {@link KeyphraseRecognitionEvent} it indicates the detected confidence level
584 * When used in a {@link RecognitionConfig} it indicates the minimum confidence level that
585 * should trigger a recognition.
586 * - The user ID is derived from the system ID {@link android.os.UserHandle#getIdentifier()}.
587 */
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700588 public static class ConfidenceLevel implements Parcelable {
Eric Laurent013f66b2014-07-06 16:35:00 -0700589 public final int userId;
590 public final int confidenceLevel;
591
592 public ConfidenceLevel(int userId, int confidenceLevel) {
593 this.userId = userId;
594 this.confidenceLevel = confidenceLevel;
595 }
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700596
597 public static final Parcelable.Creator<ConfidenceLevel> CREATOR
598 = new Parcelable.Creator<ConfidenceLevel>() {
599 public ConfidenceLevel createFromParcel(Parcel in) {
600 return ConfidenceLevel.fromParcel(in);
601 }
602
603 public ConfidenceLevel[] newArray(int size) {
604 return new ConfidenceLevel[size];
605 }
606 };
607
608 private static ConfidenceLevel fromParcel(Parcel in) {
609 int userId = in.readInt();
610 int confidenceLevel = in.readInt();
611 return new ConfidenceLevel(userId, confidenceLevel);
612 }
613
614 @Override
615 public void writeToParcel(Parcel dest, int flags) {
616 dest.writeInt(userId);
617 dest.writeInt(confidenceLevel);
618 }
619
620 @Override
621 public int describeContents() {
622 return 0;
623 }
Sandeep Siddhartha68173372014-07-28 13:25:30 -0700624
625 @Override
626 public int hashCode() {
627 final int prime = 31;
628 int result = 1;
629 result = prime * result + confidenceLevel;
630 result = prime * result + userId;
631 return result;
632 }
633
634 @Override
635 public boolean equals(Object obj) {
636 if (this == obj)
637 return true;
638 if (obj == null)
639 return false;
640 if (getClass() != obj.getClass())
641 return false;
642 ConfidenceLevel other = (ConfidenceLevel) obj;
643 if (confidenceLevel != other.confidenceLevel)
644 return false;
645 if (userId != other.userId)
646 return false;
647 return true;
648 }
649
650 @Override
651 public String toString() {
652 return "ConfidenceLevel [userId=" + userId
653 + ", confidenceLevel=" + confidenceLevel + "]";
654 }
Eric Laurent013f66b2014-07-06 16:35:00 -0700655 }
656
657 /**
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700658 * Additional data conveyed by a {@link KeyphraseRecognitionEvent}
Eric Laurente48188c2014-04-18 17:44:11 -0700659 * for a key phrase detection.
660 */
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700661 public static class KeyphraseRecognitionExtra implements Parcelable {
662 /** The keyphrase ID */
Eric Laurent013f66b2014-07-06 16:35:00 -0700663 public final int id;
Eric Laurente48188c2014-04-18 17:44:11 -0700664
665 /** Recognition modes matched for this event */
666 public final int recognitionModes;
667
Eric Laurent013f66b2014-07-06 16:35:00 -0700668 /** Confidence levels for all users recognized (KeyphraseRecognitionEvent) or to
669 * be recognized (RecognitionConfig) */
670 public final ConfidenceLevel[] confidenceLevels;
671
672 public KeyphraseRecognitionExtra(int id, int recognitionModes,
673 ConfidenceLevel[] confidenceLevels) {
674 this.id = id;
Eric Laurente48188c2014-04-18 17:44:11 -0700675 this.recognitionModes = recognitionModes;
Eric Laurent013f66b2014-07-06 16:35:00 -0700676 this.confidenceLevels = confidenceLevels;
Eric Laurente48188c2014-04-18 17:44:11 -0700677 }
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700678
679 public static final Parcelable.Creator<KeyphraseRecognitionExtra> CREATOR
680 = new Parcelable.Creator<KeyphraseRecognitionExtra>() {
681 public KeyphraseRecognitionExtra createFromParcel(Parcel in) {
682 return KeyphraseRecognitionExtra.fromParcel(in);
683 }
684
685 public KeyphraseRecognitionExtra[] newArray(int size) {
686 return new KeyphraseRecognitionExtra[size];
687 }
688 };
689
690 private static KeyphraseRecognitionExtra fromParcel(Parcel in) {
691 int id = in.readInt();
692 int recognitionModes = in.readInt();
693 ConfidenceLevel[] confidenceLevels = in.createTypedArray(ConfidenceLevel.CREATOR);
694 return new KeyphraseRecognitionExtra(id, recognitionModes, confidenceLevels);
695 }
696
697 @Override
698 public void writeToParcel(Parcel dest, int flags) {
699 dest.writeInt(id);
700 dest.writeInt(recognitionModes);
Sandeep Siddhartha68173372014-07-28 13:25:30 -0700701 dest.writeTypedArray(confidenceLevels, flags);
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700702 }
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 + Arrays.hashCode(confidenceLevels);
714 result = prime * result + id;
715 result = prime * result + recognitionModes;
716 return result;
717 }
718
719 @Override
720 public boolean equals(Object obj) {
721 if (this == obj)
722 return true;
723 if (obj == null)
724 return false;
725 if (getClass() != obj.getClass())
726 return false;
727 KeyphraseRecognitionExtra other = (KeyphraseRecognitionExtra) obj;
728 if (!Arrays.equals(confidenceLevels, other.confidenceLevels))
729 return false;
730 if (id != other.id)
731 return false;
732 if (recognitionModes != other.recognitionModes)
733 return false;
734 return true;
735 }
736
737 @Override
738 public String toString() {
739 return "KeyphraseRecognitionExtra [id=" + id + ", recognitionModes=" + recognitionModes
740 + ", confidenceLevels=" + Arrays.toString(confidenceLevels) + "]";
741 }
Eric Laurente48188c2014-04-18 17:44:11 -0700742 }
743
744 /**
745 * Specialized {@link RecognitionEvent} for a key phrase detection.
746 */
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700747 public static class KeyphraseRecognitionEvent extends RecognitionEvent {
Eric Laurente48188c2014-04-18 17:44:11 -0700748 /** Indicates if the key phrase is present in the buffered audio available for capture */
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700749 public final KeyphraseRecognitionExtra[] keyphraseExtras;
Eric Laurente48188c2014-04-18 17:44:11 -0700750
751 /** Additional data available for each recognized key phrases in the model */
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700752 public final boolean keyphraseInCapture;
Eric Laurente48188c2014-04-18 17:44:11 -0700753
Sandeep Siddhartha68173372014-07-28 13:25:30 -0700754 public KeyphraseRecognitionEvent(int status, int soundModelHandle, boolean captureAvailable,
Eric Laurent013f66b2014-07-06 16:35:00 -0700755 int captureSession, int captureDelayMs, int capturePreambleMs, byte[] data,
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700756 boolean keyphraseInCapture, KeyphraseRecognitionExtra[] keyphraseExtras) {
Eric Laurent013f66b2014-07-06 16:35:00 -0700757 super(status, soundModelHandle, captureAvailable, captureSession, captureDelayMs,
758 capturePreambleMs, data);
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700759 this.keyphraseInCapture = keyphraseInCapture;
760 this.keyphraseExtras = keyphraseExtras;
Eric Laurente48188c2014-04-18 17:44:11 -0700761 }
Sandeep Siddhartha68173372014-07-28 13:25:30 -0700762
763 public static final Parcelable.Creator<KeyphraseRecognitionEvent> CREATOR
764 = new Parcelable.Creator<KeyphraseRecognitionEvent>() {
765 public KeyphraseRecognitionEvent createFromParcel(Parcel in) {
766 return KeyphraseRecognitionEvent.fromParcel(in);
767 }
768
769 public KeyphraseRecognitionEvent[] newArray(int size) {
770 return new KeyphraseRecognitionEvent[size];
771 }
772 };
773
774 private static KeyphraseRecognitionEvent fromParcel(Parcel in) {
775 int status = in.readInt();
776 int soundModelHandle = in.readInt();
777 boolean captureAvailable = in.readByte() == 1;
778 int captureSession = in.readInt();
779 int captureDelayMs = in.readInt();
780 int capturePreambleMs = in.readInt();
781 byte[] data = in.readBlob();
782 boolean keyphraseInCapture = in.readByte() == 1;
783 KeyphraseRecognitionExtra[] keyphraseExtras =
784 in.createTypedArray(KeyphraseRecognitionExtra.CREATOR);
785 return new KeyphraseRecognitionEvent(status, soundModelHandle, captureAvailable,
786 captureSession, captureDelayMs, capturePreambleMs, data, keyphraseInCapture,
787 keyphraseExtras);
788 }
789
790 @Override
791 public void writeToParcel(Parcel dest, int flags) {
792 dest.writeInt(status);
793 dest.writeInt(soundModelHandle);
794 dest.writeByte((byte) (captureAvailable ? 1 : 0));
795 dest.writeInt(captureSession);
796 dest.writeInt(captureDelayMs);
797 dest.writeInt(capturePreambleMs);
798 dest.writeBlob(data);
799 dest.writeByte((byte) (keyphraseInCapture ? 1 : 0));
800 dest.writeTypedArray(keyphraseExtras, flags);
801 }
802
803 @Override
804 public int describeContents() {
805 return 0;
806 }
807
808 @Override
809 public int hashCode() {
810 final int prime = 31;
811 int result = super.hashCode();
812 result = prime * result + Arrays.hashCode(keyphraseExtras);
813 result = prime * result + (keyphraseInCapture ? 1231 : 1237);
814 return result;
815 }
816
817 @Override
818 public boolean equals(Object obj) {
819 if (this == obj)
820 return true;
821 if (!super.equals(obj))
822 return false;
823 if (getClass() != obj.getClass())
824 return false;
825 KeyphraseRecognitionEvent other = (KeyphraseRecognitionEvent) obj;
826 if (!Arrays.equals(keyphraseExtras, other.keyphraseExtras))
827 return false;
828 if (keyphraseInCapture != other.keyphraseInCapture)
829 return false;
830 return true;
831 }
832
833 @Override
834 public String toString() {
835 return "KeyphraseRecognitionEvent [keyphraseExtras=" + Arrays.toString(keyphraseExtras)
836 + ", keyphraseInCapture=" + keyphraseInCapture + ", status=" + status
837 + ", soundModelHandle=" + soundModelHandle + ", captureAvailable="
838 + captureAvailable + ", captureSession=" + captureSession + ", captureDelayMs="
839 + captureDelayMs + ", capturePreambleMs=" + capturePreambleMs
840 + ", data=" + (data == null ? 0 : data.length) + "]";
841 }
Eric Laurente48188c2014-04-18 17:44:11 -0700842 }
843
844 /**
845 * Returns a list of descriptors for all harware modules loaded.
846 * @param modules A ModuleProperties array where the list will be returned.
847 * @return - {@link #STATUS_OK} in case of success
848 * - {@link #STATUS_ERROR} in case of unspecified error
849 * - {@link #STATUS_PERMISSION_DENIED} if the caller does not have system permission
850 * - {@link #STATUS_NO_INIT} if the native service cannot be reached
851 * - {@link #STATUS_BAD_VALUE} if modules is null
852 * - {@link #STATUS_DEAD_OBJECT} if the binder transaction to the native service fails
853 */
854 public static native int listModules(ArrayList <ModuleProperties> modules);
855
856 /**
857 * Get an interface on a hardware module to control sound models and recognition on
858 * this module.
859 * @param moduleId Sound module system identifier {@link ModuleProperties#id}. mandatory.
860 * @param listener {@link StatusListener} interface. Mandatory.
861 * @param handler the Handler that will receive the callabcks. Can be null if default handler
862 * is OK.
863 * @return a valid sound module in case of success or null in case of error.
864 */
865 public static SoundTriggerModule attachModule(int moduleId,
866 StatusListener listener,
867 Handler handler) {
868 if (listener == null) {
869 return null;
870 }
871 SoundTriggerModule module = new SoundTriggerModule(moduleId, listener, handler);
872 return module;
873 }
874
875 /**
876 * Interface provided by the client application when attaching to a {@link SoundTriggerModule}
877 * to received recognition and error notifications.
878 */
879 public static interface StatusListener {
880 /**
881 * Called when recognition succeeds of fails
882 */
883 public abstract void onRecognition(RecognitionEvent event);
884
885 /**
886 * Called when the sound trigger native service dies
887 */
888 public abstract void onServiceDied();
889 }
890}