AudioAttributes.java revision d60e875a97867c1a6ed84325bb70f7ffe8ce4521
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.util.Log;
21
22import java.lang.annotation.Retention;
23import java.lang.annotation.RetentionPolicy;
24import java.util.Collections;
25import java.util.HashSet;
26import java.util.Set;
27
28/**
29 * A class to encapsulate a collection of attributes describing information about an audio
30 * player or recorder.
31 */
32public final class AudioAttributes {
33    private final static String TAG = "AudioAttributes";
34
35    /**
36     * Content type value to use when the content type is unknown, or other than the ones defined.
37     */
38    public final static int CONTENT_TYPE_UNKNOWN = 0;
39    /**
40     * Content type value to use when the content type is speech.
41     */
42    public final static int CONTENT_TYPE_SPEECH = 1;
43    /**
44     * Content type value to use when the content type is music.
45     */
46    public final static int CONTENT_TYPE_MUSIC = 2;
47    /**
48     * Content type value to use when the content type is a soundtrack, typically accompanying
49     * a movie or TV program.
50     */
51    public final static int CONTENT_TYPE_MOVIE = 3;
52    /**
53     * Content type value to use when the content type is a sound used to accompany a user
54     * action, such as a beep or sound effect expressing a key click, or event, such as the
55     * type of a sound for a bonus being received in a game. These sounds are mostly synthesized
56     * or short Foley sounds.
57     */
58    public final static int CONTENT_TYPE_SONIFICATION = 4;
59
60    /**
61     * Usage value to use when the usage is unknown.
62     */
63    public final static int USAGE_UNKNOWN = 0;
64    /**
65     * Usage value to use when the usage is media, such as music, or movie
66     * soundtracks.
67     */
68    public final static int USAGE_MEDIA = 1;
69    /**
70     * Usage value to use when the usage is voice communications, such as telephony
71     * or VoIP.
72     */
73    public final static int USAGE_VOICE_COMMUNICATION = 2;
74    /**
75     * Usage value to use when the usage is in-call signalling, such as with
76     * a "busy" beep, or DTMF tones.
77     */
78    public final static int USAGE_VOICE_COMMUNICATION_SIGNALLING = 3;
79    /**
80     * Usage value to use when the usage is an alarm (e.g. wake-up alarm).
81     */
82    public final static int USAGE_ALARM = 4;
83    /**
84     * Usage value to use when the usage is notification. See other
85     * notification usages for more specialized uses.
86     */
87    public final static int USAGE_NOTIFICATION = 5;
88    /**
89     * Usage value to use when the usage is telephony ringtone.
90     */
91    public final static int USAGE_NOTIFICATION_TELEPHONY_RINGTONE = 6;
92    /**
93     * Usage value to use when the usage is a request to enter/end a
94     * communication, such as a VoIP communication or video-conference.
95     */
96    public final static int USAGE_NOTIFICATION_COMMUNICATION_REQUEST = 7;
97    /**
98     * Usage value to use when the usage is notification for an "instant"
99     * communication such as a chat, or SMS.
100     */
101    public final static int USAGE_NOTIFICATION_COMMUNICATION_INSTANT = 8;
102    /**
103     * Usage value to use when the usage is notification for a
104     * non-immediate type of communication such as e-mail.
105     */
106    public final static int USAGE_NOTIFICATION_COMMUNICATION_DELAYED = 9;
107    /**
108     * Usage value to use when the usage is to attract the user's attention,
109     * such as a reminder or low battery warning.
110     */
111    public final static int USAGE_NOTIFICATION_EVENT = 10;
112    /**
113     * Usage value to use when the usage is for accessibility, such as with
114     * a screen reader.
115     */
116    public final static int USAGE_ASSISTANCE_ACCESSIBILITY = 11;
117    /**
118     * Usage value to use when the usage is driving or navigation directions.
119     */
120    public final static int USAGE_ASSISTANCE_NAVIGATION_GUIDANCE = 12;
121    /**
122     * Usage value to use when the usage is sonification, such as  with user
123     * interface sounds.
124     */
125    public final static int USAGE_ASSISTANCE_SONIFICATION = 13;
126    /**
127     * Usage value to use when the usage is for game audio.
128     */
129    public final static int USAGE_GAME = 14;
130
131    /**
132     * Flag defining a behavior where the audibility of the sound will be ensured by the system.
133     */
134    public final static int FLAG_AUDIBILITY_ENFORCED = 0x1 << 0;
135    /**
136     * @hide
137     * Flag defining a behavior where the playback of the sound is ensured without
138     * degradation only when going to a secure sink.
139     */
140    // FIXME not guaranteed yet
141    // TODO  add OR to getFlags() when supported and in public API
142    public final static int FLAG_SECURE = 0x1 << 1;
143    /**
144     * @hide
145     * Flag to enable when the stream is associated with SCO usage.
146     * Internal use only for dealing with legacy STREAM_BLUETOOTH_SCO
147     */
148    public final static int FLAG_SCO = 0x1 << 2;
149
150
151    private int mUsage = USAGE_UNKNOWN;
152    private int mContentType = CONTENT_TYPE_UNKNOWN;
153    private int mFlags = 0x0;
154    private HashSet<String> mTags;
155
156    private AudioAttributes() {
157    }
158
159    /**
160     * Return the content type.
161     * @return one of the values that can be set in {@link Builder#setContentType(int)}
162     */
163    public int getContentType() {
164        return mContentType;
165    }
166
167    /**
168     * Return the usage.
169     * @return one of the values that can be set in {@link Builder#setUsage(int)}
170     */
171    public int getUsage() {
172        return mUsage;
173    }
174
175    /**
176     * Return the flags.
177     * @return a combined mask of all flags
178     */
179    public int getFlags() {
180        // only return the flags that are public
181        return (mFlags & (FLAG_AUDIBILITY_ENFORCED));
182    }
183
184    /**
185     * @hide
186     * Return all the flags, even the non-public ones.
187     * Internal use only
188     * @return a combined mask of all flags
189     */
190    public int getAllFlags() {
191        return mFlags;
192    }
193
194    /**
195     * Return the set of tags.
196     * @return a read-only set of all tags stored as strings.
197     */
198    public Set<String> getTags() {
199        return Collections.unmodifiableSet(mTags);
200    }
201
202    /**
203     * Builder class for {@link AudioAttributes} objects.
204     */
205    public static class Builder {
206        private int mUsage = USAGE_UNKNOWN;
207        private int mContentType = CONTENT_TYPE_UNKNOWN;
208        private int mFlags = 0x0;
209        private HashSet<String> mTags = new HashSet<String>();
210
211        /**
212         * Constructs a new Builder with the defaults.
213         */
214        public Builder() {
215        }
216
217        /**
218         * Constructs a new Builder from a given AudioAttributes
219         * @param aa the AudioAttributes object whose data will be reused in the new Builder.
220         */
221        @SuppressWarnings("unchecked") // for cloning of mTags
222        public Builder(AudioAttributes aa) {
223            mUsage = aa.mUsage;
224            mContentType = aa.mContentType;
225            mFlags = aa.mFlags;
226            mTags = (HashSet<String>) aa.mTags.clone();
227        }
228
229        /**
230         * Combines all of the attributes that have been set and return a new
231         * {@link AudioAttributes} object.
232         * @return a new {@link AudioAttributes} object
233         */
234        @SuppressWarnings("unchecked") // for cloning of mTags
235        public AudioAttributes build() {
236            AudioAttributes aa = new AudioAttributes();
237            aa.mContentType = mContentType;
238            aa.mUsage = mUsage;
239            aa.mFlags = mFlags;
240            aa.mTags = (HashSet<String>) mTags.clone();
241            return aa;
242        }
243
244        /**
245         * Sets the attribute describing what is the intended use of the the audio signal,
246         * such as alarm or ringtone.
247         * @param usage one of {@link AudioAttributes#USAGE_UNKNOWN},
248         *     {@link AudioAttributes#USAGE_MEDIA},
249         *     {@link AudioAttributes#USAGE_VOICE_COMMUNICATION},
250         *     {@link AudioAttributes#USAGE_VOICE_COMMUNICATION_SIGNALLING},
251         *     {@link AudioAttributes#USAGE_ALARM}, {@link AudioAttributes#USAGE_NOTIFICATION},
252         *     {@link AudioAttributes#USAGE_NOTIFICATION_TELEPHONY_RINGTONE},
253         *     {@link AudioAttributes#USAGE_NOTIFICATION_COMMUNICATION_REQUEST},
254         *     {@link AudioAttributes#USAGE_NOTIFICATION_COMMUNICATION_INSTANT},
255         *     {@link AudioAttributes#USAGE_NOTIFICATION_COMMUNICATION_DELAYED},
256         *     {@link AudioAttributes#USAGE_NOTIFICATION_EVENT},
257         *     {@link AudioAttributes#USAGE_ASSISTANCE_ACCESSIBILITY},
258         *     {@link AudioAttributes#USAGE_ASSISTANCE_NAVIGATION_GUIDANCE},
259         *     {@link AudioAttributes#USAGE_ASSISTANCE_SONIFICATION},
260         *     {@link AudioAttributes#USAGE_GAME}.
261         * @return the same Builder instance.
262         */
263        public Builder setUsage(@AttributeUsage int usage) {
264            switch (usage) {
265                case USAGE_UNKNOWN:
266                case USAGE_MEDIA:
267                case USAGE_VOICE_COMMUNICATION:
268                case USAGE_VOICE_COMMUNICATION_SIGNALLING:
269                case USAGE_ALARM:
270                case USAGE_NOTIFICATION:
271                case USAGE_NOTIFICATION_TELEPHONY_RINGTONE:
272                case USAGE_NOTIFICATION_COMMUNICATION_REQUEST:
273                case USAGE_NOTIFICATION_COMMUNICATION_INSTANT:
274                case USAGE_NOTIFICATION_COMMUNICATION_DELAYED:
275                case USAGE_NOTIFICATION_EVENT:
276                case USAGE_ASSISTANCE_ACCESSIBILITY:
277                case USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:
278                case USAGE_ASSISTANCE_SONIFICATION:
279                case USAGE_GAME:
280                     mUsage = usage;
281                     break;
282                default:
283                     mUsage = USAGE_UNKNOWN;
284            }
285            return this;
286        }
287
288        /**
289         * Sets the attribute describing the content type of the audio signal, such as speech,
290         * or music.
291         * @param contentType the content type values, one of
292         *     {@link AudioAttributes#CONTENT_TYPE_MOVIE},
293         *     {@link AudioAttributes#CONTENT_TYPE_MUSIC},
294         *     {@link AudioAttributes#CONTENT_TYPE_SONIFICATION},
295         *     {@link AudioAttributes#CONTENT_TYPE_SPEECH},
296         *     {@link AudioAttributes#CONTENT_TYPE_UNKNOWN}.
297         * @return the same Builder instance.
298         */
299        public Builder setContentType(@AttributeContentType int contentType) {
300            switch (contentType) {
301                case CONTENT_TYPE_UNKNOWN:
302                case CONTENT_TYPE_MOVIE:
303                case CONTENT_TYPE_MUSIC:
304                case CONTENT_TYPE_SONIFICATION:
305                case CONTENT_TYPE_SPEECH:
306                     mContentType = contentType;
307                     break;
308                default:
309                     mUsage = CONTENT_TYPE_UNKNOWN;
310            }
311            return this;
312        }
313
314        /**
315         * Sets the combination of flags.
316         * @param flags the {@link AudioAttributes#FLAG_AUDIBILITY_ENFORCED} flag.
317         * @return the same Builder instance.
318         */
319        public Builder setFlags(int flags) {
320            flags &= (AudioAttributes.FLAG_AUDIBILITY_ENFORCED | AudioAttributes.FLAG_SCO
321                    | AudioAttributes.FLAG_SECURE);
322            mFlags |= flags;
323            return this;
324        }
325
326        /**
327         * Add a custom tag stored as a string
328         * @param tag
329         * @return the same Builder instance.
330         */
331        public Builder addTag(String tag) {
332            mTags.add(tag);
333            return this;
334        }
335
336        /**
337         * Adds attributes inferred from the legacy stream types.
338         * @param streamType one of {@link AudioManager#STREAM_VOICE_CALL},
339         *   {@link AudioManager#STREAM_SYSTEM}, {@link AudioManager#STREAM_RING},
340         *   {@link AudioManager#STREAM_MUSIC}, {@link AudioManager#STREAM_ALARM},
341         *    or {@link AudioManager#STREAM_NOTIFICATION}.
342         * @return the same Builder instance.
343         */
344        public Builder setLegacyStreamType(int streamType) {
345            return setInternalLegacyStreamType(streamType);
346        }
347
348        /**
349         * @hide
350         * For internal framework use only, enables building from hidden stream types.
351         * @param streamType
352         * @return the same Builder instance.
353         */
354        public Builder setInternalLegacyStreamType(int streamType) {
355            switch(streamType) {
356                case AudioSystem.STREAM_VOICE_CALL:
357                    mContentType = CONTENT_TYPE_SPEECH;
358                    mUsage = USAGE_VOICE_COMMUNICATION;
359                    break;
360                case AudioSystem.STREAM_SYSTEM_ENFORCED:
361                    mFlags |= FLAG_AUDIBILITY_ENFORCED;
362                    // intended fall through, attributes in common with STREAM_SYSTEM
363                case AudioSystem.STREAM_SYSTEM:
364                    mContentType = CONTENT_TYPE_SONIFICATION;
365                    mUsage = USAGE_ASSISTANCE_SONIFICATION;
366                    break;
367                case AudioSystem.STREAM_RING:
368                    mContentType = CONTENT_TYPE_SONIFICATION;
369                    mUsage = USAGE_NOTIFICATION_TELEPHONY_RINGTONE;
370                    break;
371                case AudioSystem.STREAM_MUSIC:
372                    mContentType = CONTENT_TYPE_MUSIC;
373                    mUsage = USAGE_MEDIA;
374                    break;
375                case AudioSystem.STREAM_ALARM:
376                    mContentType = CONTENT_TYPE_SONIFICATION;
377                    mUsage = USAGE_ALARM;
378                    break;
379                case AudioSystem.STREAM_NOTIFICATION:
380                    mContentType = CONTENT_TYPE_SONIFICATION;
381                    mUsage = USAGE_NOTIFICATION;
382                    break;
383                case AudioSystem.STREAM_BLUETOOTH_SCO:
384                    mContentType = CONTENT_TYPE_SPEECH;
385                    mUsage = USAGE_VOICE_COMMUNICATION;
386                    mFlags |= FLAG_SCO;
387                    break;
388                case AudioSystem.STREAM_DTMF:
389                    mContentType = CONTENT_TYPE_SONIFICATION;
390                    mUsage = USAGE_VOICE_COMMUNICATION_SIGNALLING;
391                    break;
392                case AudioSystem.STREAM_TTS:
393                    mContentType = CONTENT_TYPE_SPEECH;
394                    mUsage = USAGE_ASSISTANCE_ACCESSIBILITY;
395                    break;
396                default:
397                    Log.e(TAG, "Invalid stream type " + streamType + " in for AudioAttributes");
398            }
399            return this;
400        }
401    };
402
403    /** @hide */
404    @Override
405    public String toString () {
406        return new String("AudioAttributes:"
407                + " usage=" + mUsage
408                + " content=" + mContentType
409                + " flags=0x" + Integer.toHexString(mFlags)
410                + " tags=" + mTags);
411    }
412
413    /** @hide */
414    @IntDef({
415        USAGE_UNKNOWN,
416        USAGE_MEDIA,
417        USAGE_VOICE_COMMUNICATION,
418        USAGE_VOICE_COMMUNICATION_SIGNALLING,
419        USAGE_ALARM,
420        USAGE_NOTIFICATION,
421        USAGE_NOTIFICATION_TELEPHONY_RINGTONE,
422        USAGE_NOTIFICATION_COMMUNICATION_REQUEST,
423        USAGE_NOTIFICATION_COMMUNICATION_INSTANT,
424        USAGE_NOTIFICATION_COMMUNICATION_DELAYED,
425        USAGE_NOTIFICATION_EVENT,
426        USAGE_ASSISTANCE_ACCESSIBILITY,
427        USAGE_ASSISTANCE_NAVIGATION_GUIDANCE,
428        USAGE_ASSISTANCE_SONIFICATION,
429        USAGE_GAME
430    })
431    @Retention(RetentionPolicy.SOURCE)
432    public @interface AttributeUsage {}
433
434    /** @hide */
435    @IntDef({
436        CONTENT_TYPE_UNKNOWN,
437        CONTENT_TYPE_SPEECH,
438        CONTENT_TYPE_MUSIC,
439        CONTENT_TYPE_MOVIE,
440        CONTENT_TYPE_SONIFICATION
441    })
442    @Retention(RetentionPolicy.SOURCE)
443    public @interface AttributeContentType {}
444}
445