• 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      * Usage value to use for audio responses to user queries, audio instructions or help
174      * utterances.
175      */
176     public final static int USAGE_ASSISTANT = 16;
177 
178     /**
179      * IMPORTANT: when adding new usage types, add them to SDK_USAGES and update SUPPRESSIBLE_USAGES
180      *            if applicable.
181      */
182 
183     /**
184      * @hide
185      * Denotes a usage for notifications that do not expect immediate intervention from the user,
186      * will be muted when the Zen mode disables notifications
187      * @see #SUPPRESSIBLE_USAGES
188      */
189     public final static int SUPPRESSIBLE_NOTIFICATION = 1;
190     /**
191      * @hide
192      * Denotes a usage for notifications that do expect immediate intervention from the user,
193      * will be muted when the Zen mode disables calls
194      * @see #SUPPRESSIBLE_USAGES
195      */
196     public final static int SUPPRESSIBLE_CALL = 2;
197     /**
198      * @hide
199      * Denotes a usage that is never going to be muted, even in Total Silence.
200      * @see #SUPPRESSIBLE_USAGES
201      */
202     public final static int SUPPRESSIBLE_NEVER = 3;
203 
204     /**
205      * @hide
206      * Array of all usage types for calls and notifications to assign the suppression behavior,
207      * used by the Zen mode restrictions.
208      * @see com.android.server.notification.ZenModeHelper
209      */
210     public static final SparseIntArray SUPPRESSIBLE_USAGES;
211 
212     static {
213         SUPPRESSIBLE_USAGES = new SparseIntArray();
SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION, SUPPRESSIBLE_NOTIFICATION)214         SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION,                      SUPPRESSIBLE_NOTIFICATION);
SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION_RINGTONE, SUPPRESSIBLE_CALL)215         SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION_RINGTONE,             SUPPRESSIBLE_CALL);
SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION_COMMUNICATION_REQUEST,SUPPRESSIBLE_CALL)216         SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION_COMMUNICATION_REQUEST,SUPPRESSIBLE_CALL);
SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION_COMMUNICATION_INSTANT,SUPPRESSIBLE_NOTIFICATION)217         SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION_COMMUNICATION_INSTANT,SUPPRESSIBLE_NOTIFICATION);
SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION_COMMUNICATION_DELAYED,SUPPRESSIBLE_NOTIFICATION)218         SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION_COMMUNICATION_DELAYED,SUPPRESSIBLE_NOTIFICATION);
SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION_EVENT, SUPPRESSIBLE_NOTIFICATION)219         SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION_EVENT,                SUPPRESSIBLE_NOTIFICATION);
SUPPRESSIBLE_USAGES.put(USAGE_ASSISTANCE_ACCESSIBILITY, SUPPRESSIBLE_NEVER)220         SUPPRESSIBLE_USAGES.put(USAGE_ASSISTANCE_ACCESSIBILITY,          SUPPRESSIBLE_NEVER);
SUPPRESSIBLE_USAGES.put(USAGE_VOICE_COMMUNICATION, SUPPRESSIBLE_NEVER)221         SUPPRESSIBLE_USAGES.put(USAGE_VOICE_COMMUNICATION,               SUPPRESSIBLE_NEVER);
222     }
223 
224     /**
225      * @hide
226      * Array of all usage types exposed in the SDK that applications can use.
227      */
228     public final static int[] SDK_USAGES = {
229             USAGE_UNKNOWN,
230             USAGE_MEDIA,
231             USAGE_VOICE_COMMUNICATION,
232             USAGE_VOICE_COMMUNICATION_SIGNALLING,
233             USAGE_ALARM,
234             USAGE_NOTIFICATION,
235             USAGE_NOTIFICATION_RINGTONE,
236             USAGE_NOTIFICATION_COMMUNICATION_REQUEST,
237             USAGE_NOTIFICATION_COMMUNICATION_INSTANT,
238             USAGE_NOTIFICATION_COMMUNICATION_DELAYED,
239             USAGE_NOTIFICATION_EVENT,
240             USAGE_ASSISTANCE_ACCESSIBILITY,
241             USAGE_ASSISTANCE_NAVIGATION_GUIDANCE,
242             USAGE_ASSISTANCE_SONIFICATION,
243             USAGE_GAME,
244             USAGE_ASSISTANT,
245     };
246 
247     /**
248      * Flag defining a behavior where the audibility of the sound will be ensured by the system.
249      */
250     public final static int FLAG_AUDIBILITY_ENFORCED = 0x1 << 0;
251     /**
252      * @hide
253      * Flag defining a behavior where the playback of the sound is ensured without
254      * degradation only when going to a secure sink.
255      */
256     // FIXME not guaranteed yet
257     // TODO  add in FLAG_ALL_PUBLIC when supported and in public API
258     public final static int FLAG_SECURE = 0x1 << 1;
259     /**
260      * @hide
261      * Flag to enable when the stream is associated with SCO usage.
262      * Internal use only for dealing with legacy STREAM_BLUETOOTH_SCO
263      */
264     public final static int FLAG_SCO = 0x1 << 2;
265     /**
266      * @hide
267      * Flag defining a behavior where the system ensures that the playback of the sound will
268      * be compatible with its use as a broadcast for surrounding people and/or devices.
269      * Ensures audibility with no or minimal post-processing applied.
270      */
271     @SystemApi
272     public final static int FLAG_BEACON = 0x1 << 3;
273 
274     /**
275      * Flag requesting the use of an output stream supporting hardware A/V synchronization.
276      */
277     public final static int FLAG_HW_AV_SYNC = 0x1 << 4;
278 
279     /**
280      * @hide
281      * Flag requesting capture from the source used for hardware hotword detection.
282      * To be used with capture preset MediaRecorder.AudioSource.HOTWORD or
283      * MediaRecorder.AudioSource.VOICE_RECOGNITION.
284      */
285     @SystemApi
286     public final static int FLAG_HW_HOTWORD = 0x1 << 5;
287 
288     /**
289      * @hide
290      * Flag requesting audible playback even under limited interruptions.
291      */
292     @SystemApi
293     public final static int FLAG_BYPASS_INTERRUPTION_POLICY = 0x1 << 6;
294 
295     /**
296      * @hide
297      * Flag requesting audible playback even when the underlying stream is muted.
298      */
299     @SystemApi
300     public final static int FLAG_BYPASS_MUTE = 0x1 << 7;
301 
302     /**
303      * Flag requesting a low latency path when creating an AudioTrack.
304      * When using this flag, the sample rate must match the native sample rate
305      * of the device. Effects processing is also unavailable.
306      *
307      * Note that if this flag is used without specifying a bufferSizeInBytes then the
308      * AudioTrack's actual buffer size may be too small. It is recommended that a fairly
309      * large buffer should be specified when the AudioTrack is created.
310      * Then the actual size can be reduced by calling
311      * {@link AudioTrack#setBufferSizeInFrames(int)}. The buffer size can be optimized
312      * by lowering it after each write() call until the audio glitches, which is detected by calling
313      * {@link AudioTrack#getUnderrunCount()}. Then the buffer size can be increased
314      * until there are no glitches.
315      * This tuning step should be done while playing silence.
316      * This technique provides a compromise between latency and glitch rate.
317      *
318      * @deprecated Use {@link AudioTrack.Builder#setPerformanceMode(int)} with
319      * {@link AudioTrack#PERFORMANCE_MODE_LOW_LATENCY} to control performance.
320      */
321     public final static int FLAG_LOW_LATENCY = 0x1 << 8;
322 
323     /**
324      * @hide
325      * Flag requesting a deep buffer path when creating an {@code AudioTrack}.
326      *
327      * A deep buffer path, if available, may consume less power and is
328      * suitable for media playback where latency is not a concern.
329      * Use {@link AudioTrack.Builder#setPerformanceMode(int)} with
330      * {@link AudioTrack#PERFORMANCE_MODE_POWER_SAVING} to enable.
331      */
332     public final static int FLAG_DEEP_BUFFER = 0x1 << 9;
333 
334     private final static int FLAG_ALL = FLAG_AUDIBILITY_ENFORCED | FLAG_SECURE | FLAG_SCO |
335             FLAG_BEACON | FLAG_HW_AV_SYNC | FLAG_HW_HOTWORD | FLAG_BYPASS_INTERRUPTION_POLICY |
336             FLAG_BYPASS_MUTE | FLAG_LOW_LATENCY | FLAG_DEEP_BUFFER;
337     private final static int FLAG_ALL_PUBLIC = FLAG_AUDIBILITY_ENFORCED |
338             FLAG_HW_AV_SYNC | FLAG_LOW_LATENCY;
339 
340     private int mUsage = USAGE_UNKNOWN;
341     private int mContentType = CONTENT_TYPE_UNKNOWN;
342     private int mSource = MediaRecorder.AudioSource.AUDIO_SOURCE_INVALID;
343     private int mFlags = 0x0;
344     private HashSet<String> mTags;
345     private String mFormattedTags;
346     private Bundle mBundle; // lazy-initialized, may be null
347 
AudioAttributes()348     private AudioAttributes() {
349     }
350 
351     /**
352      * Return the content type.
353      * @return one of the values that can be set in {@link Builder#setContentType(int)}
354      */
getContentType()355     public int getContentType() {
356         return mContentType;
357     }
358 
359     /**
360      * Return the usage.
361      * @return one of the values that can be set in {@link Builder#setUsage(int)}
362      */
getUsage()363     public int getUsage() {
364         return mUsage;
365     }
366 
367     /**
368      * @hide
369      * Return the capture preset.
370      * @return one of the values that can be set in {@link Builder#setCapturePreset(int)} or a
371      *    negative value if none has been set.
372      */
373     @SystemApi
getCapturePreset()374     public int getCapturePreset() {
375         return mSource;
376     }
377 
378     /**
379      * Return the flags.
380      * @return a combined mask of all flags
381      */
getFlags()382     public int getFlags() {
383         // only return the flags that are public
384         return (mFlags & (FLAG_ALL_PUBLIC));
385     }
386 
387     /**
388      * @hide
389      * Return all the flags, even the non-public ones.
390      * Internal use only
391      * @return a combined mask of all flags
392      */
393     @SystemApi
getAllFlags()394     public int getAllFlags() {
395         return (mFlags & FLAG_ALL);
396     }
397 
398     /**
399      * @hide
400      * Return the Bundle of data.
401      * @return a copy of the Bundle for this instance, may be null.
402      */
403     @SystemApi
getBundle()404     public Bundle getBundle() {
405         if (mBundle == null) {
406             return mBundle;
407         } else {
408             return new Bundle(mBundle);
409         }
410     }
411 
412     /**
413      * @hide
414      * Return the set of tags.
415      * @return a read-only set of all tags stored as strings.
416      */
getTags()417     public Set<String> getTags() {
418         return Collections.unmodifiableSet(mTags);
419     }
420 
421     /**
422      * Builder class for {@link AudioAttributes} objects.
423      * <p> Here is an example where <code>Builder</code> is used to define the
424      * {@link AudioAttributes} to be used by a new <code>AudioTrack</code> instance:
425      *
426      * <pre class="prettyprint">
427      * AudioTrack myTrack = new AudioTrack(
428      *         new AudioAttributes.Builder()
429      *             .setUsage(AudioAttributes.USAGE_MEDIA)
430      *             .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
431      *             .build(),
432      *         myFormat, myBuffSize, AudioTrack.MODE_STREAM, mySession);
433      * </pre>
434      *
435      * <p>By default all types of information (usage, content type, flags) conveyed by an
436      * <code>AudioAttributes</code> instance are set to "unknown". Unknown information will be
437      * interpreted as a default value that is dependent on the context of use, for instance a
438      * {@link MediaPlayer} will use a default usage of {@link AudioAttributes#USAGE_MEDIA}.
439      */
440     public static class Builder {
441         private int mUsage = USAGE_UNKNOWN;
442         private int mContentType = CONTENT_TYPE_UNKNOWN;
443         private int mSource = MediaRecorder.AudioSource.AUDIO_SOURCE_INVALID;
444         private int mFlags = 0x0;
445         private HashSet<String> mTags = new HashSet<String>();
446         private Bundle mBundle;
447 
448         /**
449          * Constructs a new Builder with the defaults.
450          * By default, usage and content type are respectively {@link AudioAttributes#USAGE_UNKNOWN}
451          * and {@link AudioAttributes#CONTENT_TYPE_UNKNOWN}, and flags are 0. It is recommended to
452          * configure the usage (with {@link #setUsage(int)}) or deriving attributes from a legacy
453          * stream type (with {@link #setLegacyStreamType(int)}) before calling {@link #build()}
454          * to override any default playback behavior in terms of routing and volume management.
455          */
Builder()456         public Builder() {
457         }
458 
459         /**
460          * Constructs a new Builder from a given AudioAttributes
461          * @param aa the AudioAttributes object whose data will be reused in the new Builder.
462          */
463         @SuppressWarnings("unchecked") // for cloning of mTags
Builder(AudioAttributes aa)464         public Builder(AudioAttributes aa) {
465             mUsage = aa.mUsage;
466             mContentType = aa.mContentType;
467             mFlags = aa.mFlags;
468             mTags = (HashSet<String>) aa.mTags.clone();
469         }
470 
471         /**
472          * Combines all of the attributes that have been set and return a new
473          * {@link AudioAttributes} object.
474          * @return a new {@link AudioAttributes} object
475          */
476         @SuppressWarnings("unchecked") // for cloning of mTags
build()477         public AudioAttributes build() {
478             AudioAttributes aa = new AudioAttributes();
479             aa.mContentType = mContentType;
480             aa.mUsage = mUsage;
481             aa.mSource = mSource;
482             aa.mFlags = mFlags;
483             aa.mTags = (HashSet<String>) mTags.clone();
484             aa.mFormattedTags = TextUtils.join(";", mTags);
485             if (mBundle != null) {
486                 aa.mBundle = new Bundle(mBundle);
487             }
488             return aa;
489         }
490 
491         /**
492          * Sets the attribute describing what is the intended use of the the audio signal,
493          * such as alarm or ringtone.
494          * @param usage one of {@link AudioAttributes#USAGE_UNKNOWN},
495          *     {@link AudioAttributes#USAGE_MEDIA},
496          *     {@link AudioAttributes#USAGE_VOICE_COMMUNICATION},
497          *     {@link AudioAttributes#USAGE_VOICE_COMMUNICATION_SIGNALLING},
498          *     {@link AudioAttributes#USAGE_ALARM}, {@link AudioAttributes#USAGE_NOTIFICATION},
499          *     {@link AudioAttributes#USAGE_NOTIFICATION_RINGTONE},
500          *     {@link AudioAttributes#USAGE_NOTIFICATION_COMMUNICATION_REQUEST},
501          *     {@link AudioAttributes#USAGE_NOTIFICATION_COMMUNICATION_INSTANT},
502          *     {@link AudioAttributes#USAGE_NOTIFICATION_COMMUNICATION_DELAYED},
503          *     {@link AudioAttributes#USAGE_NOTIFICATION_EVENT},
504          *     {@link AudioAttributes#USAGE_ASSISTANT},
505          *     {@link AudioAttributes#USAGE_ASSISTANCE_ACCESSIBILITY},
506          *     {@link AudioAttributes#USAGE_ASSISTANCE_NAVIGATION_GUIDANCE},
507          *     {@link AudioAttributes#USAGE_ASSISTANCE_SONIFICATION},
508          *     {@link AudioAttributes#USAGE_GAME}.
509          * @return the same Builder instance.
510          */
setUsage(@ttributeUsage int usage)511         public Builder setUsage(@AttributeUsage int usage) {
512             switch (usage) {
513                 case USAGE_UNKNOWN:
514                 case USAGE_MEDIA:
515                 case USAGE_VOICE_COMMUNICATION:
516                 case USAGE_VOICE_COMMUNICATION_SIGNALLING:
517                 case USAGE_ALARM:
518                 case USAGE_NOTIFICATION:
519                 case USAGE_NOTIFICATION_RINGTONE:
520                 case USAGE_NOTIFICATION_COMMUNICATION_REQUEST:
521                 case USAGE_NOTIFICATION_COMMUNICATION_INSTANT:
522                 case USAGE_NOTIFICATION_COMMUNICATION_DELAYED:
523                 case USAGE_NOTIFICATION_EVENT:
524                 case USAGE_ASSISTANCE_ACCESSIBILITY:
525                 case USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:
526                 case USAGE_ASSISTANCE_SONIFICATION:
527                 case USAGE_GAME:
528                 case USAGE_VIRTUAL_SOURCE:
529                 case USAGE_ASSISTANT:
530                      mUsage = usage;
531                      break;
532                 default:
533                      mUsage = USAGE_UNKNOWN;
534             }
535             return this;
536         }
537 
538         /**
539          * Sets the attribute describing the content type of the audio signal, such as speech,
540          * or music.
541          * @param contentType the content type values, one of
542          *     {@link AudioAttributes#CONTENT_TYPE_MOVIE},
543          *     {@link AudioAttributes#CONTENT_TYPE_MUSIC},
544          *     {@link AudioAttributes#CONTENT_TYPE_SONIFICATION},
545          *     {@link AudioAttributes#CONTENT_TYPE_SPEECH},
546          *     {@link AudioAttributes#CONTENT_TYPE_UNKNOWN}.
547          * @return the same Builder instance.
548          */
setContentType(@ttributeContentType int contentType)549         public Builder setContentType(@AttributeContentType int contentType) {
550             switch (contentType) {
551                 case CONTENT_TYPE_UNKNOWN:
552                 case CONTENT_TYPE_MOVIE:
553                 case CONTENT_TYPE_MUSIC:
554                 case CONTENT_TYPE_SONIFICATION:
555                 case CONTENT_TYPE_SPEECH:
556                      mContentType = contentType;
557                      break;
558                 default:
559                      mUsage = CONTENT_TYPE_UNKNOWN;
560             }
561             return this;
562         }
563 
564         /**
565          * Sets the combination of flags.
566          *
567          * This is a bitwise OR with the existing flags.
568          * @param flags a combination of {@link AudioAttributes#FLAG_AUDIBILITY_ENFORCED},
569          *    {@link AudioAttributes#FLAG_HW_AV_SYNC}.
570          * @return the same Builder instance.
571          */
setFlags(int flags)572         public Builder setFlags(int flags) {
573             flags &= AudioAttributes.FLAG_ALL;
574             mFlags |= flags;
575             return this;
576         }
577 
578         /**
579          * @hide
580          * Replaces flags.
581          * @param flags any combination of {@link AudioAttributes#FLAG_ALL}.
582          * @return the same Builder instance.
583          */
replaceFlags(int flags)584         public Builder replaceFlags(int flags) {
585             mFlags = flags & AudioAttributes.FLAG_ALL;
586             return this;
587         }
588 
589         /**
590          * @hide
591          * Adds a Bundle of data
592          * @param bundle a non-null Bundle
593          * @return the same builder instance
594          */
595         @SystemApi
addBundle(@onNull Bundle bundle)596         public Builder addBundle(@NonNull Bundle bundle) {
597             if (bundle == null) {
598                 throw new IllegalArgumentException("Illegal null bundle");
599             }
600             if (mBundle == null) {
601                 mBundle = new Bundle(bundle);
602             } else {
603                 mBundle.putAll(bundle);
604             }
605             return this;
606         }
607 
608         /**
609          * @hide
610          * Add a custom tag stored as a string
611          * @param tag
612          * @return the same Builder instance.
613          */
addTag(String tag)614         public Builder addTag(String tag) {
615             mTags.add(tag);
616             return this;
617         }
618 
619         /**
620          * Sets attributes as inferred from the legacy stream types.
621          * Use this method when building an {@link AudioAttributes} instance to initialize some of
622          * the attributes by information derived from a legacy stream type.
623          * @param streamType one of {@link AudioManager#STREAM_VOICE_CALL},
624          *   {@link AudioManager#STREAM_SYSTEM}, {@link AudioManager#STREAM_RING},
625          *   {@link AudioManager#STREAM_MUSIC}, {@link AudioManager#STREAM_ALARM},
626          *    or {@link AudioManager#STREAM_NOTIFICATION}.
627          * @return the same Builder instance.
628          */
setLegacyStreamType(int streamType)629         public Builder setLegacyStreamType(int streamType) {
630             if (streamType == AudioManager.STREAM_ACCESSIBILITY) {
631                 throw new IllegalArgumentException("STREAM_ACCESSIBILITY is not a legacy stream "
632                         + "type that was used for audio playback");
633             }
634             return setInternalLegacyStreamType(streamType);
635         }
636 
637         /**
638          * @hide
639          * For internal framework use only, enables building from hidden stream types.
640          * @param streamType
641          * @return the same Builder instance.
642          */
setInternalLegacyStreamType(int streamType)643         public Builder setInternalLegacyStreamType(int streamType) {
644             switch(streamType) {
645                 case AudioSystem.STREAM_VOICE_CALL:
646                     mContentType = CONTENT_TYPE_SPEECH;
647                     break;
648                 case AudioSystem.STREAM_SYSTEM_ENFORCED:
649                     mFlags |= FLAG_AUDIBILITY_ENFORCED;
650                     // intended fall through, attributes in common with STREAM_SYSTEM
651                 case AudioSystem.STREAM_SYSTEM:
652                     mContentType = CONTENT_TYPE_SONIFICATION;
653                     break;
654                 case AudioSystem.STREAM_RING:
655                     mContentType = CONTENT_TYPE_SONIFICATION;
656                     break;
657                 case AudioSystem.STREAM_MUSIC:
658                     mContentType = CONTENT_TYPE_MUSIC;
659                     break;
660                 case AudioSystem.STREAM_ALARM:
661                     mContentType = CONTENT_TYPE_SONIFICATION;
662                     break;
663                 case AudioSystem.STREAM_NOTIFICATION:
664                     mContentType = CONTENT_TYPE_SONIFICATION;
665                     break;
666                 case AudioSystem.STREAM_BLUETOOTH_SCO:
667                     mContentType = CONTENT_TYPE_SPEECH;
668                     mFlags |= FLAG_SCO;
669                     break;
670                 case AudioSystem.STREAM_DTMF:
671                     mContentType = CONTENT_TYPE_SONIFICATION;
672                     break;
673                 case AudioSystem.STREAM_TTS:
674                     mContentType = CONTENT_TYPE_SONIFICATION;
675                     break;
676                 case AudioSystem.STREAM_ACCESSIBILITY:
677                     mContentType = CONTENT_TYPE_SPEECH;
678                     break;
679                 default:
680                     Log.e(TAG, "Invalid stream type " + streamType + " for AudioAttributes");
681             }
682             mUsage = usageForStreamType(streamType);
683             return this;
684         }
685 
686         /**
687          * @hide
688          * Sets the capture preset.
689          * Use this audio attributes configuration method when building an {@link AudioRecord}
690          * instance with {@link AudioRecord#AudioRecord(AudioAttributes, AudioFormat, int)}.
691          * @param preset one of {@link MediaRecorder.AudioSource#DEFAULT},
692          *     {@link MediaRecorder.AudioSource#MIC}, {@link MediaRecorder.AudioSource#CAMCORDER},
693          *     {@link MediaRecorder.AudioSource#VOICE_RECOGNITION},
694          *     {@link MediaRecorder.AudioSource#VOICE_COMMUNICATION} or
695          *     {@link MediaRecorder.AudioSource#UNPROCESSED}
696          * @return the same Builder instance.
697          */
698         @SystemApi
setCapturePreset(int preset)699         public Builder setCapturePreset(int preset) {
700             switch (preset) {
701                 case MediaRecorder.AudioSource.DEFAULT:
702                 case MediaRecorder.AudioSource.MIC:
703                 case MediaRecorder.AudioSource.CAMCORDER:
704                 case MediaRecorder.AudioSource.VOICE_RECOGNITION:
705                 case MediaRecorder.AudioSource.VOICE_COMMUNICATION:
706                 case MediaRecorder.AudioSource.UNPROCESSED:
707                     mSource = preset;
708                     break;
709                 default:
710                     Log.e(TAG, "Invalid capture preset " + preset + " for AudioAttributes");
711             }
712             return this;
713         }
714 
715         /**
716          * @hide
717          * Same as {@link #setCapturePreset(int)} but authorizes the use of HOTWORD,
718          * REMOTE_SUBMIX and RADIO_TUNER.
719          * @param preset
720          * @return the same Builder instance.
721          */
722         @SystemApi
setInternalCapturePreset(int preset)723         public Builder setInternalCapturePreset(int preset) {
724             if ((preset == MediaRecorder.AudioSource.HOTWORD)
725                     || (preset == MediaRecorder.AudioSource.REMOTE_SUBMIX)
726                     || (preset == MediaRecorder.AudioSource.RADIO_TUNER)) {
727                 mSource = preset;
728             } else {
729                 setCapturePreset(preset);
730             }
731             return this;
732         }
733     };
734 
735     @Override
describeContents()736     public int describeContents() {
737         return 0;
738     }
739 
740     /**
741      * @hide
742      * Used to indicate that when parcelling, the tags should be parcelled through the flattened
743      * formatted string, not through the array of strings.
744      * Keep in sync with frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp
745      * see definition of kAudioAttributesMarshallTagFlattenTags
746      */
747     public final static int FLATTEN_TAGS = 0x1;
748 
749     private final static int ATTR_PARCEL_IS_NULL_BUNDLE = -1977;
750     private final static int ATTR_PARCEL_IS_VALID_BUNDLE = 1980;
751 
752     /**
753      * When adding tags for writeToParcel(Parcel, int), add them in the list of flags (| NEW_FLAG)
754      */
755     private final static int ALL_PARCEL_FLAGS = FLATTEN_TAGS;
756     @Override
writeToParcel(Parcel dest, int flags)757     public void writeToParcel(Parcel dest, int flags) {
758         dest.writeInt(mUsage);
759         dest.writeInt(mContentType);
760         dest.writeInt(mSource);
761         dest.writeInt(mFlags);
762         dest.writeInt(flags & ALL_PARCEL_FLAGS);
763         if ((flags & FLATTEN_TAGS) == 0) {
764             String[] tagsArray = new String[mTags.size()];
765             mTags.toArray(tagsArray);
766             dest.writeStringArray(tagsArray);
767         } else if ((flags & FLATTEN_TAGS) == FLATTEN_TAGS) {
768             dest.writeString(mFormattedTags);
769         }
770         if (mBundle == null) {
771             dest.writeInt(ATTR_PARCEL_IS_NULL_BUNDLE);
772         } else {
773             dest.writeInt(ATTR_PARCEL_IS_VALID_BUNDLE);
774             dest.writeBundle(mBundle);
775         }
776     }
777 
AudioAttributes(Parcel in)778     private AudioAttributes(Parcel in) {
779         mUsage = in.readInt();
780         mContentType = in.readInt();
781         mSource = in.readInt();
782         mFlags = in.readInt();
783         boolean hasFlattenedTags = ((in.readInt() & FLATTEN_TAGS) == FLATTEN_TAGS);
784         mTags = new HashSet<String>();
785         if (hasFlattenedTags) {
786             mFormattedTags = new String(in.readString());
787             mTags.add(mFormattedTags);
788         } else {
789             String[] tagsArray = in.readStringArray();
790             for (int i = tagsArray.length - 1 ; i >= 0 ; i--) {
791                 mTags.add(tagsArray[i]);
792             }
793             mFormattedTags = TextUtils.join(";", mTags);
794         }
795         switch (in.readInt()) {
796             case ATTR_PARCEL_IS_NULL_BUNDLE:
797                 mBundle = null;
798                 break;
799             case ATTR_PARCEL_IS_VALID_BUNDLE:
800                 mBundle = new Bundle(in.readBundle());
801                 break;
802             default:
803                 Log.e(TAG, "Illegal value unmarshalling AudioAttributes, can't initialize bundle");
804         }
805     }
806 
807     public static final Parcelable.Creator<AudioAttributes> CREATOR
808             = new Parcelable.Creator<AudioAttributes>() {
809         /**
810          * Rebuilds an AudioAttributes previously stored with writeToParcel().
811          * @param p Parcel object to read the AudioAttributes from
812          * @return a new AudioAttributes created from the data in the parcel
813          */
814         public AudioAttributes createFromParcel(Parcel p) {
815             return new AudioAttributes(p);
816         }
817         public AudioAttributes[] newArray(int size) {
818             return new AudioAttributes[size];
819         }
820     };
821 
822     @Override
equals(Object o)823     public boolean equals(Object o) {
824         if (this == o) return true;
825         if (o == null || getClass() != o.getClass()) return false;
826 
827         AudioAttributes that = (AudioAttributes) o;
828 
829         return ((mContentType == that.mContentType)
830                 && (mFlags == that.mFlags)
831                 && (mSource == that.mSource)
832                 && (mUsage == that.mUsage)
833                 //mFormattedTags is never null due to assignment in Builder or unmarshalling
834                 && (mFormattedTags.equals(that.mFormattedTags)));
835     }
836 
837     @Override
hashCode()838     public int hashCode() {
839         return Objects.hash(mContentType, mFlags, mSource, mUsage, mFormattedTags, mBundle);
840     }
841 
842     @Override
toString()843     public String toString () {
844         return new String("AudioAttributes:"
845                 + " usage=" + usageToString()
846                 + " content=" + contentTypeToString()
847                 + " flags=0x" + Integer.toHexString(mFlags).toUpperCase()
848                 + " tags=" + mFormattedTags
849                 + " bundle=" + (mBundle == null ? "null" : mBundle.toString()));
850     }
851 
852     /** @hide */
usageToString()853     public String usageToString() {
854         return usageToString(mUsage);
855     }
856 
857     /** @hide */
usageToString(int usage)858     public static String usageToString(int usage) {
859         switch(usage) {
860             case USAGE_UNKNOWN:
861                 return new String("USAGE_UNKNOWN");
862             case USAGE_MEDIA:
863                 return new String("USAGE_MEDIA");
864             case USAGE_VOICE_COMMUNICATION:
865                 return new String("USAGE_VOICE_COMMUNICATION");
866             case USAGE_VOICE_COMMUNICATION_SIGNALLING:
867                 return new String("USAGE_VOICE_COMMUNICATION_SIGNALLING");
868             case USAGE_ALARM:
869                 return new String("USAGE_ALARM");
870             case USAGE_NOTIFICATION:
871                 return new String("USAGE_NOTIFICATION");
872             case USAGE_NOTIFICATION_RINGTONE:
873                 return new String("USAGE_NOTIFICATION_RINGTONE");
874             case USAGE_NOTIFICATION_COMMUNICATION_REQUEST:
875                 return new String("USAGE_NOTIFICATION_COMMUNICATION_REQUEST");
876             case USAGE_NOTIFICATION_COMMUNICATION_INSTANT:
877                 return new String("USAGE_NOTIFICATION_COMMUNICATION_INSTANT");
878             case USAGE_NOTIFICATION_COMMUNICATION_DELAYED:
879                 return new String("USAGE_NOTIFICATION_COMMUNICATION_DELAYED");
880             case USAGE_NOTIFICATION_EVENT:
881                 return new String("USAGE_NOTIFICATION_EVENT");
882             case USAGE_ASSISTANCE_ACCESSIBILITY:
883                 return new String("USAGE_ASSISTANCE_ACCESSIBILITY");
884             case USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:
885                 return new String("USAGE_ASSISTANCE_NAVIGATION_GUIDANCE");
886             case USAGE_ASSISTANCE_SONIFICATION:
887                 return new String("USAGE_ASSISTANCE_SONIFICATION");
888             case USAGE_GAME:
889                 return new String("USAGE_GAME");
890             case USAGE_ASSISTANT:
891                 return new String("USAGE_ASSISTANT");
892             default:
893                 return new String("unknown usage " + usage);
894         }
895     }
896 
897     /** @hide */
contentTypeToString()898     public String contentTypeToString() {
899         switch(mContentType) {
900             case CONTENT_TYPE_UNKNOWN:
901                 return new String("CONTENT_TYPE_UNKNOWN");
902             case CONTENT_TYPE_SPEECH: return new String("CONTENT_TYPE_SPEECH");
903             case CONTENT_TYPE_MUSIC: return new String("CONTENT_TYPE_MUSIC");
904             case CONTENT_TYPE_MOVIE: return new String("CONTENT_TYPE_MOVIE");
905             case CONTENT_TYPE_SONIFICATION: return new String("CONTENT_TYPE_SONIFICATION");
906             default: return new String("unknown content type " + mContentType);
907         }
908     }
909 
usageForStreamType(int streamType)910     private static int usageForStreamType(int streamType) {
911         switch(streamType) {
912             case AudioSystem.STREAM_VOICE_CALL:
913                 return USAGE_VOICE_COMMUNICATION;
914             case AudioSystem.STREAM_SYSTEM_ENFORCED:
915             case AudioSystem.STREAM_SYSTEM:
916                 return USAGE_ASSISTANCE_SONIFICATION;
917             case AudioSystem.STREAM_RING:
918                 return USAGE_NOTIFICATION_RINGTONE;
919             case AudioSystem.STREAM_MUSIC:
920                 return USAGE_MEDIA;
921             case AudioSystem.STREAM_ALARM:
922                 return USAGE_ALARM;
923             case AudioSystem.STREAM_NOTIFICATION:
924                 return USAGE_NOTIFICATION;
925             case AudioSystem.STREAM_BLUETOOTH_SCO:
926                 return USAGE_VOICE_COMMUNICATION;
927             case AudioSystem.STREAM_DTMF:
928                 return USAGE_VOICE_COMMUNICATION_SIGNALLING;
929             case AudioSystem.STREAM_ACCESSIBILITY:
930                 return USAGE_ASSISTANCE_ACCESSIBILITY;
931             case AudioSystem.STREAM_TTS:
932             default:
933                 return USAGE_UNKNOWN;
934         }
935     }
936 
937     /**
938      * Returns the stream type matching this {@code AudioAttributes} instance for volume control.
939      * Use this method to derive the stream type needed to configure the volume
940      * control slider in an {@link android.app.Activity} with
941      * {@link android.app.Activity#setVolumeControlStream(int)} for playback conducted with these
942      * attributes.
943      * <BR>Do not use this method to set the stream type on an audio player object
944      * (e.g. {@link AudioTrack}, {@link MediaPlayer}) as this is deprecated,
945      * use {@code AudioAttributes} instead.
946      * @return a valid stream type for {@code Activity} or stream volume control that matches
947      *     the attributes, or {@link AudioManager#USE_DEFAULT_STREAM_TYPE} if there isn't a direct
948      *     match. Note that {@code USE_DEFAULT_STREAM_TYPE} is not a valid value
949      *     for {@link AudioManager#setStreamVolume(int, int, int)}.
950      */
getVolumeControlStream()951     public int getVolumeControlStream() {
952         return toVolumeStreamType(true /*fromGetVolumeControlStream*/, this);
953     }
954 
955     /**
956      * @hide
957      * Only use to get which stream type should be used for volume control, NOT for audio playback
958      * (all audio playback APIs are supposed to take AudioAttributes as input parameters)
959      * @param aa non-null AudioAttributes.
960      * @return a valid stream type for volume control that matches the attributes.
961      */
toLegacyStreamType(@onNull AudioAttributes aa)962     public static int toLegacyStreamType(@NonNull AudioAttributes aa) {
963         return toVolumeStreamType(false /*fromGetVolumeControlStream*/, aa);
964     }
965 
toVolumeStreamType(boolean fromGetVolumeControlStream, AudioAttributes aa)966     private static int toVolumeStreamType(boolean fromGetVolumeControlStream, AudioAttributes aa) {
967         // flags to stream type mapping
968         if ((aa.getFlags() & FLAG_AUDIBILITY_ENFORCED) == FLAG_AUDIBILITY_ENFORCED) {
969             return fromGetVolumeControlStream ?
970                     AudioSystem.STREAM_SYSTEM : AudioSystem.STREAM_SYSTEM_ENFORCED;
971         }
972         if ((aa.getFlags() & FLAG_SCO) == FLAG_SCO) {
973             return fromGetVolumeControlStream ?
974                     AudioSystem.STREAM_VOICE_CALL : AudioSystem.STREAM_BLUETOOTH_SCO;
975         }
976 
977         // usage to stream type mapping
978         switch (aa.getUsage()) {
979             case USAGE_MEDIA:
980             case USAGE_GAME:
981             case USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:
982             case USAGE_ASSISTANT:
983                 return AudioSystem.STREAM_MUSIC;
984             case USAGE_ASSISTANCE_SONIFICATION:
985                 return AudioSystem.STREAM_SYSTEM;
986             case USAGE_VOICE_COMMUNICATION:
987                 return AudioSystem.STREAM_VOICE_CALL;
988             case USAGE_VOICE_COMMUNICATION_SIGNALLING:
989                 return fromGetVolumeControlStream ?
990                         AudioSystem.STREAM_VOICE_CALL : AudioSystem.STREAM_DTMF;
991             case USAGE_ALARM:
992                 return AudioSystem.STREAM_ALARM;
993             case USAGE_NOTIFICATION_RINGTONE:
994                 return AudioSystem.STREAM_RING;
995             case USAGE_NOTIFICATION:
996             case USAGE_NOTIFICATION_COMMUNICATION_REQUEST:
997             case USAGE_NOTIFICATION_COMMUNICATION_INSTANT:
998             case USAGE_NOTIFICATION_COMMUNICATION_DELAYED:
999             case USAGE_NOTIFICATION_EVENT:
1000                 return AudioSystem.STREAM_NOTIFICATION;
1001             case USAGE_ASSISTANCE_ACCESSIBILITY:
1002                 return AudioSystem.STREAM_ACCESSIBILITY;
1003             case USAGE_UNKNOWN:
1004                 return fromGetVolumeControlStream ?
1005                         AudioManager.USE_DEFAULT_STREAM_TYPE : AudioSystem.STREAM_MUSIC;
1006             default:
1007                 if (fromGetVolumeControlStream) {
1008                     throw new IllegalArgumentException("Unknown usage value " + aa.getUsage() +
1009                             " in audio attributes");
1010                 } else {
1011                     return AudioSystem.STREAM_MUSIC;
1012                 }
1013         }
1014     }
1015 
1016     /** @hide */
1017     @IntDef({
1018         USAGE_UNKNOWN,
1019         USAGE_MEDIA,
1020         USAGE_VOICE_COMMUNICATION,
1021         USAGE_VOICE_COMMUNICATION_SIGNALLING,
1022         USAGE_ALARM,
1023         USAGE_NOTIFICATION,
1024         USAGE_NOTIFICATION_RINGTONE,
1025         USAGE_NOTIFICATION_COMMUNICATION_REQUEST,
1026         USAGE_NOTIFICATION_COMMUNICATION_INSTANT,
1027         USAGE_NOTIFICATION_COMMUNICATION_DELAYED,
1028         USAGE_NOTIFICATION_EVENT,
1029         USAGE_ASSISTANCE_ACCESSIBILITY,
1030         USAGE_ASSISTANCE_NAVIGATION_GUIDANCE,
1031         USAGE_ASSISTANCE_SONIFICATION,
1032         USAGE_GAME,
1033         USAGE_ASSISTANT,
1034     })
1035     @Retention(RetentionPolicy.SOURCE)
1036     public @interface AttributeUsage {}
1037 
1038     /** @hide */
1039     @IntDef({
1040         CONTENT_TYPE_UNKNOWN,
1041         CONTENT_TYPE_SPEECH,
1042         CONTENT_TYPE_MUSIC,
1043         CONTENT_TYPE_MOVIE,
1044         CONTENT_TYPE_SONIFICATION
1045     })
1046     @Retention(RetentionPolicy.SOURCE)
1047     public @interface AttributeContentType {}
1048 }
1049