blob: adee740982176feb327eefce69e3a214a1d64ff8 [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;
Sandeep Siddhartha2c0273e2014-08-01 11:32:03 -0700527 /**
528 * True if the service should restart listening after the DSP triggers.
529 * Note: This config flag is currently used at the service layer rather than by the DSP.
530 */
531 public final boolean allowMultipleTriggers;
Eric Laurent013f66b2014-07-06 16:35:00 -0700532 /** List of all keyphrases in the sound model for which recognition should be performed with
533 * options for each keyphrase. */
534 public final KeyphraseRecognitionExtra keyphrases[];
535 /** Opaque data for use by system applications who know about voice engine internals,
536 * typically during enrollment. */
537 public final byte[] data;
538
Sandeep Siddhartha2c0273e2014-08-01 11:32:03 -0700539 public RecognitionConfig(boolean captureRequested, boolean allowMultipleTriggers,
Eric Laurent013f66b2014-07-06 16:35:00 -0700540 KeyphraseRecognitionExtra keyphrases[], byte[] data) {
541 this.captureRequested = captureRequested;
Sandeep Siddhartha2c0273e2014-08-01 11:32:03 -0700542 this.allowMultipleTriggers = allowMultipleTriggers;
Eric Laurent013f66b2014-07-06 16:35:00 -0700543 this.keyphrases = keyphrases;
544 this.data = data;
545 }
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700546
547 public static final Parcelable.Creator<RecognitionConfig> CREATOR
548 = new Parcelable.Creator<RecognitionConfig>() {
549 public RecognitionConfig createFromParcel(Parcel in) {
550 return RecognitionConfig.fromParcel(in);
551 }
552
553 public RecognitionConfig[] newArray(int size) {
554 return new RecognitionConfig[size];
555 }
556 };
557
558 private static RecognitionConfig fromParcel(Parcel in) {
559 boolean captureRequested = in.readByte() == 1;
Sandeep Siddhartha2c0273e2014-08-01 11:32:03 -0700560 boolean allowMultipleTriggers = in.readByte() == 1;
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700561 KeyphraseRecognitionExtra[] keyphrases =
562 in.createTypedArray(KeyphraseRecognitionExtra.CREATOR);
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -0700563 byte[] data = in.readBlob();
Sandeep Siddhartha2c0273e2014-08-01 11:32:03 -0700564 return new RecognitionConfig(captureRequested, allowMultipleTriggers, keyphrases, data);
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700565 }
566
567 @Override
568 public void writeToParcel(Parcel dest, int flags) {
569 dest.writeByte((byte) (captureRequested ? 1 : 0));
Sandeep Siddhartha2c0273e2014-08-01 11:32:03 -0700570 dest.writeByte((byte) (allowMultipleTriggers ? 1 : 0));
Sandeep Siddhartha68173372014-07-28 13:25:30 -0700571 dest.writeTypedArray(keyphrases, flags);
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -0700572 dest.writeBlob(data);
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700573 }
574
575 @Override
576 public int describeContents() {
577 return 0;
578 }
Sandeep Siddhartha110f5692014-07-20 12:22:56 -0700579
580 @Override
581 public String toString() {
Sandeep Siddhartha2c0273e2014-08-01 11:32:03 -0700582 return "RecognitionConfig [captureRequested=" + captureRequested
583 + ", allowMultipleTriggers=" + allowMultipleTriggers + ", keyphrases="
584 + Arrays.toString(keyphrases) + ", data=" + Arrays.toString(data) + "]";
Sandeep Siddhartha110f5692014-07-20 12:22:56 -0700585 }
Eric Laurent013f66b2014-07-06 16:35:00 -0700586 }
587
588 /**
589 * Confidence level for users defined in a keyphrase.
590 * - The confidence level is expressed in percent (0% -100%).
591 * When used in a {@link KeyphraseRecognitionEvent} it indicates the detected confidence level
592 * When used in a {@link RecognitionConfig} it indicates the minimum confidence level that
593 * should trigger a recognition.
594 * - The user ID is derived from the system ID {@link android.os.UserHandle#getIdentifier()}.
595 */
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700596 public static class ConfidenceLevel implements Parcelable {
Eric Laurent013f66b2014-07-06 16:35:00 -0700597 public final int userId;
598 public final int confidenceLevel;
599
600 public ConfidenceLevel(int userId, int confidenceLevel) {
601 this.userId = userId;
602 this.confidenceLevel = confidenceLevel;
603 }
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700604
605 public static final Parcelable.Creator<ConfidenceLevel> CREATOR
606 = new Parcelable.Creator<ConfidenceLevel>() {
607 public ConfidenceLevel createFromParcel(Parcel in) {
608 return ConfidenceLevel.fromParcel(in);
609 }
610
611 public ConfidenceLevel[] newArray(int size) {
612 return new ConfidenceLevel[size];
613 }
614 };
615
616 private static ConfidenceLevel fromParcel(Parcel in) {
617 int userId = in.readInt();
618 int confidenceLevel = in.readInt();
619 return new ConfidenceLevel(userId, confidenceLevel);
620 }
621
622 @Override
623 public void writeToParcel(Parcel dest, int flags) {
624 dest.writeInt(userId);
625 dest.writeInt(confidenceLevel);
626 }
627
628 @Override
629 public int describeContents() {
630 return 0;
631 }
Sandeep Siddhartha68173372014-07-28 13:25:30 -0700632
633 @Override
634 public int hashCode() {
635 final int prime = 31;
636 int result = 1;
637 result = prime * result + confidenceLevel;
638 result = prime * result + userId;
639 return result;
640 }
641
642 @Override
643 public boolean equals(Object obj) {
644 if (this == obj)
645 return true;
646 if (obj == null)
647 return false;
648 if (getClass() != obj.getClass())
649 return false;
650 ConfidenceLevel other = (ConfidenceLevel) obj;
651 if (confidenceLevel != other.confidenceLevel)
652 return false;
653 if (userId != other.userId)
654 return false;
655 return true;
656 }
657
658 @Override
659 public String toString() {
660 return "ConfidenceLevel [userId=" + userId
661 + ", confidenceLevel=" + confidenceLevel + "]";
662 }
Eric Laurent013f66b2014-07-06 16:35:00 -0700663 }
664
665 /**
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700666 * Additional data conveyed by a {@link KeyphraseRecognitionEvent}
Eric Laurente48188c2014-04-18 17:44:11 -0700667 * for a key phrase detection.
668 */
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700669 public static class KeyphraseRecognitionExtra implements Parcelable {
670 /** The keyphrase ID */
Eric Laurent013f66b2014-07-06 16:35:00 -0700671 public final int id;
Eric Laurente48188c2014-04-18 17:44:11 -0700672
673 /** Recognition modes matched for this event */
674 public final int recognitionModes;
675
Eric Laurent013f66b2014-07-06 16:35:00 -0700676 /** Confidence levels for all users recognized (KeyphraseRecognitionEvent) or to
677 * be recognized (RecognitionConfig) */
678 public final ConfidenceLevel[] confidenceLevels;
679
680 public KeyphraseRecognitionExtra(int id, int recognitionModes,
681 ConfidenceLevel[] confidenceLevels) {
682 this.id = id;
Eric Laurente48188c2014-04-18 17:44:11 -0700683 this.recognitionModes = recognitionModes;
Eric Laurent013f66b2014-07-06 16:35:00 -0700684 this.confidenceLevels = confidenceLevels;
Eric Laurente48188c2014-04-18 17:44:11 -0700685 }
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700686
687 public static final Parcelable.Creator<KeyphraseRecognitionExtra> CREATOR
688 = new Parcelable.Creator<KeyphraseRecognitionExtra>() {
689 public KeyphraseRecognitionExtra createFromParcel(Parcel in) {
690 return KeyphraseRecognitionExtra.fromParcel(in);
691 }
692
693 public KeyphraseRecognitionExtra[] newArray(int size) {
694 return new KeyphraseRecognitionExtra[size];
695 }
696 };
697
698 private static KeyphraseRecognitionExtra fromParcel(Parcel in) {
699 int id = in.readInt();
700 int recognitionModes = in.readInt();
701 ConfidenceLevel[] confidenceLevels = in.createTypedArray(ConfidenceLevel.CREATOR);
702 return new KeyphraseRecognitionExtra(id, recognitionModes, confidenceLevels);
703 }
704
705 @Override
706 public void writeToParcel(Parcel dest, int flags) {
707 dest.writeInt(id);
708 dest.writeInt(recognitionModes);
Sandeep Siddhartha68173372014-07-28 13:25:30 -0700709 dest.writeTypedArray(confidenceLevels, flags);
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700710 }
711
712 @Override
713 public int describeContents() {
714 return 0;
715 }
Sandeep Siddhartha68173372014-07-28 13:25:30 -0700716
717 @Override
718 public int hashCode() {
719 final int prime = 31;
720 int result = 1;
721 result = prime * result + Arrays.hashCode(confidenceLevels);
722 result = prime * result + id;
723 result = prime * result + recognitionModes;
724 return result;
725 }
726
727 @Override
728 public boolean equals(Object obj) {
729 if (this == obj)
730 return true;
731 if (obj == null)
732 return false;
733 if (getClass() != obj.getClass())
734 return false;
735 KeyphraseRecognitionExtra other = (KeyphraseRecognitionExtra) obj;
736 if (!Arrays.equals(confidenceLevels, other.confidenceLevels))
737 return false;
738 if (id != other.id)
739 return false;
740 if (recognitionModes != other.recognitionModes)
741 return false;
742 return true;
743 }
744
745 @Override
746 public String toString() {
747 return "KeyphraseRecognitionExtra [id=" + id + ", recognitionModes=" + recognitionModes
748 + ", confidenceLevels=" + Arrays.toString(confidenceLevels) + "]";
749 }
Eric Laurente48188c2014-04-18 17:44:11 -0700750 }
751
752 /**
753 * Specialized {@link RecognitionEvent} for a key phrase detection.
754 */
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700755 public static class KeyphraseRecognitionEvent extends RecognitionEvent {
Eric Laurente48188c2014-04-18 17:44:11 -0700756 /** Indicates if the key phrase is present in the buffered audio available for capture */
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700757 public final KeyphraseRecognitionExtra[] keyphraseExtras;
Eric Laurente48188c2014-04-18 17:44:11 -0700758
759 /** Additional data available for each recognized key phrases in the model */
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700760 public final boolean keyphraseInCapture;
Eric Laurente48188c2014-04-18 17:44:11 -0700761
Sandeep Siddhartha68173372014-07-28 13:25:30 -0700762 public KeyphraseRecognitionEvent(int status, int soundModelHandle, boolean captureAvailable,
Eric Laurent013f66b2014-07-06 16:35:00 -0700763 int captureSession, int captureDelayMs, int capturePreambleMs, byte[] data,
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700764 boolean keyphraseInCapture, KeyphraseRecognitionExtra[] keyphraseExtras) {
Eric Laurent013f66b2014-07-06 16:35:00 -0700765 super(status, soundModelHandle, captureAvailable, captureSession, captureDelayMs,
766 capturePreambleMs, data);
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700767 this.keyphraseInCapture = keyphraseInCapture;
768 this.keyphraseExtras = keyphraseExtras;
Eric Laurente48188c2014-04-18 17:44:11 -0700769 }
Sandeep Siddhartha68173372014-07-28 13:25:30 -0700770
771 public static final Parcelable.Creator<KeyphraseRecognitionEvent> CREATOR
772 = new Parcelable.Creator<KeyphraseRecognitionEvent>() {
773 public KeyphraseRecognitionEvent createFromParcel(Parcel in) {
774 return KeyphraseRecognitionEvent.fromParcel(in);
775 }
776
777 public KeyphraseRecognitionEvent[] newArray(int size) {
778 return new KeyphraseRecognitionEvent[size];
779 }
780 };
781
782 private static KeyphraseRecognitionEvent fromParcel(Parcel in) {
783 int status = in.readInt();
784 int soundModelHandle = in.readInt();
785 boolean captureAvailable = in.readByte() == 1;
786 int captureSession = in.readInt();
787 int captureDelayMs = in.readInt();
788 int capturePreambleMs = in.readInt();
789 byte[] data = in.readBlob();
790 boolean keyphraseInCapture = in.readByte() == 1;
791 KeyphraseRecognitionExtra[] keyphraseExtras =
792 in.createTypedArray(KeyphraseRecognitionExtra.CREATOR);
793 return new KeyphraseRecognitionEvent(status, soundModelHandle, captureAvailable,
794 captureSession, captureDelayMs, capturePreambleMs, data, keyphraseInCapture,
795 keyphraseExtras);
796 }
797
798 @Override
799 public void writeToParcel(Parcel dest, int flags) {
800 dest.writeInt(status);
801 dest.writeInt(soundModelHandle);
802 dest.writeByte((byte) (captureAvailable ? 1 : 0));
803 dest.writeInt(captureSession);
804 dest.writeInt(captureDelayMs);
805 dest.writeInt(capturePreambleMs);
806 dest.writeBlob(data);
807 dest.writeByte((byte) (keyphraseInCapture ? 1 : 0));
808 dest.writeTypedArray(keyphraseExtras, flags);
809 }
810
811 @Override
812 public int describeContents() {
813 return 0;
814 }
815
816 @Override
817 public int hashCode() {
818 final int prime = 31;
819 int result = super.hashCode();
820 result = prime * result + Arrays.hashCode(keyphraseExtras);
821 result = prime * result + (keyphraseInCapture ? 1231 : 1237);
822 return result;
823 }
824
825 @Override
826 public boolean equals(Object obj) {
827 if (this == obj)
828 return true;
829 if (!super.equals(obj))
830 return false;
831 if (getClass() != obj.getClass())
832 return false;
833 KeyphraseRecognitionEvent other = (KeyphraseRecognitionEvent) obj;
834 if (!Arrays.equals(keyphraseExtras, other.keyphraseExtras))
835 return false;
836 if (keyphraseInCapture != other.keyphraseInCapture)
837 return false;
838 return true;
839 }
840
841 @Override
842 public String toString() {
843 return "KeyphraseRecognitionEvent [keyphraseExtras=" + Arrays.toString(keyphraseExtras)
844 + ", keyphraseInCapture=" + keyphraseInCapture + ", status=" + status
845 + ", soundModelHandle=" + soundModelHandle + ", captureAvailable="
846 + captureAvailable + ", captureSession=" + captureSession + ", captureDelayMs="
847 + captureDelayMs + ", capturePreambleMs=" + capturePreambleMs
848 + ", data=" + (data == null ? 0 : data.length) + "]";
849 }
Eric Laurente48188c2014-04-18 17:44:11 -0700850 }
851
852 /**
853 * Returns a list of descriptors for all harware modules loaded.
854 * @param modules A ModuleProperties array where the list will be returned.
855 * @return - {@link #STATUS_OK} in case of success
856 * - {@link #STATUS_ERROR} in case of unspecified error
857 * - {@link #STATUS_PERMISSION_DENIED} if the caller does not have system permission
858 * - {@link #STATUS_NO_INIT} if the native service cannot be reached
859 * - {@link #STATUS_BAD_VALUE} if modules is null
860 * - {@link #STATUS_DEAD_OBJECT} if the binder transaction to the native service fails
861 */
862 public static native int listModules(ArrayList <ModuleProperties> modules);
863
864 /**
865 * Get an interface on a hardware module to control sound models and recognition on
866 * this module.
867 * @param moduleId Sound module system identifier {@link ModuleProperties#id}. mandatory.
868 * @param listener {@link StatusListener} interface. Mandatory.
869 * @param handler the Handler that will receive the callabcks. Can be null if default handler
870 * is OK.
871 * @return a valid sound module in case of success or null in case of error.
872 */
873 public static SoundTriggerModule attachModule(int moduleId,
874 StatusListener listener,
875 Handler handler) {
876 if (listener == null) {
877 return null;
878 }
879 SoundTriggerModule module = new SoundTriggerModule(moduleId, listener, handler);
880 return module;
881 }
882
883 /**
884 * Interface provided by the client application when attaching to a {@link SoundTriggerModule}
885 * to received recognition and error notifications.
886 */
887 public static interface StatusListener {
888 /**
889 * Called when recognition succeeds of fails
890 */
891 public abstract void onRecognition(RecognitionEvent event);
892
893 /**
894 * Called when the sound trigger native service dies
895 */
896 public abstract void onServiceDied();
897 }
898}