blob: 7a49eb5cee10b09bdb267a84927013684d4b1d6c [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;
483 if (triggerInData) {
484 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 Laurentd3b82232014-07-30 08:57:39 -0700511 if (triggerInData && (captureFormat != null)) {
512 dest.writeByte((byte)1);
513 dest.writeInt(captureFormat.getSampleRate());
514 dest.writeInt(captureFormat.getEncoding());
515 dest.writeInt(captureFormat.getChannelMask());
516 } else {
517 dest.writeByte((byte)0);
518 }
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -0700519 dest.writeBlob(data);
520 }
521
522 @Override
523 public int hashCode() {
524 final int prime = 31;
525 int result = 1;
526 result = prime * result + (captureAvailable ? 1231 : 1237);
527 result = prime * result + captureDelayMs;
528 result = prime * result + capturePreambleMs;
529 result = prime * result + captureSession;
Eric Laurentd3b82232014-07-30 08:57:39 -0700530 result = prime * result + (triggerInData ? 1231 : 1237);
531 if (captureFormat != null) {
532 result = prime * result + captureFormat.getSampleRate();
533 result = prime * result + captureFormat.getEncoding();
534 result = prime * result + captureFormat.getChannelMask();
535 }
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -0700536 result = prime * result + Arrays.hashCode(data);
537 result = prime * result + soundModelHandle;
538 result = prime * result + status;
539 return result;
540 }
541
542 @Override
543 public boolean equals(Object obj) {
544 if (this == obj)
545 return true;
546 if (obj == null)
547 return false;
548 if (getClass() != obj.getClass())
549 return false;
550 RecognitionEvent other = (RecognitionEvent) obj;
551 if (captureAvailable != other.captureAvailable)
552 return false;
553 if (captureDelayMs != other.captureDelayMs)
554 return false;
555 if (capturePreambleMs != other.capturePreambleMs)
556 return false;
557 if (captureSession != other.captureSession)
558 return false;
559 if (!Arrays.equals(data, other.data))
560 return false;
561 if (soundModelHandle != other.soundModelHandle)
562 return false;
563 if (status != other.status)
564 return false;
Eric Laurentd3b82232014-07-30 08:57:39 -0700565 if (triggerInData != other.triggerInData)
566 return false;
567 if (captureFormat.getSampleRate() != other.captureFormat.getSampleRate())
568 return false;
569 if (captureFormat.getEncoding() != other.captureFormat.getEncoding())
570 return false;
571 if (captureFormat.getChannelMask() != other.captureFormat.getChannelMask())
572 return false;
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -0700573 return true;
574 }
Sandeep Siddhartha68173372014-07-28 13:25:30 -0700575
576 @Override
577 public String toString() {
578 return "RecognitionEvent [status=" + status + ", soundModelHandle=" + soundModelHandle
579 + ", captureAvailable=" + captureAvailable + ", captureSession="
580 + captureSession + ", captureDelayMs=" + captureDelayMs
581 + ", capturePreambleMs=" + capturePreambleMs
Eric Laurentd3b82232014-07-30 08:57:39 -0700582 + ", triggerInData=" + triggerInData
583 + ((captureFormat == null) ? "" :
584 (", sampleRate=" + captureFormat.getSampleRate()))
585 + ((captureFormat == null) ? "" :
586 (", encoding=" + captureFormat.getEncoding()))
587 + ((captureFormat == null) ? "" :
588 (", channelMask=" + captureFormat.getChannelMask()))
Sandeep Siddhartha68173372014-07-28 13:25:30 -0700589 + ", data=" + (data == null ? 0 : data.length) + "]";
590 }
Eric Laurente48188c2014-04-18 17:44:11 -0700591 }
592
593 /**
Eric Laurent013f66b2014-07-06 16:35:00 -0700594 * A RecognitionConfig is provided to
595 * {@link SoundTriggerModule#startRecognition(int, RecognitionConfig)} to configure the
596 * recognition request.
597 */
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700598 public static class RecognitionConfig implements Parcelable {
Eric Laurent013f66b2014-07-06 16:35:00 -0700599 /** True if the DSP should capture the trigger sound and make it available for further
600 * capture. */
601 public final boolean captureRequested;
Sandeep Siddhartha2c0273e2014-08-01 11:32:03 -0700602 /**
603 * True if the service should restart listening after the DSP triggers.
604 * Note: This config flag is currently used at the service layer rather than by the DSP.
605 */
606 public final boolean allowMultipleTriggers;
Eric Laurent013f66b2014-07-06 16:35:00 -0700607 /** List of all keyphrases in the sound model for which recognition should be performed with
608 * options for each keyphrase. */
609 public final KeyphraseRecognitionExtra keyphrases[];
610 /** Opaque data for use by system applications who know about voice engine internals,
611 * typically during enrollment. */
612 public final byte[] data;
613
Sandeep Siddhartha2c0273e2014-08-01 11:32:03 -0700614 public RecognitionConfig(boolean captureRequested, boolean allowMultipleTriggers,
Eric Laurent013f66b2014-07-06 16:35:00 -0700615 KeyphraseRecognitionExtra keyphrases[], byte[] data) {
616 this.captureRequested = captureRequested;
Sandeep Siddhartha2c0273e2014-08-01 11:32:03 -0700617 this.allowMultipleTriggers = allowMultipleTriggers;
Eric Laurent013f66b2014-07-06 16:35:00 -0700618 this.keyphrases = keyphrases;
619 this.data = data;
620 }
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700621
622 public static final Parcelable.Creator<RecognitionConfig> CREATOR
623 = new Parcelable.Creator<RecognitionConfig>() {
624 public RecognitionConfig createFromParcel(Parcel in) {
625 return RecognitionConfig.fromParcel(in);
626 }
627
628 public RecognitionConfig[] newArray(int size) {
629 return new RecognitionConfig[size];
630 }
631 };
632
633 private static RecognitionConfig fromParcel(Parcel in) {
634 boolean captureRequested = in.readByte() == 1;
Sandeep Siddhartha2c0273e2014-08-01 11:32:03 -0700635 boolean allowMultipleTriggers = in.readByte() == 1;
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700636 KeyphraseRecognitionExtra[] keyphrases =
637 in.createTypedArray(KeyphraseRecognitionExtra.CREATOR);
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -0700638 byte[] data = in.readBlob();
Sandeep Siddhartha2c0273e2014-08-01 11:32:03 -0700639 return new RecognitionConfig(captureRequested, allowMultipleTriggers, keyphrases, data);
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700640 }
641
642 @Override
643 public void writeToParcel(Parcel dest, int flags) {
644 dest.writeByte((byte) (captureRequested ? 1 : 0));
Sandeep Siddhartha2c0273e2014-08-01 11:32:03 -0700645 dest.writeByte((byte) (allowMultipleTriggers ? 1 : 0));
Sandeep Siddhartha68173372014-07-28 13:25:30 -0700646 dest.writeTypedArray(keyphrases, flags);
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -0700647 dest.writeBlob(data);
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700648 }
649
650 @Override
651 public int describeContents() {
652 return 0;
653 }
Sandeep Siddhartha110f5692014-07-20 12:22:56 -0700654
655 @Override
656 public String toString() {
Sandeep Siddhartha2c0273e2014-08-01 11:32:03 -0700657 return "RecognitionConfig [captureRequested=" + captureRequested
658 + ", allowMultipleTriggers=" + allowMultipleTriggers + ", keyphrases="
659 + Arrays.toString(keyphrases) + ", data=" + Arrays.toString(data) + "]";
Sandeep Siddhartha110f5692014-07-20 12:22:56 -0700660 }
Eric Laurent013f66b2014-07-06 16:35:00 -0700661 }
662
663 /**
664 * Confidence level for users defined in a keyphrase.
665 * - The confidence level is expressed in percent (0% -100%).
666 * When used in a {@link KeyphraseRecognitionEvent} it indicates the detected confidence level
667 * When used in a {@link RecognitionConfig} it indicates the minimum confidence level that
668 * should trigger a recognition.
669 * - The user ID is derived from the system ID {@link android.os.UserHandle#getIdentifier()}.
670 */
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700671 public static class ConfidenceLevel implements Parcelable {
Eric Laurent013f66b2014-07-06 16:35:00 -0700672 public final int userId;
673 public final int confidenceLevel;
674
675 public ConfidenceLevel(int userId, int confidenceLevel) {
676 this.userId = userId;
677 this.confidenceLevel = confidenceLevel;
678 }
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700679
680 public static final Parcelable.Creator<ConfidenceLevel> CREATOR
681 = new Parcelable.Creator<ConfidenceLevel>() {
682 public ConfidenceLevel createFromParcel(Parcel in) {
683 return ConfidenceLevel.fromParcel(in);
684 }
685
686 public ConfidenceLevel[] newArray(int size) {
687 return new ConfidenceLevel[size];
688 }
689 };
690
691 private static ConfidenceLevel fromParcel(Parcel in) {
692 int userId = in.readInt();
693 int confidenceLevel = in.readInt();
694 return new ConfidenceLevel(userId, confidenceLevel);
695 }
696
697 @Override
698 public void writeToParcel(Parcel dest, int flags) {
699 dest.writeInt(userId);
700 dest.writeInt(confidenceLevel);
701 }
702
703 @Override
704 public int describeContents() {
705 return 0;
706 }
Sandeep Siddhartha68173372014-07-28 13:25:30 -0700707
708 @Override
709 public int hashCode() {
710 final int prime = 31;
711 int result = 1;
712 result = prime * result + confidenceLevel;
713 result = prime * result + userId;
714 return result;
715 }
716
717 @Override
718 public boolean equals(Object obj) {
719 if (this == obj)
720 return true;
721 if (obj == null)
722 return false;
723 if (getClass() != obj.getClass())
724 return false;
725 ConfidenceLevel other = (ConfidenceLevel) obj;
726 if (confidenceLevel != other.confidenceLevel)
727 return false;
728 if (userId != other.userId)
729 return false;
730 return true;
731 }
732
733 @Override
734 public String toString() {
735 return "ConfidenceLevel [userId=" + userId
736 + ", confidenceLevel=" + confidenceLevel + "]";
737 }
Eric Laurent013f66b2014-07-06 16:35:00 -0700738 }
739
740 /**
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700741 * Additional data conveyed by a {@link KeyphraseRecognitionEvent}
Eric Laurente48188c2014-04-18 17:44:11 -0700742 * for a key phrase detection.
743 */
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700744 public static class KeyphraseRecognitionExtra implements Parcelable {
745 /** The keyphrase ID */
Eric Laurent013f66b2014-07-06 16:35:00 -0700746 public final int id;
Eric Laurente48188c2014-04-18 17:44:11 -0700747
748 /** Recognition modes matched for this event */
749 public final int recognitionModes;
750
Eric Laurentd3b82232014-07-30 08:57:39 -0700751 /** Confidence level for mode RECOGNITION_MODE_VOICE_TRIGGER when user identification
752 * is not performed */
753 public final int coarseConfidenceLevel;
754
Eric Laurent013f66b2014-07-06 16:35:00 -0700755 /** Confidence levels for all users recognized (KeyphraseRecognitionEvent) or to
756 * be recognized (RecognitionConfig) */
757 public final ConfidenceLevel[] confidenceLevels;
758
Eric Laurentd3b82232014-07-30 08:57:39 -0700759 public KeyphraseRecognitionExtra(int id, int recognitionModes, int coarseConfidenceLevel,
760 ConfidenceLevel[] confidenceLevels) {
Eric Laurent013f66b2014-07-06 16:35:00 -0700761 this.id = id;
Eric Laurente48188c2014-04-18 17:44:11 -0700762 this.recognitionModes = recognitionModes;
Eric Laurentd3b82232014-07-30 08:57:39 -0700763 this.coarseConfidenceLevel = coarseConfidenceLevel;
Eric Laurent013f66b2014-07-06 16:35:00 -0700764 this.confidenceLevels = confidenceLevels;
Eric Laurente48188c2014-04-18 17:44:11 -0700765 }
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700766
767 public static final Parcelable.Creator<KeyphraseRecognitionExtra> CREATOR
768 = new Parcelable.Creator<KeyphraseRecognitionExtra>() {
769 public KeyphraseRecognitionExtra createFromParcel(Parcel in) {
770 return KeyphraseRecognitionExtra.fromParcel(in);
771 }
772
773 public KeyphraseRecognitionExtra[] newArray(int size) {
774 return new KeyphraseRecognitionExtra[size];
775 }
776 };
777
778 private static KeyphraseRecognitionExtra fromParcel(Parcel in) {
779 int id = in.readInt();
780 int recognitionModes = in.readInt();
Eric Laurentd3b82232014-07-30 08:57:39 -0700781 int coarseConfidenceLevel = in.readInt();
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700782 ConfidenceLevel[] confidenceLevels = in.createTypedArray(ConfidenceLevel.CREATOR);
Eric Laurentd3b82232014-07-30 08:57:39 -0700783 return new KeyphraseRecognitionExtra(id, recognitionModes, coarseConfidenceLevel,
784 confidenceLevels);
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700785 }
786
787 @Override
788 public void writeToParcel(Parcel dest, int flags) {
789 dest.writeInt(id);
790 dest.writeInt(recognitionModes);
Eric Laurentd3b82232014-07-30 08:57:39 -0700791 dest.writeInt(coarseConfidenceLevel);
Sandeep Siddhartha68173372014-07-28 13:25:30 -0700792 dest.writeTypedArray(confidenceLevels, flags);
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700793 }
794
795 @Override
796 public int describeContents() {
797 return 0;
798 }
Sandeep Siddhartha68173372014-07-28 13:25:30 -0700799
800 @Override
801 public int hashCode() {
802 final int prime = 31;
803 int result = 1;
804 result = prime * result + Arrays.hashCode(confidenceLevels);
805 result = prime * result + id;
806 result = prime * result + recognitionModes;
Eric Laurentd3b82232014-07-30 08:57:39 -0700807 result = prime * result + coarseConfidenceLevel;
Sandeep Siddhartha68173372014-07-28 13:25:30 -0700808 return result;
809 }
810
811 @Override
812 public boolean equals(Object obj) {
813 if (this == obj)
814 return true;
815 if (obj == null)
816 return false;
817 if (getClass() != obj.getClass())
818 return false;
819 KeyphraseRecognitionExtra other = (KeyphraseRecognitionExtra) obj;
820 if (!Arrays.equals(confidenceLevels, other.confidenceLevels))
821 return false;
822 if (id != other.id)
823 return false;
824 if (recognitionModes != other.recognitionModes)
825 return false;
Eric Laurentd3b82232014-07-30 08:57:39 -0700826 if (coarseConfidenceLevel != other.coarseConfidenceLevel)
827 return false;
Sandeep Siddhartha68173372014-07-28 13:25:30 -0700828 return true;
829 }
830
831 @Override
832 public String toString() {
833 return "KeyphraseRecognitionExtra [id=" + id + ", recognitionModes=" + recognitionModes
Eric Laurentd3b82232014-07-30 08:57:39 -0700834 + ", coarseConfidenceLevel=" + coarseConfidenceLevel
Sandeep Siddhartha68173372014-07-28 13:25:30 -0700835 + ", confidenceLevels=" + Arrays.toString(confidenceLevels) + "]";
836 }
Eric Laurente48188c2014-04-18 17:44:11 -0700837 }
838
839 /**
840 * Specialized {@link RecognitionEvent} for a key phrase detection.
841 */
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700842 public static class KeyphraseRecognitionEvent extends RecognitionEvent {
Eric Laurente48188c2014-04-18 17:44:11 -0700843 /** Indicates if the key phrase is present in the buffered audio available for capture */
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700844 public final KeyphraseRecognitionExtra[] keyphraseExtras;
Eric Laurente48188c2014-04-18 17:44:11 -0700845
Sandeep Siddhartha68173372014-07-28 13:25:30 -0700846 public KeyphraseRecognitionEvent(int status, int soundModelHandle, boolean captureAvailable,
Eric Laurentd3b82232014-07-30 08:57:39 -0700847 int captureSession, int captureDelayMs, int capturePreambleMs,
848 boolean triggerInData, AudioFormat captureFormat, byte[] data,
849 KeyphraseRecognitionExtra[] keyphraseExtras) {
Eric Laurent013f66b2014-07-06 16:35:00 -0700850 super(status, soundModelHandle, captureAvailable, captureSession, captureDelayMs,
Eric Laurentd3b82232014-07-30 08:57:39 -0700851 capturePreambleMs, triggerInData, captureFormat, data);
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700852 this.keyphraseExtras = keyphraseExtras;
Eric Laurente48188c2014-04-18 17:44:11 -0700853 }
Sandeep Siddhartha68173372014-07-28 13:25:30 -0700854
855 public static final Parcelable.Creator<KeyphraseRecognitionEvent> CREATOR
856 = new Parcelable.Creator<KeyphraseRecognitionEvent>() {
857 public KeyphraseRecognitionEvent createFromParcel(Parcel in) {
858 return KeyphraseRecognitionEvent.fromParcel(in);
859 }
860
861 public KeyphraseRecognitionEvent[] newArray(int size) {
862 return new KeyphraseRecognitionEvent[size];
863 }
864 };
865
866 private static KeyphraseRecognitionEvent fromParcel(Parcel in) {
867 int status = in.readInt();
868 int soundModelHandle = in.readInt();
869 boolean captureAvailable = in.readByte() == 1;
870 int captureSession = in.readInt();
871 int captureDelayMs = in.readInt();
872 int capturePreambleMs = in.readInt();
Eric Laurentd3b82232014-07-30 08:57:39 -0700873 boolean triggerInData = in.readByte() == 1;
874 AudioFormat captureFormat = null;
875 if (triggerInData) {
876 int sampleRate = in.readInt();
877 int encoding = in.readInt();
878 int channelMask = in.readInt();
879 captureFormat = (new AudioFormat.Builder())
880 .setChannelMask(channelMask)
881 .setEncoding(encoding)
882 .setSampleRate(sampleRate)
883 .build();
884 }
Sandeep Siddhartha68173372014-07-28 13:25:30 -0700885 byte[] data = in.readBlob();
Sandeep Siddhartha68173372014-07-28 13:25:30 -0700886 KeyphraseRecognitionExtra[] keyphraseExtras =
887 in.createTypedArray(KeyphraseRecognitionExtra.CREATOR);
888 return new KeyphraseRecognitionEvent(status, soundModelHandle, captureAvailable,
Eric Laurentd3b82232014-07-30 08:57:39 -0700889 captureSession, captureDelayMs, capturePreambleMs, triggerInData,
890 captureFormat, data, keyphraseExtras);
Sandeep Siddhartha68173372014-07-28 13:25:30 -0700891 }
892
893 @Override
894 public void writeToParcel(Parcel dest, int flags) {
895 dest.writeInt(status);
896 dest.writeInt(soundModelHandle);
897 dest.writeByte((byte) (captureAvailable ? 1 : 0));
898 dest.writeInt(captureSession);
899 dest.writeInt(captureDelayMs);
900 dest.writeInt(capturePreambleMs);
Eric Laurentd3b82232014-07-30 08:57:39 -0700901 if (triggerInData && (captureFormat != null)) {
902 dest.writeByte((byte)1);
903 dest.writeInt(captureFormat.getSampleRate());
904 dest.writeInt(captureFormat.getEncoding());
905 dest.writeInt(captureFormat.getChannelMask());
906 } else {
907 dest.writeByte((byte)0);
908 }
Sandeep Siddhartha68173372014-07-28 13:25:30 -0700909 dest.writeBlob(data);
Sandeep Siddhartha68173372014-07-28 13:25:30 -0700910 dest.writeTypedArray(keyphraseExtras, flags);
911 }
912
913 @Override
914 public int describeContents() {
915 return 0;
916 }
917
918 @Override
919 public int hashCode() {
920 final int prime = 31;
921 int result = super.hashCode();
922 result = prime * result + Arrays.hashCode(keyphraseExtras);
Sandeep Siddhartha68173372014-07-28 13:25:30 -0700923 return result;
924 }
925
926 @Override
927 public boolean equals(Object obj) {
928 if (this == obj)
929 return true;
930 if (!super.equals(obj))
931 return false;
932 if (getClass() != obj.getClass())
933 return false;
934 KeyphraseRecognitionEvent other = (KeyphraseRecognitionEvent) obj;
935 if (!Arrays.equals(keyphraseExtras, other.keyphraseExtras))
936 return false;
Sandeep Siddhartha68173372014-07-28 13:25:30 -0700937 return true;
938 }
939
940 @Override
941 public String toString() {
942 return "KeyphraseRecognitionEvent [keyphraseExtras=" + Arrays.toString(keyphraseExtras)
Eric Laurentd3b82232014-07-30 08:57:39 -0700943 + ", status=" + status
Sandeep Siddhartha68173372014-07-28 13:25:30 -0700944 + ", soundModelHandle=" + soundModelHandle + ", captureAvailable="
945 + captureAvailable + ", captureSession=" + captureSession + ", captureDelayMs="
946 + captureDelayMs + ", capturePreambleMs=" + capturePreambleMs
Eric Laurentd3b82232014-07-30 08:57:39 -0700947 + ", triggerInData=" + triggerInData
948 + ((captureFormat == null) ? "" :
949 (", sampleRate=" + captureFormat.getSampleRate()))
950 + ((captureFormat == null) ? "" :
951 (", encoding=" + captureFormat.getEncoding()))
952 + ((captureFormat == null) ? "" :
953 (", channelMask=" + captureFormat.getChannelMask()))
Sandeep Siddhartha68173372014-07-28 13:25:30 -0700954 + ", data=" + (data == null ? 0 : data.length) + "]";
955 }
Eric Laurente48188c2014-04-18 17:44:11 -0700956 }
957
958 /**
Eric Laurentd3b82232014-07-30 08:57:39 -0700959 * Status codes for {@link SoundModelEvent}
960 */
961 /** Sound Model was updated */
962 public static final int SOUNDMODEL_STATUS_UPDATED = 0;
963
964 /**
965 * A SoundModelEvent is provided by the
966 * {@link StatusListener#onSoundModelUpdate(SoundModelEvent)}
967 * callback when a sound model has been updated by the implementation
968 */
969 public static class SoundModelEvent implements Parcelable {
970 /** Status e.g {@link #SOUNDMODEL_STATUS_UPDATED} */
971 public final int status;
972 /** The updated sound model handle */
973 public final int soundModelHandle;
974 /** New sound model data */
975 public final byte[] data;
976
977 SoundModelEvent(int status, int soundModelHandle, byte[] data) {
978 this.status = status;
979 this.soundModelHandle = soundModelHandle;
980 this.data = data;
981 }
982
983 public static final Parcelable.Creator<SoundModelEvent> CREATOR
984 = new Parcelable.Creator<SoundModelEvent>() {
985 public SoundModelEvent createFromParcel(Parcel in) {
986 return SoundModelEvent.fromParcel(in);
987 }
988
989 public SoundModelEvent[] newArray(int size) {
990 return new SoundModelEvent[size];
991 }
992 };
993
994 private static SoundModelEvent fromParcel(Parcel in) {
995 int status = in.readInt();
996 int soundModelHandle = in.readInt();
997 byte[] data = in.readBlob();
998 return new SoundModelEvent(status, soundModelHandle, data);
999 }
1000
1001 @Override
1002 public int describeContents() {
1003 return 0;
1004 }
1005
1006 @Override
1007 public void writeToParcel(Parcel dest, int flags) {
1008 dest.writeInt(status);
1009 dest.writeInt(soundModelHandle);
1010 dest.writeBlob(data);
1011 }
1012
1013 @Override
1014 public int hashCode() {
1015 final int prime = 31;
1016 int result = 1;
1017 result = prime * result + Arrays.hashCode(data);
1018 result = prime * result + soundModelHandle;
1019 result = prime * result + status;
1020 return result;
1021 }
1022
1023 @Override
1024 public boolean equals(Object obj) {
1025 if (this == obj)
1026 return true;
1027 if (obj == null)
1028 return false;
1029 if (getClass() != obj.getClass())
1030 return false;
1031 SoundModelEvent other = (SoundModelEvent) obj;
1032 if (!Arrays.equals(data, other.data))
1033 return false;
1034 if (soundModelHandle != other.soundModelHandle)
1035 return false;
1036 if (status != other.status)
1037 return false;
1038 return true;
1039 }
1040
1041 @Override
1042 public String toString() {
1043 return "SoundModelEvent [status=" + status + ", soundModelHandle=" + soundModelHandle
1044 + ", data=" + (data == null ? 0 : data.length) + "]";
1045 }
1046 }
1047
1048 /**
1049 * Native service state. {@link StatusListener#onServiceStateChange(int)}
1050 */
1051 // Keep in sync with system/core/include/system/sound_trigger.h
1052 /** Sound trigger service is enabled */
1053 public static final int SERVICE_STATE_ENABLED = 0;
1054 /** Sound trigger service is disabled */
1055 public static final int SERVICE_STATE_DISABLED = 1;
1056
1057 /**
Eric Laurente48188c2014-04-18 17:44:11 -07001058 * Returns a list of descriptors for all harware modules loaded.
1059 * @param modules A ModuleProperties array where the list will be returned.
1060 * @return - {@link #STATUS_OK} in case of success
1061 * - {@link #STATUS_ERROR} in case of unspecified error
1062 * - {@link #STATUS_PERMISSION_DENIED} if the caller does not have system permission
1063 * - {@link #STATUS_NO_INIT} if the native service cannot be reached
1064 * - {@link #STATUS_BAD_VALUE} if modules is null
1065 * - {@link #STATUS_DEAD_OBJECT} if the binder transaction to the native service fails
1066 */
1067 public static native int listModules(ArrayList <ModuleProperties> modules);
1068
1069 /**
1070 * Get an interface on a hardware module to control sound models and recognition on
1071 * this module.
1072 * @param moduleId Sound module system identifier {@link ModuleProperties#id}. mandatory.
1073 * @param listener {@link StatusListener} interface. Mandatory.
1074 * @param handler the Handler that will receive the callabcks. Can be null if default handler
1075 * is OK.
1076 * @return a valid sound module in case of success or null in case of error.
1077 */
1078 public static SoundTriggerModule attachModule(int moduleId,
1079 StatusListener listener,
1080 Handler handler) {
1081 if (listener == null) {
1082 return null;
1083 }
1084 SoundTriggerModule module = new SoundTriggerModule(moduleId, listener, handler);
1085 return module;
1086 }
1087
1088 /**
1089 * Interface provided by the client application when attaching to a {@link SoundTriggerModule}
1090 * to received recognition and error notifications.
1091 */
1092 public static interface StatusListener {
1093 /**
1094 * Called when recognition succeeds of fails
1095 */
1096 public abstract void onRecognition(RecognitionEvent event);
1097
1098 /**
Eric Laurentd3b82232014-07-30 08:57:39 -07001099 * Called when a sound model has been updated
1100 */
1101 public abstract void onSoundModelUpdate(SoundModelEvent event);
1102
1103 /**
1104 * Called when the sound trigger native service state changes.
1105 * @param state Native service state. One of {@link SoundTrigger#SERVICE_STATE_ENABLED},
1106 * {@link SoundTrigger#SERVICE_STATE_DISABLED}
1107 */
1108 public abstract void onServiceStateChange(int state);
1109
1110 /**
Eric Laurente48188c2014-04-18 17:44:11 -07001111 * Called when the sound trigger native service dies
1112 */
1113 public abstract void onServiceDied();
1114 }
1115}