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