OSDN Git Service

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