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