Home | History | Annotate | Download | only in media
      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();
    240         SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION,                      SUPPRESSIBLE_NOTIFICATION);
    241         SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION_RINGTONE,             SUPPRESSIBLE_CALL);
    242         SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION_COMMUNICATION_REQUEST,SUPPRESSIBLE_CALL);
    243         SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION_COMMUNICATION_INSTANT,SUPPRESSIBLE_NOTIFICATION);
    244         SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION_COMMUNICATION_DELAYED,SUPPRESSIBLE_NOTIFICATION);
    245         SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION_EVENT,                SUPPRESSIBLE_NOTIFICATION);
    246         SUPPRESSIBLE_USAGES.put(USAGE_ASSISTANCE_ACCESSIBILITY,          SUPPRESSIBLE_NEVER);
    247         SUPPRESSIBLE_USAGES.put(USAGE_VOICE_COMMUNICATION,               SUPPRESSIBLE_NEVER);
    248         SUPPRESSIBLE_USAGES.put(USAGE_ALARM,                             SUPPRESSIBLE_ALARM);
    249         SUPPRESSIBLE_USAGES.put(USAGE_MEDIA,                             SUPPRESSIBLE_MEDIA);
    250         SUPPRESSIBLE_USAGES.put(USAGE_ASSISTANCE_NAVIGATION_GUIDANCE,    SUPPRESSIBLE_MEDIA);
    251         SUPPRESSIBLE_USAGES.put(USAGE_GAME,                              SUPPRESSIBLE_MEDIA);
    252         SUPPRESSIBLE_USAGES.put(USAGE_ASSISTANT,                         SUPPRESSIBLE_MEDIA);
    253         /** default volume assignment is STREAM_MUSIC, handle unknown usage as media */
    254         SUPPRESSIBLE_USAGES.put(USAGE_UNKNOWN,                           SUPPRESSIBLE_MEDIA);
    255         SUPPRESSIBLE_USAGES.put(USAGE_VOICE_COMMUNICATION_SIGNALLING,    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 
    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      */
    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      */
    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
    409     public int getCapturePreset() {
    410         return mSource;
    411     }
    412 
    413     /**
    414      * Return the flags.
    415      * @return a combined mask of all flags
    416      */
    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
    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
    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      */
    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          */
    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
    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
    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          */
    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          */
    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          */
    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          */
    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
    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          */
    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          */
    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          */
    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
    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
    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
    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
    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 
    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
    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
    876     public int hashCode() {
    877         return Objects.hash(mContentType, mFlags, mSource, mUsage, mFormattedTags, mBundle);
    878     }
    879 
    880     @Override
    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 */
    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 */
    910     public String usageToString() {
    911         return usageToString(mUsage);
    912     }
    913 
    914     /** @hide */
    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 */
    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 
    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      */
   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      */
   1019     public static int toLegacyStreamType(@NonNull AudioAttributes aa) {
   1020         return toVolumeStreamType(false /*fromGetVolumeControlStream*/, aa);
   1021     }
   1022 
   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