blob: 1932f46975c5c3a8bb5df42a0b02c31ab2deeca5 [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
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -080025import static java.util.Objects.requireNonNull;
26
Nicholas Ambur7092a562019-12-16 11:18:55 -080027import android.annotation.IntDef;
Aurimas Liutikas4d1699d2019-08-28 13:01:05 -070028import android.annotation.NonNull;
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -080029import android.annotation.Nullable;
30import android.annotation.SystemApi;
jiabin1f4b4dd2019-03-18 18:07:03 -070031import android.app.ActivityThread;
Artur Satayev26958002019-12-10 17:47:52 +000032import android.compat.annotation.UnsupportedAppUsage;
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -080033import android.content.Context;
Eric Laurentd3b82232014-07-30 08:57:39 -070034import android.media.AudioFormat;
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -080035import android.media.soundtrigger_middleware.ISoundTriggerMiddlewareService;
36import android.media.soundtrigger_middleware.SoundTriggerModuleDescriptor;
Ytai Ben-Tsvi2e8f78b2020-01-15 11:57:34 -080037import android.media.soundtrigger_middleware.Status;
Eric Laurente48188c2014-04-18 17:44:11 -070038import android.os.Handler;
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -080039import android.os.IBinder;
40import android.os.Looper;
Sandeep Siddhartha05589722014-07-17 16:21:54 -070041import android.os.Parcel;
42import android.os.Parcelable;
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -080043import android.os.RemoteException;
44import android.os.ServiceManager;
Ytai Ben-Tsvi2e8f78b2020-01-15 11:57:34 -080045import android.os.ServiceSpecificException;
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -080046import android.util.Log;
Eric Laurente48188c2014-04-18 17:44:11 -070047
Nicholas Ambur7092a562019-12-16 11:18:55 -080048import java.lang.annotation.Retention;
49import java.lang.annotation.RetentionPolicy;
Eric Laurente48188c2014-04-18 17:44:11 -070050import java.util.ArrayList;
Sandeep Siddhartha05589722014-07-17 16:21:54 -070051import java.util.Arrays;
Eric Laurente48188c2014-04-18 17:44:11 -070052import java.util.UUID;
53
54/**
Ytai Ben-Tsvic59b2802020-01-07 14:08:16 -080055 * The SoundTrigger class provides access to the service managing the sound trigger HAL.
Eric Laurente48188c2014-04-18 17:44:11 -070056 *
57 * @hide
58 */
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -080059@SystemApi
Eric Laurente48188c2014-04-18 17:44:11 -070060public class SoundTrigger {
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -080061 private static final String TAG = "SoundTrigger";
Eric Laurente48188c2014-04-18 17:44:11 -070062
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -080063 private SoundTrigger() {
64 }
65
66 /**
67 * Status code used when the operation succeeded
68 */
Eric Laurente48188c2014-04-18 17:44:11 -070069 public static final int STATUS_OK = 0;
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -080070 /** @hide */
Eric Laurente48188c2014-04-18 17:44:11 -070071 public static final int STATUS_ERROR = Integer.MIN_VALUE;
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -080072 /** @hide */
Lazar Trsic8ea56f62015-07-07 17:31:20 +020073 public static final int STATUS_PERMISSION_DENIED = -EPERM;
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -080074 /** @hide */
Lazar Trsic8ea56f62015-07-07 17:31:20 +020075 public static final int STATUS_NO_INIT = -ENODEV;
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -080076 /** @hide */
Lazar Trsic8ea56f62015-07-07 17:31:20 +020077 public static final int STATUS_BAD_VALUE = -EINVAL;
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -080078 /** @hide */
Lazar Trsic8ea56f62015-07-07 17:31:20 +020079 public static final int STATUS_DEAD_OBJECT = -EPIPE;
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -080080 /** @hide */
Lazar Trsic8ea56f62015-07-07 17:31:20 +020081 public static final int STATUS_INVALID_OPERATION = -ENOSYS;
Eric Laurente48188c2014-04-18 17:44:11 -070082
83 /*****************************************************************************
84 * A ModuleProperties describes a given sound trigger hardware module
85 * managed by the native sound trigger service. Each module has a unique
86 * ID used to target any API call to this paricular module. Module
87 * properties are returned by listModules() method.
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -080088 *
Eric Laurente48188c2014-04-18 17:44:11 -070089 ****************************************************************************/
Nicholas Ambur1aa4b4b2019-08-22 12:13:29 -070090 public static final class ModuleProperties implements Parcelable {
Nicholas Ambur7092a562019-12-16 11:18:55 -080091
92 /**
93 * Bit field values of AudioCapabilities supported by the implemented HAL
94 * driver.
95 * @hide
96 */
97 @Retention(RetentionPolicy.SOURCE)
98 @IntDef(flag = true, prefix = { "AUDIO_CAPABILITY_" }, value = {
99 CAPABILITY_ECHO_CANCELLATION,
100 CAPABILITY_NOISE_SUPPRESSION
101 })
102 public @interface AudioCapabilities {}
103
104 /**
105 * If set the underlying module supports AEC.
106 * Describes bit field {@link ModuleProperties#audioCapabilities}
107 */
108 public static final int CAPABILITY_ECHO_CANCELLATION = 0x1;
109 /**
110 * If set, the underlying module supports noise suppression.
111 * Describes bit field {@link ModuleProperties#audioCapabilities}
112 */
113 public static final int CAPABILITY_NOISE_SUPPRESSION = 0x2;
114
Eric Laurente48188c2014-04-18 17:44:11 -0700115 /** Unique module ID provided by the native service */
116 public final int id;
117
118 /** human readable voice detection engine implementor */
Nicholas Ambur1aa4b4b2019-08-22 12:13:29 -0700119 @NonNull
Eric Laurente48188c2014-04-18 17:44:11 -0700120 public final String implementor;
121
122 /** human readable voice detection engine description */
Nicholas Ambur1aa4b4b2019-08-22 12:13:29 -0700123 @NonNull
Eric Laurente48188c2014-04-18 17:44:11 -0700124 public final String description;
125
126 /** Unique voice engine Id (changes with each version) */
Nicholas Ambur1aa4b4b2019-08-22 12:13:29 -0700127 @NonNull
Eric Laurente48188c2014-04-18 17:44:11 -0700128 public final UUID uuid;
129
130 /** Voice detection engine version */
131 public final int version;
132
Nicholas Ambur38027cd2019-12-16 00:06:19 -0800133 /**
134 * String naming the architecture used for running the supported models.
135 * (eg. a platform running models on a DSP could implement this string to convey the DSP
136 * architecture used)
137 */
138 @NonNull
139 public final String supportedModelArch;
140
Eric Laurente48188c2014-04-18 17:44:11 -0700141 /** Maximum number of active sound models */
142 public final int maxSoundModels;
143
144 /** Maximum number of key phrases */
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700145 public final int maxKeyphrases;
Eric Laurente48188c2014-04-18 17:44:11 -0700146
147 /** Maximum number of users per key phrase */
148 public final int maxUsers;
149
150 /** Supported recognition modes (bit field, RECOGNITION_MODE_VOICE_TRIGGER ...) */
151 public final int recognitionModes;
152
153 /** Supports seamless transition to capture mode after recognition */
154 public final boolean supportsCaptureTransition;
155
156 /** Maximum buffering capacity in ms if supportsCaptureTransition() is true */
157 public final int maxBufferMs;
158
159 /** Supports capture by other use cases while detection is active */
160 public final boolean supportsConcurrentCapture;
161
162 /** Rated power consumption when detection is active with TDB silence/sound/speech ratio */
163 public final int powerConsumptionMw;
164
Eric Laurentd3b82232014-07-30 08:57:39 -0700165 /** Returns the trigger (key phrase) capture in the binary data of the
166 * recognition callback event */
167 public final boolean returnsTriggerInEvent;
168
Nicholas Ambur7092a562019-12-16 11:18:55 -0800169 /**
170 * Bit field encoding of the AudioCapabilities
171 * supported by the firmware.
172 */
173 @AudioCapabilities
174 public final int audioCapabilities;
175
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -0800176 ModuleProperties(int id, @NonNull String implementor, @NonNull String description,
Nicholas Ambur38027cd2019-12-16 00:06:19 -0800177 @NonNull String uuid, int version, @NonNull String supportedModelArch,
178 int maxSoundModels, int maxKeyphrases, int maxUsers, int recognitionModes,
179 boolean supportsCaptureTransition, int maxBufferMs,
180 boolean supportsConcurrentCapture, int powerConsumptionMw,
Nicholas Ambur7092a562019-12-16 11:18:55 -0800181 boolean returnsTriggerInEvent, int audioCapabilities) {
Eric Laurente48188c2014-04-18 17:44:11 -0700182 this.id = id;
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -0800183 this.implementor = requireNonNull(implementor);
184 this.description = requireNonNull(description);
185 this.uuid = UUID.fromString(requireNonNull(uuid));
Eric Laurente48188c2014-04-18 17:44:11 -0700186 this.version = version;
Nicholas Ambur38027cd2019-12-16 00:06:19 -0800187 this.supportedModelArch = requireNonNull(supportedModelArch);
Eric Laurente48188c2014-04-18 17:44:11 -0700188 this.maxSoundModels = maxSoundModels;
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700189 this.maxKeyphrases = maxKeyphrases;
Eric Laurente48188c2014-04-18 17:44:11 -0700190 this.maxUsers = maxUsers;
191 this.recognitionModes = recognitionModes;
192 this.supportsCaptureTransition = supportsCaptureTransition;
193 this.maxBufferMs = maxBufferMs;
194 this.supportsConcurrentCapture = supportsConcurrentCapture;
195 this.powerConsumptionMw = powerConsumptionMw;
Eric Laurentd3b82232014-07-30 08:57:39 -0700196 this.returnsTriggerInEvent = returnsTriggerInEvent;
Nicholas Ambur7092a562019-12-16 11:18:55 -0800197 this.audioCapabilities = audioCapabilities;
Eric Laurente48188c2014-04-18 17:44:11 -0700198 }
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700199
Jeff Sharkey9e8f83d2019-02-28 12:06:45 -0700200 public static final @android.annotation.NonNull Parcelable.Creator<ModuleProperties> CREATOR
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700201 = new Parcelable.Creator<ModuleProperties>() {
202 public ModuleProperties createFromParcel(Parcel in) {
203 return ModuleProperties.fromParcel(in);
204 }
205
206 public ModuleProperties[] newArray(int size) {
207 return new ModuleProperties[size];
208 }
209 };
210
211 private static ModuleProperties fromParcel(Parcel in) {
212 int id = in.readInt();
213 String implementor = in.readString();
214 String description = in.readString();
215 String uuid = in.readString();
216 int version = in.readInt();
Nicholas Ambur38027cd2019-12-16 00:06:19 -0800217 String supportedModelArch = in.readString();
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700218 int maxSoundModels = in.readInt();
219 int maxKeyphrases = in.readInt();
220 int maxUsers = in.readInt();
221 int recognitionModes = in.readInt();
222 boolean supportsCaptureTransition = in.readByte() == 1;
223 int maxBufferMs = in.readInt();
224 boolean supportsConcurrentCapture = in.readByte() == 1;
225 int powerConsumptionMw = in.readInt();
Eric Laurentd3b82232014-07-30 08:57:39 -0700226 boolean returnsTriggerInEvent = in.readByte() == 1;
Nicholas Ambur7092a562019-12-16 11:18:55 -0800227 int audioCapabilities = in.readInt();
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700228 return new ModuleProperties(id, implementor, description, uuid, version,
Nicholas Ambur38027cd2019-12-16 00:06:19 -0800229 supportedModelArch, maxSoundModels, maxKeyphrases, maxUsers, recognitionModes,
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700230 supportsCaptureTransition, maxBufferMs, supportsConcurrentCapture,
Nicholas Ambur7092a562019-12-16 11:18:55 -0800231 powerConsumptionMw, returnsTriggerInEvent, audioCapabilities);
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700232 }
233
234 @Override
235 public void writeToParcel(Parcel dest, int flags) {
236 dest.writeInt(id);
237 dest.writeString(implementor);
238 dest.writeString(description);
239 dest.writeString(uuid.toString());
240 dest.writeInt(version);
Nicholas Ambur38027cd2019-12-16 00:06:19 -0800241 dest.writeString(supportedModelArch);
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700242 dest.writeInt(maxSoundModels);
243 dest.writeInt(maxKeyphrases);
244 dest.writeInt(maxUsers);
245 dest.writeInt(recognitionModes);
246 dest.writeByte((byte) (supportsCaptureTransition ? 1 : 0));
247 dest.writeInt(maxBufferMs);
248 dest.writeByte((byte) (supportsConcurrentCapture ? 1 : 0));
249 dest.writeInt(powerConsumptionMw);
Eric Laurentd3b82232014-07-30 08:57:39 -0700250 dest.writeByte((byte) (returnsTriggerInEvent ? 1 : 0));
Nicholas Ambur7092a562019-12-16 11:18:55 -0800251 dest.writeInt(audioCapabilities);
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700252 }
253
254 @Override
255 public int describeContents() {
256 return 0;
257 }
258
259 @Override
260 public String toString() {
261 return "ModuleProperties [id=" + id + ", implementor=" + implementor + ", description="
Nicholas Ambur38027cd2019-12-16 00:06:19 -0800262 + description + ", uuid=" + uuid + ", version=" + version
263 + " , supportedModelArch=" + supportedModelArch + ", maxSoundModels="
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700264 + maxSoundModels + ", maxKeyphrases=" + maxKeyphrases + ", maxUsers="
265 + maxUsers + ", recognitionModes=" + recognitionModes
266 + ", supportsCaptureTransition=" + supportsCaptureTransition + ", maxBufferMs="
267 + maxBufferMs + ", supportsConcurrentCapture=" + supportsConcurrentCapture
Eric Laurentd3b82232014-07-30 08:57:39 -0700268 + ", powerConsumptionMw=" + powerConsumptionMw
Nicholas Ambur7092a562019-12-16 11:18:55 -0800269 + ", returnsTriggerInEvent=" + returnsTriggerInEvent
270 + ", audioCapabilities=" + audioCapabilities + "]";
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700271 }
Eric Laurente48188c2014-04-18 17:44:11 -0700272 }
273
274 /*****************************************************************************
275 * A SoundModel describes the attributes and contains the binary data used by the hardware
276 * implementation to detect a particular sound pattern.
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700277 * A specialized version {@link KeyphraseSoundModel} is defined for key phrase
Eric Laurente48188c2014-04-18 17:44:11 -0700278 * sound models.
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -0800279 *
280 * @hide
Eric Laurente48188c2014-04-18 17:44:11 -0700281 ****************************************************************************/
282 public static class SoundModel {
283 /** Undefined sound model type */
284 public static final int TYPE_UNKNOWN = -1;
285
286 /** Keyphrase sound model */
287 public static final int TYPE_KEYPHRASE = 0;
288
Arunesh Mishraa772e5f2016-01-25 10:33:11 -0800289 /**
290 * A generic sound model. Use this type only for non-keyphrase sound models such as
291 * ones that match a particular sound pattern.
292 */
293 public static final int TYPE_GENERIC_SOUND = 1;
294
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700295 /** Unique sound model identifier */
Mathew Inwoodbcbe4402018-08-08 15:42:59 +0100296 @UnsupportedAppUsage
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -0800297 @NonNull
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700298 public final UUID uuid;
299
Eric Laurente48188c2014-04-18 17:44:11 -0700300 /** Sound model type (e.g. TYPE_KEYPHRASE); */
301 public final int type;
302
Eric Laurentd3b82232014-07-30 08:57:39 -0700303 /** Unique sound model vendor identifier */
Mathew Inwoodbcbe4402018-08-08 15:42:59 +0100304 @UnsupportedAppUsage
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -0800305 @NonNull
Eric Laurentd3b82232014-07-30 08:57:39 -0700306 public final UUID vendorUuid;
307
Nicholas Amburd3ec82f2020-01-03 17:44:19 -0800308 /** vendor specific version number of the model */
309 public final int version;
310
Eric Laurente48188c2014-04-18 17:44:11 -0700311 /** Opaque data. For use by vendor implementation and enrollment application */
Mathew Inwoodbcbe4402018-08-08 15:42:59 +0100312 @UnsupportedAppUsage
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -0800313 @NonNull
Eric Laurente48188c2014-04-18 17:44:11 -0700314 public final byte[] data;
315
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -0800316 public SoundModel(@NonNull UUID uuid, @Nullable UUID vendorUuid, int type,
Nicholas Amburd3ec82f2020-01-03 17:44:19 -0800317 @Nullable byte[] data, int version) {
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -0800318 this.uuid = requireNonNull(uuid);
319 this.vendorUuid = vendorUuid != null ? vendorUuid : new UUID(0, 0);
Eric Laurente48188c2014-04-18 17:44:11 -0700320 this.type = type;
Nicholas Amburd3ec82f2020-01-03 17:44:19 -0800321 this.version = version;
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -0800322 this.data = data != null ? data : new byte[0];
Eric Laurente48188c2014-04-18 17:44:11 -0700323 }
Sandeep Siddhartha45c00b52014-10-16 16:17:11 -0700324
325 @Override
326 public int hashCode() {
327 final int prime = 31;
328 int result = 1;
Nicholas Amburd3ec82f2020-01-03 17:44:19 -0800329 result = prime * result + version;
Sandeep Siddhartha45c00b52014-10-16 16:17:11 -0700330 result = prime * result + Arrays.hashCode(data);
331 result = prime * result + type;
332 result = prime * result + ((uuid == null) ? 0 : uuid.hashCode());
333 result = prime * result + ((vendorUuid == null) ? 0 : vendorUuid.hashCode());
334 return result;
335 }
336
337 @Override
338 public boolean equals(Object obj) {
339 if (this == obj)
340 return true;
341 if (obj == null)
342 return false;
343 if (!(obj instanceof SoundModel))
344 return false;
345 SoundModel other = (SoundModel) obj;
Sandeep Siddhartha45c00b52014-10-16 16:17:11 -0700346 if (type != other.type)
347 return false;
348 if (uuid == null) {
349 if (other.uuid != null)
350 return false;
351 } else if (!uuid.equals(other.uuid))
352 return false;
353 if (vendorUuid == null) {
354 if (other.vendorUuid != null)
355 return false;
356 } else if (!vendorUuid.equals(other.vendorUuid))
357 return false;
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -0800358 if (!Arrays.equals(data, other.data))
359 return false;
Nicholas Amburd3ec82f2020-01-03 17:44:19 -0800360 if (version != other.version)
361 return false;
Sandeep Siddhartha45c00b52014-10-16 16:17:11 -0700362 return true;
363 }
Eric Laurente48188c2014-04-18 17:44:11 -0700364 }
365
366 /*****************************************************************************
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700367 * A Keyphrase describes a key phrase that can be detected by a
368 * {@link KeyphraseSoundModel}
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -0800369 *
370 * @hide
Eric Laurente48188c2014-04-18 17:44:11 -0700371 ****************************************************************************/
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700372 public static class Keyphrase implements Parcelable {
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700373 /** Unique identifier for this keyphrase */
Mathew Inwoodbcbe4402018-08-08 15:42:59 +0100374 @UnsupportedAppUsage
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700375 public final int id;
376
Eric Laurente48188c2014-04-18 17:44:11 -0700377 /** Recognition modes supported for this key phrase in the model */
Mathew Inwoodbcbe4402018-08-08 15:42:59 +0100378 @UnsupportedAppUsage
Eric Laurente48188c2014-04-18 17:44:11 -0700379 public final int recognitionModes;
380
381 /** Locale of the keyphrase. JAVA Locale string e.g en_US */
Mathew Inwoodbcbe4402018-08-08 15:42:59 +0100382 @UnsupportedAppUsage
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -0800383 @NonNull
Eric Laurente48188c2014-04-18 17:44:11 -0700384 public final String locale;
385
386 /** Key phrase text */
Mathew Inwoodbcbe4402018-08-08 15:42:59 +0100387 @UnsupportedAppUsage
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -0800388 @NonNull
Eric Laurente48188c2014-04-18 17:44:11 -0700389 public final String text;
390
Eric Laurent013f66b2014-07-06 16:35:00 -0700391 /** Users this key phrase has been trained for. countains sound trigger specific user IDs
392 * derived from system user IDs {@link android.os.UserHandle#getIdentifier()}. */
Mathew Inwoodbcbe4402018-08-08 15:42:59 +0100393 @UnsupportedAppUsage
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -0800394 @NonNull
Eric Laurent013f66b2014-07-06 16:35:00 -0700395 public final int[] users;
Eric Laurente48188c2014-04-18 17:44:11 -0700396
Mathew Inwoodbcbe4402018-08-08 15:42:59 +0100397 @UnsupportedAppUsage
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -0800398 public Keyphrase(int id, int recognitionModes, @NonNull String locale, @NonNull String text,
399 @Nullable int[] users) {
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700400 this.id = id;
Eric Laurente48188c2014-04-18 17:44:11 -0700401 this.recognitionModes = recognitionModes;
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -0800402 this.locale = requireNonNull(locale);
403 this.text = requireNonNull(text);
404 this.users = users != null ? users : new int[0];
Eric Laurente48188c2014-04-18 17:44:11 -0700405 }
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700406
Jeff Sharkey9e8f83d2019-02-28 12:06:45 -0700407 public static final @android.annotation.NonNull Parcelable.Creator<Keyphrase> CREATOR
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700408 = new Parcelable.Creator<Keyphrase>() {
409 public Keyphrase createFromParcel(Parcel in) {
410 return Keyphrase.fromParcel(in);
411 }
412
413 public Keyphrase[] newArray(int size) {
414 return new Keyphrase[size];
415 }
416 };
417
418 private static Keyphrase fromParcel(Parcel in) {
419 int id = in.readInt();
420 int recognitionModes = in.readInt();
421 String locale = in.readString();
422 String text = in.readString();
423 int[] users = null;
424 int numUsers = in.readInt();
Sandeep Siddhartha110f5692014-07-20 12:22:56 -0700425 if (numUsers >= 0) {
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700426 users = new int[numUsers];
427 in.readIntArray(users);
428 }
429 return new Keyphrase(id, recognitionModes, locale, text, users);
430 }
431
432 @Override
433 public void writeToParcel(Parcel dest, int flags) {
434 dest.writeInt(id);
435 dest.writeInt(recognitionModes);
436 dest.writeString(locale);
437 dest.writeString(text);
438 if (users != null) {
439 dest.writeInt(users.length);
440 dest.writeIntArray(users);
441 } else {
Sandeep Siddhartha110f5692014-07-20 12:22:56 -0700442 dest.writeInt(-1);
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700443 }
444 }
445
446 @Override
447 public int describeContents() {
448 return 0;
449 }
450
451 @Override
452 public int hashCode() {
453 final int prime = 31;
454 int result = 1;
455 result = prime * result + ((text == null) ? 0 : text.hashCode());
456 result = prime * result + id;
457 result = prime * result + ((locale == null) ? 0 : locale.hashCode());
458 result = prime * result + recognitionModes;
459 result = prime * result + Arrays.hashCode(users);
460 return result;
461 }
462
463 @Override
464 public boolean equals(Object obj) {
465 if (this == obj)
466 return true;
467 if (obj == null)
468 return false;
469 if (getClass() != obj.getClass())
470 return false;
471 Keyphrase other = (Keyphrase) obj;
472 if (text == null) {
473 if (other.text != null)
474 return false;
475 } else if (!text.equals(other.text))
476 return false;
477 if (id != other.id)
478 return false;
479 if (locale == null) {
480 if (other.locale != null)
481 return false;
482 } else if (!locale.equals(other.locale))
483 return false;
484 if (recognitionModes != other.recognitionModes)
485 return false;
486 if (!Arrays.equals(users, other.users))
487 return false;
488 return true;
489 }
490
491 @Override
492 public String toString() {
493 return "Keyphrase [id=" + id + ", recognitionModes=" + recognitionModes + ", locale="
494 + locale + ", text=" + text + ", users=" + Arrays.toString(users) + "]";
495 }
Eric Laurente48188c2014-04-18 17:44:11 -0700496 }
497
498 /*****************************************************************************
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700499 * A KeyphraseSoundModel is a specialized {@link SoundModel} for key phrases.
Eric Laurente48188c2014-04-18 17:44:11 -0700500 * It contains data needed by the hardware to detect a certain number of key phrases
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700501 * and the list of corresponding {@link Keyphrase} descriptors.
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -0800502 *
503 * @hide
Eric Laurente48188c2014-04-18 17:44:11 -0700504 ****************************************************************************/
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700505 public static class KeyphraseSoundModel extends SoundModel implements Parcelable {
Eric Laurente48188c2014-04-18 17:44:11 -0700506 /** Key phrases in this sound model */
Mathew Inwoodbcbe4402018-08-08 15:42:59 +0100507 @UnsupportedAppUsage
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -0800508 @NonNull
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700509 public final Keyphrase[] keyphrases; // keyword phrases in model
Eric Laurente48188c2014-04-18 17:44:11 -0700510
Eric Laurentd3b82232014-07-30 08:57:39 -0700511 public KeyphraseSoundModel(
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -0800512 @NonNull UUID uuid, @NonNull UUID vendorUuid, @Nullable byte[] data,
Nicholas Amburd3ec82f2020-01-03 17:44:19 -0800513 @Nullable Keyphrase[] keyphrases, int version) {
514 super(uuid, vendorUuid, TYPE_KEYPHRASE, data, version);
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -0800515 this.keyphrases = keyphrases != null ? keyphrases : new Keyphrase[0];
Eric Laurente48188c2014-04-18 17:44:11 -0700516 }
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700517
Nicholas Amburd3ec82f2020-01-03 17:44:19 -0800518 @UnsupportedAppUsage
519 public KeyphraseSoundModel(@NonNull UUID uuid, @NonNull UUID vendorUuid,
520 @Nullable byte[] data, @Nullable Keyphrase[] keyphrases) {
521 this(uuid, vendorUuid, data, keyphrases, -1);
522 }
523
Jeff Sharkey9e8f83d2019-02-28 12:06:45 -0700524 public static final @android.annotation.NonNull Parcelable.Creator<KeyphraseSoundModel> CREATOR
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700525 = new Parcelable.Creator<KeyphraseSoundModel>() {
526 public KeyphraseSoundModel createFromParcel(Parcel in) {
527 return KeyphraseSoundModel.fromParcel(in);
528 }
529
530 public KeyphraseSoundModel[] newArray(int size) {
531 return new KeyphraseSoundModel[size];
532 }
533 };
534
535 private static KeyphraseSoundModel fromParcel(Parcel in) {
536 UUID uuid = UUID.fromString(in.readString());
Eric Laurentd3b82232014-07-30 08:57:39 -0700537 UUID vendorUuid = null;
538 int length = in.readInt();
539 if (length >= 0) {
540 vendorUuid = UUID.fromString(in.readString());
541 }
Nicholas Amburd3ec82f2020-01-03 17:44:19 -0800542 int version = in.readInt();
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -0700543 byte[] data = in.readBlob();
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700544 Keyphrase[] keyphrases = in.createTypedArray(Keyphrase.CREATOR);
Nicholas Amburd3ec82f2020-01-03 17:44:19 -0800545 return new KeyphraseSoundModel(uuid, vendorUuid, data, keyphrases, version);
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700546 }
547
548 @Override
549 public int describeContents() {
550 return 0;
551 }
552
553 @Override
554 public void writeToParcel(Parcel dest, int flags) {
555 dest.writeString(uuid.toString());
Eric Laurentd3b82232014-07-30 08:57:39 -0700556 if (vendorUuid == null) {
557 dest.writeInt(-1);
558 } else {
559 dest.writeInt(vendorUuid.toString().length());
560 dest.writeString(vendorUuid.toString());
561 }
Nicholas Ambur43970b52020-01-14 18:54:26 -0800562 dest.writeInt(version);
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -0700563 dest.writeBlob(data);
Sandeep Siddhartha68173372014-07-28 13:25:30 -0700564 dest.writeTypedArray(keyphrases, flags);
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700565 }
Sandeep Siddhartha110f5692014-07-20 12:22:56 -0700566
567 @Override
568 public String toString() {
Eric Laurentd3b82232014-07-30 08:57:39 -0700569 return "KeyphraseSoundModel [keyphrases=" + Arrays.toString(keyphrases)
570 + ", uuid=" + uuid + ", vendorUuid=" + vendorUuid
Nicholas Amburd3ec82f2020-01-03 17:44:19 -0800571 + ", type=" + type
572 + ", data=" + (data == null ? 0 : data.length)
573 + ", version=" + version + "]";
Sandeep Siddhartha110f5692014-07-20 12:22:56 -0700574 }
Sandeep Siddhartha45c00b52014-10-16 16:17:11 -0700575
576 @Override
577 public int hashCode() {
578 final int prime = 31;
579 int result = super.hashCode();
580 result = prime * result + Arrays.hashCode(keyphrases);
581 return result;
582 }
583
584 @Override
585 public boolean equals(Object obj) {
586 if (this == obj)
587 return true;
588 if (!super.equals(obj))
589 return false;
590 if (!(obj instanceof KeyphraseSoundModel))
591 return false;
592 KeyphraseSoundModel other = (KeyphraseSoundModel) obj;
593 if (!Arrays.equals(keyphrases, other.keyphrases))
594 return false;
595 return true;
596 }
Eric Laurente48188c2014-04-18 17:44:11 -0700597 }
598
Arunesh Mishraa772e5f2016-01-25 10:33:11 -0800599
600 /*****************************************************************************
601 * A GenericSoundModel is a specialized {@link SoundModel} for non-voice sound
602 * patterns.
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -0800603 *
604 * @hide
Arunesh Mishraa772e5f2016-01-25 10:33:11 -0800605 ****************************************************************************/
606 public static class GenericSoundModel extends SoundModel implements Parcelable {
607
Jeff Sharkey9e8f83d2019-02-28 12:06:45 -0700608 public static final @android.annotation.NonNull Parcelable.Creator<GenericSoundModel> CREATOR
Arunesh Mishraa772e5f2016-01-25 10:33:11 -0800609 = new Parcelable.Creator<GenericSoundModel>() {
610 public GenericSoundModel createFromParcel(Parcel in) {
611 return GenericSoundModel.fromParcel(in);
612 }
613
614 public GenericSoundModel[] newArray(int size) {
615 return new GenericSoundModel[size];
616 }
617 };
618
Nicholas Amburd3ec82f2020-01-03 17:44:19 -0800619 public GenericSoundModel(@NonNull UUID uuid, @NonNull UUID vendorUuid,
620 @Nullable byte[] data, int version) {
621 super(uuid, vendorUuid, TYPE_GENERIC_SOUND, data, version);
622 }
623
Mathew Inwoodbcbe4402018-08-08 15:42:59 +0100624 @UnsupportedAppUsage
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -0800625 public GenericSoundModel(@NonNull UUID uuid, @NonNull UUID vendorUuid,
626 @Nullable byte[] data) {
Nicholas Amburd3ec82f2020-01-03 17:44:19 -0800627 this(uuid, vendorUuid, data, -1);
Arunesh Mishraa772e5f2016-01-25 10:33:11 -0800628 }
629
630 @Override
631 public int describeContents() {
632 return 0;
633 }
634
635 private static GenericSoundModel fromParcel(Parcel in) {
636 UUID uuid = UUID.fromString(in.readString());
637 UUID vendorUuid = null;
638 int length = in.readInt();
639 if (length >= 0) {
640 vendorUuid = UUID.fromString(in.readString());
641 }
642 byte[] data = in.readBlob();
Nicholas Amburd3ec82f2020-01-03 17:44:19 -0800643 int version = in.readInt();
644 return new GenericSoundModel(uuid, vendorUuid, data, version);
Arunesh Mishraa772e5f2016-01-25 10:33:11 -0800645 }
646
647 @Override
648 public void writeToParcel(Parcel dest, int flags) {
649 dest.writeString(uuid.toString());
650 if (vendorUuid == null) {
651 dest.writeInt(-1);
652 } else {
653 dest.writeInt(vendorUuid.toString().length());
654 dest.writeString(vendorUuid.toString());
655 }
656 dest.writeBlob(data);
Nicholas Amburd3ec82f2020-01-03 17:44:19 -0800657 dest.writeInt(version);
Arunesh Mishraa772e5f2016-01-25 10:33:11 -0800658 }
659
660 @Override
661 public String toString() {
662 return "GenericSoundModel [uuid=" + uuid + ", vendorUuid=" + vendorUuid
Nicholas Amburd3ec82f2020-01-03 17:44:19 -0800663 + ", type=" + type
664 + ", data=" + (data == null ? 0 : data.length)
665 + ", version=" + version + "]";
Arunesh Mishraa772e5f2016-01-25 10:33:11 -0800666 }
667 }
668
Nicholas Amburf94db1c2019-12-08 19:04:06 -0800669 /**
Nicholas Ambura0be6be2019-10-01 10:11:39 -0700670 * A ModelParamRange is a representation of supported parameter range for a
671 * given loaded model.
Nicholas Amburf94db1c2019-12-08 19:04:06 -0800672 */
Nicholas Ambura0be6be2019-10-01 10:11:39 -0700673 public static final class ModelParamRange implements Parcelable {
674
675 /**
Nicholas Amburf94db1c2019-12-08 19:04:06 -0800676 * The inclusive start of supported range.
Nicholas Ambura0be6be2019-10-01 10:11:39 -0700677 */
678 public final int start;
679
680 /**
Nicholas Amburf94db1c2019-12-08 19:04:06 -0800681 * The inclusive end of supported range.
Nicholas Ambura0be6be2019-10-01 10:11:39 -0700682 */
683 public final int end;
684
685 ModelParamRange(int start, int end) {
686 this.start = start;
687 this.end = end;
688 }
689
Nicholas Amburf94db1c2019-12-08 19:04:06 -0800690 /** @hide */
Nicholas Ambura0be6be2019-10-01 10:11:39 -0700691 private ModelParamRange(@NonNull Parcel in) {
692 this.start = in.readInt();
693 this.end = in.readInt();
694 }
695
696 @NonNull
Nicholas Amburf94db1c2019-12-08 19:04:06 -0800697 public static final Creator<ModelParamRange> CREATOR =
698 new Creator<ModelParamRange>() {
699 @Override
700 @NonNull
701 public ModelParamRange createFromParcel(@NonNull Parcel in) {
702 return new ModelParamRange(in);
703 }
Nicholas Ambura0be6be2019-10-01 10:11:39 -0700704
Nicholas Amburf94db1c2019-12-08 19:04:06 -0800705 @Override
706 @NonNull
707 public ModelParamRange[] newArray(int size) {
708 return new ModelParamRange[size];
709 }
710 };
Nicholas Ambura0be6be2019-10-01 10:11:39 -0700711
Nicholas Amburf94db1c2019-12-08 19:04:06 -0800712 /** @hide */
Nicholas Ambura0be6be2019-10-01 10:11:39 -0700713 @Override
714 public int describeContents() {
715 return 0;
716 }
717
Nicholas Amburf94db1c2019-12-08 19:04:06 -0800718 /** @hide */
719 @Override
720 public int hashCode() {
721 final int prime = 31;
722 int result = 1;
723 result = prime * result + (start);
724 result = prime * result + (end);
725 return result;
726 }
727
728 @Override
729 public boolean equals(@Nullable Object obj) {
730 if (this == obj) {
731 return true;
732 }
733 if (obj == null) {
734 return false;
735 }
736 if (getClass() != obj.getClass()) {
737 return false;
738 }
739 ModelParamRange other = (ModelParamRange) obj;
740 if (start != other.start) {
741 return false;
742 }
743 if (end != other.end) {
744 return false;
745 }
746 return true;
747 }
748
Nicholas Ambura0be6be2019-10-01 10:11:39 -0700749 @Override
750 public void writeToParcel(@NonNull Parcel dest, int flags) {
751 dest.writeInt(start);
752 dest.writeInt(end);
753 }
754
755 @Override
756 @NonNull
757 public String toString() {
758 return "ModelParamRange [start=" + start + ", end=" + end + "]";
759 }
760 }
761
Eric Laurente48188c2014-04-18 17:44:11 -0700762 /**
763 * Modes for key phrase recognition
764 */
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -0800765
766 /**
767 * Simple recognition of the key phrase
768 *
769 * @hide
770 */
Eric Laurente48188c2014-04-18 17:44:11 -0700771 public static final int RECOGNITION_MODE_VOICE_TRIGGER = 0x1;
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -0800772 /**
773 * Trigger only if one user is identified
774 *
775 * @hide
776 */
Eric Laurente48188c2014-04-18 17:44:11 -0700777 public static final int RECOGNITION_MODE_USER_IDENTIFICATION = 0x2;
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -0800778 /**
779 * Trigger only if one user is authenticated
780 *
781 * @hide
782 */
Eric Laurente48188c2014-04-18 17:44:11 -0700783 public static final int RECOGNITION_MODE_USER_AUTHENTICATION = 0x4;
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -0800784 /**
785 * Generic (non-speech) recognition.
786 *
787 * @hide
788 */
789 public static final int RECOGNITION_MODE_GENERIC = 0x8;
Eric Laurente48188c2014-04-18 17:44:11 -0700790
791 /**
792 * Status codes for {@link RecognitionEvent}
793 */
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -0800794 /**
795 * Recognition success
796 *
797 * @hide
798 */
Eric Laurente48188c2014-04-18 17:44:11 -0700799 public static final int RECOGNITION_STATUS_SUCCESS = 0;
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -0800800 /**
801 * Recognition aborted (e.g. capture preempted by anotehr use case
802 *
803 * @hide
804 */
Eric Laurente48188c2014-04-18 17:44:11 -0700805 public static final int RECOGNITION_STATUS_ABORT = 1;
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -0800806 /**
807 * Recognition failure
808 *
809 * @hide
810 */
Eric Laurente48188c2014-04-18 17:44:11 -0700811 public static final int RECOGNITION_STATUS_FAILURE = 2;
mike dooleyb2ab04a2018-11-07 15:48:54 +0100812 /**
813 * Recognition event was triggered by a getModelState request, not by the
814 * DSP.
815 *
816 * @hide
817 */
818 public static final int RECOGNITION_STATUS_GET_STATE_RESPONSE = 3;
Eric Laurente48188c2014-04-18 17:44:11 -0700819
820 /**
821 * A RecognitionEvent is provided by the
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -0800822 * {@code StatusListener#onRecognition(RecognitionEvent)}
Eric Laurente48188c2014-04-18 17:44:11 -0700823 * callback upon recognition success or failure.
824 */
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -0800825 public static class RecognitionEvent {
826 /**
827 * Recognition status e.g RECOGNITION_STATUS_SUCCESS
828 *
829 * @hide
830 */
Mathew Inwoodbcbe4402018-08-08 15:42:59 +0100831 @UnsupportedAppUsage
Eric Laurente48188c2014-04-18 17:44:11 -0700832 public final int status;
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -0800833 /**
834 *
835 * Sound Model corresponding to this event callback
836 *
837 * @hide
838 */
Mathew Inwoodbcbe4402018-08-08 15:42:59 +0100839 @UnsupportedAppUsage
Eric Laurente48188c2014-04-18 17:44:11 -0700840 public final int soundModelHandle;
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -0800841 /**
842 * True if it is possible to capture audio from this utterance buffered by the hardware
843 *
844 * @hide
845 */
Mathew Inwoodbcbe4402018-08-08 15:42:59 +0100846 @UnsupportedAppUsage
Eric Laurente48188c2014-04-18 17:44:11 -0700847 public final boolean captureAvailable;
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -0800848 /**
849 * Audio session ID to be used when capturing the utterance with an AudioRecord
850 * if captureAvailable() is true.
851 *
852 * @hide
853 */
Mathew Inwoodbcbe4402018-08-08 15:42:59 +0100854 @UnsupportedAppUsage
Eric Laurente48188c2014-04-18 17:44:11 -0700855 public final int captureSession;
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -0800856 /**
857 * Delay in ms between end of model detection and start of audio available for capture.
858 * A negative value is possible (e.g. if keyphrase is also available for capture)
859 *
860 * @hide
861 */
Eric Laurente48188c2014-04-18 17:44:11 -0700862 public final int captureDelayMs;
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -0800863 /**
864 * Duration in ms of audio captured before the start of the trigger. 0 if none.
865 *
866 * @hide
867 */
Eric Laurent013f66b2014-07-06 16:35:00 -0700868 public final int capturePreambleMs;
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -0800869 /**
870 * True if the trigger (key phrase capture is present in binary data
871 *
872 * @hide
873 */
Eric Laurentd3b82232014-07-30 08:57:39 -0700874 public final boolean triggerInData;
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -0800875 /**
876 * Audio format of either the trigger in event data or to use for capture of the
877 * rest of the utterance
878 *
879 * @hide
880 */
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -0800881 @NonNull
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -0800882 public final AudioFormat captureFormat;
883 /**
884 * Opaque data for use by system applications who know about voice engine internals,
885 * typically during enrollment.
886 *
887 * @hide
888 */
Mathew Inwoodbcbe4402018-08-08 15:42:59 +0100889 @UnsupportedAppUsage
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -0800890 @NonNull
Eric Laurente48188c2014-04-18 17:44:11 -0700891 public final byte[] data;
892
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -0800893 /** @hide */
Mathew Inwoodbcbe4402018-08-08 15:42:59 +0100894 @UnsupportedAppUsage
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -0700895 public RecognitionEvent(int status, int soundModelHandle, boolean captureAvailable,
Eric Laurentd3b82232014-07-30 08:57:39 -0700896 int captureSession, int captureDelayMs, int capturePreambleMs,
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -0800897 boolean triggerInData, @NonNull AudioFormat captureFormat, @Nullable byte[] data) {
Eric Laurente48188c2014-04-18 17:44:11 -0700898 this.status = status;
899 this.soundModelHandle = soundModelHandle;
900 this.captureAvailable = captureAvailable;
901 this.captureSession = captureSession;
902 this.captureDelayMs = captureDelayMs;
Eric Laurent013f66b2014-07-06 16:35:00 -0700903 this.capturePreambleMs = capturePreambleMs;
Eric Laurentd3b82232014-07-30 08:57:39 -0700904 this.triggerInData = triggerInData;
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -0800905 this.captureFormat = requireNonNull(captureFormat);
906 this.data = data != null ? data : new byte[0];
Eric Laurente48188c2014-04-18 17:44:11 -0700907 }
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -0700908
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -0800909 /**
910 * Check if is possible to capture audio from this utterance buffered by the hardware.
911 *
912 * @return {@code true} iff a capturing is possible
913 */
914 public boolean isCaptureAvailable() {
915 return captureAvailable;
916 }
917
918 /**
919 * Get the audio format of either the trigger in event data or to use for capture of the
920 * rest of the utterance
921 *
922 * @return the audio format
923 */
924 @Nullable public AudioFormat getCaptureFormat() {
925 return captureFormat;
926 }
927
928 /**
929 * Get Audio session ID to be used when capturing the utterance with an {@link AudioRecord}
930 * if {@link #isCaptureAvailable()} is true.
931 *
932 * @return The id of the capture session
933 */
934 public int getCaptureSession() {
935 return captureSession;
936 }
937
938 /**
939 * Get the opaque data for use by system applications who know about voice engine
940 * internals, typically during enrollment.
941 *
942 * @return The data of the event
943 */
944 public byte[] getData() {
945 return data;
946 }
947
948 /** @hide */
Jeff Sharkey9e8f83d2019-02-28 12:06:45 -0700949 public static final @android.annotation.NonNull Parcelable.Creator<RecognitionEvent> CREATOR
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -0700950 = new Parcelable.Creator<RecognitionEvent>() {
951 public RecognitionEvent createFromParcel(Parcel in) {
952 return RecognitionEvent.fromParcel(in);
953 }
954
955 public RecognitionEvent[] newArray(int size) {
956 return new RecognitionEvent[size];
957 }
958 };
959
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -0800960 /** @hide */
Arunesh Mishraf47f1732016-02-18 16:16:12 -0800961 protected static RecognitionEvent fromParcel(Parcel in) {
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -0700962 int status = in.readInt();
963 int soundModelHandle = in.readInt();
964 boolean captureAvailable = in.readByte() == 1;
965 int captureSession = in.readInt();
966 int captureDelayMs = in.readInt();
967 int capturePreambleMs = in.readInt();
Eric Laurentd3b82232014-07-30 08:57:39 -0700968 boolean triggerInData = in.readByte() == 1;
969 AudioFormat captureFormat = null;
Eric Laurent39fcca02014-09-05 16:44:19 -0700970 if (in.readByte() == 1) {
Eric Laurentd3b82232014-07-30 08:57:39 -0700971 int sampleRate = in.readInt();
972 int encoding = in.readInt();
973 int channelMask = in.readInt();
974 captureFormat = (new AudioFormat.Builder())
975 .setChannelMask(channelMask)
976 .setEncoding(encoding)
977 .setSampleRate(sampleRate)
978 .build();
979 }
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -0700980 byte[] data = in.readBlob();
981 return new RecognitionEvent(status, soundModelHandle, captureAvailable, captureSession,
Eric Laurentd3b82232014-07-30 08:57:39 -0700982 captureDelayMs, capturePreambleMs, triggerInData, captureFormat, data);
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -0700983 }
984
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -0800985 /** @hide */
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -0700986 public int describeContents() {
987 return 0;
988 }
989
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -0800990 /** @hide */
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -0700991 public void writeToParcel(Parcel dest, int flags) {
992 dest.writeInt(status);
993 dest.writeInt(soundModelHandle);
994 dest.writeByte((byte) (captureAvailable ? 1 : 0));
995 dest.writeInt(captureSession);
996 dest.writeInt(captureDelayMs);
997 dest.writeInt(capturePreambleMs);
Eric Laurent39fcca02014-09-05 16:44:19 -0700998 dest.writeByte((byte) (triggerInData ? 1 : 0));
999 if (captureFormat != null) {
Eric Laurentd3b82232014-07-30 08:57:39 -07001000 dest.writeByte((byte)1);
1001 dest.writeInt(captureFormat.getSampleRate());
1002 dest.writeInt(captureFormat.getEncoding());
1003 dest.writeInt(captureFormat.getChannelMask());
1004 } else {
1005 dest.writeByte((byte)0);
1006 }
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -07001007 dest.writeBlob(data);
1008 }
1009
1010 @Override
1011 public int hashCode() {
1012 final int prime = 31;
1013 int result = 1;
1014 result = prime * result + (captureAvailable ? 1231 : 1237);
1015 result = prime * result + captureDelayMs;
1016 result = prime * result + capturePreambleMs;
1017 result = prime * result + captureSession;
Eric Laurentd3b82232014-07-30 08:57:39 -07001018 result = prime * result + (triggerInData ? 1231 : 1237);
1019 if (captureFormat != null) {
1020 result = prime * result + captureFormat.getSampleRate();
1021 result = prime * result + captureFormat.getEncoding();
1022 result = prime * result + captureFormat.getChannelMask();
1023 }
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -07001024 result = prime * result + Arrays.hashCode(data);
1025 result = prime * result + soundModelHandle;
1026 result = prime * result + status;
1027 return result;
1028 }
1029
1030 @Override
Aurimas Liutikas4d1699d2019-08-28 13:01:05 -07001031 public boolean equals(@Nullable Object obj) {
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -07001032 if (this == obj)
1033 return true;
1034 if (obj == null)
1035 return false;
1036 if (getClass() != obj.getClass())
1037 return false;
1038 RecognitionEvent other = (RecognitionEvent) obj;
1039 if (captureAvailable != other.captureAvailable)
1040 return false;
1041 if (captureDelayMs != other.captureDelayMs)
1042 return false;
1043 if (capturePreambleMs != other.capturePreambleMs)
1044 return false;
1045 if (captureSession != other.captureSession)
1046 return false;
1047 if (!Arrays.equals(data, other.data))
1048 return false;
1049 if (soundModelHandle != other.soundModelHandle)
1050 return false;
1051 if (status != other.status)
1052 return false;
Eric Laurentd3b82232014-07-30 08:57:39 -07001053 if (triggerInData != other.triggerInData)
1054 return false;
Ryan Bavettaea04e8f2016-03-02 18:34:50 -08001055 if (captureFormat == null) {
1056 if (other.captureFormat != null)
1057 return false;
1058 } else {
1059 if (other.captureFormat == null)
1060 return false;
1061 if (captureFormat.getSampleRate() != other.captureFormat.getSampleRate())
1062 return false;
1063 if (captureFormat.getEncoding() != other.captureFormat.getEncoding())
1064 return false;
1065 if (captureFormat.getChannelMask() != other.captureFormat.getChannelMask())
1066 return false;
1067 }
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -07001068 return true;
1069 }
Sandeep Siddhartha68173372014-07-28 13:25:30 -07001070
Aurimas Liutikas4d1699d2019-08-28 13:01:05 -07001071 @NonNull
Sandeep Siddhartha68173372014-07-28 13:25:30 -07001072 @Override
1073 public String toString() {
1074 return "RecognitionEvent [status=" + status + ", soundModelHandle=" + soundModelHandle
1075 + ", captureAvailable=" + captureAvailable + ", captureSession="
1076 + captureSession + ", captureDelayMs=" + captureDelayMs
1077 + ", capturePreambleMs=" + capturePreambleMs
Eric Laurentd3b82232014-07-30 08:57:39 -07001078 + ", triggerInData=" + triggerInData
1079 + ((captureFormat == null) ? "" :
1080 (", sampleRate=" + captureFormat.getSampleRate()))
1081 + ((captureFormat == null) ? "" :
1082 (", encoding=" + captureFormat.getEncoding()))
1083 + ((captureFormat == null) ? "" :
1084 (", channelMask=" + captureFormat.getChannelMask()))
Sandeep Siddhartha68173372014-07-28 13:25:30 -07001085 + ", data=" + (data == null ? 0 : data.length) + "]";
1086 }
Eric Laurente48188c2014-04-18 17:44:11 -07001087 }
1088
1089 /**
Eric Laurent013f66b2014-07-06 16:35:00 -07001090 * A RecognitionConfig is provided to
1091 * {@link SoundTriggerModule#startRecognition(int, RecognitionConfig)} to configure the
1092 * recognition request.
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -08001093 *
1094 * @hide
Eric Laurent013f66b2014-07-06 16:35:00 -07001095 */
Sandeep Siddhartha05589722014-07-17 16:21:54 -07001096 public static class RecognitionConfig implements Parcelable {
Eric Laurent013f66b2014-07-06 16:35:00 -07001097 /** True if the DSP should capture the trigger sound and make it available for further
1098 * capture. */
Mathew Inwoodbcbe4402018-08-08 15:42:59 +01001099 @UnsupportedAppUsage
Eric Laurent013f66b2014-07-06 16:35:00 -07001100 public final boolean captureRequested;
Sandeep Siddhartha2c0273e2014-08-01 11:32:03 -07001101 /**
1102 * True if the service should restart listening after the DSP triggers.
1103 * Note: This config flag is currently used at the service layer rather than by the DSP.
1104 */
1105 public final boolean allowMultipleTriggers;
Eric Laurent013f66b2014-07-06 16:35:00 -07001106 /** List of all keyphrases in the sound model for which recognition should be performed with
1107 * options for each keyphrase. */
Mathew Inwoodbcbe4402018-08-08 15:42:59 +01001108 @UnsupportedAppUsage
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -08001109 @NonNull
Eric Laurent013f66b2014-07-06 16:35:00 -07001110 public final KeyphraseRecognitionExtra keyphrases[];
1111 /** Opaque data for use by system applications who know about voice engine internals,
1112 * typically during enrollment. */
Mathew Inwoodbcbe4402018-08-08 15:42:59 +01001113 @UnsupportedAppUsage
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -08001114 @NonNull
Eric Laurent013f66b2014-07-06 16:35:00 -07001115 public final byte[] data;
1116
Nicholas Ambur7092a562019-12-16 11:18:55 -08001117 /**
1118 * Bit field encoding of the AudioCapabilities
1119 * supported by the firmware.
1120 */
1121 @ModuleProperties.AudioCapabilities
1122 public final int audioCapabilities;
1123
Sandeep Siddhartha2c0273e2014-08-01 11:32:03 -07001124 public RecognitionConfig(boolean captureRequested, boolean allowMultipleTriggers,
Nicholas Ambur7092a562019-12-16 11:18:55 -08001125 @Nullable KeyphraseRecognitionExtra[] keyphrases, @Nullable byte[] data,
1126 int audioCapabilities) {
Eric Laurent013f66b2014-07-06 16:35:00 -07001127 this.captureRequested = captureRequested;
Sandeep Siddhartha2c0273e2014-08-01 11:32:03 -07001128 this.allowMultipleTriggers = allowMultipleTriggers;
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -08001129 this.keyphrases = keyphrases != null ? keyphrases : new KeyphraseRecognitionExtra[0];
1130 this.data = data != null ? data : new byte[0];
Nicholas Ambur7092a562019-12-16 11:18:55 -08001131 this.audioCapabilities = audioCapabilities;
1132 }
1133
1134 @UnsupportedAppUsage
1135 public RecognitionConfig(boolean captureRequested, boolean allowMultipleTriggers,
1136 @Nullable KeyphraseRecognitionExtra[] keyphrases, @Nullable byte[] data) {
1137 this(captureRequested, allowMultipleTriggers, keyphrases, data, 0);
Eric Laurent013f66b2014-07-06 16:35:00 -07001138 }
Sandeep Siddhartha05589722014-07-17 16:21:54 -07001139
Jeff Sharkey9e8f83d2019-02-28 12:06:45 -07001140 public static final @android.annotation.NonNull Parcelable.Creator<RecognitionConfig> CREATOR
Sandeep Siddhartha05589722014-07-17 16:21:54 -07001141 = new Parcelable.Creator<RecognitionConfig>() {
1142 public RecognitionConfig createFromParcel(Parcel in) {
1143 return RecognitionConfig.fromParcel(in);
1144 }
1145
1146 public RecognitionConfig[] newArray(int size) {
1147 return new RecognitionConfig[size];
1148 }
1149 };
1150
1151 private static RecognitionConfig fromParcel(Parcel in) {
1152 boolean captureRequested = in.readByte() == 1;
Sandeep Siddhartha2c0273e2014-08-01 11:32:03 -07001153 boolean allowMultipleTriggers = in.readByte() == 1;
Sandeep Siddhartha05589722014-07-17 16:21:54 -07001154 KeyphraseRecognitionExtra[] keyphrases =
1155 in.createTypedArray(KeyphraseRecognitionExtra.CREATOR);
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -07001156 byte[] data = in.readBlob();
Nicholas Ambur7092a562019-12-16 11:18:55 -08001157 int audioCapabilities = in.readInt();
1158 return new RecognitionConfig(captureRequested, allowMultipleTriggers, keyphrases, data,
1159 audioCapabilities);
Sandeep Siddhartha05589722014-07-17 16:21:54 -07001160 }
1161
1162 @Override
1163 public void writeToParcel(Parcel dest, int flags) {
1164 dest.writeByte((byte) (captureRequested ? 1 : 0));
Sandeep Siddhartha2c0273e2014-08-01 11:32:03 -07001165 dest.writeByte((byte) (allowMultipleTriggers ? 1 : 0));
Sandeep Siddhartha68173372014-07-28 13:25:30 -07001166 dest.writeTypedArray(keyphrases, flags);
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -07001167 dest.writeBlob(data);
Nicholas Ambur7092a562019-12-16 11:18:55 -08001168 dest.writeInt(audioCapabilities);
Sandeep Siddhartha05589722014-07-17 16:21:54 -07001169 }
1170
1171 @Override
1172 public int describeContents() {
1173 return 0;
1174 }
Sandeep Siddhartha110f5692014-07-20 12:22:56 -07001175
1176 @Override
1177 public String toString() {
Sandeep Siddhartha2c0273e2014-08-01 11:32:03 -07001178 return "RecognitionConfig [captureRequested=" + captureRequested
1179 + ", allowMultipleTriggers=" + allowMultipleTriggers + ", keyphrases="
Nicholas Ambur7092a562019-12-16 11:18:55 -08001180 + Arrays.toString(keyphrases) + ", data=" + Arrays.toString(data)
1181 + ", audioCapabilities=" + Integer.toHexString(audioCapabilities) + "]";
Sandeep Siddhartha110f5692014-07-20 12:22:56 -07001182 }
Eric Laurent013f66b2014-07-06 16:35:00 -07001183 }
1184
1185 /**
1186 * Confidence level for users defined in a keyphrase.
1187 * - The confidence level is expressed in percent (0% -100%).
1188 * When used in a {@link KeyphraseRecognitionEvent} it indicates the detected confidence level
1189 * When used in a {@link RecognitionConfig} it indicates the minimum confidence level that
1190 * should trigger a recognition.
1191 * - The user ID is derived from the system ID {@link android.os.UserHandle#getIdentifier()}.
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -08001192 *
1193 * @hide
Eric Laurent013f66b2014-07-06 16:35:00 -07001194 */
Sandeep Siddhartha05589722014-07-17 16:21:54 -07001195 public static class ConfidenceLevel implements Parcelable {
Mathew Inwoodbcbe4402018-08-08 15:42:59 +01001196 @UnsupportedAppUsage
Eric Laurent013f66b2014-07-06 16:35:00 -07001197 public final int userId;
Mathew Inwoodbcbe4402018-08-08 15:42:59 +01001198 @UnsupportedAppUsage
Eric Laurent013f66b2014-07-06 16:35:00 -07001199 public final int confidenceLevel;
1200
Mathew Inwoodbcbe4402018-08-08 15:42:59 +01001201 @UnsupportedAppUsage
Eric Laurent013f66b2014-07-06 16:35:00 -07001202 public ConfidenceLevel(int userId, int confidenceLevel) {
1203 this.userId = userId;
1204 this.confidenceLevel = confidenceLevel;
1205 }
Sandeep Siddhartha05589722014-07-17 16:21:54 -07001206
Jeff Sharkey9e8f83d2019-02-28 12:06:45 -07001207 public static final @android.annotation.NonNull Parcelable.Creator<ConfidenceLevel> CREATOR
Sandeep Siddhartha05589722014-07-17 16:21:54 -07001208 = new Parcelable.Creator<ConfidenceLevel>() {
1209 public ConfidenceLevel createFromParcel(Parcel in) {
1210 return ConfidenceLevel.fromParcel(in);
1211 }
1212
1213 public ConfidenceLevel[] newArray(int size) {
1214 return new ConfidenceLevel[size];
1215 }
1216 };
1217
1218 private static ConfidenceLevel fromParcel(Parcel in) {
1219 int userId = in.readInt();
1220 int confidenceLevel = in.readInt();
1221 return new ConfidenceLevel(userId, confidenceLevel);
1222 }
1223
1224 @Override
1225 public void writeToParcel(Parcel dest, int flags) {
1226 dest.writeInt(userId);
1227 dest.writeInt(confidenceLevel);
1228 }
1229
1230 @Override
1231 public int describeContents() {
1232 return 0;
1233 }
Sandeep Siddhartha68173372014-07-28 13:25:30 -07001234
1235 @Override
1236 public int hashCode() {
1237 final int prime = 31;
1238 int result = 1;
1239 result = prime * result + confidenceLevel;
1240 result = prime * result + userId;
1241 return result;
1242 }
1243
1244 @Override
1245 public boolean equals(Object obj) {
1246 if (this == obj)
1247 return true;
1248 if (obj == null)
1249 return false;
1250 if (getClass() != obj.getClass())
1251 return false;
1252 ConfidenceLevel other = (ConfidenceLevel) obj;
1253 if (confidenceLevel != other.confidenceLevel)
1254 return false;
1255 if (userId != other.userId)
1256 return false;
1257 return true;
1258 }
1259
1260 @Override
1261 public String toString() {
1262 return "ConfidenceLevel [userId=" + userId
1263 + ", confidenceLevel=" + confidenceLevel + "]";
1264 }
Eric Laurent013f66b2014-07-06 16:35:00 -07001265 }
1266
1267 /**
Sandeep Siddharthad4233c62014-06-12 18:31:19 -07001268 * Additional data conveyed by a {@link KeyphraseRecognitionEvent}
Eric Laurente48188c2014-04-18 17:44:11 -07001269 * for a key phrase detection.
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -08001270 *
1271 * @hide
Eric Laurente48188c2014-04-18 17:44:11 -07001272 */
Sandeep Siddhartha05589722014-07-17 16:21:54 -07001273 public static class KeyphraseRecognitionExtra implements Parcelable {
1274 /** The keyphrase ID */
Mathew Inwoodbcbe4402018-08-08 15:42:59 +01001275 @UnsupportedAppUsage
Eric Laurent013f66b2014-07-06 16:35:00 -07001276 public final int id;
Eric Laurente48188c2014-04-18 17:44:11 -07001277
1278 /** Recognition modes matched for this event */
Mathew Inwoodbcbe4402018-08-08 15:42:59 +01001279 @UnsupportedAppUsage
Eric Laurente48188c2014-04-18 17:44:11 -07001280 public final int recognitionModes;
1281
Eric Laurentd3b82232014-07-30 08:57:39 -07001282 /** Confidence level for mode RECOGNITION_MODE_VOICE_TRIGGER when user identification
1283 * is not performed */
Mathew Inwoodbcbe4402018-08-08 15:42:59 +01001284 @UnsupportedAppUsage
Eric Laurentd3b82232014-07-30 08:57:39 -07001285 public final int coarseConfidenceLevel;
1286
Eric Laurent013f66b2014-07-06 16:35:00 -07001287 /** Confidence levels for all users recognized (KeyphraseRecognitionEvent) or to
1288 * be recognized (RecognitionConfig) */
Mathew Inwoodbcbe4402018-08-08 15:42:59 +01001289 @UnsupportedAppUsage
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -08001290 @NonNull
Eric Laurent013f66b2014-07-06 16:35:00 -07001291 public final ConfidenceLevel[] confidenceLevels;
1292
Mathew Inwoodbcbe4402018-08-08 15:42:59 +01001293 @UnsupportedAppUsage
Eric Laurentd3b82232014-07-30 08:57:39 -07001294 public KeyphraseRecognitionExtra(int id, int recognitionModes, int coarseConfidenceLevel,
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -08001295 @Nullable ConfidenceLevel[] confidenceLevels) {
Eric Laurent013f66b2014-07-06 16:35:00 -07001296 this.id = id;
Eric Laurente48188c2014-04-18 17:44:11 -07001297 this.recognitionModes = recognitionModes;
Eric Laurentd3b82232014-07-30 08:57:39 -07001298 this.coarseConfidenceLevel = coarseConfidenceLevel;
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -08001299 this.confidenceLevels =
1300 confidenceLevels != null ? confidenceLevels : new ConfidenceLevel[0];
Eric Laurente48188c2014-04-18 17:44:11 -07001301 }
Sandeep Siddhartha05589722014-07-17 16:21:54 -07001302
Jeff Sharkey9e8f83d2019-02-28 12:06:45 -07001303 public static final @android.annotation.NonNull Parcelable.Creator<KeyphraseRecognitionExtra> CREATOR
Sandeep Siddhartha05589722014-07-17 16:21:54 -07001304 = new Parcelable.Creator<KeyphraseRecognitionExtra>() {
1305 public KeyphraseRecognitionExtra createFromParcel(Parcel in) {
1306 return KeyphraseRecognitionExtra.fromParcel(in);
1307 }
1308
1309 public KeyphraseRecognitionExtra[] newArray(int size) {
1310 return new KeyphraseRecognitionExtra[size];
1311 }
1312 };
1313
1314 private static KeyphraseRecognitionExtra fromParcel(Parcel in) {
1315 int id = in.readInt();
1316 int recognitionModes = in.readInt();
Eric Laurentd3b82232014-07-30 08:57:39 -07001317 int coarseConfidenceLevel = in.readInt();
Sandeep Siddhartha05589722014-07-17 16:21:54 -07001318 ConfidenceLevel[] confidenceLevels = in.createTypedArray(ConfidenceLevel.CREATOR);
Eric Laurentd3b82232014-07-30 08:57:39 -07001319 return new KeyphraseRecognitionExtra(id, recognitionModes, coarseConfidenceLevel,
1320 confidenceLevels);
Sandeep Siddhartha05589722014-07-17 16:21:54 -07001321 }
1322
1323 @Override
1324 public void writeToParcel(Parcel dest, int flags) {
1325 dest.writeInt(id);
1326 dest.writeInt(recognitionModes);
Eric Laurentd3b82232014-07-30 08:57:39 -07001327 dest.writeInt(coarseConfidenceLevel);
Sandeep Siddhartha68173372014-07-28 13:25:30 -07001328 dest.writeTypedArray(confidenceLevels, flags);
Sandeep Siddhartha05589722014-07-17 16:21:54 -07001329 }
1330
1331 @Override
1332 public int describeContents() {
1333 return 0;
1334 }
Sandeep Siddhartha68173372014-07-28 13:25:30 -07001335
1336 @Override
1337 public int hashCode() {
1338 final int prime = 31;
1339 int result = 1;
1340 result = prime * result + Arrays.hashCode(confidenceLevels);
1341 result = prime * result + id;
1342 result = prime * result + recognitionModes;
Eric Laurentd3b82232014-07-30 08:57:39 -07001343 result = prime * result + coarseConfidenceLevel;
Sandeep Siddhartha68173372014-07-28 13:25:30 -07001344 return result;
1345 }
1346
1347 @Override
1348 public boolean equals(Object obj) {
1349 if (this == obj)
1350 return true;
1351 if (obj == null)
1352 return false;
1353 if (getClass() != obj.getClass())
1354 return false;
1355 KeyphraseRecognitionExtra other = (KeyphraseRecognitionExtra) obj;
1356 if (!Arrays.equals(confidenceLevels, other.confidenceLevels))
1357 return false;
1358 if (id != other.id)
1359 return false;
1360 if (recognitionModes != other.recognitionModes)
1361 return false;
Eric Laurentd3b82232014-07-30 08:57:39 -07001362 if (coarseConfidenceLevel != other.coarseConfidenceLevel)
1363 return false;
Sandeep Siddhartha68173372014-07-28 13:25:30 -07001364 return true;
1365 }
1366
1367 @Override
1368 public String toString() {
1369 return "KeyphraseRecognitionExtra [id=" + id + ", recognitionModes=" + recognitionModes
Eric Laurentd3b82232014-07-30 08:57:39 -07001370 + ", coarseConfidenceLevel=" + coarseConfidenceLevel
Sandeep Siddhartha68173372014-07-28 13:25:30 -07001371 + ", confidenceLevels=" + Arrays.toString(confidenceLevels) + "]";
1372 }
Eric Laurente48188c2014-04-18 17:44:11 -07001373 }
1374
1375 /**
1376 * Specialized {@link RecognitionEvent} for a key phrase detection.
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -08001377 *
1378 * @hide
Eric Laurente48188c2014-04-18 17:44:11 -07001379 */
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -08001380 public static class KeyphraseRecognitionEvent extends RecognitionEvent implements Parcelable {
Eric Laurente48188c2014-04-18 17:44:11 -07001381 /** Indicates if the key phrase is present in the buffered audio available for capture */
Mathew Inwoodbcbe4402018-08-08 15:42:59 +01001382 @UnsupportedAppUsage
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -08001383 @NonNull
Sandeep Siddharthad4233c62014-06-12 18:31:19 -07001384 public final KeyphraseRecognitionExtra[] keyphraseExtras;
Eric Laurente48188c2014-04-18 17:44:11 -07001385
Mathew Inwoodbcbe4402018-08-08 15:42:59 +01001386 @UnsupportedAppUsage
Sandeep Siddhartha68173372014-07-28 13:25:30 -07001387 public KeyphraseRecognitionEvent(int status, int soundModelHandle, boolean captureAvailable,
Eric Laurentd3b82232014-07-30 08:57:39 -07001388 int captureSession, int captureDelayMs, int capturePreambleMs,
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -08001389 boolean triggerInData, @NonNull AudioFormat captureFormat, @Nullable byte[] data,
1390 @Nullable KeyphraseRecognitionExtra[] keyphraseExtras) {
Eric Laurent013f66b2014-07-06 16:35:00 -07001391 super(status, soundModelHandle, captureAvailable, captureSession, captureDelayMs,
Eric Laurentd3b82232014-07-30 08:57:39 -07001392 capturePreambleMs, triggerInData, captureFormat, data);
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -08001393 this.keyphraseExtras =
1394 keyphraseExtras != null ? keyphraseExtras : new KeyphraseRecognitionExtra[0];
Eric Laurente48188c2014-04-18 17:44:11 -07001395 }
Sandeep Siddhartha68173372014-07-28 13:25:30 -07001396
Jeff Sharkey9e8f83d2019-02-28 12:06:45 -07001397 public static final @android.annotation.NonNull Parcelable.Creator<KeyphraseRecognitionEvent> CREATOR
Sandeep Siddhartha68173372014-07-28 13:25:30 -07001398 = new Parcelable.Creator<KeyphraseRecognitionEvent>() {
1399 public KeyphraseRecognitionEvent createFromParcel(Parcel in) {
Arunesh Mishraf47f1732016-02-18 16:16:12 -08001400 return KeyphraseRecognitionEvent.fromParcelForKeyphrase(in);
Sandeep Siddhartha68173372014-07-28 13:25:30 -07001401 }
1402
1403 public KeyphraseRecognitionEvent[] newArray(int size) {
1404 return new KeyphraseRecognitionEvent[size];
1405 }
1406 };
1407
Arunesh Mishraf47f1732016-02-18 16:16:12 -08001408 private static KeyphraseRecognitionEvent fromParcelForKeyphrase(Parcel in) {
Sandeep Siddhartha68173372014-07-28 13:25:30 -07001409 int status = in.readInt();
1410 int soundModelHandle = in.readInt();
1411 boolean captureAvailable = in.readByte() == 1;
1412 int captureSession = in.readInt();
1413 int captureDelayMs = in.readInt();
1414 int capturePreambleMs = in.readInt();
Eric Laurentd3b82232014-07-30 08:57:39 -07001415 boolean triggerInData = in.readByte() == 1;
1416 AudioFormat captureFormat = null;
Eric Laurent75b433f2014-09-12 15:45:47 -07001417 if (in.readByte() == 1) {
Eric Laurentd3b82232014-07-30 08:57:39 -07001418 int sampleRate = in.readInt();
1419 int encoding = in.readInt();
1420 int channelMask = in.readInt();
1421 captureFormat = (new AudioFormat.Builder())
Ryan Bavettaea04e8f2016-03-02 18:34:50 -08001422 .setChannelMask(channelMask)
1423 .setEncoding(encoding)
1424 .setSampleRate(sampleRate)
1425 .build();
Eric Laurentd3b82232014-07-30 08:57:39 -07001426 }
Sandeep Siddhartha68173372014-07-28 13:25:30 -07001427 byte[] data = in.readBlob();
Sandeep Siddhartha68173372014-07-28 13:25:30 -07001428 KeyphraseRecognitionExtra[] keyphraseExtras =
1429 in.createTypedArray(KeyphraseRecognitionExtra.CREATOR);
1430 return new KeyphraseRecognitionEvent(status, soundModelHandle, captureAvailable,
Eric Laurentd3b82232014-07-30 08:57:39 -07001431 captureSession, captureDelayMs, capturePreambleMs, triggerInData,
1432 captureFormat, data, keyphraseExtras);
Sandeep Siddhartha68173372014-07-28 13:25:30 -07001433 }
1434
1435 @Override
1436 public void writeToParcel(Parcel dest, int flags) {
1437 dest.writeInt(status);
1438 dest.writeInt(soundModelHandle);
1439 dest.writeByte((byte) (captureAvailable ? 1 : 0));
1440 dest.writeInt(captureSession);
1441 dest.writeInt(captureDelayMs);
1442 dest.writeInt(capturePreambleMs);
Eric Laurent75b433f2014-09-12 15:45:47 -07001443 dest.writeByte((byte) (triggerInData ? 1 : 0));
1444 if (captureFormat != null) {
Eric Laurentd3b82232014-07-30 08:57:39 -07001445 dest.writeByte((byte)1);
1446 dest.writeInt(captureFormat.getSampleRate());
1447 dest.writeInt(captureFormat.getEncoding());
1448 dest.writeInt(captureFormat.getChannelMask());
1449 } else {
1450 dest.writeByte((byte)0);
1451 }
Sandeep Siddhartha68173372014-07-28 13:25:30 -07001452 dest.writeBlob(data);
Sandeep Siddhartha68173372014-07-28 13:25:30 -07001453 dest.writeTypedArray(keyphraseExtras, flags);
1454 }
1455
1456 @Override
1457 public int describeContents() {
1458 return 0;
1459 }
1460
1461 @Override
1462 public int hashCode() {
1463 final int prime = 31;
1464 int result = super.hashCode();
1465 result = prime * result + Arrays.hashCode(keyphraseExtras);
Sandeep Siddhartha68173372014-07-28 13:25:30 -07001466 return result;
1467 }
1468
1469 @Override
1470 public boolean equals(Object obj) {
1471 if (this == obj)
1472 return true;
1473 if (!super.equals(obj))
1474 return false;
1475 if (getClass() != obj.getClass())
1476 return false;
1477 KeyphraseRecognitionEvent other = (KeyphraseRecognitionEvent) obj;
1478 if (!Arrays.equals(keyphraseExtras, other.keyphraseExtras))
1479 return false;
Sandeep Siddhartha68173372014-07-28 13:25:30 -07001480 return true;
1481 }
1482
1483 @Override
1484 public String toString() {
1485 return "KeyphraseRecognitionEvent [keyphraseExtras=" + Arrays.toString(keyphraseExtras)
Eric Laurentd3b82232014-07-30 08:57:39 -07001486 + ", status=" + status
Sandeep Siddhartha68173372014-07-28 13:25:30 -07001487 + ", soundModelHandle=" + soundModelHandle + ", captureAvailable="
1488 + captureAvailable + ", captureSession=" + captureSession + ", captureDelayMs="
1489 + captureDelayMs + ", capturePreambleMs=" + capturePreambleMs
Eric Laurentd3b82232014-07-30 08:57:39 -07001490 + ", triggerInData=" + triggerInData
1491 + ((captureFormat == null) ? "" :
1492 (", sampleRate=" + captureFormat.getSampleRate()))
1493 + ((captureFormat == null) ? "" :
1494 (", encoding=" + captureFormat.getEncoding()))
1495 + ((captureFormat == null) ? "" :
1496 (", channelMask=" + captureFormat.getChannelMask()))
Sandeep Siddhartha68173372014-07-28 13:25:30 -07001497 + ", data=" + (data == null ? 0 : data.length) + "]";
1498 }
Eric Laurente48188c2014-04-18 17:44:11 -07001499 }
1500
1501 /**
Arunesh Mishraa772e5f2016-01-25 10:33:11 -08001502 * Sub-class of RecognitionEvent specifically for sound-trigger based sound
1503 * models(non-keyphrase). Currently does not contain any additional fields.
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -08001504 *
1505 * @hide
Arunesh Mishraa772e5f2016-01-25 10:33:11 -08001506 */
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -08001507 public static class GenericRecognitionEvent extends RecognitionEvent implements Parcelable {
Mathew Inwoodbcbe4402018-08-08 15:42:59 +01001508 @UnsupportedAppUsage
Arunesh Mishraa772e5f2016-01-25 10:33:11 -08001509 public GenericRecognitionEvent(int status, int soundModelHandle,
1510 boolean captureAvailable, int captureSession, int captureDelayMs,
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -08001511 int capturePreambleMs, boolean triggerInData, @NonNull AudioFormat captureFormat,
1512 @Nullable byte[] data) {
Arunesh Mishraa772e5f2016-01-25 10:33:11 -08001513 super(status, soundModelHandle, captureAvailable, captureSession,
1514 captureDelayMs, capturePreambleMs, triggerInData, captureFormat,
1515 data);
1516 }
Arunesh Mishraf47f1732016-02-18 16:16:12 -08001517
Jeff Sharkey9e8f83d2019-02-28 12:06:45 -07001518 public static final @android.annotation.NonNull Parcelable.Creator<GenericRecognitionEvent> CREATOR
Arunesh Mishraf47f1732016-02-18 16:16:12 -08001519 = new Parcelable.Creator<GenericRecognitionEvent>() {
1520 public GenericRecognitionEvent createFromParcel(Parcel in) {
1521 return GenericRecognitionEvent.fromParcelForGeneric(in);
1522 }
1523
1524 public GenericRecognitionEvent[] newArray(int size) {
1525 return new GenericRecognitionEvent[size];
1526 }
1527 };
1528
1529 private static GenericRecognitionEvent fromParcelForGeneric(Parcel in) {
1530 RecognitionEvent event = RecognitionEvent.fromParcel(in);
1531 return new GenericRecognitionEvent(event.status, event.soundModelHandle,
1532 event.captureAvailable, event.captureSession, event.captureDelayMs,
1533 event.capturePreambleMs, event.triggerInData, event.captureFormat, event.data);
1534 }
1535
1536 @Override
1537 public boolean equals(Object obj) {
1538 if (this == obj)
1539 return true;
1540 if (obj == null)
1541 return false;
1542 if (getClass() != obj.getClass()) return false;
1543 RecognitionEvent other = (RecognitionEvent) obj;
1544 return super.equals(obj);
1545 }
1546
1547 @Override
1548 public String toString() {
1549 return "GenericRecognitionEvent ::" + super.toString();
1550 }
Arunesh Mishraa772e5f2016-01-25 10:33:11 -08001551 }
1552
1553 /**
Eric Laurentd3b82232014-07-30 08:57:39 -07001554 * Status codes for {@link SoundModelEvent}
1555 */
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -08001556 /**
1557 * Sound Model was updated
1558 *
1559 * @hide
1560 */
Eric Laurentd3b82232014-07-30 08:57:39 -07001561 public static final int SOUNDMODEL_STATUS_UPDATED = 0;
1562
1563 /**
1564 * A SoundModelEvent is provided by the
1565 * {@link StatusListener#onSoundModelUpdate(SoundModelEvent)}
1566 * callback when a sound model has been updated by the implementation
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -08001567 *
1568 * @hide
Eric Laurentd3b82232014-07-30 08:57:39 -07001569 */
1570 public static class SoundModelEvent implements Parcelable {
1571 /** Status e.g {@link #SOUNDMODEL_STATUS_UPDATED} */
1572 public final int status;
1573 /** The updated sound model handle */
1574 public final int soundModelHandle;
1575 /** New sound model data */
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -08001576 @NonNull
Eric Laurentd3b82232014-07-30 08:57:39 -07001577 public final byte[] data;
1578
Mathew Inwoodbcbe4402018-08-08 15:42:59 +01001579 @UnsupportedAppUsage
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -08001580 SoundModelEvent(int status, int soundModelHandle, @Nullable byte[] data) {
Eric Laurentd3b82232014-07-30 08:57:39 -07001581 this.status = status;
1582 this.soundModelHandle = soundModelHandle;
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -08001583 this.data = data != null ? data : new byte[0];
Eric Laurentd3b82232014-07-30 08:57:39 -07001584 }
1585
Jeff Sharkey9e8f83d2019-02-28 12:06:45 -07001586 public static final @android.annotation.NonNull Parcelable.Creator<SoundModelEvent> CREATOR
Eric Laurentd3b82232014-07-30 08:57:39 -07001587 = new Parcelable.Creator<SoundModelEvent>() {
1588 public SoundModelEvent createFromParcel(Parcel in) {
1589 return SoundModelEvent.fromParcel(in);
1590 }
1591
1592 public SoundModelEvent[] newArray(int size) {
1593 return new SoundModelEvent[size];
1594 }
1595 };
1596
1597 private static SoundModelEvent fromParcel(Parcel in) {
1598 int status = in.readInt();
1599 int soundModelHandle = in.readInt();
1600 byte[] data = in.readBlob();
1601 return new SoundModelEvent(status, soundModelHandle, data);
1602 }
1603
1604 @Override
1605 public int describeContents() {
1606 return 0;
1607 }
1608
1609 @Override
1610 public void writeToParcel(Parcel dest, int flags) {
1611 dest.writeInt(status);
1612 dest.writeInt(soundModelHandle);
1613 dest.writeBlob(data);
1614 }
1615
1616 @Override
1617 public int hashCode() {
1618 final int prime = 31;
1619 int result = 1;
1620 result = prime * result + Arrays.hashCode(data);
1621 result = prime * result + soundModelHandle;
1622 result = prime * result + status;
1623 return result;
1624 }
1625
1626 @Override
1627 public boolean equals(Object obj) {
1628 if (this == obj)
1629 return true;
1630 if (obj == null)
1631 return false;
1632 if (getClass() != obj.getClass())
1633 return false;
1634 SoundModelEvent other = (SoundModelEvent) obj;
1635 if (!Arrays.equals(data, other.data))
1636 return false;
1637 if (soundModelHandle != other.soundModelHandle)
1638 return false;
1639 if (status != other.status)
1640 return false;
1641 return true;
1642 }
1643
1644 @Override
1645 public String toString() {
1646 return "SoundModelEvent [status=" + status + ", soundModelHandle=" + soundModelHandle
1647 + ", data=" + (data == null ? 0 : data.length) + "]";
1648 }
1649 }
1650
1651 /**
1652 * Native service state. {@link StatusListener#onServiceStateChange(int)}
1653 */
1654 // Keep in sync with system/core/include/system/sound_trigger.h
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -08001655 /**
1656 * Sound trigger service is enabled
1657 *
1658 * @hide
1659 */
Eric Laurentd3b82232014-07-30 08:57:39 -07001660 public static final int SERVICE_STATE_ENABLED = 0;
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -08001661 /**
1662 * Sound trigger service is disabled
1663 *
1664 * @hide
1665 */
Eric Laurentd3b82232014-07-30 08:57:39 -07001666 public static final int SERVICE_STATE_DISABLED = 1;
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -08001667 private static Object mServiceLock = new Object();
1668 private static ISoundTriggerMiddlewareService mService;
1669 /**
jiabin1f4b4dd2019-03-18 18:07:03 -07001670 * @return returns current package name.
1671 */
1672 static String getCurrentOpPackageName() {
1673 String packageName = ActivityThread.currentOpPackageName();
1674 if (packageName == null) {
1675 return "";
1676 }
1677 return packageName;
1678 }
1679
1680 /**
Ytai Ben-Tsvi2e8f78b2020-01-15 11:57:34 -08001681 * Translate an exception thrown from interaction with the underlying service to an error code.
1682 * Throws a runtime exception for unexpected conditions.
1683 * @param e The caught exception.
1684 * @return The error code.
1685 *
1686 * @hide
1687 */
1688 static int handleException(Exception e) {
1689 Log.w(TAG, "Exception caught", e);
1690 if (e instanceof RemoteException) {
1691 return STATUS_DEAD_OBJECT;
1692 }
1693 if (e instanceof ServiceSpecificException) {
1694 switch (((ServiceSpecificException) e).errorCode) {
1695 case Status.OPERATION_NOT_SUPPORTED:
1696 return STATUS_INVALID_OPERATION;
1697 case Status.TEMPORARY_PERMISSION_DENIED:
1698 return STATUS_PERMISSION_DENIED;
1699 case Status.DEAD_OBJECT:
1700 return STATUS_DEAD_OBJECT;
1701 }
1702 return STATUS_ERROR;
1703 }
1704 if (e instanceof SecurityException) {
1705 return STATUS_PERMISSION_DENIED;
1706 }
1707 if (e instanceof IllegalStateException) {
1708 return STATUS_INVALID_OPERATION;
1709 }
1710 if (e instanceof IllegalArgumentException || e instanceof NullPointerException) {
1711 return STATUS_BAD_VALUE;
1712 }
1713 // This is not one of the conditions represented by our error code, escalate to a
1714 // RuntimeException.
1715 Log.e(TAG, "Escalating unexpected exception: ", e);
1716 throw new RuntimeException(e);
1717 }
1718
1719 /**
Arunesh Mishraa772e5f2016-01-25 10:33:11 -08001720 * Returns a list of descriptors for all hardware modules loaded.
Eric Laurente48188c2014-04-18 17:44:11 -07001721 * @param modules A ModuleProperties array where the list will be returned.
1722 * @return - {@link #STATUS_OK} in case of success
1723 * - {@link #STATUS_ERROR} in case of unspecified error
1724 * - {@link #STATUS_PERMISSION_DENIED} if the caller does not have system permission
1725 * - {@link #STATUS_NO_INIT} if the native service cannot be reached
1726 * - {@link #STATUS_BAD_VALUE} if modules is null
1727 * - {@link #STATUS_DEAD_OBJECT} if the binder transaction to the native service fails
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -08001728 *
1729 * @hide
Eric Laurente48188c2014-04-18 17:44:11 -07001730 */
Mathew Inwoodbcbe4402018-08-08 15:42:59 +01001731 @UnsupportedAppUsage
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -08001732 public static int listModules(@NonNull ArrayList<ModuleProperties> modules) {
1733 try {
1734 SoundTriggerModuleDescriptor[] descs = getService().listModules();
1735 modules.clear();
1736 modules.ensureCapacity(descs.length);
1737 for (SoundTriggerModuleDescriptor desc : descs) {
1738 modules.add(ConversionUtil.aidl2apiModuleDescriptor(desc));
1739 }
1740 return STATUS_OK;
Ytai Ben-Tsvi2e8f78b2020-01-15 11:57:34 -08001741 } catch (Exception e) {
1742 return handleException(e);
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -08001743 }
jiabin1f4b4dd2019-03-18 18:07:03 -07001744 }
1745
1746 /**
Eric Laurente48188c2014-04-18 17:44:11 -07001747 * Get an interface on a hardware module to control sound models and recognition on
1748 * this module.
1749 * @param moduleId Sound module system identifier {@link ModuleProperties#id}. mandatory.
1750 * @param listener {@link StatusListener} interface. Mandatory.
1751 * @param handler the Handler that will receive the callabcks. Can be null if default handler
1752 * is OK.
1753 * @return a valid sound module in case of success or null in case of error.
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -08001754 *
1755 * @hide
Eric Laurente48188c2014-04-18 17:44:11 -07001756 */
Mathew Inwoodbcbe4402018-08-08 15:42:59 +01001757 @UnsupportedAppUsage
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -08001758 public static @NonNull SoundTriggerModule attachModule(int moduleId,
1759 @NonNull StatusListener listener,
1760 @Nullable Handler handler) {
1761 Looper looper = handler != null ? handler.getLooper() : Looper.getMainLooper();
1762 try {
1763 return new SoundTriggerModule(getService(), moduleId, listener, looper);
1764 } catch (RemoteException e) {
1765 Log.e(TAG, "", e);
Eric Laurente48188c2014-04-18 17:44:11 -07001766 return null;
1767 }
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -08001768 }
1769
1770 private static ISoundTriggerMiddlewareService getService() {
1771 synchronized (mServiceLock) {
1772 while (true) {
1773 IBinder binder = null;
1774 try {
1775 binder =
1776 ServiceManager.getServiceOrThrow(
1777 Context.SOUND_TRIGGER_MIDDLEWARE_SERVICE);
1778 binder.linkToDeath(() -> {
1779 synchronized (mServiceLock) {
1780 mService = null;
1781 }
1782 }, 0);
1783 mService = ISoundTriggerMiddlewareService.Stub.asInterface(binder);
1784 break;
1785 } catch (Exception e) {
1786 Log.e(TAG, "Failed to bind to soundtrigger service", e);
1787 }
1788 }
1789 return mService;
1790 }
1791
Eric Laurente48188c2014-04-18 17:44:11 -07001792 }
1793
1794 /**
1795 * Interface provided by the client application when attaching to a {@link SoundTriggerModule}
1796 * to received recognition and error notifications.
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -08001797 *
1798 * @hide
Eric Laurente48188c2014-04-18 17:44:11 -07001799 */
1800 public static interface StatusListener {
1801 /**
1802 * Called when recognition succeeds of fails
1803 */
1804 public abstract void onRecognition(RecognitionEvent event);
1805
1806 /**
Eric Laurentd3b82232014-07-30 08:57:39 -07001807 * Called when a sound model has been updated
1808 */
1809 public abstract void onSoundModelUpdate(SoundModelEvent event);
1810
1811 /**
1812 * Called when the sound trigger native service state changes.
1813 * @param state Native service state. One of {@link SoundTrigger#SERVICE_STATE_ENABLED},
1814 * {@link SoundTrigger#SERVICE_STATE_DISABLED}
1815 */
1816 public abstract void onServiceStateChange(int state);
1817
1818 /**
Eric Laurente48188c2014-04-18 17:44:11 -07001819 * Called when the sound trigger native service dies
1820 */
1821 public abstract void onServiceDied();
1822 }
1823}