blob: f4039889adedf0b39987c80c12496629fad7eb46 [file] [log] [blame]
Jean-Michel Trivid60e8752014-04-18 09:47:08 -07001/*
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;
Jean-Michel Trivid1d5a0a2015-05-18 11:50:50 -070020import android.annotation.NonNull;
Jean-Michel Trivi6894cd32014-07-21 16:06:33 -070021import android.annotation.SystemApi;
Jean-Michel Trivif82f7462016-02-05 15:20:35 -080022import android.os.Bundle;
Jean-Michel Trivib45c2732014-06-03 16:06:48 -070023import android.os.Parcel;
24import android.os.Parcelable;
Jean-Michel Trivicc58c762014-07-30 16:03:41 -070025import android.text.TextUtils;
Jean-Michel Trivid60e8752014-04-18 09:47:08 -070026import android.util.Log;
Jean-Michel Trivie743bda2016-09-09 11:56:48 -070027import android.util.SparseIntArray;
Jean-Michel Trivid60e8752014-04-18 09:47:08 -070028
29import java.lang.annotation.Retention;
30import java.lang.annotation.RetentionPolicy;
31import java.util.Collections;
32import java.util.HashSet;
Jean-Michel Trivie9c19a52014-07-29 13:04:41 -070033import java.util.Objects;
Jean-Michel Trivid60e8752014-04-18 09:47:08 -070034import java.util.Set;
35
36/**
37 * A class to encapsulate a collection of attributes describing information about an audio
Jean-Michel Trivi04f55a492014-09-12 10:07:05 -070038 * 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}.
Jean-Michel Trivid60e8752014-04-18 09:47:08 -070067 */
Jean-Michel Trivib45c2732014-06-03 16:06:48 -070068public final class AudioAttributes implements Parcelable {
Jean-Michel Trivid60e8752014-04-18 09:47:08 -070069 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 */
Jean-Michel Trivi89c3b292014-07-20 11:41:02 -0700127 public final static int USAGE_NOTIFICATION_RINGTONE = 6;
128 /**
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700129 * 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;
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -0700166 /**
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;
Jean-Michel Trivi0c8855d02016-12-29 10:33:29 -0800172 /**
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;
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700177
178 /**
Jean-Michel Trivie743bda2016-09-09 11:56:48 -0700179 * 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;
Jean-Michel Trivi7a84eae2017-06-20 14:58:18 -0700197 /**
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;
Jean-Michel Trivie743bda2016-09-09 11:56:48 -0700203
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();
214 SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION, SUPPRESSIBLE_NOTIFICATION);
215 SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION_RINGTONE, SUPPRESSIBLE_CALL);
216 SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION_COMMUNICATION_REQUEST,SUPPRESSIBLE_CALL);
217 SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION_COMMUNICATION_INSTANT,SUPPRESSIBLE_NOTIFICATION);
218 SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION_COMMUNICATION_DELAYED,SUPPRESSIBLE_NOTIFICATION);
219 SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION_EVENT, SUPPRESSIBLE_NOTIFICATION);
Jean-Michel Trivi7a84eae2017-06-20 14:58:18 -0700220 SUPPRESSIBLE_USAGES.put(USAGE_ASSISTANCE_ACCESSIBILITY, SUPPRESSIBLE_NEVER);
Jean-Michel Trivif1cd71a32017-06-22 19:30:29 -0700221 SUPPRESSIBLE_USAGES.put(USAGE_VOICE_COMMUNICATION, SUPPRESSIBLE_NEVER);
Jean-Michel Trivie743bda2016-09-09 11:56:48 -0700222 }
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,
Jean-Michel Trivi0c8855d02016-12-29 10:33:29 -0800243 USAGE_GAME,
244 USAGE_ASSISTANT,
Jean-Michel Trivie743bda2016-09-09 11:56:48 -0700245 };
246
247 /**
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700248 * 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
Jean-Michel Trivi6894cd32014-07-21 16:06:33 -0700257 // TODO add in FLAG_ALL_PUBLIC when supported and in public API
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700258 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;
Jean-Michel Trivi6894cd32014-07-21 16:06:33 -0700265 /**
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;
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700273
Eric Laurentb634e1b2014-08-01 14:44:46 -0700274 /**
Eric Laurentb634e1b2014-08-01 14:44:46 -0700275 * 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;
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700278
Eric Laurentbdad1af2014-09-19 17:43:29 -0700279 /**
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
John Spurlockbbfd31a2015-02-18 11:58:14 -0500288 /**
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
Phil Burkdd731422015-12-28 10:34:33 -0800302 /**
Phil Burk2050f6c2016-05-25 15:13:57 -0700303 * Flag requesting a low latency path when creating an AudioTrack.
Phil Burkdd731422015-12-28 10:34:33 -0800304 * When using this flag, the sample rate must match the native sample rate
305 * of the device. Effects processing is also unavailable.
Phil Burk2050f6c2016-05-25 15:13:57 -0700306 *
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.
Andy Hungebc2c142017-01-12 19:20:29 -0800317 *
318 * @deprecated Use {@link AudioTrack.Builder#setPerformanceMode(int)} with
319 * {@link AudioTrack#PERFORMANCE_MODE_LOW_LATENCY} to control performance.
Phil Burkdd731422015-12-28 10:34:33 -0800320 */
321 public final static int FLAG_LOW_LATENCY = 0x1 << 8;
322
Andy Hungebc2c142017-01-12 19:20:29 -0800323 /**
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
Jean-Michel Trivi6894cd32014-07-21 16:06:33 -0700334 private final static int FLAG_ALL = FLAG_AUDIBILITY_ENFORCED | FLAG_SECURE | FLAG_SCO |
John Spurlockbbfd31a2015-02-18 11:58:14 -0500335 FLAG_BEACON | FLAG_HW_AV_SYNC | FLAG_HW_HOTWORD | FLAG_BYPASS_INTERRUPTION_POLICY |
Andy Hungebc2c142017-01-12 19:20:29 -0800336 FLAG_BYPASS_MUTE | FLAG_LOW_LATENCY | FLAG_DEEP_BUFFER;
Phil Burkdd731422015-12-28 10:34:33 -0800337 private final static int FLAG_ALL_PUBLIC = FLAG_AUDIBILITY_ENFORCED |
338 FLAG_HW_AV_SYNC | FLAG_LOW_LATENCY;
Jean-Michel Trivi6894cd32014-07-21 16:06:33 -0700339
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700340 private int mUsage = USAGE_UNKNOWN;
341 private int mContentType = CONTENT_TYPE_UNKNOWN;
Jean-Michel Trivi701d6ff2014-07-16 07:51:22 -0700342 private int mSource = MediaRecorder.AudioSource.AUDIO_SOURCE_INVALID;
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700343 private int mFlags = 0x0;
344 private HashSet<String> mTags;
Jean-Michel Trivia1d80e32014-06-18 08:18:41 -0700345 private String mFormattedTags;
Jean-Michel Trivif82f7462016-02-05 15:20:35 -0800346 private Bundle mBundle; // lazy-initialized, may be null
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700347
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 */
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 */
363 public int getUsage() {
364 return mUsage;
365 }
366
367 /**
Jean-Michel Trivi701d6ff2014-07-16 07:51:22 -0700368 * @hide
Jean-Michel Trivi701d6ff2014-07-16 07:51:22 -0700369 * 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 */
Jean-Michel Trivi1b3541d2014-11-25 12:53:41 -0800373 @SystemApi
Jean-Michel Trivi701d6ff2014-07-16 07:51:22 -0700374 public int getCapturePreset() {
375 return mSource;
376 }
377
378 /**
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700379 * Return the flags.
380 * @return a combined mask of all flags
381 */
382 public int getFlags() {
383 // only return the flags that are public
Jean-Michel Trivi6894cd32014-07-21 16:06:33 -0700384 return (mFlags & (FLAG_ALL_PUBLIC));
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700385 }
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 */
Eric Laurent00a00922015-03-09 09:25:45 -0700393 @SystemApi
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700394 public int getAllFlags() {
Jean-Michel Trivi6894cd32014-07-21 16:06:33 -0700395 return (mFlags & FLAG_ALL);
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700396 }
397
398 /**
Jean-Michel Trivib45c2732014-06-03 16:06:48 -0700399 * @hide
Jean-Michel Trivif82f7462016-02-05 15:20:35 -0800400 * Return the Bundle of data.
401 * @return a copy of the Bundle for this instance, may be null.
402 */
403 @SystemApi
404 public Bundle getBundle() {
405 if (mBundle == null) {
406 return mBundle;
407 } else {
408 return new Bundle(mBundle);
409 }
410 }
411
412 /**
413 * @hide
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700414 * Return the set of tags.
415 * @return a read-only set of all tags stored as strings.
416 */
417 public Set<String> getTags() {
418 return Collections.unmodifiableSet(mTags);
419 }
420
421 /**
422 * Builder class for {@link AudioAttributes} objects.
Jean-Michel Trivi04f55a492014-09-12 10:07:05 -0700423 * <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}.
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700439 */
440 public static class Builder {
441 private int mUsage = USAGE_UNKNOWN;
442 private int mContentType = CONTENT_TYPE_UNKNOWN;
Jean-Michel Trivi701d6ff2014-07-16 07:51:22 -0700443 private int mSource = MediaRecorder.AudioSource.AUDIO_SOURCE_INVALID;
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700444 private int mFlags = 0x0;
445 private HashSet<String> mTags = new HashSet<String>();
Jean-Michel Trivif82f7462016-02-05 15:20:35 -0800446 private Bundle mBundle;
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700447
448 /**
449 * Constructs a new Builder with the defaults.
Jean-Michel Trivi04f55a492014-09-12 10:07:05 -0700450 * 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.
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700455 */
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
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
477 public AudioAttributes build() {
478 AudioAttributes aa = new AudioAttributes();
479 aa.mContentType = mContentType;
480 aa.mUsage = mUsage;
Jean-Michel Trivi701d6ff2014-07-16 07:51:22 -0700481 aa.mSource = mSource;
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700482 aa.mFlags = mFlags;
483 aa.mTags = (HashSet<String>) mTags.clone();
Jean-Michel Trivicc58c762014-07-30 16:03:41 -0700484 aa.mFormattedTags = TextUtils.join(";", mTags);
Jean-Michel Trivif82f7462016-02-05 15:20:35 -0800485 if (mBundle != null) {
486 aa.mBundle = new Bundle(mBundle);
487 }
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700488 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},
Jean-Michel Trivi89c3b292014-07-20 11:41:02 -0700499 * {@link AudioAttributes#USAGE_NOTIFICATION_RINGTONE},
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700500 * {@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},
Jean-Michel Trivi0c8855d02016-12-29 10:33:29 -0800504 * {@link AudioAttributes#USAGE_ASSISTANT},
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700505 * {@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 */
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:
Jean-Michel Trivi89c3b292014-07-20 11:41:02 -0700519 case USAGE_NOTIFICATION_RINGTONE:
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700520 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:
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -0700528 case USAGE_VIRTUAL_SOURCE:
Jean-Michel Trivi0c8855d02016-12-29 10:33:29 -0800529 case USAGE_ASSISTANT:
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700530 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 */
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.
Andy Hungebc2c142017-01-12 19:20:29 -0800566 *
567 * This is a bitwise OR with the existing flags.
Jean-Michel Trivi26d2fdb2016-01-14 12:59:39 -0800568 * @param flags a combination of {@link AudioAttributes#FLAG_AUDIBILITY_ENFORCED},
569 * {@link AudioAttributes#FLAG_HW_AV_SYNC}.
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700570 * @return the same Builder instance.
571 */
572 public Builder setFlags(int flags) {
Jean-Michel Trivi6894cd32014-07-21 16:06:33 -0700573 flags &= AudioAttributes.FLAG_ALL;
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700574 mFlags |= flags;
575 return this;
576 }
577
578 /**
Jean-Michel Trivib45c2732014-06-03 16:06:48 -0700579 * @hide
Andy Hungebc2c142017-01-12 19:20:29 -0800580 * Replaces flags.
581 * @param flags any combination of {@link AudioAttributes#FLAG_ALL}.
582 * @return the same Builder instance.
583 */
584 public Builder replaceFlags(int flags) {
585 mFlags = flags & AudioAttributes.FLAG_ALL;
586 return this;
587 }
588
589 /**
590 * @hide
Jean-Michel Trivif82f7462016-02-05 15:20:35 -0800591 * Adds a Bundle of data
592 * @param bundle a non-null Bundle
593 * @return the same builder instance
594 */
595 @SystemApi
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
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700610 * Add a custom tag stored as a string
611 * @param tag
612 * @return the same Builder instance.
613 */
614 public Builder addTag(String tag) {
615 mTags.add(tag);
616 return this;
617 }
618
619 /**
Jean-Michel Trivi04f55a492014-09-12 10:07:05 -0700620 * 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.
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700623 * @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 */
629 public Builder setLegacyStreamType(int streamType) {
Jean-Michel Trivi3f0945a2016-11-11 10:05:18 -0800630 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 }
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700634 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 */
643 public Builder setInternalLegacyStreamType(int streamType) {
644 switch(streamType) {
645 case AudioSystem.STREAM_VOICE_CALL:
646 mContentType = CONTENT_TYPE_SPEECH;
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700647 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;
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700653 break;
654 case AudioSystem.STREAM_RING:
655 mContentType = CONTENT_TYPE_SONIFICATION;
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700656 break;
657 case AudioSystem.STREAM_MUSIC:
658 mContentType = CONTENT_TYPE_MUSIC;
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700659 break;
660 case AudioSystem.STREAM_ALARM:
661 mContentType = CONTENT_TYPE_SONIFICATION;
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700662 break;
663 case AudioSystem.STREAM_NOTIFICATION:
664 mContentType = CONTENT_TYPE_SONIFICATION;
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700665 break;
666 case AudioSystem.STREAM_BLUETOOTH_SCO:
667 mContentType = CONTENT_TYPE_SPEECH;
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700668 mFlags |= FLAG_SCO;
669 break;
670 case AudioSystem.STREAM_DTMF:
671 mContentType = CONTENT_TYPE_SONIFICATION;
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700672 break;
673 case AudioSystem.STREAM_TTS:
Jean-Michel Trivi3f0945a2016-11-11 10:05:18 -0800674 mContentType = CONTENT_TYPE_SONIFICATION;
675 break;
676 case AudioSystem.STREAM_ACCESSIBILITY:
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700677 mContentType = CONTENT_TYPE_SPEECH;
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700678 break;
679 default:
Jean-Michel Trivi701d6ff2014-07-16 07:51:22 -0700680 Log.e(TAG, "Invalid stream type " + streamType + " for AudioAttributes");
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700681 }
Jean-Michel Trivi3f0945a2016-11-11 10:05:18 -0800682 mUsage = usageForStreamType(streamType);
Jean-Michel Trivi701d6ff2014-07-16 07:51:22 -0700683 return this;
684 }
685
686 /**
687 * @hide
Jean-Michel Trivi701d6ff2014-07-16 07:51:22 -0700688 * 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},
ragoa7cc59c2015-12-02 11:31:15 -0800693 * {@link MediaRecorder.AudioSource#VOICE_RECOGNITION},
694 * {@link MediaRecorder.AudioSource#VOICE_COMMUNICATION} or
695 * {@link MediaRecorder.AudioSource#UNPROCESSED}
Jean-Michel Trivi701d6ff2014-07-16 07:51:22 -0700696 * @return the same Builder instance.
697 */
Jean-Michel Trivi1b3541d2014-11-25 12:53:41 -0800698 @SystemApi
Jean-Michel Trivi701d6ff2014-07-16 07:51:22 -0700699 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:
ragoa7cc59c2015-12-02 11:31:15 -0800706 case MediaRecorder.AudioSource.UNPROCESSED:
Jean-Michel Trivi701d6ff2014-07-16 07:51:22 -0700707 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
Benson Huangce4483c2014-09-17 17:21:02 +0800717 * Same as {@link #setCapturePreset(int)} but authorizes the use of HOTWORD,
Eric Laurent00a00922015-03-09 09:25:45 -0700718 * REMOTE_SUBMIX and RADIO_TUNER.
Jean-Michel Trivi701d6ff2014-07-16 07:51:22 -0700719 * @param preset
720 * @return the same Builder instance.
721 */
Eric Laurent00a00922015-03-09 09:25:45 -0700722 @SystemApi
Jean-Michel Trivi701d6ff2014-07-16 07:51:22 -0700723 public Builder setInternalCapturePreset(int preset) {
724 if ((preset == MediaRecorder.AudioSource.HOTWORD)
Benson Huangce4483c2014-09-17 17:21:02 +0800725 || (preset == MediaRecorder.AudioSource.REMOTE_SUBMIX)
Eric Laurent00a00922015-03-09 09:25:45 -0700726 || (preset == MediaRecorder.AudioSource.RADIO_TUNER)) {
Jean-Michel Trivi701d6ff2014-07-16 07:51:22 -0700727 mSource = preset;
728 } else {
729 setCapturePreset(preset);
730 }
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700731 return this;
732 }
733 };
734
Jean-Michel Trivib45c2732014-06-03 16:06:48 -0700735 @Override
736 public int describeContents() {
737 return 0;
738 }
739
Jean-Michel Trivi8df982d2014-06-26 12:05:16 -0700740 /**
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;
Jean-Michel Trivif82f7462016-02-05 15:20:35 -0800748
749 private final static int ATTR_PARCEL_IS_NULL_BUNDLE = -1977;
750 private final static int ATTR_PARCEL_IS_VALID_BUNDLE = 1980;
751
Jean-Michel Trivi8df982d2014-06-26 12:05:16 -0700752 /**
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;
Jean-Michel Trivib45c2732014-06-03 16:06:48 -0700756 @Override
757 public void writeToParcel(Parcel dest, int flags) {
758 dest.writeInt(mUsage);
759 dest.writeInt(mContentType);
Jean-Michel Trivi701d6ff2014-07-16 07:51:22 -0700760 dest.writeInt(mSource);
Jean-Michel Trivib45c2732014-06-03 16:06:48 -0700761 dest.writeInt(mFlags);
Jean-Michel Trivi8df982d2014-06-26 12:05:16 -0700762 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 }
Jean-Michel Trivif82f7462016-02-05 15:20:35 -0800770 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 }
Jean-Michel Trivib45c2732014-06-03 16:06:48 -0700776 }
777
778 private AudioAttributes(Parcel in) {
779 mUsage = in.readInt();
780 mContentType = in.readInt();
Jean-Michel Trivi701d6ff2014-07-16 07:51:22 -0700781 mSource = in.readInt();
Jean-Michel Trivib45c2732014-06-03 16:06:48 -0700782 mFlags = in.readInt();
Jean-Michel Trivi8df982d2014-06-26 12:05:16 -0700783 boolean hasFlattenedTags = ((in.readInt() & FLATTEN_TAGS) == FLATTEN_TAGS);
Jean-Michel Trivib45c2732014-06-03 16:06:48 -0700784 mTags = new HashSet<String>();
Jean-Michel Trivi8df982d2014-06-26 12:05:16 -0700785 if (hasFlattenedTags) {
Jean-Michel Trivicc58c762014-07-30 16:03:41 -0700786 mFormattedTags = new String(in.readString());
787 mTags.add(mFormattedTags);
Jean-Michel Trivi8df982d2014-06-26 12:05:16 -0700788 } else {
789 String[] tagsArray = in.readStringArray();
790 for (int i = tagsArray.length - 1 ; i >= 0 ; i--) {
791 mTags.add(tagsArray[i]);
792 }
Jean-Michel Trivicc58c762014-07-30 16:03:41 -0700793 mFormattedTags = TextUtils.join(";", mTags);
Jean-Michel Trivib45c2732014-06-03 16:06:48 -0700794 }
Jean-Michel Trivif82f7462016-02-05 15:20:35 -0800795 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 }
Jean-Michel Trivib45c2732014-06-03 16:06:48 -0700805 }
806
Jean-Michel Trivib45c2732014-06-03 16:06:48 -0700807 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
Jean-Michel Trivie9c19a52014-07-29 13:04:41 -0700822 @Override
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
838 public int hashCode() {
Jean-Michel Trivif82f7462016-02-05 15:20:35 -0800839 return Objects.hash(mContentType, mFlags, mSource, mUsage, mFormattedTags, mBundle);
Jean-Michel Trivie9c19a52014-07-29 13:04:41 -0700840 }
841
Jean-Michel Trivia8b6bd882014-07-01 09:48:46 -0700842 @Override
843 public String toString () {
844 return new String("AudioAttributes:"
845 + " usage=" + mUsage
846 + " content=" + mContentType
847 + " flags=0x" + Integer.toHexString(mFlags).toUpperCase()
Jean-Michel Trivif82f7462016-02-05 15:20:35 -0800848 + " tags=" + mFormattedTags
849 + " bundle=" + (mBundle == null ? "null" : mBundle.toString()));
Jean-Michel Trivia8b6bd882014-07-01 09:48:46 -0700850 }
851
Jean-Michel Trivi998ff752014-07-11 10:01:00 -0700852 /** @hide */
Jean-Michel Trivia8b6bd882014-07-01 09:48:46 -0700853 public String usageToString() {
John Spurlock7b414672014-07-18 13:02:39 -0400854 return usageToString(mUsage);
855 }
856
857 /** @hide */
858 public static String usageToString(int usage) {
859 switch(usage) {
Jean-Michel Trivia8b6bd882014-07-01 09:48:46 -0700860 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:
Zach Johnson45228bf2015-08-24 16:33:16 -0700867 return new String("USAGE_VOICE_COMMUNICATION_SIGNALLING");
Jean-Michel Trivia8b6bd882014-07-01 09:48:46 -0700868 case USAGE_ALARM:
869 return new String("USAGE_ALARM");
870 case USAGE_NOTIFICATION:
871 return new String("USAGE_NOTIFICATION");
Jean-Michel Trivi89c3b292014-07-20 11:41:02 -0700872 case USAGE_NOTIFICATION_RINGTONE:
Zach Johnson45228bf2015-08-24 16:33:16 -0700873 return new String("USAGE_NOTIFICATION_RINGTONE");
Jean-Michel Trivia8b6bd882014-07-01 09:48:46 -0700874 case USAGE_NOTIFICATION_COMMUNICATION_REQUEST:
Zach Johnson45228bf2015-08-24 16:33:16 -0700875 return new String("USAGE_NOTIFICATION_COMMUNICATION_REQUEST");
Jean-Michel Trivia8b6bd882014-07-01 09:48:46 -0700876 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");
Jean-Michel Trivi0c8855d02016-12-29 10:33:29 -0800890 case USAGE_ASSISTANT:
891 return new String("USAGE_ASSISTANT");
Jean-Michel Trivia8b6bd882014-07-01 09:48:46 -0700892 default:
John Spurlock7b414672014-07-18 13:02:39 -0400893 return new String("unknown usage " + usage);
894 }
895 }
896
Jean-Michel Trivi3f0945a2016-11-11 10:05:18 -0800897 private static int usageForStreamType(int streamType) {
John Spurlock7b414672014-07-18 13:02:39 -0400898 switch(streamType) {
899 case AudioSystem.STREAM_VOICE_CALL:
900 return USAGE_VOICE_COMMUNICATION;
901 case AudioSystem.STREAM_SYSTEM_ENFORCED:
902 case AudioSystem.STREAM_SYSTEM:
903 return USAGE_ASSISTANCE_SONIFICATION;
904 case AudioSystem.STREAM_RING:
Jean-Michel Trivi89c3b292014-07-20 11:41:02 -0700905 return USAGE_NOTIFICATION_RINGTONE;
John Spurlock7b414672014-07-18 13:02:39 -0400906 case AudioSystem.STREAM_MUSIC:
907 return USAGE_MEDIA;
908 case AudioSystem.STREAM_ALARM:
909 return USAGE_ALARM;
910 case AudioSystem.STREAM_NOTIFICATION:
911 return USAGE_NOTIFICATION;
912 case AudioSystem.STREAM_BLUETOOTH_SCO:
913 return USAGE_VOICE_COMMUNICATION;
914 case AudioSystem.STREAM_DTMF:
915 return USAGE_VOICE_COMMUNICATION_SIGNALLING;
Jean-Michel Trivi3f0945a2016-11-11 10:05:18 -0800916 case AudioSystem.STREAM_ACCESSIBILITY:
John Spurlock7b414672014-07-18 13:02:39 -0400917 return USAGE_ASSISTANCE_ACCESSIBILITY;
Jean-Michel Trivi3f0945a2016-11-11 10:05:18 -0800918 case AudioSystem.STREAM_TTS:
John Spurlock7b414672014-07-18 13:02:39 -0400919 default:
920 return USAGE_UNKNOWN;
Jean-Michel Trivia8b6bd882014-07-01 09:48:46 -0700921 }
922 }
Jean-Michel Trivie67bc4d2017-03-27 11:52:18 -0700923
Jean-Michel Trivi3d22bf02015-02-03 10:15:08 -0800924 /**
Jean-Michel Trivie67bc4d2017-03-27 11:52:18 -0700925 * Returns the stream type matching this {@code AudioAttributes} instance for volume control.
926 * Use this method to derive the stream type needed to configure the volume
927 * control slider in an {@link android.app.Activity} with
928 * {@link android.app.Activity#setVolumeControlStream(int)} for playback conducted with these
929 * attributes.
930 * <BR>Do not use this method to set the stream type on an audio player object
931 * (e.g. {@link AudioTrack}, {@link MediaPlayer}) as this is deprecated,
932 * use {@code AudioAttributes} instead.
933 * @return a valid stream type for {@code Activity} or stream volume control that matches
934 * the attributes, or {@link AudioManager#USE_DEFAULT_STREAM_TYPE} if there isn't a direct
935 * match. Note that {@code USE_DEFAULT_STREAM_TYPE} is not a valid value
936 * for {@link AudioManager#setStreamVolume(int, int, int)}.
937 */
938 public int getVolumeControlStream() {
939 return toVolumeStreamType(true /*fromGetVolumeControlStream*/, this);
940 }
941
942 /**
Jean-Michel Trivi3d22bf02015-02-03 10:15:08 -0800943 * @hide
944 * Only use to get which stream type should be used for volume control, NOT for audio playback
945 * (all audio playback APIs are supposed to take AudioAttributes as input parameters)
946 * @param aa non-null AudioAttributes.
947 * @return a valid stream type for volume control that matches the attributes.
948 */
Jean-Michel Trivid1d5a0a2015-05-18 11:50:50 -0700949 public static int toLegacyStreamType(@NonNull AudioAttributes aa) {
950 return toVolumeStreamType(false /*fromGetVolumeControlStream*/, aa);
951 }
952
953 private static int toVolumeStreamType(boolean fromGetVolumeControlStream, AudioAttributes aa) {
Jean-Michel Trivi09818c12014-07-18 17:19:03 -0700954 // flags to stream type mapping
955 if ((aa.getFlags() & FLAG_AUDIBILITY_ENFORCED) == FLAG_AUDIBILITY_ENFORCED) {
Jean-Michel Trivid1d5a0a2015-05-18 11:50:50 -0700956 return fromGetVolumeControlStream ?
957 AudioSystem.STREAM_SYSTEM : AudioSystem.STREAM_SYSTEM_ENFORCED;
Jean-Michel Trivi09818c12014-07-18 17:19:03 -0700958 }
959 if ((aa.getFlags() & FLAG_SCO) == FLAG_SCO) {
Jean-Michel Trivid1d5a0a2015-05-18 11:50:50 -0700960 return fromGetVolumeControlStream ?
961 AudioSystem.STREAM_VOICE_CALL : AudioSystem.STREAM_BLUETOOTH_SCO;
Jean-Michel Trivi09818c12014-07-18 17:19:03 -0700962 }
963
964 // usage to stream type mapping
965 switch (aa.getUsage()) {
966 case USAGE_MEDIA:
967 case USAGE_GAME:
Jean-Michel Trivi09818c12014-07-18 17:19:03 -0700968 case USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:
Jean-Michel Trivi0c8855d02016-12-29 10:33:29 -0800969 case USAGE_ASSISTANT:
Jean-Michel Trivi09818c12014-07-18 17:19:03 -0700970 return AudioSystem.STREAM_MUSIC;
971 case USAGE_ASSISTANCE_SONIFICATION:
972 return AudioSystem.STREAM_SYSTEM;
973 case USAGE_VOICE_COMMUNICATION:
974 return AudioSystem.STREAM_VOICE_CALL;
975 case USAGE_VOICE_COMMUNICATION_SIGNALLING:
Jean-Michel Trivid1d5a0a2015-05-18 11:50:50 -0700976 return fromGetVolumeControlStream ?
977 AudioSystem.STREAM_VOICE_CALL : AudioSystem.STREAM_DTMF;
Jean-Michel Trivi09818c12014-07-18 17:19:03 -0700978 case USAGE_ALARM:
979 return AudioSystem.STREAM_ALARM;
Jean-Michel Trivi89c3b292014-07-20 11:41:02 -0700980 case USAGE_NOTIFICATION_RINGTONE:
Jean-Michel Trivi09818c12014-07-18 17:19:03 -0700981 return AudioSystem.STREAM_RING;
982 case USAGE_NOTIFICATION:
983 case USAGE_NOTIFICATION_COMMUNICATION_REQUEST:
984 case USAGE_NOTIFICATION_COMMUNICATION_INSTANT:
985 case USAGE_NOTIFICATION_COMMUNICATION_DELAYED:
986 case USAGE_NOTIFICATION_EVENT:
987 return AudioSystem.STREAM_NOTIFICATION;
Jean-Michel Trivi3f0945a2016-11-11 10:05:18 -0800988 case USAGE_ASSISTANCE_ACCESSIBILITY:
989 return AudioSystem.STREAM_ACCESSIBILITY;
Jean-Michel Trivi09818c12014-07-18 17:19:03 -0700990 case USAGE_UNKNOWN:
Jean-Michel Trivid1d5a0a2015-05-18 11:50:50 -0700991 return fromGetVolumeControlStream ?
992 AudioManager.USE_DEFAULT_STREAM_TYPE : AudioSystem.STREAM_MUSIC;
Jean-Michel Trivi09818c12014-07-18 17:19:03 -0700993 default:
Jean-Michel Trivid1d5a0a2015-05-18 11:50:50 -0700994 if (fromGetVolumeControlStream) {
995 throw new IllegalArgumentException("Unknown usage value " + aa.getUsage() +
996 " in audio attributes");
997 } else {
998 return AudioSystem.STREAM_MUSIC;
999 }
Jean-Michel Trivi09818c12014-07-18 17:19:03 -07001000 }
1001 }
1002
1003 /** @hide */
Jean-Michel Trivid60e8752014-04-18 09:47:08 -07001004 @IntDef({
1005 USAGE_UNKNOWN,
1006 USAGE_MEDIA,
1007 USAGE_VOICE_COMMUNICATION,
1008 USAGE_VOICE_COMMUNICATION_SIGNALLING,
1009 USAGE_ALARM,
1010 USAGE_NOTIFICATION,
Jean-Michel Trivi89c3b292014-07-20 11:41:02 -07001011 USAGE_NOTIFICATION_RINGTONE,
Jean-Michel Trivid60e8752014-04-18 09:47:08 -07001012 USAGE_NOTIFICATION_COMMUNICATION_REQUEST,
1013 USAGE_NOTIFICATION_COMMUNICATION_INSTANT,
1014 USAGE_NOTIFICATION_COMMUNICATION_DELAYED,
1015 USAGE_NOTIFICATION_EVENT,
1016 USAGE_ASSISTANCE_ACCESSIBILITY,
1017 USAGE_ASSISTANCE_NAVIGATION_GUIDANCE,
1018 USAGE_ASSISTANCE_SONIFICATION,
Jean-Michel Trivi0c8855d02016-12-29 10:33:29 -08001019 USAGE_GAME,
1020 USAGE_ASSISTANT,
Jean-Michel Trivid60e8752014-04-18 09:47:08 -07001021 })
1022 @Retention(RetentionPolicy.SOURCE)
1023 public @interface AttributeUsage {}
1024
1025 /** @hide */
1026 @IntDef({
1027 CONTENT_TYPE_UNKNOWN,
1028 CONTENT_TYPE_SPEECH,
1029 CONTENT_TYPE_MUSIC,
1030 CONTENT_TYPE_MOVIE,
1031 CONTENT_TYPE_SONIFICATION
1032 })
1033 @Retention(RetentionPolicy.SOURCE)
1034 public @interface AttributeContentType {}
1035}