blob: d505ae59dfaf0cde32d531451fbed9d43c18821a [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;
Nicholas Amburef84fc42020-01-14 20:28:37 -080052import java.util.Locale;
Eric Laurente48188c2014-04-18 17:44:11 -070053import java.util.UUID;
54
55/**
Ytai Ben-Tsvic59b2802020-01-07 14:08:16 -080056 * The SoundTrigger class provides access to the service managing the sound trigger HAL.
Eric Laurente48188c2014-04-18 17:44:11 -070057 *
58 * @hide
59 */
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -080060@SystemApi
Eric Laurente48188c2014-04-18 17:44:11 -070061public class SoundTrigger {
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -080062 private static final String TAG = "SoundTrigger";
Eric Laurente48188c2014-04-18 17:44:11 -070063
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -080064 private SoundTrigger() {
65 }
66
67 /**
68 * Status code used when the operation succeeded
69 */
Eric Laurente48188c2014-04-18 17:44:11 -070070 public static final int STATUS_OK = 0;
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -080071 /** @hide */
Eric Laurente48188c2014-04-18 17:44:11 -070072 public static final int STATUS_ERROR = Integer.MIN_VALUE;
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -080073 /** @hide */
Lazar Trsic8ea56f62015-07-07 17:31:20 +020074 public static final int STATUS_PERMISSION_DENIED = -EPERM;
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -080075 /** @hide */
Lazar Trsic8ea56f62015-07-07 17:31:20 +020076 public static final int STATUS_NO_INIT = -ENODEV;
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -080077 /** @hide */
Lazar Trsic8ea56f62015-07-07 17:31:20 +020078 public static final int STATUS_BAD_VALUE = -EINVAL;
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -080079 /** @hide */
Lazar Trsic8ea56f62015-07-07 17:31:20 +020080 public static final int STATUS_DEAD_OBJECT = -EPIPE;
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -080081 /** @hide */
Lazar Trsic8ea56f62015-07-07 17:31:20 +020082 public static final int STATUS_INVALID_OPERATION = -ENOSYS;
Eric Laurente48188c2014-04-18 17:44:11 -070083
84 /*****************************************************************************
85 * A ModuleProperties describes a given sound trigger hardware module
86 * managed by the native sound trigger service. Each module has a unique
87 * ID used to target any API call to this paricular module. Module
88 * properties are returned by listModules() method.
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -080089 *
Eric Laurente48188c2014-04-18 17:44:11 -070090 ****************************************************************************/
Nicholas Ambur1aa4b4b2019-08-22 12:13:29 -070091 public static final class ModuleProperties implements Parcelable {
Nicholas Ambur7092a562019-12-16 11:18:55 -080092
93 /**
94 * Bit field values of AudioCapabilities supported by the implemented HAL
95 * driver.
96 * @hide
97 */
98 @Retention(RetentionPolicy.SOURCE)
99 @IntDef(flag = true, prefix = { "AUDIO_CAPABILITY_" }, value = {
100 CAPABILITY_ECHO_CANCELLATION,
101 CAPABILITY_NOISE_SUPPRESSION
102 })
103 public @interface AudioCapabilities {}
104
105 /**
106 * If set the underlying module supports AEC.
107 * Describes bit field {@link ModuleProperties#audioCapabilities}
108 */
109 public static final int CAPABILITY_ECHO_CANCELLATION = 0x1;
110 /**
111 * If set, the underlying module supports noise suppression.
112 * Describes bit field {@link ModuleProperties#audioCapabilities}
113 */
114 public static final int CAPABILITY_NOISE_SUPPRESSION = 0x2;
115
Eric Laurente48188c2014-04-18 17:44:11 -0700116 /** Unique module ID provided by the native service */
117 public final int id;
118
119 /** human readable voice detection engine implementor */
Nicholas Ambur1aa4b4b2019-08-22 12:13:29 -0700120 @NonNull
Eric Laurente48188c2014-04-18 17:44:11 -0700121 public final String implementor;
122
123 /** human readable voice detection engine description */
Nicholas Ambur1aa4b4b2019-08-22 12:13:29 -0700124 @NonNull
Eric Laurente48188c2014-04-18 17:44:11 -0700125 public final String description;
126
127 /** Unique voice engine Id (changes with each version) */
Nicholas Ambur1aa4b4b2019-08-22 12:13:29 -0700128 @NonNull
Eric Laurente48188c2014-04-18 17:44:11 -0700129 public final UUID uuid;
130
131 /** Voice detection engine version */
132 public final int version;
133
Nicholas Ambur38027cd2019-12-16 00:06:19 -0800134 /**
135 * String naming the architecture used for running the supported models.
136 * (eg. a platform running models on a DSP could implement this string to convey the DSP
137 * architecture used)
138 */
139 @NonNull
140 public final String supportedModelArch;
141
Eric Laurente48188c2014-04-18 17:44:11 -0700142 /** Maximum number of active sound models */
143 public final int maxSoundModels;
144
145 /** Maximum number of key phrases */
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700146 public final int maxKeyphrases;
Eric Laurente48188c2014-04-18 17:44:11 -0700147
148 /** Maximum number of users per key phrase */
149 public final int maxUsers;
150
151 /** Supported recognition modes (bit field, RECOGNITION_MODE_VOICE_TRIGGER ...) */
Nicholas Amburef84fc42020-01-14 20:28:37 -0800152 @RecognitionModes
Eric Laurente48188c2014-04-18 17:44:11 -0700153 public final int recognitionModes;
154
155 /** Supports seamless transition to capture mode after recognition */
156 public final boolean supportsCaptureTransition;
157
158 /** Maximum buffering capacity in ms if supportsCaptureTransition() is true */
159 public final int maxBufferMs;
160
161 /** Supports capture by other use cases while detection is active */
162 public final boolean supportsConcurrentCapture;
163
164 /** Rated power consumption when detection is active with TDB silence/sound/speech ratio */
165 public final int powerConsumptionMw;
166
Eric Laurentd3b82232014-07-30 08:57:39 -0700167 /** Returns the trigger (key phrase) capture in the binary data of the
168 * recognition callback event */
169 public final boolean returnsTriggerInEvent;
170
Nicholas Ambur7092a562019-12-16 11:18:55 -0800171 /**
172 * Bit field encoding of the AudioCapabilities
173 * supported by the firmware.
174 */
175 @AudioCapabilities
176 public final int audioCapabilities;
177
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -0800178 ModuleProperties(int id, @NonNull String implementor, @NonNull String description,
Nicholas Ambur38027cd2019-12-16 00:06:19 -0800179 @NonNull String uuid, int version, @NonNull String supportedModelArch,
Nicholas Amburef84fc42020-01-14 20:28:37 -0800180 int maxSoundModels, int maxKeyphrases, int maxUsers,
181 @RecognitionModes int recognitionModes, boolean supportsCaptureTransition,
182 int maxBufferMs, boolean supportsConcurrentCapture, int powerConsumptionMw,
Nicholas Ambur7092a562019-12-16 11:18:55 -0800183 boolean returnsTriggerInEvent, int audioCapabilities) {
Eric Laurente48188c2014-04-18 17:44:11 -0700184 this.id = id;
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -0800185 this.implementor = requireNonNull(implementor);
186 this.description = requireNonNull(description);
187 this.uuid = UUID.fromString(requireNonNull(uuid));
Eric Laurente48188c2014-04-18 17:44:11 -0700188 this.version = version;
Nicholas Ambur38027cd2019-12-16 00:06:19 -0800189 this.supportedModelArch = requireNonNull(supportedModelArch);
Eric Laurente48188c2014-04-18 17:44:11 -0700190 this.maxSoundModels = maxSoundModels;
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700191 this.maxKeyphrases = maxKeyphrases;
Eric Laurente48188c2014-04-18 17:44:11 -0700192 this.maxUsers = maxUsers;
193 this.recognitionModes = recognitionModes;
194 this.supportsCaptureTransition = supportsCaptureTransition;
195 this.maxBufferMs = maxBufferMs;
196 this.supportsConcurrentCapture = supportsConcurrentCapture;
197 this.powerConsumptionMw = powerConsumptionMw;
Eric Laurentd3b82232014-07-30 08:57:39 -0700198 this.returnsTriggerInEvent = returnsTriggerInEvent;
Nicholas Ambur7092a562019-12-16 11:18:55 -0800199 this.audioCapabilities = audioCapabilities;
Eric Laurente48188c2014-04-18 17:44:11 -0700200 }
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700201
Jeff Sharkey9e8f83d2019-02-28 12:06:45 -0700202 public static final @android.annotation.NonNull Parcelable.Creator<ModuleProperties> CREATOR
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700203 = new Parcelable.Creator<ModuleProperties>() {
204 public ModuleProperties createFromParcel(Parcel in) {
205 return ModuleProperties.fromParcel(in);
206 }
207
208 public ModuleProperties[] newArray(int size) {
209 return new ModuleProperties[size];
210 }
211 };
212
213 private static ModuleProperties fromParcel(Parcel in) {
214 int id = in.readInt();
215 String implementor = in.readString();
216 String description = in.readString();
217 String uuid = in.readString();
218 int version = in.readInt();
Nicholas Ambur38027cd2019-12-16 00:06:19 -0800219 String supportedModelArch = in.readString();
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700220 int maxSoundModels = in.readInt();
221 int maxKeyphrases = in.readInt();
222 int maxUsers = in.readInt();
223 int recognitionModes = in.readInt();
224 boolean supportsCaptureTransition = in.readByte() == 1;
225 int maxBufferMs = in.readInt();
226 boolean supportsConcurrentCapture = in.readByte() == 1;
227 int powerConsumptionMw = in.readInt();
Eric Laurentd3b82232014-07-30 08:57:39 -0700228 boolean returnsTriggerInEvent = in.readByte() == 1;
Nicholas Ambur7092a562019-12-16 11:18:55 -0800229 int audioCapabilities = in.readInt();
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700230 return new ModuleProperties(id, implementor, description, uuid, version,
Nicholas Ambur38027cd2019-12-16 00:06:19 -0800231 supportedModelArch, maxSoundModels, maxKeyphrases, maxUsers, recognitionModes,
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700232 supportsCaptureTransition, maxBufferMs, supportsConcurrentCapture,
Nicholas Ambur7092a562019-12-16 11:18:55 -0800233 powerConsumptionMw, returnsTriggerInEvent, audioCapabilities);
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700234 }
235
236 @Override
237 public void writeToParcel(Parcel dest, int flags) {
238 dest.writeInt(id);
239 dest.writeString(implementor);
240 dest.writeString(description);
241 dest.writeString(uuid.toString());
242 dest.writeInt(version);
Nicholas Ambur38027cd2019-12-16 00:06:19 -0800243 dest.writeString(supportedModelArch);
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700244 dest.writeInt(maxSoundModels);
245 dest.writeInt(maxKeyphrases);
246 dest.writeInt(maxUsers);
247 dest.writeInt(recognitionModes);
248 dest.writeByte((byte) (supportsCaptureTransition ? 1 : 0));
249 dest.writeInt(maxBufferMs);
250 dest.writeByte((byte) (supportsConcurrentCapture ? 1 : 0));
251 dest.writeInt(powerConsumptionMw);
Eric Laurentd3b82232014-07-30 08:57:39 -0700252 dest.writeByte((byte) (returnsTriggerInEvent ? 1 : 0));
Nicholas Ambur7092a562019-12-16 11:18:55 -0800253 dest.writeInt(audioCapabilities);
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700254 }
255
256 @Override
257 public int describeContents() {
258 return 0;
259 }
260
261 @Override
262 public String toString() {
263 return "ModuleProperties [id=" + id + ", implementor=" + implementor + ", description="
Nicholas Ambur38027cd2019-12-16 00:06:19 -0800264 + description + ", uuid=" + uuid + ", version=" + version
265 + " , supportedModelArch=" + supportedModelArch + ", maxSoundModels="
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700266 + maxSoundModels + ", maxKeyphrases=" + maxKeyphrases + ", maxUsers="
267 + maxUsers + ", recognitionModes=" + recognitionModes
268 + ", supportsCaptureTransition=" + supportsCaptureTransition + ", maxBufferMs="
269 + maxBufferMs + ", supportsConcurrentCapture=" + supportsConcurrentCapture
Eric Laurentd3b82232014-07-30 08:57:39 -0700270 + ", powerConsumptionMw=" + powerConsumptionMw
Nicholas Ambur7092a562019-12-16 11:18:55 -0800271 + ", returnsTriggerInEvent=" + returnsTriggerInEvent
272 + ", audioCapabilities=" + audioCapabilities + "]";
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700273 }
Eric Laurente48188c2014-04-18 17:44:11 -0700274 }
275
Nicholas Amburef84fc42020-01-14 20:28:37 -0800276 /**
Eric Laurente48188c2014-04-18 17:44:11 -0700277 * A SoundModel describes the attributes and contains the binary data used by the hardware
278 * implementation to detect a particular sound pattern.
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700279 * A specialized version {@link KeyphraseSoundModel} is defined for key phrase
Eric Laurente48188c2014-04-18 17:44:11 -0700280 * sound models.
Nicholas Amburef84fc42020-01-14 20:28:37 -0800281 */
Eric Laurente48188c2014-04-18 17:44:11 -0700282 public static class SoundModel {
Nicholas Amburef84fc42020-01-14 20:28:37 -0800283
284 /** @hide */
285 @Retention(RetentionPolicy.SOURCE)
286 @IntDef({
287 TYPE_GENERIC_SOUND,
288 TYPE_KEYPHRASE,
289 TYPE_UNKNOWN,
290 })
291 public @interface SoundModelType {}
292
293 /**
294 * Undefined sound model type
295 * @hide
296 */
Eric Laurente48188c2014-04-18 17:44:11 -0700297 public static final int TYPE_UNKNOWN = -1;
298
299 /** Keyphrase sound model */
300 public static final int TYPE_KEYPHRASE = 0;
301
Arunesh Mishraa772e5f2016-01-25 10:33:11 -0800302 /**
303 * A generic sound model. Use this type only for non-keyphrase sound models such as
304 * ones that match a particular sound pattern.
305 */
306 public static final int TYPE_GENERIC_SOUND = 1;
307
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700308 /** Unique sound model identifier */
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -0800309 @NonNull
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700310 public final UUID uuid;
311
Eric Laurente48188c2014-04-18 17:44:11 -0700312 /** Sound model type (e.g. TYPE_KEYPHRASE); */
Nicholas Amburef84fc42020-01-14 20:28:37 -0800313 @SoundModelType
Eric Laurente48188c2014-04-18 17:44:11 -0700314 public final int type;
315
Eric Laurentd3b82232014-07-30 08:57:39 -0700316 /** Unique sound model vendor identifier */
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -0800317 @NonNull
Eric Laurentd3b82232014-07-30 08:57:39 -0700318 public final UUID vendorUuid;
319
Nicholas Amburd3ec82f2020-01-03 17:44:19 -0800320 /** vendor specific version number of the model */
321 public final int version;
322
Eric Laurente48188c2014-04-18 17:44:11 -0700323 /** Opaque data. For use by vendor implementation and enrollment application */
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -0800324 @NonNull
Eric Laurente48188c2014-04-18 17:44:11 -0700325 public final byte[] data;
326
Nicholas Amburef84fc42020-01-14 20:28:37 -0800327 /** @hide */
328 public SoundModel(@NonNull UUID uuid, @Nullable UUID vendorUuid, @SoundModelType int type,
Nicholas Amburd3ec82f2020-01-03 17:44:19 -0800329 @Nullable byte[] data, int version) {
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -0800330 this.uuid = requireNonNull(uuid);
331 this.vendorUuid = vendorUuid != null ? vendorUuid : new UUID(0, 0);
Eric Laurente48188c2014-04-18 17:44:11 -0700332 this.type = type;
Nicholas Amburd3ec82f2020-01-03 17:44:19 -0800333 this.version = version;
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -0800334 this.data = data != null ? data : new byte[0];
Eric Laurente48188c2014-04-18 17:44:11 -0700335 }
Sandeep Siddhartha45c00b52014-10-16 16:17:11 -0700336
337 @Override
338 public int hashCode() {
339 final int prime = 31;
340 int result = 1;
Nicholas Amburd3ec82f2020-01-03 17:44:19 -0800341 result = prime * result + version;
Sandeep Siddhartha45c00b52014-10-16 16:17:11 -0700342 result = prime * result + Arrays.hashCode(data);
343 result = prime * result + type;
344 result = prime * result + ((uuid == null) ? 0 : uuid.hashCode());
345 result = prime * result + ((vendorUuid == null) ? 0 : vendorUuid.hashCode());
346 return result;
347 }
348
349 @Override
350 public boolean equals(Object obj) {
Nicholas Amburef84fc42020-01-14 20:28:37 -0800351 if (this == obj) {
Sandeep Siddhartha45c00b52014-10-16 16:17:11 -0700352 return true;
Nicholas Amburef84fc42020-01-14 20:28:37 -0800353 }
354 if (obj == null) {
Sandeep Siddhartha45c00b52014-10-16 16:17:11 -0700355 return false;
Nicholas Amburef84fc42020-01-14 20:28:37 -0800356 }
357 if (!(obj instanceof SoundModel)) {
Sandeep Siddhartha45c00b52014-10-16 16:17:11 -0700358 return false;
Nicholas Amburef84fc42020-01-14 20:28:37 -0800359 }
Sandeep Siddhartha45c00b52014-10-16 16:17:11 -0700360 SoundModel other = (SoundModel) obj;
Nicholas Amburef84fc42020-01-14 20:28:37 -0800361 if (type != other.type) {
Sandeep Siddhartha45c00b52014-10-16 16:17:11 -0700362 return false;
Nicholas Amburef84fc42020-01-14 20:28:37 -0800363 }
Sandeep Siddhartha45c00b52014-10-16 16:17:11 -0700364 if (uuid == null) {
Nicholas Amburef84fc42020-01-14 20:28:37 -0800365 if (other.uuid != null) {
Sandeep Siddhartha45c00b52014-10-16 16:17:11 -0700366 return false;
Nicholas Amburef84fc42020-01-14 20:28:37 -0800367 }
368 } else if (!uuid.equals(other.uuid)) {
Sandeep Siddhartha45c00b52014-10-16 16:17:11 -0700369 return false;
Nicholas Amburef84fc42020-01-14 20:28:37 -0800370 }
Sandeep Siddhartha45c00b52014-10-16 16:17:11 -0700371 if (vendorUuid == null) {
Nicholas Amburef84fc42020-01-14 20:28:37 -0800372 if (other.vendorUuid != null) {
Sandeep Siddhartha45c00b52014-10-16 16:17:11 -0700373 return false;
Nicholas Amburef84fc42020-01-14 20:28:37 -0800374 }
375 } else if (!vendorUuid.equals(other.vendorUuid)) {
Sandeep Siddhartha45c00b52014-10-16 16:17:11 -0700376 return false;
Nicholas Amburef84fc42020-01-14 20:28:37 -0800377 }
378 if (!Arrays.equals(data, other.data)) {
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -0800379 return false;
Nicholas Amburef84fc42020-01-14 20:28:37 -0800380 }
381 if (version != other.version) {
Nicholas Amburd3ec82f2020-01-03 17:44:19 -0800382 return false;
Nicholas Amburef84fc42020-01-14 20:28:37 -0800383 }
Sandeep Siddhartha45c00b52014-10-16 16:17:11 -0700384 return true;
385 }
Eric Laurente48188c2014-04-18 17:44:11 -0700386 }
387
Nicholas Amburef84fc42020-01-14 20:28:37 -0800388 /**
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700389 * A Keyphrase describes a key phrase that can be detected by a
390 * {@link KeyphraseSoundModel}
Nicholas Amburef84fc42020-01-14 20:28:37 -0800391 */
392 public static final class Keyphrase implements Parcelable {
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700393 /** Unique identifier for this keyphrase */
394 public final int id;
395
Nicholas Amburef84fc42020-01-14 20:28:37 -0800396 /**
397 * Recognition modes supported for this key phrase in the model
398 *
399 * @see #RECOGNITION_MODE_VOICE_TRIGGER
400 * @see #RECOGNITION_MODE_USER_IDENTIFICATION
401 * @see #RECOGNITION_MODE_USER_AUTHENTICATION
402 * @see #RECOGNITION_MODE_GENERIC
403 */
404 @RecognitionModes
Eric Laurente48188c2014-04-18 17:44:11 -0700405 public final int recognitionModes;
406
Nicholas Amburef84fc42020-01-14 20:28:37 -0800407 /** Locale of the keyphrase. */
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -0800408 @NonNull
Nicholas Amburef84fc42020-01-14 20:28:37 -0800409 public final Locale locale;
Eric Laurente48188c2014-04-18 17:44:11 -0700410
411 /** Key phrase text */
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -0800412 @NonNull
Eric Laurente48188c2014-04-18 17:44:11 -0700413 public final String text;
414
Nicholas Amburef84fc42020-01-14 20:28:37 -0800415 /**
416 * Users this key phrase has been trained for. countains sound trigger specific user IDs
417 * derived from system user IDs {@link android.os.UserHandle#getIdentifier()}.
418 */
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -0800419 @NonNull
Eric Laurent013f66b2014-07-06 16:35:00 -0700420 public final int[] users;
Eric Laurente48188c2014-04-18 17:44:11 -0700421
Nicholas Amburef84fc42020-01-14 20:28:37 -0800422 /**
423 * Constructor for Keyphrase describes a key phrase that can be detected by a
424 * {@link KeyphraseSoundModel}
425 *
426 * @param id Unique keyphrase identifier for this keyphrase
427 * @param recognitionModes Bit field representation of recognition modes this keyphrase
428 * supports
429 * @param locale Locale of the keyphrase
430 * @param text Key phrase text
431 * @param users Users this key phrase has been trained for.
432 */
433 public Keyphrase(int id, @RecognitionModes int recognitionModes, @NonNull Locale locale,
434 @NonNull String text, @Nullable int[] users) {
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700435 this.id = id;
Eric Laurente48188c2014-04-18 17:44:11 -0700436 this.recognitionModes = recognitionModes;
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -0800437 this.locale = requireNonNull(locale);
438 this.text = requireNonNull(text);
439 this.users = users != null ? users : new int[0];
Eric Laurente48188c2014-04-18 17:44:11 -0700440 }
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700441
Nicholas Amburef84fc42020-01-14 20:28:37 -0800442 public static final @NonNull Parcelable.Creator<Keyphrase> CREATOR =
443 new Parcelable.Creator<Keyphrase>() {
444 @NonNull
445 public Keyphrase createFromParcel(@NonNull Parcel in) {
446 return Keyphrase.readFromParcel(in);
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700447 }
448
Nicholas Amburef84fc42020-01-14 20:28:37 -0800449 @NonNull
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700450 public Keyphrase[] newArray(int size) {
451 return new Keyphrase[size];
452 }
453 };
454
Nicholas Amburef84fc42020-01-14 20:28:37 -0800455 /**
456 * Read from Parcel to generate keyphrase
457 */
458 @NonNull
459 public static Keyphrase readFromParcel(@NonNull Parcel in) {
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700460 int id = in.readInt();
461 int recognitionModes = in.readInt();
Nicholas Amburef84fc42020-01-14 20:28:37 -0800462 Locale locale = Locale.forLanguageTag(in.readString());
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700463 String text = in.readString();
464 int[] users = null;
465 int numUsers = in.readInt();
Sandeep Siddhartha110f5692014-07-20 12:22:56 -0700466 if (numUsers >= 0) {
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700467 users = new int[numUsers];
468 in.readIntArray(users);
469 }
470 return new Keyphrase(id, recognitionModes, locale, text, users);
471 }
472
473 @Override
Nicholas Amburef84fc42020-01-14 20:28:37 -0800474 public void writeToParcel(@NonNull Parcel dest, int flags) {
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700475 dest.writeInt(id);
476 dest.writeInt(recognitionModes);
Nicholas Amburef84fc42020-01-14 20:28:37 -0800477 dest.writeString(locale.toLanguageTag());
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700478 dest.writeString(text);
479 if (users != null) {
480 dest.writeInt(users.length);
481 dest.writeIntArray(users);
482 } else {
Sandeep Siddhartha110f5692014-07-20 12:22:56 -0700483 dest.writeInt(-1);
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700484 }
485 }
486
Nicholas Amburef84fc42020-01-14 20:28:37 -0800487 /** @hide */
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700488 @Override
489 public int describeContents() {
490 return 0;
491 }
492
493 @Override
494 public int hashCode() {
495 final int prime = 31;
496 int result = 1;
497 result = prime * result + ((text == null) ? 0 : text.hashCode());
498 result = prime * result + id;
499 result = prime * result + ((locale == null) ? 0 : locale.hashCode());
500 result = prime * result + recognitionModes;
501 result = prime * result + Arrays.hashCode(users);
502 return result;
503 }
504
505 @Override
506 public boolean equals(Object obj) {
Nicholas Amburef84fc42020-01-14 20:28:37 -0800507 if (this == obj) {
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700508 return true;
Nicholas Amburef84fc42020-01-14 20:28:37 -0800509 }
510 if (obj == null) {
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700511 return false;
Nicholas Amburef84fc42020-01-14 20:28:37 -0800512 }
513 if (getClass() != obj.getClass()) {
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700514 return false;
Nicholas Amburef84fc42020-01-14 20:28:37 -0800515 }
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700516 Keyphrase other = (Keyphrase) obj;
517 if (text == null) {
Nicholas Amburef84fc42020-01-14 20:28:37 -0800518 if (other.text != null) {
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700519 return false;
Nicholas Amburef84fc42020-01-14 20:28:37 -0800520 }
521 } else if (!text.equals(other.text)) {
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700522 return false;
Nicholas Amburef84fc42020-01-14 20:28:37 -0800523 }
524 if (id != other.id) {
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700525 return false;
Nicholas Amburef84fc42020-01-14 20:28:37 -0800526 }
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700527 if (locale == null) {
Nicholas Amburef84fc42020-01-14 20:28:37 -0800528 if (other.locale != null) {
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700529 return false;
Nicholas Amburef84fc42020-01-14 20:28:37 -0800530 }
531 } else if (!locale.equals(other.locale)) {
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700532 return false;
Nicholas Amburef84fc42020-01-14 20:28:37 -0800533 }
534 if (recognitionModes != other.recognitionModes) {
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700535 return false;
Nicholas Amburef84fc42020-01-14 20:28:37 -0800536 }
537 if (!Arrays.equals(users, other.users)) {
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700538 return false;
Nicholas Amburef84fc42020-01-14 20:28:37 -0800539 }
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700540 return true;
541 }
542
543 @Override
544 public String toString() {
Nicholas Amburef84fc42020-01-14 20:28:37 -0800545 return "Keyphrase [id=" + id + ", recognitionModes=" + recognitionModes
546 + ", locale=" + locale.toLanguageTag() + ", text=" + text
547 + ", users=" + Arrays.toString(users) + "]";
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700548 }
Eric Laurente48188c2014-04-18 17:44:11 -0700549 }
550
Nicholas Amburef84fc42020-01-14 20:28:37 -0800551 /**
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700552 * A KeyphraseSoundModel is a specialized {@link SoundModel} for key phrases.
Eric Laurente48188c2014-04-18 17:44:11 -0700553 * It contains data needed by the hardware to detect a certain number of key phrases
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700554 * and the list of corresponding {@link Keyphrase} descriptors.
Nicholas Amburef84fc42020-01-14 20:28:37 -0800555 */
556 public static final class KeyphraseSoundModel extends SoundModel implements Parcelable {
Eric Laurente48188c2014-04-18 17:44:11 -0700557 /** Key phrases in this sound model */
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -0800558 @NonNull
Sandeep Siddharthad4233c62014-06-12 18:31:19 -0700559 public final Keyphrase[] keyphrases; // keyword phrases in model
Eric Laurente48188c2014-04-18 17:44:11 -0700560
Eric Laurentd3b82232014-07-30 08:57:39 -0700561 public KeyphraseSoundModel(
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -0800562 @NonNull UUID uuid, @NonNull UUID vendorUuid, @Nullable byte[] data,
Nicholas Amburd3ec82f2020-01-03 17:44:19 -0800563 @Nullable Keyphrase[] keyphrases, int version) {
564 super(uuid, vendorUuid, TYPE_KEYPHRASE, data, version);
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -0800565 this.keyphrases = keyphrases != null ? keyphrases : new Keyphrase[0];
Eric Laurente48188c2014-04-18 17:44:11 -0700566 }
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700567
Nicholas Amburd3ec82f2020-01-03 17:44:19 -0800568 public KeyphraseSoundModel(@NonNull UUID uuid, @NonNull UUID vendorUuid,
569 @Nullable byte[] data, @Nullable Keyphrase[] keyphrases) {
570 this(uuid, vendorUuid, data, keyphrases, -1);
571 }
572
Nicholas Amburef84fc42020-01-14 20:28:37 -0800573 public static final @NonNull Parcelable.Creator<KeyphraseSoundModel> CREATOR =
574 new Parcelable.Creator<KeyphraseSoundModel>() {
575 @NonNull
576 public KeyphraseSoundModel createFromParcel(@NonNull Parcel in) {
577 return KeyphraseSoundModel.readFromParcel(in);
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700578 }
579
Nicholas Amburef84fc42020-01-14 20:28:37 -0800580 @NonNull
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700581 public KeyphraseSoundModel[] newArray(int size) {
582 return new KeyphraseSoundModel[size];
583 }
584 };
585
Nicholas Amburef84fc42020-01-14 20:28:37 -0800586 /**
587 * Read from Parcel to generate KeyphraseSoundModel
588 */
589 @NonNull
590 public static KeyphraseSoundModel readFromParcel(@NonNull Parcel in) {
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700591 UUID uuid = UUID.fromString(in.readString());
Eric Laurentd3b82232014-07-30 08:57:39 -0700592 UUID vendorUuid = null;
593 int length = in.readInt();
594 if (length >= 0) {
595 vendorUuid = UUID.fromString(in.readString());
596 }
Nicholas Amburd3ec82f2020-01-03 17:44:19 -0800597 int version = in.readInt();
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -0700598 byte[] data = in.readBlob();
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700599 Keyphrase[] keyphrases = in.createTypedArray(Keyphrase.CREATOR);
Nicholas Amburd3ec82f2020-01-03 17:44:19 -0800600 return new KeyphraseSoundModel(uuid, vendorUuid, data, keyphrases, version);
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700601 }
602
Nicholas Amburef84fc42020-01-14 20:28:37 -0800603 /** @hide */
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700604 @Override
605 public int describeContents() {
606 return 0;
607 }
608
609 @Override
Nicholas Amburef84fc42020-01-14 20:28:37 -0800610 public void writeToParcel(@NonNull Parcel dest, int flags) {
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700611 dest.writeString(uuid.toString());
Eric Laurentd3b82232014-07-30 08:57:39 -0700612 if (vendorUuid == null) {
613 dest.writeInt(-1);
614 } else {
615 dest.writeInt(vendorUuid.toString().length());
616 dest.writeString(vendorUuid.toString());
617 }
Nicholas Ambur43970b52020-01-14 18:54:26 -0800618 dest.writeInt(version);
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -0700619 dest.writeBlob(data);
Sandeep Siddhartha68173372014-07-28 13:25:30 -0700620 dest.writeTypedArray(keyphrases, flags);
Sandeep Siddhartha05589722014-07-17 16:21:54 -0700621 }
Sandeep Siddhartha110f5692014-07-20 12:22:56 -0700622
623 @Override
624 public String toString() {
Eric Laurentd3b82232014-07-30 08:57:39 -0700625 return "KeyphraseSoundModel [keyphrases=" + Arrays.toString(keyphrases)
626 + ", uuid=" + uuid + ", vendorUuid=" + vendorUuid
Nicholas Amburd3ec82f2020-01-03 17:44:19 -0800627 + ", type=" + type
628 + ", data=" + (data == null ? 0 : data.length)
629 + ", version=" + version + "]";
Sandeep Siddhartha110f5692014-07-20 12:22:56 -0700630 }
Sandeep Siddhartha45c00b52014-10-16 16:17:11 -0700631
632 @Override
633 public int hashCode() {
634 final int prime = 31;
635 int result = super.hashCode();
636 result = prime * result + Arrays.hashCode(keyphrases);
637 return result;
638 }
639
640 @Override
641 public boolean equals(Object obj) {
Nicholas Amburef84fc42020-01-14 20:28:37 -0800642 if (this == obj) {
Sandeep Siddhartha45c00b52014-10-16 16:17:11 -0700643 return true;
Nicholas Amburef84fc42020-01-14 20:28:37 -0800644 }
645 if (!super.equals(obj)) {
Sandeep Siddhartha45c00b52014-10-16 16:17:11 -0700646 return false;
Nicholas Amburef84fc42020-01-14 20:28:37 -0800647 }
648 if (!(obj instanceof KeyphraseSoundModel)) {
Sandeep Siddhartha45c00b52014-10-16 16:17:11 -0700649 return false;
Nicholas Amburef84fc42020-01-14 20:28:37 -0800650 }
Sandeep Siddhartha45c00b52014-10-16 16:17:11 -0700651 KeyphraseSoundModel other = (KeyphraseSoundModel) obj;
Nicholas Amburef84fc42020-01-14 20:28:37 -0800652 if (!Arrays.equals(keyphrases, other.keyphrases)) {
Sandeep Siddhartha45c00b52014-10-16 16:17:11 -0700653 return false;
Nicholas Amburef84fc42020-01-14 20:28:37 -0800654 }
Sandeep Siddhartha45c00b52014-10-16 16:17:11 -0700655 return true;
656 }
Eric Laurente48188c2014-04-18 17:44:11 -0700657 }
658
Arunesh Mishraa772e5f2016-01-25 10:33:11 -0800659
660 /*****************************************************************************
661 * A GenericSoundModel is a specialized {@link SoundModel} for non-voice sound
662 * patterns.
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -0800663 *
664 * @hide
Arunesh Mishraa772e5f2016-01-25 10:33:11 -0800665 ****************************************************************************/
666 public static class GenericSoundModel extends SoundModel implements Parcelable {
667
Jeff Sharkey9e8f83d2019-02-28 12:06:45 -0700668 public static final @android.annotation.NonNull Parcelable.Creator<GenericSoundModel> CREATOR
Arunesh Mishraa772e5f2016-01-25 10:33:11 -0800669 = new Parcelable.Creator<GenericSoundModel>() {
670 public GenericSoundModel createFromParcel(Parcel in) {
671 return GenericSoundModel.fromParcel(in);
672 }
673
674 public GenericSoundModel[] newArray(int size) {
675 return new GenericSoundModel[size];
676 }
677 };
678
Nicholas Amburd3ec82f2020-01-03 17:44:19 -0800679 public GenericSoundModel(@NonNull UUID uuid, @NonNull UUID vendorUuid,
680 @Nullable byte[] data, int version) {
681 super(uuid, vendorUuid, TYPE_GENERIC_SOUND, data, version);
682 }
683
Mathew Inwoodbcbe4402018-08-08 15:42:59 +0100684 @UnsupportedAppUsage
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -0800685 public GenericSoundModel(@NonNull UUID uuid, @NonNull UUID vendorUuid,
686 @Nullable byte[] data) {
Nicholas Amburd3ec82f2020-01-03 17:44:19 -0800687 this(uuid, vendorUuid, data, -1);
Arunesh Mishraa772e5f2016-01-25 10:33:11 -0800688 }
689
690 @Override
691 public int describeContents() {
692 return 0;
693 }
694
695 private static GenericSoundModel fromParcel(Parcel in) {
696 UUID uuid = UUID.fromString(in.readString());
697 UUID vendorUuid = null;
698 int length = in.readInt();
699 if (length >= 0) {
700 vendorUuid = UUID.fromString(in.readString());
701 }
702 byte[] data = in.readBlob();
Nicholas Amburd3ec82f2020-01-03 17:44:19 -0800703 int version = in.readInt();
704 return new GenericSoundModel(uuid, vendorUuid, data, version);
Arunesh Mishraa772e5f2016-01-25 10:33:11 -0800705 }
706
707 @Override
708 public void writeToParcel(Parcel dest, int flags) {
709 dest.writeString(uuid.toString());
710 if (vendorUuid == null) {
711 dest.writeInt(-1);
712 } else {
713 dest.writeInt(vendorUuid.toString().length());
714 dest.writeString(vendorUuid.toString());
715 }
716 dest.writeBlob(data);
Nicholas Amburd3ec82f2020-01-03 17:44:19 -0800717 dest.writeInt(version);
Arunesh Mishraa772e5f2016-01-25 10:33:11 -0800718 }
719
720 @Override
721 public String toString() {
722 return "GenericSoundModel [uuid=" + uuid + ", vendorUuid=" + vendorUuid
Nicholas Amburd3ec82f2020-01-03 17:44:19 -0800723 + ", type=" + type
724 + ", data=" + (data == null ? 0 : data.length)
725 + ", version=" + version + "]";
Arunesh Mishraa772e5f2016-01-25 10:33:11 -0800726 }
727 }
728
Nicholas Amburf94db1c2019-12-08 19:04:06 -0800729 /**
Nicholas Ambura0be6be2019-10-01 10:11:39 -0700730 * A ModelParamRange is a representation of supported parameter range for a
731 * given loaded model.
Nicholas Amburf94db1c2019-12-08 19:04:06 -0800732 */
Nicholas Ambura0be6be2019-10-01 10:11:39 -0700733 public static final class ModelParamRange implements Parcelable {
734
735 /**
Nicholas Amburf94db1c2019-12-08 19:04:06 -0800736 * The inclusive start of supported range.
Nicholas Ambura0be6be2019-10-01 10:11:39 -0700737 */
738 public final int start;
739
740 /**
Nicholas Amburf94db1c2019-12-08 19:04:06 -0800741 * The inclusive end of supported range.
Nicholas Ambura0be6be2019-10-01 10:11:39 -0700742 */
743 public final int end;
744
745 ModelParamRange(int start, int end) {
746 this.start = start;
747 this.end = end;
748 }
749
Nicholas Amburf94db1c2019-12-08 19:04:06 -0800750 /** @hide */
Nicholas Ambura0be6be2019-10-01 10:11:39 -0700751 private ModelParamRange(@NonNull Parcel in) {
752 this.start = in.readInt();
753 this.end = in.readInt();
754 }
755
756 @NonNull
Nicholas Amburf94db1c2019-12-08 19:04:06 -0800757 public static final Creator<ModelParamRange> CREATOR =
758 new Creator<ModelParamRange>() {
759 @Override
760 @NonNull
761 public ModelParamRange createFromParcel(@NonNull Parcel in) {
762 return new ModelParamRange(in);
763 }
Nicholas Ambura0be6be2019-10-01 10:11:39 -0700764
Nicholas Amburf94db1c2019-12-08 19:04:06 -0800765 @Override
766 @NonNull
767 public ModelParamRange[] newArray(int size) {
768 return new ModelParamRange[size];
769 }
770 };
Nicholas Ambura0be6be2019-10-01 10:11:39 -0700771
Nicholas Amburf94db1c2019-12-08 19:04:06 -0800772 /** @hide */
Nicholas Ambura0be6be2019-10-01 10:11:39 -0700773 @Override
774 public int describeContents() {
775 return 0;
776 }
777
Nicholas Amburf94db1c2019-12-08 19:04:06 -0800778 /** @hide */
779 @Override
780 public int hashCode() {
781 final int prime = 31;
782 int result = 1;
783 result = prime * result + (start);
784 result = prime * result + (end);
785 return result;
786 }
787
788 @Override
789 public boolean equals(@Nullable Object obj) {
790 if (this == obj) {
791 return true;
792 }
793 if (obj == null) {
794 return false;
795 }
796 if (getClass() != obj.getClass()) {
797 return false;
798 }
799 ModelParamRange other = (ModelParamRange) obj;
800 if (start != other.start) {
801 return false;
802 }
803 if (end != other.end) {
804 return false;
805 }
806 return true;
807 }
808
Nicholas Ambura0be6be2019-10-01 10:11:39 -0700809 @Override
810 public void writeToParcel(@NonNull Parcel dest, int flags) {
811 dest.writeInt(start);
812 dest.writeInt(end);
813 }
814
815 @Override
816 @NonNull
817 public String toString() {
818 return "ModelParamRange [start=" + start + ", end=" + end + "]";
819 }
820 }
821
Eric Laurente48188c2014-04-18 17:44:11 -0700822 /**
Nicholas Amburef84fc42020-01-14 20:28:37 -0800823 * Modes for key phrase recognition
824 * @hide
Eric Laurente48188c2014-04-18 17:44:11 -0700825 */
Nicholas Amburef84fc42020-01-14 20:28:37 -0800826 @Retention(RetentionPolicy.SOURCE)
827 @IntDef(flag = true, prefix = { "RECOGNITION_MODE_" }, value = {
828 RECOGNITION_MODE_VOICE_TRIGGER,
829 RECOGNITION_MODE_USER_IDENTIFICATION,
830 RECOGNITION_MODE_USER_AUTHENTICATION,
831 RECOGNITION_MODE_GENERIC
832 })
833 public @interface RecognitionModes {}
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -0800834
835 /**
Nicholas Amburef84fc42020-01-14 20:28:37 -0800836 * Trigger on recognition of a key phrase
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -0800837 */
Eric Laurente48188c2014-04-18 17:44:11 -0700838 public static final int RECOGNITION_MODE_VOICE_TRIGGER = 0x1;
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -0800839 /**
840 * Trigger only if one user is identified
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -0800841 */
Eric Laurente48188c2014-04-18 17:44:11 -0700842 public static final int RECOGNITION_MODE_USER_IDENTIFICATION = 0x2;
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -0800843 /**
844 * Trigger only if one user is authenticated
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -0800845 */
Eric Laurente48188c2014-04-18 17:44:11 -0700846 public static final int RECOGNITION_MODE_USER_AUTHENTICATION = 0x4;
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -0800847 /**
848 * Generic (non-speech) recognition.
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -0800849 */
850 public static final int RECOGNITION_MODE_GENERIC = 0x8;
Eric Laurente48188c2014-04-18 17:44:11 -0700851
852 /**
853 * Status codes for {@link RecognitionEvent}
854 */
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -0800855 /**
856 * Recognition success
857 *
858 * @hide
859 */
Eric Laurente48188c2014-04-18 17:44:11 -0700860 public static final int RECOGNITION_STATUS_SUCCESS = 0;
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -0800861 /**
862 * Recognition aborted (e.g. capture preempted by anotehr use case
863 *
864 * @hide
865 */
Eric Laurente48188c2014-04-18 17:44:11 -0700866 public static final int RECOGNITION_STATUS_ABORT = 1;
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -0800867 /**
868 * Recognition failure
869 *
870 * @hide
871 */
Eric Laurente48188c2014-04-18 17:44:11 -0700872 public static final int RECOGNITION_STATUS_FAILURE = 2;
mike dooleyb2ab04a2018-11-07 15:48:54 +0100873 /**
874 * Recognition event was triggered by a getModelState request, not by the
875 * DSP.
876 *
877 * @hide
878 */
879 public static final int RECOGNITION_STATUS_GET_STATE_RESPONSE = 3;
Eric Laurente48188c2014-04-18 17:44:11 -0700880
881 /**
882 * A RecognitionEvent is provided by the
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -0800883 * {@code StatusListener#onRecognition(RecognitionEvent)}
Eric Laurente48188c2014-04-18 17:44:11 -0700884 * callback upon recognition success or failure.
885 */
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -0800886 public static class RecognitionEvent {
887 /**
888 * Recognition status e.g RECOGNITION_STATUS_SUCCESS
889 *
890 * @hide
891 */
Mathew Inwoodbcbe4402018-08-08 15:42:59 +0100892 @UnsupportedAppUsage
Eric Laurente48188c2014-04-18 17:44:11 -0700893 public final int status;
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -0800894 /**
895 *
896 * Sound Model corresponding to this event callback
897 *
898 * @hide
899 */
Mathew Inwoodbcbe4402018-08-08 15:42:59 +0100900 @UnsupportedAppUsage
Eric Laurente48188c2014-04-18 17:44:11 -0700901 public final int soundModelHandle;
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -0800902 /**
903 * True if it is possible to capture audio from this utterance buffered by the hardware
904 *
905 * @hide
906 */
Mathew Inwoodbcbe4402018-08-08 15:42:59 +0100907 @UnsupportedAppUsage
Eric Laurente48188c2014-04-18 17:44:11 -0700908 public final boolean captureAvailable;
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -0800909 /**
910 * Audio session ID to be used when capturing the utterance with an AudioRecord
911 * if captureAvailable() is true.
912 *
913 * @hide
914 */
Mathew Inwoodbcbe4402018-08-08 15:42:59 +0100915 @UnsupportedAppUsage
Eric Laurente48188c2014-04-18 17:44:11 -0700916 public final int captureSession;
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -0800917 /**
918 * Delay in ms between end of model detection and start of audio available for capture.
919 * A negative value is possible (e.g. if keyphrase is also available for capture)
920 *
921 * @hide
922 */
Eric Laurente48188c2014-04-18 17:44:11 -0700923 public final int captureDelayMs;
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -0800924 /**
925 * Duration in ms of audio captured before the start of the trigger. 0 if none.
926 *
927 * @hide
928 */
Eric Laurent013f66b2014-07-06 16:35:00 -0700929 public final int capturePreambleMs;
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -0800930 /**
931 * True if the trigger (key phrase capture is present in binary data
932 *
933 * @hide
934 */
Eric Laurentd3b82232014-07-30 08:57:39 -0700935 public final boolean triggerInData;
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -0800936 /**
937 * Audio format of either the trigger in event data or to use for capture of the
938 * rest of the utterance
939 *
940 * @hide
941 */
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -0800942 @NonNull
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -0800943 public final AudioFormat captureFormat;
944 /**
945 * Opaque data for use by system applications who know about voice engine internals,
946 * typically during enrollment.
947 *
948 * @hide
949 */
Mathew Inwoodbcbe4402018-08-08 15:42:59 +0100950 @UnsupportedAppUsage
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -0800951 @NonNull
Eric Laurente48188c2014-04-18 17:44:11 -0700952 public final byte[] data;
953
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -0800954 /** @hide */
Mathew Inwoodbcbe4402018-08-08 15:42:59 +0100955 @UnsupportedAppUsage
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -0700956 public RecognitionEvent(int status, int soundModelHandle, boolean captureAvailable,
Eric Laurentd3b82232014-07-30 08:57:39 -0700957 int captureSession, int captureDelayMs, int capturePreambleMs,
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -0800958 boolean triggerInData, @NonNull AudioFormat captureFormat, @Nullable byte[] data) {
Eric Laurente48188c2014-04-18 17:44:11 -0700959 this.status = status;
960 this.soundModelHandle = soundModelHandle;
961 this.captureAvailable = captureAvailable;
962 this.captureSession = captureSession;
963 this.captureDelayMs = captureDelayMs;
Eric Laurent013f66b2014-07-06 16:35:00 -0700964 this.capturePreambleMs = capturePreambleMs;
Eric Laurentd3b82232014-07-30 08:57:39 -0700965 this.triggerInData = triggerInData;
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -0800966 this.captureFormat = requireNonNull(captureFormat);
967 this.data = data != null ? data : new byte[0];
Eric Laurente48188c2014-04-18 17:44:11 -0700968 }
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -0700969
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -0800970 /**
971 * Check if is possible to capture audio from this utterance buffered by the hardware.
972 *
973 * @return {@code true} iff a capturing is possible
974 */
975 public boolean isCaptureAvailable() {
976 return captureAvailable;
977 }
978
979 /**
980 * Get the audio format of either the trigger in event data or to use for capture of the
981 * rest of the utterance
982 *
983 * @return the audio format
984 */
985 @Nullable public AudioFormat getCaptureFormat() {
986 return captureFormat;
987 }
988
989 /**
990 * Get Audio session ID to be used when capturing the utterance with an {@link AudioRecord}
991 * if {@link #isCaptureAvailable()} is true.
992 *
993 * @return The id of the capture session
994 */
995 public int getCaptureSession() {
996 return captureSession;
997 }
998
999 /**
1000 * Get the opaque data for use by system applications who know about voice engine
1001 * internals, typically during enrollment.
1002 *
1003 * @return The data of the event
1004 */
1005 public byte[] getData() {
1006 return data;
1007 }
1008
1009 /** @hide */
Jeff Sharkey9e8f83d2019-02-28 12:06:45 -07001010 public static final @android.annotation.NonNull Parcelable.Creator<RecognitionEvent> CREATOR
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -07001011 = new Parcelable.Creator<RecognitionEvent>() {
1012 public RecognitionEvent createFromParcel(Parcel in) {
1013 return RecognitionEvent.fromParcel(in);
1014 }
1015
1016 public RecognitionEvent[] newArray(int size) {
1017 return new RecognitionEvent[size];
1018 }
1019 };
1020
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -08001021 /** @hide */
Arunesh Mishraf47f1732016-02-18 16:16:12 -08001022 protected static RecognitionEvent fromParcel(Parcel in) {
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -07001023 int status = in.readInt();
1024 int soundModelHandle = in.readInt();
1025 boolean captureAvailable = in.readByte() == 1;
1026 int captureSession = in.readInt();
1027 int captureDelayMs = in.readInt();
1028 int capturePreambleMs = in.readInt();
Eric Laurentd3b82232014-07-30 08:57:39 -07001029 boolean triggerInData = in.readByte() == 1;
1030 AudioFormat captureFormat = null;
Eric Laurent39fcca02014-09-05 16:44:19 -07001031 if (in.readByte() == 1) {
Eric Laurentd3b82232014-07-30 08:57:39 -07001032 int sampleRate = in.readInt();
1033 int encoding = in.readInt();
1034 int channelMask = in.readInt();
1035 captureFormat = (new AudioFormat.Builder())
1036 .setChannelMask(channelMask)
1037 .setEncoding(encoding)
1038 .setSampleRate(sampleRate)
1039 .build();
1040 }
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -07001041 byte[] data = in.readBlob();
1042 return new RecognitionEvent(status, soundModelHandle, captureAvailable, captureSession,
Eric Laurentd3b82232014-07-30 08:57:39 -07001043 captureDelayMs, capturePreambleMs, triggerInData, captureFormat, data);
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -07001044 }
1045
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -08001046 /** @hide */
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -07001047 public int describeContents() {
1048 return 0;
1049 }
1050
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -08001051 /** @hide */
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -07001052 public void writeToParcel(Parcel dest, int flags) {
1053 dest.writeInt(status);
1054 dest.writeInt(soundModelHandle);
1055 dest.writeByte((byte) (captureAvailable ? 1 : 0));
1056 dest.writeInt(captureSession);
1057 dest.writeInt(captureDelayMs);
1058 dest.writeInt(capturePreambleMs);
Eric Laurent39fcca02014-09-05 16:44:19 -07001059 dest.writeByte((byte) (triggerInData ? 1 : 0));
1060 if (captureFormat != null) {
Eric Laurentd3b82232014-07-30 08:57:39 -07001061 dest.writeByte((byte)1);
1062 dest.writeInt(captureFormat.getSampleRate());
1063 dest.writeInt(captureFormat.getEncoding());
1064 dest.writeInt(captureFormat.getChannelMask());
1065 } else {
1066 dest.writeByte((byte)0);
1067 }
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -07001068 dest.writeBlob(data);
1069 }
1070
1071 @Override
1072 public int hashCode() {
1073 final int prime = 31;
1074 int result = 1;
1075 result = prime * result + (captureAvailable ? 1231 : 1237);
1076 result = prime * result + captureDelayMs;
1077 result = prime * result + capturePreambleMs;
1078 result = prime * result + captureSession;
Eric Laurentd3b82232014-07-30 08:57:39 -07001079 result = prime * result + (triggerInData ? 1231 : 1237);
1080 if (captureFormat != null) {
1081 result = prime * result + captureFormat.getSampleRate();
1082 result = prime * result + captureFormat.getEncoding();
1083 result = prime * result + captureFormat.getChannelMask();
1084 }
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -07001085 result = prime * result + Arrays.hashCode(data);
1086 result = prime * result + soundModelHandle;
1087 result = prime * result + status;
1088 return result;
1089 }
1090
1091 @Override
Aurimas Liutikas4d1699d2019-08-28 13:01:05 -07001092 public boolean equals(@Nullable Object obj) {
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -07001093 if (this == obj)
1094 return true;
1095 if (obj == null)
1096 return false;
1097 if (getClass() != obj.getClass())
1098 return false;
1099 RecognitionEvent other = (RecognitionEvent) obj;
1100 if (captureAvailable != other.captureAvailable)
1101 return false;
1102 if (captureDelayMs != other.captureDelayMs)
1103 return false;
1104 if (capturePreambleMs != other.capturePreambleMs)
1105 return false;
1106 if (captureSession != other.captureSession)
1107 return false;
1108 if (!Arrays.equals(data, other.data))
1109 return false;
1110 if (soundModelHandle != other.soundModelHandle)
1111 return false;
1112 if (status != other.status)
1113 return false;
Eric Laurentd3b82232014-07-30 08:57:39 -07001114 if (triggerInData != other.triggerInData)
1115 return false;
Ryan Bavettaea04e8f2016-03-02 18:34:50 -08001116 if (captureFormat == null) {
1117 if (other.captureFormat != null)
1118 return false;
1119 } else {
1120 if (other.captureFormat == null)
1121 return false;
1122 if (captureFormat.getSampleRate() != other.captureFormat.getSampleRate())
1123 return false;
1124 if (captureFormat.getEncoding() != other.captureFormat.getEncoding())
1125 return false;
1126 if (captureFormat.getChannelMask() != other.captureFormat.getChannelMask())
1127 return false;
1128 }
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -07001129 return true;
1130 }
Sandeep Siddhartha68173372014-07-28 13:25:30 -07001131
Aurimas Liutikas4d1699d2019-08-28 13:01:05 -07001132 @NonNull
Sandeep Siddhartha68173372014-07-28 13:25:30 -07001133 @Override
1134 public String toString() {
1135 return "RecognitionEvent [status=" + status + ", soundModelHandle=" + soundModelHandle
1136 + ", captureAvailable=" + captureAvailable + ", captureSession="
1137 + captureSession + ", captureDelayMs=" + captureDelayMs
1138 + ", capturePreambleMs=" + capturePreambleMs
Eric Laurentd3b82232014-07-30 08:57:39 -07001139 + ", triggerInData=" + triggerInData
1140 + ((captureFormat == null) ? "" :
1141 (", sampleRate=" + captureFormat.getSampleRate()))
1142 + ((captureFormat == null) ? "" :
1143 (", encoding=" + captureFormat.getEncoding()))
1144 + ((captureFormat == null) ? "" :
1145 (", channelMask=" + captureFormat.getChannelMask()))
Sandeep Siddhartha68173372014-07-28 13:25:30 -07001146 + ", data=" + (data == null ? 0 : data.length) + "]";
1147 }
Eric Laurente48188c2014-04-18 17:44:11 -07001148 }
1149
1150 /**
Eric Laurent013f66b2014-07-06 16:35:00 -07001151 * A RecognitionConfig is provided to
1152 * {@link SoundTriggerModule#startRecognition(int, RecognitionConfig)} to configure the
1153 * recognition request.
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -08001154 *
1155 * @hide
Eric Laurent013f66b2014-07-06 16:35:00 -07001156 */
Sandeep Siddhartha05589722014-07-17 16:21:54 -07001157 public static class RecognitionConfig implements Parcelable {
Eric Laurent013f66b2014-07-06 16:35:00 -07001158 /** True if the DSP should capture the trigger sound and make it available for further
1159 * capture. */
Mathew Inwoodbcbe4402018-08-08 15:42:59 +01001160 @UnsupportedAppUsage
Eric Laurent013f66b2014-07-06 16:35:00 -07001161 public final boolean captureRequested;
Sandeep Siddhartha2c0273e2014-08-01 11:32:03 -07001162 /**
1163 * True if the service should restart listening after the DSP triggers.
1164 * Note: This config flag is currently used at the service layer rather than by the DSP.
1165 */
1166 public final boolean allowMultipleTriggers;
Eric Laurent013f66b2014-07-06 16:35:00 -07001167 /** List of all keyphrases in the sound model for which recognition should be performed with
1168 * options for each keyphrase. */
Mathew Inwoodbcbe4402018-08-08 15:42:59 +01001169 @UnsupportedAppUsage
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -08001170 @NonNull
Eric Laurent013f66b2014-07-06 16:35:00 -07001171 public final KeyphraseRecognitionExtra keyphrases[];
1172 /** Opaque data for use by system applications who know about voice engine internals,
1173 * typically during enrollment. */
Mathew Inwoodbcbe4402018-08-08 15:42:59 +01001174 @UnsupportedAppUsage
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -08001175 @NonNull
Eric Laurent013f66b2014-07-06 16:35:00 -07001176 public final byte[] data;
1177
Nicholas Ambur7092a562019-12-16 11:18:55 -08001178 /**
1179 * Bit field encoding of the AudioCapabilities
1180 * supported by the firmware.
1181 */
1182 @ModuleProperties.AudioCapabilities
1183 public final int audioCapabilities;
1184
Sandeep Siddhartha2c0273e2014-08-01 11:32:03 -07001185 public RecognitionConfig(boolean captureRequested, boolean allowMultipleTriggers,
Nicholas Ambur7092a562019-12-16 11:18:55 -08001186 @Nullable KeyphraseRecognitionExtra[] keyphrases, @Nullable byte[] data,
1187 int audioCapabilities) {
Eric Laurent013f66b2014-07-06 16:35:00 -07001188 this.captureRequested = captureRequested;
Sandeep Siddhartha2c0273e2014-08-01 11:32:03 -07001189 this.allowMultipleTriggers = allowMultipleTriggers;
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -08001190 this.keyphrases = keyphrases != null ? keyphrases : new KeyphraseRecognitionExtra[0];
1191 this.data = data != null ? data : new byte[0];
Nicholas Ambur7092a562019-12-16 11:18:55 -08001192 this.audioCapabilities = audioCapabilities;
1193 }
1194
1195 @UnsupportedAppUsage
1196 public RecognitionConfig(boolean captureRequested, boolean allowMultipleTriggers,
1197 @Nullable KeyphraseRecognitionExtra[] keyphrases, @Nullable byte[] data) {
1198 this(captureRequested, allowMultipleTriggers, keyphrases, data, 0);
Eric Laurent013f66b2014-07-06 16:35:00 -07001199 }
Sandeep Siddhartha05589722014-07-17 16:21:54 -07001200
Jeff Sharkey9e8f83d2019-02-28 12:06:45 -07001201 public static final @android.annotation.NonNull Parcelable.Creator<RecognitionConfig> CREATOR
Sandeep Siddhartha05589722014-07-17 16:21:54 -07001202 = new Parcelable.Creator<RecognitionConfig>() {
1203 public RecognitionConfig createFromParcel(Parcel in) {
1204 return RecognitionConfig.fromParcel(in);
1205 }
1206
1207 public RecognitionConfig[] newArray(int size) {
1208 return new RecognitionConfig[size];
1209 }
1210 };
1211
1212 private static RecognitionConfig fromParcel(Parcel in) {
1213 boolean captureRequested = in.readByte() == 1;
Sandeep Siddhartha2c0273e2014-08-01 11:32:03 -07001214 boolean allowMultipleTriggers = in.readByte() == 1;
Sandeep Siddhartha05589722014-07-17 16:21:54 -07001215 KeyphraseRecognitionExtra[] keyphrases =
1216 in.createTypedArray(KeyphraseRecognitionExtra.CREATOR);
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -07001217 byte[] data = in.readBlob();
Nicholas Ambur7092a562019-12-16 11:18:55 -08001218 int audioCapabilities = in.readInt();
1219 return new RecognitionConfig(captureRequested, allowMultipleTriggers, keyphrases, data,
1220 audioCapabilities);
Sandeep Siddhartha05589722014-07-17 16:21:54 -07001221 }
1222
1223 @Override
1224 public void writeToParcel(Parcel dest, int flags) {
1225 dest.writeByte((byte) (captureRequested ? 1 : 0));
Sandeep Siddhartha2c0273e2014-08-01 11:32:03 -07001226 dest.writeByte((byte) (allowMultipleTriggers ? 1 : 0));
Sandeep Siddhartha68173372014-07-28 13:25:30 -07001227 dest.writeTypedArray(keyphrases, flags);
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -07001228 dest.writeBlob(data);
Nicholas Ambur7092a562019-12-16 11:18:55 -08001229 dest.writeInt(audioCapabilities);
Sandeep Siddhartha05589722014-07-17 16:21:54 -07001230 }
1231
1232 @Override
1233 public int describeContents() {
1234 return 0;
1235 }
Sandeep Siddhartha110f5692014-07-20 12:22:56 -07001236
1237 @Override
1238 public String toString() {
Sandeep Siddhartha2c0273e2014-08-01 11:32:03 -07001239 return "RecognitionConfig [captureRequested=" + captureRequested
1240 + ", allowMultipleTriggers=" + allowMultipleTriggers + ", keyphrases="
Nicholas Ambur7092a562019-12-16 11:18:55 -08001241 + Arrays.toString(keyphrases) + ", data=" + Arrays.toString(data)
1242 + ", audioCapabilities=" + Integer.toHexString(audioCapabilities) + "]";
Sandeep Siddhartha110f5692014-07-20 12:22:56 -07001243 }
Eric Laurent013f66b2014-07-06 16:35:00 -07001244 }
1245
1246 /**
1247 * Confidence level for users defined in a keyphrase.
1248 * - The confidence level is expressed in percent (0% -100%).
1249 * When used in a {@link KeyphraseRecognitionEvent} it indicates the detected confidence level
1250 * When used in a {@link RecognitionConfig} it indicates the minimum confidence level that
1251 * should trigger a recognition.
1252 * - The user ID is derived from the system ID {@link android.os.UserHandle#getIdentifier()}.
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -08001253 *
1254 * @hide
Eric Laurent013f66b2014-07-06 16:35:00 -07001255 */
Sandeep Siddhartha05589722014-07-17 16:21:54 -07001256 public static class ConfidenceLevel implements Parcelable {
Mathew Inwoodbcbe4402018-08-08 15:42:59 +01001257 @UnsupportedAppUsage
Eric Laurent013f66b2014-07-06 16:35:00 -07001258 public final int userId;
Mathew Inwoodbcbe4402018-08-08 15:42:59 +01001259 @UnsupportedAppUsage
Eric Laurent013f66b2014-07-06 16:35:00 -07001260 public final int confidenceLevel;
1261
Mathew Inwoodbcbe4402018-08-08 15:42:59 +01001262 @UnsupportedAppUsage
Eric Laurent013f66b2014-07-06 16:35:00 -07001263 public ConfidenceLevel(int userId, int confidenceLevel) {
1264 this.userId = userId;
1265 this.confidenceLevel = confidenceLevel;
1266 }
Sandeep Siddhartha05589722014-07-17 16:21:54 -07001267
Jeff Sharkey9e8f83d2019-02-28 12:06:45 -07001268 public static final @android.annotation.NonNull Parcelable.Creator<ConfidenceLevel> CREATOR
Sandeep Siddhartha05589722014-07-17 16:21:54 -07001269 = new Parcelable.Creator<ConfidenceLevel>() {
1270 public ConfidenceLevel createFromParcel(Parcel in) {
1271 return ConfidenceLevel.fromParcel(in);
1272 }
1273
1274 public ConfidenceLevel[] newArray(int size) {
1275 return new ConfidenceLevel[size];
1276 }
1277 };
1278
1279 private static ConfidenceLevel fromParcel(Parcel in) {
1280 int userId = in.readInt();
1281 int confidenceLevel = in.readInt();
1282 return new ConfidenceLevel(userId, confidenceLevel);
1283 }
1284
1285 @Override
1286 public void writeToParcel(Parcel dest, int flags) {
1287 dest.writeInt(userId);
1288 dest.writeInt(confidenceLevel);
1289 }
1290
1291 @Override
1292 public int describeContents() {
1293 return 0;
1294 }
Sandeep Siddhartha68173372014-07-28 13:25:30 -07001295
1296 @Override
1297 public int hashCode() {
1298 final int prime = 31;
1299 int result = 1;
1300 result = prime * result + confidenceLevel;
1301 result = prime * result + userId;
1302 return result;
1303 }
1304
1305 @Override
1306 public boolean equals(Object obj) {
1307 if (this == obj)
1308 return true;
1309 if (obj == null)
1310 return false;
1311 if (getClass() != obj.getClass())
1312 return false;
1313 ConfidenceLevel other = (ConfidenceLevel) obj;
1314 if (confidenceLevel != other.confidenceLevel)
1315 return false;
1316 if (userId != other.userId)
1317 return false;
1318 return true;
1319 }
1320
1321 @Override
1322 public String toString() {
1323 return "ConfidenceLevel [userId=" + userId
1324 + ", confidenceLevel=" + confidenceLevel + "]";
1325 }
Eric Laurent013f66b2014-07-06 16:35:00 -07001326 }
1327
1328 /**
Sandeep Siddharthad4233c62014-06-12 18:31:19 -07001329 * Additional data conveyed by a {@link KeyphraseRecognitionEvent}
Eric Laurente48188c2014-04-18 17:44:11 -07001330 * for a key phrase detection.
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -08001331 *
1332 * @hide
Eric Laurente48188c2014-04-18 17:44:11 -07001333 */
Sandeep Siddhartha05589722014-07-17 16:21:54 -07001334 public static class KeyphraseRecognitionExtra implements Parcelable {
1335 /** The keyphrase ID */
Mathew Inwoodbcbe4402018-08-08 15:42:59 +01001336 @UnsupportedAppUsage
Eric Laurent013f66b2014-07-06 16:35:00 -07001337 public final int id;
Eric Laurente48188c2014-04-18 17:44:11 -07001338
1339 /** Recognition modes matched for this event */
Mathew Inwoodbcbe4402018-08-08 15:42:59 +01001340 @UnsupportedAppUsage
Eric Laurente48188c2014-04-18 17:44:11 -07001341 public final int recognitionModes;
1342
Eric Laurentd3b82232014-07-30 08:57:39 -07001343 /** Confidence level for mode RECOGNITION_MODE_VOICE_TRIGGER when user identification
1344 * is not performed */
Mathew Inwoodbcbe4402018-08-08 15:42:59 +01001345 @UnsupportedAppUsage
Eric Laurentd3b82232014-07-30 08:57:39 -07001346 public final int coarseConfidenceLevel;
1347
Eric Laurent013f66b2014-07-06 16:35:00 -07001348 /** Confidence levels for all users recognized (KeyphraseRecognitionEvent) or to
1349 * be recognized (RecognitionConfig) */
Mathew Inwoodbcbe4402018-08-08 15:42:59 +01001350 @UnsupportedAppUsage
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -08001351 @NonNull
Eric Laurent013f66b2014-07-06 16:35:00 -07001352 public final ConfidenceLevel[] confidenceLevels;
1353
Mathew Inwoodbcbe4402018-08-08 15:42:59 +01001354 @UnsupportedAppUsage
Eric Laurentd3b82232014-07-30 08:57:39 -07001355 public KeyphraseRecognitionExtra(int id, int recognitionModes, int coarseConfidenceLevel,
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -08001356 @Nullable ConfidenceLevel[] confidenceLevels) {
Eric Laurent013f66b2014-07-06 16:35:00 -07001357 this.id = id;
Eric Laurente48188c2014-04-18 17:44:11 -07001358 this.recognitionModes = recognitionModes;
Eric Laurentd3b82232014-07-30 08:57:39 -07001359 this.coarseConfidenceLevel = coarseConfidenceLevel;
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -08001360 this.confidenceLevels =
1361 confidenceLevels != null ? confidenceLevels : new ConfidenceLevel[0];
Eric Laurente48188c2014-04-18 17:44:11 -07001362 }
Sandeep Siddhartha05589722014-07-17 16:21:54 -07001363
Jeff Sharkey9e8f83d2019-02-28 12:06:45 -07001364 public static final @android.annotation.NonNull Parcelable.Creator<KeyphraseRecognitionExtra> CREATOR
Sandeep Siddhartha05589722014-07-17 16:21:54 -07001365 = new Parcelable.Creator<KeyphraseRecognitionExtra>() {
1366 public KeyphraseRecognitionExtra createFromParcel(Parcel in) {
1367 return KeyphraseRecognitionExtra.fromParcel(in);
1368 }
1369
1370 public KeyphraseRecognitionExtra[] newArray(int size) {
1371 return new KeyphraseRecognitionExtra[size];
1372 }
1373 };
1374
1375 private static KeyphraseRecognitionExtra fromParcel(Parcel in) {
1376 int id = in.readInt();
1377 int recognitionModes = in.readInt();
Eric Laurentd3b82232014-07-30 08:57:39 -07001378 int coarseConfidenceLevel = in.readInt();
Sandeep Siddhartha05589722014-07-17 16:21:54 -07001379 ConfidenceLevel[] confidenceLevels = in.createTypedArray(ConfidenceLevel.CREATOR);
Eric Laurentd3b82232014-07-30 08:57:39 -07001380 return new KeyphraseRecognitionExtra(id, recognitionModes, coarseConfidenceLevel,
1381 confidenceLevels);
Sandeep Siddhartha05589722014-07-17 16:21:54 -07001382 }
1383
1384 @Override
1385 public void writeToParcel(Parcel dest, int flags) {
1386 dest.writeInt(id);
1387 dest.writeInt(recognitionModes);
Eric Laurentd3b82232014-07-30 08:57:39 -07001388 dest.writeInt(coarseConfidenceLevel);
Sandeep Siddhartha68173372014-07-28 13:25:30 -07001389 dest.writeTypedArray(confidenceLevels, flags);
Sandeep Siddhartha05589722014-07-17 16:21:54 -07001390 }
1391
1392 @Override
1393 public int describeContents() {
1394 return 0;
1395 }
Sandeep Siddhartha68173372014-07-28 13:25:30 -07001396
1397 @Override
1398 public int hashCode() {
1399 final int prime = 31;
1400 int result = 1;
1401 result = prime * result + Arrays.hashCode(confidenceLevels);
1402 result = prime * result + id;
1403 result = prime * result + recognitionModes;
Eric Laurentd3b82232014-07-30 08:57:39 -07001404 result = prime * result + coarseConfidenceLevel;
Sandeep Siddhartha68173372014-07-28 13:25:30 -07001405 return result;
1406 }
1407
1408 @Override
1409 public boolean equals(Object obj) {
1410 if (this == obj)
1411 return true;
1412 if (obj == null)
1413 return false;
1414 if (getClass() != obj.getClass())
1415 return false;
1416 KeyphraseRecognitionExtra other = (KeyphraseRecognitionExtra) obj;
1417 if (!Arrays.equals(confidenceLevels, other.confidenceLevels))
1418 return false;
1419 if (id != other.id)
1420 return false;
1421 if (recognitionModes != other.recognitionModes)
1422 return false;
Eric Laurentd3b82232014-07-30 08:57:39 -07001423 if (coarseConfidenceLevel != other.coarseConfidenceLevel)
1424 return false;
Sandeep Siddhartha68173372014-07-28 13:25:30 -07001425 return true;
1426 }
1427
1428 @Override
1429 public String toString() {
1430 return "KeyphraseRecognitionExtra [id=" + id + ", recognitionModes=" + recognitionModes
Eric Laurentd3b82232014-07-30 08:57:39 -07001431 + ", coarseConfidenceLevel=" + coarseConfidenceLevel
Sandeep Siddhartha68173372014-07-28 13:25:30 -07001432 + ", confidenceLevels=" + Arrays.toString(confidenceLevels) + "]";
1433 }
Eric Laurente48188c2014-04-18 17:44:11 -07001434 }
1435
1436 /**
1437 * Specialized {@link RecognitionEvent} for a key phrase detection.
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -08001438 *
1439 * @hide
Eric Laurente48188c2014-04-18 17:44:11 -07001440 */
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -08001441 public static class KeyphraseRecognitionEvent extends RecognitionEvent implements Parcelable {
Eric Laurente48188c2014-04-18 17:44:11 -07001442 /** Indicates if the key phrase is present in the buffered audio available for capture */
Mathew Inwoodbcbe4402018-08-08 15:42:59 +01001443 @UnsupportedAppUsage
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -08001444 @NonNull
Sandeep Siddharthad4233c62014-06-12 18:31:19 -07001445 public final KeyphraseRecognitionExtra[] keyphraseExtras;
Eric Laurente48188c2014-04-18 17:44:11 -07001446
Mathew Inwoodbcbe4402018-08-08 15:42:59 +01001447 @UnsupportedAppUsage
Sandeep Siddhartha68173372014-07-28 13:25:30 -07001448 public KeyphraseRecognitionEvent(int status, int soundModelHandle, boolean captureAvailable,
Eric Laurentd3b82232014-07-30 08:57:39 -07001449 int captureSession, int captureDelayMs, int capturePreambleMs,
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -08001450 boolean triggerInData, @NonNull AudioFormat captureFormat, @Nullable byte[] data,
1451 @Nullable KeyphraseRecognitionExtra[] keyphraseExtras) {
Eric Laurent013f66b2014-07-06 16:35:00 -07001452 super(status, soundModelHandle, captureAvailable, captureSession, captureDelayMs,
Eric Laurentd3b82232014-07-30 08:57:39 -07001453 capturePreambleMs, triggerInData, captureFormat, data);
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -08001454 this.keyphraseExtras =
1455 keyphraseExtras != null ? keyphraseExtras : new KeyphraseRecognitionExtra[0];
Eric Laurente48188c2014-04-18 17:44:11 -07001456 }
Sandeep Siddhartha68173372014-07-28 13:25:30 -07001457
Jeff Sharkey9e8f83d2019-02-28 12:06:45 -07001458 public static final @android.annotation.NonNull Parcelable.Creator<KeyphraseRecognitionEvent> CREATOR
Sandeep Siddhartha68173372014-07-28 13:25:30 -07001459 = new Parcelable.Creator<KeyphraseRecognitionEvent>() {
1460 public KeyphraseRecognitionEvent createFromParcel(Parcel in) {
Arunesh Mishraf47f1732016-02-18 16:16:12 -08001461 return KeyphraseRecognitionEvent.fromParcelForKeyphrase(in);
Sandeep Siddhartha68173372014-07-28 13:25:30 -07001462 }
1463
1464 public KeyphraseRecognitionEvent[] newArray(int size) {
1465 return new KeyphraseRecognitionEvent[size];
1466 }
1467 };
1468
Arunesh Mishraf47f1732016-02-18 16:16:12 -08001469 private static KeyphraseRecognitionEvent fromParcelForKeyphrase(Parcel in) {
Sandeep Siddhartha68173372014-07-28 13:25:30 -07001470 int status = in.readInt();
1471 int soundModelHandle = in.readInt();
1472 boolean captureAvailable = in.readByte() == 1;
1473 int captureSession = in.readInt();
1474 int captureDelayMs = in.readInt();
1475 int capturePreambleMs = in.readInt();
Eric Laurentd3b82232014-07-30 08:57:39 -07001476 boolean triggerInData = in.readByte() == 1;
1477 AudioFormat captureFormat = null;
Eric Laurent75b433f2014-09-12 15:45:47 -07001478 if (in.readByte() == 1) {
Eric Laurentd3b82232014-07-30 08:57:39 -07001479 int sampleRate = in.readInt();
1480 int encoding = in.readInt();
1481 int channelMask = in.readInt();
1482 captureFormat = (new AudioFormat.Builder())
Ryan Bavettaea04e8f2016-03-02 18:34:50 -08001483 .setChannelMask(channelMask)
1484 .setEncoding(encoding)
1485 .setSampleRate(sampleRate)
1486 .build();
Eric Laurentd3b82232014-07-30 08:57:39 -07001487 }
Sandeep Siddhartha68173372014-07-28 13:25:30 -07001488 byte[] data = in.readBlob();
Sandeep Siddhartha68173372014-07-28 13:25:30 -07001489 KeyphraseRecognitionExtra[] keyphraseExtras =
1490 in.createTypedArray(KeyphraseRecognitionExtra.CREATOR);
1491 return new KeyphraseRecognitionEvent(status, soundModelHandle, captureAvailable,
Eric Laurentd3b82232014-07-30 08:57:39 -07001492 captureSession, captureDelayMs, capturePreambleMs, triggerInData,
1493 captureFormat, data, keyphraseExtras);
Sandeep Siddhartha68173372014-07-28 13:25:30 -07001494 }
1495
1496 @Override
1497 public void writeToParcel(Parcel dest, int flags) {
1498 dest.writeInt(status);
1499 dest.writeInt(soundModelHandle);
1500 dest.writeByte((byte) (captureAvailable ? 1 : 0));
1501 dest.writeInt(captureSession);
1502 dest.writeInt(captureDelayMs);
1503 dest.writeInt(capturePreambleMs);
Eric Laurent75b433f2014-09-12 15:45:47 -07001504 dest.writeByte((byte) (triggerInData ? 1 : 0));
1505 if (captureFormat != null) {
Eric Laurentd3b82232014-07-30 08:57:39 -07001506 dest.writeByte((byte)1);
1507 dest.writeInt(captureFormat.getSampleRate());
1508 dest.writeInt(captureFormat.getEncoding());
1509 dest.writeInt(captureFormat.getChannelMask());
1510 } else {
1511 dest.writeByte((byte)0);
1512 }
Sandeep Siddhartha68173372014-07-28 13:25:30 -07001513 dest.writeBlob(data);
Sandeep Siddhartha68173372014-07-28 13:25:30 -07001514 dest.writeTypedArray(keyphraseExtras, flags);
1515 }
1516
1517 @Override
1518 public int describeContents() {
1519 return 0;
1520 }
1521
1522 @Override
1523 public int hashCode() {
1524 final int prime = 31;
1525 int result = super.hashCode();
1526 result = prime * result + Arrays.hashCode(keyphraseExtras);
Sandeep Siddhartha68173372014-07-28 13:25:30 -07001527 return result;
1528 }
1529
1530 @Override
1531 public boolean equals(Object obj) {
1532 if (this == obj)
1533 return true;
1534 if (!super.equals(obj))
1535 return false;
1536 if (getClass() != obj.getClass())
1537 return false;
1538 KeyphraseRecognitionEvent other = (KeyphraseRecognitionEvent) obj;
1539 if (!Arrays.equals(keyphraseExtras, other.keyphraseExtras))
1540 return false;
Sandeep Siddhartha68173372014-07-28 13:25:30 -07001541 return true;
1542 }
1543
1544 @Override
1545 public String toString() {
1546 return "KeyphraseRecognitionEvent [keyphraseExtras=" + Arrays.toString(keyphraseExtras)
Eric Laurentd3b82232014-07-30 08:57:39 -07001547 + ", status=" + status
Sandeep Siddhartha68173372014-07-28 13:25:30 -07001548 + ", soundModelHandle=" + soundModelHandle + ", captureAvailable="
1549 + captureAvailable + ", captureSession=" + captureSession + ", captureDelayMs="
1550 + captureDelayMs + ", capturePreambleMs=" + capturePreambleMs
Eric Laurentd3b82232014-07-30 08:57:39 -07001551 + ", triggerInData=" + triggerInData
1552 + ((captureFormat == null) ? "" :
1553 (", sampleRate=" + captureFormat.getSampleRate()))
1554 + ((captureFormat == null) ? "" :
1555 (", encoding=" + captureFormat.getEncoding()))
1556 + ((captureFormat == null) ? "" :
1557 (", channelMask=" + captureFormat.getChannelMask()))
Sandeep Siddhartha68173372014-07-28 13:25:30 -07001558 + ", data=" + (data == null ? 0 : data.length) + "]";
1559 }
Eric Laurente48188c2014-04-18 17:44:11 -07001560 }
1561
1562 /**
Arunesh Mishraa772e5f2016-01-25 10:33:11 -08001563 * Sub-class of RecognitionEvent specifically for sound-trigger based sound
1564 * models(non-keyphrase). Currently does not contain any additional fields.
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -08001565 *
1566 * @hide
Arunesh Mishraa772e5f2016-01-25 10:33:11 -08001567 */
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -08001568 public static class GenericRecognitionEvent extends RecognitionEvent implements Parcelable {
Mathew Inwoodbcbe4402018-08-08 15:42:59 +01001569 @UnsupportedAppUsage
Arunesh Mishraa772e5f2016-01-25 10:33:11 -08001570 public GenericRecognitionEvent(int status, int soundModelHandle,
1571 boolean captureAvailable, int captureSession, int captureDelayMs,
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -08001572 int capturePreambleMs, boolean triggerInData, @NonNull AudioFormat captureFormat,
1573 @Nullable byte[] data) {
Arunesh Mishraa772e5f2016-01-25 10:33:11 -08001574 super(status, soundModelHandle, captureAvailable, captureSession,
1575 captureDelayMs, capturePreambleMs, triggerInData, captureFormat,
1576 data);
1577 }
Arunesh Mishraf47f1732016-02-18 16:16:12 -08001578
Jeff Sharkey9e8f83d2019-02-28 12:06:45 -07001579 public static final @android.annotation.NonNull Parcelable.Creator<GenericRecognitionEvent> CREATOR
Arunesh Mishraf47f1732016-02-18 16:16:12 -08001580 = new Parcelable.Creator<GenericRecognitionEvent>() {
1581 public GenericRecognitionEvent createFromParcel(Parcel in) {
1582 return GenericRecognitionEvent.fromParcelForGeneric(in);
1583 }
1584
1585 public GenericRecognitionEvent[] newArray(int size) {
1586 return new GenericRecognitionEvent[size];
1587 }
1588 };
1589
1590 private static GenericRecognitionEvent fromParcelForGeneric(Parcel in) {
1591 RecognitionEvent event = RecognitionEvent.fromParcel(in);
1592 return new GenericRecognitionEvent(event.status, event.soundModelHandle,
1593 event.captureAvailable, event.captureSession, event.captureDelayMs,
1594 event.capturePreambleMs, event.triggerInData, event.captureFormat, event.data);
1595 }
1596
1597 @Override
1598 public boolean equals(Object obj) {
1599 if (this == obj)
1600 return true;
1601 if (obj == null)
1602 return false;
1603 if (getClass() != obj.getClass()) return false;
1604 RecognitionEvent other = (RecognitionEvent) obj;
1605 return super.equals(obj);
1606 }
1607
1608 @Override
1609 public String toString() {
1610 return "GenericRecognitionEvent ::" + super.toString();
1611 }
Arunesh Mishraa772e5f2016-01-25 10:33:11 -08001612 }
1613
1614 /**
Eric Laurentd3b82232014-07-30 08:57:39 -07001615 * Status codes for {@link SoundModelEvent}
1616 */
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -08001617 /**
1618 * Sound Model was updated
1619 *
1620 * @hide
1621 */
Eric Laurentd3b82232014-07-30 08:57:39 -07001622 public static final int SOUNDMODEL_STATUS_UPDATED = 0;
1623
1624 /**
1625 * A SoundModelEvent is provided by the
1626 * {@link StatusListener#onSoundModelUpdate(SoundModelEvent)}
1627 * callback when a sound model has been updated by the implementation
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -08001628 *
1629 * @hide
Eric Laurentd3b82232014-07-30 08:57:39 -07001630 */
1631 public static class SoundModelEvent implements Parcelable {
1632 /** Status e.g {@link #SOUNDMODEL_STATUS_UPDATED} */
1633 public final int status;
1634 /** The updated sound model handle */
1635 public final int soundModelHandle;
1636 /** New sound model data */
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -08001637 @NonNull
Eric Laurentd3b82232014-07-30 08:57:39 -07001638 public final byte[] data;
1639
Mathew Inwoodbcbe4402018-08-08 15:42:59 +01001640 @UnsupportedAppUsage
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -08001641 SoundModelEvent(int status, int soundModelHandle, @Nullable byte[] data) {
Eric Laurentd3b82232014-07-30 08:57:39 -07001642 this.status = status;
1643 this.soundModelHandle = soundModelHandle;
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -08001644 this.data = data != null ? data : new byte[0];
Eric Laurentd3b82232014-07-30 08:57:39 -07001645 }
1646
Jeff Sharkey9e8f83d2019-02-28 12:06:45 -07001647 public static final @android.annotation.NonNull Parcelable.Creator<SoundModelEvent> CREATOR
Eric Laurentd3b82232014-07-30 08:57:39 -07001648 = new Parcelable.Creator<SoundModelEvent>() {
1649 public SoundModelEvent createFromParcel(Parcel in) {
1650 return SoundModelEvent.fromParcel(in);
1651 }
1652
1653 public SoundModelEvent[] newArray(int size) {
1654 return new SoundModelEvent[size];
1655 }
1656 };
1657
1658 private static SoundModelEvent fromParcel(Parcel in) {
1659 int status = in.readInt();
1660 int soundModelHandle = in.readInt();
1661 byte[] data = in.readBlob();
1662 return new SoundModelEvent(status, soundModelHandle, data);
1663 }
1664
1665 @Override
1666 public int describeContents() {
1667 return 0;
1668 }
1669
1670 @Override
1671 public void writeToParcel(Parcel dest, int flags) {
1672 dest.writeInt(status);
1673 dest.writeInt(soundModelHandle);
1674 dest.writeBlob(data);
1675 }
1676
1677 @Override
1678 public int hashCode() {
1679 final int prime = 31;
1680 int result = 1;
1681 result = prime * result + Arrays.hashCode(data);
1682 result = prime * result + soundModelHandle;
1683 result = prime * result + status;
1684 return result;
1685 }
1686
1687 @Override
1688 public boolean equals(Object obj) {
1689 if (this == obj)
1690 return true;
1691 if (obj == null)
1692 return false;
1693 if (getClass() != obj.getClass())
1694 return false;
1695 SoundModelEvent other = (SoundModelEvent) obj;
1696 if (!Arrays.equals(data, other.data))
1697 return false;
1698 if (soundModelHandle != other.soundModelHandle)
1699 return false;
1700 if (status != other.status)
1701 return false;
1702 return true;
1703 }
1704
1705 @Override
1706 public String toString() {
1707 return "SoundModelEvent [status=" + status + ", soundModelHandle=" + soundModelHandle
1708 + ", data=" + (data == null ? 0 : data.length) + "]";
1709 }
1710 }
1711
1712 /**
1713 * Native service state. {@link StatusListener#onServiceStateChange(int)}
1714 */
1715 // Keep in sync with system/core/include/system/sound_trigger.h
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -08001716 /**
1717 * Sound trigger service is enabled
1718 *
1719 * @hide
1720 */
Eric Laurentd3b82232014-07-30 08:57:39 -07001721 public static final int SERVICE_STATE_ENABLED = 0;
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -08001722 /**
1723 * Sound trigger service is disabled
1724 *
1725 * @hide
1726 */
Eric Laurentd3b82232014-07-30 08:57:39 -07001727 public static final int SERVICE_STATE_DISABLED = 1;
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -08001728 private static Object mServiceLock = new Object();
1729 private static ISoundTriggerMiddlewareService mService;
1730 /**
jiabin1f4b4dd2019-03-18 18:07:03 -07001731 * @return returns current package name.
1732 */
1733 static String getCurrentOpPackageName() {
1734 String packageName = ActivityThread.currentOpPackageName();
1735 if (packageName == null) {
1736 return "";
1737 }
1738 return packageName;
1739 }
1740
1741 /**
Ytai Ben-Tsvi2e8f78b2020-01-15 11:57:34 -08001742 * Translate an exception thrown from interaction with the underlying service to an error code.
1743 * Throws a runtime exception for unexpected conditions.
1744 * @param e The caught exception.
1745 * @return The error code.
1746 *
1747 * @hide
1748 */
1749 static int handleException(Exception e) {
1750 Log.w(TAG, "Exception caught", e);
1751 if (e instanceof RemoteException) {
1752 return STATUS_DEAD_OBJECT;
1753 }
1754 if (e instanceof ServiceSpecificException) {
1755 switch (((ServiceSpecificException) e).errorCode) {
1756 case Status.OPERATION_NOT_SUPPORTED:
1757 return STATUS_INVALID_OPERATION;
1758 case Status.TEMPORARY_PERMISSION_DENIED:
1759 return STATUS_PERMISSION_DENIED;
1760 case Status.DEAD_OBJECT:
1761 return STATUS_DEAD_OBJECT;
1762 }
1763 return STATUS_ERROR;
1764 }
1765 if (e instanceof SecurityException) {
1766 return STATUS_PERMISSION_DENIED;
1767 }
1768 if (e instanceof IllegalStateException) {
1769 return STATUS_INVALID_OPERATION;
1770 }
1771 if (e instanceof IllegalArgumentException || e instanceof NullPointerException) {
1772 return STATUS_BAD_VALUE;
1773 }
1774 // This is not one of the conditions represented by our error code, escalate to a
1775 // RuntimeException.
1776 Log.e(TAG, "Escalating unexpected exception: ", e);
1777 throw new RuntimeException(e);
1778 }
1779
1780 /**
Arunesh Mishraa772e5f2016-01-25 10:33:11 -08001781 * Returns a list of descriptors for all hardware modules loaded.
Eric Laurente48188c2014-04-18 17:44:11 -07001782 * @param modules A ModuleProperties array where the list will be returned.
1783 * @return - {@link #STATUS_OK} in case of success
1784 * - {@link #STATUS_ERROR} in case of unspecified error
1785 * - {@link #STATUS_PERMISSION_DENIED} if the caller does not have system permission
1786 * - {@link #STATUS_NO_INIT} if the native service cannot be reached
1787 * - {@link #STATUS_BAD_VALUE} if modules is null
1788 * - {@link #STATUS_DEAD_OBJECT} if the binder transaction to the native service fails
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -08001789 *
1790 * @hide
Eric Laurente48188c2014-04-18 17:44:11 -07001791 */
Mathew Inwoodbcbe4402018-08-08 15:42:59 +01001792 @UnsupportedAppUsage
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -08001793 public static int listModules(@NonNull ArrayList<ModuleProperties> modules) {
1794 try {
1795 SoundTriggerModuleDescriptor[] descs = getService().listModules();
1796 modules.clear();
1797 modules.ensureCapacity(descs.length);
1798 for (SoundTriggerModuleDescriptor desc : descs) {
1799 modules.add(ConversionUtil.aidl2apiModuleDescriptor(desc));
1800 }
1801 return STATUS_OK;
Ytai Ben-Tsvi2e8f78b2020-01-15 11:57:34 -08001802 } catch (Exception e) {
1803 return handleException(e);
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -08001804 }
jiabin1f4b4dd2019-03-18 18:07:03 -07001805 }
1806
1807 /**
Eric Laurente48188c2014-04-18 17:44:11 -07001808 * Get an interface on a hardware module to control sound models and recognition on
1809 * this module.
1810 * @param moduleId Sound module system identifier {@link ModuleProperties#id}. mandatory.
1811 * @param listener {@link StatusListener} interface. Mandatory.
1812 * @param handler the Handler that will receive the callabcks. Can be null if default handler
1813 * is OK.
1814 * @return a valid sound module in case of success or null in case of error.
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -08001815 *
1816 * @hide
Eric Laurente48188c2014-04-18 17:44:11 -07001817 */
Mathew Inwoodbcbe4402018-08-08 15:42:59 +01001818 @UnsupportedAppUsage
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -08001819 public static @NonNull SoundTriggerModule attachModule(int moduleId,
1820 @NonNull StatusListener listener,
1821 @Nullable Handler handler) {
1822 Looper looper = handler != null ? handler.getLooper() : Looper.getMainLooper();
1823 try {
1824 return new SoundTriggerModule(getService(), moduleId, listener, looper);
1825 } catch (RemoteException e) {
1826 Log.e(TAG, "", e);
Eric Laurente48188c2014-04-18 17:44:11 -07001827 return null;
1828 }
Ytai Ben-Tsvi7d383d12019-11-25 12:47:40 -08001829 }
1830
1831 private static ISoundTriggerMiddlewareService getService() {
1832 synchronized (mServiceLock) {
1833 while (true) {
1834 IBinder binder = null;
1835 try {
1836 binder =
1837 ServiceManager.getServiceOrThrow(
1838 Context.SOUND_TRIGGER_MIDDLEWARE_SERVICE);
1839 binder.linkToDeath(() -> {
1840 synchronized (mServiceLock) {
1841 mService = null;
1842 }
1843 }, 0);
1844 mService = ISoundTriggerMiddlewareService.Stub.asInterface(binder);
1845 break;
1846 } catch (Exception e) {
1847 Log.e(TAG, "Failed to bind to soundtrigger service", e);
1848 }
1849 }
1850 return mService;
1851 }
1852
Eric Laurente48188c2014-04-18 17:44:11 -07001853 }
1854
1855 /**
1856 * Interface provided by the client application when attaching to a {@link SoundTriggerModule}
1857 * to received recognition and error notifications.
Philip P. Moltmanna5fd0292018-03-06 13:44:07 -08001858 *
1859 * @hide
Eric Laurente48188c2014-04-18 17:44:11 -07001860 */
1861 public static interface StatusListener {
1862 /**
1863 * Called when recognition succeeds of fails
1864 */
1865 public abstract void onRecognition(RecognitionEvent event);
1866
1867 /**
Eric Laurentd3b82232014-07-30 08:57:39 -07001868 * Called when a sound model has been updated
1869 */
1870 public abstract void onSoundModelUpdate(SoundModelEvent event);
1871
1872 /**
1873 * Called when the sound trigger native service state changes.
1874 * @param state Native service state. One of {@link SoundTrigger#SERVICE_STATE_ENABLED},
1875 * {@link SoundTrigger#SERVICE_STATE_DISABLED}
1876 */
1877 public abstract void onServiceStateChange(int state);
1878
1879 /**
Eric Laurente48188c2014-04-18 17:44:11 -07001880 * Called when the sound trigger native service dies
1881 */
1882 public abstract void onServiceDied();
1883 }
1884}