1 /*
2  * Copyright (C) 2021 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 
17 package android.service.voice;
18 
19 import android.annotation.IntDef;
20 import android.annotation.NonNull;
21 import android.annotation.Nullable;
22 import android.annotation.SuppressLint;
23 import android.annotation.SystemApi;
24 import android.content.res.Resources;
25 import android.media.AudioRecord;
26 import android.media.MediaSyncEvent;
27 import android.os.Parcel;
28 import android.os.Parcelable;
29 import android.os.PersistableBundle;
30 
31 import com.android.internal.R;
32 import com.android.internal.util.DataClass;
33 import com.android.internal.util.Preconditions;
34 
35 import java.lang.annotation.Retention;
36 import java.lang.annotation.RetentionPolicy;
37 import java.util.ArrayList;
38 import java.util.Collections;
39 import java.util.List;
40 import java.util.Objects;
41 
42 /**
43  * Represents a result supporting the hotword detection.
44  *
45  * @hide
46  */
47 @DataClass(
48         genConstructor = false,
49         genBuilder = true,
50         genEqualsHashCode = true,
51         genHiddenConstDefs = true,
52         genParcelable = true,
53         genToString = true
54 )
55 @SystemApi
56 public final class HotwordDetectedResult implements Parcelable {
57 
58     /** No confidence in hotword detector result. */
59     public static final int CONFIDENCE_LEVEL_NONE = 0;
60 
61     /** Low confidence in hotword detector result. */
62     public static final int CONFIDENCE_LEVEL_LOW = 1;
63 
64     /** Low-to-medium confidence in hotword detector result. */
65     public static final int CONFIDENCE_LEVEL_LOW_MEDIUM = 2;
66 
67     /** Medium confidence in hotword detector result. */
68     public static final int CONFIDENCE_LEVEL_MEDIUM = 3;
69 
70     /** Medium-to-high confidence in hotword detector result. */
71     public static final int CONFIDENCE_LEVEL_MEDIUM_HIGH = 4;
72 
73     /** High confidence in hotword detector result. */
74     public static final int CONFIDENCE_LEVEL_HIGH = 5;
75 
76     /** Very high confidence in hotword detector result. */
77     public static final int CONFIDENCE_LEVEL_VERY_HIGH = 6;
78 
79     /** @hide */
80     @IntDef(prefix = {"CONFIDENCE_LEVEL_"}, value = {
81             CONFIDENCE_LEVEL_NONE,
82             CONFIDENCE_LEVEL_LOW,
83             CONFIDENCE_LEVEL_LOW_MEDIUM,
84             CONFIDENCE_LEVEL_MEDIUM,
85             CONFIDENCE_LEVEL_MEDIUM_HIGH,
86             CONFIDENCE_LEVEL_HIGH,
87             CONFIDENCE_LEVEL_VERY_HIGH
88     })
89     @Retention(RetentionPolicy.SOURCE)
90     @interface HotwordConfidenceLevelValue {
91     }
92 
93     /** Represents unset value for the hotword offset. */
94     public static final int HOTWORD_OFFSET_UNSET = -1;
95 
96     /** Represents unset value for the triggered audio channel. */
97     public static final int AUDIO_CHANNEL_UNSET = -1;
98 
99     /** Represents unset value for the background audio signal power. */
100     public static final int BACKGROUND_AUDIO_POWER_UNSET = -1;
101 
102     /** Limits the max value for the hotword offset. */
103     private static final int LIMIT_HOTWORD_OFFSET_MAX_VALUE = 60 * 60 * 1000; // 1 hour
104 
105     /** Limits the max value for the triggered audio channel. */
106     private static final int LIMIT_AUDIO_CHANNEL_MAX_VALUE = 63;
107 
108     /**
109      * The bundle key for proximity
110      *
111      * TODO(b/238896013): Move the proximity logic out of bundle to proper API.
112      */
113     private static final String EXTRA_PROXIMITY =
114             "android.service.voice.extra.PROXIMITY";
115 
116     /** Users’ proximity is unknown (proximity sensing was inconclusive and is unsupported). */
117     public static final int PROXIMITY_UNKNOWN = -1;
118 
119     /** Proximity value that represents that the object is near. */
120     public static final int PROXIMITY_NEAR = 1;
121 
122     /** Proximity value that represents that the object is far. */
123     public static final int PROXIMITY_FAR = 2;
124 
125     /** @hide */
126     @IntDef(prefix = {"PROXIMITY"}, value = {
127             PROXIMITY_UNKNOWN,
128             PROXIMITY_NEAR,
129             PROXIMITY_FAR
130     })
131     @Retention(RetentionPolicy.SOURCE)
132     public @interface ProximityValue {}
133 
134     /** Id of the current speaker
135      *
136      * <p>Only values between 0 and {@link #getMaxSpeakerId} (inclusive) are accepted.
137      */
138     private final int mSpeakerId;
defaultSpeakerId()139     private static int defaultSpeakerId() {
140         return 0;
141     }
142 
143     /** Maximum number of active speaker ids. **/
144     @SuppressLint("UnflaggedApi") // b/325678077 flags not supported in isolated process
getMaxSpeakerId()145     public static int getMaxSpeakerId() {
146         return 15;
147     }
148 
149     /** Confidence level in the trigger outcome. */
150     @HotwordConfidenceLevelValue
151     private final int mConfidenceLevel;
defaultConfidenceLevel()152     private static int defaultConfidenceLevel() {
153         return CONFIDENCE_LEVEL_NONE;
154     }
155 
156     /**
157      * A {@code MediaSyncEvent} that allows the {@link HotwordDetector} to recapture the audio
158      * that contains the hotword trigger. This must be obtained using
159      * {@link android.media.AudioRecord#shareAudioHistory(String, long)}.
160      */
161     @Nullable
162     private MediaSyncEvent mMediaSyncEvent = null;
163 
164     /**
165      * Offset in milliseconds the audio stream when the trigger event happened (end of hotword
166      * phrase).
167      *
168      * <p>Only value between 0 and 3600000 (inclusive) is accepted.
169      */
170     private int mHotwordOffsetMillis = HOTWORD_OFFSET_UNSET;
171 
172     /**
173      * Duration in milliseconds of the hotword trigger phrase.
174      *
175      * <p>Only values between 0 and {@link android.media.AudioRecord#getMaxSharedAudioHistoryMillis}
176      * (inclusive) are accepted.
177      */
178     private int mHotwordDurationMillis = 0;
179 
180     /**
181      * Audio channel containing the highest-confidence hotword signal.
182      *
183      * <p>Only value between 0 and 63 (inclusive) is accepted.
184      */
185     private int mAudioChannel = AUDIO_CHANNEL_UNSET;
186 
187     /**
188      * Returns whether the trigger has happened due to model having been personalized to fit user's
189      * voice.
190      */
191     private boolean mHotwordDetectionPersonalized = false;
192 
193     /**
194      * Score for the hotword trigger.
195      *
196      * <p>Only values between 0 and {@link #getMaxScore} (inclusive) are accepted.
197      */
198     private final int mScore;
defaultScore()199     private static int defaultScore() {
200         return 0;
201     }
202 
203     /**
204      * Score for the hotword trigger for device user.
205      *
206      * <p>Only values between 0 and {@link #getMaxScore} (inclusive) are accepted.
207      */
208     private final int mPersonalizedScore;
defaultPersonalizedScore()209     private static int defaultPersonalizedScore() {
210         return 0;
211     }
212 
213     /**
214      * Returns the maximum values of {@link #getScore} and {@link #getPersonalizedScore}.
215      * <p>
216      * The float value should be calculated as {@code getScore() / getMaxScore()}.
217      */
getMaxScore()218     public static int getMaxScore() {
219         return 255;
220     }
221 
222     /**
223      * An ID representing the keyphrase that triggered the successful detection.
224      *
225      * <p>Only values between 0 and {@link #getMaxHotwordPhraseId()} (inclusive) are accepted.
226      */
227     private final int mHotwordPhraseId;
defaultHotwordPhraseId()228     private static int defaultHotwordPhraseId() {
229         return 0;
230     }
231 
232     /**
233      * Returns the maximum value of {@link #getHotwordPhraseId()}.
234      */
getMaxHotwordPhraseId()235     public static int getMaxHotwordPhraseId() {
236         return 63;
237     }
238 
239     /**
240      * The list of the audio streams containing audio bytes that were used for hotword detection.
241      */
242     @NonNull
243     private final List<HotwordAudioStream> mAudioStreams;
defaultAudioStreams()244     private static List<HotwordAudioStream> defaultAudioStreams() {
245         return Collections.emptyList();
246     }
247 
248     /**
249      * App-specific extras to support trigger.
250      *
251      * <p>The size of this bundle will be limited to {@link #getMaxBundleSize}. Results will larger
252      * bundles will be rejected.
253      *
254      * <p>Only primitive types are supported in this bundle. Complex types will be removed from the
255      * bundle.
256      *
257      * <p>The use of this method is discouraged, and support for it will be removed in future
258      * versions of Android.
259      *
260      * <p>After the trigger happens, a special case of proximity-related extra, with the key of
261      * 'android.service.voice.extra.PROXIMITY_VALUE' and the value of proximity value (integer)
262      * will be stored to enable proximity logic. {@link HotwordDetectedResult#PROXIMITY_NEAR} will
263      * indicate 'NEAR' proximity and {@link HotwordDetectedResult#PROXIMITY_FAR} will indicate 'FAR'
264      * proximity. The proximity value is provided by the system, on devices that support detecting
265      * proximity of nearby users, to help disambiguate which nearby device should respond. When the
266      * proximity is unknown, the proximity value will not be stored. This mapping will be excluded
267      * from the max bundle size calculation because this mapping is included after the result is
268      * returned from the hotword detector service.
269      *
270      * <p>This is a PersistableBundle so it doesn't allow any remotable objects or other contents
271      * that can be used to communicate with other processes.
272      */
273     @NonNull
274     private final PersistableBundle mExtras;
defaultExtras()275     private static PersistableBundle defaultExtras() {
276         return new PersistableBundle();
277     }
278 
279     private static int sMaxBundleSize = -1;
280 
281     /**
282      * Returns the maximum byte size of the information contained in the bundle.
283      *
284      * <p>The total size will be calculated by how much bundle data should be written into the
285      * Parcel.
286      */
getMaxBundleSize()287     public static int getMaxBundleSize() {
288         if (sMaxBundleSize < 0) {
289             sMaxBundleSize = Resources.getSystem().getInteger(
290                     R.integer.config_hotwordDetectedResultMaxBundleSize);
291         }
292         return sMaxBundleSize;
293     }
294 
295     /**
296      * A {@code MediaSyncEvent} that allows the {@link HotwordDetector} to recapture the audio
297      * that contains the hotword trigger. This must be obtained using
298      * {@link android.media.AudioRecord#shareAudioHistory(String, long)}.
299      * <p>
300      * This can be {@code null} if reprocessing the hotword trigger isn't required.
301      */
302     // Suppress codegen to make javadoc consistent. Getter returns @Nullable, setter accepts
303     // @NonNull only, and by default codegen would use the same javadoc on both.
getMediaSyncEvent()304     public @Nullable MediaSyncEvent getMediaSyncEvent() {
305         return mMediaSyncEvent;
306     }
307 
308     /**
309      * Power of the background audio signal in which the hotword phrase was detected.
310      *
311      * <p> Only values between 0 and {@link #getMaxBackgroundAudioPower} (inclusive)
312      * and the special value {@link #BACKGROUND_AUDIO_POWER_UNSET} are valid.
313      *
314      * <p> This value is unitless. The relation between this value and the real audio signal
315      * power measured in decibels depends on the hotword detection service implementation.
316      */
317     private final int mBackgroundAudioPower;
defaultBackgroundAudioPower()318     private static int defaultBackgroundAudioPower() {
319         return BACKGROUND_AUDIO_POWER_UNSET;
320     }
321 
322     /**
323      * Returns the maximum value of {@link #getBackgroundAudioPower()}.
324      */
getMaxBackgroundAudioPower()325     public static int getMaxBackgroundAudioPower() {
326         return 255;
327     }
328 
329     /**
330      * Returns how many bytes should be written into the Parcel
331      *
332      * @hide
333      */
getParcelableSize(@onNull Parcelable parcelable)334     public static int getParcelableSize(@NonNull Parcelable parcelable) {
335         final Parcel p = Parcel.obtain();
336         parcelable.writeToParcel(p, 0);
337         p.setDataPosition(0);
338         final int size = p.dataSize();
339         p.recycle();
340         return size;
341     }
342 
343     /**
344      * Returns how many bits have been written into the HotwordDetectedResult.
345      *
346      * @hide
347      */
getUsageSize(@onNull HotwordDetectedResult hotwordDetectedResult)348     public static int getUsageSize(@NonNull HotwordDetectedResult hotwordDetectedResult) {
349         int totalBits = 0;
350 
351         if (hotwordDetectedResult.getConfidenceLevel() != defaultConfidenceLevel()) {
352             totalBits += bitCount(CONFIDENCE_LEVEL_VERY_HIGH);
353         }
354         if (hotwordDetectedResult.getHotwordOffsetMillis() != HOTWORD_OFFSET_UNSET) {
355             totalBits += bitCount(LIMIT_HOTWORD_OFFSET_MAX_VALUE);
356         }
357         if (hotwordDetectedResult.getHotwordDurationMillis() != 0) {
358             totalBits += bitCount(AudioRecord.getMaxSharedAudioHistoryMillis());
359         }
360         if (hotwordDetectedResult.getAudioChannel() != AUDIO_CHANNEL_UNSET) {
361             totalBits += bitCount(LIMIT_AUDIO_CHANNEL_MAX_VALUE);
362         }
363 
364         // Add one bit for HotwordDetectionPersonalized
365         totalBits += 1;
366 
367         if (hotwordDetectedResult.getScore() != defaultScore()) {
368             totalBits += bitCount(HotwordDetectedResult.getMaxScore());
369         }
370         if (hotwordDetectedResult.getPersonalizedScore() != defaultPersonalizedScore()) {
371             totalBits += bitCount(HotwordDetectedResult.getMaxScore());
372         }
373         if (hotwordDetectedResult.getHotwordPhraseId() != defaultHotwordPhraseId()) {
374             totalBits += bitCount(HotwordDetectedResult.getMaxHotwordPhraseId());
375         }
376         PersistableBundle persistableBundle = hotwordDetectedResult.getExtras();
377         if (!persistableBundle.isEmpty()) {
378             totalBits += getParcelableSize(persistableBundle) * Byte.SIZE;
379         }
380         if (hotwordDetectedResult.getBackgroundAudioPower() != defaultBackgroundAudioPower()) {
381             totalBits += bitCount(HotwordDetectedResult.getMaxBackgroundAudioPower());
382         }
383 
384         return totalBits;
385     }
386 
bitCount(long value)387     private static int bitCount(long value) {
388         int bits = 0;
389         while (value > 0) {
390             bits++;
391             value = value >> 1;
392         }
393         return bits;
394     }
395 
onConstructed()396     private void onConstructed() {
397         Preconditions.checkArgumentInRange(mSpeakerId, 0, getMaxSpeakerId(), "speakerId");
398         Preconditions.checkArgumentInRange(mScore, 0, getMaxScore(), "score");
399         Preconditions.checkArgumentInRange(mPersonalizedScore, 0, getMaxScore(),
400                 "personalizedScore");
401         Preconditions.checkArgumentInRange(mHotwordPhraseId, 0, getMaxHotwordPhraseId(),
402                 "hotwordPhraseId");
403         if (mBackgroundAudioPower != BACKGROUND_AUDIO_POWER_UNSET) {
404             Preconditions.checkArgumentInRange(mBackgroundAudioPower,
405                     0, getMaxBackgroundAudioPower(), "backgroundAudioPower");
406         }
407         Preconditions.checkArgumentInRange((long) mHotwordDurationMillis, 0,
408                 AudioRecord.getMaxSharedAudioHistoryMillis(), "hotwordDurationMillis");
409         if (mHotwordOffsetMillis != HOTWORD_OFFSET_UNSET) {
410             Preconditions.checkArgumentInRange(mHotwordOffsetMillis, 0,
411                     LIMIT_HOTWORD_OFFSET_MAX_VALUE, "hotwordOffsetMillis");
412         }
413         if (mAudioChannel != AUDIO_CHANNEL_UNSET) {
414             Preconditions.checkArgumentInRange(mAudioChannel, 0, LIMIT_AUDIO_CHANNEL_MAX_VALUE,
415                     "audioChannel");
416         }
417         if (!mExtras.isEmpty()) {
418             // Remove the proximity key from the bundle before checking the bundle size. The
419             // proximity value is added after the privileged module and can avoid the
420             // maxBundleSize limitation.
421             if (mExtras.containsKey(EXTRA_PROXIMITY)) {
422                 int proximityValue = mExtras.getInt(EXTRA_PROXIMITY);
423                 mExtras.remove(EXTRA_PROXIMITY);
424                 // Skip checking parcelable size if the new bundle size is 0. Newly empty bundle
425                 // has parcelable size of 4, but the default bundle has parcelable size of 0.
426                 if (mExtras.size() > 0) {
427                     Preconditions.checkArgumentInRange(getParcelableSize(mExtras), 0,
428                             getMaxBundleSize(), "extras");
429                 }
430                 mExtras.putInt(EXTRA_PROXIMITY, proximityValue);
431             } else {
432                 Preconditions.checkArgumentInRange(getParcelableSize(mExtras), 0,
433                         getMaxBundleSize(), "extras");
434             }
435         }
436     }
437 
438     /**
439      * The list of the audio streams containing audio bytes that were used for hotword detection.
440      */
getAudioStreams()441     public @NonNull List<HotwordAudioStream> getAudioStreams() {
442         return List.copyOf(mAudioStreams);
443     }
444 
445     /**
446      * Adds proximity level, either near or far, that is mapped for the given distance into
447      * the bundle. The proximity value is provided by the system, on devices that support detecting
448      * proximity of nearby users, to help disambiguate which nearby device should respond.
449      * This mapping will be excluded from the max bundle size calculation because this mapping is
450      * included after the result is returned from the hotword detector service. The value will not
451      * be included if the proximity was unknown.
452      *
453      * @hide
454      */
setProximity(double distance)455     public void setProximity(double distance) {
456         int proximityLevel = convertToProximityLevel(distance);
457         if (proximityLevel != PROXIMITY_UNKNOWN) {
458             mExtras.putInt(EXTRA_PROXIMITY, proximityLevel);
459         }
460     }
461 
462     /**
463      * Returns proximity level, which can be either of {@link HotwordDetectedResult#PROXIMITY_NEAR}
464      * or {@link HotwordDetectedResult#PROXIMITY_FAR}. If the proximity is unknown, it will
465      * return {@link HotwordDetectedResult#PROXIMITY_UNKNOWN}.
466      */
467     @ProximityValue
getProximity()468     public int getProximity() {
469         return mExtras.getInt(EXTRA_PROXIMITY, PROXIMITY_UNKNOWN);
470     }
471 
472     /**
473      * Mapping of the proximity distance (meters) to proximity values, unknown, near, and far.
474      * Currently, this mapping is handled by HotwordDetectedResult because it handles just
475      * HotwordDetectionConnection which we know the mapping of. However, the mapping will need to
476      * move to a more centralized place once there are more clients.
477      *
478      * TODO(b/258531144): Move the proximity mapping to a central location
479      */
480     @ProximityValue
convertToProximityLevel(double distance)481     private int convertToProximityLevel(double distance) {
482         if (distance < 0) {
483             return PROXIMITY_UNKNOWN;
484         } else if (distance <= 3) {
485             return PROXIMITY_NEAR;
486         } else {
487             return PROXIMITY_FAR;
488         }
489     }
490 
491     @DataClass.Suppress("addAudioStreams")
492     abstract static class BaseBuilder {
493         /**
494          * The list of the audio streams containing audio bytes that were used for hotword
495          * detection.
496          */
setAudioStreams(@onNull List<HotwordAudioStream> value)497         public @NonNull Builder setAudioStreams(@NonNull List<HotwordAudioStream> value) {
498             Objects.requireNonNull(value, "value should not be null");
499             final Builder builder = (Builder) this;
500             // If the code gen flag in build() is changed, we must update the flag e.g. 0x400 here.
501             builder.mBuilderFieldsSet |= 0x400;
502             builder.mAudioStreams = List.copyOf(value);
503             return builder;
504         }
505     }
506 
507     /**
508      * Provides an instance of {@link Builder} with state corresponding to this instance.
509      * @hide
510      */
buildUpon()511     public Builder buildUpon() {
512         return new Builder()
513             .setConfidenceLevel(mConfidenceLevel)
514             .setMediaSyncEvent(mMediaSyncEvent)
515             .setHotwordOffsetMillis(mHotwordOffsetMillis)
516             .setHotwordDurationMillis(mHotwordDurationMillis)
517             .setAudioChannel(mAudioChannel)
518             .setHotwordDetectionPersonalized(mHotwordDetectionPersonalized)
519             .setScore(mScore)
520             .setPersonalizedScore(mPersonalizedScore)
521             .setHotwordPhraseId(mHotwordPhraseId)
522             .setAudioStreams(mAudioStreams)
523             .setExtras(mExtras)
524             .setBackgroundAudioPower(mBackgroundAudioPower)
525             .setSpeakerId(mSpeakerId);
526     }
527 
528 
529 
530     // Code below generated by codegen v1.0.23.
531     //
532     // DO NOT MODIFY!
533     // CHECKSTYLE:OFF Generated code
534     //
535     // To regenerate run:
536     // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/service/voice/HotwordDetectedResult.java
537     //
538     // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
539     //   Settings > Editor > Code Style > Formatter Control
540     //@formatter:off
541 
542 
543     /** @hide */
544     @IntDef(prefix = "CONFIDENCE_LEVEL_", value = {
545         CONFIDENCE_LEVEL_NONE,
546         CONFIDENCE_LEVEL_LOW,
547         CONFIDENCE_LEVEL_LOW_MEDIUM,
548         CONFIDENCE_LEVEL_MEDIUM,
549         CONFIDENCE_LEVEL_MEDIUM_HIGH,
550         CONFIDENCE_LEVEL_HIGH,
551         CONFIDENCE_LEVEL_VERY_HIGH
552     })
553     @Retention(RetentionPolicy.SOURCE)
554     @DataClass.Generated.Member
555     public @interface ConfidenceLevel {}
556 
557     /** @hide */
558     @DataClass.Generated.Member
confidenceLevelToString(@onfidenceLevel int value)559     public static String confidenceLevelToString(@ConfidenceLevel int value) {
560         switch (value) {
561             case CONFIDENCE_LEVEL_NONE:
562                     return "CONFIDENCE_LEVEL_NONE";
563             case CONFIDENCE_LEVEL_LOW:
564                     return "CONFIDENCE_LEVEL_LOW";
565             case CONFIDENCE_LEVEL_LOW_MEDIUM:
566                     return "CONFIDENCE_LEVEL_LOW_MEDIUM";
567             case CONFIDENCE_LEVEL_MEDIUM:
568                     return "CONFIDENCE_LEVEL_MEDIUM";
569             case CONFIDENCE_LEVEL_MEDIUM_HIGH:
570                     return "CONFIDENCE_LEVEL_MEDIUM_HIGH";
571             case CONFIDENCE_LEVEL_HIGH:
572                     return "CONFIDENCE_LEVEL_HIGH";
573             case CONFIDENCE_LEVEL_VERY_HIGH:
574                     return "CONFIDENCE_LEVEL_VERY_HIGH";
575             default: return Integer.toHexString(value);
576         }
577     }
578 
579     /** @hide */
580     @IntDef(prefix = "LIMIT_", value = {
581         LIMIT_HOTWORD_OFFSET_MAX_VALUE,
582         LIMIT_AUDIO_CHANNEL_MAX_VALUE
583     })
584     @Retention(RetentionPolicy.SOURCE)
585     @DataClass.Generated.Member
586     /* package-private */ @interface Limit {}
587 
588     /** @hide */
589     @DataClass.Generated.Member
limitToString(@imit int value)590     /* package-private */ static String limitToString(@Limit int value) {
591         switch (value) {
592             case LIMIT_HOTWORD_OFFSET_MAX_VALUE:
593                     return "LIMIT_HOTWORD_OFFSET_MAX_VALUE";
594             case LIMIT_AUDIO_CHANNEL_MAX_VALUE:
595                     return "LIMIT_AUDIO_CHANNEL_MAX_VALUE";
596             default: return Integer.toHexString(value);
597         }
598     }
599 
600     /** @hide */
601     @IntDef(prefix = "PROXIMITY_", value = {
602         PROXIMITY_UNKNOWN,
603         PROXIMITY_NEAR,
604         PROXIMITY_FAR
605     })
606     @Retention(RetentionPolicy.SOURCE)
607     @DataClass.Generated.Member
608     public @interface Proximity {}
609 
610     /** @hide */
611     @DataClass.Generated.Member
proximityToString(@roximity int value)612     public static String proximityToString(@Proximity int value) {
613         switch (value) {
614             case PROXIMITY_UNKNOWN:
615                     return "PROXIMITY_UNKNOWN";
616             case PROXIMITY_NEAR:
617                     return "PROXIMITY_NEAR";
618             case PROXIMITY_FAR:
619                     return "PROXIMITY_FAR";
620             default: return Integer.toHexString(value);
621         }
622     }
623 
624     @DataClass.Generated.Member
HotwordDetectedResult( int speakerId, @HotwordConfidenceLevelValue int confidenceLevel, @Nullable MediaSyncEvent mediaSyncEvent, int hotwordOffsetMillis, int hotwordDurationMillis, int audioChannel, boolean hotwordDetectionPersonalized, int score, int personalizedScore, int hotwordPhraseId, @NonNull List<HotwordAudioStream> audioStreams, @NonNull PersistableBundle extras, int backgroundAudioPower)625     /* package-private */ HotwordDetectedResult(
626             int speakerId,
627             @HotwordConfidenceLevelValue int confidenceLevel,
628             @Nullable MediaSyncEvent mediaSyncEvent,
629             int hotwordOffsetMillis,
630             int hotwordDurationMillis,
631             int audioChannel,
632             boolean hotwordDetectionPersonalized,
633             int score,
634             int personalizedScore,
635             int hotwordPhraseId,
636             @NonNull List<HotwordAudioStream> audioStreams,
637             @NonNull PersistableBundle extras,
638             int backgroundAudioPower) {
639         this.mSpeakerId = speakerId;
640         this.mConfidenceLevel = confidenceLevel;
641         com.android.internal.util.AnnotationValidations.validate(
642                 HotwordConfidenceLevelValue.class, null, mConfidenceLevel);
643         this.mMediaSyncEvent = mediaSyncEvent;
644         this.mHotwordOffsetMillis = hotwordOffsetMillis;
645         this.mHotwordDurationMillis = hotwordDurationMillis;
646         this.mAudioChannel = audioChannel;
647         this.mHotwordDetectionPersonalized = hotwordDetectionPersonalized;
648         this.mScore = score;
649         this.mPersonalizedScore = personalizedScore;
650         this.mHotwordPhraseId = hotwordPhraseId;
651         this.mAudioStreams = audioStreams;
652         com.android.internal.util.AnnotationValidations.validate(
653                 NonNull.class, null, mAudioStreams);
654         this.mExtras = extras;
655         com.android.internal.util.AnnotationValidations.validate(
656                 NonNull.class, null, mExtras);
657         this.mBackgroundAudioPower = backgroundAudioPower;
658 
659         onConstructed();
660     }
661 
662     /**
663      * Id of the current speaker
664      *
665      * <p>Only values between 0 and {@link #getMaxSpeakerId} (inclusive) are accepted.
666      */
667     @DataClass.Generated.Member
668     @SuppressLint("UnflaggedApi") // b/325678077 flags not supported in isolated process
getSpeakerId()669     public int getSpeakerId() {
670         return mSpeakerId;
671     }
672 
673     /**
674      * Confidence level in the trigger outcome.
675      */
676     @DataClass.Generated.Member
getConfidenceLevel()677     public @HotwordConfidenceLevelValue int getConfidenceLevel() {
678         return mConfidenceLevel;
679     }
680 
681     /**
682      * Offset in milliseconds the audio stream when the trigger event happened (end of hotword
683      * phrase).
684      *
685      * <p>Only value between 0 and 3600000 (inclusive) is accepted.
686      */
687     @DataClass.Generated.Member
getHotwordOffsetMillis()688     public int getHotwordOffsetMillis() {
689         return mHotwordOffsetMillis;
690     }
691 
692     /**
693      * Duration in milliseconds of the hotword trigger phrase.
694      *
695      * <p>Only values between 0 and {@link android.media.AudioRecord#getMaxSharedAudioHistoryMillis}
696      * (inclusive) are accepted.
697      */
698     @DataClass.Generated.Member
getHotwordDurationMillis()699     public int getHotwordDurationMillis() {
700         return mHotwordDurationMillis;
701     }
702 
703     /**
704      * Audio channel containing the highest-confidence hotword signal.
705      *
706      * <p>Only value between 0 and 63 (inclusive) is accepted.
707      */
708     @DataClass.Generated.Member
getAudioChannel()709     public int getAudioChannel() {
710         return mAudioChannel;
711     }
712 
713     /**
714      * Returns whether the trigger has happened due to model having been personalized to fit user's
715      * voice.
716      */
717     @DataClass.Generated.Member
isHotwordDetectionPersonalized()718     public boolean isHotwordDetectionPersonalized() {
719         return mHotwordDetectionPersonalized;
720     }
721 
722     /**
723      * Score for the hotword trigger.
724      *
725      * <p>Only values between 0 and {@link #getMaxScore} (inclusive) are accepted.
726      */
727     @DataClass.Generated.Member
getScore()728     public int getScore() {
729         return mScore;
730     }
731 
732     /**
733      * Score for the hotword trigger for device user.
734      *
735      * <p>Only values between 0 and {@link #getMaxScore} (inclusive) are accepted.
736      */
737     @DataClass.Generated.Member
getPersonalizedScore()738     public int getPersonalizedScore() {
739         return mPersonalizedScore;
740     }
741 
742     /**
743      * An ID representing the keyphrase that triggered the successful detection.
744      *
745      * <p>Only values between 0 and {@link #getMaxHotwordPhraseId()} (inclusive) are accepted.
746      */
747     @DataClass.Generated.Member
getHotwordPhraseId()748     public int getHotwordPhraseId() {
749         return mHotwordPhraseId;
750     }
751 
752     /**
753      * App-specific extras to support trigger.
754      *
755      * <p>The size of this bundle will be limited to {@link #getMaxBundleSize}. Results will larger
756      * bundles will be rejected.
757      *
758      * <p>Only primitive types are supported in this bundle. Complex types will be removed from the
759      * bundle.
760      *
761      * <p>The use of this method is discouraged, and support for it will be removed in future
762      * versions of Android.
763      *
764      * <p>After the trigger happens, a special case of proximity-related extra, with the key of
765      * 'android.service.voice.extra.PROXIMITY_VALUE' and the value of proximity value (integer)
766      * will be stored to enable proximity logic. {@link HotwordDetectedResult#PROXIMITY_NEAR} will
767      * indicate 'NEAR' proximity and {@link HotwordDetectedResult#PROXIMITY_FAR} will indicate 'FAR'
768      * proximity. The proximity value is provided by the system, on devices that support detecting
769      * proximity of nearby users, to help disambiguate which nearby device should respond. When the
770      * proximity is unknown, the proximity value will not be stored. This mapping will be excluded
771      * from the max bundle size calculation because this mapping is included after the result is
772      * returned from the hotword detector service.
773      *
774      * <p>This is a PersistableBundle so it doesn't allow any remotable objects or other contents
775      * that can be used to communicate with other processes.
776      */
777     @DataClass.Generated.Member
getExtras()778     public @NonNull PersistableBundle getExtras() {
779         return mExtras;
780     }
781 
782     /**
783      * Power of the background audio signal in which the hotword phrase was detected.
784      *
785      * <p> Only values between 0 and {@link #getMaxBackgroundAudioPower} (inclusive)
786      * and the special value {@link #BACKGROUND_AUDIO_POWER_UNSET} are valid.
787      *
788      * <p> This value is unitless. The relation between this value and the real audio signal
789      * power measured in decibels depends on the hotword detection service implementation.
790      */
791     @DataClass.Generated.Member
getBackgroundAudioPower()792     public int getBackgroundAudioPower() {
793         return mBackgroundAudioPower;
794     }
795 
796     @Override
797     @DataClass.Generated.Member
toString()798     public String toString() {
799         // You can override field toString logic by defining methods like:
800         // String fieldNameToString() { ... }
801 
802         return "HotwordDetectedResult { " +
803                 "speakerId = " + mSpeakerId + ", " +
804                 "confidenceLevel = " + mConfidenceLevel + ", " +
805                 "mediaSyncEvent = " + mMediaSyncEvent + ", " +
806                 "hotwordOffsetMillis = " + mHotwordOffsetMillis + ", " +
807                 "hotwordDurationMillis = " + mHotwordDurationMillis + ", " +
808                 "audioChannel = " + mAudioChannel + ", " +
809                 "hotwordDetectionPersonalized = " + mHotwordDetectionPersonalized + ", " +
810                 "score = " + mScore + ", " +
811                 "personalizedScore = " + mPersonalizedScore + ", " +
812                 "hotwordPhraseId = " + mHotwordPhraseId + ", " +
813                 "audioStreams = " + mAudioStreams + ", " +
814                 "extras = " + mExtras + ", " +
815                 "backgroundAudioPower = " + mBackgroundAudioPower +
816         " }";
817     }
818 
819     @Override
820     @DataClass.Generated.Member
equals(@ullable Object o)821     public boolean equals(@Nullable Object o) {
822         // You can override field equality logic by defining either of the methods like:
823         // boolean fieldNameEquals(HotwordDetectedResult other) { ... }
824         // boolean fieldNameEquals(FieldType otherValue) { ... }
825 
826         if (this == o) return true;
827         if (o == null || getClass() != o.getClass()) return false;
828         @SuppressWarnings("unchecked")
829         HotwordDetectedResult that = (HotwordDetectedResult) o;
830         //noinspection PointlessBooleanExpression
831         return true
832                 && mSpeakerId == that.mSpeakerId
833                 && mConfidenceLevel == that.mConfidenceLevel
834                 && Objects.equals(mMediaSyncEvent, that.mMediaSyncEvent)
835                 && mHotwordOffsetMillis == that.mHotwordOffsetMillis
836                 && mHotwordDurationMillis == that.mHotwordDurationMillis
837                 && mAudioChannel == that.mAudioChannel
838                 && mHotwordDetectionPersonalized == that.mHotwordDetectionPersonalized
839                 && mScore == that.mScore
840                 && mPersonalizedScore == that.mPersonalizedScore
841                 && mHotwordPhraseId == that.mHotwordPhraseId
842                 && Objects.equals(mAudioStreams, that.mAudioStreams)
843                 && Objects.equals(mExtras, that.mExtras)
844                 && mBackgroundAudioPower == that.mBackgroundAudioPower;
845     }
846 
847     @Override
848     @DataClass.Generated.Member
hashCode()849     public int hashCode() {
850         // You can override field hashCode logic by defining methods like:
851         // int fieldNameHashCode() { ... }
852 
853         int _hash = 1;
854         _hash = 31 * _hash + mSpeakerId;
855         _hash = 31 * _hash + mConfidenceLevel;
856         _hash = 31 * _hash + Objects.hashCode(mMediaSyncEvent);
857         _hash = 31 * _hash + mHotwordOffsetMillis;
858         _hash = 31 * _hash + mHotwordDurationMillis;
859         _hash = 31 * _hash + mAudioChannel;
860         _hash = 31 * _hash + Boolean.hashCode(mHotwordDetectionPersonalized);
861         _hash = 31 * _hash + mScore;
862         _hash = 31 * _hash + mPersonalizedScore;
863         _hash = 31 * _hash + mHotwordPhraseId;
864         _hash = 31 * _hash + Objects.hashCode(mAudioStreams);
865         _hash = 31 * _hash + Objects.hashCode(mExtras);
866         _hash = 31 * _hash + mBackgroundAudioPower;
867         return _hash;
868     }
869 
870     @Override
871     @DataClass.Generated.Member
writeToParcel(@onNull Parcel dest, int flags)872     public void writeToParcel(@NonNull Parcel dest, int flags) {
873         // You can override field parcelling by defining methods like:
874         // void parcelFieldName(Parcel dest, int flags) { ... }
875 
876         int flg = 0;
877         if (mHotwordDetectionPersonalized) flg |= 0x40;
878         if (mMediaSyncEvent != null) flg |= 0x4;
879         dest.writeInt(flg);
880         dest.writeInt(mSpeakerId);
881         dest.writeInt(mConfidenceLevel);
882         if (mMediaSyncEvent != null) dest.writeTypedObject(mMediaSyncEvent, flags);
883         dest.writeInt(mHotwordOffsetMillis);
884         dest.writeInt(mHotwordDurationMillis);
885         dest.writeInt(mAudioChannel);
886         dest.writeInt(mScore);
887         dest.writeInt(mPersonalizedScore);
888         dest.writeInt(mHotwordPhraseId);
889         dest.writeParcelableList(mAudioStreams, flags);
890         dest.writeTypedObject(mExtras, flags);
891         dest.writeInt(mBackgroundAudioPower);
892     }
893 
894     @Override
895     @DataClass.Generated.Member
describeContents()896     public int describeContents() { return 0; }
897 
898     /** @hide */
899     @SuppressWarnings({"unchecked", "RedundantCast"})
900     @DataClass.Generated.Member
HotwordDetectedResult(@onNull Parcel in)901     /* package-private */ HotwordDetectedResult(@NonNull Parcel in) {
902         // You can override field unparcelling by defining methods like:
903         // static FieldType unparcelFieldName(Parcel in) { ... }
904 
905         int flg = in.readInt();
906         boolean hotwordDetectionPersonalized = (flg & 0x40) != 0;
907         int speakerId = in.readInt();
908         int confidenceLevel = in.readInt();
909         MediaSyncEvent mediaSyncEvent = (flg & 0x4) == 0 ? null : (MediaSyncEvent) in.readTypedObject(MediaSyncEvent.CREATOR);
910         int hotwordOffsetMillis = in.readInt();
911         int hotwordDurationMillis = in.readInt();
912         int audioChannel = in.readInt();
913         int score = in.readInt();
914         int personalizedScore = in.readInt();
915         int hotwordPhraseId = in.readInt();
916         List<HotwordAudioStream> audioStreams = new ArrayList<>();
917         in.readParcelableList(audioStreams, HotwordAudioStream.class.getClassLoader());
918         PersistableBundle extras = (PersistableBundle) in.readTypedObject(PersistableBundle.CREATOR);
919         int backgroundAudioPower = in.readInt();
920 
921         this.mSpeakerId = speakerId;
922         this.mConfidenceLevel = confidenceLevel;
923         com.android.internal.util.AnnotationValidations.validate(
924                 HotwordConfidenceLevelValue.class, null, mConfidenceLevel);
925         this.mMediaSyncEvent = mediaSyncEvent;
926         this.mHotwordOffsetMillis = hotwordOffsetMillis;
927         this.mHotwordDurationMillis = hotwordDurationMillis;
928         this.mAudioChannel = audioChannel;
929         this.mHotwordDetectionPersonalized = hotwordDetectionPersonalized;
930         this.mScore = score;
931         this.mPersonalizedScore = personalizedScore;
932         this.mHotwordPhraseId = hotwordPhraseId;
933         this.mAudioStreams = audioStreams;
934         com.android.internal.util.AnnotationValidations.validate(
935                 NonNull.class, null, mAudioStreams);
936         this.mExtras = extras;
937         com.android.internal.util.AnnotationValidations.validate(
938                 NonNull.class, null, mExtras);
939         this.mBackgroundAudioPower = backgroundAudioPower;
940 
941         onConstructed();
942     }
943 
944     @DataClass.Generated.Member
945     public static final @NonNull Parcelable.Creator<HotwordDetectedResult> CREATOR
946             = new Parcelable.Creator<HotwordDetectedResult>() {
947         @Override
948         public HotwordDetectedResult[] newArray(int size) {
949             return new HotwordDetectedResult[size];
950         }
951 
952         @Override
953         public HotwordDetectedResult createFromParcel(@NonNull Parcel in) {
954             return new HotwordDetectedResult(in);
955         }
956     };
957 
958     /**
959      * A builder for {@link HotwordDetectedResult}
960      */
961     @SuppressWarnings("WeakerAccess")
962     @DataClass.Generated.Member
963     public static final class Builder extends BaseBuilder {
964 
965         private int mSpeakerId;
966         private @HotwordConfidenceLevelValue int mConfidenceLevel;
967         private @Nullable MediaSyncEvent mMediaSyncEvent;
968         private int mHotwordOffsetMillis;
969         private int mHotwordDurationMillis;
970         private int mAudioChannel;
971         private boolean mHotwordDetectionPersonalized;
972         private int mScore;
973         private int mPersonalizedScore;
974         private int mHotwordPhraseId;
975         private @NonNull List<HotwordAudioStream> mAudioStreams;
976         private @NonNull PersistableBundle mExtras;
977         private int mBackgroundAudioPower;
978 
979         private long mBuilderFieldsSet = 0L;
980 
Builder()981         public Builder() {
982         }
983 
984         /**
985          * Id of the current speaker
986          *
987          * <p>Only values between 0 and {@link #getMaxSpeakerId} (inclusive) are accepted.
988          */
989         @DataClass.Generated.Member
990         @SuppressLint("UnflaggedApi") // b/325678077 flags not supported in isolated process
setSpeakerId(int value)991         public @NonNull Builder setSpeakerId(int value) {
992             checkNotUsed();
993             mBuilderFieldsSet |= 0x1;
994             mSpeakerId = value;
995             return this;
996         }
997 
998         /**
999          * Confidence level in the trigger outcome.
1000          */
1001         @DataClass.Generated.Member
setConfidenceLevel(@otwordConfidenceLevelValue int value)1002         public @NonNull Builder setConfidenceLevel(@HotwordConfidenceLevelValue int value) {
1003             checkNotUsed();
1004             mBuilderFieldsSet |= 0x2;
1005             mConfidenceLevel = value;
1006             return this;
1007         }
1008 
1009         /**
1010          * A {@code MediaSyncEvent} that allows the {@link HotwordDetector} to recapture the audio
1011          * that contains the hotword trigger. This must be obtained using
1012          * {@link android.media.AudioRecord#shareAudioHistory(String, long)}.
1013          */
1014         @DataClass.Generated.Member
setMediaSyncEvent(@onNull MediaSyncEvent value)1015         public @NonNull Builder setMediaSyncEvent(@NonNull MediaSyncEvent value) {
1016             checkNotUsed();
1017             mBuilderFieldsSet |= 0x4;
1018             mMediaSyncEvent = value;
1019             return this;
1020         }
1021 
1022         /**
1023          * Offset in milliseconds the audio stream when the trigger event happened (end of hotword
1024          * phrase).
1025          *
1026          * <p>Only value between 0 and 3600000 (inclusive) is accepted.
1027          */
1028         @DataClass.Generated.Member
setHotwordOffsetMillis(int value)1029         public @NonNull Builder setHotwordOffsetMillis(int value) {
1030             checkNotUsed();
1031             mBuilderFieldsSet |= 0x8;
1032             mHotwordOffsetMillis = value;
1033             return this;
1034         }
1035 
1036         /**
1037          * Duration in milliseconds of the hotword trigger phrase.
1038          *
1039          * <p>Only values between 0 and {@link android.media.AudioRecord#getMaxSharedAudioHistoryMillis}
1040          * (inclusive) are accepted.
1041          */
1042         @DataClass.Generated.Member
setHotwordDurationMillis(int value)1043         public @NonNull Builder setHotwordDurationMillis(int value) {
1044             checkNotUsed();
1045             mBuilderFieldsSet |= 0x10;
1046             mHotwordDurationMillis = value;
1047             return this;
1048         }
1049 
1050         /**
1051          * Audio channel containing the highest-confidence hotword signal.
1052          *
1053          * <p>Only value between 0 and 63 (inclusive) is accepted.
1054          */
1055         @DataClass.Generated.Member
setAudioChannel(int value)1056         public @NonNull Builder setAudioChannel(int value) {
1057             checkNotUsed();
1058             mBuilderFieldsSet |= 0x20;
1059             mAudioChannel = value;
1060             return this;
1061         }
1062 
1063         /**
1064          * Returns whether the trigger has happened due to model having been personalized to fit user's
1065          * voice.
1066          */
1067         @DataClass.Generated.Member
setHotwordDetectionPersonalized(boolean value)1068         public @NonNull Builder setHotwordDetectionPersonalized(boolean value) {
1069             checkNotUsed();
1070             mBuilderFieldsSet |= 0x40;
1071             mHotwordDetectionPersonalized = value;
1072             return this;
1073         }
1074 
1075         /**
1076          * Score for the hotword trigger.
1077          *
1078          * <p>Only values between 0 and {@link #getMaxScore} (inclusive) are accepted.
1079          */
1080         @DataClass.Generated.Member
setScore(int value)1081         public @NonNull Builder setScore(int value) {
1082             checkNotUsed();
1083             mBuilderFieldsSet |= 0x80;
1084             mScore = value;
1085             return this;
1086         }
1087 
1088         /**
1089          * Score for the hotword trigger for device user.
1090          *
1091          * <p>Only values between 0 and {@link #getMaxScore} (inclusive) are accepted.
1092          */
1093         @DataClass.Generated.Member
setPersonalizedScore(int value)1094         public @NonNull Builder setPersonalizedScore(int value) {
1095             checkNotUsed();
1096             mBuilderFieldsSet |= 0x100;
1097             mPersonalizedScore = value;
1098             return this;
1099         }
1100 
1101         /**
1102          * An ID representing the keyphrase that triggered the successful detection.
1103          *
1104          * <p>Only values between 0 and {@link #getMaxHotwordPhraseId()} (inclusive) are accepted.
1105          */
1106         @DataClass.Generated.Member
setHotwordPhraseId(int value)1107         public @NonNull Builder setHotwordPhraseId(int value) {
1108             checkNotUsed();
1109             mBuilderFieldsSet |= 0x200;
1110             mHotwordPhraseId = value;
1111             return this;
1112         }
1113 
1114         /**
1115          * App-specific extras to support trigger.
1116          *
1117          * <p>The size of this bundle will be limited to {@link #getMaxBundleSize}. Results will larger
1118          * bundles will be rejected.
1119          *
1120          * <p>Only primitive types are supported in this bundle. Complex types will be removed from the
1121          * bundle.
1122          *
1123          * <p>The use of this method is discouraged, and support for it will be removed in future
1124          * versions of Android.
1125          *
1126          * <p>After the trigger happens, a special case of proximity-related extra, with the key of
1127          * 'android.service.voice.extra.PROXIMITY_VALUE' and the value of proximity value (integer)
1128          * will be stored to enable proximity logic. {@link HotwordDetectedResult#PROXIMITY_NEAR} will
1129          * indicate 'NEAR' proximity and {@link HotwordDetectedResult#PROXIMITY_FAR} will indicate 'FAR'
1130          * proximity. The proximity value is provided by the system, on devices that support detecting
1131          * proximity of nearby users, to help disambiguate which nearby device should respond. When the
1132          * proximity is unknown, the proximity value will not be stored. This mapping will be excluded
1133          * from the max bundle size calculation because this mapping is included after the result is
1134          * returned from the hotword detector service.
1135          *
1136          * <p>This is a PersistableBundle so it doesn't allow any remotable objects or other contents
1137          * that can be used to communicate with other processes.
1138          */
1139         @DataClass.Generated.Member
setExtras(@onNull PersistableBundle value)1140         public @NonNull Builder setExtras(@NonNull PersistableBundle value) {
1141             checkNotUsed();
1142             mBuilderFieldsSet |= 0x800;
1143             mExtras = value;
1144             return this;
1145         }
1146 
1147         /**
1148          * Power of the background audio signal in which the hotword phrase was detected.
1149          *
1150          * <p> Only values between 0 and {@link #getMaxBackgroundAudioPower} (inclusive)
1151          * and the special value {@link #BACKGROUND_AUDIO_POWER_UNSET} are valid.
1152          *
1153          * <p> This value is unitless. The relation between this value and the real audio signal
1154          * power measured in decibels depends on the hotword detection service implementation.
1155          */
1156         @DataClass.Generated.Member
setBackgroundAudioPower(int value)1157         public @NonNull Builder setBackgroundAudioPower(int value) {
1158             checkNotUsed();
1159             mBuilderFieldsSet |= 0x1000;
1160             mBackgroundAudioPower = value;
1161             return this;
1162         }
1163 
1164         /** Builds the instance. This builder should not be touched after calling this! */
build()1165         public @NonNull HotwordDetectedResult build() {
1166             checkNotUsed();
1167             mBuilderFieldsSet |= 0x2000; // Mark builder used
1168 
1169             if ((mBuilderFieldsSet & 0x1) == 0) {
1170                 mSpeakerId = defaultSpeakerId();
1171             }
1172             if ((mBuilderFieldsSet & 0x2) == 0) {
1173                 mConfidenceLevel = defaultConfidenceLevel();
1174             }
1175             if ((mBuilderFieldsSet & 0x4) == 0) {
1176                 mMediaSyncEvent = null;
1177             }
1178             if ((mBuilderFieldsSet & 0x8) == 0) {
1179                 mHotwordOffsetMillis = HOTWORD_OFFSET_UNSET;
1180             }
1181             if ((mBuilderFieldsSet & 0x10) == 0) {
1182                 mHotwordDurationMillis = 0;
1183             }
1184             if ((mBuilderFieldsSet & 0x20) == 0) {
1185                 mAudioChannel = AUDIO_CHANNEL_UNSET;
1186             }
1187             if ((mBuilderFieldsSet & 0x40) == 0) {
1188                 mHotwordDetectionPersonalized = false;
1189             }
1190             if ((mBuilderFieldsSet & 0x80) == 0) {
1191                 mScore = defaultScore();
1192             }
1193             if ((mBuilderFieldsSet & 0x100) == 0) {
1194                 mPersonalizedScore = defaultPersonalizedScore();
1195             }
1196             if ((mBuilderFieldsSet & 0x200) == 0) {
1197                 mHotwordPhraseId = defaultHotwordPhraseId();
1198             }
1199             if ((mBuilderFieldsSet & 0x400) == 0) {
1200                 mAudioStreams = defaultAudioStreams();
1201             }
1202             if ((mBuilderFieldsSet & 0x800) == 0) {
1203                 mExtras = defaultExtras();
1204             }
1205             if ((mBuilderFieldsSet & 0x1000) == 0) {
1206                 mBackgroundAudioPower = defaultBackgroundAudioPower();
1207             }
1208             HotwordDetectedResult o = new HotwordDetectedResult(
1209                     mSpeakerId,
1210                     mConfidenceLevel,
1211                     mMediaSyncEvent,
1212                     mHotwordOffsetMillis,
1213                     mHotwordDurationMillis,
1214                     mAudioChannel,
1215                     mHotwordDetectionPersonalized,
1216                     mScore,
1217                     mPersonalizedScore,
1218                     mHotwordPhraseId,
1219                     mAudioStreams,
1220                     mExtras,
1221                     mBackgroundAudioPower);
1222             return o;
1223         }
1224 
checkNotUsed()1225         private void checkNotUsed() {
1226             if ((mBuilderFieldsSet & 0x2000) != 0) {
1227                 throw new IllegalStateException(
1228                         "This Builder should not be reused. Use a new Builder instance instead");
1229             }
1230         }
1231     }
1232 
1233     @DataClass.Generated(
1234             time = 1710918729668L,
1235             codegenVersion = "1.0.23",
1236             sourceFile = "frameworks/base/core/java/android/service/voice/HotwordDetectedResult.java",
1237             inputSignatures = "public static final  int CONFIDENCE_LEVEL_NONE\npublic static final  int CONFIDENCE_LEVEL_LOW\npublic static final  int CONFIDENCE_LEVEL_LOW_MEDIUM\npublic static final  int CONFIDENCE_LEVEL_MEDIUM\npublic static final  int CONFIDENCE_LEVEL_MEDIUM_HIGH\npublic static final  int CONFIDENCE_LEVEL_HIGH\npublic static final  int CONFIDENCE_LEVEL_VERY_HIGH\npublic static final  int HOTWORD_OFFSET_UNSET\npublic static final  int AUDIO_CHANNEL_UNSET\npublic static final  int BACKGROUND_AUDIO_POWER_UNSET\nprivate static final  int LIMIT_HOTWORD_OFFSET_MAX_VALUE\nprivate static final  int LIMIT_AUDIO_CHANNEL_MAX_VALUE\nprivate static final  java.lang.String EXTRA_PROXIMITY\npublic static final  int PROXIMITY_UNKNOWN\npublic static final  int PROXIMITY_NEAR\npublic static final  int PROXIMITY_FAR\nprivate final  int mSpeakerId\nprivate final @android.service.voice.HotwordDetectedResult.HotwordConfidenceLevelValue int mConfidenceLevel\nprivate @android.annotation.Nullable android.media.MediaSyncEvent mMediaSyncEvent\nprivate  int mHotwordOffsetMillis\nprivate  int mHotwordDurationMillis\nprivate  int mAudioChannel\nprivate  boolean mHotwordDetectionPersonalized\nprivate final  int mScore\nprivate final  int mPersonalizedScore\nprivate final  int mHotwordPhraseId\nprivate final @android.annotation.NonNull java.util.List<android.service.voice.HotwordAudioStream> mAudioStreams\nprivate final @android.annotation.NonNull android.os.PersistableBundle mExtras\nprivate static  int sMaxBundleSize\nprivate final  int mBackgroundAudioPower\nprivate static  int defaultSpeakerId()\npublic static @android.annotation.SuppressLint int getMaxSpeakerId()\nprivate static  int defaultConfidenceLevel()\nprivate static  int defaultScore()\nprivate static  int defaultPersonalizedScore()\npublic static  int getMaxScore()\nprivate static  int defaultHotwordPhraseId()\npublic static  int getMaxHotwordPhraseId()\nprivate static  java.util.List<android.service.voice.HotwordAudioStream> defaultAudioStreams()\nprivate static  android.os.PersistableBundle defaultExtras()\npublic static  int getMaxBundleSize()\npublic @android.annotation.Nullable android.media.MediaSyncEvent getMediaSyncEvent()\nprivate static  int defaultBackgroundAudioPower()\npublic static  int getMaxBackgroundAudioPower()\npublic static  int getParcelableSize(android.os.Parcelable)\npublic static  int getUsageSize(android.service.voice.HotwordDetectedResult)\nprivate static  int bitCount(long)\nprivate  void onConstructed()\npublic @android.annotation.NonNull java.util.List<android.service.voice.HotwordAudioStream> getAudioStreams()\npublic  void setProximity(double)\npublic @android.service.voice.HotwordDetectedResult.ProximityValue int getProximity()\nprivate @android.service.voice.HotwordDetectedResult.ProximityValue int convertToProximityLevel(double)\npublic  android.service.voice.HotwordDetectedResult.Builder buildUpon()\nclass HotwordDetectedResult extends java.lang.Object implements [android.os.Parcelable]\npublic @android.annotation.NonNull android.service.voice.HotwordDetectedResult.Builder setAudioStreams(java.util.List<android.service.voice.HotwordAudioStream>)\nclass BaseBuilder extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genConstructor=false, genBuilder=true, genEqualsHashCode=true, genHiddenConstDefs=true, genParcelable=true, genToString=true)\npublic @android.annotation.NonNull android.service.voice.HotwordDetectedResult.Builder setAudioStreams(java.util.List<android.service.voice.HotwordAudioStream>)\nclass BaseBuilder extends java.lang.Object implements []")
1238     @Deprecated
__metadata()1239     private void __metadata() {}
1240 
1241 
1242     //@formatter:on
1243     // End of generated code
1244 
1245 }
1246