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