• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * 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 
17 package android.media;
18 
19 import android.annotation.IntDef;
20 import android.annotation.NonNull;
21 import android.annotation.RequiresPermission;
22 import android.annotation.SystemApi;
23 import android.annotation.TestApi;
24 import android.audio.policy.configuration.V7_0.AudioUsage;
25 import android.compat.annotation.UnsupportedAppUsage;
26 import android.media.audiopolicy.AudioProductStrategy;
27 import android.os.Build;
28 import android.os.Bundle;
29 import android.os.Parcel;
30 import android.os.Parcelable;
31 import android.text.TextUtils;
32 import android.util.IntArray;
33 import android.util.Log;
34 import android.util.SparseIntArray;
35 import android.util.proto.ProtoOutputStream;
36 
37 import java.lang.annotation.Retention;
38 import java.lang.annotation.RetentionPolicy;
39 import java.util.Collections;
40 import java.util.HashMap;
41 import java.util.HashSet;
42 import java.util.Map;
43 import java.util.Objects;
44 import java.util.Set;
45 
46 /**
47  * A class to encapsulate a collection of attributes describing information about an audio
48  * stream.
49  * <p><code>AudioAttributes</code> supersede the notion of stream types (see for instance
50  * {@link AudioManager#STREAM_MUSIC} or {@link AudioManager#STREAM_ALARM}) for defining the
51  * behavior of audio playback. Attributes allow an application to specify more information than is
52  * conveyed in a stream type by allowing the application to define:
53  * <ul>
54  * <li>usage: "why" you are playing a sound, what is this sound used for. This is achieved with
55  *     the "usage" information. Examples of usage are {@link #USAGE_MEDIA} and {@link #USAGE_ALARM}.
56  *     These two examples are the closest to stream types, but more detailed use cases are
57  *     available. Usage information is more expressive than a stream type, and allows certain
58  *     platforms or routing policies to use this information for more refined volume or routing
59  *     decisions. Usage is the most important information to supply in <code>AudioAttributes</code>
60  *     and it is recommended to build any instance with this information supplied, see
61  *     {@link AudioAttributes.Builder} for exceptions.</li>
62  * <li>content type: "what" you are playing. The content type expresses the general category of
63  *     the content. This information is optional. But in case it is known (for instance
64  *     {@link #CONTENT_TYPE_MOVIE} for a movie streaming service or {@link #CONTENT_TYPE_MUSIC} for
65  *     a music playback application) this information might be used by the audio framework to
66  *     selectively configure some audio post-processing blocks.</li>
67  * <li>flags: "how" is playback to be affected, see the flag definitions for the specific playback
68  *     behaviors they control. </li>
69  * </ul>
70  * <p><code>AudioAttributes</code> are used for example in one of the {@link AudioTrack}
71  * constructors (see {@link AudioTrack#AudioTrack(AudioAttributes, AudioFormat, int, int, int)}),
72  * to configure a {@link MediaPlayer}
73  * (see {@link MediaPlayer#setAudioAttributes(AudioAttributes)} or a
74  * {@link android.app.Notification} (see {@link android.app.Notification#audioAttributes}). An
75  * <code>AudioAttributes</code> instance is built through its builder,
76  * {@link AudioAttributes.Builder}.
77  */
78 public final class AudioAttributes implements Parcelable {
79     private final static String TAG = "AudioAttributes";
80 
81     /**
82      * Content type value to use when the content type is unknown, or other than the ones defined.
83      */
84     public final static int CONTENT_TYPE_UNKNOWN = 0;
85     /**
86      * Content type value to use when the content type is speech.
87      */
88     public final static int CONTENT_TYPE_SPEECH = 1;
89     /**
90      * Content type value to use when the content type is music.
91      */
92     public final static int CONTENT_TYPE_MUSIC = 2;
93     /**
94      * Content type value to use when the content type is a soundtrack, typically accompanying
95      * a movie or TV program.
96      */
97     public final static int CONTENT_TYPE_MOVIE = 3;
98     /**
99      * Content type value to use when the content type is a sound used to accompany a user
100      * action, such as a beep or sound effect expressing a key click, or event, such as the
101      * type of a sound for a bonus being received in a game. These sounds are mostly synthesized
102      * or short Foley sounds.
103      */
104     public final static int CONTENT_TYPE_SONIFICATION = 4;
105     /**
106      * @hide
107      * Content type value to use when the content type is ultrasound.
108      */
109     @SystemApi
110     @RequiresPermission(android.Manifest.permission.ACCESS_ULTRASOUND)
111     public static final int CONTENT_TYPE_ULTRASOUND = 1997;
112 
113     /**
114      * Invalid value, only ever used for an uninitialized usage value
115      */
116     private static final int USAGE_INVALID = -1;
117     /**
118      * Usage value to use when the usage is unknown.
119      */
120     public final static int USAGE_UNKNOWN = 0;
121     /**
122      * Usage value to use when the usage is media, such as music, or movie
123      * soundtracks.
124      */
125     public final static int USAGE_MEDIA = 1;
126     /**
127      * Usage value to use when the usage is voice communications, such as telephony
128      * or VoIP.
129      */
130     public final static int USAGE_VOICE_COMMUNICATION = 2;
131     /**
132      * Usage value to use when the usage is in-call signalling, such as with
133      * a "busy" beep, or DTMF tones.
134      */
135     public final static int USAGE_VOICE_COMMUNICATION_SIGNALLING = 3;
136     /**
137      * Usage value to use when the usage is an alarm (e.g. wake-up alarm).
138      */
139     public final static int USAGE_ALARM = 4;
140     /**
141      * Usage value to use when the usage is notification. See other
142      * notification usages for more specialized uses.
143      */
144     public final static int USAGE_NOTIFICATION = 5;
145     /**
146      * Usage value to use when the usage is telephony ringtone.
147      */
148     public final static int USAGE_NOTIFICATION_RINGTONE = 6;
149     /**
150      * Usage value to use when the usage is a request to enter/end a
151      * communication, such as a VoIP communication or video-conference.
152      * @deprecated Use {@link #USAGE_NOTIFICATION} which is handled
153      *             the same way as this usage by the audio framework
154      */
155     @Deprecated
156     public final static int USAGE_NOTIFICATION_COMMUNICATION_REQUEST = 7;
157     /**
158      * Usage value to use when the usage is notification for an "instant"
159      * communication such as a chat, or SMS.
160      * @deprecated Use {@link #USAGE_NOTIFICATION} which is handled
161      *             the same way as this usage by the audio framework
162      */
163     @Deprecated
164     public final static int USAGE_NOTIFICATION_COMMUNICATION_INSTANT = 8;
165     /**
166      * Usage value to use when the usage is notification for a
167      * non-immediate type of communication such as e-mail.
168      * @deprecated Use {@link #USAGE_NOTIFICATION} which is handled
169      *             the same way as this usage by the audio framework
170      */
171     @Deprecated
172     public final static int USAGE_NOTIFICATION_COMMUNICATION_DELAYED = 9;
173     /**
174      * Usage value to use when the usage is to attract the user's attention,
175      * such as a reminder or low battery warning.
176      */
177     public final static int USAGE_NOTIFICATION_EVENT = 10;
178     /**
179      * Usage value to use when the usage is for accessibility, such as with
180      * a screen reader.
181      */
182     public final static int USAGE_ASSISTANCE_ACCESSIBILITY = 11;
183     /**
184      * Usage value to use when the usage is driving or navigation directions.
185      */
186     public final static int USAGE_ASSISTANCE_NAVIGATION_GUIDANCE = 12;
187     /**
188      * Usage value to use when the usage is sonification, such as  with user
189      * interface sounds.
190      */
191     public final static int USAGE_ASSISTANCE_SONIFICATION = 13;
192     /**
193      * Usage value to use when the usage is for game audio.
194      */
195     public final static int USAGE_GAME = 14;
196     /**
197      * @hide
198      * Usage value to use when feeding audio to the platform and replacing "traditional" audio
199      * source, such as audio capture devices.
200      */
201     public final static int USAGE_VIRTUAL_SOURCE = 15;
202     /**
203      * Usage value to use for audio responses to user queries, audio instructions or help
204      * utterances.
205      */
206     public final static int USAGE_ASSISTANT = 16;
207     /**
208      * @hide
209      * Usage value to use for assistant voice interaction with remote caller on Cell and VoIP calls.
210      */
211     @SystemApi
212     @RequiresPermission(allOf = {
213             android.Manifest.permission.MODIFY_PHONE_STATE,
214             android.Manifest.permission.MODIFY_AUDIO_ROUTING
215     })
216     public static final int USAGE_CALL_ASSISTANT = 17;
217 
218     private static final int SYSTEM_USAGE_OFFSET = 1000;
219 
220     /**
221      * @hide
222      * Usage value to use when the usage is an emergency.
223      */
224     @SystemApi
225     @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
226     public static final int USAGE_EMERGENCY = SYSTEM_USAGE_OFFSET;
227     /**
228      * @hide
229      * Usage value to use when the usage is a safety sound.
230      */
231     @SystemApi
232     @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
233     public static final int USAGE_SAFETY = SYSTEM_USAGE_OFFSET + 1;
234     /**
235      * @hide
236      * Usage value to use when the usage is a vehicle status.
237      */
238     @SystemApi
239     @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
240     public static final int USAGE_VEHICLE_STATUS = SYSTEM_USAGE_OFFSET + 2;
241     /**
242      * @hide
243      * Usage value to use when the usage is an announcement.
244      */
245     @SystemApi
246     @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
247     public static final int USAGE_ANNOUNCEMENT = SYSTEM_USAGE_OFFSET + 3;
248 
249     /**
250      * IMPORTANT: when adding new usage types, add them to SDK_USAGES and update SUPPRESSIBLE_USAGES
251      *            if applicable, as well as audioattributes.proto.
252      *            Also consider adding them to <aaudio/AAudio.h> for the NDK.
253      *            Also consider adding them to UsageTypeConverter for service dump and etc.
254      */
255 
256     /**
257      * @hide
258      * Denotes a usage for notifications that do not expect immediate intervention from the user,
259      * will be muted when the Zen mode disables notifications
260      * @see #SUPPRESSIBLE_USAGES
261      */
262     public final static int SUPPRESSIBLE_NOTIFICATION = 1;
263     /**
264      * @hide
265      * Denotes a usage for notifications that do expect immediate intervention from the user,
266      * will be muted when the Zen mode disables calls
267      * @see #SUPPRESSIBLE_USAGES
268      */
269     public final static int SUPPRESSIBLE_CALL = 2;
270     /**
271      * @hide
272      * Denotes a usage that is never going to be muted, even in Total Silence.
273      * @see #SUPPRESSIBLE_USAGES
274      */
275     public final static int SUPPRESSIBLE_NEVER = 3;
276     /**
277      * @hide
278      * Denotes a usage for alarms,
279      * will be muted when the Zen mode priority doesn't allow alarms or in Alarms Only Mode
280      * @see #SUPPRESSIBLE_USAGES
281      */
282     public final static int SUPPRESSIBLE_ALARM = 4;
283     /**
284      * @hide
285      * Denotes a usage for media, game, assistant, and navigation
286      * will be muted when the Zen priority mode doesn't allow media
287      * @see #SUPPRESSIBLE_USAGES
288      */
289     public final static int SUPPRESSIBLE_MEDIA = 5;
290     /**
291      * @hide
292      * Denotes a usage for sounds not caught in SUPPRESSIBLE_NOTIFICATION,
293      * SUPPRESSIBLE_CALL,SUPPRESSIBLE_NEVER, SUPPRESSIBLE_ALARM or SUPPRESSIBLE_MEDIA.
294      * This includes sonification sounds.
295      * These will be muted when the Zen priority mode doesn't allow system sounds
296      * @see #SUPPRESSIBLE_USAGES
297      */
298     public final static int SUPPRESSIBLE_SYSTEM = 6;
299 
300     /**
301      * @hide
302      * Array of all usage types for calls and notifications to assign the suppression behavior,
303      * used by the Zen mode restrictions.
304      * @see com.android.server.notification.ZenModeHelper
305      */
306     public static final SparseIntArray SUPPRESSIBLE_USAGES;
307 
308     static {
309         SUPPRESSIBLE_USAGES = new SparseIntArray();
SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION, SUPPRESSIBLE_NOTIFICATION)310         SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION,                      SUPPRESSIBLE_NOTIFICATION);
SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION_RINGTONE, SUPPRESSIBLE_CALL)311         SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION_RINGTONE,             SUPPRESSIBLE_CALL);
SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION_COMMUNICATION_REQUEST,SUPPRESSIBLE_CALL)312         SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION_COMMUNICATION_REQUEST,SUPPRESSIBLE_CALL);
SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION_COMMUNICATION_INSTANT,SUPPRESSIBLE_NOTIFICATION)313         SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION_COMMUNICATION_INSTANT,SUPPRESSIBLE_NOTIFICATION);
SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION_COMMUNICATION_DELAYED,SUPPRESSIBLE_NOTIFICATION)314         SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION_COMMUNICATION_DELAYED,SUPPRESSIBLE_NOTIFICATION);
SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION_EVENT, SUPPRESSIBLE_NOTIFICATION)315         SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION_EVENT,                SUPPRESSIBLE_NOTIFICATION);
SUPPRESSIBLE_USAGES.put(USAGE_ASSISTANCE_ACCESSIBILITY, SUPPRESSIBLE_NEVER)316         SUPPRESSIBLE_USAGES.put(USAGE_ASSISTANCE_ACCESSIBILITY,          SUPPRESSIBLE_NEVER);
SUPPRESSIBLE_USAGES.put(USAGE_VOICE_COMMUNICATION, SUPPRESSIBLE_NEVER)317         SUPPRESSIBLE_USAGES.put(USAGE_VOICE_COMMUNICATION,               SUPPRESSIBLE_NEVER);
SUPPRESSIBLE_USAGES.put(USAGE_VOICE_COMMUNICATION_SIGNALLING, SUPPRESSIBLE_NEVER)318         SUPPRESSIBLE_USAGES.put(USAGE_VOICE_COMMUNICATION_SIGNALLING,    SUPPRESSIBLE_NEVER);
SUPPRESSIBLE_USAGES.put(USAGE_ALARM, SUPPRESSIBLE_ALARM)319         SUPPRESSIBLE_USAGES.put(USAGE_ALARM,                             SUPPRESSIBLE_ALARM);
SUPPRESSIBLE_USAGES.put(USAGE_MEDIA, SUPPRESSIBLE_MEDIA)320         SUPPRESSIBLE_USAGES.put(USAGE_MEDIA,                             SUPPRESSIBLE_MEDIA);
SUPPRESSIBLE_USAGES.put(USAGE_ASSISTANCE_NAVIGATION_GUIDANCE, SUPPRESSIBLE_MEDIA)321         SUPPRESSIBLE_USAGES.put(USAGE_ASSISTANCE_NAVIGATION_GUIDANCE,    SUPPRESSIBLE_MEDIA);
SUPPRESSIBLE_USAGES.put(USAGE_GAME, SUPPRESSIBLE_MEDIA)322         SUPPRESSIBLE_USAGES.put(USAGE_GAME,                              SUPPRESSIBLE_MEDIA);
SUPPRESSIBLE_USAGES.put(USAGE_ASSISTANT, SUPPRESSIBLE_MEDIA)323         SUPPRESSIBLE_USAGES.put(USAGE_ASSISTANT,                         SUPPRESSIBLE_MEDIA);
SUPPRESSIBLE_USAGES.put(USAGE_CALL_ASSISTANT, SUPPRESSIBLE_NEVER)324         SUPPRESSIBLE_USAGES.put(USAGE_CALL_ASSISTANT,                    SUPPRESSIBLE_NEVER);
325         /** default volume assignment is STREAM_MUSIC, handle unknown usage as media */
SUPPRESSIBLE_USAGES.put(USAGE_UNKNOWN, SUPPRESSIBLE_MEDIA)326         SUPPRESSIBLE_USAGES.put(USAGE_UNKNOWN,                           SUPPRESSIBLE_MEDIA);
SUPPRESSIBLE_USAGES.put(USAGE_ASSISTANCE_SONIFICATION, SUPPRESSIBLE_SYSTEM)327         SUPPRESSIBLE_USAGES.put(USAGE_ASSISTANCE_SONIFICATION,           SUPPRESSIBLE_SYSTEM);
328     }
329 
330     /**
331      * @hide
332      * Array of all usage types exposed in the SDK that applications can use.
333      */
334     public static final IntArray SDK_USAGES = IntArray.wrap(new int[] {
335             USAGE_UNKNOWN,
336             USAGE_MEDIA,
337             USAGE_VOICE_COMMUNICATION,
338             USAGE_VOICE_COMMUNICATION_SIGNALLING,
339             USAGE_ALARM,
340             USAGE_NOTIFICATION,
341             USAGE_NOTIFICATION_RINGTONE,
342             USAGE_NOTIFICATION_COMMUNICATION_REQUEST,
343             USAGE_NOTIFICATION_COMMUNICATION_INSTANT,
344             USAGE_NOTIFICATION_COMMUNICATION_DELAYED,
345             USAGE_NOTIFICATION_EVENT,
346             USAGE_ASSISTANCE_ACCESSIBILITY,
347             USAGE_ASSISTANCE_NAVIGATION_GUIDANCE,
348             USAGE_ASSISTANCE_SONIFICATION,
349             USAGE_GAME,
350             USAGE_ASSISTANT,
351     });
352 
353     /**
354      * @hide
355      */
356     @TestApi
getSdkUsages()357     public static int[] getSdkUsages() {
358         return SDK_USAGES.toArray();
359     }
360 
361     /**
362      * Flag defining a behavior where the audibility of the sound will be ensured by the system.
363      * To ensure sound audibility, the system only uses built-in speakers or wired headphones
364      * and specifically excludes wireless audio devices.
365      * <p>Note this flag should only be used for sounds subject to regulatory behaviors in some
366      * countries, such as for camera shutter sound, and not for routing behaviors.
367      */
368     public final static int FLAG_AUDIBILITY_ENFORCED = 0x1 << 0;
369     /**
370      * @hide
371      * Flag defining a behavior where the playback of the sound is ensured without
372      * degradation only when going to a secure sink.
373      */
374     // FIXME not guaranteed yet
375     // TODO  add in FLAG_ALL_PUBLIC when supported and in public API
376     public final static int FLAG_SECURE = 0x1 << 1;
377     /**
378      * @hide
379      * Flag to enable when the stream is associated with SCO usage.
380      * Internal use only for dealing with legacy STREAM_BLUETOOTH_SCO
381      */
382     public final static int FLAG_SCO = 0x1 << 2;
383     /**
384      * @hide
385      * Flag defining a behavior where the system ensures that the playback of the sound will
386      * be compatible with its use as a broadcast for surrounding people and/or devices.
387      * Ensures audibility with no or minimal post-processing applied.
388      */
389     @SystemApi
390     public final static int FLAG_BEACON = 0x1 << 3;
391 
392     /**
393      * Flag requesting the use of an output stream supporting hardware A/V synchronization.
394      */
395     public final static int FLAG_HW_AV_SYNC = 0x1 << 4;
396 
397     /**
398      * @hide
399      * Flag requesting capture from the source used for hardware hotword detection.
400      * To be used with capture preset MediaRecorder.AudioSource.HOTWORD or
401      * MediaRecorder.AudioSource.VOICE_RECOGNITION.
402      */
403     @SystemApi
404     public final static int FLAG_HW_HOTWORD = 0x1 << 5;
405 
406     /**
407      * @hide
408      * Flag requesting audible playback even under limited interruptions.
409      */
410     @SystemApi
411     public final static int FLAG_BYPASS_INTERRUPTION_POLICY = 0x1 << 6;
412 
413     /**
414      * @hide
415      * Flag requesting audible playback even when the underlying stream is muted.
416      */
417     @SystemApi
418     public final static int FLAG_BYPASS_MUTE = 0x1 << 7;
419 
420     /**
421      * Flag requesting a low latency path when creating an AudioTrack.
422      * When using this flag, the sample rate must match the native sample rate
423      * of the device. Effects processing is also unavailable.
424      *
425      * Note that if this flag is used without specifying a bufferSizeInBytes then the
426      * AudioTrack's actual buffer size may be too small. It is recommended that a fairly
427      * large buffer should be specified when the AudioTrack is created.
428      * Then the actual size can be reduced by calling
429      * {@link AudioTrack#setBufferSizeInFrames(int)}. The buffer size can be optimized
430      * by lowering it after each write() call until the audio glitches, which is detected by calling
431      * {@link AudioTrack#getUnderrunCount()}. Then the buffer size can be increased
432      * until there are no glitches.
433      * This tuning step should be done while playing silence.
434      * This technique provides a compromise between latency and glitch rate.
435      *
436      * @deprecated Use {@link AudioTrack.Builder#setPerformanceMode(int)} with
437      * {@link AudioTrack#PERFORMANCE_MODE_LOW_LATENCY} to control performance.
438      */
439     public final static int FLAG_LOW_LATENCY = 0x1 << 8;
440 
441     /**
442      * @hide
443      * Flag requesting a deep buffer path when creating an {@code AudioTrack}.
444      *
445      * A deep buffer path, if available, may consume less power and is
446      * suitable for media playback where latency is not a concern.
447      * Use {@link AudioTrack.Builder#setPerformanceMode(int)} with
448      * {@link AudioTrack#PERFORMANCE_MODE_POWER_SAVING} to enable.
449      */
450     public final static int FLAG_DEEP_BUFFER = 0x1 << 9;
451 
452     /**
453      * @hide
454      * Flag specifying that the audio shall not be captured by third-party apps
455      * with a MediaProjection.
456      */
457     public static final int FLAG_NO_MEDIA_PROJECTION = 0x1 << 10;
458 
459     /**
460      * @hide
461      * Flag indicating force muting haptic channels.
462      */
463     public static final int FLAG_MUTE_HAPTIC = 0x1 << 11;
464 
465     /**
466      * @hide
467      * Flag specifying that the audio shall not be captured by any apps, not even system apps.
468      */
469     public static final int FLAG_NO_SYSTEM_CAPTURE = 0x1 << 12;
470 
471     /**
472      * @hide
473      * Flag requesting private audio capture. When set in audio attributes passed to an
474      * AudioRecord, this prevents a privileged Assistant from capturing audio while this
475      * AudioRecord is active.
476      */
477     public static final int FLAG_CAPTURE_PRIVATE = 0x1 << 13;
478 
479     /**
480      * @hide
481      * Flag indicating the audio content has been processed to provide a virtual multichannel
482      * audio experience
483      */
484     public static final int FLAG_CONTENT_SPATIALIZED = 0x1 << 14;
485 
486     /**
487      * @hide
488      * Flag indicating the audio content is to never be spatialized
489      */
490     public static final int FLAG_NEVER_SPATIALIZE = 0x1 << 15;
491 
492     /**
493      * @hide
494      * Flag indicating the audio is part of a call redirection.
495      * Valid for playback and capture.
496      */
497     public static final int FLAG_CALL_REDIRECTION = 0x1 << 16;
498 
499     // Note that even though FLAG_MUTE_HAPTIC is stored as a flag bit, it is not here since
500     // it is known as a boolean value outside of AudioAttributes.
501     private static final int FLAG_ALL = FLAG_AUDIBILITY_ENFORCED | FLAG_SECURE | FLAG_SCO
502             | FLAG_BEACON | FLAG_HW_AV_SYNC | FLAG_HW_HOTWORD | FLAG_BYPASS_INTERRUPTION_POLICY
503             | FLAG_BYPASS_MUTE | FLAG_LOW_LATENCY | FLAG_DEEP_BUFFER | FLAG_NO_MEDIA_PROJECTION
504             | FLAG_NO_SYSTEM_CAPTURE | FLAG_CAPTURE_PRIVATE | FLAG_CONTENT_SPATIALIZED
505             | FLAG_NEVER_SPATIALIZE | FLAG_CALL_REDIRECTION;
506     private final static int FLAG_ALL_PUBLIC = FLAG_AUDIBILITY_ENFORCED |
507             FLAG_HW_AV_SYNC | FLAG_LOW_LATENCY;
508     /* mask of flags that can be set by SDK and System APIs through the Builder */
509     private static final int FLAG_ALL_API_SET = FLAG_ALL_PUBLIC
510             | FLAG_BYPASS_INTERRUPTION_POLICY
511             | FLAG_BYPASS_MUTE;
512 
513     /**
514      * Indicates that the audio may be captured by any app.
515      *
516      * For privacy, the following usages cannot be recorded: VOICE_COMMUNICATION*,
517      * USAGE_NOTIFICATION*, USAGE_ASSISTANCE* and USAGE_ASSISTANT.
518      *
519      * On {@link android.os.Build.VERSION_CODES#Q}, this means only {@link #USAGE_UNKNOWN},
520      * {@link #USAGE_MEDIA} and {@link #USAGE_GAME} may be captured.
521      *
522      * See {@link android.media.projection.MediaProjection} and
523      * {@link Builder#setAllowedCapturePolicy}.
524      */
525     public static final int ALLOW_CAPTURE_BY_ALL = 1;
526     /**
527      * Indicates that the audio may only be captured by system apps.
528      *
529      * System apps can capture for many purposes like accessibility, live captions, user guidance...
530      * but abide to the following restrictions:
531      *  - the audio cannot leave the device
532      *  - the audio cannot be passed to a third party app
533      *  - the audio cannot be recorded at a higher quality than 16kHz 16bit mono
534      *
535      * See {@link Builder#setAllowedCapturePolicy}.
536      */
537     public static final int ALLOW_CAPTURE_BY_SYSTEM = 2;
538     /**
539      * Indicates that the audio is not to be recorded by any app, even if it is a system app.
540      *
541      * It is encouraged to use {@link #ALLOW_CAPTURE_BY_SYSTEM} instead of this value as system apps
542      * provide significant and useful features for the user (such as live captioning
543      * and accessibility).
544      *
545      * See {@link Builder#setAllowedCapturePolicy}.
546      */
547     public static final int ALLOW_CAPTURE_BY_NONE = 3;
548 
549     /** @hide */
550     @IntDef({
551         ALLOW_CAPTURE_BY_ALL,
552         ALLOW_CAPTURE_BY_SYSTEM,
553         ALLOW_CAPTURE_BY_NONE,
554     })
555     @Retention(RetentionPolicy.SOURCE)
556     public @interface CapturePolicy {}
557 
558     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
559     private int mUsage = USAGE_UNKNOWN;
560     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
561     private int mContentType = CONTENT_TYPE_UNKNOWN;
562     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
563     private int mSource = MediaRecorder.AudioSource.AUDIO_SOURCE_INVALID;
564     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
565     private int mFlags = 0x0;
566     private HashSet<String> mTags;
567     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
568     private String mFormattedTags;
569     private Bundle mBundle; // lazy-initialized, may be null
570 
571     /** Array of all content types exposed in the SDK that applications can use */
572     private static final IntArray CONTENT_TYPES = IntArray.wrap(new int[]{
573             CONTENT_TYPE_UNKNOWN,
574             CONTENT_TYPE_SPEECH,
575             CONTENT_TYPE_MUSIC,
576             CONTENT_TYPE_MOVIE,
577             CONTENT_TYPE_SONIFICATION,
578     });
579 
AudioAttributes()580     private AudioAttributes() {
581     }
582 
583     /**
584      * Return the content type.
585      * @return one of the values that can be set in {@link Builder#setContentType(int)}
586      */
getContentType()587     public int getContentType() {
588         return mContentType;
589     }
590 
591     /**
592      * Return the usage.
593      * @return one of the values that can be set in {@link Builder#setUsage(int)}
594      */
getUsage()595     public int getUsage() {
596         if (isSystemUsage(mUsage)) {
597             return USAGE_UNKNOWN;
598         }
599         return mUsage;
600     }
601 
602     /**
603      * @hide
604      * Return the system usage.
605      * @return one of the values that can be set in {@link Builder#setUsage(int)} or
606      * {@link Builder#setSystemUsage(int)}
607      */
608     @SystemApi
getSystemUsage()609     public int getSystemUsage() {
610         return mUsage;
611     }
612 
613     /**
614      * @hide
615      * Return the capture preset.
616      * @return one of the values that can be set in {@link Builder#setCapturePreset(int)} or a
617      *    negative value if none has been set.
618      */
619     @SystemApi
getCapturePreset()620     public int getCapturePreset() {
621         return mSource;
622     }
623 
624     /**
625      * Return the flags.
626      * @return a combined mask of all flags
627      */
getFlags()628     public int getFlags() {
629         // only return the flags that are public
630         return (mFlags & (FLAG_ALL_PUBLIC));
631     }
632 
633     /**
634      * @hide
635      * Return all the flags, even the non-public ones.
636      * Internal use only
637      * @return a combined mask of all flags
638      */
639     @SystemApi
getAllFlags()640     public int getAllFlags() {
641         return (mFlags & FLAG_ALL);
642     }
643 
644     /**
645      * @hide
646      * Return the Bundle of data.
647      * @return a copy of the Bundle for this instance, may be null.
648      */
649     @SystemApi
getBundle()650     public Bundle getBundle() {
651         if (mBundle == null) {
652             return mBundle;
653         } else {
654             return new Bundle(mBundle);
655         }
656     }
657 
658     /**
659      * @hide
660      * Return the set of tags.
661      * @return a read-only set of all tags stored as strings.
662      */
getTags()663     public Set<String> getTags() {
664         return Collections.unmodifiableSet(mTags);
665     }
666 
667     /**
668      * Return if haptic channels are muted.
669      * @return {@code true} if haptic channels are muted, {@code false} otherwise.
670      */
areHapticChannelsMuted()671     public boolean areHapticChannelsMuted() {
672         return (mFlags & FLAG_MUTE_HAPTIC) != 0;
673     }
674 
675     /**
676      * Return true if the audio content associated with these attributes has already been
677      * spatialized, that is it has already been processed to offer a binaural or transaural
678      * immersive audio experience.
679      * @return {@code true} if the content has been processed
680      */
isContentSpatialized()681     public boolean isContentSpatialized() {
682         return (mFlags & FLAG_CONTENT_SPATIALIZED) != 0;
683     }
684 
685     /** @hide */
686     @IntDef(flag = false, value = {
687             SPATIALIZATION_BEHAVIOR_AUTO,
688             SPATIALIZATION_BEHAVIOR_NEVER,
689     })
690     @Retention(RetentionPolicy.SOURCE)
691     public @interface SpatializationBehavior {};
692 
693     /**
694      * Constant indicating the audio content associated with these attributes will follow the
695      * default platform behavior with regards to which content will be spatialized or not.
696      * @see #getSpatializationBehavior()
697      * @see Spatializer
698      */
699     public static final int SPATIALIZATION_BEHAVIOR_AUTO = 0;
700 
701     /**
702      * Constant indicating the audio content associated with these attributes should never
703      * be virtualized.
704      * @see #getSpatializationBehavior()
705      * @see Spatializer
706      */
707     public static final int SPATIALIZATION_BEHAVIOR_NEVER = 1;
708 
709     /**
710      * Return the behavior affecting whether spatialization will be used.
711      * @return the spatialization behavior
712      */
getSpatializationBehavior()713     public @SpatializationBehavior int getSpatializationBehavior() {
714         return ((mFlags & FLAG_NEVER_SPATIALIZE) != 0)
715                 ? SPATIALIZATION_BEHAVIOR_NEVER : SPATIALIZATION_BEHAVIOR_AUTO;
716     }
717 
718     /**
719      * Return the capture policy.
720      * @return the capture policy set by {@link Builder#setAllowedCapturePolicy(int)} or
721      *         the default if it was not called.
722      */
723     @CapturePolicy
getAllowedCapturePolicy()724     public int getAllowedCapturePolicy() {
725         if ((mFlags & FLAG_NO_SYSTEM_CAPTURE) == FLAG_NO_SYSTEM_CAPTURE) {
726             return ALLOW_CAPTURE_BY_NONE;
727         }
728         if ((mFlags & FLAG_NO_MEDIA_PROJECTION) == FLAG_NO_MEDIA_PROJECTION) {
729             return ALLOW_CAPTURE_BY_SYSTEM;
730         }
731         return ALLOW_CAPTURE_BY_ALL;
732     }
733 
734     /**
735      * @hide
736      * Indicates if the audio is used for call redirection
737      * @return true if used for call redirection, false otherwise.
738      */
isForCallRedirection()739     public boolean isForCallRedirection() {
740         return (mFlags & FLAG_CALL_REDIRECTION) == FLAG_CALL_REDIRECTION;
741     }
742 
743     /**
744      * Builder class for {@link AudioAttributes} objects.
745      * <p> Here is an example where <code>Builder</code> is used to define the
746      * {@link AudioAttributes} to be used by a new <code>AudioTrack</code> instance:
747      *
748      * <pre class="prettyprint">
749      * AudioTrack myTrack = new AudioTrack(
750      *         new AudioAttributes.Builder()
751      *             .setUsage(AudioAttributes.USAGE_MEDIA)
752      *             .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
753      *             .build(),
754      *         myFormat, myBuffSize, AudioTrack.MODE_STREAM, mySession);
755      * </pre>
756      *
757      * <p>By default all types of information (usage, content type, flags) conveyed by an
758      * <code>AudioAttributes</code> instance are set to "unknown". Unknown information will be
759      * interpreted as a default value that is dependent on the context of use, for instance a
760      * {@link MediaPlayer} will use a default usage of {@link AudioAttributes#USAGE_MEDIA}.
761      */
762     public static class Builder {
763         private int mUsage = USAGE_INVALID;
764         private int mSystemUsage = USAGE_INVALID;
765         private int mContentType = CONTENT_TYPE_UNKNOWN;
766         private int mSource = MediaRecorder.AudioSource.AUDIO_SOURCE_INVALID;
767         private int mFlags = 0x0;
768         private boolean mMuteHapticChannels = true;
769         private boolean mIsContentSpatialized = false;
770         private int mSpatializationBehavior = SPATIALIZATION_BEHAVIOR_AUTO;
771         private HashSet<String> mTags = new HashSet<String>();
772         private Bundle mBundle;
773         private int mPrivacySensitive = PRIVACY_SENSITIVE_DEFAULT;
774 
775         private static final int PRIVACY_SENSITIVE_DEFAULT = -1;
776         private static final int PRIVACY_SENSITIVE_DISABLED = 0;
777         private static final int PRIVACY_SENSITIVE_ENABLED = 1;
778 
779         /**
780          * Constructs a new Builder with the defaults.
781          * By default, usage and content type are respectively {@link AudioAttributes#USAGE_UNKNOWN}
782          * and {@link AudioAttributes#CONTENT_TYPE_UNKNOWN}, and flags are 0. It is recommended to
783          * configure the usage (with {@link #setUsage(int)}) or deriving attributes from a legacy
784          * stream type (with {@link #setLegacyStreamType(int)}) before calling {@link #build()}
785          * to override any default playback behavior in terms of routing and volume management.
786          */
Builder()787         public Builder() {
788         }
789 
790         /**
791          * Constructs a new Builder from a given AudioAttributes
792          * @param aa the AudioAttributes object whose data will be reused in the new Builder.
793          */
794         @SuppressWarnings("unchecked") // for cloning of mTags
Builder(AudioAttributes aa)795         public Builder(AudioAttributes aa) {
796             mUsage = aa.mUsage;
797             mContentType = aa.mContentType;
798             mSource = aa.mSource;
799             mFlags = aa.getAllFlags();
800             mTags = (HashSet<String>) aa.mTags.clone();
801             mMuteHapticChannels = aa.areHapticChannelsMuted();
802             mIsContentSpatialized = aa.isContentSpatialized();
803             mSpatializationBehavior = aa.getSpatializationBehavior();
804             if ((mFlags & FLAG_CAPTURE_PRIVATE) != 0) {
805                 mPrivacySensitive = PRIVACY_SENSITIVE_ENABLED;
806             }
807         }
808 
809         /**
810          * Combines all of the attributes that have been set and return a new
811          * {@link AudioAttributes} object.
812          * @return a new {@link AudioAttributes} object
813          */
814         @SuppressWarnings("unchecked") // for cloning of mTags
build()815         public AudioAttributes build() {
816             AudioAttributes aa = new AudioAttributes();
817             aa.mContentType = mContentType;
818 
819             if (mUsage == USAGE_INVALID) {
820                 if (mSystemUsage == USAGE_INVALID) {
821                     aa.mUsage = USAGE_UNKNOWN;
822                 } else {
823                     aa.mUsage = mSystemUsage;
824                 }
825             } else {
826                 if (mSystemUsage == USAGE_INVALID) {
827                     aa.mUsage = mUsage;
828                 } else {
829                     throw new IllegalArgumentException(
830                             "Cannot set both usage and system usage on same builder");
831                 }
832             }
833 
834             // handle deprecation of notification usages by remapping to USAGE_NOTIFICATION
835             switch (aa.mUsage) {
836                 case USAGE_NOTIFICATION_COMMUNICATION_REQUEST:
837                 case USAGE_NOTIFICATION_COMMUNICATION_INSTANT:
838                 case USAGE_NOTIFICATION_COMMUNICATION_DELAYED:
839                     aa.mUsage = USAGE_NOTIFICATION;
840                     break;
841                 default:
842                     break;
843             }
844 
845             aa.mSource = mSource;
846             aa.mFlags = mFlags;
847             if (mMuteHapticChannels) {
848                 aa.mFlags |= FLAG_MUTE_HAPTIC;
849             }
850             if (mIsContentSpatialized) {
851                 aa.mFlags |= FLAG_CONTENT_SPATIALIZED;
852             }
853             if (mSpatializationBehavior == SPATIALIZATION_BEHAVIOR_NEVER) {
854                 aa.mFlags |= FLAG_NEVER_SPATIALIZE;
855             }
856 
857             if (mPrivacySensitive == PRIVACY_SENSITIVE_DEFAULT) {
858                 // capturing for camcorder or communication is private by default to
859                 // reflect legacy behavior
860                 if (mSource == MediaRecorder.AudioSource.VOICE_COMMUNICATION
861                         || mSource == MediaRecorder.AudioSource.CAMCORDER) {
862                     aa.mFlags |= FLAG_CAPTURE_PRIVATE;
863                 } else {
864                     aa.mFlags &= ~FLAG_CAPTURE_PRIVATE;
865                 }
866             } else if (mPrivacySensitive == PRIVACY_SENSITIVE_ENABLED) {
867                 aa.mFlags |= FLAG_CAPTURE_PRIVATE;
868             } else {
869                 aa.mFlags &= ~FLAG_CAPTURE_PRIVATE;
870             }
871             aa.mTags = (HashSet<String>) mTags.clone();
872             aa.mFormattedTags = TextUtils.join(";", mTags);
873             if (mBundle != null) {
874                 aa.mBundle = new Bundle(mBundle);
875             }
876 
877             // Allow the FLAG_HW_HOTWORD only for AudioSource.VOICE_RECOGNITION
878             if (mSource != MediaRecorder.AudioSource.VOICE_RECOGNITION
879                     && (mFlags & FLAG_HW_HOTWORD) == FLAG_HW_HOTWORD) {
880                 aa.mFlags &= ~FLAG_HW_HOTWORD;
881             }
882             return aa;
883         }
884 
885         /**
886          * Sets the attribute describing what is the intended use of the audio signal,
887          * such as alarm or ringtone.
888          * @param usage the usage to set.
889          * @return the same Builder instance.
890          */
setUsage(@ttributeSdkUsage int usage)891         public Builder setUsage(@AttributeSdkUsage int usage) {
892             switch (usage) {
893                 case USAGE_UNKNOWN:
894                 case USAGE_MEDIA:
895                 case USAGE_VOICE_COMMUNICATION:
896                 case USAGE_VOICE_COMMUNICATION_SIGNALLING:
897                 case USAGE_ALARM:
898                 case USAGE_NOTIFICATION:
899                 case USAGE_NOTIFICATION_RINGTONE:
900                 case USAGE_NOTIFICATION_COMMUNICATION_REQUEST:
901                 case USAGE_NOTIFICATION_COMMUNICATION_INSTANT:
902                 case USAGE_NOTIFICATION_COMMUNICATION_DELAYED:
903                 case USAGE_NOTIFICATION_EVENT:
904                 case USAGE_ASSISTANCE_ACCESSIBILITY:
905                 case USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:
906                 case USAGE_ASSISTANCE_SONIFICATION:
907                 case USAGE_GAME:
908                 case USAGE_VIRTUAL_SOURCE:
909                 case USAGE_ASSISTANT:
910                     mUsage = usage;
911                     break;
912                 default:
913                     throw new IllegalArgumentException("Invalid usage " + usage);
914             }
915             return this;
916         }
917 
918         /**
919          * @hide
920          * Sets the attribute describing what is the intended use of the audio signal for categories
921          * of sounds restricted to the system, such as vehicle status or emergency.
922          *
923          * <p>Note that the AudioAttributes have a single usage value, therefore it is illegal to
924          * call both this method and {@link #setUsage(int)}.
925          * @param systemUsage the system-restricted usage.
926          * @return the same Builder instance.
927          */
928         @SystemApi
929         @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
setSystemUsage(@ttributeSystemUsage int systemUsage)930         public @NonNull Builder setSystemUsage(@AttributeSystemUsage int systemUsage) {
931             if (isSystemUsage(systemUsage)) {
932                 mSystemUsage = systemUsage;
933             } else {
934                 throw new IllegalArgumentException("Invalid system usage " + systemUsage);
935             }
936 
937             return this;
938         }
939 
940         /**
941          * Sets the attribute describing the content type of the audio signal, such as speech,
942          * or music.
943          * @param contentType the content type values, one of
944          *     {@link AudioAttributes#CONTENT_TYPE_MOVIE},
945          *     {@link AudioAttributes#CONTENT_TYPE_MUSIC},
946          *     {@link AudioAttributes#CONTENT_TYPE_SONIFICATION},
947          *     {@link AudioAttributes#CONTENT_TYPE_SPEECH},
948          *     {@link AudioAttributes#CONTENT_TYPE_UNKNOWN}.
949          * @return the same Builder instance.
950          */
setContentType(@ttributeContentType int contentType)951         public Builder setContentType(@AttributeContentType int contentType) {
952             switch (contentType) {
953                 case CONTENT_TYPE_UNKNOWN:
954                 case CONTENT_TYPE_MOVIE:
955                 case CONTENT_TYPE_MUSIC:
956                 case CONTENT_TYPE_SONIFICATION:
957                 case CONTENT_TYPE_SPEECH:
958                     mContentType = contentType;
959                     break;
960                 default:
961                     throw new IllegalArgumentException("Invalid content type " + contentType);
962             }
963             return this;
964         }
965 
966         /**
967          * @hide
968          * Sets the attribute describing the content type of the audio signal, such as speech,
969          * , music or ultrasound.
970          * @param contentType the content type values.
971          * @return the same Builder instance.
972          */
973         @SystemApi
setInternalContentType(@ttrInternalContentType int contentType)974         public @NonNull Builder setInternalContentType(@AttrInternalContentType int contentType) {
975             switch (contentType) {
976                 case CONTENT_TYPE_ULTRASOUND:
977                     mContentType = contentType;
978                     break;
979                 default:
980                     setContentType(contentType);
981                     break;
982             }
983             return this;
984         }
985 
986         /**
987          * Sets the combination of flags.
988          *
989          * This is a bitwise OR with the existing flags.
990          * @param flags a combination of {@link AudioAttributes#FLAG_AUDIBILITY_ENFORCED},
991          *    {@link AudioAttributes#FLAG_HW_AV_SYNC}.
992          * @return the same Builder instance.
993          */
setFlags(int flags)994         public Builder setFlags(int flags) {
995             flags &= AudioAttributes.FLAG_ALL_API_SET;
996             mFlags |= flags;
997             return this;
998         }
999 
1000         /**
1001          * @hide
1002          * Request for capture in hotword mode.
1003          *
1004          * Requests an audio path optimized for Hotword detection use cases from
1005          * the low power audio DSP. This is valid only for capture with
1006          * audio source {@link MediaRecorder.AudioSource#VOICE_RECOGNITION}.
1007          * There is no guarantee that this mode is available on the device.
1008          * @return the same Builder instance.
1009          */
1010         @SystemApi
1011         @RequiresPermission(android.Manifest.permission.CAPTURE_AUDIO_HOTWORD)
setHotwordModeEnabled(boolean enable)1012         public @NonNull Builder setHotwordModeEnabled(boolean enable) {
1013             if (enable) {
1014                 mFlags |= FLAG_HW_HOTWORD;
1015             } else {
1016                 mFlags &= ~FLAG_HW_HOTWORD;
1017             }
1018             return this;
1019         }
1020 
1021         /**
1022          * Specifies whether the audio may or may not be captured by other apps or the system.
1023          *
1024          * The default is {@link AudioAttributes#ALLOW_CAPTURE_BY_ALL}.
1025          *
1026          * There are multiple ways to set this policy:
1027          * <ul>
1028          * <li> for each track independently, with this method </li>
1029          * <li> application-wide at runtime, with
1030          *      {@link AudioManager#setAllowedCapturePolicy(int)} </li>
1031          * <li> application-wide at build time, see {@code allowAudioPlaybackCapture} in the
1032          *      application manifest. </li>
1033          * </ul>
1034          * The most restrictive policy is always applied.
1035          *
1036          * See {@link AudioPlaybackCaptureConfiguration} for more details on
1037          * which audio signals can be captured.
1038          *
1039          * @return the same Builder instance
1040          * @throws IllegalArgumentException if the argument is not a valid value.
1041          */
setAllowedCapturePolicy(@apturePolicy int capturePolicy)1042         public @NonNull Builder setAllowedCapturePolicy(@CapturePolicy int capturePolicy) {
1043             mFlags = capturePolicyToFlags(capturePolicy, mFlags);
1044             return this;
1045         }
1046 
1047         /**
1048          * Specifies whether the content has already been processed for spatialization.
1049          * If it has, setting this to true will prevent issues such as double-processing.
1050          * @param isSpatialized
1051          * @return the same Builder instance
1052          */
setIsContentSpatialized(boolean isSpatialized)1053         public @NonNull Builder setIsContentSpatialized(boolean isSpatialized) {
1054             mIsContentSpatialized = isSpatialized;
1055             return this;
1056         }
1057 
1058         /**
1059          * Sets the behavior affecting whether spatialization will be used.
1060          * @param sb the spatialization behavior
1061          * @return the same Builder instance
1062          *
1063          */
setSpatializationBehavior(@patializationBehavior int sb)1064         public @NonNull Builder setSpatializationBehavior(@SpatializationBehavior int sb) {
1065             switch (sb) {
1066                 case SPATIALIZATION_BEHAVIOR_NEVER:
1067                 case SPATIALIZATION_BEHAVIOR_AUTO:
1068                     break;
1069                 default:
1070                     throw new IllegalArgumentException("Invalid spatialization behavior " + sb);
1071             }
1072             mSpatializationBehavior = sb;
1073             return this;
1074         }
1075 
1076         /**
1077          * @hide
1078          * Replaces flags.
1079          * @param flags any combination of {@link AudioAttributes#FLAG_ALL}.
1080          * @return the same Builder instance.
1081          */
replaceFlags(int flags)1082         public Builder replaceFlags(int flags) {
1083             mFlags = flags & AudioAttributes.FLAG_ALL;
1084             return this;
1085         }
1086 
1087         /**
1088          * @hide
1089          * Adds a Bundle of data
1090          * @param bundle a non-null Bundle
1091          * @return the same builder instance
1092          */
1093         @SystemApi
addBundle(@onNull Bundle bundle)1094         public Builder addBundle(@NonNull Bundle bundle) {
1095             if (bundle == null) {
1096                 throw new IllegalArgumentException("Illegal null bundle");
1097             }
1098             if (mBundle == null) {
1099                 mBundle = new Bundle(bundle);
1100             } else {
1101                 mBundle.putAll(bundle);
1102             }
1103             return this;
1104         }
1105 
1106         /**
1107          * @hide
1108          * Add a custom tag stored as a string
1109          * @param tag
1110          * @return the same Builder instance.
1111          */
1112         @UnsupportedAppUsage
addTag(String tag)1113         public Builder addTag(String tag) {
1114             mTags.add(tag);
1115             return this;
1116         }
1117 
1118         /**
1119          * @hide
1120          * Replace all custom tags
1121          * @param tags
1122          * @return the same Builder instance.
1123          */
replaceTags(HashSet<String> tags)1124         public Builder replaceTags(HashSet<String> tags) {
1125             mTags = (HashSet<String>) tags.clone();
1126             return this;
1127         }
1128 
1129         /**
1130          * Sets attributes as inferred from the legacy stream types.
1131          * Warning: do not use this method in combination with setting any other attributes such as
1132          * usage, content type, flags or haptic control, as this method will overwrite (the more
1133          * accurate) information describing the use case previously set in the <code>Builder</code>.
1134          * In general, avoid using it and prefer setting usage and content type directly
1135          * with {@link #setUsage(int)} and {@link #setContentType(int)}.
1136          * <p>Use this method when building an {@link AudioAttributes} instance to initialize some
1137          * of the attributes by information derived from a legacy stream type.
1138          * @param streamType one of {@link AudioManager#STREAM_VOICE_CALL},
1139          *   {@link AudioManager#STREAM_SYSTEM}, {@link AudioManager#STREAM_RING},
1140          *   {@link AudioManager#STREAM_MUSIC}, {@link AudioManager#STREAM_ALARM},
1141          *    or {@link AudioManager#STREAM_NOTIFICATION}.
1142          * @return the same Builder instance.
1143          */
setLegacyStreamType(int streamType)1144         public Builder setLegacyStreamType(int streamType) {
1145             if (streamType == AudioManager.STREAM_ACCESSIBILITY) {
1146                 throw new IllegalArgumentException("STREAM_ACCESSIBILITY is not a legacy stream "
1147                         + "type that was used for audio playback");
1148             }
1149             setInternalLegacyStreamType(streamType);
1150             return this;
1151         }
1152 
1153         /**
1154          * @hide
1155          * For internal framework use only, enables building from hidden stream types.
1156          * @param streamType
1157          * @return the same Builder instance.
1158          */
1159         @UnsupportedAppUsage
setInternalLegacyStreamType(int streamType)1160         public Builder setInternalLegacyStreamType(int streamType) {
1161             mContentType = CONTENT_TYPE_UNKNOWN;
1162             mUsage = USAGE_UNKNOWN;
1163             if (AudioProductStrategy.getAudioProductStrategies().size() > 0) {
1164                 AudioAttributes attributes =
1165                         AudioProductStrategy.getAudioAttributesForStrategyWithLegacyStreamType(
1166                                 streamType);
1167                 if (attributes != null) {
1168                     mUsage = attributes.mUsage;
1169                     // on purpose ignoring the content type: stream types are deprecated for
1170                     // playback, making assumptions about the content type is prone to
1171                     // interpretation errors for ambiguous types such as STREAM_TTS and STREAM_MUSIC
1172                     //mContentType = attributes.mContentType;
1173                     mFlags = attributes.getAllFlags();
1174                     mMuteHapticChannels = attributes.areHapticChannelsMuted();
1175                     mIsContentSpatialized = attributes.isContentSpatialized();
1176                     mSpatializationBehavior = attributes.getSpatializationBehavior();
1177                     mTags = attributes.mTags;
1178                     mBundle = attributes.mBundle;
1179                     mSource = attributes.mSource;
1180                 }
1181             }
1182             switch (streamType) {
1183                 case AudioSystem.STREAM_VOICE_CALL:
1184                     mContentType = CONTENT_TYPE_SPEECH;
1185                     break;
1186                 case AudioSystem.STREAM_SYSTEM_ENFORCED:
1187                     mFlags |= FLAG_AUDIBILITY_ENFORCED;
1188                     // intended fall through, attributes in common with STREAM_SYSTEM
1189                 case AudioSystem.STREAM_SYSTEM:
1190                     mContentType = CONTENT_TYPE_SONIFICATION;
1191                     break;
1192                 case AudioSystem.STREAM_RING:
1193                     mContentType = CONTENT_TYPE_SONIFICATION;
1194                     break;
1195                 case AudioSystem.STREAM_ALARM:
1196                     mContentType = CONTENT_TYPE_SONIFICATION;
1197                     break;
1198                 case AudioSystem.STREAM_NOTIFICATION:
1199                     mContentType = CONTENT_TYPE_SONIFICATION;
1200                     break;
1201                 case AudioSystem.STREAM_BLUETOOTH_SCO:
1202                     mContentType = CONTENT_TYPE_SPEECH;
1203                     mFlags |= FLAG_SCO;
1204                     break;
1205                 case AudioSystem.STREAM_DTMF:
1206                     mContentType = CONTENT_TYPE_SONIFICATION;
1207                     break;
1208                 case AudioSystem.STREAM_TTS:
1209                     mContentType = CONTENT_TYPE_SONIFICATION;
1210                     mFlags |= FLAG_BEACON;
1211                     break;
1212                 case AudioSystem.STREAM_ACCESSIBILITY:
1213                     mContentType = CONTENT_TYPE_SPEECH;
1214                     break;
1215                 case AudioSystem.STREAM_ASSISTANT:
1216                     mContentType = CONTENT_TYPE_SPEECH;
1217                     break;
1218                 case AudioSystem.STREAM_MUSIC:
1219                     // leaving as CONTENT_TYPE_UNKNOWN
1220                     break;
1221                 default:
1222                     Log.e(TAG, "Invalid stream type " + streamType + " for AudioAttributes");
1223             }
1224             if (mUsage == USAGE_UNKNOWN) {
1225                 mUsage = usageForStreamType(streamType);
1226             }
1227             return this;
1228         }
1229 
1230         /**
1231          * @hide
1232          * Sets the capture preset.
1233          * Use this audio attributes configuration method when building an {@link AudioRecord}
1234          * instance with {@link AudioRecord#AudioRecord(AudioAttributes, AudioFormat, int)}.
1235          * @param preset one of {@link MediaRecorder.AudioSource#DEFAULT},
1236          *     {@link MediaRecorder.AudioSource#MIC}, {@link MediaRecorder.AudioSource#CAMCORDER},
1237          *     {@link MediaRecorder.AudioSource#VOICE_RECOGNITION},
1238          *     {@link MediaRecorder.AudioSource#VOICE_COMMUNICATION},
1239          *     {@link MediaRecorder.AudioSource#UNPROCESSED} or
1240          *     {@link MediaRecorder.AudioSource#VOICE_PERFORMANCE}
1241          * @return the same Builder instance.
1242          */
1243         @SystemApi
setCapturePreset(int preset)1244         public Builder setCapturePreset(int preset) {
1245             switch (preset) {
1246                 case MediaRecorder.AudioSource.DEFAULT:
1247                 case MediaRecorder.AudioSource.MIC:
1248                 case MediaRecorder.AudioSource.CAMCORDER:
1249                 case MediaRecorder.AudioSource.VOICE_RECOGNITION:
1250                 case MediaRecorder.AudioSource.VOICE_COMMUNICATION:
1251                 case MediaRecorder.AudioSource.UNPROCESSED:
1252                 case MediaRecorder.AudioSource.VOICE_PERFORMANCE:
1253                     mSource = preset;
1254                     break;
1255                 default:
1256                     Log.e(TAG, "Invalid capture preset " + preset + " for AudioAttributes");
1257             }
1258             return this;
1259         }
1260 
1261         /**
1262          * @hide
1263          * Same as {@link #setCapturePreset(int)} but authorizes the use of HOTWORD,
1264          * REMOTE_SUBMIX, RADIO_TUNER, VOICE_DOWNLINK, VOICE_UPLINK, VOICE_CALL, ECHO_REFERENCE
1265          * and ULTRASOUND
1266          * @param preset
1267          * @return the same Builder instance.
1268          */
1269         @SystemApi
setInternalCapturePreset(int preset)1270         public Builder setInternalCapturePreset(int preset) {
1271             if ((preset == MediaRecorder.AudioSource.HOTWORD)
1272                     || (preset == MediaRecorder.AudioSource.REMOTE_SUBMIX)
1273                     || (preset == MediaRecorder.AudioSource.RADIO_TUNER)
1274                     || (preset == MediaRecorder.AudioSource.VOICE_DOWNLINK)
1275                     || (preset == MediaRecorder.AudioSource.VOICE_UPLINK)
1276                     || (preset == MediaRecorder.AudioSource.VOICE_CALL)
1277                     || (preset == MediaRecorder.AudioSource.ECHO_REFERENCE)
1278                     || (preset == MediaRecorder.AudioSource.ULTRASOUND)
1279                     // AUDIO_SOURCE_INVALID is used by convention on default initialized
1280                     // audio attributes
1281                     || (preset == MediaRecorder.AudioSource.AUDIO_SOURCE_INVALID)) {
1282                 mSource = preset;
1283             } else {
1284                 setCapturePreset(preset);
1285             }
1286             return this;
1287         }
1288 
1289         /**
1290          * Specifying if haptic should be muted or not when playing audio-haptic coupled data.
1291          * By default, haptic channels are disabled.
1292          * <p>This will be ignored if the caller doesn't have the
1293          * {@link android.Manifest.permission#VIBRATE} permission.
1294          * @param muted true to force muting haptic channels.
1295          * @return the same Builder instance.
1296          */
setHapticChannelsMuted(boolean muted)1297         public @NonNull Builder setHapticChannelsMuted(boolean muted) {
1298             mMuteHapticChannels = muted;
1299             return this;
1300         }
1301 
1302         /**
1303          * @hide
1304          * Indicates if an AudioRecord build with this AudioAttributes is privacy sensitive or not.
1305          * See {@link AudioRecord.Builder#setPrivacySensitive(boolean)}.
1306          * @param privacySensitive True if capture must be marked as privacy sensitive,
1307          * false otherwise.
1308          * @return the same Builder instance.
1309          */
setPrivacySensitive(boolean privacySensitive)1310         public @NonNull Builder setPrivacySensitive(boolean privacySensitive) {
1311             mPrivacySensitive =
1312                 privacySensitive ? PRIVACY_SENSITIVE_ENABLED : PRIVACY_SENSITIVE_DISABLED;
1313             return this;
1314         }
1315 
1316         /**
1317          * @hide
1318          * Designates the audio to be used for call redirection
1319          * @return the same Builder instance.
1320          */
setForCallRedirection()1321         public Builder setForCallRedirection() {
1322             mFlags |= FLAG_CALL_REDIRECTION;
1323             return this;
1324         }
1325     };
1326 
1327     @Override
describeContents()1328     public int describeContents() {
1329         return 0;
1330     }
1331 
1332     /**
1333      * @hide
1334      * Used to indicate that when parcelling, the tags should be parcelled through the flattened
1335      * formatted string, not through the array of strings.
1336      * Keep in sync with frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp
1337      * see definition of kAudioAttributesMarshallTagFlattenTags
1338      */
1339     public final static int FLATTEN_TAGS = 0x1;
1340 
1341     private final static int ATTR_PARCEL_IS_NULL_BUNDLE = -1977;
1342     private final static int ATTR_PARCEL_IS_VALID_BUNDLE = 1980;
1343 
1344     /**
1345      * When adding tags for writeToParcel(Parcel, int), add them in the list of flags (| NEW_FLAG)
1346      */
1347     private final static int ALL_PARCEL_FLAGS = FLATTEN_TAGS;
1348     @Override
writeToParcel(Parcel dest, int flags)1349     public void writeToParcel(Parcel dest, int flags) {
1350         dest.writeInt(mUsage);
1351         dest.writeInt(mContentType);
1352         dest.writeInt(mSource);
1353         dest.writeInt(mFlags);
1354         dest.writeInt(flags & ALL_PARCEL_FLAGS);
1355         if ((flags & FLATTEN_TAGS) == 0) {
1356             String[] tagsArray = new String[mTags.size()];
1357             mTags.toArray(tagsArray);
1358             dest.writeStringArray(tagsArray);
1359         } else if ((flags & FLATTEN_TAGS) == FLATTEN_TAGS) {
1360             dest.writeString(mFormattedTags);
1361         }
1362         if (mBundle == null) {
1363             dest.writeInt(ATTR_PARCEL_IS_NULL_BUNDLE);
1364         } else {
1365             dest.writeInt(ATTR_PARCEL_IS_VALID_BUNDLE);
1366             dest.writeBundle(mBundle);
1367         }
1368     }
1369 
AudioAttributes(Parcel in)1370     private AudioAttributes(Parcel in) {
1371         mUsage = in.readInt();
1372         mContentType = in.readInt();
1373         mSource = in.readInt();
1374         mFlags = in.readInt();
1375         boolean hasFlattenedTags = ((in.readInt() & FLATTEN_TAGS) == FLATTEN_TAGS);
1376         mTags = new HashSet<String>();
1377         if (hasFlattenedTags) {
1378             mFormattedTags = new String(in.readString());
1379             mTags.add(mFormattedTags);
1380         } else {
1381             String[] tagsArray = in.readStringArray();
1382             for (int i = tagsArray.length - 1 ; i >= 0 ; i--) {
1383                 mTags.add(tagsArray[i]);
1384             }
1385             mFormattedTags = TextUtils.join(";", mTags);
1386         }
1387         switch (in.readInt()) {
1388             case ATTR_PARCEL_IS_NULL_BUNDLE:
1389                 mBundle = null;
1390                 break;
1391             case ATTR_PARCEL_IS_VALID_BUNDLE:
1392                 mBundle = new Bundle(in.readBundle());
1393                 break;
1394             default:
1395                 Log.e(TAG, "Illegal value unmarshalling AudioAttributes, can't initialize bundle");
1396         }
1397     }
1398 
1399     public static final @android.annotation.NonNull Parcelable.Creator<AudioAttributes> CREATOR
1400             = new Parcelable.Creator<AudioAttributes>() {
1401         /**
1402          * Rebuilds an AudioAttributes previously stored with writeToParcel().
1403          * @param p Parcel object to read the AudioAttributes from
1404          * @return a new AudioAttributes created from the data in the parcel
1405          */
1406         public AudioAttributes createFromParcel(Parcel p) {
1407             return new AudioAttributes(p);
1408         }
1409         public AudioAttributes[] newArray(int size) {
1410             return new AudioAttributes[size];
1411         }
1412     };
1413 
1414     @Override
equals(Object o)1415     public boolean equals(Object o) {
1416         if (this == o) return true;
1417         if (o == null || getClass() != o.getClass()) return false;
1418 
1419         AudioAttributes that = (AudioAttributes) o;
1420 
1421         return ((mContentType == that.mContentType)
1422                 && (mFlags == that.mFlags)
1423                 && (mSource == that.mSource)
1424                 && (mUsage == that.mUsage)
1425                 //mFormattedTags is never null due to assignment in Builder or unmarshalling
1426                 && (mFormattedTags.equals(that.mFormattedTags)));
1427     }
1428 
1429     @Override
hashCode()1430     public int hashCode() {
1431         return Objects.hash(mContentType, mFlags, mSource, mUsage, mFormattedTags, mBundle);
1432     }
1433 
1434     @Override
toString()1435     public String toString () {
1436         return new String("AudioAttributes:"
1437                 + " usage=" + usageToString()
1438                 + " content=" + contentTypeToString()
1439                 + (mSource != MediaRecorder.AudioSource.AUDIO_SOURCE_INVALID
1440                     ? " source=" + MediaRecorder.toLogFriendlyAudioSource(mSource) : "")
1441                 + " flags=0x" + Integer.toHexString(mFlags).toUpperCase()
1442                 + " tags=" + mFormattedTags
1443                 + " bundle=" + (mBundle == null ? "null" : mBundle.toString()));
1444     }
1445 
1446     /** @hide */
dumpDebug(ProtoOutputStream proto, long fieldId)1447     public void dumpDebug(ProtoOutputStream proto, long fieldId) {
1448         final long token = proto.start(fieldId);
1449 
1450         proto.write(AudioAttributesProto.USAGE, mUsage);
1451         proto.write(AudioAttributesProto.CONTENT_TYPE, mContentType);
1452         proto.write(AudioAttributesProto.FLAGS, mFlags);
1453         // mFormattedTags is never null due to assignment in Builder or unmarshalling.
1454         for (String t : mFormattedTags.split(";")) {
1455             t = t.trim();
1456             if (t != "") {
1457                 proto.write(AudioAttributesProto.TAGS, t);
1458             }
1459         }
1460         // TODO: is the data in mBundle useful for debugging?
1461 
1462         proto.end(token);
1463     }
1464 
1465     /** @hide */
usageToString()1466     public String usageToString() {
1467         return usageToString(mUsage);
1468     }
1469 
1470     /**
1471      * Returns the string representation for the usage constant passed as parameter.
1472      *
1473      * @param usage one of the {@link AudioAttributes} usage constants
1474      * @return string representing the {@link AudioAttributes} usage constant passed as a parameter
1475      *
1476      * @hide
1477      */
1478     @NonNull
usageToString(@ttributeSdkUsage int usage)1479     public static String usageToString(@AttributeSdkUsage int usage) {
1480         switch(usage) {
1481             case USAGE_UNKNOWN:
1482                 return "USAGE_UNKNOWN";
1483             case USAGE_MEDIA:
1484                 return "USAGE_MEDIA";
1485             case USAGE_VOICE_COMMUNICATION:
1486                 return "USAGE_VOICE_COMMUNICATION";
1487             case USAGE_VOICE_COMMUNICATION_SIGNALLING:
1488                 return "USAGE_VOICE_COMMUNICATION_SIGNALLING";
1489             case USAGE_ALARM:
1490                 return "USAGE_ALARM";
1491             case USAGE_NOTIFICATION:
1492                 return "USAGE_NOTIFICATION";
1493             case USAGE_NOTIFICATION_RINGTONE:
1494                 return "USAGE_NOTIFICATION_RINGTONE";
1495             case USAGE_NOTIFICATION_COMMUNICATION_REQUEST:
1496                 return "USAGE_NOTIFICATION_COMMUNICATION_REQUEST";
1497             case USAGE_NOTIFICATION_COMMUNICATION_INSTANT:
1498                 return "USAGE_NOTIFICATION_COMMUNICATION_INSTANT";
1499             case USAGE_NOTIFICATION_COMMUNICATION_DELAYED:
1500                 return "USAGE_NOTIFICATION_COMMUNICATION_DELAYED";
1501             case USAGE_NOTIFICATION_EVENT:
1502                 return "USAGE_NOTIFICATION_EVENT";
1503             case USAGE_ASSISTANCE_ACCESSIBILITY:
1504                 return "USAGE_ASSISTANCE_ACCESSIBILITY";
1505             case USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:
1506                 return "USAGE_ASSISTANCE_NAVIGATION_GUIDANCE";
1507             case USAGE_ASSISTANCE_SONIFICATION:
1508                 return "USAGE_ASSISTANCE_SONIFICATION";
1509             case USAGE_GAME:
1510                 return "USAGE_GAME";
1511             case USAGE_ASSISTANT:
1512                 return "USAGE_ASSISTANT";
1513             case USAGE_CALL_ASSISTANT:
1514                 return "USAGE_CALL_ASSISTANT";
1515             case USAGE_EMERGENCY:
1516                 return "USAGE_EMERGENCY";
1517             case USAGE_SAFETY:
1518                 return "USAGE_SAFETY";
1519             case USAGE_VEHICLE_STATUS:
1520                 return "USAGE_VEHICLE_STATUS";
1521             case USAGE_ANNOUNCEMENT:
1522                 return "USAGE_ANNOUNCEMENT";
1523             default:
1524                 return "unknown usage " + usage;
1525         }
1526     }
1527 
1528     /** @hide **/
1529     @TestApi
1530     @NonNull
usageToXsdString(@ttributeUsage int usage)1531     public static String usageToXsdString(@AttributeUsage int usage) {
1532         switch (usage) {
1533             case AudioAttributes.USAGE_UNKNOWN:
1534                 return AudioUsage.AUDIO_USAGE_UNKNOWN.toString();
1535             case AudioAttributes.USAGE_MEDIA:
1536                 return AudioUsage.AUDIO_USAGE_MEDIA.toString();
1537             case AudioAttributes.USAGE_VOICE_COMMUNICATION:
1538                 return AudioUsage.AUDIO_USAGE_VOICE_COMMUNICATION.toString();
1539             case AudioAttributes.USAGE_VOICE_COMMUNICATION_SIGNALLING:
1540                 return AudioUsage.AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING.toString();
1541             case AudioAttributes.USAGE_ALARM:
1542                 return AudioUsage.AUDIO_USAGE_ALARM.toString();
1543             case AudioAttributes.USAGE_NOTIFICATION:
1544                 return AudioUsage.AUDIO_USAGE_NOTIFICATION.toString();
1545             case AudioAttributes.USAGE_NOTIFICATION_RINGTONE:
1546                 return AudioUsage.AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE.toString();
1547             case AudioAttributes.USAGE_ASSISTANCE_ACCESSIBILITY:
1548                 return AudioUsage.AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY.toString();
1549             case AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:
1550                 return AudioUsage.AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE.toString();
1551             case AudioAttributes.USAGE_ASSISTANCE_SONIFICATION:
1552                 return AudioUsage.AUDIO_USAGE_ASSISTANCE_SONIFICATION.toString();
1553             case AudioAttributes.USAGE_GAME:
1554                 return AudioUsage.AUDIO_USAGE_GAME.toString();
1555             case AudioAttributes.USAGE_VIRTUAL_SOURCE:
1556                 return AudioUsage.AUDIO_USAGE_VIRTUAL_SOURCE.toString();
1557             case AudioAttributes.USAGE_ASSISTANT:
1558                 return AudioUsage.AUDIO_USAGE_ASSISTANT.toString();
1559             case AudioAttributes.USAGE_CALL_ASSISTANT:
1560                 return AudioUsage.AUDIO_USAGE_CALL_ASSISTANT.toString();
1561             case AudioAttributes.USAGE_EMERGENCY:
1562                 return AudioUsage.AUDIO_USAGE_EMERGENCY.toString();
1563             case AudioAttributes.USAGE_SAFETY:
1564                 return AudioUsage.AUDIO_USAGE_SAFETY.toString();
1565             case AudioAttributes.USAGE_VEHICLE_STATUS:
1566                 return AudioUsage.AUDIO_USAGE_VEHICLE_STATUS.toString();
1567             case AudioAttributes.USAGE_ANNOUNCEMENT:
1568                 return AudioUsage.AUDIO_USAGE_ANNOUNCEMENT.toString();
1569             default:
1570                 Log.w(TAG, "Unknown usage value " + usage);
1571                 return AudioUsage.AUDIO_USAGE_UNKNOWN.toString();
1572         }
1573     }
1574 
1575     private static final Map<String, Integer> sXsdStringToUsage = new HashMap<>();
1576 
1577     static {
AudioUsage.AUDIO_USAGE_UNKNOWN.toString()1578         sXsdStringToUsage.put(AudioUsage.AUDIO_USAGE_UNKNOWN.toString(), USAGE_UNKNOWN);
AudioUsage.AUDIO_USAGE_UNKNOWN.toString()1579         sXsdStringToUsage.put(AudioUsage.AUDIO_USAGE_UNKNOWN.toString(), USAGE_UNKNOWN);
AudioUsage.AUDIO_USAGE_MEDIA.toString()1580         sXsdStringToUsage.put(AudioUsage.AUDIO_USAGE_MEDIA.toString(), USAGE_MEDIA);
AudioUsage.AUDIO_USAGE_VOICE_COMMUNICATION.toString()1581         sXsdStringToUsage.put(AudioUsage.AUDIO_USAGE_VOICE_COMMUNICATION.toString(),
1582                 USAGE_VOICE_COMMUNICATION);
AudioUsage.AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING.toString()1583         sXsdStringToUsage.put(AudioUsage.AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING.toString(),
1584                 USAGE_VOICE_COMMUNICATION_SIGNALLING);
AudioUsage.AUDIO_USAGE_ALARM.toString()1585         sXsdStringToUsage.put(AudioUsage.AUDIO_USAGE_ALARM.toString(), USAGE_ALARM);
AudioUsage.AUDIO_USAGE_NOTIFICATION.toString()1586         sXsdStringToUsage.put(AudioUsage.AUDIO_USAGE_NOTIFICATION.toString(), USAGE_NOTIFICATION);
AudioUsage.AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE.toString()1587         sXsdStringToUsage.put(AudioUsage.AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE.toString(),
1588                 USAGE_NOTIFICATION_RINGTONE);
AudioUsage.AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY.toString()1589         sXsdStringToUsage.put(AudioUsage.AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY.toString(),
1590                 USAGE_ASSISTANCE_ACCESSIBILITY);
AudioUsage.AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE.toString()1591         sXsdStringToUsage.put(AudioUsage.AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE.toString(),
1592                 USAGE_ASSISTANCE_NAVIGATION_GUIDANCE);
AudioUsage.AUDIO_USAGE_ASSISTANCE_SONIFICATION.toString()1593         sXsdStringToUsage.put(AudioUsage.AUDIO_USAGE_ASSISTANCE_SONIFICATION.toString(),
1594                 USAGE_ASSISTANCE_SONIFICATION);
AudioUsage.AUDIO_USAGE_GAME.toString()1595         sXsdStringToUsage.put(AudioUsage.AUDIO_USAGE_GAME.toString(), USAGE_GAME);
AudioUsage.AUDIO_USAGE_VIRTUAL_SOURCE.toString()1596         sXsdStringToUsage.put(AudioUsage.AUDIO_USAGE_VIRTUAL_SOURCE.toString(),
1597                 USAGE_VIRTUAL_SOURCE);
AudioUsage.AUDIO_USAGE_ASSISTANT.toString()1598         sXsdStringToUsage.put(AudioUsage.AUDIO_USAGE_ASSISTANT.toString(), USAGE_ASSISTANT);
AudioUsage.AUDIO_USAGE_CALL_ASSISTANT.toString()1599         sXsdStringToUsage.put(AudioUsage.AUDIO_USAGE_CALL_ASSISTANT.toString(),
1600                 USAGE_CALL_ASSISTANT);
AudioUsage.AUDIO_USAGE_EMERGENCY.toString()1601         sXsdStringToUsage.put(AudioUsage.AUDIO_USAGE_EMERGENCY.toString(), USAGE_EMERGENCY);
AudioUsage.AUDIO_USAGE_SAFETY.toString()1602         sXsdStringToUsage.put(AudioUsage.AUDIO_USAGE_SAFETY.toString(), USAGE_SAFETY);
AudioUsage.AUDIO_USAGE_VEHICLE_STATUS.toString()1603         sXsdStringToUsage.put(AudioUsage.AUDIO_USAGE_VEHICLE_STATUS.toString(),
1604                 USAGE_VEHICLE_STATUS);
AudioUsage.AUDIO_USAGE_ANNOUNCEMENT.toString()1605         sXsdStringToUsage.put(AudioUsage.AUDIO_USAGE_ANNOUNCEMENT.toString(), USAGE_ANNOUNCEMENT);
1606     }
1607 
1608     /** @hide **/
1609     @TestApi
xsdStringToUsage(@onNull String xsdUsage)1610     public static @AttributeUsage int xsdStringToUsage(@NonNull String xsdUsage) {
1611         if (sXsdStringToUsage.containsKey(xsdUsage)) {
1612             return sXsdStringToUsage.get(xsdUsage);
1613         } else {
1614             Log.w(TAG, "Usage name not found in AudioUsage enum: " + xsdUsage);
1615             return USAGE_UNKNOWN;
1616         }
1617     }
1618 
1619     /** @hide */
contentTypeToString()1620     public String contentTypeToString() {
1621         switch(mContentType) {
1622             case CONTENT_TYPE_UNKNOWN:
1623                 return new String("CONTENT_TYPE_UNKNOWN");
1624             case CONTENT_TYPE_SPEECH: return new String("CONTENT_TYPE_SPEECH");
1625             case CONTENT_TYPE_MUSIC: return new String("CONTENT_TYPE_MUSIC");
1626             case CONTENT_TYPE_MOVIE: return new String("CONTENT_TYPE_MOVIE");
1627             case CONTENT_TYPE_SONIFICATION: return new String("CONTENT_TYPE_SONIFICATION");
1628             case CONTENT_TYPE_ULTRASOUND: return new String("CONTENT_TYPE_ULTRASOUND");
1629             default: return new String("unknown content type " + mContentType);
1630         }
1631     }
1632 
usageForStreamType(int streamType)1633     private static int usageForStreamType(int streamType) {
1634         switch(streamType) {
1635             case AudioSystem.STREAM_VOICE_CALL:
1636                 return USAGE_VOICE_COMMUNICATION;
1637             case AudioSystem.STREAM_SYSTEM_ENFORCED:
1638             case AudioSystem.STREAM_SYSTEM:
1639                 return USAGE_ASSISTANCE_SONIFICATION;
1640             case AudioSystem.STREAM_RING:
1641                 return USAGE_NOTIFICATION_RINGTONE;
1642             case AudioSystem.STREAM_MUSIC:
1643                 return USAGE_MEDIA;
1644             case AudioSystem.STREAM_ALARM:
1645                 return USAGE_ALARM;
1646             case AudioSystem.STREAM_NOTIFICATION:
1647                 return USAGE_NOTIFICATION;
1648             case AudioSystem.STREAM_BLUETOOTH_SCO:
1649                 return USAGE_VOICE_COMMUNICATION;
1650             case AudioSystem.STREAM_DTMF:
1651                 return USAGE_VOICE_COMMUNICATION_SIGNALLING;
1652             case AudioSystem.STREAM_ACCESSIBILITY:
1653                 return USAGE_ASSISTANCE_ACCESSIBILITY;
1654             case AudioSystem.STREAM_ASSISTANT:
1655                 return USAGE_ASSISTANT;
1656             case AudioSystem.STREAM_TTS:
1657             default:
1658                 return USAGE_UNKNOWN;
1659         }
1660     }
1661 
1662     /**
1663      * @param usage one of {@link AttributeSystemUsage},
1664      *     {@link AttributeSystemUsage#USAGE_CALL_ASSISTANT},
1665      *     {@link AttributeSystemUsage#USAGE_EMERGENCY},
1666      *     {@link AttributeSystemUsage#USAGE_SAFETY},
1667      *     {@link AttributeSystemUsage#USAGE_VEHICLE_STATUS},
1668      *     {@link AttributeSystemUsage#USAGE_ANNOUNCEMENT}
1669      * @return boolean indicating if the usage is a system usage or not
1670      * @hide
1671      */
1672     @SystemApi
isSystemUsage(@ttributeSystemUsage int usage)1673     public static boolean isSystemUsage(@AttributeSystemUsage int usage) {
1674         return (usage == USAGE_CALL_ASSISTANT
1675                 || usage == USAGE_EMERGENCY
1676                 || usage == USAGE_SAFETY
1677                 || usage == USAGE_VEHICLE_STATUS
1678                 || usage == USAGE_ANNOUNCEMENT);
1679     }
1680 
1681     /**
1682      * Query if the usage is a valid sdk usage
1683      *
1684      * @param usage one of {@link AttributeSdkUsage}
1685      * @return {@code true} if the usage is valid for sdk or {@code false} otherwise
1686      * @hide
1687      */
isSdkUsage(@ttributeSdkUsage int usage)1688     public static boolean isSdkUsage(@AttributeSdkUsage int usage) {
1689         return SDK_USAGES.contains(usage);
1690     }
1691 
1692     /**
1693      * Query if the usage is a hidden (neither sdk nor SystemApi) usage
1694      *
1695      * @param usage the {@link android.media.AudioAttributes usage}
1696      * @return {@code true} if the usage is {@link AudioAttributes#USAGE_VIRTUAL_SOURCE} or
1697      *     {@code false} otherwise
1698      * @hide
1699      */
isHiddenUsage(@ttributeUsage int usage)1700     public static boolean isHiddenUsage(@AttributeUsage int usage) {
1701         return usage == USAGE_VIRTUAL_SOURCE;
1702     }
1703 
1704     /**
1705      * Query if the content type is a valid sdk content type
1706      * @param contentType one of {@link AttributeContentType}
1707      * @return {@code true} if the content type is valid for sdk or {@code false} otherwise
1708      * @hide
1709      */
isSdkContentType(@ttributeContentType int contentType)1710     public static boolean isSdkContentType(@AttributeContentType int contentType) {
1711         return CONTENT_TYPES.contains(contentType);
1712     }
1713 
1714     /**
1715      * Returns the stream type matching this {@code AudioAttributes} instance for volume control.
1716      * Use this method to derive the stream type needed to configure the volume
1717      * control slider in an {@link android.app.Activity} with
1718      * {@link android.app.Activity#setVolumeControlStream(int)} for playback conducted with these
1719      * attributes.
1720      * <BR>Do not use this method to set the stream type on an audio player object
1721      * (e.g. {@link AudioTrack}, {@link MediaPlayer}) as this is deprecated,
1722      * use {@code AudioAttributes} instead.
1723      * @return a valid stream type for {@code Activity} or stream volume control that matches
1724      *     the attributes, or {@link AudioManager#USE_DEFAULT_STREAM_TYPE} if there isn't a direct
1725      *     match. Note that {@code USE_DEFAULT_STREAM_TYPE} is not a valid value
1726      *     for {@link AudioManager#setStreamVolume(int, int, int)}.
1727      */
getVolumeControlStream()1728     public int getVolumeControlStream() {
1729         return toVolumeStreamType(true /*fromGetVolumeControlStream*/, this);
1730     }
1731 
1732     /**
1733      * @hide
1734      * Only use to get which stream type should be used for volume control, NOT for audio playback
1735      * (all audio playback APIs are supposed to take AudioAttributes as input parameters)
1736      * @param aa non-null AudioAttributes.
1737      * @return a valid stream type for volume control that matches the attributes.
1738      */
1739     @UnsupportedAppUsage
toLegacyStreamType(@onNull AudioAttributes aa)1740     public static int toLegacyStreamType(@NonNull AudioAttributes aa) {
1741         return toVolumeStreamType(false /*fromGetVolumeControlStream*/, aa);
1742     }
1743 
toVolumeStreamType(boolean fromGetVolumeControlStream, AudioAttributes aa)1744     private static int toVolumeStreamType(boolean fromGetVolumeControlStream, AudioAttributes aa) {
1745         // flags to stream type mapping
1746         if ((aa.getFlags() & FLAG_AUDIBILITY_ENFORCED) == FLAG_AUDIBILITY_ENFORCED) {
1747             return fromGetVolumeControlStream ?
1748                     AudioSystem.STREAM_SYSTEM : AudioSystem.STREAM_SYSTEM_ENFORCED;
1749         }
1750         if ((aa.getAllFlags() & FLAG_SCO) == FLAG_SCO) {
1751             return fromGetVolumeControlStream ?
1752                     AudioSystem.STREAM_VOICE_CALL : AudioSystem.STREAM_BLUETOOTH_SCO;
1753         }
1754         if ((aa.getAllFlags() & FLAG_BEACON) == FLAG_BEACON) {
1755             return fromGetVolumeControlStream ?
1756                     AudioSystem.STREAM_MUSIC : AudioSystem.STREAM_TTS;
1757         }
1758 
1759         if (AudioProductStrategy.getAudioProductStrategies().size() > 0) {
1760             return AudioProductStrategy.getLegacyStreamTypeForStrategyWithAudioAttributes(aa);
1761         }
1762         // usage to stream type mapping
1763         switch (aa.getUsage()) {
1764             case USAGE_MEDIA:
1765             case USAGE_GAME:
1766             case USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:
1767             case USAGE_ASSISTANT:
1768                 return AudioSystem.STREAM_MUSIC;
1769             case USAGE_ASSISTANCE_SONIFICATION:
1770                 return AudioSystem.STREAM_SYSTEM;
1771             case USAGE_VOICE_COMMUNICATION:
1772             case USAGE_CALL_ASSISTANT:
1773                 return AudioSystem.STREAM_VOICE_CALL;
1774             case USAGE_VOICE_COMMUNICATION_SIGNALLING:
1775                 return fromGetVolumeControlStream ?
1776                         AudioSystem.STREAM_VOICE_CALL : AudioSystem.STREAM_DTMF;
1777             case USAGE_ALARM:
1778                 return AudioSystem.STREAM_ALARM;
1779             case USAGE_NOTIFICATION_RINGTONE:
1780                 return AudioSystem.STREAM_RING;
1781             case USAGE_NOTIFICATION:
1782             case USAGE_NOTIFICATION_COMMUNICATION_REQUEST:
1783             case USAGE_NOTIFICATION_COMMUNICATION_INSTANT:
1784             case USAGE_NOTIFICATION_COMMUNICATION_DELAYED:
1785             case USAGE_NOTIFICATION_EVENT:
1786                 return AudioSystem.STREAM_NOTIFICATION;
1787             case USAGE_ASSISTANCE_ACCESSIBILITY:
1788                 return AudioSystem.STREAM_ACCESSIBILITY;
1789             case USAGE_EMERGENCY:
1790             case USAGE_SAFETY:
1791             case USAGE_VEHICLE_STATUS:
1792             case USAGE_ANNOUNCEMENT:
1793             case USAGE_UNKNOWN:
1794                 return AudioSystem.STREAM_MUSIC;
1795             default:
1796                 if (fromGetVolumeControlStream) {
1797                     throw new IllegalArgumentException("Unknown usage value " + aa.getUsage() +
1798                             " in audio attributes");
1799                 } else {
1800                     return AudioSystem.STREAM_MUSIC;
1801                 }
1802         }
1803     }
1804 
1805     /**
1806      * @hide
1807      */
capturePolicyToFlags(@apturePolicy int capturePolicy, int flags)1808     public static int capturePolicyToFlags(@CapturePolicy int capturePolicy, int flags) {
1809         switch (capturePolicy) {
1810             case ALLOW_CAPTURE_BY_NONE:
1811                 flags |= FLAG_NO_MEDIA_PROJECTION | FLAG_NO_SYSTEM_CAPTURE;
1812                 break;
1813             case ALLOW_CAPTURE_BY_SYSTEM:
1814                 flags |= FLAG_NO_MEDIA_PROJECTION;
1815                 flags &= ~FLAG_NO_SYSTEM_CAPTURE;
1816                 break;
1817             case ALLOW_CAPTURE_BY_ALL:
1818                 flags &= ~FLAG_NO_SYSTEM_CAPTURE & ~FLAG_NO_MEDIA_PROJECTION;
1819                 break;
1820             default:
1821                 throw new IllegalArgumentException("Unknown allow playback capture policy");
1822         }
1823         return flags;
1824     }
1825 
1826     /** @hide */
1827     @IntDef({
1828             USAGE_CALL_ASSISTANT,
1829             USAGE_EMERGENCY,
1830             USAGE_SAFETY,
1831             USAGE_VEHICLE_STATUS,
1832             USAGE_ANNOUNCEMENT
1833     })
1834     @Retention(RetentionPolicy.SOURCE)
1835     public @interface AttributeSystemUsage {}
1836 
1837     /** @hide */
1838     @IntDef({
1839             USAGE_UNKNOWN,
1840             USAGE_MEDIA,
1841             USAGE_VOICE_COMMUNICATION,
1842             USAGE_VOICE_COMMUNICATION_SIGNALLING,
1843             USAGE_ALARM,
1844             USAGE_NOTIFICATION,
1845             USAGE_NOTIFICATION_RINGTONE,
1846             USAGE_NOTIFICATION_COMMUNICATION_REQUEST,
1847             USAGE_NOTIFICATION_COMMUNICATION_INSTANT,
1848             USAGE_NOTIFICATION_COMMUNICATION_DELAYED,
1849             USAGE_NOTIFICATION_EVENT,
1850             USAGE_ASSISTANCE_ACCESSIBILITY,
1851             USAGE_ASSISTANCE_NAVIGATION_GUIDANCE,
1852             USAGE_ASSISTANCE_SONIFICATION,
1853             USAGE_GAME,
1854             USAGE_ASSISTANT,
1855     })
1856     @Retention(RetentionPolicy.SOURCE)
1857     public @interface AttributeSdkUsage {}
1858 
1859     /** @hide */
1860     @IntDef({
1861         USAGE_UNKNOWN,
1862         USAGE_MEDIA,
1863         USAGE_VOICE_COMMUNICATION,
1864         USAGE_VOICE_COMMUNICATION_SIGNALLING,
1865         USAGE_ALARM,
1866         USAGE_NOTIFICATION,
1867         USAGE_NOTIFICATION_RINGTONE,
1868         USAGE_NOTIFICATION_COMMUNICATION_REQUEST,
1869         USAGE_NOTIFICATION_COMMUNICATION_INSTANT,
1870         USAGE_NOTIFICATION_COMMUNICATION_DELAYED,
1871         USAGE_NOTIFICATION_EVENT,
1872         USAGE_ASSISTANCE_ACCESSIBILITY,
1873         USAGE_ASSISTANCE_NAVIGATION_GUIDANCE,
1874         USAGE_ASSISTANCE_SONIFICATION,
1875         USAGE_GAME,
1876         USAGE_ASSISTANT,
1877         USAGE_CALL_ASSISTANT,
1878         USAGE_EMERGENCY,
1879         USAGE_SAFETY,
1880         USAGE_VEHICLE_STATUS,
1881         USAGE_ANNOUNCEMENT,
1882     })
1883     @Retention(RetentionPolicy.SOURCE)
1884     public @interface AttributeUsage {}
1885 
1886     /** @hide */
1887     @IntDef({
1888         CONTENT_TYPE_UNKNOWN,
1889         CONTENT_TYPE_SPEECH,
1890         CONTENT_TYPE_MUSIC,
1891         CONTENT_TYPE_MOVIE,
1892         CONTENT_TYPE_SONIFICATION
1893     })
1894     @Retention(RetentionPolicy.SOURCE)
1895     public @interface AttributeContentType {}
1896 
1897     /** @hide */
1898     @IntDef({
1899         CONTENT_TYPE_UNKNOWN,
1900         CONTENT_TYPE_SPEECH,
1901         CONTENT_TYPE_MUSIC,
1902         CONTENT_TYPE_MOVIE,
1903         CONTENT_TYPE_SONIFICATION,
1904         CONTENT_TYPE_ULTRASOUND
1905     })
1906     @Retention(RetentionPolicy.SOURCE)
1907     public @interface AttrInternalContentType {}
1908 }
1909