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