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