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