• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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();
SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION, SUPPRESSIBLE_NOTIFICATION)203         SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION,                      SUPPRESSIBLE_NOTIFICATION);
SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION_RINGTONE, SUPPRESSIBLE_CALL)204         SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION_RINGTONE,             SUPPRESSIBLE_CALL);
SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION_COMMUNICATION_REQUEST,SUPPRESSIBLE_CALL)205         SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION_COMMUNICATION_REQUEST,SUPPRESSIBLE_CALL);
SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION_COMMUNICATION_INSTANT,SUPPRESSIBLE_NOTIFICATION)206         SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION_COMMUNICATION_INSTANT,SUPPRESSIBLE_NOTIFICATION);
SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION_COMMUNICATION_DELAYED,SUPPRESSIBLE_NOTIFICATION)207         SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION_COMMUNICATION_DELAYED,SUPPRESSIBLE_NOTIFICATION);
SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION_EVENT, 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 
AudioAttributes()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      */
getContentType()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      */
getUsage()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
getCapturePreset()346     public int getCapturePreset() {
347         return mSource;
348     }
349 
350     /**
351      * Return the flags.
352      * @return a combined mask of all flags
353      */
getFlags()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
getAllFlags()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
getBundle()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      */
getTags()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          */
Builder()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
Builder(AudioAttributes aa)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
build()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          */
setUsage(@ttributeUsage int usage)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          */
setContentType(@ttributeContentType int contentType)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          */
setFlags(int flags)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
addBundle(@onNull Bundle bundle)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          */
addTag(String tag)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          */
setLegacyStreamType(int streamType)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          */
setInternalLegacyStreamType(int streamType)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
setCapturePreset(int preset)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
setInternalCapturePreset(int preset)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
describeContents()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
writeToParcel(Parcel dest, int flags)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 
AudioAttributes(Parcel in)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
equals(Object o)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
hashCode()788     public int hashCode() {
789         return Objects.hash(mContentType, mFlags, mSource, mUsage, mFormattedTags, mBundle);
790     }
791 
792     @Override
toString()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 */
usageToString()803     public String usageToString() {
804         return usageToString(mUsage);
805     }
806 
807     /** @hide */
usageToString(int usage)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 */
usageForLegacyStreamType(int streamType)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      */
getVolumeControlStream(@onNull AudioAttributes aa)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      */
toLegacyStreamType(@onNull AudioAttributes aa)899     public static int toLegacyStreamType(@NonNull AudioAttributes aa) {
900         return toVolumeStreamType(false /*fromGetVolumeControlStream*/, aa);
901     }
902 
toVolumeStreamType(boolean fromGetVolumeControlStream, AudioAttributes aa)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