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