blob: dde8a33271723a19b387725443b58d284004f460 [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
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -080019import static android.system.OsConstants.EINVAL;
20import static android.system.OsConstants.ENODEV;
21import static android.system.OsConstants.ENOSYS;
22import static android.system.OsConstants.EPERM;
23import static android.system.OsConstants.EPIPE;
24
25import android.annotation.Nullable;
26import android.annotation.SystemApi;
Eric Laurentd3b82232014-07-30 08:57:39 -070027import android.media.AudioFormat;
Eric Laurente48188c2014-04-18 17:44:11 -070028import android.os.Handler;
Sandeep Siddhartha05589722014-07-17 16:21:54 -070029import android.os.Parcel;
30import android.os.Parcelable;
Eric Laurente48188c2014-04-18 17:44:11 -070031
32import java.util.ArrayList;
Sandeep Siddhartha05589722014-07-17 16:21:54 -070033import java.util.Arrays;
Eric Laurente48188c2014-04-18 17:44:11 -070034import java.util.UUID;
35
36/**
37 * The SoundTrigger class provides access via JNI to the native service managing
38 * the sound trigger HAL.
39 *
40 * @hide
41 */
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -080042@SystemApi
Eric Laurente48188c2014-04-18 17:44:11 -070043public class SoundTrigger {
44
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -080045 private SoundTrigger() {
46 }
47
48 /**
49 * Status code used when the operation succeeded
50 */
Eric Laurente48188c2014-04-18 17:44:11 -070051 public static final int STATUS_OK = 0;
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -080052 /** @hide */
Eric Laurente48188c2014-04-18 17:44:11 -070053 public static final int STATUS_ERROR = Integer.MIN_VALUE;
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -080054 /** @hide */
Lazar Trsic8ea56f62015-07-07 17:31:20 +020055 public static final int STATUS_PERMISSION_DENIED = -EPERM;
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -080056 /** @hide */
Lazar Trsic8ea56f62015-07-07 17:31:20 +020057 public static final int STATUS_NO_INIT = -ENODEV;
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -080058 /** @hide */
Lazar Trsic8ea56f62015-07-07 17:31:20 +020059 public static final int STATUS_BAD_VALUE = -EINVAL;
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -080060 /** @hide */
Lazar Trsic8ea56f62015-07-07 17:31:20 +020061 public static final int STATUS_DEAD_OBJECT = -EPIPE;
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -080062 /** @hide */
Lazar Trsic8ea56f62015-07-07 17:31:20 +020063 public static final int STATUS_INVALID_OPERATION = -ENOSYS;
Eric Laurente48188c2014-04-18 17:44:11 -070064
65 /*****************************************************************************
66 * A ModuleProperties describes a given sound trigger hardware module
67 * managed by the native sound trigger service. Each module has a unique
68 * ID used to target any API call to this paricular module. Module
69 * properties are returned by listModules() method.
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -080070 *
71 * @hide
Eric Laurente48188c2014-04-18 17:44:11 -070072 ****************************************************************************/
Sandeep Siddhartha05589722014-07-17 16:21:54 -070073 public static class ModuleProperties implements Parcelable {
Eric Laurente48188c2014-04-18 17:44:11 -070074 /** Unique module ID provided by the native service */
75 public final int id;
76
77 /** human readable voice detection engine implementor */
78 public final String implementor;
79
80 /** human readable voice detection engine description */
81 public final String description;
82
83 /** Unique voice engine Id (changes with each version) */
84 public final UUID uuid;
85
86 /** Voice detection engine version */
87 public final int version;
88
89 /** Maximum number of active sound models */
90 public final int maxSoundModels;
91
92 /** Maximum number of key phrases */
Sandeep Siddharthad4233c62014-06-12 18:31:19 -070093 public final int maxKeyphrases;
Eric Laurente48188c2014-04-18 17:44:11 -070094
95 /** Maximum number of users per key phrase */
96 public final int maxUsers;
97
98 /** Supported recognition modes (bit field, RECOGNITION_MODE_VOICE_TRIGGER ...) */
99 public final int recognitionModes;
100
101 /** Supports seamless transition to capture mode after recognition */
102 public final boolean supportsCaptureTransition;
103
104 /** Maximum buffering capacity in ms if supportsCaptureTransition() is true */
105 public final int maxBufferMs;
106
107 /** Supports capture by other use cases while detection is active */
108 public final boolean supportsConcurrentCapture;
109
110 /** Rated power consumption when detection is active with TDB silence/sound/speech ratio */
111 public final int powerConsumptionMw;
112
Eric Laurentd3b82232014-07-30 08:57:39 -0700113 /** Returns the trigger (key phrase) capture in the binary data of the
114 * recognition callback event */
115 public final boolean returnsTriggerInEvent;
116
Eric Laurente48188c2014-04-18 17:44:11 -0700117 ModuleProperties(int id, String implementor, String description,
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700118 String uuid, int version, int maxSoundModels, int maxKeyphrases,
Eric Laurente48188c2014-04-18 17:44:11 -0700119 int maxUsers, int recognitionModes, boolean supportsCaptureTransition,
120 int maxBufferMs, boolean supportsConcurrentCapture,
Eric Laurentd3b82232014-07-30 08:57:39 -0700121 int powerConsumptionMw, boolean returnsTriggerInEvent) {
Eric Laurente48188c2014-04-18 17:44:11 -0700122 this.id = id;
123 this.implementor = implementor;
124 this.description = description;
125 this.uuid = UUID.fromString(uuid);
126 this.version = version;
127 this.maxSoundModels = maxSoundModels;
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700128 this.maxKeyphrases = maxKeyphrases;
Eric Laurente48188c2014-04-18 17:44:11 -0700129 this.maxUsers = maxUsers;
130 this.recognitionModes = recognitionModes;
131 this.supportsCaptureTransition = supportsCaptureTransition;
132 this.maxBufferMs = maxBufferMs;
133 this.supportsConcurrentCapture = supportsConcurrentCapture;
134 this.powerConsumptionMw = powerConsumptionMw;
Eric Laurentd3b82232014-07-30 08:57:39 -0700135 this.returnsTriggerInEvent = returnsTriggerInEvent;
Eric Laurente48188c2014-04-18 17:44:11 -0700136 }
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700137
138 public static final Parcelable.Creator<ModuleProperties> CREATOR
139 = new Parcelable.Creator<ModuleProperties>() {
140 public ModuleProperties createFromParcel(Parcel in) {
141 return ModuleProperties.fromParcel(in);
142 }
143
144 public ModuleProperties[] newArray(int size) {
145 return new ModuleProperties[size];
146 }
147 };
148
149 private static ModuleProperties fromParcel(Parcel in) {
150 int id = in.readInt();
151 String implementor = in.readString();
152 String description = in.readString();
153 String uuid = in.readString();
154 int version = in.readInt();
155 int maxSoundModels = in.readInt();
156 int maxKeyphrases = in.readInt();
157 int maxUsers = in.readInt();
158 int recognitionModes = in.readInt();
159 boolean supportsCaptureTransition = in.readByte() == 1;
160 int maxBufferMs = in.readInt();
161 boolean supportsConcurrentCapture = in.readByte() == 1;
162 int powerConsumptionMw = in.readInt();
Eric Laurentd3b82232014-07-30 08:57:39 -0700163 boolean returnsTriggerInEvent = in.readByte() == 1;
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700164 return new ModuleProperties(id, implementor, description, uuid, version,
165 maxSoundModels, maxKeyphrases, maxUsers, recognitionModes,
166 supportsCaptureTransition, maxBufferMs, supportsConcurrentCapture,
Eric Laurentd3b82232014-07-30 08:57:39 -0700167 powerConsumptionMw, returnsTriggerInEvent);
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700168 }
169
170 @Override
171 public void writeToParcel(Parcel dest, int flags) {
172 dest.writeInt(id);
173 dest.writeString(implementor);
174 dest.writeString(description);
175 dest.writeString(uuid.toString());
176 dest.writeInt(version);
177 dest.writeInt(maxSoundModels);
178 dest.writeInt(maxKeyphrases);
179 dest.writeInt(maxUsers);
180 dest.writeInt(recognitionModes);
181 dest.writeByte((byte) (supportsCaptureTransition ? 1 : 0));
182 dest.writeInt(maxBufferMs);
183 dest.writeByte((byte) (supportsConcurrentCapture ? 1 : 0));
184 dest.writeInt(powerConsumptionMw);
Eric Laurentd3b82232014-07-30 08:57:39 -0700185 dest.writeByte((byte) (returnsTriggerInEvent ? 1 : 0));
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700186 }
187
188 @Override
189 public int describeContents() {
190 return 0;
191 }
192
193 @Override
194 public String toString() {
195 return "ModuleProperties [id=" + id + ", implementor=" + implementor + ", description="
196 + description + ", uuid=" + uuid + ", version=" + version + ", maxSoundModels="
197 + maxSoundModels + ", maxKeyphrases=" + maxKeyphrases + ", maxUsers="
198 + maxUsers + ", recognitionModes=" + recognitionModes
199 + ", supportsCaptureTransition=" + supportsCaptureTransition + ", maxBufferMs="
200 + maxBufferMs + ", supportsConcurrentCapture=" + supportsConcurrentCapture
Eric Laurentd3b82232014-07-30 08:57:39 -0700201 + ", powerConsumptionMw=" + powerConsumptionMw
202 + ", returnsTriggerInEvent=" + returnsTriggerInEvent + "]";
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700203 }
Eric Laurente48188c2014-04-18 17:44:11 -0700204 }
205
206 /*****************************************************************************
207 * A SoundModel describes the attributes and contains the binary data used by the hardware
208 * implementation to detect a particular sound pattern.
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700209 * A specialized version {@link KeyphraseSoundModel} is defined for key phrase
Eric Laurente48188c2014-04-18 17:44:11 -0700210 * sound models.
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -0800211 *
212 * @hide
Eric Laurente48188c2014-04-18 17:44:11 -0700213 ****************************************************************************/
214 public static class SoundModel {
215 /** Undefined sound model type */
216 public static final int TYPE_UNKNOWN = -1;
217
218 /** Keyphrase sound model */
219 public static final int TYPE_KEYPHRASE = 0;
220
Arunesh Mishraa772e5f2016-01-25 10:33:11 -0800221 /**
222 * A generic sound model. Use this type only for non-keyphrase sound models such as
223 * ones that match a particular sound pattern.
224 */
225 public static final int TYPE_GENERIC_SOUND = 1;
226
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700227 /** Unique sound model identifier */
228 public final UUID uuid;
229
Eric Laurente48188c2014-04-18 17:44:11 -0700230 /** Sound model type (e.g. TYPE_KEYPHRASE); */
231 public final int type;
232
Eric Laurentd3b82232014-07-30 08:57:39 -0700233 /** Unique sound model vendor identifier */
234 public final UUID vendorUuid;
235
Eric Laurente48188c2014-04-18 17:44:11 -0700236 /** Opaque data. For use by vendor implementation and enrollment application */
237 public final byte[] data;
238
Eric Laurentd3b82232014-07-30 08:57:39 -0700239 public SoundModel(UUID uuid, UUID vendorUuid, int type, byte[] data) {
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700240 this.uuid = uuid;
Eric Laurentd3b82232014-07-30 08:57:39 -0700241 this.vendorUuid = vendorUuid;
Eric Laurente48188c2014-04-18 17:44:11 -0700242 this.type = type;
243 this.data = data;
244 }
Sandeep Siddhartha45c00b52014-10-16 16:17:11 -0700245
246 @Override
247 public int hashCode() {
248 final int prime = 31;
249 int result = 1;
250 result = prime * result + Arrays.hashCode(data);
251 result = prime * result + type;
252 result = prime * result + ((uuid == null) ? 0 : uuid.hashCode());
253 result = prime * result + ((vendorUuid == null) ? 0 : vendorUuid.hashCode());
254 return result;
255 }
256
257 @Override
258 public boolean equals(Object obj) {
259 if (this == obj)
260 return true;
261 if (obj == null)
262 return false;
263 if (!(obj instanceof SoundModel))
264 return false;
265 SoundModel other = (SoundModel) obj;
266 if (!Arrays.equals(data, other.data))
267 return false;
268 if (type != other.type)
269 return false;
270 if (uuid == null) {
271 if (other.uuid != null)
272 return false;
273 } else if (!uuid.equals(other.uuid))
274 return false;
275 if (vendorUuid == null) {
276 if (other.vendorUuid != null)
277 return false;
278 } else if (!vendorUuid.equals(other.vendorUuid))
279 return false;
280 return true;
281 }
Eric Laurente48188c2014-04-18 17:44:11 -0700282 }
283
284 /*****************************************************************************
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700285 * A Keyphrase describes a key phrase that can be detected by a
286 * {@link KeyphraseSoundModel}
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -0800287 *
288 * @hide
Eric Laurente48188c2014-04-18 17:44:11 -0700289 ****************************************************************************/
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700290 public static class Keyphrase implements Parcelable {
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700291 /** Unique identifier for this keyphrase */
292 public final int id;
293
Eric Laurente48188c2014-04-18 17:44:11 -0700294 /** Recognition modes supported for this key phrase in the model */
295 public final int recognitionModes;
296
297 /** Locale of the keyphrase. JAVA Locale string e.g en_US */
298 public final String locale;
299
300 /** Key phrase text */
301 public final String text;
302
Eric Laurent013f66b2014-07-06 16:35:00 -0700303 /** Users this key phrase has been trained for. countains sound trigger specific user IDs
304 * derived from system user IDs {@link android.os.UserHandle#getIdentifier()}. */
305 public final int[] users;
Eric Laurente48188c2014-04-18 17:44:11 -0700306
Eric Laurent013f66b2014-07-06 16:35:00 -0700307 public Keyphrase(int id, int recognitionModes, String locale, String text, int[] users) {
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700308 this.id = id;
Eric Laurente48188c2014-04-18 17:44:11 -0700309 this.recognitionModes = recognitionModes;
310 this.locale = locale;
311 this.text = text;
Eric Laurent013f66b2014-07-06 16:35:00 -0700312 this.users = users;
Eric Laurente48188c2014-04-18 17:44:11 -0700313 }
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700314
315 public static final Parcelable.Creator<Keyphrase> CREATOR
316 = new Parcelable.Creator<Keyphrase>() {
317 public Keyphrase createFromParcel(Parcel in) {
318 return Keyphrase.fromParcel(in);
319 }
320
321 public Keyphrase[] newArray(int size) {
322 return new Keyphrase[size];
323 }
324 };
325
326 private static Keyphrase fromParcel(Parcel in) {
327 int id = in.readInt();
328 int recognitionModes = in.readInt();
329 String locale = in.readString();
330 String text = in.readString();
331 int[] users = null;
332 int numUsers = in.readInt();
Sandeep Siddhartha110f5692014-07-20 12:22:56 -0700333 if (numUsers >= 0) {
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700334 users = new int[numUsers];
335 in.readIntArray(users);
336 }
337 return new Keyphrase(id, recognitionModes, locale, text, users);
338 }
339
340 @Override
341 public void writeToParcel(Parcel dest, int flags) {
342 dest.writeInt(id);
343 dest.writeInt(recognitionModes);
344 dest.writeString(locale);
345 dest.writeString(text);
346 if (users != null) {
347 dest.writeInt(users.length);
348 dest.writeIntArray(users);
349 } else {
Sandeep Siddhartha110f5692014-07-20 12:22:56 -0700350 dest.writeInt(-1);
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700351 }
352 }
353
354 @Override
355 public int describeContents() {
356 return 0;
357 }
358
359 @Override
360 public int hashCode() {
361 final int prime = 31;
362 int result = 1;
363 result = prime * result + ((text == null) ? 0 : text.hashCode());
364 result = prime * result + id;
365 result = prime * result + ((locale == null) ? 0 : locale.hashCode());
366 result = prime * result + recognitionModes;
367 result = prime * result + Arrays.hashCode(users);
368 return result;
369 }
370
371 @Override
372 public boolean equals(Object obj) {
373 if (this == obj)
374 return true;
375 if (obj == null)
376 return false;
377 if (getClass() != obj.getClass())
378 return false;
379 Keyphrase other = (Keyphrase) obj;
380 if (text == null) {
381 if (other.text != null)
382 return false;
383 } else if (!text.equals(other.text))
384 return false;
385 if (id != other.id)
386 return false;
387 if (locale == null) {
388 if (other.locale != null)
389 return false;
390 } else if (!locale.equals(other.locale))
391 return false;
392 if (recognitionModes != other.recognitionModes)
393 return false;
394 if (!Arrays.equals(users, other.users))
395 return false;
396 return true;
397 }
398
399 @Override
400 public String toString() {
401 return "Keyphrase [id=" + id + ", recognitionModes=" + recognitionModes + ", locale="
402 + locale + ", text=" + text + ", users=" + Arrays.toString(users) + "]";
403 }
Eric Laurente48188c2014-04-18 17:44:11 -0700404 }
405
406 /*****************************************************************************
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700407 * A KeyphraseSoundModel is a specialized {@link SoundModel} for key phrases.
Eric Laurente48188c2014-04-18 17:44:11 -0700408 * It contains data needed by the hardware to detect a certain number of key phrases
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700409 * and the list of corresponding {@link Keyphrase} descriptors.
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -0800410 *
411 * @hide
Eric Laurente48188c2014-04-18 17:44:11 -0700412 ****************************************************************************/
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700413 public static class KeyphraseSoundModel extends SoundModel implements Parcelable {
Eric Laurente48188c2014-04-18 17:44:11 -0700414 /** Key phrases in this sound model */
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700415 public final Keyphrase[] keyphrases; // keyword phrases in model
Eric Laurente48188c2014-04-18 17:44:11 -0700416
Eric Laurentd3b82232014-07-30 08:57:39 -0700417 public KeyphraseSoundModel(
418 UUID uuid, UUID vendorUuid, byte[] data, Keyphrase[] keyphrases) {
419 super(uuid, vendorUuid, TYPE_KEYPHRASE, data);
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700420 this.keyphrases = keyphrases;
Eric Laurente48188c2014-04-18 17:44:11 -0700421 }
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700422
423 public static final Parcelable.Creator<KeyphraseSoundModel> CREATOR
424 = new Parcelable.Creator<KeyphraseSoundModel>() {
425 public KeyphraseSoundModel createFromParcel(Parcel in) {
426 return KeyphraseSoundModel.fromParcel(in);
427 }
428
429 public KeyphraseSoundModel[] newArray(int size) {
430 return new KeyphraseSoundModel[size];
431 }
432 };
433
434 private static KeyphraseSoundModel fromParcel(Parcel in) {
435 UUID uuid = UUID.fromString(in.readString());
Eric Laurentd3b82232014-07-30 08:57:39 -0700436 UUID vendorUuid = null;
437 int length = in.readInt();
438 if (length >= 0) {
439 vendorUuid = UUID.fromString(in.readString());
440 }
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -0700441 byte[] data = in.readBlob();
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700442 Keyphrase[] keyphrases = in.createTypedArray(Keyphrase.CREATOR);
Eric Laurentd3b82232014-07-30 08:57:39 -0700443 return new KeyphraseSoundModel(uuid, vendorUuid, data, keyphrases);
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700444 }
445
446 @Override
447 public int describeContents() {
448 return 0;
449 }
450
451 @Override
452 public void writeToParcel(Parcel dest, int flags) {
453 dest.writeString(uuid.toString());
Eric Laurentd3b82232014-07-30 08:57:39 -0700454 if (vendorUuid == null) {
455 dest.writeInt(-1);
456 } else {
457 dest.writeInt(vendorUuid.toString().length());
458 dest.writeString(vendorUuid.toString());
459 }
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -0700460 dest.writeBlob(data);
Sandeep Siddhartha68173372014-07-28 13:25:30 -0700461 dest.writeTypedArray(keyphrases, flags);
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700462 }
Sandeep Siddhartha110f5692014-07-20 12:22:56 -0700463
464 @Override
465 public String toString() {
Eric Laurentd3b82232014-07-30 08:57:39 -0700466 return "KeyphraseSoundModel [keyphrases=" + Arrays.toString(keyphrases)
467 + ", uuid=" + uuid + ", vendorUuid=" + vendorUuid
468 + ", type=" + type + ", data=" + (data == null ? 0 : data.length) + "]";
Sandeep Siddhartha110f5692014-07-20 12:22:56 -0700469 }
Sandeep Siddhartha45c00b52014-10-16 16:17:11 -0700470
471 @Override
472 public int hashCode() {
473 final int prime = 31;
474 int result = super.hashCode();
475 result = prime * result + Arrays.hashCode(keyphrases);
476 return result;
477 }
478
479 @Override
480 public boolean equals(Object obj) {
481 if (this == obj)
482 return true;
483 if (!super.equals(obj))
484 return false;
485 if (!(obj instanceof KeyphraseSoundModel))
486 return false;
487 KeyphraseSoundModel other = (KeyphraseSoundModel) obj;
488 if (!Arrays.equals(keyphrases, other.keyphrases))
489 return false;
490 return true;
491 }
Eric Laurente48188c2014-04-18 17:44:11 -0700492 }
493
Arunesh Mishraa772e5f2016-01-25 10:33:11 -0800494
495 /*****************************************************************************
496 * A GenericSoundModel is a specialized {@link SoundModel} for non-voice sound
497 * patterns.
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -0800498 *
499 * @hide
Arunesh Mishraa772e5f2016-01-25 10:33:11 -0800500 ****************************************************************************/
501 public static class GenericSoundModel extends SoundModel implements Parcelable {
502
503 public static final Parcelable.Creator<GenericSoundModel> CREATOR
504 = new Parcelable.Creator<GenericSoundModel>() {
505 public GenericSoundModel createFromParcel(Parcel in) {
506 return GenericSoundModel.fromParcel(in);
507 }
508
509 public GenericSoundModel[] newArray(int size) {
510 return new GenericSoundModel[size];
511 }
512 };
513
514 public GenericSoundModel(UUID uuid, UUID vendorUuid, byte[] data) {
515 super(uuid, vendorUuid, TYPE_GENERIC_SOUND, data);
516 }
517
518 @Override
519 public int describeContents() {
520 return 0;
521 }
522
523 private static GenericSoundModel fromParcel(Parcel in) {
524 UUID uuid = UUID.fromString(in.readString());
525 UUID vendorUuid = null;
526 int length = in.readInt();
527 if (length >= 0) {
528 vendorUuid = UUID.fromString(in.readString());
529 }
530 byte[] data = in.readBlob();
531 return new GenericSoundModel(uuid, vendorUuid, data);
532 }
533
534 @Override
535 public void writeToParcel(Parcel dest, int flags) {
536 dest.writeString(uuid.toString());
537 if (vendorUuid == null) {
538 dest.writeInt(-1);
539 } else {
540 dest.writeInt(vendorUuid.toString().length());
541 dest.writeString(vendorUuid.toString());
542 }
543 dest.writeBlob(data);
544 }
545
546 @Override
547 public String toString() {
548 return "GenericSoundModel [uuid=" + uuid + ", vendorUuid=" + vendorUuid
549 + ", type=" + type + ", data=" + (data == null ? 0 : data.length) + "]";
550 }
551 }
552
Eric Laurente48188c2014-04-18 17:44:11 -0700553 /**
554 * Modes for key phrase recognition
555 */
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -0800556
557 /**
558 * Simple recognition of the key phrase
559 *
560 * @hide
561 */
Eric Laurente48188c2014-04-18 17:44:11 -0700562 public static final int RECOGNITION_MODE_VOICE_TRIGGER = 0x1;
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -0800563 /**
564 * Trigger only if one user is identified
565 *
566 * @hide
567 */
Eric Laurente48188c2014-04-18 17:44:11 -0700568 public static final int RECOGNITION_MODE_USER_IDENTIFICATION = 0x2;
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -0800569 /**
570 * Trigger only if one user is authenticated
571 *
572 * @hide
573 */
Eric Laurente48188c2014-04-18 17:44:11 -0700574 public static final int RECOGNITION_MODE_USER_AUTHENTICATION = 0x4;
575
576 /**
577 * Status codes for {@link RecognitionEvent}
578 */
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -0800579 /**
580 * Recognition success
581 *
582 * @hide
583 */
Eric Laurente48188c2014-04-18 17:44:11 -0700584 public static final int RECOGNITION_STATUS_SUCCESS = 0;
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -0800585 /**
586 * Recognition aborted (e.g. capture preempted by anotehr use case
587 *
588 * @hide
589 */
Eric Laurente48188c2014-04-18 17:44:11 -0700590 public static final int RECOGNITION_STATUS_ABORT = 1;
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -0800591 /**
592 * Recognition failure
593 *
594 * @hide
595 */
Eric Laurente48188c2014-04-18 17:44:11 -0700596 public static final int RECOGNITION_STATUS_FAILURE = 2;
597
598 /**
599 * A RecognitionEvent is provided by the
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -0800600 * {@code StatusListener#onRecognition(RecognitionEvent)}
Eric Laurente48188c2014-04-18 17:44:11 -0700601 * callback upon recognition success or failure.
602 */
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -0800603 public static class RecognitionEvent {
604 /**
605 * Recognition status e.g RECOGNITION_STATUS_SUCCESS
606 *
607 * @hide
608 */
Eric Laurente48188c2014-04-18 17:44:11 -0700609 public final int status;
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -0800610 /**
611 *
612 * Sound Model corresponding to this event callback
613 *
614 * @hide
615 */
Eric Laurente48188c2014-04-18 17:44:11 -0700616 public final int soundModelHandle;
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -0800617 /**
618 * True if it is possible to capture audio from this utterance buffered by the hardware
619 *
620 * @hide
621 */
Eric Laurente48188c2014-04-18 17:44:11 -0700622 public final boolean captureAvailable;
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -0800623 /**
624 * Audio session ID to be used when capturing the utterance with an AudioRecord
625 * if captureAvailable() is true.
626 *
627 * @hide
628 */
Eric Laurente48188c2014-04-18 17:44:11 -0700629 public final int captureSession;
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -0800630 /**
631 * Delay in ms between end of model detection and start of audio available for capture.
632 * A negative value is possible (e.g. if keyphrase is also available for capture)
633 *
634 * @hide
635 */
Eric Laurente48188c2014-04-18 17:44:11 -0700636 public final int captureDelayMs;
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -0800637 /**
638 * Duration in ms of audio captured before the start of the trigger. 0 if none.
639 *
640 * @hide
641 */
Eric Laurent013f66b2014-07-06 16:35:00 -0700642 public final int capturePreambleMs;
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -0800643 /**
644 * True if the trigger (key phrase capture is present in binary data
645 *
646 * @hide
647 */
Eric Laurentd3b82232014-07-30 08:57:39 -0700648 public final boolean triggerInData;
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -0800649 /**
650 * Audio format of either the trigger in event data or to use for capture of the
651 * rest of the utterance
652 *
653 * @hide
654 */
655 public final AudioFormat captureFormat;
656 /**
657 * Opaque data for use by system applications who know about voice engine internals,
658 * typically during enrollment.
659 *
660 * @hide
661 */
Eric Laurente48188c2014-04-18 17:44:11 -0700662 public final byte[] data;
663
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -0800664 /** @hide */
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -0700665 public RecognitionEvent(int status, int soundModelHandle, boolean captureAvailable,
Eric Laurentd3b82232014-07-30 08:57:39 -0700666 int captureSession, int captureDelayMs, int capturePreambleMs,
667 boolean triggerInData, AudioFormat captureFormat, byte[] data) {
Eric Laurente48188c2014-04-18 17:44:11 -0700668 this.status = status;
669 this.soundModelHandle = soundModelHandle;
670 this.captureAvailable = captureAvailable;
671 this.captureSession = captureSession;
672 this.captureDelayMs = captureDelayMs;
Eric Laurent013f66b2014-07-06 16:35:00 -0700673 this.capturePreambleMs = capturePreambleMs;
Eric Laurentd3b82232014-07-30 08:57:39 -0700674 this.triggerInData = triggerInData;
675 this.captureFormat = captureFormat;
Eric Laurente48188c2014-04-18 17:44:11 -0700676 this.data = data;
677 }
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -0700678
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -0800679 /**
680 * Check if is possible to capture audio from this utterance buffered by the hardware.
681 *
682 * @return {@code true} iff a capturing is possible
683 */
684 public boolean isCaptureAvailable() {
685 return captureAvailable;
686 }
687
688 /**
689 * Get the audio format of either the trigger in event data or to use for capture of the
690 * rest of the utterance
691 *
692 * @return the audio format
693 */
694 @Nullable public AudioFormat getCaptureFormat() {
695 return captureFormat;
696 }
697
698 /**
699 * Get Audio session ID to be used when capturing the utterance with an {@link AudioRecord}
700 * if {@link #isCaptureAvailable()} is true.
701 *
702 * @return The id of the capture session
703 */
704 public int getCaptureSession() {
705 return captureSession;
706 }
707
708 /**
709 * Get the opaque data for use by system applications who know about voice engine
710 * internals, typically during enrollment.
711 *
712 * @return The data of the event
713 */
714 public byte[] getData() {
715 return data;
716 }
717
718 /** @hide */
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -0700719 public static final Parcelable.Creator<RecognitionEvent> CREATOR
720 = new Parcelable.Creator<RecognitionEvent>() {
721 public RecognitionEvent createFromParcel(Parcel in) {
722 return RecognitionEvent.fromParcel(in);
723 }
724
725 public RecognitionEvent[] newArray(int size) {
726 return new RecognitionEvent[size];
727 }
728 };
729
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -0800730 /** @hide */
Arunesh Mishraf47f1732016-02-18 16:16:12 -0800731 protected static RecognitionEvent fromParcel(Parcel in) {
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -0700732 int status = in.readInt();
733 int soundModelHandle = in.readInt();
734 boolean captureAvailable = in.readByte() == 1;
735 int captureSession = in.readInt();
736 int captureDelayMs = in.readInt();
737 int capturePreambleMs = in.readInt();
Eric Laurentd3b82232014-07-30 08:57:39 -0700738 boolean triggerInData = in.readByte() == 1;
739 AudioFormat captureFormat = null;
Eric Laurent39fcca02014-09-05 16:44:19 -0700740 if (in.readByte() == 1) {
Eric Laurentd3b82232014-07-30 08:57:39 -0700741 int sampleRate = in.readInt();
742 int encoding = in.readInt();
743 int channelMask = in.readInt();
744 captureFormat = (new AudioFormat.Builder())
745 .setChannelMask(channelMask)
746 .setEncoding(encoding)
747 .setSampleRate(sampleRate)
748 .build();
749 }
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -0700750 byte[] data = in.readBlob();
751 return new RecognitionEvent(status, soundModelHandle, captureAvailable, captureSession,
Eric Laurentd3b82232014-07-30 08:57:39 -0700752 captureDelayMs, capturePreambleMs, triggerInData, captureFormat, data);
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -0700753 }
754
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -0800755 /** @hide */
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -0700756 public int describeContents() {
757 return 0;
758 }
759
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -0800760 /** @hide */
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -0700761 public void writeToParcel(Parcel dest, int flags) {
762 dest.writeInt(status);
763 dest.writeInt(soundModelHandle);
764 dest.writeByte((byte) (captureAvailable ? 1 : 0));
765 dest.writeInt(captureSession);
766 dest.writeInt(captureDelayMs);
767 dest.writeInt(capturePreambleMs);
Eric Laurent39fcca02014-09-05 16:44:19 -0700768 dest.writeByte((byte) (triggerInData ? 1 : 0));
769 if (captureFormat != null) {
Eric Laurentd3b82232014-07-30 08:57:39 -0700770 dest.writeByte((byte)1);
771 dest.writeInt(captureFormat.getSampleRate());
772 dest.writeInt(captureFormat.getEncoding());
773 dest.writeInt(captureFormat.getChannelMask());
774 } else {
775 dest.writeByte((byte)0);
776 }
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -0700777 dest.writeBlob(data);
778 }
779
780 @Override
781 public int hashCode() {
782 final int prime = 31;
783 int result = 1;
784 result = prime * result + (captureAvailable ? 1231 : 1237);
785 result = prime * result + captureDelayMs;
786 result = prime * result + capturePreambleMs;
787 result = prime * result + captureSession;
Eric Laurentd3b82232014-07-30 08:57:39 -0700788 result = prime * result + (triggerInData ? 1231 : 1237);
789 if (captureFormat != null) {
790 result = prime * result + captureFormat.getSampleRate();
791 result = prime * result + captureFormat.getEncoding();
792 result = prime * result + captureFormat.getChannelMask();
793 }
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -0700794 result = prime * result + Arrays.hashCode(data);
795 result = prime * result + soundModelHandle;
796 result = prime * result + status;
797 return result;
798 }
799
800 @Override
801 public boolean equals(Object obj) {
802 if (this == obj)
803 return true;
804 if (obj == null)
805 return false;
806 if (getClass() != obj.getClass())
807 return false;
808 RecognitionEvent other = (RecognitionEvent) obj;
809 if (captureAvailable != other.captureAvailable)
810 return false;
811 if (captureDelayMs != other.captureDelayMs)
812 return false;
813 if (capturePreambleMs != other.capturePreambleMs)
814 return false;
815 if (captureSession != other.captureSession)
816 return false;
817 if (!Arrays.equals(data, other.data))
818 return false;
819 if (soundModelHandle != other.soundModelHandle)
820 return false;
821 if (status != other.status)
822 return false;
Eric Laurentd3b82232014-07-30 08:57:39 -0700823 if (triggerInData != other.triggerInData)
824 return false;
Ryan Bavettaea04e8f2016-03-02 18:34:50 -0800825 if (captureFormat == null) {
826 if (other.captureFormat != null)
827 return false;
828 } else {
829 if (other.captureFormat == null)
830 return false;
831 if (captureFormat.getSampleRate() != other.captureFormat.getSampleRate())
832 return false;
833 if (captureFormat.getEncoding() != other.captureFormat.getEncoding())
834 return false;
835 if (captureFormat.getChannelMask() != other.captureFormat.getChannelMask())
836 return false;
837 }
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -0700838 return true;
839 }
Sandeep Siddhartha68173372014-07-28 13:25:30 -0700840
841 @Override
842 public String toString() {
843 return "RecognitionEvent [status=" + status + ", soundModelHandle=" + soundModelHandle
844 + ", captureAvailable=" + captureAvailable + ", captureSession="
845 + captureSession + ", captureDelayMs=" + captureDelayMs
846 + ", capturePreambleMs=" + capturePreambleMs
Eric Laurentd3b82232014-07-30 08:57:39 -0700847 + ", triggerInData=" + triggerInData
848 + ((captureFormat == null) ? "" :
849 (", sampleRate=" + captureFormat.getSampleRate()))
850 + ((captureFormat == null) ? "" :
851 (", encoding=" + captureFormat.getEncoding()))
852 + ((captureFormat == null) ? "" :
853 (", channelMask=" + captureFormat.getChannelMask()))
Sandeep Siddhartha68173372014-07-28 13:25:30 -0700854 + ", data=" + (data == null ? 0 : data.length) + "]";
855 }
Eric Laurente48188c2014-04-18 17:44:11 -0700856 }
857
858 /**
Eric Laurent013f66b2014-07-06 16:35:00 -0700859 * A RecognitionConfig is provided to
860 * {@link SoundTriggerModule#startRecognition(int, RecognitionConfig)} to configure the
861 * recognition request.
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -0800862 *
863 * @hide
Eric Laurent013f66b2014-07-06 16:35:00 -0700864 */
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700865 public static class RecognitionConfig implements Parcelable {
Eric Laurent013f66b2014-07-06 16:35:00 -0700866 /** True if the DSP should capture the trigger sound and make it available for further
867 * capture. */
868 public final boolean captureRequested;
Sandeep Siddhartha2c0273e2014-08-01 11:32:03 -0700869 /**
870 * True if the service should restart listening after the DSP triggers.
871 * Note: This config flag is currently used at the service layer rather than by the DSP.
872 */
873 public final boolean allowMultipleTriggers;
Eric Laurent013f66b2014-07-06 16:35:00 -0700874 /** List of all keyphrases in the sound model for which recognition should be performed with
875 * options for each keyphrase. */
876 public final KeyphraseRecognitionExtra keyphrases[];
877 /** Opaque data for use by system applications who know about voice engine internals,
878 * typically during enrollment. */
879 public final byte[] data;
880
Sandeep Siddhartha2c0273e2014-08-01 11:32:03 -0700881 public RecognitionConfig(boolean captureRequested, boolean allowMultipleTriggers,
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -0800882 KeyphraseRecognitionExtra[] keyphrases, byte[] data) {
Eric Laurent013f66b2014-07-06 16:35:00 -0700883 this.captureRequested = captureRequested;
Sandeep Siddhartha2c0273e2014-08-01 11:32:03 -0700884 this.allowMultipleTriggers = allowMultipleTriggers;
Eric Laurent013f66b2014-07-06 16:35:00 -0700885 this.keyphrases = keyphrases;
886 this.data = data;
887 }
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700888
889 public static final Parcelable.Creator<RecognitionConfig> CREATOR
890 = new Parcelable.Creator<RecognitionConfig>() {
891 public RecognitionConfig createFromParcel(Parcel in) {
892 return RecognitionConfig.fromParcel(in);
893 }
894
895 public RecognitionConfig[] newArray(int size) {
896 return new RecognitionConfig[size];
897 }
898 };
899
900 private static RecognitionConfig fromParcel(Parcel in) {
901 boolean captureRequested = in.readByte() == 1;
Sandeep Siddhartha2c0273e2014-08-01 11:32:03 -0700902 boolean allowMultipleTriggers = in.readByte() == 1;
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700903 KeyphraseRecognitionExtra[] keyphrases =
904 in.createTypedArray(KeyphraseRecognitionExtra.CREATOR);
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -0700905 byte[] data = in.readBlob();
Sandeep Siddhartha2c0273e2014-08-01 11:32:03 -0700906 return new RecognitionConfig(captureRequested, allowMultipleTriggers, keyphrases, data);
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700907 }
908
909 @Override
910 public void writeToParcel(Parcel dest, int flags) {
911 dest.writeByte((byte) (captureRequested ? 1 : 0));
Sandeep Siddhartha2c0273e2014-08-01 11:32:03 -0700912 dest.writeByte((byte) (allowMultipleTriggers ? 1 : 0));
Sandeep Siddhartha68173372014-07-28 13:25:30 -0700913 dest.writeTypedArray(keyphrases, flags);
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -0700914 dest.writeBlob(data);
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700915 }
916
917 @Override
918 public int describeContents() {
919 return 0;
920 }
Sandeep Siddhartha110f5692014-07-20 12:22:56 -0700921
922 @Override
923 public String toString() {
Sandeep Siddhartha2c0273e2014-08-01 11:32:03 -0700924 return "RecognitionConfig [captureRequested=" + captureRequested
925 + ", allowMultipleTriggers=" + allowMultipleTriggers + ", keyphrases="
926 + Arrays.toString(keyphrases) + ", data=" + Arrays.toString(data) + "]";
Sandeep Siddhartha110f5692014-07-20 12:22:56 -0700927 }
Eric Laurent013f66b2014-07-06 16:35:00 -0700928 }
929
930 /**
931 * Confidence level for users defined in a keyphrase.
932 * - The confidence level is expressed in percent (0% -100%).
933 * When used in a {@link KeyphraseRecognitionEvent} it indicates the detected confidence level
934 * When used in a {@link RecognitionConfig} it indicates the minimum confidence level that
935 * should trigger a recognition.
936 * - The user ID is derived from the system ID {@link android.os.UserHandle#getIdentifier()}.
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -0800937 *
938 * @hide
Eric Laurent013f66b2014-07-06 16:35:00 -0700939 */
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700940 public static class ConfidenceLevel implements Parcelable {
Eric Laurent013f66b2014-07-06 16:35:00 -0700941 public final int userId;
942 public final int confidenceLevel;
943
944 public ConfidenceLevel(int userId, int confidenceLevel) {
945 this.userId = userId;
946 this.confidenceLevel = confidenceLevel;
947 }
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700948
949 public static final Parcelable.Creator<ConfidenceLevel> CREATOR
950 = new Parcelable.Creator<ConfidenceLevel>() {
951 public ConfidenceLevel createFromParcel(Parcel in) {
952 return ConfidenceLevel.fromParcel(in);
953 }
954
955 public ConfidenceLevel[] newArray(int size) {
956 return new ConfidenceLevel[size];
957 }
958 };
959
960 private static ConfidenceLevel fromParcel(Parcel in) {
961 int userId = in.readInt();
962 int confidenceLevel = in.readInt();
963 return new ConfidenceLevel(userId, confidenceLevel);
964 }
965
966 @Override
967 public void writeToParcel(Parcel dest, int flags) {
968 dest.writeInt(userId);
969 dest.writeInt(confidenceLevel);
970 }
971
972 @Override
973 public int describeContents() {
974 return 0;
975 }
Sandeep Siddhartha68173372014-07-28 13:25:30 -0700976
977 @Override
978 public int hashCode() {
979 final int prime = 31;
980 int result = 1;
981 result = prime * result + confidenceLevel;
982 result = prime * result + userId;
983 return result;
984 }
985
986 @Override
987 public boolean equals(Object obj) {
988 if (this == obj)
989 return true;
990 if (obj == null)
991 return false;
992 if (getClass() != obj.getClass())
993 return false;
994 ConfidenceLevel other = (ConfidenceLevel) obj;
995 if (confidenceLevel != other.confidenceLevel)
996 return false;
997 if (userId != other.userId)
998 return false;
999 return true;
1000 }
1001
1002 @Override
1003 public String toString() {
1004 return "ConfidenceLevel [userId=" + userId
1005 + ", confidenceLevel=" + confidenceLevel + "]";
1006 }
Eric Laurent013f66b2014-07-06 16:35:00 -07001007 }
1008
1009 /**
Sandeep Siddharthad4233c62014-06-12 18:31:19 -07001010 * Additional data conveyed by a {@link KeyphraseRecognitionEvent}
Eric Laurente48188c2014-04-18 17:44:11 -07001011 * for a key phrase detection.
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -08001012 *
1013 * @hide
Eric Laurente48188c2014-04-18 17:44:11 -07001014 */
Sandeep Siddhartha05589722014-07-17 16:21:54 -07001015 public static class KeyphraseRecognitionExtra implements Parcelable {
1016 /** The keyphrase ID */
Eric Laurent013f66b2014-07-06 16:35:00 -07001017 public final int id;
Eric Laurente48188c2014-04-18 17:44:11 -07001018
1019 /** Recognition modes matched for this event */
1020 public final int recognitionModes;
1021
Eric Laurentd3b82232014-07-30 08:57:39 -07001022 /** Confidence level for mode RECOGNITION_MODE_VOICE_TRIGGER when user identification
1023 * is not performed */
1024 public final int coarseConfidenceLevel;
1025
Eric Laurent013f66b2014-07-06 16:35:00 -07001026 /** Confidence levels for all users recognized (KeyphraseRecognitionEvent) or to
1027 * be recognized (RecognitionConfig) */
1028 public final ConfidenceLevel[] confidenceLevels;
1029
Eric Laurentd3b82232014-07-30 08:57:39 -07001030 public KeyphraseRecognitionExtra(int id, int recognitionModes, int coarseConfidenceLevel,
1031 ConfidenceLevel[] confidenceLevels) {
Eric Laurent013f66b2014-07-06 16:35:00 -07001032 this.id = id;
Eric Laurente48188c2014-04-18 17:44:11 -07001033 this.recognitionModes = recognitionModes;
Eric Laurentd3b82232014-07-30 08:57:39 -07001034 this.coarseConfidenceLevel = coarseConfidenceLevel;
Eric Laurent013f66b2014-07-06 16:35:00 -07001035 this.confidenceLevels = confidenceLevels;
Eric Laurente48188c2014-04-18 17:44:11 -07001036 }
Sandeep Siddhartha05589722014-07-17 16:21:54 -07001037
1038 public static final Parcelable.Creator<KeyphraseRecognitionExtra> CREATOR
1039 = new Parcelable.Creator<KeyphraseRecognitionExtra>() {
1040 public KeyphraseRecognitionExtra createFromParcel(Parcel in) {
1041 return KeyphraseRecognitionExtra.fromParcel(in);
1042 }
1043
1044 public KeyphraseRecognitionExtra[] newArray(int size) {
1045 return new KeyphraseRecognitionExtra[size];
1046 }
1047 };
1048
1049 private static KeyphraseRecognitionExtra fromParcel(Parcel in) {
1050 int id = in.readInt();
1051 int recognitionModes = in.readInt();
Eric Laurentd3b82232014-07-30 08:57:39 -07001052 int coarseConfidenceLevel = in.readInt();
Sandeep Siddhartha05589722014-07-17 16:21:54 -07001053 ConfidenceLevel[] confidenceLevels = in.createTypedArray(ConfidenceLevel.CREATOR);
Eric Laurentd3b82232014-07-30 08:57:39 -07001054 return new KeyphraseRecognitionExtra(id, recognitionModes, coarseConfidenceLevel,
1055 confidenceLevels);
Sandeep Siddhartha05589722014-07-17 16:21:54 -07001056 }
1057
1058 @Override
1059 public void writeToParcel(Parcel dest, int flags) {
1060 dest.writeInt(id);
1061 dest.writeInt(recognitionModes);
Eric Laurentd3b82232014-07-30 08:57:39 -07001062 dest.writeInt(coarseConfidenceLevel);
Sandeep Siddhartha68173372014-07-28 13:25:30 -07001063 dest.writeTypedArray(confidenceLevels, flags);
Sandeep Siddhartha05589722014-07-17 16:21:54 -07001064 }
1065
1066 @Override
1067 public int describeContents() {
1068 return 0;
1069 }
Sandeep Siddhartha68173372014-07-28 13:25:30 -07001070
1071 @Override
1072 public int hashCode() {
1073 final int prime = 31;
1074 int result = 1;
1075 result = prime * result + Arrays.hashCode(confidenceLevels);
1076 result = prime * result + id;
1077 result = prime * result + recognitionModes;
Eric Laurentd3b82232014-07-30 08:57:39 -07001078 result = prime * result + coarseConfidenceLevel;
Sandeep Siddhartha68173372014-07-28 13:25:30 -07001079 return result;
1080 }
1081
1082 @Override
1083 public boolean equals(Object obj) {
1084 if (this == obj)
1085 return true;
1086 if (obj == null)
1087 return false;
1088 if (getClass() != obj.getClass())
1089 return false;
1090 KeyphraseRecognitionExtra other = (KeyphraseRecognitionExtra) obj;
1091 if (!Arrays.equals(confidenceLevels, other.confidenceLevels))
1092 return false;
1093 if (id != other.id)
1094 return false;
1095 if (recognitionModes != other.recognitionModes)
1096 return false;
Eric Laurentd3b82232014-07-30 08:57:39 -07001097 if (coarseConfidenceLevel != other.coarseConfidenceLevel)
1098 return false;
Sandeep Siddhartha68173372014-07-28 13:25:30 -07001099 return true;
1100 }
1101
1102 @Override
1103 public String toString() {
1104 return "KeyphraseRecognitionExtra [id=" + id + ", recognitionModes=" + recognitionModes
Eric Laurentd3b82232014-07-30 08:57:39 -07001105 + ", coarseConfidenceLevel=" + coarseConfidenceLevel
Sandeep Siddhartha68173372014-07-28 13:25:30 -07001106 + ", confidenceLevels=" + Arrays.toString(confidenceLevels) + "]";
1107 }
Eric Laurente48188c2014-04-18 17:44:11 -07001108 }
1109
1110 /**
1111 * Specialized {@link RecognitionEvent} for a key phrase detection.
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -08001112 *
1113 * @hide
Eric Laurente48188c2014-04-18 17:44:11 -07001114 */
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -08001115 public static class KeyphraseRecognitionEvent extends RecognitionEvent implements Parcelable {
Eric Laurente48188c2014-04-18 17:44:11 -07001116 /** Indicates if the key phrase is present in the buffered audio available for capture */
Sandeep Siddharthad4233c62014-06-12 18:31:19 -07001117 public final KeyphraseRecognitionExtra[] keyphraseExtras;
Eric Laurente48188c2014-04-18 17:44:11 -07001118
Sandeep Siddhartha68173372014-07-28 13:25:30 -07001119 public KeyphraseRecognitionEvent(int status, int soundModelHandle, boolean captureAvailable,
Eric Laurentd3b82232014-07-30 08:57:39 -07001120 int captureSession, int captureDelayMs, int capturePreambleMs,
1121 boolean triggerInData, AudioFormat captureFormat, byte[] data,
1122 KeyphraseRecognitionExtra[] keyphraseExtras) {
Eric Laurent013f66b2014-07-06 16:35:00 -07001123 super(status, soundModelHandle, captureAvailable, captureSession, captureDelayMs,
Eric Laurentd3b82232014-07-30 08:57:39 -07001124 capturePreambleMs, triggerInData, captureFormat, data);
Sandeep Siddharthad4233c62014-06-12 18:31:19 -07001125 this.keyphraseExtras = keyphraseExtras;
Eric Laurente48188c2014-04-18 17:44:11 -07001126 }
Sandeep Siddhartha68173372014-07-28 13:25:30 -07001127
1128 public static final Parcelable.Creator<KeyphraseRecognitionEvent> CREATOR
1129 = new Parcelable.Creator<KeyphraseRecognitionEvent>() {
1130 public KeyphraseRecognitionEvent createFromParcel(Parcel in) {
Arunesh Mishraf47f1732016-02-18 16:16:12 -08001131 return KeyphraseRecognitionEvent.fromParcelForKeyphrase(in);
Sandeep Siddhartha68173372014-07-28 13:25:30 -07001132 }
1133
1134 public KeyphraseRecognitionEvent[] newArray(int size) {
1135 return new KeyphraseRecognitionEvent[size];
1136 }
1137 };
1138
Arunesh Mishraf47f1732016-02-18 16:16:12 -08001139 private static KeyphraseRecognitionEvent fromParcelForKeyphrase(Parcel in) {
Sandeep Siddhartha68173372014-07-28 13:25:30 -07001140 int status = in.readInt();
1141 int soundModelHandle = in.readInt();
1142 boolean captureAvailable = in.readByte() == 1;
1143 int captureSession = in.readInt();
1144 int captureDelayMs = in.readInt();
1145 int capturePreambleMs = in.readInt();
Eric Laurentd3b82232014-07-30 08:57:39 -07001146 boolean triggerInData = in.readByte() == 1;
1147 AudioFormat captureFormat = null;
Eric Laurent75b433f2014-09-12 15:45:47 -07001148 if (in.readByte() == 1) {
Eric Laurentd3b82232014-07-30 08:57:39 -07001149 int sampleRate = in.readInt();
1150 int encoding = in.readInt();
1151 int channelMask = in.readInt();
1152 captureFormat = (new AudioFormat.Builder())
Ryan Bavettaea04e8f2016-03-02 18:34:50 -08001153 .setChannelMask(channelMask)
1154 .setEncoding(encoding)
1155 .setSampleRate(sampleRate)
1156 .build();
Eric Laurentd3b82232014-07-30 08:57:39 -07001157 }
Sandeep Siddhartha68173372014-07-28 13:25:30 -07001158 byte[] data = in.readBlob();
Sandeep Siddhartha68173372014-07-28 13:25:30 -07001159 KeyphraseRecognitionExtra[] keyphraseExtras =
1160 in.createTypedArray(KeyphraseRecognitionExtra.CREATOR);
1161 return new KeyphraseRecognitionEvent(status, soundModelHandle, captureAvailable,
Eric Laurentd3b82232014-07-30 08:57:39 -07001162 captureSession, captureDelayMs, capturePreambleMs, triggerInData,
1163 captureFormat, data, keyphraseExtras);
Sandeep Siddhartha68173372014-07-28 13:25:30 -07001164 }
1165
1166 @Override
1167 public void writeToParcel(Parcel dest, int flags) {
1168 dest.writeInt(status);
1169 dest.writeInt(soundModelHandle);
1170 dest.writeByte((byte) (captureAvailable ? 1 : 0));
1171 dest.writeInt(captureSession);
1172 dest.writeInt(captureDelayMs);
1173 dest.writeInt(capturePreambleMs);
Eric Laurent75b433f2014-09-12 15:45:47 -07001174 dest.writeByte((byte) (triggerInData ? 1 : 0));
1175 if (captureFormat != null) {
Eric Laurentd3b82232014-07-30 08:57:39 -07001176 dest.writeByte((byte)1);
1177 dest.writeInt(captureFormat.getSampleRate());
1178 dest.writeInt(captureFormat.getEncoding());
1179 dest.writeInt(captureFormat.getChannelMask());
1180 } else {
1181 dest.writeByte((byte)0);
1182 }
Sandeep Siddhartha68173372014-07-28 13:25:30 -07001183 dest.writeBlob(data);
Sandeep Siddhartha68173372014-07-28 13:25:30 -07001184 dest.writeTypedArray(keyphraseExtras, flags);
1185 }
1186
1187 @Override
1188 public int describeContents() {
1189 return 0;
1190 }
1191
1192 @Override
1193 public int hashCode() {
1194 final int prime = 31;
1195 int result = super.hashCode();
1196 result = prime * result + Arrays.hashCode(keyphraseExtras);
Sandeep Siddhartha68173372014-07-28 13:25:30 -07001197 return result;
1198 }
1199
1200 @Override
1201 public boolean equals(Object obj) {
1202 if (this == obj)
1203 return true;
1204 if (!super.equals(obj))
1205 return false;
1206 if (getClass() != obj.getClass())
1207 return false;
1208 KeyphraseRecognitionEvent other = (KeyphraseRecognitionEvent) obj;
1209 if (!Arrays.equals(keyphraseExtras, other.keyphraseExtras))
1210 return false;
Sandeep Siddhartha68173372014-07-28 13:25:30 -07001211 return true;
1212 }
1213
1214 @Override
1215 public String toString() {
1216 return "KeyphraseRecognitionEvent [keyphraseExtras=" + Arrays.toString(keyphraseExtras)
Eric Laurentd3b82232014-07-30 08:57:39 -07001217 + ", status=" + status
Sandeep Siddhartha68173372014-07-28 13:25:30 -07001218 + ", soundModelHandle=" + soundModelHandle + ", captureAvailable="
1219 + captureAvailable + ", captureSession=" + captureSession + ", captureDelayMs="
1220 + captureDelayMs + ", capturePreambleMs=" + capturePreambleMs
Eric Laurentd3b82232014-07-30 08:57:39 -07001221 + ", triggerInData=" + triggerInData
1222 + ((captureFormat == null) ? "" :
1223 (", sampleRate=" + captureFormat.getSampleRate()))
1224 + ((captureFormat == null) ? "" :
1225 (", encoding=" + captureFormat.getEncoding()))
1226 + ((captureFormat == null) ? "" :
1227 (", channelMask=" + captureFormat.getChannelMask()))
Sandeep Siddhartha68173372014-07-28 13:25:30 -07001228 + ", data=" + (data == null ? 0 : data.length) + "]";
1229 }
Eric Laurente48188c2014-04-18 17:44:11 -07001230 }
1231
1232 /**
Arunesh Mishraa772e5f2016-01-25 10:33:11 -08001233 * Sub-class of RecognitionEvent specifically for sound-trigger based sound
1234 * models(non-keyphrase). Currently does not contain any additional fields.
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -08001235 *
1236 * @hide
Arunesh Mishraa772e5f2016-01-25 10:33:11 -08001237 */
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -08001238 public static class GenericRecognitionEvent extends RecognitionEvent implements Parcelable {
Arunesh Mishraa772e5f2016-01-25 10:33:11 -08001239 public GenericRecognitionEvent(int status, int soundModelHandle,
1240 boolean captureAvailable, int captureSession, int captureDelayMs,
1241 int capturePreambleMs, boolean triggerInData, AudioFormat captureFormat,
1242 byte[] data) {
1243 super(status, soundModelHandle, captureAvailable, captureSession,
1244 captureDelayMs, capturePreambleMs, triggerInData, captureFormat,
1245 data);
1246 }
Arunesh Mishraf47f1732016-02-18 16:16:12 -08001247
1248 public static final Parcelable.Creator<GenericRecognitionEvent> CREATOR
1249 = new Parcelable.Creator<GenericRecognitionEvent>() {
1250 public GenericRecognitionEvent createFromParcel(Parcel in) {
1251 return GenericRecognitionEvent.fromParcelForGeneric(in);
1252 }
1253
1254 public GenericRecognitionEvent[] newArray(int size) {
1255 return new GenericRecognitionEvent[size];
1256 }
1257 };
1258
1259 private static GenericRecognitionEvent fromParcelForGeneric(Parcel in) {
1260 RecognitionEvent event = RecognitionEvent.fromParcel(in);
1261 return new GenericRecognitionEvent(event.status, event.soundModelHandle,
1262 event.captureAvailable, event.captureSession, event.captureDelayMs,
1263 event.capturePreambleMs, event.triggerInData, event.captureFormat, event.data);
1264 }
1265
1266 @Override
1267 public boolean equals(Object obj) {
1268 if (this == obj)
1269 return true;
1270 if (obj == null)
1271 return false;
1272 if (getClass() != obj.getClass()) return false;
1273 RecognitionEvent other = (RecognitionEvent) obj;
1274 return super.equals(obj);
1275 }
1276
1277 @Override
1278 public String toString() {
1279 return "GenericRecognitionEvent ::" + super.toString();
1280 }
Arunesh Mishraa772e5f2016-01-25 10:33:11 -08001281 }
1282
1283 /**
Eric Laurentd3b82232014-07-30 08:57:39 -07001284 * Status codes for {@link SoundModelEvent}
1285 */
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -08001286 /**
1287 * Sound Model was updated
1288 *
1289 * @hide
1290 */
Eric Laurentd3b82232014-07-30 08:57:39 -07001291 public static final int SOUNDMODEL_STATUS_UPDATED = 0;
1292
1293 /**
1294 * A SoundModelEvent is provided by the
1295 * {@link StatusListener#onSoundModelUpdate(SoundModelEvent)}
1296 * callback when a sound model has been updated by the implementation
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -08001297 *
1298 * @hide
Eric Laurentd3b82232014-07-30 08:57:39 -07001299 */
1300 public static class SoundModelEvent implements Parcelable {
1301 /** Status e.g {@link #SOUNDMODEL_STATUS_UPDATED} */
1302 public final int status;
1303 /** The updated sound model handle */
1304 public final int soundModelHandle;
1305 /** New sound model data */
1306 public final byte[] data;
1307
1308 SoundModelEvent(int status, int soundModelHandle, byte[] data) {
1309 this.status = status;
1310 this.soundModelHandle = soundModelHandle;
1311 this.data = data;
1312 }
1313
1314 public static final Parcelable.Creator<SoundModelEvent> CREATOR
1315 = new Parcelable.Creator<SoundModelEvent>() {
1316 public SoundModelEvent createFromParcel(Parcel in) {
1317 return SoundModelEvent.fromParcel(in);
1318 }
1319
1320 public SoundModelEvent[] newArray(int size) {
1321 return new SoundModelEvent[size];
1322 }
1323 };
1324
1325 private static SoundModelEvent fromParcel(Parcel in) {
1326 int status = in.readInt();
1327 int soundModelHandle = in.readInt();
1328 byte[] data = in.readBlob();
1329 return new SoundModelEvent(status, soundModelHandle, data);
1330 }
1331
1332 @Override
1333 public int describeContents() {
1334 return 0;
1335 }
1336
1337 @Override
1338 public void writeToParcel(Parcel dest, int flags) {
1339 dest.writeInt(status);
1340 dest.writeInt(soundModelHandle);
1341 dest.writeBlob(data);
1342 }
1343
1344 @Override
1345 public int hashCode() {
1346 final int prime = 31;
1347 int result = 1;
1348 result = prime * result + Arrays.hashCode(data);
1349 result = prime * result + soundModelHandle;
1350 result = prime * result + status;
1351 return result;
1352 }
1353
1354 @Override
1355 public boolean equals(Object obj) {
1356 if (this == obj)
1357 return true;
1358 if (obj == null)
1359 return false;
1360 if (getClass() != obj.getClass())
1361 return false;
1362 SoundModelEvent other = (SoundModelEvent) obj;
1363 if (!Arrays.equals(data, other.data))
1364 return false;
1365 if (soundModelHandle != other.soundModelHandle)
1366 return false;
1367 if (status != other.status)
1368 return false;
1369 return true;
1370 }
1371
1372 @Override
1373 public String toString() {
1374 return "SoundModelEvent [status=" + status + ", soundModelHandle=" + soundModelHandle
1375 + ", data=" + (data == null ? 0 : data.length) + "]";
1376 }
1377 }
1378
1379 /**
1380 * Native service state. {@link StatusListener#onServiceStateChange(int)}
1381 */
1382 // Keep in sync with system/core/include/system/sound_trigger.h
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -08001383 /**
1384 * Sound trigger service is enabled
1385 *
1386 * @hide
1387 */
Eric Laurentd3b82232014-07-30 08:57:39 -07001388 public static final int SERVICE_STATE_ENABLED = 0;
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -08001389 /**
1390 * Sound trigger service is disabled
1391 *
1392 * @hide
1393 */
Eric Laurentd3b82232014-07-30 08:57:39 -07001394 public static final int SERVICE_STATE_DISABLED = 1;
1395
1396 /**
Arunesh Mishraa772e5f2016-01-25 10:33:11 -08001397 * Returns a list of descriptors for all hardware modules loaded.
Eric Laurente48188c2014-04-18 17:44:11 -07001398 * @param modules A ModuleProperties array where the list will be returned.
1399 * @return - {@link #STATUS_OK} in case of success
1400 * - {@link #STATUS_ERROR} in case of unspecified error
1401 * - {@link #STATUS_PERMISSION_DENIED} if the caller does not have system permission
1402 * - {@link #STATUS_NO_INIT} if the native service cannot be reached
1403 * - {@link #STATUS_BAD_VALUE} if modules is null
1404 * - {@link #STATUS_DEAD_OBJECT} if the binder transaction to the native service fails
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -08001405 *
1406 * @hide
Eric Laurente48188c2014-04-18 17:44:11 -07001407 */
1408 public static native int listModules(ArrayList <ModuleProperties> modules);
1409
1410 /**
1411 * Get an interface on a hardware module to control sound models and recognition on
1412 * this module.
1413 * @param moduleId Sound module system identifier {@link ModuleProperties#id}. mandatory.
1414 * @param listener {@link StatusListener} interface. Mandatory.
1415 * @param handler the Handler that will receive the callabcks. Can be null if default handler
1416 * is OK.
1417 * @return a valid sound module in case of success or null in case of error.
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -08001418 *
1419 * @hide
Eric Laurente48188c2014-04-18 17:44:11 -07001420 */
1421 public static SoundTriggerModule attachModule(int moduleId,
1422 StatusListener listener,
1423 Handler handler) {
1424 if (listener == null) {
1425 return null;
1426 }
1427 SoundTriggerModule module = new SoundTriggerModule(moduleId, listener, handler);
1428 return module;
1429 }
1430
1431 /**
1432 * Interface provided by the client application when attaching to a {@link SoundTriggerModule}
1433 * to received recognition and error notifications.
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -08001434 *
1435 * @hide
Eric Laurente48188c2014-04-18 17:44:11 -07001436 */
1437 public static interface StatusListener {
1438 /**
1439 * Called when recognition succeeds of fails
1440 */
1441 public abstract void onRecognition(RecognitionEvent event);
1442
1443 /**
Eric Laurentd3b82232014-07-30 08:57:39 -07001444 * Called when a sound model has been updated
1445 */
1446 public abstract void onSoundModelUpdate(SoundModelEvent event);
1447
1448 /**
1449 * Called when the sound trigger native service state changes.
1450 * @param state Native service state. One of {@link SoundTrigger#SERVICE_STATE_ENABLED},
1451 * {@link SoundTrigger#SERVICE_STATE_DISABLED}
1452 */
1453 public abstract void onServiceStateChange(int state);
1454
1455 /**
Eric Laurente48188c2014-04-18 17:44:11 -07001456 * Called when the sound trigger native service dies
1457 */
1458 public abstract void onServiceDied();
1459 }
1460}