1 /*
2  * Copyright (C) 2022 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.NonNull;
20 import android.annotation.Nullable;
21 import android.annotation.SystemApi;
22 import android.media.AudioFormat;
23 import android.media.AudioRecord;
24 import android.media.AudioTimestamp;
25 import android.os.Parcel;
26 import android.os.ParcelFileDescriptor;
27 import android.os.Parcelable;
28 import android.os.PersistableBundle;
29 
30 import com.android.internal.util.DataClass;
31 
32 import java.util.Arrays;
33 import java.util.Objects;
34 
35 /**
36  * Represents an audio stream supporting the hotword detection.
37  *
38  * @hide
39  */
40 @DataClass(
41         genConstructor = false,
42         genBuilder = true,
43         genEqualsHashCode = true,
44         genParcelable = true,
45         genToString = true
46 )
47 @SystemApi
48 public final class HotwordAudioStream implements Parcelable {
49 
50     /**
51      * Key for int value to be read from {@link #getMetadata()}. The value is read by the system and
52      * is the length (in bytes) of the byte buffers created to copy bytes in the
53      * {@link #getAudioStreamParcelFileDescriptor()} written by the {@link HotwordDetectionService}.
54      * The buffer length should be chosen such that no additional latency is introduced. Typically,
55      * this should be <em>at least</em> the size of byte chunks written by the
56      * {@link HotwordDetectionService}.
57      *
58      * <p>If no value specified in the metadata for the buffer length, or if the value is less than
59      * 1, or if it is greater than 65,536, or if it is not an int, the default value of 2,560 will
60      * be used.</p>
61      */
62     public static final String KEY_AUDIO_STREAM_COPY_BUFFER_LENGTH_BYTES =
63             "android.service.voice.key.AUDIO_STREAM_COPY_BUFFER_LENGTH_BYTES";
64 
65     /**
66      * The {@link AudioFormat} of the audio stream.
67      */
68     @NonNull
69     private final AudioFormat mAudioFormat;
70 
71     /**
72      * This stream typically starts with the audio bytes used for hotword detection, but continues
73      * streaming the audio (e.g., with the query) until the stream is shutdown by the
74      * {@link HotwordDetectionService}. The data format is expected to match
75      * {@link #getAudioFormat()}.
76      *
77      * <p>
78      * Alternatively, the {@link HotwordDetectionService} may use {@link #getInitialAudio()}
79      * to pass the start of the audio instead of streaming it here. This may prevent added latency
80      * caused by the streaming buffer (see {@link #KEY_AUDIO_STREAM_COPY_BUFFER_LENGTH_BYTES}) not
81      * being large enough to handle this initial chunk of audio.
82      * </p>
83      */
84     @NonNull
85     private final ParcelFileDescriptor mAudioStreamParcelFileDescriptor;
86 
87     /**
88      * The timestamp when the audio stream was captured by the Audio platform.
89      *
90      * <p>
91      * The {@link HotwordDetectionService} egressing the audio is the owner of the underlying
92      * AudioRecord. The {@link HotwordDetectionService} is expected to optionally populate this
93      * field by {@link AudioRecord#getTimestamp}.
94      * </p>
95      *
96      * <p>
97      * This timestamp can be used in conjunction with the
98      * {@link HotwordDetectedResult#getHotwordOffsetMillis()} and
99      * {@link HotwordDetectedResult#getHotwordDurationMillis()} to translate these durations to
100      * timestamps.
101      * </p>
102      *
103      * @see #getAudioStreamParcelFileDescriptor()
104      */
105     @Nullable
106     private final AudioTimestamp mTimestamp;
defaultTimestamp()107     private static AudioTimestamp defaultTimestamp() {
108         return null;
109     }
110 
111     /**
112      * The metadata associated with the audio stream.
113      */
114     @NonNull
115     private final PersistableBundle mMetadata;
defaultMetadata()116     private static PersistableBundle defaultMetadata() {
117         return new PersistableBundle();
118     }
119 
120     /**
121      * The start of the audio used for hotword detection. The data format is expected to match
122      * {@link #getAudioFormat()}.
123      *
124      * <p>
125      * The {@link HotwordDetectionService} may use this instead of using
126      * {@link #getAudioStreamParcelFileDescriptor()} to stream these initial bytes of audio. This
127      * may prevent added latency caused by the streaming buffer (see
128      * {@link #KEY_AUDIO_STREAM_COPY_BUFFER_LENGTH_BYTES}) not being large enough to handle this
129      * initial chunk of audio.
130      * </p>
131      */
132     @NonNull
133     private final byte[] mInitialAudio;
134     private static final byte[] DEFAULT_INITIAL_EMPTY_AUDIO = {};
defaultInitialAudio()135     private static byte[] defaultInitialAudio() {
136         return DEFAULT_INITIAL_EMPTY_AUDIO;
137     }
138 
initialAudioToString()139     private String initialAudioToString() {
140         return "length=" + mInitialAudio.length;
141     }
142 
143     /**
144      * Provides an instance of {@link Builder} with state corresponding to this instance.
145      * @hide
146      */
buildUpon()147     public Builder buildUpon() {
148         return new Builder(mAudioFormat, mAudioStreamParcelFileDescriptor)
149             .setTimestamp(mTimestamp)
150             .setMetadata(mMetadata)
151             .setInitialAudio(mInitialAudio);
152     }
153 
154     @DataClass.Suppress("setInitialAudio")
155     abstract static class BaseBuilder {
156 
157         /**
158          * The start of the audio used for hotword detection. The data format is expected to match
159          * {@link #getAudioFormat()}.
160          *
161          * <p>
162          * The {@link HotwordDetectionService} may use this instead of using
163          * {@link #getAudioStreamParcelFileDescriptor()} to stream these initial bytes of audio.
164          * This may prevent added latency caused by the streaming buffer (see
165          * {@link #KEY_AUDIO_STREAM_COPY_BUFFER_LENGTH_BYTES}) not being large enough to handle this
166          * initial chunk of audio.
167          * </p>
168          */
setInitialAudio(@onNull byte[] value)169         public @NonNull Builder setInitialAudio(@NonNull byte[] value) {
170             Objects.requireNonNull(value, "value should not be null");
171             final Builder builder = (Builder) this;
172             // If the code gen flag in build() is changed, we must update the flag e.g. 0x10 here.
173             builder.mBuilderFieldsSet |= 0x10;
174             builder.mInitialAudio = value;
175             return builder;
176         }
177     }
178 
179 
180 
181     // Code below generated by codegen v1.0.23.
182     //
183     // DO NOT MODIFY!
184     // CHECKSTYLE:OFF Generated code
185     //
186     // To regenerate run:
187     // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/service/voice/HotwordAudioStream.java
188     //
189     // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
190     //   Settings > Editor > Code Style > Formatter Control
191     //@formatter:off
192 
193 
194     @DataClass.Generated.Member
HotwordAudioStream( @onNull AudioFormat audioFormat, @NonNull ParcelFileDescriptor audioStreamParcelFileDescriptor, @Nullable AudioTimestamp timestamp, @NonNull PersistableBundle metadata, @NonNull byte[] initialAudio)195     /* package-private */ HotwordAudioStream(
196             @NonNull AudioFormat audioFormat,
197             @NonNull ParcelFileDescriptor audioStreamParcelFileDescriptor,
198             @Nullable AudioTimestamp timestamp,
199             @NonNull PersistableBundle metadata,
200             @NonNull byte[] initialAudio) {
201         this.mAudioFormat = audioFormat;
202         com.android.internal.util.AnnotationValidations.validate(
203                 NonNull.class, null, mAudioFormat);
204         this.mAudioStreamParcelFileDescriptor = audioStreamParcelFileDescriptor;
205         com.android.internal.util.AnnotationValidations.validate(
206                 NonNull.class, null, mAudioStreamParcelFileDescriptor);
207         this.mTimestamp = timestamp;
208         this.mMetadata = metadata;
209         com.android.internal.util.AnnotationValidations.validate(
210                 NonNull.class, null, mMetadata);
211         this.mInitialAudio = initialAudio;
212         com.android.internal.util.AnnotationValidations.validate(
213                 NonNull.class, null, mInitialAudio);
214 
215         // onConstructed(); // You can define this method to get a callback
216     }
217 
218     /**
219      * The {@link AudioFormat} of the audio stream.
220      */
221     @DataClass.Generated.Member
getAudioFormat()222     public @NonNull AudioFormat getAudioFormat() {
223         return mAudioFormat;
224     }
225 
226     /**
227      * This stream typically starts with the audio bytes used for hotword detection, but continues
228      * streaming the audio (e.g., with the query) until the stream is shutdown by the
229      * {@link HotwordDetectionService}. The data format is expected to match
230      * {@link #getAudioFormat()}.
231      *
232      * <p>
233      * Alternatively, the {@link HotwordDetectionService} may use {@link #getInitialAudio()}
234      * to pass the start of the audio instead of streaming it here. This may prevent added latency
235      * caused by the streaming buffer (see {@link #KEY_AUDIO_STREAM_COPY_BUFFER_LENGTH_BYTES}) not
236      * being large enough to handle this initial chunk of audio.
237      * </p>
238      */
239     @DataClass.Generated.Member
getAudioStreamParcelFileDescriptor()240     public @NonNull ParcelFileDescriptor getAudioStreamParcelFileDescriptor() {
241         return mAudioStreamParcelFileDescriptor;
242     }
243 
244     /**
245      * The timestamp when the audio stream was captured by the Audio platform.
246      *
247      * <p>
248      * The {@link HotwordDetectionService} egressing the audio is the owner of the underlying
249      * AudioRecord. The {@link HotwordDetectionService} is expected to optionally populate this
250      * field by {@link AudioRecord#getTimestamp}.
251      * </p>
252      *
253      * <p>
254      * This timestamp can be used in conjunction with the
255      * {@link HotwordDetectedResult#getHotwordOffsetMillis()} and
256      * {@link HotwordDetectedResult#getHotwordDurationMillis()} to translate these durations to
257      * timestamps.
258      * </p>
259      *
260      * @see #getAudioStreamParcelFileDescriptor()
261      */
262     @DataClass.Generated.Member
getTimestamp()263     public @Nullable AudioTimestamp getTimestamp() {
264         return mTimestamp;
265     }
266 
267     /**
268      * The metadata associated with the audio stream.
269      */
270     @DataClass.Generated.Member
getMetadata()271     public @NonNull PersistableBundle getMetadata() {
272         return mMetadata;
273     }
274 
275     /**
276      * The start of the audio used for hotword detection. The data format is expected to match
277      * {@link #getAudioFormat()}.
278      *
279      * <p>
280      * The {@link HotwordDetectionService} may use this instead of using
281      * {@link #getAudioStreamParcelFileDescriptor()} to stream these initial bytes of audio. This
282      * may prevent added latency caused by the streaming buffer (see
283      * {@link #KEY_AUDIO_STREAM_COPY_BUFFER_LENGTH_BYTES}) not being large enough to handle this
284      * initial chunk of audio.
285      * </p>
286      */
287     @DataClass.Generated.Member
getInitialAudio()288     public @NonNull byte[] getInitialAudio() {
289         return mInitialAudio;
290     }
291 
292     @Override
293     @DataClass.Generated.Member
toString()294     public String toString() {
295         // You can override field toString logic by defining methods like:
296         // String fieldNameToString() { ... }
297 
298         return "HotwordAudioStream { " +
299                 "audioFormat = " + mAudioFormat + ", " +
300                 "audioStreamParcelFileDescriptor = " + mAudioStreamParcelFileDescriptor + ", " +
301                 "timestamp = " + mTimestamp + ", " +
302                 "metadata = " + mMetadata + ", " +
303                 "initialAudio = " + initialAudioToString() +
304         " }";
305     }
306 
307     @Override
308     @DataClass.Generated.Member
equals(@ullable Object o)309     public boolean equals(@Nullable Object o) {
310         // You can override field equality logic by defining either of the methods like:
311         // boolean fieldNameEquals(HotwordAudioStream other) { ... }
312         // boolean fieldNameEquals(FieldType otherValue) { ... }
313 
314         if (this == o) return true;
315         if (o == null || getClass() != o.getClass()) return false;
316         @SuppressWarnings("unchecked")
317         HotwordAudioStream that = (HotwordAudioStream) o;
318         //noinspection PointlessBooleanExpression
319         return true
320                 && Objects.equals(mAudioFormat, that.mAudioFormat)
321                 && Objects.equals(mAudioStreamParcelFileDescriptor, that.mAudioStreamParcelFileDescriptor)
322                 && Objects.equals(mTimestamp, that.mTimestamp)
323                 && Objects.equals(mMetadata, that.mMetadata)
324                 && Arrays.equals(mInitialAudio, that.mInitialAudio);
325     }
326 
327     @Override
328     @DataClass.Generated.Member
hashCode()329     public int hashCode() {
330         // You can override field hashCode logic by defining methods like:
331         // int fieldNameHashCode() { ... }
332 
333         int _hash = 1;
334         _hash = 31 * _hash + Objects.hashCode(mAudioFormat);
335         _hash = 31 * _hash + Objects.hashCode(mAudioStreamParcelFileDescriptor);
336         _hash = 31 * _hash + Objects.hashCode(mTimestamp);
337         _hash = 31 * _hash + Objects.hashCode(mMetadata);
338         _hash = 31 * _hash + Arrays.hashCode(mInitialAudio);
339         return _hash;
340     }
341 
342     @Override
343     @DataClass.Generated.Member
writeToParcel(@onNull Parcel dest, int flags)344     public void writeToParcel(@NonNull Parcel dest, int flags) {
345         // You can override field parcelling by defining methods like:
346         // void parcelFieldName(Parcel dest, int flags) { ... }
347 
348         byte flg = 0;
349         if (mTimestamp != null) flg |= 0x4;
350         dest.writeByte(flg);
351         dest.writeTypedObject(mAudioFormat, flags);
352         dest.writeTypedObject(mAudioStreamParcelFileDescriptor, flags);
353         if (mTimestamp != null) dest.writeTypedObject(mTimestamp, flags);
354         dest.writeTypedObject(mMetadata, flags);
355         dest.writeByteArray(mInitialAudio);
356     }
357 
358     @Override
359     @DataClass.Generated.Member
describeContents()360     public int describeContents() { return 0; }
361 
362     /** @hide */
363     @SuppressWarnings({"unchecked", "RedundantCast"})
364     @DataClass.Generated.Member
HotwordAudioStream(@onNull Parcel in)365     /* package-private */ HotwordAudioStream(@NonNull Parcel in) {
366         // You can override field unparcelling by defining methods like:
367         // static FieldType unparcelFieldName(Parcel in) { ... }
368 
369         byte flg = in.readByte();
370         AudioFormat audioFormat = (AudioFormat) in.readTypedObject(AudioFormat.CREATOR);
371         ParcelFileDescriptor audioStreamParcelFileDescriptor = (ParcelFileDescriptor) in.readTypedObject(ParcelFileDescriptor.CREATOR);
372         AudioTimestamp timestamp = (flg & 0x4) == 0 ? null : (AudioTimestamp) in.readTypedObject(AudioTimestamp.CREATOR);
373         PersistableBundle metadata = (PersistableBundle) in.readTypedObject(PersistableBundle.CREATOR);
374         byte[] initialAudio = in.createByteArray();
375 
376         this.mAudioFormat = audioFormat;
377         com.android.internal.util.AnnotationValidations.validate(
378                 NonNull.class, null, mAudioFormat);
379         this.mAudioStreamParcelFileDescriptor = audioStreamParcelFileDescriptor;
380         com.android.internal.util.AnnotationValidations.validate(
381                 NonNull.class, null, mAudioStreamParcelFileDescriptor);
382         this.mTimestamp = timestamp;
383         this.mMetadata = metadata;
384         com.android.internal.util.AnnotationValidations.validate(
385                 NonNull.class, null, mMetadata);
386         this.mInitialAudio = initialAudio;
387         com.android.internal.util.AnnotationValidations.validate(
388                 NonNull.class, null, mInitialAudio);
389 
390         // onConstructed(); // You can define this method to get a callback
391     }
392 
393     @DataClass.Generated.Member
394     public static final @NonNull Parcelable.Creator<HotwordAudioStream> CREATOR
395             = new Parcelable.Creator<HotwordAudioStream>() {
396         @Override
397         public HotwordAudioStream[] newArray(int size) {
398             return new HotwordAudioStream[size];
399         }
400 
401         @Override
402         public HotwordAudioStream createFromParcel(@NonNull Parcel in) {
403             return new HotwordAudioStream(in);
404         }
405     };
406 
407     /**
408      * A builder for {@link HotwordAudioStream}
409      */
410     @SuppressWarnings("WeakerAccess")
411     @DataClass.Generated.Member
412     public static final class Builder extends BaseBuilder {
413 
414         private @NonNull AudioFormat mAudioFormat;
415         private @NonNull ParcelFileDescriptor mAudioStreamParcelFileDescriptor;
416         private @Nullable AudioTimestamp mTimestamp;
417         private @NonNull PersistableBundle mMetadata;
418         private @NonNull byte[] mInitialAudio;
419 
420         private long mBuilderFieldsSet = 0L;
421 
422         /**
423          * Creates a new Builder.
424          *
425          * @param audioFormat
426          *   The {@link AudioFormat} of the audio stream.
427          * @param audioStreamParcelFileDescriptor
428          *   This stream typically starts with the audio bytes used for hotword detection, but continues
429          *   streaming the audio (e.g., with the query) until the stream is shutdown by the
430          *   {@link HotwordDetectionService}. The data format is expected to match
431          *   {@link #getAudioFormat()}.
432          *
433          *   <p>
434          *   Alternatively, the {@link HotwordDetectionService} may use {@link #getInitialAudio()}
435          *   to pass the start of the audio instead of streaming it here. This may prevent added latency
436          *   caused by the streaming buffer (see {@link #KEY_AUDIO_STREAM_COPY_BUFFER_LENGTH_BYTES}) not
437          *   being large enough to handle this initial chunk of audio.
438          *   </p>
439          */
Builder( @onNull AudioFormat audioFormat, @NonNull ParcelFileDescriptor audioStreamParcelFileDescriptor)440         public Builder(
441                 @NonNull AudioFormat audioFormat,
442                 @NonNull ParcelFileDescriptor audioStreamParcelFileDescriptor) {
443             mAudioFormat = audioFormat;
444             com.android.internal.util.AnnotationValidations.validate(
445                     NonNull.class, null, mAudioFormat);
446             mAudioStreamParcelFileDescriptor = audioStreamParcelFileDescriptor;
447             com.android.internal.util.AnnotationValidations.validate(
448                     NonNull.class, null, mAudioStreamParcelFileDescriptor);
449         }
450 
451         /**
452          * The {@link AudioFormat} of the audio stream.
453          */
454         @DataClass.Generated.Member
setAudioFormat(@onNull AudioFormat value)455         public @NonNull Builder setAudioFormat(@NonNull AudioFormat value) {
456             checkNotUsed();
457             mBuilderFieldsSet |= 0x1;
458             mAudioFormat = value;
459             return this;
460         }
461 
462         /**
463          * This stream typically starts with the audio bytes used for hotword detection, but continues
464          * streaming the audio (e.g., with the query) until the stream is shutdown by the
465          * {@link HotwordDetectionService}. The data format is expected to match
466          * {@link #getAudioFormat()}.
467          *
468          * <p>
469          * Alternatively, the {@link HotwordDetectionService} may use {@link #getInitialAudio()}
470          * to pass the start of the audio instead of streaming it here. This may prevent added latency
471          * caused by the streaming buffer (see {@link #KEY_AUDIO_STREAM_COPY_BUFFER_LENGTH_BYTES}) not
472          * being large enough to handle this initial chunk of audio.
473          * </p>
474          */
475         @DataClass.Generated.Member
setAudioStreamParcelFileDescriptor(@onNull ParcelFileDescriptor value)476         public @NonNull Builder setAudioStreamParcelFileDescriptor(@NonNull ParcelFileDescriptor value) {
477             checkNotUsed();
478             mBuilderFieldsSet |= 0x2;
479             mAudioStreamParcelFileDescriptor = value;
480             return this;
481         }
482 
483         /**
484          * The timestamp when the audio stream was captured by the Audio platform.
485          *
486          * <p>
487          * The {@link HotwordDetectionService} egressing the audio is the owner of the underlying
488          * AudioRecord. The {@link HotwordDetectionService} is expected to optionally populate this
489          * field by {@link AudioRecord#getTimestamp}.
490          * </p>
491          *
492          * <p>
493          * This timestamp can be used in conjunction with the
494          * {@link HotwordDetectedResult#getHotwordOffsetMillis()} and
495          * {@link HotwordDetectedResult#getHotwordDurationMillis()} to translate these durations to
496          * timestamps.
497          * </p>
498          *
499          * @see #getAudioStreamParcelFileDescriptor()
500          */
501         @DataClass.Generated.Member
setTimestamp(@onNull AudioTimestamp value)502         public @NonNull Builder setTimestamp(@NonNull AudioTimestamp value) {
503             checkNotUsed();
504             mBuilderFieldsSet |= 0x4;
505             mTimestamp = value;
506             return this;
507         }
508 
509         /**
510          * The metadata associated with the audio stream.
511          */
512         @DataClass.Generated.Member
setMetadata(@onNull PersistableBundle value)513         public @NonNull Builder setMetadata(@NonNull PersistableBundle value) {
514             checkNotUsed();
515             mBuilderFieldsSet |= 0x8;
516             mMetadata = value;
517             return this;
518         }
519 
520         /** Builds the instance. This builder should not be touched after calling this! */
build()521         public @NonNull HotwordAudioStream build() {
522             checkNotUsed();
523             mBuilderFieldsSet |= 0x20; // Mark builder used
524 
525             if ((mBuilderFieldsSet & 0x4) == 0) {
526                 mTimestamp = defaultTimestamp();
527             }
528             if ((mBuilderFieldsSet & 0x8) == 0) {
529                 mMetadata = defaultMetadata();
530             }
531             if ((mBuilderFieldsSet & 0x10) == 0) {
532                 mInitialAudio = defaultInitialAudio();
533             }
534             HotwordAudioStream o = new HotwordAudioStream(
535                     mAudioFormat,
536                     mAudioStreamParcelFileDescriptor,
537                     mTimestamp,
538                     mMetadata,
539                     mInitialAudio);
540             return o;
541         }
542 
checkNotUsed()543         private void checkNotUsed() {
544             if ((mBuilderFieldsSet & 0x20) != 0) {
545                 throw new IllegalStateException(
546                         "This Builder should not be reused. Use a new Builder instance instead");
547             }
548         }
549     }
550 
551     @DataClass.Generated(
552             time = 1671232056270L,
553             codegenVersion = "1.0.23",
554             sourceFile = "frameworks/base/core/java/android/service/voice/HotwordAudioStream.java",
555             inputSignatures = "public static final  java.lang.String KEY_AUDIO_STREAM_COPY_BUFFER_LENGTH_BYTES\nprivate final @android.annotation.NonNull android.media.AudioFormat mAudioFormat\nprivate final @android.annotation.NonNull android.os.ParcelFileDescriptor mAudioStreamParcelFileDescriptor\nprivate final @android.annotation.Nullable android.media.AudioTimestamp mTimestamp\nprivate final @android.annotation.NonNull android.os.PersistableBundle mMetadata\nprivate final @android.annotation.NonNull byte[] mInitialAudio\nprivate static final  byte[] DEFAULT_INITIAL_EMPTY_AUDIO\nprivate static  android.media.AudioTimestamp defaultTimestamp()\nprivate static  android.os.PersistableBundle defaultMetadata()\nprivate static  byte[] defaultInitialAudio()\nprivate  java.lang.String initialAudioToString()\npublic  android.service.voice.HotwordAudioStream.Builder buildUpon()\nclass HotwordAudioStream extends java.lang.Object implements [android.os.Parcelable]\npublic @android.annotation.NonNull android.service.voice.HotwordAudioStream.Builder setInitialAudio(byte[])\nclass BaseBuilder extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genConstructor=false, genBuilder=true, genEqualsHashCode=true, genParcelable=true, genToString=true)\npublic @android.annotation.NonNull android.service.voice.HotwordAudioStream.Builder setInitialAudio(byte[])\nclass BaseBuilder extends java.lang.Object implements []")
556     @Deprecated
__metadata()557     private void __metadata() {}
558 
559 
560     //@formatter:on
561     // End of generated code
562 
563 }
564