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