blob: a5757b908144f4ee62f58c0677668906edc5bdfe [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;
Eric Laurent0eb901b2019-12-06 18:15:28 -080021import android.annotation.RequiresPermission;
Jean-Michel Trivi6894cd32014-07-21 16:06:33 -070022import android.annotation.SystemApi;
Hayden Gomes24b336f2020-11-05 16:28:21 -080023import android.annotation.TestApi;
24import android.audio.policy.configuration.V7_0.AudioUsage;
Artur Satayev53fe9662019-12-10 17:47:55 +000025import android.compat.annotation.UnsupportedAppUsage;
Hayden Gomes6d69bde2019-04-04 13:10:13 -070026import android.media.audiopolicy.AudioProductStrategy;
Mathew Inwood8c854f82018-09-14 12:35:36 +010027import android.os.Build;
Jean-Michel Trivif82f7462016-02-05 15:20:35 -080028import android.os.Bundle;
Jean-Michel Trivib45c2732014-06-03 16:06:48 -070029import android.os.Parcel;
30import android.os.Parcelable;
Jean-Michel Trivicc58c762014-07-30 16:03:41 -070031import android.text.TextUtils;
Jean-Michel Trivid60e8752014-04-18 09:47:08 -070032import android.util.Log;
Jean-Michel Trivie743bda2016-09-09 11:56:48 -070033import android.util.SparseIntArray;
Kweku Adams62b42242017-09-25 12:54:02 -070034import android.util.proto.ProtoOutputStream;
Jean-Michel Trivid60e8752014-04-18 09:47:08 -070035
36import java.lang.annotation.Retention;
37import java.lang.annotation.RetentionPolicy;
38import java.util.Collections;
Hayden Gomes24b336f2020-11-05 16:28:21 -080039import java.util.HashMap;
Jean-Michel Trivid60e8752014-04-18 09:47:08 -070040import java.util.HashSet;
Hayden Gomes24b336f2020-11-05 16:28:21 -080041import java.util.Map;
Jean-Michel Trivie9c19a52014-07-29 13:04:41 -070042import java.util.Objects;
Jean-Michel Trivid60e8752014-04-18 09:47:08 -070043import java.util.Set;
44
45/**
46 * A class to encapsulate a collection of attributes describing information about an audio
Jean-Michel Trivi04f55a492014-09-12 10:07:05 -070047 * stream.
48 * <p><code>AudioAttributes</code> supersede the notion of stream types (see for instance
49 * {@link AudioManager#STREAM_MUSIC} or {@link AudioManager#STREAM_ALARM}) for defining the
50 * behavior of audio playback. Attributes allow an application to specify more information than is
51 * conveyed in a stream type by allowing the application to define:
52 * <ul>
53 * <li>usage: "why" you are playing a sound, what is this sound used for. This is achieved with
54 * the "usage" information. Examples of usage are {@link #USAGE_MEDIA} and {@link #USAGE_ALARM}.
55 * These two examples are the closest to stream types, but more detailed use cases are
56 * available. Usage information is more expressive than a stream type, and allows certain
57 * platforms or routing policies to use this information for more refined volume or routing
58 * decisions. Usage is the most important information to supply in <code>AudioAttributes</code>
59 * and it is recommended to build any instance with this information supplied, see
60 * {@link AudioAttributes.Builder} for exceptions.</li>
61 * <li>content type: "what" you are playing. The content type expresses the general category of
62 * the content. This information is optional. But in case it is known (for instance
63 * {@link #CONTENT_TYPE_MOVIE} for a movie streaming service or {@link #CONTENT_TYPE_MUSIC} for
64 * a music playback application) this information might be used by the audio framework to
65 * selectively configure some audio post-processing blocks.</li>
66 * <li>flags: "how" is playback to be affected, see the flag definitions for the specific playback
67 * behaviors they control. </li>
68 * </ul>
69 * <p><code>AudioAttributes</code> are used for example in one of the {@link AudioTrack}
70 * constructors (see {@link AudioTrack#AudioTrack(AudioAttributes, AudioFormat, int, int, int)}),
71 * to configure a {@link MediaPlayer}
72 * (see {@link MediaPlayer#setAudioAttributes(AudioAttributes)} or a
73 * {@link android.app.Notification} (see {@link android.app.Notification#audioAttributes}). An
74 * <code>AudioAttributes</code> instance is built through its builder,
75 * {@link AudioAttributes.Builder}.
Jean-Michel Trivid60e8752014-04-18 09:47:08 -070076 */
Jean-Michel Trivib45c2732014-06-03 16:06:48 -070077public final class AudioAttributes implements Parcelable {
Jean-Michel Trivid60e8752014-04-18 09:47:08 -070078 private final static String TAG = "AudioAttributes";
79
80 /**
81 * Content type value to use when the content type is unknown, or other than the ones defined.
82 */
83 public final static int CONTENT_TYPE_UNKNOWN = 0;
84 /**
85 * Content type value to use when the content type is speech.
86 */
87 public final static int CONTENT_TYPE_SPEECH = 1;
88 /**
89 * Content type value to use when the content type is music.
90 */
91 public final static int CONTENT_TYPE_MUSIC = 2;
92 /**
93 * Content type value to use when the content type is a soundtrack, typically accompanying
94 * a movie or TV program.
95 */
96 public final static int CONTENT_TYPE_MOVIE = 3;
97 /**
98 * Content type value to use when the content type is a sound used to accompany a user
99 * action, such as a beep or sound effect expressing a key click, or event, such as the
100 * type of a sound for a bonus being received in a game. These sounds are mostly synthesized
101 * or short Foley sounds.
102 */
103 public final static int CONTENT_TYPE_SONIFICATION = 4;
Carter Hsu02677712021-10-20 16:12:53 +0800104 /**
105 * @hide
106 * Content type value to use when the content type is ultrasound.
107 */
108 @SystemApi
109 @RequiresPermission(android.Manifest.permission.ACCESS_ULTRASOUND)
110 public static final int CONTENT_TYPE_ULTRASOUND = 1997;
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700111
112 /**
Hayden Gomesfe2c8772019-12-23 11:37:23 -0800113 * Invalid value, only ever used for an uninitialized usage value
114 */
115 private static final int USAGE_INVALID = -1;
116 /**
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700117 * Usage value to use when the usage is unknown.
118 */
119 public final static int USAGE_UNKNOWN = 0;
120 /**
121 * Usage value to use when the usage is media, such as music, or movie
122 * soundtracks.
123 */
124 public final static int USAGE_MEDIA = 1;
125 /**
126 * Usage value to use when the usage is voice communications, such as telephony
127 * or VoIP.
128 */
129 public final static int USAGE_VOICE_COMMUNICATION = 2;
130 /**
131 * Usage value to use when the usage is in-call signalling, such as with
132 * a "busy" beep, or DTMF tones.
133 */
134 public final static int USAGE_VOICE_COMMUNICATION_SIGNALLING = 3;
135 /**
136 * Usage value to use when the usage is an alarm (e.g. wake-up alarm).
137 */
138 public final static int USAGE_ALARM = 4;
139 /**
140 * Usage value to use when the usage is notification. See other
141 * notification usages for more specialized uses.
142 */
143 public final static int USAGE_NOTIFICATION = 5;
144 /**
145 * Usage value to use when the usage is telephony ringtone.
146 */
Jean-Michel Trivi89c3b292014-07-20 11:41:02 -0700147 public final static int USAGE_NOTIFICATION_RINGTONE = 6;
148 /**
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700149 * Usage value to use when the usage is a request to enter/end a
150 * communication, such as a VoIP communication or video-conference.
Jean-Michel Trivi9ed5b232021-09-07 08:16:32 -0700151 * @deprecated Use {@link #USAGE_NOTIFICATION} which is handled
152 * the same way as this usage by the audio framework
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700153 */
Jean-Michel Trivide334852021-08-30 10:47:03 -0700154 @Deprecated
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700155 public final static int USAGE_NOTIFICATION_COMMUNICATION_REQUEST = 7;
156 /**
157 * Usage value to use when the usage is notification for an "instant"
158 * communication such as a chat, or SMS.
Jean-Michel Trivi9ed5b232021-09-07 08:16:32 -0700159 * @deprecated Use {@link #USAGE_NOTIFICATION} which is handled
160 * the same way as this usage by the audio framework
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700161 */
Jean-Michel Trivide334852021-08-30 10:47:03 -0700162 @Deprecated
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700163 public final static int USAGE_NOTIFICATION_COMMUNICATION_INSTANT = 8;
164 /**
165 * Usage value to use when the usage is notification for a
166 * non-immediate type of communication such as e-mail.
Jean-Michel Trivi9ed5b232021-09-07 08:16:32 -0700167 * @deprecated Use {@link #USAGE_NOTIFICATION} which is handled
168 * the same way as this usage by the audio framework
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700169 */
Jean-Michel Trivide334852021-08-30 10:47:03 -0700170 @Deprecated
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700171 public final static int USAGE_NOTIFICATION_COMMUNICATION_DELAYED = 9;
172 /**
173 * Usage value to use when the usage is to attract the user's attention,
174 * such as a reminder or low battery warning.
175 */
176 public final static int USAGE_NOTIFICATION_EVENT = 10;
177 /**
178 * Usage value to use when the usage is for accessibility, such as with
179 * a screen reader.
180 */
181 public final static int USAGE_ASSISTANCE_ACCESSIBILITY = 11;
182 /**
183 * Usage value to use when the usage is driving or navigation directions.
184 */
185 public final static int USAGE_ASSISTANCE_NAVIGATION_GUIDANCE = 12;
186 /**
187 * Usage value to use when the usage is sonification, such as with user
188 * interface sounds.
189 */
190 public final static int USAGE_ASSISTANCE_SONIFICATION = 13;
191 /**
192 * Usage value to use when the usage is for game audio.
193 */
194 public final static int USAGE_GAME = 14;
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -0700195 /**
196 * @hide
197 * Usage value to use when feeding audio to the platform and replacing "traditional" audio
198 * source, such as audio capture devices.
199 */
200 public final static int USAGE_VIRTUAL_SOURCE = 15;
Jean-Michel Trivi0c8855d02016-12-29 10:33:29 -0800201 /**
202 * Usage value to use for audio responses to user queries, audio instructions or help
203 * utterances.
204 */
205 public final static int USAGE_ASSISTANT = 16;
Eric Laurent0eb901b2019-12-06 18:15:28 -0800206 /**
207 * @hide
208 * Usage value to use for assistant voice interaction with remote caller on Cell and VoIP calls.
209 */
210 @SystemApi
Hayden Gomesfe2c8772019-12-23 11:37:23 -0800211 @RequiresPermission(allOf = {
212 android.Manifest.permission.MODIFY_PHONE_STATE,
213 android.Manifest.permission.MODIFY_AUDIO_ROUTING
214 })
Eric Laurent0eb901b2019-12-06 18:15:28 -0800215 public static final int USAGE_CALL_ASSISTANT = 17;
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700216
Hayden Gomesfe2c8772019-12-23 11:37:23 -0800217 private static final int SYSTEM_USAGE_OFFSET = 1000;
218
219 /**
220 * @hide
221 * Usage value to use when the usage is an emergency.
222 */
223 @SystemApi
224 @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
225 public static final int USAGE_EMERGENCY = SYSTEM_USAGE_OFFSET;
226 /**
227 * @hide
228 * Usage value to use when the usage is a safety sound.
229 */
230 @SystemApi
231 @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
232 public static final int USAGE_SAFETY = SYSTEM_USAGE_OFFSET + 1;
233 /**
234 * @hide
235 * Usage value to use when the usage is a vehicle status.
236 */
237 @SystemApi
238 @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
239 public static final int USAGE_VEHICLE_STATUS = SYSTEM_USAGE_OFFSET + 2;
240 /**
241 * @hide
242 * Usage value to use when the usage is an announcement.
243 */
244 @SystemApi
245 @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
246 public static final int USAGE_ANNOUNCEMENT = SYSTEM_USAGE_OFFSET + 3;
247
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700248 /**
Jean-Michel Trivie743bda2016-09-09 11:56:48 -0700249 * IMPORTANT: when adding new usage types, add them to SDK_USAGES and update SUPPRESSIBLE_USAGES
Kweku Adams62b42242017-09-25 12:54:02 -0700250 * if applicable, as well as audioattributes.proto.
Phil Burk91df2712018-01-17 15:01:43 -0800251 * Also consider adding them to <aaudio/AAudio.h> for the NDK.
Hongwei Wang1b322dd2018-04-03 16:22:06 -0700252 * Also consider adding them to UsageTypeConverter for service dump and etc.
Jean-Michel Trivie743bda2016-09-09 11:56:48 -0700253 */
254
255 /**
256 * @hide
257 * Denotes a usage for notifications that do not expect immediate intervention from the user,
258 * will be muted when the Zen mode disables notifications
259 * @see #SUPPRESSIBLE_USAGES
260 */
261 public final static int SUPPRESSIBLE_NOTIFICATION = 1;
262 /**
263 * @hide
264 * Denotes a usage for notifications that do expect immediate intervention from the user,
265 * will be muted when the Zen mode disables calls
266 * @see #SUPPRESSIBLE_USAGES
267 */
268 public final static int SUPPRESSIBLE_CALL = 2;
Jean-Michel Trivi7a84eae2017-06-20 14:58:18 -0700269 /**
270 * @hide
271 * Denotes a usage that is never going to be muted, even in Total Silence.
272 * @see #SUPPRESSIBLE_USAGES
273 */
274 public final static int SUPPRESSIBLE_NEVER = 3;
Beverly04216872017-09-28 10:55:32 -0400275 /**
276 * @hide
277 * Denotes a usage for alarms,
Beverlyd6964762018-02-16 14:07:03 -0500278 * will be muted when the Zen mode priority doesn't allow alarms or in Alarms Only Mode
Beverly04216872017-09-28 10:55:32 -0400279 * @see #SUPPRESSIBLE_USAGES
280 */
281 public final static int SUPPRESSIBLE_ALARM = 4;
282 /**
283 * @hide
Beverlyd6964762018-02-16 14:07:03 -0500284 * Denotes a usage for media, game, assistant, and navigation
285 * will be muted when the Zen priority mode doesn't allow media
Beverly04216872017-09-28 10:55:32 -0400286 * @see #SUPPRESSIBLE_USAGES
287 */
Beverlyd6964762018-02-16 14:07:03 -0500288 public final static int SUPPRESSIBLE_MEDIA = 5;
289 /**
290 * @hide
Beverly1feff712019-05-29 09:31:12 -0400291 * Denotes a usage for sounds not caught in SUPPRESSIBLE_NOTIFICATION,
Beverlyd6964762018-02-16 14:07:03 -0500292 * SUPPRESSIBLE_CALL,SUPPRESSIBLE_NEVER, SUPPRESSIBLE_ALARM or SUPPRESSIBLE_MEDIA.
Beverly1feff712019-05-29 09:31:12 -0400293 * This includes sonification sounds.
294 * These will be muted when the Zen priority mode doesn't allow system sounds
Beverlyd6964762018-02-16 14:07:03 -0500295 * @see #SUPPRESSIBLE_USAGES
296 */
297 public final static int SUPPRESSIBLE_SYSTEM = 6;
Jean-Michel Trivie743bda2016-09-09 11:56:48 -0700298
299 /**
300 * @hide
301 * Array of all usage types for calls and notifications to assign the suppression behavior,
302 * used by the Zen mode restrictions.
303 * @see com.android.server.notification.ZenModeHelper
304 */
305 public static final SparseIntArray SUPPRESSIBLE_USAGES;
306
307 static {
308 SUPPRESSIBLE_USAGES = new SparseIntArray();
309 SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION, SUPPRESSIBLE_NOTIFICATION);
310 SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION_RINGTONE, SUPPRESSIBLE_CALL);
311 SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION_COMMUNICATION_REQUEST,SUPPRESSIBLE_CALL);
312 SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION_COMMUNICATION_INSTANT,SUPPRESSIBLE_NOTIFICATION);
313 SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION_COMMUNICATION_DELAYED,SUPPRESSIBLE_NOTIFICATION);
314 SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION_EVENT, SUPPRESSIBLE_NOTIFICATION);
Jean-Michel Trivi7a84eae2017-06-20 14:58:18 -0700315 SUPPRESSIBLE_USAGES.put(USAGE_ASSISTANCE_ACCESSIBILITY, SUPPRESSIBLE_NEVER);
Jean-Michel Trivif1cd71a2017-06-22 19:30:29 -0700316 SUPPRESSIBLE_USAGES.put(USAGE_VOICE_COMMUNICATION, SUPPRESSIBLE_NEVER);
Beverly1feff712019-05-29 09:31:12 -0400317 SUPPRESSIBLE_USAGES.put(USAGE_VOICE_COMMUNICATION_SIGNALLING, SUPPRESSIBLE_NEVER);
Beverly04216872017-09-28 10:55:32 -0400318 SUPPRESSIBLE_USAGES.put(USAGE_ALARM, SUPPRESSIBLE_ALARM);
Beverlyd6964762018-02-16 14:07:03 -0500319 SUPPRESSIBLE_USAGES.put(USAGE_MEDIA, SUPPRESSIBLE_MEDIA);
320 SUPPRESSIBLE_USAGES.put(USAGE_ASSISTANCE_NAVIGATION_GUIDANCE, SUPPRESSIBLE_MEDIA);
321 SUPPRESSIBLE_USAGES.put(USAGE_GAME, SUPPRESSIBLE_MEDIA);
322 SUPPRESSIBLE_USAGES.put(USAGE_ASSISTANT, SUPPRESSIBLE_MEDIA);
Eric Laurent0eb901b2019-12-06 18:15:28 -0800323 SUPPRESSIBLE_USAGES.put(USAGE_CALL_ASSISTANT, SUPPRESSIBLE_NEVER);
Jean-Michel Trivi6d38a1b2018-04-09 10:54:36 -0700324 /** default volume assignment is STREAM_MUSIC, handle unknown usage as media */
325 SUPPRESSIBLE_USAGES.put(USAGE_UNKNOWN, SUPPRESSIBLE_MEDIA);
Beverlyd6964762018-02-16 14:07:03 -0500326 SUPPRESSIBLE_USAGES.put(USAGE_ASSISTANCE_SONIFICATION, SUPPRESSIBLE_SYSTEM);
Jean-Michel Trivie743bda2016-09-09 11:56:48 -0700327 }
328
329 /**
330 * @hide
331 * Array of all usage types exposed in the SDK that applications can use.
332 */
333 public final static int[] SDK_USAGES = {
334 USAGE_UNKNOWN,
335 USAGE_MEDIA,
336 USAGE_VOICE_COMMUNICATION,
337 USAGE_VOICE_COMMUNICATION_SIGNALLING,
338 USAGE_ALARM,
339 USAGE_NOTIFICATION,
340 USAGE_NOTIFICATION_RINGTONE,
341 USAGE_NOTIFICATION_COMMUNICATION_REQUEST,
342 USAGE_NOTIFICATION_COMMUNICATION_INSTANT,
343 USAGE_NOTIFICATION_COMMUNICATION_DELAYED,
344 USAGE_NOTIFICATION_EVENT,
345 USAGE_ASSISTANCE_ACCESSIBILITY,
346 USAGE_ASSISTANCE_NAVIGATION_GUIDANCE,
347 USAGE_ASSISTANCE_SONIFICATION,
Jean-Michel Trivi0c8855d02016-12-29 10:33:29 -0800348 USAGE_GAME,
349 USAGE_ASSISTANT,
Jean-Michel Trivie743bda2016-09-09 11:56:48 -0700350 };
351
352 /**
Paul McLeand6f87c82021-03-31 13:02:41 -0600353 * @hide
354 */
355 @TestApi
356 public static int[] getSdkUsages() {
357 return SDK_USAGES;
358 }
359
360 /**
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700361 * Flag defining a behavior where the audibility of the sound will be ensured by the system.
Jean-Michel Trivie8fb9cb2021-06-30 09:13:27 -0700362 * To ensure sound audibility, the system only uses built-in speakers or wired headphones
363 * and specifically excludes wireless audio devices.
364 * <p>Note this flag should only be used for sounds subject to regulatory behaviors in some
365 * countries, such as for camera shutter sound, and not for routing behaviors.
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700366 */
367 public final static int FLAG_AUDIBILITY_ENFORCED = 0x1 << 0;
368 /**
369 * @hide
370 * Flag defining a behavior where the playback of the sound is ensured without
371 * degradation only when going to a secure sink.
372 */
373 // FIXME not guaranteed yet
Jean-Michel Trivi6894cd32014-07-21 16:06:33 -0700374 // TODO add in FLAG_ALL_PUBLIC when supported and in public API
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700375 public final static int FLAG_SECURE = 0x1 << 1;
376 /**
377 * @hide
378 * Flag to enable when the stream is associated with SCO usage.
379 * Internal use only for dealing with legacy STREAM_BLUETOOTH_SCO
380 */
381 public final static int FLAG_SCO = 0x1 << 2;
Jean-Michel Trivi6894cd32014-07-21 16:06:33 -0700382 /**
383 * @hide
384 * Flag defining a behavior where the system ensures that the playback of the sound will
385 * be compatible with its use as a broadcast for surrounding people and/or devices.
386 * Ensures audibility with no or minimal post-processing applied.
387 */
388 @SystemApi
389 public final static int FLAG_BEACON = 0x1 << 3;
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700390
Eric Laurentb634e1b2014-08-01 14:44:46 -0700391 /**
Eric Laurentb634e1b2014-08-01 14:44:46 -0700392 * Flag requesting the use of an output stream supporting hardware A/V synchronization.
393 */
394 public final static int FLAG_HW_AV_SYNC = 0x1 << 4;
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700395
Eric Laurentbdad1af2014-09-19 17:43:29 -0700396 /**
397 * @hide
398 * Flag requesting capture from the source used for hardware hotword detection.
399 * To be used with capture preset MediaRecorder.AudioSource.HOTWORD or
400 * MediaRecorder.AudioSource.VOICE_RECOGNITION.
401 */
402 @SystemApi
403 public final static int FLAG_HW_HOTWORD = 0x1 << 5;
404
John Spurlockbbfd31a2015-02-18 11:58:14 -0500405 /**
406 * @hide
407 * Flag requesting audible playback even under limited interruptions.
408 */
409 @SystemApi
410 public final static int FLAG_BYPASS_INTERRUPTION_POLICY = 0x1 << 6;
411
412 /**
413 * @hide
414 * Flag requesting audible playback even when the underlying stream is muted.
415 */
416 @SystemApi
417 public final static int FLAG_BYPASS_MUTE = 0x1 << 7;
418
Phil Burkdd731422015-12-28 10:34:33 -0800419 /**
Phil Burk2050f6c2016-05-25 15:13:57 -0700420 * Flag requesting a low latency path when creating an AudioTrack.
Phil Burkdd731422015-12-28 10:34:33 -0800421 * When using this flag, the sample rate must match the native sample rate
422 * of the device. Effects processing is also unavailable.
Phil Burk2050f6c2016-05-25 15:13:57 -0700423 *
424 * Note that if this flag is used without specifying a bufferSizeInBytes then the
425 * AudioTrack's actual buffer size may be too small. It is recommended that a fairly
426 * large buffer should be specified when the AudioTrack is created.
427 * Then the actual size can be reduced by calling
428 * {@link AudioTrack#setBufferSizeInFrames(int)}. The buffer size can be optimized
429 * by lowering it after each write() call until the audio glitches, which is detected by calling
430 * {@link AudioTrack#getUnderrunCount()}. Then the buffer size can be increased
431 * until there are no glitches.
432 * This tuning step should be done while playing silence.
433 * This technique provides a compromise between latency and glitch rate.
Andy Hungebc2c142017-01-12 19:20:29 -0800434 *
435 * @deprecated Use {@link AudioTrack.Builder#setPerformanceMode(int)} with
436 * {@link AudioTrack#PERFORMANCE_MODE_LOW_LATENCY} to control performance.
Phil Burkdd731422015-12-28 10:34:33 -0800437 */
438 public final static int FLAG_LOW_LATENCY = 0x1 << 8;
439
Andy Hungebc2c142017-01-12 19:20:29 -0800440 /**
441 * @hide
442 * Flag requesting a deep buffer path when creating an {@code AudioTrack}.
443 *
444 * A deep buffer path, if available, may consume less power and is
445 * suitable for media playback where latency is not a concern.
446 * Use {@link AudioTrack.Builder#setPerformanceMode(int)} with
447 * {@link AudioTrack#PERFORMANCE_MODE_POWER_SAVING} to enable.
448 */
449 public final static int FLAG_DEEP_BUFFER = 0x1 << 9;
450
Kevin Rocard9ce6e562019-02-05 15:45:26 -0800451 /**
452 * @hide
Kevin Rocarda3a4bbb2019-03-07 18:29:48 -0800453 * Flag specifying that the audio shall not be captured by third-party apps
454 * with a MediaProjection.
Kevin Rocard9ce6e562019-02-05 15:45:26 -0800455 */
Kevin Rocarda3a4bbb2019-03-07 18:29:48 -0800456 public static final int FLAG_NO_MEDIA_PROJECTION = 0x1 << 10;
Kevin Rocard9ce6e562019-02-05 15:45:26 -0800457
jiabin41584392019-02-26 12:57:57 -0800458 /**
459 * @hide
460 * Flag indicating force muting haptic channels.
461 */
462 public static final int FLAG_MUTE_HAPTIC = 0x1 << 11;
463
Kevin Rocarda3a4bbb2019-03-07 18:29:48 -0800464 /**
465 * @hide
466 * Flag specifying that the audio shall not be captured by any apps, not even system apps.
467 */
468 public static final int FLAG_NO_SYSTEM_CAPTURE = 0x1 << 12;
469
Eric Laurent597f0b5e2019-10-24 15:57:27 -0700470 /**
471 * @hide
472 * Flag requesting private audio capture. When set in audio attributes passed to an
473 * AudioRecord, this prevents a privileged Assistant from capturing audio while this
474 * AudioRecord is active.
475 */
476 public static final int FLAG_CAPTURE_PRIVATE = 0x1 << 13;
477
Jean-Michel Trivie9dd14e2021-07-12 11:10:18 -0700478 /**
479 * @hide
480 * Flag indicating the audio content has been processed to provide a virtual multichannel
481 * audio experience
482 */
483 public static final int FLAG_CONTENT_SPATIALIZED = 0x1 << 14;
484
485 /**
486 * @hide
487 * Flag indicating the audio content is to never be spatialized
488 */
489 public static final int FLAG_NEVER_SPATIALIZE = 0x1 << 15;
Eric Laurent597f0b5e2019-10-24 15:57:27 -0700490
Eric Laurent78eef3a2021-11-09 16:10:42 +0100491 /**
492 * @hide
493 * Flag indicating the audio is part of a call redirection.
494 * Valid for playback and capture.
495 */
496 public static final int FLAG_CALL_REDIRECTION = 0x1 << 16;
497
jiabin1073ee62019-04-16 17:27:41 -0700498 // Note that even though FLAG_MUTE_HAPTIC is stored as a flag bit, it is not here since
499 // it is known as a boolean value outside of AudioAttributes.
Kevin Rocard506541c2019-04-03 12:35:46 -0700500 private static final int FLAG_ALL = FLAG_AUDIBILITY_ENFORCED | FLAG_SECURE | FLAG_SCO
501 | FLAG_BEACON | FLAG_HW_AV_SYNC | FLAG_HW_HOTWORD | FLAG_BYPASS_INTERRUPTION_POLICY
502 | FLAG_BYPASS_MUTE | FLAG_LOW_LATENCY | FLAG_DEEP_BUFFER | FLAG_NO_MEDIA_PROJECTION
Jean-Michel Trivie9dd14e2021-07-12 11:10:18 -0700503 | FLAG_NO_SYSTEM_CAPTURE | FLAG_CAPTURE_PRIVATE | FLAG_CONTENT_SPATIALIZED
Eric Laurent78eef3a2021-11-09 16:10:42 +0100504 | FLAG_NEVER_SPATIALIZE | FLAG_CALL_REDIRECTION;
Phil Burkdd731422015-12-28 10:34:33 -0800505 private final static int FLAG_ALL_PUBLIC = FLAG_AUDIBILITY_ENFORCED |
506 FLAG_HW_AV_SYNC | FLAG_LOW_LATENCY;
Jean-Michel Trivib097d9e2020-06-25 17:55:39 -0700507 /* mask of flags that can be set by SDK and System APIs through the Builder */
508 private static final int FLAG_ALL_API_SET = FLAG_ALL_PUBLIC
509 | FLAG_BYPASS_INTERRUPTION_POLICY
510 | FLAG_BYPASS_MUTE;
Jean-Michel Trivi6894cd32014-07-21 16:06:33 -0700511
Kevin Rocarda3a4bbb2019-03-07 18:29:48 -0800512 /**
513 * Indicates that the audio may be captured by any app.
514 *
Kevin Rocarde5b29c92019-04-03 12:37:32 -0700515 * For privacy, the following usages cannot be recorded: VOICE_COMMUNICATION*,
Kevin Rocarda3a4bbb2019-03-07 18:29:48 -0800516 * USAGE_NOTIFICATION*, USAGE_ASSISTANCE* and USAGE_ASSISTANT.
517 *
518 * On {@link android.os.Build.VERSION_CODES#Q}, this means only {@link #USAGE_UNKNOWN},
519 * {@link #USAGE_MEDIA} and {@link #USAGE_GAME} may be captured.
520 *
521 * See {@link android.media.projection.MediaProjection} and
522 * {@link Builder#setAllowedCapturePolicy}.
523 */
524 public static final int ALLOW_CAPTURE_BY_ALL = 1;
525 /**
526 * Indicates that the audio may only be captured by system apps.
527 *
Kevin Rocarde5b29c92019-04-03 12:37:32 -0700528 * System apps can capture for many purposes like accessibility, live captions, user guidance...
Kevin Rocarda3a4bbb2019-03-07 18:29:48 -0800529 * but abide to the following restrictions:
Kevin Rocarde5b29c92019-04-03 12:37:32 -0700530 * - the audio cannot leave the device
531 * - the audio cannot be passed to a third party app
532 * - the audio cannot be recorded at a higher quality than 16kHz 16bit mono
Kevin Rocarda3a4bbb2019-03-07 18:29:48 -0800533 *
534 * See {@link Builder#setAllowedCapturePolicy}.
535 */
536 public static final int ALLOW_CAPTURE_BY_SYSTEM = 2;
537 /**
538 * Indicates that the audio is not to be recorded by any app, even if it is a system app.
539 *
540 * It is encouraged to use {@link #ALLOW_CAPTURE_BY_SYSTEM} instead of this value as system apps
541 * provide significant and useful features for the user (such as live captioning
542 * and accessibility).
543 *
544 * See {@link Builder#setAllowedCapturePolicy}.
545 */
546 public static final int ALLOW_CAPTURE_BY_NONE = 3;
547
548 /** @hide */
549 @IntDef({
550 ALLOW_CAPTURE_BY_ALL,
551 ALLOW_CAPTURE_BY_SYSTEM,
552 ALLOW_CAPTURE_BY_NONE,
553 })
554 @Retention(RetentionPolicy.SOURCE)
555 public @interface CapturePolicy {}
556
Mathew Inwood8e742f92020-10-27 11:47:29 +0000557 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700558 private int mUsage = USAGE_UNKNOWN;
Mathew Inwood8c854f82018-09-14 12:35:36 +0100559 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700560 private int mContentType = CONTENT_TYPE_UNKNOWN;
Mathew Inwood8c854f82018-09-14 12:35:36 +0100561 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Jean-Michel Trivi701d6ff2014-07-16 07:51:22 -0700562 private int mSource = MediaRecorder.AudioSource.AUDIO_SOURCE_INVALID;
Mathew Inwood8c854f82018-09-14 12:35:36 +0100563 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700564 private int mFlags = 0x0;
565 private HashSet<String> mTags;
Mathew Inwood8e742f92020-10-27 11:47:29 +0000566 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
Jean-Michel Trivia1d80e32014-06-18 08:18:41 -0700567 private String mFormattedTags;
Jean-Michel Trivif82f7462016-02-05 15:20:35 -0800568 private Bundle mBundle; // lazy-initialized, may be null
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700569
570 private AudioAttributes() {
571 }
572
573 /**
574 * Return the content type.
575 * @return one of the values that can be set in {@link Builder#setContentType(int)}
576 */
577 public int getContentType() {
578 return mContentType;
579 }
580
581 /**
582 * Return the usage.
583 * @return one of the values that can be set in {@link Builder#setUsage(int)}
584 */
585 public int getUsage() {
Hayden Gomesfe2c8772019-12-23 11:37:23 -0800586 if (isSystemUsage(mUsage)) {
587 return USAGE_UNKNOWN;
588 }
589 return mUsage;
590 }
591
592 /**
593 * @hide
594 * Return the system usage.
595 * @return one of the values that can be set in {@link Builder#setUsage(int)} or
596 * {@link Builder#setSystemUsage(int)}
597 */
598 @SystemApi
599 public int getSystemUsage() {
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700600 return mUsage;
601 }
602
603 /**
Jean-Michel Trivi701d6ff2014-07-16 07:51:22 -0700604 * @hide
Jean-Michel Trivi701d6ff2014-07-16 07:51:22 -0700605 * Return the capture preset.
606 * @return one of the values that can be set in {@link Builder#setCapturePreset(int)} or a
607 * negative value if none has been set.
608 */
Jean-Michel Trivi1b3541d2014-11-25 12:53:41 -0800609 @SystemApi
Jean-Michel Trivi701d6ff2014-07-16 07:51:22 -0700610 public int getCapturePreset() {
611 return mSource;
612 }
613
614 /**
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700615 * Return the flags.
616 * @return a combined mask of all flags
617 */
618 public int getFlags() {
619 // only return the flags that are public
Jean-Michel Trivi6894cd32014-07-21 16:06:33 -0700620 return (mFlags & (FLAG_ALL_PUBLIC));
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700621 }
622
623 /**
624 * @hide
625 * Return all the flags, even the non-public ones.
626 * Internal use only
627 * @return a combined mask of all flags
628 */
Eric Laurent00a00922015-03-09 09:25:45 -0700629 @SystemApi
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700630 public int getAllFlags() {
Jean-Michel Trivi6894cd32014-07-21 16:06:33 -0700631 return (mFlags & FLAG_ALL);
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700632 }
633
634 /**
Jean-Michel Trivib45c2732014-06-03 16:06:48 -0700635 * @hide
Jean-Michel Trivif82f7462016-02-05 15:20:35 -0800636 * Return the Bundle of data.
637 * @return a copy of the Bundle for this instance, may be null.
638 */
639 @SystemApi
640 public Bundle getBundle() {
641 if (mBundle == null) {
642 return mBundle;
643 } else {
644 return new Bundle(mBundle);
645 }
646 }
647
648 /**
649 * @hide
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700650 * Return the set of tags.
651 * @return a read-only set of all tags stored as strings.
652 */
653 public Set<String> getTags() {
654 return Collections.unmodifiableSet(mTags);
655 }
656
657 /**
jiabin41584392019-02-26 12:57:57 -0800658 * Return if haptic channels are muted.
659 * @return {@code true} if haptic channels are muted, {@code false} otherwise.
660 */
661 public boolean areHapticChannelsMuted() {
662 return (mFlags & FLAG_MUTE_HAPTIC) != 0;
663 }
664
665 /**
Jean-Michel Trivie9dd14e2021-07-12 11:10:18 -0700666 * Return true if the audio content associated with these attributes has already been
667 * spatialized, that is it has already been processed to offer a binaural or transaural
668 * immersive audio experience.
669 * @return {@code true} if the content has been processed
670 */
671 public boolean isContentSpatialized() {
672 return (mFlags & FLAG_CONTENT_SPATIALIZED) != 0;
673 }
674
675 /** @hide */
676 @IntDef(flag = false, value = {
677 SPATIALIZATION_BEHAVIOR_AUTO,
678 SPATIALIZATION_BEHAVIOR_NEVER,
679 })
680 @Retention(RetentionPolicy.SOURCE)
681 public @interface SpatializationBehavior {};
682
683 /**
684 * Constant indicating the audio content associated with these attributes will follow the
685 * default platform behavior with regards to which content will be spatialized or not.
686 * @see #getSpatializationBehavior()
687 * @see Spatializer
688 */
689 public static final int SPATIALIZATION_BEHAVIOR_AUTO = 0;
690
691 /**
692 * Constant indicating the audio content associated with these attributes should never
693 * be virtualized.
694 * @see #getSpatializationBehavior()
695 * @see Spatializer
696 */
697 public static final int SPATIALIZATION_BEHAVIOR_NEVER = 1;
698
699 /**
700 * Return the behavior affecting whether spatialization will be used.
701 * @return the spatialization behavior
702 */
703 public @SpatializationBehavior int getSpatializationBehavior() {
704 return ((mFlags & FLAG_NEVER_SPATIALIZE) != 0)
705 ? SPATIALIZATION_BEHAVIOR_NEVER : SPATIALIZATION_BEHAVIOR_AUTO;
706 }
707
708 /**
Kevin Rocard9bf75fa2019-04-09 16:25:26 -0700709 * Return the capture policy.
710 * @return the capture policy set by {@link Builder#setAllowedCapturePolicy(int)} or
711 * the default if it was not called.
712 */
713 @CapturePolicy
714 public int getAllowedCapturePolicy() {
715 if ((mFlags & FLAG_NO_SYSTEM_CAPTURE) == FLAG_NO_SYSTEM_CAPTURE) {
716 return ALLOW_CAPTURE_BY_NONE;
717 }
718 if ((mFlags & FLAG_NO_MEDIA_PROJECTION) == FLAG_NO_MEDIA_PROJECTION) {
719 return ALLOW_CAPTURE_BY_SYSTEM;
720 }
721 return ALLOW_CAPTURE_BY_ALL;
722 }
723
Eric Laurent78eef3a2021-11-09 16:10:42 +0100724 /**
725 * @hide
726 * Indicates if the audio is used for call redirection
727 * @return true if used for call redirection, false otherwise.
728 */
729 public boolean isForCallRedirection() {
730 return (mFlags & FLAG_CALL_REDIRECTION) == FLAG_CALL_REDIRECTION;
731 }
Kevin Rocard9bf75fa2019-04-09 16:25:26 -0700732
733 /**
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700734 * Builder class for {@link AudioAttributes} objects.
Jean-Michel Trivi04f55a492014-09-12 10:07:05 -0700735 * <p> Here is an example where <code>Builder</code> is used to define the
736 * {@link AudioAttributes} to be used by a new <code>AudioTrack</code> instance:
737 *
738 * <pre class="prettyprint">
739 * AudioTrack myTrack = new AudioTrack(
740 * new AudioAttributes.Builder()
741 * .setUsage(AudioAttributes.USAGE_MEDIA)
742 * .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
743 * .build(),
744 * myFormat, myBuffSize, AudioTrack.MODE_STREAM, mySession);
745 * </pre>
746 *
747 * <p>By default all types of information (usage, content type, flags) conveyed by an
748 * <code>AudioAttributes</code> instance are set to "unknown". Unknown information will be
749 * interpreted as a default value that is dependent on the context of use, for instance a
750 * {@link MediaPlayer} will use a default usage of {@link AudioAttributes#USAGE_MEDIA}.
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700751 */
752 public static class Builder {
Hayden Gomesfe2c8772019-12-23 11:37:23 -0800753 private int mUsage = USAGE_INVALID;
754 private int mSystemUsage = USAGE_INVALID;
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700755 private int mContentType = CONTENT_TYPE_UNKNOWN;
Jean-Michel Trivi701d6ff2014-07-16 07:51:22 -0700756 private int mSource = MediaRecorder.AudioSource.AUDIO_SOURCE_INVALID;
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700757 private int mFlags = 0x0;
Eric Laurentc9d353d2019-04-03 16:16:14 -0700758 private boolean mMuteHapticChannels = true;
Jean-Michel Trivie9dd14e2021-07-12 11:10:18 -0700759 private boolean mIsContentSpatialized = false;
760 private int mSpatializationBehavior = SPATIALIZATION_BEHAVIOR_AUTO;
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700761 private HashSet<String> mTags = new HashSet<String>();
Jean-Michel Trivif82f7462016-02-05 15:20:35 -0800762 private Bundle mBundle;
Eric Laurent64ed2ec2020-01-13 16:29:16 -0800763 private int mPrivacySensitive = PRIVACY_SENSITIVE_DEFAULT;
764
765 private static final int PRIVACY_SENSITIVE_DEFAULT = -1;
766 private static final int PRIVACY_SENSITIVE_DISABLED = 0;
767 private static final int PRIVACY_SENSITIVE_ENABLED = 1;
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700768
769 /**
770 * Constructs a new Builder with the defaults.
Jean-Michel Trivi04f55a492014-09-12 10:07:05 -0700771 * By default, usage and content type are respectively {@link AudioAttributes#USAGE_UNKNOWN}
772 * and {@link AudioAttributes#CONTENT_TYPE_UNKNOWN}, and flags are 0. It is recommended to
773 * configure the usage (with {@link #setUsage(int)}) or deriving attributes from a legacy
774 * stream type (with {@link #setLegacyStreamType(int)}) before calling {@link #build()}
775 * to override any default playback behavior in terms of routing and volume management.
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700776 */
777 public Builder() {
778 }
779
780 /**
781 * Constructs a new Builder from a given AudioAttributes
782 * @param aa the AudioAttributes object whose data will be reused in the new Builder.
783 */
784 @SuppressWarnings("unchecked") // for cloning of mTags
785 public Builder(AudioAttributes aa) {
786 mUsage = aa.mUsage;
787 mContentType = aa.mContentType;
Eric Laurent78eef3a2021-11-09 16:10:42 +0100788 mSource = aa.mSource;
jiabin1073ee62019-04-16 17:27:41 -0700789 mFlags = aa.getAllFlags();
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700790 mTags = (HashSet<String>) aa.mTags.clone();
jiabin1073ee62019-04-16 17:27:41 -0700791 mMuteHapticChannels = aa.areHapticChannelsMuted();
Jean-Michel Trivie9dd14e2021-07-12 11:10:18 -0700792 mIsContentSpatialized = aa.isContentSpatialized();
793 mSpatializationBehavior = aa.getSpatializationBehavior();
Eric Laurent78eef3a2021-11-09 16:10:42 +0100794 if ((mFlags & FLAG_CAPTURE_PRIVATE) != 0) {
795 mPrivacySensitive = PRIVACY_SENSITIVE_ENABLED;
796 }
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700797 }
798
799 /**
800 * Combines all of the attributes that have been set and return a new
801 * {@link AudioAttributes} object.
802 * @return a new {@link AudioAttributes} object
803 */
804 @SuppressWarnings("unchecked") // for cloning of mTags
805 public AudioAttributes build() {
806 AudioAttributes aa = new AudioAttributes();
807 aa.mContentType = mContentType;
Hayden Gomesfe2c8772019-12-23 11:37:23 -0800808
809 if (mUsage == USAGE_INVALID) {
810 if (mSystemUsage == USAGE_INVALID) {
811 aa.mUsage = USAGE_UNKNOWN;
812 } else {
813 aa.mUsage = mSystemUsage;
814 }
815 } else {
816 if (mSystemUsage == USAGE_INVALID) {
817 aa.mUsage = mUsage;
818 } else {
819 throw new IllegalArgumentException(
820 "Cannot set both usage and system usage on same builder");
821 }
822 }
823
Jean-Michel Trivide334852021-08-30 10:47:03 -0700824 // handle deprecation of notification usages by remapping to USAGE_NOTIFICATION
825 switch (aa.mUsage) {
826 case USAGE_NOTIFICATION_COMMUNICATION_REQUEST:
827 case USAGE_NOTIFICATION_COMMUNICATION_INSTANT:
828 case USAGE_NOTIFICATION_COMMUNICATION_DELAYED:
829 aa.mUsage = USAGE_NOTIFICATION;
830 break;
831 default:
832 break;
833 }
834
Jean-Michel Trivi701d6ff2014-07-16 07:51:22 -0700835 aa.mSource = mSource;
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700836 aa.mFlags = mFlags;
jiabin41584392019-02-26 12:57:57 -0800837 if (mMuteHapticChannels) {
838 aa.mFlags |= FLAG_MUTE_HAPTIC;
839 }
Jean-Michel Trivie9dd14e2021-07-12 11:10:18 -0700840 if (mIsContentSpatialized) {
841 aa.mFlags |= FLAG_CONTENT_SPATIALIZED;
842 }
843 if (mSpatializationBehavior == SPATIALIZATION_BEHAVIOR_NEVER) {
844 aa.mFlags |= FLAG_NEVER_SPATIALIZE;
845 }
Eric Laurent64ed2ec2020-01-13 16:29:16 -0800846
847 if (mPrivacySensitive == PRIVACY_SENSITIVE_DEFAULT) {
848 // capturing for camcorder or communication is private by default to
849 // reflect legacy behavior
850 if (mSource == MediaRecorder.AudioSource.VOICE_COMMUNICATION
851 || mSource == MediaRecorder.AudioSource.CAMCORDER) {
852 aa.mFlags |= FLAG_CAPTURE_PRIVATE;
853 } else {
854 aa.mFlags &= ~FLAG_CAPTURE_PRIVATE;
855 }
856 } else if (mPrivacySensitive == PRIVACY_SENSITIVE_ENABLED) {
Eric Laurent597f0b5e2019-10-24 15:57:27 -0700857 aa.mFlags |= FLAG_CAPTURE_PRIVATE;
Eric Laurent64ed2ec2020-01-13 16:29:16 -0800858 } else {
859 aa.mFlags &= ~FLAG_CAPTURE_PRIVATE;
Eric Laurent597f0b5e2019-10-24 15:57:27 -0700860 }
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700861 aa.mTags = (HashSet<String>) mTags.clone();
Jean-Michel Trivicc58c762014-07-30 16:03:41 -0700862 aa.mFormattedTags = TextUtils.join(";", mTags);
Jean-Michel Trivif82f7462016-02-05 15:20:35 -0800863 if (mBundle != null) {
864 aa.mBundle = new Bundle(mBundle);
865 }
Bhalchandra Gajarec86c4ca2021-01-24 07:21:59 -0800866
867 // Allow the FLAG_HW_HOTWORD only for AudioSource.VOICE_RECOGNITION
868 if (mSource != MediaRecorder.AudioSource.VOICE_RECOGNITION
869 && (mFlags & FLAG_HW_HOTWORD) == FLAG_HW_HOTWORD) {
870 aa.mFlags &= ~FLAG_HW_HOTWORD;
871 }
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700872 return aa;
873 }
874
875 /**
Hayden Gomes62812aa2019-12-23 11:40:27 -0800876 * Sets the attribute describing what is the intended use of the audio signal,
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700877 * such as alarm or ringtone.
Hayden Gomesfe2c8772019-12-23 11:37:23 -0800878 * @param usage one of {@link AttributeSdkUsage#USAGE_UNKNOWN},
879 * {@link AttributeSdkUsage#USAGE_MEDIA},
880 * {@link AttributeSdkUsage#USAGE_VOICE_COMMUNICATION},
881 * {@link AttributeSdkUsage#USAGE_VOICE_COMMUNICATION_SIGNALLING},
882 * {@link AttributeSdkUsage#USAGE_ALARM}, {@link AudioAttributes#USAGE_NOTIFICATION},
883 * {@link AttributeSdkUsage#USAGE_NOTIFICATION_RINGTONE},
Hayden Gomesfe2c8772019-12-23 11:37:23 -0800884 * {@link AttributeSdkUsage#USAGE_NOTIFICATION_EVENT},
885 * {@link AttributeSdkUsage#USAGE_ASSISTANT},
886 * {@link AttributeSdkUsage#USAGE_ASSISTANCE_ACCESSIBILITY},
887 * {@link AttributeSdkUsage#USAGE_ASSISTANCE_NAVIGATION_GUIDANCE},
888 * {@link AttributeSdkUsage#USAGE_ASSISTANCE_SONIFICATION},
889 * {@link AttributeSdkUsage#USAGE_GAME}.
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700890 * @return the same Builder instance.
891 */
Hayden Gomesfe2c8772019-12-23 11:37:23 -0800892 public Builder setUsage(@AttributeSdkUsage int usage) {
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700893 switch (usage) {
894 case USAGE_UNKNOWN:
895 case USAGE_MEDIA:
896 case USAGE_VOICE_COMMUNICATION:
897 case USAGE_VOICE_COMMUNICATION_SIGNALLING:
898 case USAGE_ALARM:
899 case USAGE_NOTIFICATION:
Jean-Michel Trivi89c3b292014-07-20 11:41:02 -0700900 case USAGE_NOTIFICATION_RINGTONE:
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700901 case USAGE_NOTIFICATION_COMMUNICATION_REQUEST:
902 case USAGE_NOTIFICATION_COMMUNICATION_INSTANT:
903 case USAGE_NOTIFICATION_COMMUNICATION_DELAYED:
904 case USAGE_NOTIFICATION_EVENT:
905 case USAGE_ASSISTANCE_ACCESSIBILITY:
906 case USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:
907 case USAGE_ASSISTANCE_SONIFICATION:
908 case USAGE_GAME:
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -0700909 case USAGE_VIRTUAL_SOURCE:
Jean-Michel Trivi0c8855d02016-12-29 10:33:29 -0800910 case USAGE_ASSISTANT:
Kevin Rocarda3a4bbb2019-03-07 18:29:48 -0800911 mUsage = usage;
912 break;
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700913 default:
Jean-Michel Trivid8aaf452019-10-16 15:09:37 -0700914 throw new IllegalArgumentException("Invalid usage " + usage);
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700915 }
916 return this;
917 }
918
919 /**
Hayden Gomesfe2c8772019-12-23 11:37:23 -0800920 * @hide
921 * Sets the attribute describing what is the intended use of the audio signal for categories
922 * of sounds restricted to the system, such as vehicle status or emergency.
923 *
924 * <p>Note that the AudioAttributes have a single usage value, therefore it is illegal to
925 * call both this method and {@link #setUsage(int)}.
926 * @param systemUsage the system-restricted usage.
927 * @return the same Builder instance.
928 */
929 @SystemApi
930 @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
931 public @NonNull Builder setSystemUsage(@AttributeSystemUsage int systemUsage) {
932 if (isSystemUsage(systemUsage)) {
933 mSystemUsage = systemUsage;
934 } else {
935 throw new IllegalArgumentException("Invalid system usage " + systemUsage);
936 }
937
938 return this;
939 }
940
941 /**
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700942 * Sets the attribute describing the content type of the audio signal, such as speech,
943 * or music.
944 * @param contentType the content type values, one of
945 * {@link AudioAttributes#CONTENT_TYPE_MOVIE},
946 * {@link AudioAttributes#CONTENT_TYPE_MUSIC},
947 * {@link AudioAttributes#CONTENT_TYPE_SONIFICATION},
948 * {@link AudioAttributes#CONTENT_TYPE_SPEECH},
949 * {@link AudioAttributes#CONTENT_TYPE_UNKNOWN}.
950 * @return the same Builder instance.
951 */
952 public Builder setContentType(@AttributeContentType int contentType) {
953 switch (contentType) {
954 case CONTENT_TYPE_UNKNOWN:
955 case CONTENT_TYPE_MOVIE:
956 case CONTENT_TYPE_MUSIC:
957 case CONTENT_TYPE_SONIFICATION:
958 case CONTENT_TYPE_SPEECH:
Sungsoo Lim00d0bb32018-11-22 13:50:31 +0900959 mContentType = contentType;
960 break;
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700961 default:
Jean-Michel Trivid8aaf452019-10-16 15:09:37 -0700962 throw new IllegalArgumentException("Invalid content type " + contentType);
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700963 }
964 return this;
965 }
966
967 /**
Carter Hsu02677712021-10-20 16:12:53 +0800968 * @hide
969 * Sets the attribute describing the content type of the audio signal, such as speech,
970 * , music or ultrasound.
971 * @param contentType the content type values.
972 * @return the same Builder instance.
973 */
974 @SystemApi
975 public @NonNull Builder setInternalContentType(@AttrInternalContentType int contentType) {
976 switch (contentType) {
977 case CONTENT_TYPE_ULTRASOUND:
978 mContentType = contentType;
979 break;
980 default:
981 setContentType(contentType);
982 break;
983 }
984 return this;
985 }
986
987 /**
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700988 * Sets the combination of flags.
Andy Hungebc2c142017-01-12 19:20:29 -0800989 *
990 * This is a bitwise OR with the existing flags.
Jean-Michel Trivi26d2fdb2016-01-14 12:59:39 -0800991 * @param flags a combination of {@link AudioAttributes#FLAG_AUDIBILITY_ENFORCED},
992 * {@link AudioAttributes#FLAG_HW_AV_SYNC}.
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700993 * @return the same Builder instance.
994 */
995 public Builder setFlags(int flags) {
Jean-Michel Trivib097d9e2020-06-25 17:55:39 -0700996 flags &= AudioAttributes.FLAG_ALL_API_SET;
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700997 mFlags |= flags;
998 return this;
999 }
1000
1001 /**
Bhalchandra Gajarec86c4ca2021-01-24 07:21:59 -08001002 * @hide
1003 * Request for capture in hotword mode.
1004 *
1005 * Requests an audio path optimized for Hotword detection use cases from
1006 * the low power audio DSP. This is valid only for capture with
1007 * audio source {@link MediaRecorder.AudioSource#VOICE_RECOGNITION}.
1008 * There is no guarantee that this mode is available on the device.
1009 * @return the same Builder instance.
1010 */
1011 @SystemApi
1012 @RequiresPermission(android.Manifest.permission.CAPTURE_AUDIO_HOTWORD)
Bhalchandra Gajareab5fedc2021-03-29 13:01:25 -07001013 public @NonNull Builder setHotwordModeEnabled(boolean enable) {
1014 if (enable) {
1015 mFlags |= FLAG_HW_HOTWORD;
1016 } else {
1017 mFlags &= ~FLAG_HW_HOTWORD;
1018 }
Bhalchandra Gajarec86c4ca2021-01-24 07:21:59 -08001019 return this;
1020 }
1021
1022 /**
Kevin Rocarddb0ff412019-05-02 17:55:35 -07001023 * Specifies whether the audio may or may not be captured by other apps or the system.
Kevin Rocarda3a4bbb2019-03-07 18:29:48 -08001024 *
1025 * The default is {@link AudioAttributes#ALLOW_CAPTURE_BY_ALL}.
1026 *
Kevin Rocard654b3cb2019-04-03 16:51:11 -07001027 * There are multiple ways to set this policy:
Kevin Rocarddb0ff412019-05-02 17:55:35 -07001028 * <ul>
1029 * <li> for each track independently, with this method </li>
1030 * <li> application-wide at runtime, with
1031 * {@link AudioManager#setAllowedCapturePolicy(int)} </li>
1032 * <li> application-wide at build time, see {@code allowAudioPlaybackCapture} in the
1033 * application manifest. </li>
1034 * </ul>
Kevin Rocard654b3cb2019-04-03 16:51:11 -07001035 * The most restrictive policy is always applied.
1036 *
Kevin Rocarddb0ff412019-05-02 17:55:35 -07001037 * See {@link AudioPlaybackCaptureConfiguration} for more details on
Kevin Rocard654b3cb2019-04-03 16:51:11 -07001038 * which audio signals can be captured.
Kevin Rocarda3a4bbb2019-03-07 18:29:48 -08001039 *
Kevin Rocard9ce6e562019-02-05 15:45:26 -08001040 * @return the same Builder instance
Kevin Rocarda3a4bbb2019-03-07 18:29:48 -08001041 * @throws IllegalArgumentException if the argument is not a valid value.
Kevin Rocard9ce6e562019-02-05 15:45:26 -08001042 */
Kevin Rocarda3a4bbb2019-03-07 18:29:48 -08001043 public @NonNull Builder setAllowedCapturePolicy(@CapturePolicy int capturePolicy) {
Kevin Rocard7919c2a2019-03-21 10:28:01 -07001044 mFlags = capturePolicyToFlags(capturePolicy, mFlags);
Kevin Rocard9ce6e562019-02-05 15:45:26 -08001045 return this;
1046 }
1047
1048 /**
Jean-Michel Trivie9dd14e2021-07-12 11:10:18 -07001049 * Specifies whether the content has already been processed for spatialization.
1050 * If it has, setting this to true will prevent issues such as double-processing.
1051 * @param isSpatialized
1052 * @return the same Builder instance
1053 */
1054 public @NonNull Builder setIsContentSpatialized(boolean isSpatialized) {
1055 mIsContentSpatialized = isSpatialized;
1056 return this;
1057 }
1058
1059 /**
1060 * Sets the behavior affecting whether spatialization will be used.
1061 * @param sb the spatialization behavior
1062 * @return the same Builder instance
1063 *
1064 */
1065 public @NonNull Builder setSpatializationBehavior(@SpatializationBehavior int sb) {
1066 switch (sb) {
1067 case SPATIALIZATION_BEHAVIOR_NEVER:
1068 case SPATIALIZATION_BEHAVIOR_AUTO:
1069 break;
1070 default:
1071 throw new IllegalArgumentException("Invalid spatialization behavior " + sb);
1072 }
1073 mSpatializationBehavior = sb;
1074 return this;
1075 }
1076
1077 /**
Jean-Michel Trivib45c2732014-06-03 16:06:48 -07001078 * @hide
Andy Hungebc2c142017-01-12 19:20:29 -08001079 * Replaces flags.
1080 * @param flags any combination of {@link AudioAttributes#FLAG_ALL}.
1081 * @return the same Builder instance.
1082 */
1083 public Builder replaceFlags(int flags) {
1084 mFlags = flags & AudioAttributes.FLAG_ALL;
1085 return this;
1086 }
1087
1088 /**
1089 * @hide
Jean-Michel Trivif82f7462016-02-05 15:20:35 -08001090 * Adds a Bundle of data
1091 * @param bundle a non-null Bundle
1092 * @return the same builder instance
1093 */
1094 @SystemApi
1095 public Builder addBundle(@NonNull Bundle bundle) {
1096 if (bundle == null) {
1097 throw new IllegalArgumentException("Illegal null bundle");
1098 }
1099 if (mBundle == null) {
1100 mBundle = new Bundle(bundle);
1101 } else {
1102 mBundle.putAll(bundle);
1103 }
1104 return this;
1105 }
1106
1107 /**
1108 * @hide
Jean-Michel Trivid60e8752014-04-18 09:47:08 -07001109 * Add a custom tag stored as a string
1110 * @param tag
1111 * @return the same Builder instance.
1112 */
Mathew Inwood473b9d52018-08-17 09:07:01 +01001113 @UnsupportedAppUsage
Jean-Michel Trivid60e8752014-04-18 09:47:08 -07001114 public Builder addTag(String tag) {
1115 mTags.add(tag);
1116 return this;
1117 }
1118
1119 /**
Eric Laurent78eef3a2021-11-09 16:10:42 +01001120 * @hide
1121 * Replace all custom tags
1122 * @param tags
1123 * @return the same Builder instance.
1124 */
1125 public Builder replaceTags(HashSet<String> tags) {
1126 mTags = (HashSet<String>) tags.clone();
1127 return this;
1128 }
1129
1130 /**
Jean-Michel Trivi04f55a492014-09-12 10:07:05 -07001131 * Sets attributes as inferred from the legacy stream types.
Jean-Michel Trivi9f70d4e2019-04-23 16:49:50 -07001132 * Warning: do not use this method in combination with setting any other attributes such as
1133 * usage, content type, flags or haptic control, as this method will overwrite (the more
1134 * accurate) information describing the use case previously set in the <code>Builder</code>.
1135 * In general, avoid using it and prefer setting usage and content type directly
1136 * with {@link #setUsage(int)} and {@link #setContentType(int)}.
1137 * <p>Use this method when building an {@link AudioAttributes} instance to initialize some
1138 * of the attributes by information derived from a legacy stream type.
Jean-Michel Trivid60e8752014-04-18 09:47:08 -07001139 * @param streamType one of {@link AudioManager#STREAM_VOICE_CALL},
1140 * {@link AudioManager#STREAM_SYSTEM}, {@link AudioManager#STREAM_RING},
1141 * {@link AudioManager#STREAM_MUSIC}, {@link AudioManager#STREAM_ALARM},
1142 * or {@link AudioManager#STREAM_NOTIFICATION}.
1143 * @return the same Builder instance.
1144 */
1145 public Builder setLegacyStreamType(int streamType) {
Jean-Michel Trivi3f0945a2016-11-11 10:05:18 -08001146 if (streamType == AudioManager.STREAM_ACCESSIBILITY) {
1147 throw new IllegalArgumentException("STREAM_ACCESSIBILITY is not a legacy stream "
1148 + "type that was used for audio playback");
1149 }
Jean-Michel Trivi9f70d4e2019-04-23 16:49:50 -07001150 setInternalLegacyStreamType(streamType);
1151 return this;
Jean-Michel Trivid60e8752014-04-18 09:47:08 -07001152 }
1153
1154 /**
1155 * @hide
1156 * For internal framework use only, enables building from hidden stream types.
1157 * @param streamType
1158 * @return the same Builder instance.
1159 */
Mathew Inwood473b9d52018-08-17 09:07:01 +01001160 @UnsupportedAppUsage
Jean-Michel Trivid60e8752014-04-18 09:47:08 -07001161 public Builder setInternalLegacyStreamType(int streamType) {
Eric Laurente6c89722019-05-01 14:24:40 -07001162 mContentType = CONTENT_TYPE_UNKNOWN;
1163 mUsage = USAGE_UNKNOWN;
Hayden Gomes6d69bde2019-04-04 13:10:13 -07001164 if (AudioProductStrategy.getAudioProductStrategies().size() > 0) {
1165 AudioAttributes attributes =
1166 AudioProductStrategy.getAudioAttributesForStrategyWithLegacyStreamType(
1167 streamType);
François Gaffiee6d280d2018-03-21 16:08:33 +01001168 if (attributes != null) {
Jean-Michel Trivi9f70d4e2019-04-23 16:49:50 -07001169 mUsage = attributes.mUsage;
1170 mContentType = attributes.mContentType;
jiabina9b4f092019-08-01 15:41:20 -07001171 mFlags = attributes.getAllFlags();
Jean-Michel Trivi9f70d4e2019-04-23 16:49:50 -07001172 mMuteHapticChannels = attributes.areHapticChannelsMuted();
Jean-Michel Trivie9dd14e2021-07-12 11:10:18 -07001173 mIsContentSpatialized = attributes.isContentSpatialized();
1174 mSpatializationBehavior = attributes.getSpatializationBehavior();
Jean-Michel Trivi9f70d4e2019-04-23 16:49:50 -07001175 mTags = attributes.mTags;
1176 mBundle = attributes.mBundle;
1177 mSource = attributes.mSource;
François Gaffiee6d280d2018-03-21 16:08:33 +01001178 }
1179 }
Eric Laurente6c89722019-05-01 14:24:40 -07001180 if (mContentType == CONTENT_TYPE_UNKNOWN) {
1181 switch (streamType) {
1182 case AudioSystem.STREAM_VOICE_CALL:
1183 mContentType = CONTENT_TYPE_SPEECH;
1184 break;
1185 case AudioSystem.STREAM_SYSTEM_ENFORCED:
1186 mFlags |= FLAG_AUDIBILITY_ENFORCED;
1187 // intended fall through, attributes in common with STREAM_SYSTEM
1188 case AudioSystem.STREAM_SYSTEM:
1189 mContentType = CONTENT_TYPE_SONIFICATION;
1190 break;
1191 case AudioSystem.STREAM_RING:
1192 mContentType = CONTENT_TYPE_SONIFICATION;
1193 break;
1194 case AudioSystem.STREAM_MUSIC:
1195 mContentType = CONTENT_TYPE_MUSIC;
1196 break;
1197 case AudioSystem.STREAM_ALARM:
1198 mContentType = CONTENT_TYPE_SONIFICATION;
1199 break;
1200 case AudioSystem.STREAM_NOTIFICATION:
1201 mContentType = CONTENT_TYPE_SONIFICATION;
1202 break;
1203 case AudioSystem.STREAM_BLUETOOTH_SCO:
1204 mContentType = CONTENT_TYPE_SPEECH;
1205 mFlags |= FLAG_SCO;
1206 break;
1207 case AudioSystem.STREAM_DTMF:
1208 mContentType = CONTENT_TYPE_SONIFICATION;
1209 break;
1210 case AudioSystem.STREAM_TTS:
1211 mContentType = CONTENT_TYPE_SONIFICATION;
1212 mFlags |= FLAG_BEACON;
1213 break;
1214 case AudioSystem.STREAM_ACCESSIBILITY:
1215 mContentType = CONTENT_TYPE_SPEECH;
1216 break;
Eric Laurent9b57d572021-11-29 15:20:32 +01001217 case AudioSystem.STREAM_ASSISTANT:
1218 mContentType = CONTENT_TYPE_SPEECH;
1219 break;
Eric Laurente6c89722019-05-01 14:24:40 -07001220 default:
1221 Log.e(TAG, "Invalid stream type " + streamType + " for AudioAttributes");
1222 }
Jean-Michel Trivid60e8752014-04-18 09:47:08 -07001223 }
Eric Laurente6c89722019-05-01 14:24:40 -07001224 if (mUsage == USAGE_UNKNOWN) {
1225 mUsage = usageForStreamType(streamType);
1226 }
Jean-Michel Trivi701d6ff2014-07-16 07:51:22 -07001227 return this;
1228 }
1229
1230 /**
1231 * @hide
Jean-Michel Trivi701d6ff2014-07-16 07:51:22 -07001232 * Sets the capture preset.
1233 * Use this audio attributes configuration method when building an {@link AudioRecord}
1234 * instance with {@link AudioRecord#AudioRecord(AudioAttributes, AudioFormat, int)}.
1235 * @param preset one of {@link MediaRecorder.AudioSource#DEFAULT},
1236 * {@link MediaRecorder.AudioSource#MIC}, {@link MediaRecorder.AudioSource#CAMCORDER},
ragoa7cc59c2015-12-02 11:31:15 -08001237 * {@link MediaRecorder.AudioSource#VOICE_RECOGNITION},
Eric Laurent0016c5b2019-01-15 18:38:32 -08001238 * {@link MediaRecorder.AudioSource#VOICE_COMMUNICATION},
1239 * {@link MediaRecorder.AudioSource#UNPROCESSED} or
1240 * {@link MediaRecorder.AudioSource#VOICE_PERFORMANCE}
Jean-Michel Trivi701d6ff2014-07-16 07:51:22 -07001241 * @return the same Builder instance.
1242 */
Jean-Michel Trivi1b3541d2014-11-25 12:53:41 -08001243 @SystemApi
Jean-Michel Trivi701d6ff2014-07-16 07:51:22 -07001244 public Builder setCapturePreset(int preset) {
1245 switch (preset) {
1246 case MediaRecorder.AudioSource.DEFAULT:
1247 case MediaRecorder.AudioSource.MIC:
1248 case MediaRecorder.AudioSource.CAMCORDER:
1249 case MediaRecorder.AudioSource.VOICE_RECOGNITION:
1250 case MediaRecorder.AudioSource.VOICE_COMMUNICATION:
ragoa7cc59c2015-12-02 11:31:15 -08001251 case MediaRecorder.AudioSource.UNPROCESSED:
Eric Laurent0016c5b2019-01-15 18:38:32 -08001252 case MediaRecorder.AudioSource.VOICE_PERFORMANCE:
Jean-Michel Trivi701d6ff2014-07-16 07:51:22 -07001253 mSource = preset;
1254 break;
1255 default:
1256 Log.e(TAG, "Invalid capture preset " + preset + " for AudioAttributes");
1257 }
1258 return this;
1259 }
1260
1261 /**
1262 * @hide
Benson Huangce4483c2014-09-17 17:21:02 +08001263 * Same as {@link #setCapturePreset(int)} but authorizes the use of HOTWORD,
Carter Hsu02677712021-10-20 16:12:53 +08001264 * REMOTE_SUBMIX, RADIO_TUNER, VOICE_DOWNLINK, VOICE_UPLINK, VOICE_CALL, ECHO_REFERENCE
1265 * and ULTRASOUND
Jean-Michel Trivi701d6ff2014-07-16 07:51:22 -07001266 * @param preset
1267 * @return the same Builder instance.
1268 */
Eric Laurent00a00922015-03-09 09:25:45 -07001269 @SystemApi
Jean-Michel Trivi701d6ff2014-07-16 07:51:22 -07001270 public Builder setInternalCapturePreset(int preset) {
1271 if ((preset == MediaRecorder.AudioSource.HOTWORD)
Benson Huangce4483c2014-09-17 17:21:02 +08001272 || (preset == MediaRecorder.AudioSource.REMOTE_SUBMIX)
Nadav Bar33f4f682017-11-21 12:21:13 +02001273 || (preset == MediaRecorder.AudioSource.RADIO_TUNER)
1274 || (preset == MediaRecorder.AudioSource.VOICE_DOWNLINK)
1275 || (preset == MediaRecorder.AudioSource.VOICE_UPLINK)
Eric Laurent0016c5b2019-01-15 18:38:32 -08001276 || (preset == MediaRecorder.AudioSource.VOICE_CALL)
Carter Hsu02677712021-10-20 16:12:53 +08001277 || (preset == MediaRecorder.AudioSource.ECHO_REFERENCE)
Eric Laurentd90f6902023-02-08 11:52:24 +01001278 || (preset == MediaRecorder.AudioSource.ULTRASOUND)
1279 // AUDIO_SOURCE_INVALID is used by convention on default initialized
1280 // audio attributes
1281 || (preset == MediaRecorder.AudioSource.AUDIO_SOURCE_INVALID)) {
Jean-Michel Trivi701d6ff2014-07-16 07:51:22 -07001282 mSource = preset;
1283 } else {
1284 setCapturePreset(preset);
1285 }
Jean-Michel Trivid60e8752014-04-18 09:47:08 -07001286 return this;
1287 }
jiabin41584392019-02-26 12:57:57 -08001288
1289 /**
1290 * Specifying if haptic should be muted or not when playing audio-haptic coupled data.
Eric Laurentc9d353d2019-04-03 16:16:14 -07001291 * By default, haptic channels are disabled.
jiabin41584392019-02-26 12:57:57 -08001292 * @param muted true to force muting haptic channels.
1293 * @return the same Builder instance.
1294 */
jiabin3b180112019-04-09 16:13:38 -07001295 public @NonNull Builder setHapticChannelsMuted(boolean muted) {
jiabin41584392019-02-26 12:57:57 -08001296 mMuteHapticChannels = muted;
1297 return this;
1298 }
Eric Laurent64ed2ec2020-01-13 16:29:16 -08001299
1300 /**
1301 * @hide
1302 * Indicates if an AudioRecord build with this AudioAttributes is privacy sensitive or not.
1303 * See {@link AudioRecord.Builder#setPrivacySensitive(boolean)}.
1304 * @param privacySensitive True if capture must be marked as privacy sensitive,
1305 * false otherwise.
1306 * @return the same Builder instance.
1307 */
1308 public @NonNull Builder setPrivacySensitive(boolean privacySensitive) {
1309 mPrivacySensitive =
1310 privacySensitive ? PRIVACY_SENSITIVE_ENABLED : PRIVACY_SENSITIVE_DISABLED;
1311 return this;
1312 }
Eric Laurent78eef3a2021-11-09 16:10:42 +01001313
1314 /**
1315 * @hide
1316 * Designates the audio to be used for call redirection
1317 * @return the same Builder instance.
1318 */
1319 public Builder setForCallRedirection() {
1320 mFlags |= FLAG_CALL_REDIRECTION;
1321 return this;
1322 }
Jean-Michel Trivid60e8752014-04-18 09:47:08 -07001323 };
1324
Jean-Michel Trivib45c2732014-06-03 16:06:48 -07001325 @Override
1326 public int describeContents() {
1327 return 0;
1328 }
1329
Jean-Michel Trivi8df982d2014-06-26 12:05:16 -07001330 /**
1331 * @hide
1332 * Used to indicate that when parcelling, the tags should be parcelled through the flattened
1333 * formatted string, not through the array of strings.
1334 * Keep in sync with frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp
1335 * see definition of kAudioAttributesMarshallTagFlattenTags
1336 */
1337 public final static int FLATTEN_TAGS = 0x1;
Jean-Michel Trivif82f7462016-02-05 15:20:35 -08001338
1339 private final static int ATTR_PARCEL_IS_NULL_BUNDLE = -1977;
1340 private final static int ATTR_PARCEL_IS_VALID_BUNDLE = 1980;
1341
Jean-Michel Trivi8df982d2014-06-26 12:05:16 -07001342 /**
1343 * When adding tags for writeToParcel(Parcel, int), add them in the list of flags (| NEW_FLAG)
1344 */
1345 private final static int ALL_PARCEL_FLAGS = FLATTEN_TAGS;
Jean-Michel Trivib45c2732014-06-03 16:06:48 -07001346 @Override
1347 public void writeToParcel(Parcel dest, int flags) {
1348 dest.writeInt(mUsage);
1349 dest.writeInt(mContentType);
Jean-Michel Trivi701d6ff2014-07-16 07:51:22 -07001350 dest.writeInt(mSource);
Jean-Michel Trivib45c2732014-06-03 16:06:48 -07001351 dest.writeInt(mFlags);
Jean-Michel Trivi8df982d2014-06-26 12:05:16 -07001352 dest.writeInt(flags & ALL_PARCEL_FLAGS);
1353 if ((flags & FLATTEN_TAGS) == 0) {
1354 String[] tagsArray = new String[mTags.size()];
1355 mTags.toArray(tagsArray);
1356 dest.writeStringArray(tagsArray);
1357 } else if ((flags & FLATTEN_TAGS) == FLATTEN_TAGS) {
1358 dest.writeString(mFormattedTags);
1359 }
Jean-Michel Trivif82f7462016-02-05 15:20:35 -08001360 if (mBundle == null) {
1361 dest.writeInt(ATTR_PARCEL_IS_NULL_BUNDLE);
1362 } else {
1363 dest.writeInt(ATTR_PARCEL_IS_VALID_BUNDLE);
1364 dest.writeBundle(mBundle);
1365 }
Jean-Michel Trivib45c2732014-06-03 16:06:48 -07001366 }
1367
1368 private AudioAttributes(Parcel in) {
1369 mUsage = in.readInt();
1370 mContentType = in.readInt();
Jean-Michel Trivi701d6ff2014-07-16 07:51:22 -07001371 mSource = in.readInt();
Jean-Michel Trivib45c2732014-06-03 16:06:48 -07001372 mFlags = in.readInt();
Jean-Michel Trivi8df982d2014-06-26 12:05:16 -07001373 boolean hasFlattenedTags = ((in.readInt() & FLATTEN_TAGS) == FLATTEN_TAGS);
Jean-Michel Trivib45c2732014-06-03 16:06:48 -07001374 mTags = new HashSet<String>();
Jean-Michel Trivi8df982d2014-06-26 12:05:16 -07001375 if (hasFlattenedTags) {
Jean-Michel Trivicc58c762014-07-30 16:03:41 -07001376 mFormattedTags = new String(in.readString());
1377 mTags.add(mFormattedTags);
Jean-Michel Trivi8df982d2014-06-26 12:05:16 -07001378 } else {
1379 String[] tagsArray = in.readStringArray();
1380 for (int i = tagsArray.length - 1 ; i >= 0 ; i--) {
1381 mTags.add(tagsArray[i]);
1382 }
Jean-Michel Trivicc58c762014-07-30 16:03:41 -07001383 mFormattedTags = TextUtils.join(";", mTags);
Jean-Michel Trivib45c2732014-06-03 16:06:48 -07001384 }
Jean-Michel Trivif82f7462016-02-05 15:20:35 -08001385 switch (in.readInt()) {
1386 case ATTR_PARCEL_IS_NULL_BUNDLE:
1387 mBundle = null;
1388 break;
1389 case ATTR_PARCEL_IS_VALID_BUNDLE:
1390 mBundle = new Bundle(in.readBundle());
1391 break;
1392 default:
1393 Log.e(TAG, "Illegal value unmarshalling AudioAttributes, can't initialize bundle");
1394 }
Jean-Michel Trivib45c2732014-06-03 16:06:48 -07001395 }
1396
Jeff Sharkey9e8f83d2019-02-28 12:06:45 -07001397 public static final @android.annotation.NonNull Parcelable.Creator<AudioAttributes> CREATOR
Jean-Michel Trivib45c2732014-06-03 16:06:48 -07001398 = new Parcelable.Creator<AudioAttributes>() {
1399 /**
1400 * Rebuilds an AudioAttributes previously stored with writeToParcel().
1401 * @param p Parcel object to read the AudioAttributes from
1402 * @return a new AudioAttributes created from the data in the parcel
1403 */
1404 public AudioAttributes createFromParcel(Parcel p) {
1405 return new AudioAttributes(p);
1406 }
1407 public AudioAttributes[] newArray(int size) {
1408 return new AudioAttributes[size];
1409 }
1410 };
1411
Jean-Michel Trivie9c19a52014-07-29 13:04:41 -07001412 @Override
1413 public boolean equals(Object o) {
1414 if (this == o) return true;
1415 if (o == null || getClass() != o.getClass()) return false;
1416
1417 AudioAttributes that = (AudioAttributes) o;
1418
1419 return ((mContentType == that.mContentType)
1420 && (mFlags == that.mFlags)
1421 && (mSource == that.mSource)
1422 && (mUsage == that.mUsage)
1423 //mFormattedTags is never null due to assignment in Builder or unmarshalling
1424 && (mFormattedTags.equals(that.mFormattedTags)));
1425 }
1426
1427 @Override
1428 public int hashCode() {
Jean-Michel Trivif82f7462016-02-05 15:20:35 -08001429 return Objects.hash(mContentType, mFlags, mSource, mUsage, mFormattedTags, mBundle);
Jean-Michel Trivie9c19a52014-07-29 13:04:41 -07001430 }
1431
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07001432 @Override
1433 public String toString () {
1434 return new String("AudioAttributes:"
Jean-Michel Trivi3120059d2017-08-28 12:40:55 -07001435 + " usage=" + usageToString()
1436 + " content=" + contentTypeToString()
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07001437 + " flags=0x" + Integer.toHexString(mFlags).toUpperCase()
Jean-Michel Trivif82f7462016-02-05 15:20:35 -08001438 + " tags=" + mFormattedTags
1439 + " bundle=" + (mBundle == null ? "null" : mBundle.toString()));
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07001440 }
1441
Jean-Michel Trivi998ff752014-07-11 10:01:00 -07001442 /** @hide */
Jeffrey Huangcb782852019-12-05 11:28:11 -08001443 public void dumpDebug(ProtoOutputStream proto, long fieldId) {
Kweku Adamsbc84aec2018-01-23 13:33:12 -08001444 final long token = proto.start(fieldId);
1445
Kweku Adams62b42242017-09-25 12:54:02 -07001446 proto.write(AudioAttributesProto.USAGE, mUsage);
1447 proto.write(AudioAttributesProto.CONTENT_TYPE, mContentType);
1448 proto.write(AudioAttributesProto.FLAGS, mFlags);
1449 // mFormattedTags is never null due to assignment in Builder or unmarshalling.
1450 for (String t : mFormattedTags.split(";")) {
1451 t = t.trim();
1452 if (t != "") {
1453 proto.write(AudioAttributesProto.TAGS, t);
1454 }
1455 }
1456 // TODO: is the data in mBundle useful for debugging?
Kweku Adamsbc84aec2018-01-23 13:33:12 -08001457
1458 proto.end(token);
Kweku Adams62b42242017-09-25 12:54:02 -07001459 }
1460
1461 /** @hide */
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07001462 public String usageToString() {
John Spurlock7b414672014-07-18 13:02:39 -04001463 return usageToString(mUsage);
1464 }
1465
Antonio Kantek3935bdf2020-12-03 16:53:45 -08001466 /**
1467 * Returns the string representation for the usage constant passed as parameter.
1468 *
1469 * @param usage one of the {@link AudioAttributes} usage constants
1470 * @return string representing the {@link AudioAttributes} usage constant passed as a parameter
Antonio Kantek116467f2021-02-24 15:56:34 -08001471 *
1472 * @hide
Antonio Kantek3935bdf2020-12-03 16:53:45 -08001473 */
1474 @NonNull
1475 public static String usageToString(@AttributeSdkUsage int usage) {
John Spurlock7b414672014-07-18 13:02:39 -04001476 switch(usage) {
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07001477 case USAGE_UNKNOWN:
Antonio Kantek3935bdf2020-12-03 16:53:45 -08001478 return "USAGE_UNKNOWN";
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07001479 case USAGE_MEDIA:
Antonio Kantek3935bdf2020-12-03 16:53:45 -08001480 return "USAGE_MEDIA";
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07001481 case USAGE_VOICE_COMMUNICATION:
Antonio Kantek3935bdf2020-12-03 16:53:45 -08001482 return "USAGE_VOICE_COMMUNICATION";
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07001483 case USAGE_VOICE_COMMUNICATION_SIGNALLING:
Antonio Kantek3935bdf2020-12-03 16:53:45 -08001484 return "USAGE_VOICE_COMMUNICATION_SIGNALLING";
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07001485 case USAGE_ALARM:
Antonio Kantek3935bdf2020-12-03 16:53:45 -08001486 return "USAGE_ALARM";
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07001487 case USAGE_NOTIFICATION:
Antonio Kantek3935bdf2020-12-03 16:53:45 -08001488 return "USAGE_NOTIFICATION";
Jean-Michel Trivi89c3b292014-07-20 11:41:02 -07001489 case USAGE_NOTIFICATION_RINGTONE:
Antonio Kantek3935bdf2020-12-03 16:53:45 -08001490 return "USAGE_NOTIFICATION_RINGTONE";
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07001491 case USAGE_NOTIFICATION_COMMUNICATION_REQUEST:
Antonio Kantek3935bdf2020-12-03 16:53:45 -08001492 return "USAGE_NOTIFICATION_COMMUNICATION_REQUEST";
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07001493 case USAGE_NOTIFICATION_COMMUNICATION_INSTANT:
Antonio Kantek3935bdf2020-12-03 16:53:45 -08001494 return "USAGE_NOTIFICATION_COMMUNICATION_INSTANT";
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07001495 case USAGE_NOTIFICATION_COMMUNICATION_DELAYED:
Antonio Kantek3935bdf2020-12-03 16:53:45 -08001496 return "USAGE_NOTIFICATION_COMMUNICATION_DELAYED";
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07001497 case USAGE_NOTIFICATION_EVENT:
Antonio Kantek3935bdf2020-12-03 16:53:45 -08001498 return "USAGE_NOTIFICATION_EVENT";
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07001499 case USAGE_ASSISTANCE_ACCESSIBILITY:
Antonio Kantek3935bdf2020-12-03 16:53:45 -08001500 return "USAGE_ASSISTANCE_ACCESSIBILITY";
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07001501 case USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:
Antonio Kantek3935bdf2020-12-03 16:53:45 -08001502 return "USAGE_ASSISTANCE_NAVIGATION_GUIDANCE";
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07001503 case USAGE_ASSISTANCE_SONIFICATION:
Antonio Kantek3935bdf2020-12-03 16:53:45 -08001504 return "USAGE_ASSISTANCE_SONIFICATION";
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07001505 case USAGE_GAME:
Antonio Kantek3935bdf2020-12-03 16:53:45 -08001506 return "USAGE_GAME";
Jean-Michel Trivi0c8855d02016-12-29 10:33:29 -08001507 case USAGE_ASSISTANT:
Antonio Kantek3935bdf2020-12-03 16:53:45 -08001508 return "USAGE_ASSISTANT";
Eric Laurent0eb901b2019-12-06 18:15:28 -08001509 case USAGE_CALL_ASSISTANT:
Antonio Kantek3935bdf2020-12-03 16:53:45 -08001510 return "USAGE_CALL_ASSISTANT";
Hayden Gomesfe2c8772019-12-23 11:37:23 -08001511 case USAGE_EMERGENCY:
Antonio Kantek3935bdf2020-12-03 16:53:45 -08001512 return "USAGE_EMERGENCY";
Hayden Gomesfe2c8772019-12-23 11:37:23 -08001513 case USAGE_SAFETY:
Antonio Kantek3935bdf2020-12-03 16:53:45 -08001514 return "USAGE_SAFETY";
Hayden Gomesfe2c8772019-12-23 11:37:23 -08001515 case USAGE_VEHICLE_STATUS:
Antonio Kantek3935bdf2020-12-03 16:53:45 -08001516 return "USAGE_VEHICLE_STATUS";
Hayden Gomesfe2c8772019-12-23 11:37:23 -08001517 case USAGE_ANNOUNCEMENT:
Antonio Kantek3935bdf2020-12-03 16:53:45 -08001518 return "USAGE_ANNOUNCEMENT";
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07001519 default:
Antonio Kantek3935bdf2020-12-03 16:53:45 -08001520 return "unknown usage " + usage;
John Spurlock7b414672014-07-18 13:02:39 -04001521 }
1522 }
1523
Hayden Gomes24b336f2020-11-05 16:28:21 -08001524 /** @hide **/
1525 @TestApi
1526 @NonNull
1527 public static String usageToXsdString(@AttributeUsage int usage) {
1528 switch (usage) {
1529 case AudioAttributes.USAGE_UNKNOWN:
1530 return AudioUsage.AUDIO_USAGE_UNKNOWN.toString();
1531 case AudioAttributes.USAGE_MEDIA:
1532 return AudioUsage.AUDIO_USAGE_MEDIA.toString();
1533 case AudioAttributes.USAGE_VOICE_COMMUNICATION:
1534 return AudioUsage.AUDIO_USAGE_VOICE_COMMUNICATION.toString();
1535 case AudioAttributes.USAGE_VOICE_COMMUNICATION_SIGNALLING:
1536 return AudioUsage.AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING.toString();
1537 case AudioAttributes.USAGE_ALARM:
1538 return AudioUsage.AUDIO_USAGE_ALARM.toString();
1539 case AudioAttributes.USAGE_NOTIFICATION:
1540 return AudioUsage.AUDIO_USAGE_NOTIFICATION.toString();
1541 case AudioAttributes.USAGE_NOTIFICATION_RINGTONE:
1542 return AudioUsage.AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE.toString();
1543 case AudioAttributes.USAGE_ASSISTANCE_ACCESSIBILITY:
1544 return AudioUsage.AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY.toString();
1545 case AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:
1546 return AudioUsage.AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE.toString();
1547 case AudioAttributes.USAGE_ASSISTANCE_SONIFICATION:
1548 return AudioUsage.AUDIO_USAGE_ASSISTANCE_SONIFICATION.toString();
1549 case AudioAttributes.USAGE_GAME:
1550 return AudioUsage.AUDIO_USAGE_GAME.toString();
1551 case AudioAttributes.USAGE_VIRTUAL_SOURCE:
1552 return AudioUsage.AUDIO_USAGE_VIRTUAL_SOURCE.toString();
1553 case AudioAttributes.USAGE_ASSISTANT:
1554 return AudioUsage.AUDIO_USAGE_ASSISTANT.toString();
1555 case AudioAttributes.USAGE_CALL_ASSISTANT:
1556 return AudioUsage.AUDIO_USAGE_CALL_ASSISTANT.toString();
1557 case AudioAttributes.USAGE_EMERGENCY:
1558 return AudioUsage.AUDIO_USAGE_EMERGENCY.toString();
1559 case AudioAttributes.USAGE_SAFETY:
1560 return AudioUsage.AUDIO_USAGE_SAFETY.toString();
1561 case AudioAttributes.USAGE_VEHICLE_STATUS:
1562 return AudioUsage.AUDIO_USAGE_VEHICLE_STATUS.toString();
1563 case AudioAttributes.USAGE_ANNOUNCEMENT:
1564 return AudioUsage.AUDIO_USAGE_ANNOUNCEMENT.toString();
1565 default:
1566 Log.w(TAG, "Unknown usage value " + usage);
1567 return AudioUsage.AUDIO_USAGE_UNKNOWN.toString();
1568 }
1569 }
1570
1571 private static final Map<String, Integer> sXsdStringToUsage = new HashMap<>();
1572
1573 static {
1574 sXsdStringToUsage.put(AudioUsage.AUDIO_USAGE_UNKNOWN.toString(), USAGE_UNKNOWN);
1575 sXsdStringToUsage.put(AudioUsage.AUDIO_USAGE_UNKNOWN.toString(), USAGE_UNKNOWN);
1576 sXsdStringToUsage.put(AudioUsage.AUDIO_USAGE_MEDIA.toString(), USAGE_MEDIA);
1577 sXsdStringToUsage.put(AudioUsage.AUDIO_USAGE_VOICE_COMMUNICATION.toString(),
1578 USAGE_VOICE_COMMUNICATION);
1579 sXsdStringToUsage.put(AudioUsage.AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING.toString(),
1580 USAGE_VOICE_COMMUNICATION_SIGNALLING);
1581 sXsdStringToUsage.put(AudioUsage.AUDIO_USAGE_ALARM.toString(), USAGE_ALARM);
1582 sXsdStringToUsage.put(AudioUsage.AUDIO_USAGE_NOTIFICATION.toString(), USAGE_NOTIFICATION);
1583 sXsdStringToUsage.put(AudioUsage.AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE.toString(),
1584 USAGE_NOTIFICATION_RINGTONE);
1585 sXsdStringToUsage.put(AudioUsage.AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY.toString(),
1586 USAGE_ASSISTANCE_ACCESSIBILITY);
1587 sXsdStringToUsage.put(AudioUsage.AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE.toString(),
1588 USAGE_ASSISTANCE_NAVIGATION_GUIDANCE);
1589 sXsdStringToUsage.put(AudioUsage.AUDIO_USAGE_ASSISTANCE_SONIFICATION.toString(),
1590 USAGE_ASSISTANCE_SONIFICATION);
1591 sXsdStringToUsage.put(AudioUsage.AUDIO_USAGE_GAME.toString(), USAGE_GAME);
1592 sXsdStringToUsage.put(AudioUsage.AUDIO_USAGE_VIRTUAL_SOURCE.toString(),
1593 USAGE_VIRTUAL_SOURCE);
1594 sXsdStringToUsage.put(AudioUsage.AUDIO_USAGE_ASSISTANT.toString(), USAGE_ASSISTANT);
1595 sXsdStringToUsage.put(AudioUsage.AUDIO_USAGE_CALL_ASSISTANT.toString(),
1596 USAGE_CALL_ASSISTANT);
1597 sXsdStringToUsage.put(AudioUsage.AUDIO_USAGE_EMERGENCY.toString(), USAGE_EMERGENCY);
1598 sXsdStringToUsage.put(AudioUsage.AUDIO_USAGE_SAFETY.toString(), USAGE_SAFETY);
1599 sXsdStringToUsage.put(AudioUsage.AUDIO_USAGE_VEHICLE_STATUS.toString(),
1600 USAGE_VEHICLE_STATUS);
1601 sXsdStringToUsage.put(AudioUsage.AUDIO_USAGE_ANNOUNCEMENT.toString(), USAGE_ANNOUNCEMENT);
1602 }
1603
1604 /** @hide **/
1605 @TestApi
1606 public static @AttributeUsage int xsdStringToUsage(@NonNull String xsdUsage) {
1607 if (sXsdStringToUsage.containsKey(xsdUsage)) {
1608 return sXsdStringToUsage.get(xsdUsage);
1609 } else {
1610 Log.w(TAG, "Usage name not found in AudioUsage enum: " + xsdUsage);
1611 return USAGE_UNKNOWN;
1612 }
1613 }
1614
Jean-Michel Trivi3120059d2017-08-28 12:40:55 -07001615 /** @hide */
1616 public String contentTypeToString() {
1617 switch(mContentType) {
1618 case CONTENT_TYPE_UNKNOWN:
1619 return new String("CONTENT_TYPE_UNKNOWN");
1620 case CONTENT_TYPE_SPEECH: return new String("CONTENT_TYPE_SPEECH");
1621 case CONTENT_TYPE_MUSIC: return new String("CONTENT_TYPE_MUSIC");
1622 case CONTENT_TYPE_MOVIE: return new String("CONTENT_TYPE_MOVIE");
1623 case CONTENT_TYPE_SONIFICATION: return new String("CONTENT_TYPE_SONIFICATION");
Carter Hsu02677712021-10-20 16:12:53 +08001624 case CONTENT_TYPE_ULTRASOUND: return new String("CONTENT_TYPE_ULTRASOUND");
Jean-Michel Trivi3120059d2017-08-28 12:40:55 -07001625 default: return new String("unknown content type " + mContentType);
1626 }
1627 }
1628
Jean-Michel Trivi3f0945a2016-11-11 10:05:18 -08001629 private static int usageForStreamType(int streamType) {
John Spurlock7b414672014-07-18 13:02:39 -04001630 switch(streamType) {
1631 case AudioSystem.STREAM_VOICE_CALL:
1632 return USAGE_VOICE_COMMUNICATION;
1633 case AudioSystem.STREAM_SYSTEM_ENFORCED:
1634 case AudioSystem.STREAM_SYSTEM:
1635 return USAGE_ASSISTANCE_SONIFICATION;
1636 case AudioSystem.STREAM_RING:
Jean-Michel Trivi89c3b292014-07-20 11:41:02 -07001637 return USAGE_NOTIFICATION_RINGTONE;
John Spurlock7b414672014-07-18 13:02:39 -04001638 case AudioSystem.STREAM_MUSIC:
1639 return USAGE_MEDIA;
1640 case AudioSystem.STREAM_ALARM:
1641 return USAGE_ALARM;
1642 case AudioSystem.STREAM_NOTIFICATION:
1643 return USAGE_NOTIFICATION;
1644 case AudioSystem.STREAM_BLUETOOTH_SCO:
1645 return USAGE_VOICE_COMMUNICATION;
1646 case AudioSystem.STREAM_DTMF:
1647 return USAGE_VOICE_COMMUNICATION_SIGNALLING;
Jean-Michel Trivi3f0945a2016-11-11 10:05:18 -08001648 case AudioSystem.STREAM_ACCESSIBILITY:
John Spurlock7b414672014-07-18 13:02:39 -04001649 return USAGE_ASSISTANCE_ACCESSIBILITY;
Eric Laurent9b57d572021-11-29 15:20:32 +01001650 case AudioSystem.STREAM_ASSISTANT:
1651 return USAGE_ASSISTANT;
Jean-Michel Trivi3f0945a2016-11-11 10:05:18 -08001652 case AudioSystem.STREAM_TTS:
John Spurlock7b414672014-07-18 13:02:39 -04001653 default:
1654 return USAGE_UNKNOWN;
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07001655 }
1656 }
Jean-Michel Trivie67bc4d2017-03-27 11:52:18 -07001657
Jean-Michel Trivi3d22bf02015-02-03 10:15:08 -08001658 /**
Hayden Gomesfe2c8772019-12-23 11:37:23 -08001659 * @param usage one of {@link AttributeSystemUsage},
1660 * {@link AttributeSystemUsage#USAGE_CALL_ASSISTANT},
1661 * {@link AttributeSystemUsage#USAGE_EMERGENCY},
1662 * {@link AttributeSystemUsage#USAGE_SAFETY},
1663 * {@link AttributeSystemUsage#USAGE_VEHICLE_STATUS},
1664 * {@link AttributeSystemUsage#USAGE_ANNOUNCEMENT}
1665 * @return boolean indicating if the usage is a system usage or not
1666 * @hide
1667 */
1668 @SystemApi
1669 public static boolean isSystemUsage(@AttributeSystemUsage int usage) {
1670 return (usage == USAGE_CALL_ASSISTANT
1671 || usage == USAGE_EMERGENCY
1672 || usage == USAGE_SAFETY
1673 || usage == USAGE_VEHICLE_STATUS
1674 || usage == USAGE_ANNOUNCEMENT);
1675 }
1676
1677 /**
Jean-Michel Trivie67bc4d2017-03-27 11:52:18 -07001678 * Returns the stream type matching this {@code AudioAttributes} instance for volume control.
1679 * Use this method to derive the stream type needed to configure the volume
1680 * control slider in an {@link android.app.Activity} with
1681 * {@link android.app.Activity#setVolumeControlStream(int)} for playback conducted with these
1682 * attributes.
1683 * <BR>Do not use this method to set the stream type on an audio player object
1684 * (e.g. {@link AudioTrack}, {@link MediaPlayer}) as this is deprecated,
1685 * use {@code AudioAttributes} instead.
1686 * @return a valid stream type for {@code Activity} or stream volume control that matches
1687 * the attributes, or {@link AudioManager#USE_DEFAULT_STREAM_TYPE} if there isn't a direct
1688 * match. Note that {@code USE_DEFAULT_STREAM_TYPE} is not a valid value
1689 * for {@link AudioManager#setStreamVolume(int, int, int)}.
1690 */
1691 public int getVolumeControlStream() {
1692 return toVolumeStreamType(true /*fromGetVolumeControlStream*/, this);
1693 }
1694
1695 /**
Jean-Michel Trivi3d22bf02015-02-03 10:15:08 -08001696 * @hide
1697 * Only use to get which stream type should be used for volume control, NOT for audio playback
1698 * (all audio playback APIs are supposed to take AudioAttributes as input parameters)
1699 * @param aa non-null AudioAttributes.
1700 * @return a valid stream type for volume control that matches the attributes.
1701 */
Mathew Inwood473b9d52018-08-17 09:07:01 +01001702 @UnsupportedAppUsage
Jean-Michel Trivid1d5a0a2015-05-18 11:50:50 -07001703 public static int toLegacyStreamType(@NonNull AudioAttributes aa) {
1704 return toVolumeStreamType(false /*fromGetVolumeControlStream*/, aa);
1705 }
1706
1707 private static int toVolumeStreamType(boolean fromGetVolumeControlStream, AudioAttributes aa) {
Jean-Michel Trivi09818c12014-07-18 17:19:03 -07001708 // flags to stream type mapping
1709 if ((aa.getFlags() & FLAG_AUDIBILITY_ENFORCED) == FLAG_AUDIBILITY_ENFORCED) {
Jean-Michel Trivid1d5a0a2015-05-18 11:50:50 -07001710 return fromGetVolumeControlStream ?
1711 AudioSystem.STREAM_SYSTEM : AudioSystem.STREAM_SYSTEM_ENFORCED;
Jean-Michel Trivi09818c12014-07-18 17:19:03 -07001712 }
Par-Gunnar Hjalmdahl96e68bc2015-05-28 10:02:43 +02001713 if ((aa.getAllFlags() & FLAG_SCO) == FLAG_SCO) {
Jean-Michel Trivid1d5a0a2015-05-18 11:50:50 -07001714 return fromGetVolumeControlStream ?
1715 AudioSystem.STREAM_VOICE_CALL : AudioSystem.STREAM_BLUETOOTH_SCO;
Jean-Michel Trivi09818c12014-07-18 17:19:03 -07001716 }
Tomoharu Kasaharabe0103c2018-09-11 19:14:39 +09001717 if ((aa.getAllFlags() & FLAG_BEACON) == FLAG_BEACON) {
1718 return fromGetVolumeControlStream ?
1719 AudioSystem.STREAM_MUSIC : AudioSystem.STREAM_TTS;
1720 }
Jean-Michel Trivi09818c12014-07-18 17:19:03 -07001721
Hayden Gomes6d69bde2019-04-04 13:10:13 -07001722 if (AudioProductStrategy.getAudioProductStrategies().size() > 0) {
1723 return AudioProductStrategy.getLegacyStreamTypeForStrategyWithAudioAttributes(aa);
François Gaffiee6d280d2018-03-21 16:08:33 +01001724 }
Jean-Michel Trivi09818c12014-07-18 17:19:03 -07001725 // usage to stream type mapping
1726 switch (aa.getUsage()) {
1727 case USAGE_MEDIA:
1728 case USAGE_GAME:
Jean-Michel Trivi09818c12014-07-18 17:19:03 -07001729 case USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:
Jean-Michel Trivi0c8855d02016-12-29 10:33:29 -08001730 case USAGE_ASSISTANT:
Jean-Michel Trivi09818c12014-07-18 17:19:03 -07001731 return AudioSystem.STREAM_MUSIC;
1732 case USAGE_ASSISTANCE_SONIFICATION:
1733 return AudioSystem.STREAM_SYSTEM;
1734 case USAGE_VOICE_COMMUNICATION:
Eric Laurent0eb901b2019-12-06 18:15:28 -08001735 case USAGE_CALL_ASSISTANT:
Jean-Michel Trivi09818c12014-07-18 17:19:03 -07001736 return AudioSystem.STREAM_VOICE_CALL;
1737 case USAGE_VOICE_COMMUNICATION_SIGNALLING:
Jean-Michel Trivid1d5a0a2015-05-18 11:50:50 -07001738 return fromGetVolumeControlStream ?
1739 AudioSystem.STREAM_VOICE_CALL : AudioSystem.STREAM_DTMF;
Jean-Michel Trivi09818c12014-07-18 17:19:03 -07001740 case USAGE_ALARM:
1741 return AudioSystem.STREAM_ALARM;
Jean-Michel Trivi89c3b292014-07-20 11:41:02 -07001742 case USAGE_NOTIFICATION_RINGTONE:
Jean-Michel Trivi09818c12014-07-18 17:19:03 -07001743 return AudioSystem.STREAM_RING;
1744 case USAGE_NOTIFICATION:
1745 case USAGE_NOTIFICATION_COMMUNICATION_REQUEST:
1746 case USAGE_NOTIFICATION_COMMUNICATION_INSTANT:
1747 case USAGE_NOTIFICATION_COMMUNICATION_DELAYED:
1748 case USAGE_NOTIFICATION_EVENT:
1749 return AudioSystem.STREAM_NOTIFICATION;
Jean-Michel Trivi3f0945a2016-11-11 10:05:18 -08001750 case USAGE_ASSISTANCE_ACCESSIBILITY:
1751 return AudioSystem.STREAM_ACCESSIBILITY;
Hayden Gomesfe2c8772019-12-23 11:37:23 -08001752 case USAGE_EMERGENCY:
1753 case USAGE_SAFETY:
1754 case USAGE_VEHICLE_STATUS:
1755 case USAGE_ANNOUNCEMENT:
Jean-Michel Trivi09818c12014-07-18 17:19:03 -07001756 case USAGE_UNKNOWN:
Jean-Michel Trivi6d38a1b2018-04-09 10:54:36 -07001757 return AudioSystem.STREAM_MUSIC;
Jean-Michel Trivi09818c12014-07-18 17:19:03 -07001758 default:
Jean-Michel Trivid1d5a0a2015-05-18 11:50:50 -07001759 if (fromGetVolumeControlStream) {
1760 throw new IllegalArgumentException("Unknown usage value " + aa.getUsage() +
1761 " in audio attributes");
1762 } else {
1763 return AudioSystem.STREAM_MUSIC;
1764 }
Jean-Michel Trivi09818c12014-07-18 17:19:03 -07001765 }
1766 }
1767
jiabinb33f3692019-12-23 13:09:58 -08001768 /**
1769 * @hide
1770 */
1771 public static int capturePolicyToFlags(@CapturePolicy int capturePolicy, int flags) {
Kevin Rocard7919c2a2019-03-21 10:28:01 -07001772 switch (capturePolicy) {
1773 case ALLOW_CAPTURE_BY_NONE:
1774 flags |= FLAG_NO_MEDIA_PROJECTION | FLAG_NO_SYSTEM_CAPTURE;
1775 break;
1776 case ALLOW_CAPTURE_BY_SYSTEM:
1777 flags |= FLAG_NO_MEDIA_PROJECTION;
1778 flags &= ~FLAG_NO_SYSTEM_CAPTURE;
1779 break;
1780 case ALLOW_CAPTURE_BY_ALL:
1781 flags &= ~FLAG_NO_SYSTEM_CAPTURE & ~FLAG_NO_MEDIA_PROJECTION;
1782 break;
1783 default:
1784 throw new IllegalArgumentException("Unknown allow playback capture policy");
1785 }
1786 return flags;
1787 }
1788
Jean-Michel Trivi09818c12014-07-18 17:19:03 -07001789 /** @hide */
Jean-Michel Trivid60e8752014-04-18 09:47:08 -07001790 @IntDef({
Hayden Gomesfe2c8772019-12-23 11:37:23 -08001791 USAGE_CALL_ASSISTANT,
1792 USAGE_EMERGENCY,
1793 USAGE_SAFETY,
1794 USAGE_VEHICLE_STATUS,
1795 USAGE_ANNOUNCEMENT
1796 })
1797 @Retention(RetentionPolicy.SOURCE)
1798 public @interface AttributeSystemUsage {}
1799
1800 /** @hide */
1801 @IntDef({
1802 USAGE_UNKNOWN,
1803 USAGE_MEDIA,
1804 USAGE_VOICE_COMMUNICATION,
1805 USAGE_VOICE_COMMUNICATION_SIGNALLING,
1806 USAGE_ALARM,
1807 USAGE_NOTIFICATION,
1808 USAGE_NOTIFICATION_RINGTONE,
1809 USAGE_NOTIFICATION_COMMUNICATION_REQUEST,
1810 USAGE_NOTIFICATION_COMMUNICATION_INSTANT,
1811 USAGE_NOTIFICATION_COMMUNICATION_DELAYED,
1812 USAGE_NOTIFICATION_EVENT,
1813 USAGE_ASSISTANCE_ACCESSIBILITY,
1814 USAGE_ASSISTANCE_NAVIGATION_GUIDANCE,
1815 USAGE_ASSISTANCE_SONIFICATION,
1816 USAGE_GAME,
1817 USAGE_ASSISTANT,
1818 })
1819 @Retention(RetentionPolicy.SOURCE)
1820 public @interface AttributeSdkUsage {}
1821
1822 /** @hide */
1823 @IntDef({
Jean-Michel Trivid60e8752014-04-18 09:47:08 -07001824 USAGE_UNKNOWN,
1825 USAGE_MEDIA,
1826 USAGE_VOICE_COMMUNICATION,
1827 USAGE_VOICE_COMMUNICATION_SIGNALLING,
1828 USAGE_ALARM,
1829 USAGE_NOTIFICATION,
Jean-Michel Trivi89c3b292014-07-20 11:41:02 -07001830 USAGE_NOTIFICATION_RINGTONE,
Jean-Michel Trivid60e8752014-04-18 09:47:08 -07001831 USAGE_NOTIFICATION_COMMUNICATION_REQUEST,
1832 USAGE_NOTIFICATION_COMMUNICATION_INSTANT,
1833 USAGE_NOTIFICATION_COMMUNICATION_DELAYED,
1834 USAGE_NOTIFICATION_EVENT,
1835 USAGE_ASSISTANCE_ACCESSIBILITY,
1836 USAGE_ASSISTANCE_NAVIGATION_GUIDANCE,
1837 USAGE_ASSISTANCE_SONIFICATION,
Jean-Michel Trivi0c8855d02016-12-29 10:33:29 -08001838 USAGE_GAME,
1839 USAGE_ASSISTANT,
Eric Laurent0eb901b2019-12-06 18:15:28 -08001840 USAGE_CALL_ASSISTANT,
Hayden Gomesfe2c8772019-12-23 11:37:23 -08001841 USAGE_EMERGENCY,
1842 USAGE_SAFETY,
1843 USAGE_VEHICLE_STATUS,
1844 USAGE_ANNOUNCEMENT,
Jean-Michel Trivid60e8752014-04-18 09:47:08 -07001845 })
1846 @Retention(RetentionPolicy.SOURCE)
1847 public @interface AttributeUsage {}
1848
1849 /** @hide */
1850 @IntDef({
1851 CONTENT_TYPE_UNKNOWN,
1852 CONTENT_TYPE_SPEECH,
1853 CONTENT_TYPE_MUSIC,
1854 CONTENT_TYPE_MOVIE,
1855 CONTENT_TYPE_SONIFICATION
1856 })
1857 @Retention(RetentionPolicy.SOURCE)
1858 public @interface AttributeContentType {}
Carter Hsu02677712021-10-20 16:12:53 +08001859
1860 /** @hide */
1861 @IntDef({
1862 CONTENT_TYPE_UNKNOWN,
1863 CONTENT_TYPE_SPEECH,
1864 CONTENT_TYPE_MUSIC,
1865 CONTENT_TYPE_MOVIE,
1866 CONTENT_TYPE_SONIFICATION,
1867 CONTENT_TYPE_ULTRASOUND
1868 })
1869 @Retention(RetentionPolicy.SOURCE)
1870 public @interface AttrInternalContentType {}
Jean-Michel Trivid60e8752014-04-18 09:47:08 -07001871}