blob: 7dd4b10c5fbf3f9cacbf7ac6c1bf68cd85777a6d [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 Gomesc164f6a2020-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 Gomesc164f6a2020-11-05 16:28:21 -080039import java.util.HashMap;
Jean-Michel Trivid60e8752014-04-18 09:47:08 -070040import java.util.HashSet;
Hayden Gomesc164f6a2020-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;
104
105 /**
Hayden Gomesfe2c8772019-12-23 11:37:23 -0800106 * Invalid value, only ever used for an uninitialized usage value
107 */
108 private static final int USAGE_INVALID = -1;
109 /**
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700110 * Usage value to use when the usage is unknown.
111 */
112 public final static int USAGE_UNKNOWN = 0;
113 /**
114 * Usage value to use when the usage is media, such as music, or movie
115 * soundtracks.
116 */
117 public final static int USAGE_MEDIA = 1;
118 /**
119 * Usage value to use when the usage is voice communications, such as telephony
120 * or VoIP.
121 */
122 public final static int USAGE_VOICE_COMMUNICATION = 2;
123 /**
124 * Usage value to use when the usage is in-call signalling, such as with
125 * a "busy" beep, or DTMF tones.
126 */
127 public final static int USAGE_VOICE_COMMUNICATION_SIGNALLING = 3;
128 /**
129 * Usage value to use when the usage is an alarm (e.g. wake-up alarm).
130 */
131 public final static int USAGE_ALARM = 4;
132 /**
133 * Usage value to use when the usage is notification. See other
134 * notification usages for more specialized uses.
135 */
136 public final static int USAGE_NOTIFICATION = 5;
137 /**
138 * Usage value to use when the usage is telephony ringtone.
139 */
Jean-Michel Trivi89c3b292014-07-20 11:41:02 -0700140 public final static int USAGE_NOTIFICATION_RINGTONE = 6;
141 /**
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700142 * Usage value to use when the usage is a request to enter/end a
143 * communication, such as a VoIP communication or video-conference.
144 */
145 public final static int USAGE_NOTIFICATION_COMMUNICATION_REQUEST = 7;
146 /**
147 * Usage value to use when the usage is notification for an "instant"
148 * communication such as a chat, or SMS.
149 */
150 public final static int USAGE_NOTIFICATION_COMMUNICATION_INSTANT = 8;
151 /**
152 * Usage value to use when the usage is notification for a
153 * non-immediate type of communication such as e-mail.
154 */
155 public final static int USAGE_NOTIFICATION_COMMUNICATION_DELAYED = 9;
156 /**
157 * Usage value to use when the usage is to attract the user's attention,
158 * such as a reminder or low battery warning.
159 */
160 public final static int USAGE_NOTIFICATION_EVENT = 10;
161 /**
162 * Usage value to use when the usage is for accessibility, such as with
163 * a screen reader.
164 */
165 public final static int USAGE_ASSISTANCE_ACCESSIBILITY = 11;
166 /**
167 * Usage value to use when the usage is driving or navigation directions.
168 */
169 public final static int USAGE_ASSISTANCE_NAVIGATION_GUIDANCE = 12;
170 /**
171 * Usage value to use when the usage is sonification, such as with user
172 * interface sounds.
173 */
174 public final static int USAGE_ASSISTANCE_SONIFICATION = 13;
175 /**
176 * Usage value to use when the usage is for game audio.
177 */
178 public final static int USAGE_GAME = 14;
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -0700179 /**
180 * @hide
181 * Usage value to use when feeding audio to the platform and replacing "traditional" audio
182 * source, such as audio capture devices.
183 */
184 public final static int USAGE_VIRTUAL_SOURCE = 15;
Jean-Michel Trivi0c8855d02016-12-29 10:33:29 -0800185 /**
186 * Usage value to use for audio responses to user queries, audio instructions or help
187 * utterances.
188 */
189 public final static int USAGE_ASSISTANT = 16;
Eric Laurent0eb901b2019-12-06 18:15:28 -0800190 /**
191 * @hide
192 * Usage value to use for assistant voice interaction with remote caller on Cell and VoIP calls.
193 */
194 @SystemApi
Hayden Gomesfe2c8772019-12-23 11:37:23 -0800195 @RequiresPermission(allOf = {
196 android.Manifest.permission.MODIFY_PHONE_STATE,
197 android.Manifest.permission.MODIFY_AUDIO_ROUTING
198 })
Eric Laurent0eb901b2019-12-06 18:15:28 -0800199 public static final int USAGE_CALL_ASSISTANT = 17;
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700200
Hayden Gomesfe2c8772019-12-23 11:37:23 -0800201 private static final int SYSTEM_USAGE_OFFSET = 1000;
202
203 /**
204 * @hide
205 * Usage value to use when the usage is an emergency.
206 */
207 @SystemApi
208 @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
209 public static final int USAGE_EMERGENCY = SYSTEM_USAGE_OFFSET;
210 /**
211 * @hide
212 * Usage value to use when the usage is a safety sound.
213 */
214 @SystemApi
215 @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
216 public static final int USAGE_SAFETY = SYSTEM_USAGE_OFFSET + 1;
217 /**
218 * @hide
219 * Usage value to use when the usage is a vehicle status.
220 */
221 @SystemApi
222 @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
223 public static final int USAGE_VEHICLE_STATUS = SYSTEM_USAGE_OFFSET + 2;
224 /**
225 * @hide
226 * Usage value to use when the usage is an announcement.
227 */
228 @SystemApi
229 @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
230 public static final int USAGE_ANNOUNCEMENT = SYSTEM_USAGE_OFFSET + 3;
231
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700232 /**
Jean-Michel Trivie743bda2016-09-09 11:56:48 -0700233 * IMPORTANT: when adding new usage types, add them to SDK_USAGES and update SUPPRESSIBLE_USAGES
Kweku Adams62b42242017-09-25 12:54:02 -0700234 * if applicable, as well as audioattributes.proto.
Phil Burk91df2712018-01-17 15:01:43 -0800235 * Also consider adding them to <aaudio/AAudio.h> for the NDK.
Hongwei Wang1b322dd2018-04-03 16:22:06 -0700236 * Also consider adding them to UsageTypeConverter for service dump and etc.
Jean-Michel Trivie743bda2016-09-09 11:56:48 -0700237 */
238
239 /**
240 * @hide
241 * Denotes a usage for notifications that do not expect immediate intervention from the user,
242 * will be muted when the Zen mode disables notifications
243 * @see #SUPPRESSIBLE_USAGES
244 */
245 public final static int SUPPRESSIBLE_NOTIFICATION = 1;
246 /**
247 * @hide
248 * Denotes a usage for notifications that do expect immediate intervention from the user,
249 * will be muted when the Zen mode disables calls
250 * @see #SUPPRESSIBLE_USAGES
251 */
252 public final static int SUPPRESSIBLE_CALL = 2;
Jean-Michel Trivi7a84eae2017-06-20 14:58:18 -0700253 /**
254 * @hide
255 * Denotes a usage that is never going to be muted, even in Total Silence.
256 * @see #SUPPRESSIBLE_USAGES
257 */
258 public final static int SUPPRESSIBLE_NEVER = 3;
Beverly04216872017-09-28 10:55:32 -0400259 /**
260 * @hide
261 * Denotes a usage for alarms,
Beverlyd6964762018-02-16 14:07:03 -0500262 * will be muted when the Zen mode priority doesn't allow alarms or in Alarms Only Mode
Beverly04216872017-09-28 10:55:32 -0400263 * @see #SUPPRESSIBLE_USAGES
264 */
265 public final static int SUPPRESSIBLE_ALARM = 4;
266 /**
267 * @hide
Beverlyd6964762018-02-16 14:07:03 -0500268 * Denotes a usage for media, game, assistant, and navigation
269 * will be muted when the Zen priority mode doesn't allow media
Beverly04216872017-09-28 10:55:32 -0400270 * @see #SUPPRESSIBLE_USAGES
271 */
Beverlyd6964762018-02-16 14:07:03 -0500272 public final static int SUPPRESSIBLE_MEDIA = 5;
273 /**
274 * @hide
Beverly1feff712019-05-29 09:31:12 -0400275 * Denotes a usage for sounds not caught in SUPPRESSIBLE_NOTIFICATION,
Beverlyd6964762018-02-16 14:07:03 -0500276 * SUPPRESSIBLE_CALL,SUPPRESSIBLE_NEVER, SUPPRESSIBLE_ALARM or SUPPRESSIBLE_MEDIA.
Beverly1feff712019-05-29 09:31:12 -0400277 * This includes sonification sounds.
278 * These will be muted when the Zen priority mode doesn't allow system sounds
Beverlyd6964762018-02-16 14:07:03 -0500279 * @see #SUPPRESSIBLE_USAGES
280 */
281 public final static int SUPPRESSIBLE_SYSTEM = 6;
Jean-Michel Trivie743bda2016-09-09 11:56:48 -0700282
283 /**
284 * @hide
285 * Array of all usage types for calls and notifications to assign the suppression behavior,
286 * used by the Zen mode restrictions.
287 * @see com.android.server.notification.ZenModeHelper
288 */
289 public static final SparseIntArray SUPPRESSIBLE_USAGES;
290
291 static {
292 SUPPRESSIBLE_USAGES = new SparseIntArray();
293 SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION, SUPPRESSIBLE_NOTIFICATION);
294 SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION_RINGTONE, SUPPRESSIBLE_CALL);
295 SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION_COMMUNICATION_REQUEST,SUPPRESSIBLE_CALL);
296 SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION_COMMUNICATION_INSTANT,SUPPRESSIBLE_NOTIFICATION);
297 SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION_COMMUNICATION_DELAYED,SUPPRESSIBLE_NOTIFICATION);
298 SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION_EVENT, SUPPRESSIBLE_NOTIFICATION);
Jean-Michel Trivi7a84eae2017-06-20 14:58:18 -0700299 SUPPRESSIBLE_USAGES.put(USAGE_ASSISTANCE_ACCESSIBILITY, SUPPRESSIBLE_NEVER);
Jean-Michel Trivif1cd71a2017-06-22 19:30:29 -0700300 SUPPRESSIBLE_USAGES.put(USAGE_VOICE_COMMUNICATION, SUPPRESSIBLE_NEVER);
Beverly1feff712019-05-29 09:31:12 -0400301 SUPPRESSIBLE_USAGES.put(USAGE_VOICE_COMMUNICATION_SIGNALLING, SUPPRESSIBLE_NEVER);
Beverly04216872017-09-28 10:55:32 -0400302 SUPPRESSIBLE_USAGES.put(USAGE_ALARM, SUPPRESSIBLE_ALARM);
Beverlyd6964762018-02-16 14:07:03 -0500303 SUPPRESSIBLE_USAGES.put(USAGE_MEDIA, SUPPRESSIBLE_MEDIA);
304 SUPPRESSIBLE_USAGES.put(USAGE_ASSISTANCE_NAVIGATION_GUIDANCE, SUPPRESSIBLE_MEDIA);
305 SUPPRESSIBLE_USAGES.put(USAGE_GAME, SUPPRESSIBLE_MEDIA);
306 SUPPRESSIBLE_USAGES.put(USAGE_ASSISTANT, SUPPRESSIBLE_MEDIA);
Eric Laurent0eb901b2019-12-06 18:15:28 -0800307 SUPPRESSIBLE_USAGES.put(USAGE_CALL_ASSISTANT, SUPPRESSIBLE_NEVER);
Jean-Michel Trivi6d38a1b2018-04-09 10:54:36 -0700308 /** default volume assignment is STREAM_MUSIC, handle unknown usage as media */
309 SUPPRESSIBLE_USAGES.put(USAGE_UNKNOWN, SUPPRESSIBLE_MEDIA);
Beverlyd6964762018-02-16 14:07:03 -0500310 SUPPRESSIBLE_USAGES.put(USAGE_ASSISTANCE_SONIFICATION, SUPPRESSIBLE_SYSTEM);
Jean-Michel Trivie743bda2016-09-09 11:56:48 -0700311 }
312
313 /**
314 * @hide
315 * Array of all usage types exposed in the SDK that applications can use.
316 */
317 public final static int[] SDK_USAGES = {
318 USAGE_UNKNOWN,
319 USAGE_MEDIA,
320 USAGE_VOICE_COMMUNICATION,
321 USAGE_VOICE_COMMUNICATION_SIGNALLING,
322 USAGE_ALARM,
323 USAGE_NOTIFICATION,
324 USAGE_NOTIFICATION_RINGTONE,
325 USAGE_NOTIFICATION_COMMUNICATION_REQUEST,
326 USAGE_NOTIFICATION_COMMUNICATION_INSTANT,
327 USAGE_NOTIFICATION_COMMUNICATION_DELAYED,
328 USAGE_NOTIFICATION_EVENT,
329 USAGE_ASSISTANCE_ACCESSIBILITY,
330 USAGE_ASSISTANCE_NAVIGATION_GUIDANCE,
331 USAGE_ASSISTANCE_SONIFICATION,
Jean-Michel Trivi0c8855d02016-12-29 10:33:29 -0800332 USAGE_GAME,
333 USAGE_ASSISTANT,
Jean-Michel Trivie743bda2016-09-09 11:56:48 -0700334 };
335
336 /**
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700337 * Flag defining a behavior where the audibility of the sound will be ensured by the system.
Jean-Michel Trivie8fb9cb2021-06-30 09:13:27 -0700338 * To ensure sound audibility, the system only uses built-in speakers or wired headphones
339 * and specifically excludes wireless audio devices.
340 * <p>Note this flag should only be used for sounds subject to regulatory behaviors in some
341 * countries, such as for camera shutter sound, and not for routing behaviors.
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700342 */
343 public final static int FLAG_AUDIBILITY_ENFORCED = 0x1 << 0;
344 /**
345 * @hide
346 * Flag defining a behavior where the playback of the sound is ensured without
347 * degradation only when going to a secure sink.
348 */
349 // FIXME not guaranteed yet
Jean-Michel Trivi6894cd32014-07-21 16:06:33 -0700350 // TODO add in FLAG_ALL_PUBLIC when supported and in public API
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700351 public final static int FLAG_SECURE = 0x1 << 1;
352 /**
353 * @hide
354 * Flag to enable when the stream is associated with SCO usage.
355 * Internal use only for dealing with legacy STREAM_BLUETOOTH_SCO
356 */
357 public final static int FLAG_SCO = 0x1 << 2;
Jean-Michel Trivi6894cd32014-07-21 16:06:33 -0700358 /**
359 * @hide
360 * Flag defining a behavior where the system ensures that the playback of the sound will
361 * be compatible with its use as a broadcast for surrounding people and/or devices.
362 * Ensures audibility with no or minimal post-processing applied.
363 */
364 @SystemApi
365 public final static int FLAG_BEACON = 0x1 << 3;
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700366
Eric Laurentb634e1b2014-08-01 14:44:46 -0700367 /**
Eric Laurentb634e1b2014-08-01 14:44:46 -0700368 * Flag requesting the use of an output stream supporting hardware A/V synchronization.
369 */
370 public final static int FLAG_HW_AV_SYNC = 0x1 << 4;
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700371
Eric Laurentbdad1af2014-09-19 17:43:29 -0700372 /**
373 * @hide
374 * Flag requesting capture from the source used for hardware hotword detection.
375 * To be used with capture preset MediaRecorder.AudioSource.HOTWORD or
376 * MediaRecorder.AudioSource.VOICE_RECOGNITION.
377 */
378 @SystemApi
379 public final static int FLAG_HW_HOTWORD = 0x1 << 5;
380
John Spurlockbbfd31a2015-02-18 11:58:14 -0500381 /**
382 * @hide
383 * Flag requesting audible playback even under limited interruptions.
384 */
385 @SystemApi
386 public final static int FLAG_BYPASS_INTERRUPTION_POLICY = 0x1 << 6;
387
388 /**
389 * @hide
390 * Flag requesting audible playback even when the underlying stream is muted.
391 */
392 @SystemApi
393 public final static int FLAG_BYPASS_MUTE = 0x1 << 7;
394
Phil Burkdd731422015-12-28 10:34:33 -0800395 /**
Phil Burk2050f6c2016-05-25 15:13:57 -0700396 * Flag requesting a low latency path when creating an AudioTrack.
Phil Burkdd731422015-12-28 10:34:33 -0800397 * When using this flag, the sample rate must match the native sample rate
398 * of the device. Effects processing is also unavailable.
Phil Burk2050f6c2016-05-25 15:13:57 -0700399 *
400 * Note that if this flag is used without specifying a bufferSizeInBytes then the
401 * AudioTrack's actual buffer size may be too small. It is recommended that a fairly
402 * large buffer should be specified when the AudioTrack is created.
403 * Then the actual size can be reduced by calling
404 * {@link AudioTrack#setBufferSizeInFrames(int)}. The buffer size can be optimized
405 * by lowering it after each write() call until the audio glitches, which is detected by calling
406 * {@link AudioTrack#getUnderrunCount()}. Then the buffer size can be increased
407 * until there are no glitches.
408 * This tuning step should be done while playing silence.
409 * This technique provides a compromise between latency and glitch rate.
Andy Hungebc2c142017-01-12 19:20:29 -0800410 *
411 * @deprecated Use {@link AudioTrack.Builder#setPerformanceMode(int)} with
412 * {@link AudioTrack#PERFORMANCE_MODE_LOW_LATENCY} to control performance.
Phil Burkdd731422015-12-28 10:34:33 -0800413 */
414 public final static int FLAG_LOW_LATENCY = 0x1 << 8;
415
Andy Hungebc2c142017-01-12 19:20:29 -0800416 /**
417 * @hide
418 * Flag requesting a deep buffer path when creating an {@code AudioTrack}.
419 *
420 * A deep buffer path, if available, may consume less power and is
421 * suitable for media playback where latency is not a concern.
422 * Use {@link AudioTrack.Builder#setPerformanceMode(int)} with
423 * {@link AudioTrack#PERFORMANCE_MODE_POWER_SAVING} to enable.
424 */
425 public final static int FLAG_DEEP_BUFFER = 0x1 << 9;
426
Kevin Rocard9ce6e562019-02-05 15:45:26 -0800427 /**
428 * @hide
Kevin Rocarda3a4bbb2019-03-07 18:29:48 -0800429 * Flag specifying that the audio shall not be captured by third-party apps
430 * with a MediaProjection.
Kevin Rocard9ce6e562019-02-05 15:45:26 -0800431 */
Kevin Rocarda3a4bbb2019-03-07 18:29:48 -0800432 public static final int FLAG_NO_MEDIA_PROJECTION = 0x1 << 10;
Kevin Rocard9ce6e562019-02-05 15:45:26 -0800433
jiabin41584392019-02-26 12:57:57 -0800434 /**
435 * @hide
436 * Flag indicating force muting haptic channels.
437 */
438 public static final int FLAG_MUTE_HAPTIC = 0x1 << 11;
439
Kevin Rocarda3a4bbb2019-03-07 18:29:48 -0800440 /**
441 * @hide
442 * Flag specifying that the audio shall not be captured by any apps, not even system apps.
443 */
444 public static final int FLAG_NO_SYSTEM_CAPTURE = 0x1 << 12;
445
Eric Laurent597f0b5e2019-10-24 15:57:27 -0700446 /**
447 * @hide
448 * Flag requesting private audio capture. When set in audio attributes passed to an
449 * AudioRecord, this prevents a privileged Assistant from capturing audio while this
450 * AudioRecord is active.
451 */
452 public static final int FLAG_CAPTURE_PRIVATE = 0x1 << 13;
453
454
jiabin1073ee62019-04-16 17:27:41 -0700455 // Note that even though FLAG_MUTE_HAPTIC is stored as a flag bit, it is not here since
456 // it is known as a boolean value outside of AudioAttributes.
Kevin Rocard506541c2019-04-03 12:35:46 -0700457 private static final int FLAG_ALL = FLAG_AUDIBILITY_ENFORCED | FLAG_SECURE | FLAG_SCO
458 | FLAG_BEACON | FLAG_HW_AV_SYNC | FLAG_HW_HOTWORD | FLAG_BYPASS_INTERRUPTION_POLICY
459 | FLAG_BYPASS_MUTE | FLAG_LOW_LATENCY | FLAG_DEEP_BUFFER | FLAG_NO_MEDIA_PROJECTION
Eric Laurent597f0b5e2019-10-24 15:57:27 -0700460 | FLAG_NO_SYSTEM_CAPTURE | FLAG_CAPTURE_PRIVATE;
Phil Burkdd731422015-12-28 10:34:33 -0800461 private final static int FLAG_ALL_PUBLIC = FLAG_AUDIBILITY_ENFORCED |
462 FLAG_HW_AV_SYNC | FLAG_LOW_LATENCY;
Jean-Michel Trivib097d9e2020-06-25 17:55:39 -0700463 /* mask of flags that can be set by SDK and System APIs through the Builder */
464 private static final int FLAG_ALL_API_SET = FLAG_ALL_PUBLIC
465 | FLAG_BYPASS_INTERRUPTION_POLICY
466 | FLAG_BYPASS_MUTE;
Jean-Michel Trivi6894cd32014-07-21 16:06:33 -0700467
Kevin Rocarda3a4bbb2019-03-07 18:29:48 -0800468 /**
469 * Indicates that the audio may be captured by any app.
470 *
Kevin Rocarde5b29c92019-04-03 12:37:32 -0700471 * For privacy, the following usages cannot be recorded: VOICE_COMMUNICATION*,
Kevin Rocarda3a4bbb2019-03-07 18:29:48 -0800472 * USAGE_NOTIFICATION*, USAGE_ASSISTANCE* and USAGE_ASSISTANT.
473 *
474 * On {@link android.os.Build.VERSION_CODES#Q}, this means only {@link #USAGE_UNKNOWN},
475 * {@link #USAGE_MEDIA} and {@link #USAGE_GAME} may be captured.
476 *
477 * See {@link android.media.projection.MediaProjection} and
478 * {@link Builder#setAllowedCapturePolicy}.
479 */
480 public static final int ALLOW_CAPTURE_BY_ALL = 1;
481 /**
482 * Indicates that the audio may only be captured by system apps.
483 *
Kevin Rocarde5b29c92019-04-03 12:37:32 -0700484 * System apps can capture for many purposes like accessibility, live captions, user guidance...
Kevin Rocarda3a4bbb2019-03-07 18:29:48 -0800485 * but abide to the following restrictions:
Kevin Rocarde5b29c92019-04-03 12:37:32 -0700486 * - the audio cannot leave the device
487 * - the audio cannot be passed to a third party app
488 * - the audio cannot be recorded at a higher quality than 16kHz 16bit mono
Kevin Rocarda3a4bbb2019-03-07 18:29:48 -0800489 *
490 * See {@link Builder#setAllowedCapturePolicy}.
491 */
492 public static final int ALLOW_CAPTURE_BY_SYSTEM = 2;
493 /**
494 * Indicates that the audio is not to be recorded by any app, even if it is a system app.
495 *
496 * It is encouraged to use {@link #ALLOW_CAPTURE_BY_SYSTEM} instead of this value as system apps
497 * provide significant and useful features for the user (such as live captioning
498 * and accessibility).
499 *
500 * See {@link Builder#setAllowedCapturePolicy}.
501 */
502 public static final int ALLOW_CAPTURE_BY_NONE = 3;
503
504 /** @hide */
505 @IntDef({
506 ALLOW_CAPTURE_BY_ALL,
507 ALLOW_CAPTURE_BY_SYSTEM,
508 ALLOW_CAPTURE_BY_NONE,
509 })
510 @Retention(RetentionPolicy.SOURCE)
511 public @interface CapturePolicy {}
512
Mathew Inwood5d123b62020-11-04 09:29:36 +0000513 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700514 private int mUsage = USAGE_UNKNOWN;
Mathew Inwood8c854f82018-09-14 12:35:36 +0100515 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700516 private int mContentType = CONTENT_TYPE_UNKNOWN;
Mathew Inwood8c854f82018-09-14 12:35:36 +0100517 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Jean-Michel Trivi701d6ff2014-07-16 07:51:22 -0700518 private int mSource = MediaRecorder.AudioSource.AUDIO_SOURCE_INVALID;
Mathew Inwood8c854f82018-09-14 12:35:36 +0100519 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700520 private int mFlags = 0x0;
521 private HashSet<String> mTags;
Mathew Inwood5d123b62020-11-04 09:29:36 +0000522 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
Jean-Michel Trivia1d80e32014-06-18 08:18:41 -0700523 private String mFormattedTags;
Jean-Michel Trivif82f7462016-02-05 15:20:35 -0800524 private Bundle mBundle; // lazy-initialized, may be null
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700525
526 private AudioAttributes() {
527 }
528
529 /**
530 * Return the content type.
531 * @return one of the values that can be set in {@link Builder#setContentType(int)}
532 */
533 public int getContentType() {
534 return mContentType;
535 }
536
537 /**
538 * Return the usage.
539 * @return one of the values that can be set in {@link Builder#setUsage(int)}
540 */
541 public int getUsage() {
Hayden Gomesfe2c8772019-12-23 11:37:23 -0800542 if (isSystemUsage(mUsage)) {
543 return USAGE_UNKNOWN;
544 }
545 return mUsage;
546 }
547
548 /**
549 * @hide
550 * Return the system usage.
551 * @return one of the values that can be set in {@link Builder#setUsage(int)} or
552 * {@link Builder#setSystemUsage(int)}
553 */
554 @SystemApi
555 public int getSystemUsage() {
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700556 return mUsage;
557 }
558
559 /**
Jean-Michel Trivi701d6ff2014-07-16 07:51:22 -0700560 * @hide
Jean-Michel Trivi701d6ff2014-07-16 07:51:22 -0700561 * Return the capture preset.
562 * @return one of the values that can be set in {@link Builder#setCapturePreset(int)} or a
563 * negative value if none has been set.
564 */
Jean-Michel Trivi1b3541d2014-11-25 12:53:41 -0800565 @SystemApi
Jean-Michel Trivi701d6ff2014-07-16 07:51:22 -0700566 public int getCapturePreset() {
567 return mSource;
568 }
569
570 /**
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700571 * Return the flags.
572 * @return a combined mask of all flags
573 */
574 public int getFlags() {
575 // only return the flags that are public
Jean-Michel Trivi6894cd32014-07-21 16:06:33 -0700576 return (mFlags & (FLAG_ALL_PUBLIC));
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700577 }
578
579 /**
580 * @hide
581 * Return all the flags, even the non-public ones.
582 * Internal use only
583 * @return a combined mask of all flags
584 */
Eric Laurent00a00922015-03-09 09:25:45 -0700585 @SystemApi
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700586 public int getAllFlags() {
Jean-Michel Trivi6894cd32014-07-21 16:06:33 -0700587 return (mFlags & FLAG_ALL);
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700588 }
589
590 /**
Jean-Michel Trivib45c2732014-06-03 16:06:48 -0700591 * @hide
Jean-Michel Trivif82f7462016-02-05 15:20:35 -0800592 * Return the Bundle of data.
593 * @return a copy of the Bundle for this instance, may be null.
594 */
595 @SystemApi
596 public Bundle getBundle() {
597 if (mBundle == null) {
598 return mBundle;
599 } else {
600 return new Bundle(mBundle);
601 }
602 }
603
604 /**
605 * @hide
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700606 * Return the set of tags.
607 * @return a read-only set of all tags stored as strings.
608 */
609 public Set<String> getTags() {
610 return Collections.unmodifiableSet(mTags);
611 }
612
613 /**
jiabin41584392019-02-26 12:57:57 -0800614 * Return if haptic channels are muted.
615 * @return {@code true} if haptic channels are muted, {@code false} otherwise.
616 */
617 public boolean areHapticChannelsMuted() {
618 return (mFlags & FLAG_MUTE_HAPTIC) != 0;
619 }
620
621 /**
Kevin Rocard9bf75fa2019-04-09 16:25:26 -0700622 * Return the capture policy.
623 * @return the capture policy set by {@link Builder#setAllowedCapturePolicy(int)} or
624 * the default if it was not called.
625 */
626 @CapturePolicy
627 public int getAllowedCapturePolicy() {
628 if ((mFlags & FLAG_NO_SYSTEM_CAPTURE) == FLAG_NO_SYSTEM_CAPTURE) {
629 return ALLOW_CAPTURE_BY_NONE;
630 }
631 if ((mFlags & FLAG_NO_MEDIA_PROJECTION) == FLAG_NO_MEDIA_PROJECTION) {
632 return ALLOW_CAPTURE_BY_SYSTEM;
633 }
634 return ALLOW_CAPTURE_BY_ALL;
635 }
636
637
638 /**
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700639 * Builder class for {@link AudioAttributes} objects.
Jean-Michel Trivi04f55a492014-09-12 10:07:05 -0700640 * <p> Here is an example where <code>Builder</code> is used to define the
641 * {@link AudioAttributes} to be used by a new <code>AudioTrack</code> instance:
642 *
643 * <pre class="prettyprint">
644 * AudioTrack myTrack = new AudioTrack(
645 * new AudioAttributes.Builder()
646 * .setUsage(AudioAttributes.USAGE_MEDIA)
647 * .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
648 * .build(),
649 * myFormat, myBuffSize, AudioTrack.MODE_STREAM, mySession);
650 * </pre>
651 *
652 * <p>By default all types of information (usage, content type, flags) conveyed by an
653 * <code>AudioAttributes</code> instance are set to "unknown". Unknown information will be
654 * interpreted as a default value that is dependent on the context of use, for instance a
655 * {@link MediaPlayer} will use a default usage of {@link AudioAttributes#USAGE_MEDIA}.
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700656 */
657 public static class Builder {
Hayden Gomesfe2c8772019-12-23 11:37:23 -0800658 private int mUsage = USAGE_INVALID;
659 private int mSystemUsage = USAGE_INVALID;
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700660 private int mContentType = CONTENT_TYPE_UNKNOWN;
Jean-Michel Trivi701d6ff2014-07-16 07:51:22 -0700661 private int mSource = MediaRecorder.AudioSource.AUDIO_SOURCE_INVALID;
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700662 private int mFlags = 0x0;
Eric Laurentc9d353d2019-04-03 16:16:14 -0700663 private boolean mMuteHapticChannels = true;
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700664 private HashSet<String> mTags = new HashSet<String>();
Jean-Michel Trivif82f7462016-02-05 15:20:35 -0800665 private Bundle mBundle;
Eric Laurent64ed2ec2020-01-13 16:29:16 -0800666 private int mPrivacySensitive = PRIVACY_SENSITIVE_DEFAULT;
667
668 private static final int PRIVACY_SENSITIVE_DEFAULT = -1;
669 private static final int PRIVACY_SENSITIVE_DISABLED = 0;
670 private static final int PRIVACY_SENSITIVE_ENABLED = 1;
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700671
672 /**
673 * Constructs a new Builder with the defaults.
Jean-Michel Trivi04f55a492014-09-12 10:07:05 -0700674 * By default, usage and content type are respectively {@link AudioAttributes#USAGE_UNKNOWN}
675 * and {@link AudioAttributes#CONTENT_TYPE_UNKNOWN}, and flags are 0. It is recommended to
676 * configure the usage (with {@link #setUsage(int)}) or deriving attributes from a legacy
677 * stream type (with {@link #setLegacyStreamType(int)}) before calling {@link #build()}
678 * to override any default playback behavior in terms of routing and volume management.
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700679 */
680 public Builder() {
681 }
682
683 /**
684 * Constructs a new Builder from a given AudioAttributes
685 * @param aa the AudioAttributes object whose data will be reused in the new Builder.
686 */
687 @SuppressWarnings("unchecked") // for cloning of mTags
688 public Builder(AudioAttributes aa) {
689 mUsage = aa.mUsage;
690 mContentType = aa.mContentType;
jiabin1073ee62019-04-16 17:27:41 -0700691 mFlags = aa.getAllFlags();
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700692 mTags = (HashSet<String>) aa.mTags.clone();
jiabin1073ee62019-04-16 17:27:41 -0700693 mMuteHapticChannels = aa.areHapticChannelsMuted();
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700694 }
695
696 /**
697 * Combines all of the attributes that have been set and return a new
698 * {@link AudioAttributes} object.
699 * @return a new {@link AudioAttributes} object
700 */
701 @SuppressWarnings("unchecked") // for cloning of mTags
702 public AudioAttributes build() {
703 AudioAttributes aa = new AudioAttributes();
704 aa.mContentType = mContentType;
Hayden Gomesfe2c8772019-12-23 11:37:23 -0800705
706 if (mUsage == USAGE_INVALID) {
707 if (mSystemUsage == USAGE_INVALID) {
708 aa.mUsage = USAGE_UNKNOWN;
709 } else {
710 aa.mUsage = mSystemUsage;
711 }
712 } else {
713 if (mSystemUsage == USAGE_INVALID) {
714 aa.mUsage = mUsage;
715 } else {
716 throw new IllegalArgumentException(
717 "Cannot set both usage and system usage on same builder");
718 }
719 }
720
Jean-Michel Trivi701d6ff2014-07-16 07:51:22 -0700721 aa.mSource = mSource;
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700722 aa.mFlags = mFlags;
jiabin41584392019-02-26 12:57:57 -0800723 if (mMuteHapticChannels) {
724 aa.mFlags |= FLAG_MUTE_HAPTIC;
725 }
Eric Laurent64ed2ec2020-01-13 16:29:16 -0800726
727 if (mPrivacySensitive == PRIVACY_SENSITIVE_DEFAULT) {
728 // capturing for camcorder or communication is private by default to
729 // reflect legacy behavior
730 if (mSource == MediaRecorder.AudioSource.VOICE_COMMUNICATION
731 || mSource == MediaRecorder.AudioSource.CAMCORDER) {
732 aa.mFlags |= FLAG_CAPTURE_PRIVATE;
733 } else {
734 aa.mFlags &= ~FLAG_CAPTURE_PRIVATE;
735 }
736 } else if (mPrivacySensitive == PRIVACY_SENSITIVE_ENABLED) {
Eric Laurent597f0b5e2019-10-24 15:57:27 -0700737 aa.mFlags |= FLAG_CAPTURE_PRIVATE;
Eric Laurent64ed2ec2020-01-13 16:29:16 -0800738 } else {
739 aa.mFlags &= ~FLAG_CAPTURE_PRIVATE;
Eric Laurent597f0b5e2019-10-24 15:57:27 -0700740 }
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700741 aa.mTags = (HashSet<String>) mTags.clone();
Jean-Michel Trivicc58c762014-07-30 16:03:41 -0700742 aa.mFormattedTags = TextUtils.join(";", mTags);
Jean-Michel Trivif82f7462016-02-05 15:20:35 -0800743 if (mBundle != null) {
744 aa.mBundle = new Bundle(mBundle);
745 }
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700746 return aa;
747 }
748
749 /**
Hayden Gomes62812aa2019-12-23 11:40:27 -0800750 * Sets the attribute describing what is the intended use of the audio signal,
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700751 * such as alarm or ringtone.
Hayden Gomesfe2c8772019-12-23 11:37:23 -0800752 * @param usage one of {@link AttributeSdkUsage#USAGE_UNKNOWN},
753 * {@link AttributeSdkUsage#USAGE_MEDIA},
754 * {@link AttributeSdkUsage#USAGE_VOICE_COMMUNICATION},
755 * {@link AttributeSdkUsage#USAGE_VOICE_COMMUNICATION_SIGNALLING},
756 * {@link AttributeSdkUsage#USAGE_ALARM}, {@link AudioAttributes#USAGE_NOTIFICATION},
757 * {@link AttributeSdkUsage#USAGE_NOTIFICATION_RINGTONE},
758 * {@link AttributeSdkUsage#USAGE_NOTIFICATION_COMMUNICATION_REQUEST},
759 * {@link AttributeSdkUsage#USAGE_NOTIFICATION_COMMUNICATION_INSTANT},
760 * {@link AttributeSdkUsage#USAGE_NOTIFICATION_COMMUNICATION_DELAYED},
761 * {@link AttributeSdkUsage#USAGE_NOTIFICATION_EVENT},
762 * {@link AttributeSdkUsage#USAGE_ASSISTANT},
763 * {@link AttributeSdkUsage#USAGE_ASSISTANCE_ACCESSIBILITY},
764 * {@link AttributeSdkUsage#USAGE_ASSISTANCE_NAVIGATION_GUIDANCE},
765 * {@link AttributeSdkUsage#USAGE_ASSISTANCE_SONIFICATION},
766 * {@link AttributeSdkUsage#USAGE_GAME}.
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700767 * @return the same Builder instance.
768 */
Hayden Gomesfe2c8772019-12-23 11:37:23 -0800769 public Builder setUsage(@AttributeSdkUsage int usage) {
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700770 switch (usage) {
771 case USAGE_UNKNOWN:
772 case USAGE_MEDIA:
773 case USAGE_VOICE_COMMUNICATION:
774 case USAGE_VOICE_COMMUNICATION_SIGNALLING:
775 case USAGE_ALARM:
776 case USAGE_NOTIFICATION:
Jean-Michel Trivi89c3b292014-07-20 11:41:02 -0700777 case USAGE_NOTIFICATION_RINGTONE:
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700778 case USAGE_NOTIFICATION_COMMUNICATION_REQUEST:
779 case USAGE_NOTIFICATION_COMMUNICATION_INSTANT:
780 case USAGE_NOTIFICATION_COMMUNICATION_DELAYED:
781 case USAGE_NOTIFICATION_EVENT:
782 case USAGE_ASSISTANCE_ACCESSIBILITY:
783 case USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:
784 case USAGE_ASSISTANCE_SONIFICATION:
785 case USAGE_GAME:
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -0700786 case USAGE_VIRTUAL_SOURCE:
Jean-Michel Trivi0c8855d02016-12-29 10:33:29 -0800787 case USAGE_ASSISTANT:
Kevin Rocarda3a4bbb2019-03-07 18:29:48 -0800788 mUsage = usage;
789 break;
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700790 default:
Jean-Michel Trivid8aaf452019-10-16 15:09:37 -0700791 throw new IllegalArgumentException("Invalid usage " + usage);
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700792 }
793 return this;
794 }
795
796 /**
Hayden Gomesfe2c8772019-12-23 11:37:23 -0800797 * @hide
798 * Sets the attribute describing what is the intended use of the audio signal for categories
799 * of sounds restricted to the system, such as vehicle status or emergency.
800 *
801 * <p>Note that the AudioAttributes have a single usage value, therefore it is illegal to
802 * call both this method and {@link #setUsage(int)}.
803 * @param systemUsage the system-restricted usage.
804 * @return the same Builder instance.
805 */
806 @SystemApi
807 @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
808 public @NonNull Builder setSystemUsage(@AttributeSystemUsage int systemUsage) {
809 if (isSystemUsage(systemUsage)) {
810 mSystemUsage = systemUsage;
811 } else {
812 throw new IllegalArgumentException("Invalid system usage " + systemUsage);
813 }
814
815 return this;
816 }
817
818 /**
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700819 * Sets the attribute describing the content type of the audio signal, such as speech,
820 * or music.
821 * @param contentType the content type values, one of
822 * {@link AudioAttributes#CONTENT_TYPE_MOVIE},
823 * {@link AudioAttributes#CONTENT_TYPE_MUSIC},
824 * {@link AudioAttributes#CONTENT_TYPE_SONIFICATION},
825 * {@link AudioAttributes#CONTENT_TYPE_SPEECH},
826 * {@link AudioAttributes#CONTENT_TYPE_UNKNOWN}.
827 * @return the same Builder instance.
828 */
829 public Builder setContentType(@AttributeContentType int contentType) {
830 switch (contentType) {
831 case CONTENT_TYPE_UNKNOWN:
832 case CONTENT_TYPE_MOVIE:
833 case CONTENT_TYPE_MUSIC:
834 case CONTENT_TYPE_SONIFICATION:
835 case CONTENT_TYPE_SPEECH:
Sungsoo Lim00d0bb32018-11-22 13:50:31 +0900836 mContentType = contentType;
837 break;
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700838 default:
Jean-Michel Trivid8aaf452019-10-16 15:09:37 -0700839 throw new IllegalArgumentException("Invalid content type " + contentType);
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700840 }
841 return this;
842 }
843
844 /**
845 * Sets the combination of flags.
Andy Hungebc2c142017-01-12 19:20:29 -0800846 *
847 * This is a bitwise OR with the existing flags.
Jean-Michel Trivi26d2fdb2016-01-14 12:59:39 -0800848 * @param flags a combination of {@link AudioAttributes#FLAG_AUDIBILITY_ENFORCED},
849 * {@link AudioAttributes#FLAG_HW_AV_SYNC}.
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700850 * @return the same Builder instance.
851 */
852 public Builder setFlags(int flags) {
Jean-Michel Trivib097d9e2020-06-25 17:55:39 -0700853 flags &= AudioAttributes.FLAG_ALL_API_SET;
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700854 mFlags |= flags;
855 return this;
856 }
857
858 /**
Kevin Rocarddb0ff412019-05-02 17:55:35 -0700859 * Specifies whether the audio may or may not be captured by other apps or the system.
Kevin Rocarda3a4bbb2019-03-07 18:29:48 -0800860 *
861 * The default is {@link AudioAttributes#ALLOW_CAPTURE_BY_ALL}.
862 *
Kevin Rocard654b3cb2019-04-03 16:51:11 -0700863 * There are multiple ways to set this policy:
Kevin Rocarddb0ff412019-05-02 17:55:35 -0700864 * <ul>
865 * <li> for each track independently, with this method </li>
866 * <li> application-wide at runtime, with
867 * {@link AudioManager#setAllowedCapturePolicy(int)} </li>
868 * <li> application-wide at build time, see {@code allowAudioPlaybackCapture} in the
869 * application manifest. </li>
870 * </ul>
Kevin Rocard654b3cb2019-04-03 16:51:11 -0700871 * The most restrictive policy is always applied.
872 *
Kevin Rocarddb0ff412019-05-02 17:55:35 -0700873 * See {@link AudioPlaybackCaptureConfiguration} for more details on
Kevin Rocard654b3cb2019-04-03 16:51:11 -0700874 * which audio signals can be captured.
Kevin Rocarda3a4bbb2019-03-07 18:29:48 -0800875 *
Kevin Rocard9ce6e562019-02-05 15:45:26 -0800876 * @return the same Builder instance
Kevin Rocarda3a4bbb2019-03-07 18:29:48 -0800877 * @throws IllegalArgumentException if the argument is not a valid value.
Kevin Rocard9ce6e562019-02-05 15:45:26 -0800878 */
Kevin Rocarda3a4bbb2019-03-07 18:29:48 -0800879 public @NonNull Builder setAllowedCapturePolicy(@CapturePolicy int capturePolicy) {
Kevin Rocard7919c2a2019-03-21 10:28:01 -0700880 mFlags = capturePolicyToFlags(capturePolicy, mFlags);
Kevin Rocard9ce6e562019-02-05 15:45:26 -0800881 return this;
882 }
883
884 /**
Jean-Michel Trivib45c2732014-06-03 16:06:48 -0700885 * @hide
Andy Hungebc2c142017-01-12 19:20:29 -0800886 * Replaces flags.
887 * @param flags any combination of {@link AudioAttributes#FLAG_ALL}.
888 * @return the same Builder instance.
889 */
890 public Builder replaceFlags(int flags) {
891 mFlags = flags & AudioAttributes.FLAG_ALL;
892 return this;
893 }
894
895 /**
896 * @hide
Jean-Michel Trivif82f7462016-02-05 15:20:35 -0800897 * Adds a Bundle of data
898 * @param bundle a non-null Bundle
899 * @return the same builder instance
900 */
901 @SystemApi
902 public Builder addBundle(@NonNull Bundle bundle) {
903 if (bundle == null) {
904 throw new IllegalArgumentException("Illegal null bundle");
905 }
906 if (mBundle == null) {
907 mBundle = new Bundle(bundle);
908 } else {
909 mBundle.putAll(bundle);
910 }
911 return this;
912 }
913
914 /**
915 * @hide
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700916 * Add a custom tag stored as a string
917 * @param tag
918 * @return the same Builder instance.
919 */
Mathew Inwood473b9d52018-08-17 09:07:01 +0100920 @UnsupportedAppUsage
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700921 public Builder addTag(String tag) {
922 mTags.add(tag);
923 return this;
924 }
925
926 /**
Jean-Michel Trivi04f55a492014-09-12 10:07:05 -0700927 * Sets attributes as inferred from the legacy stream types.
Jean-Michel Trivi9f70d4e2019-04-23 16:49:50 -0700928 * Warning: do not use this method in combination with setting any other attributes such as
929 * usage, content type, flags or haptic control, as this method will overwrite (the more
930 * accurate) information describing the use case previously set in the <code>Builder</code>.
931 * In general, avoid using it and prefer setting usage and content type directly
932 * with {@link #setUsage(int)} and {@link #setContentType(int)}.
933 * <p>Use this method when building an {@link AudioAttributes} instance to initialize some
934 * of the attributes by information derived from a legacy stream type.
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700935 * @param streamType one of {@link AudioManager#STREAM_VOICE_CALL},
936 * {@link AudioManager#STREAM_SYSTEM}, {@link AudioManager#STREAM_RING},
937 * {@link AudioManager#STREAM_MUSIC}, {@link AudioManager#STREAM_ALARM},
938 * or {@link AudioManager#STREAM_NOTIFICATION}.
939 * @return the same Builder instance.
940 */
941 public Builder setLegacyStreamType(int streamType) {
Jean-Michel Trivi3f0945a2016-11-11 10:05:18 -0800942 if (streamType == AudioManager.STREAM_ACCESSIBILITY) {
943 throw new IllegalArgumentException("STREAM_ACCESSIBILITY is not a legacy stream "
944 + "type that was used for audio playback");
945 }
Jean-Michel Trivi9f70d4e2019-04-23 16:49:50 -0700946 setInternalLegacyStreamType(streamType);
947 return this;
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700948 }
949
950 /**
951 * @hide
952 * For internal framework use only, enables building from hidden stream types.
953 * @param streamType
954 * @return the same Builder instance.
955 */
Mathew Inwood473b9d52018-08-17 09:07:01 +0100956 @UnsupportedAppUsage
Jean-Michel Trivid60e8752014-04-18 09:47:08 -0700957 public Builder setInternalLegacyStreamType(int streamType) {
Eric Laurente6c89722019-05-01 14:24:40 -0700958 mContentType = CONTENT_TYPE_UNKNOWN;
959 mUsage = USAGE_UNKNOWN;
Hayden Gomes6d69bde2019-04-04 13:10:13 -0700960 if (AudioProductStrategy.getAudioProductStrategies().size() > 0) {
961 AudioAttributes attributes =
962 AudioProductStrategy.getAudioAttributesForStrategyWithLegacyStreamType(
963 streamType);
François Gaffiee6d280d2018-03-21 16:08:33 +0100964 if (attributes != null) {
Jean-Michel Trivi9f70d4e2019-04-23 16:49:50 -0700965 mUsage = attributes.mUsage;
966 mContentType = attributes.mContentType;
jiabina9b4f092019-08-01 15:41:20 -0700967 mFlags = attributes.getAllFlags();
Jean-Michel Trivi9f70d4e2019-04-23 16:49:50 -0700968 mMuteHapticChannels = attributes.areHapticChannelsMuted();
969 mTags = attributes.mTags;
970 mBundle = attributes.mBundle;
971 mSource = attributes.mSource;
François Gaffiee6d280d2018-03-21 16:08:33 +0100972 }
973 }
Eric Laurente6c89722019-05-01 14:24:40 -0700974 if (mContentType == CONTENT_TYPE_UNKNOWN) {
975 switch (streamType) {
976 case AudioSystem.STREAM_VOICE_CALL:
977 mContentType = CONTENT_TYPE_SPEECH;
978 break;
979 case AudioSystem.STREAM_SYSTEM_ENFORCED:
980 mFlags |= FLAG_AUDIBILITY_ENFORCED;
981 // intended fall through, attributes in common with STREAM_SYSTEM
982 case AudioSystem.STREAM_SYSTEM:
983 mContentType = CONTENT_TYPE_SONIFICATION;
984 break;
985 case AudioSystem.STREAM_RING:
986 mContentType = CONTENT_TYPE_SONIFICATION;
987 break;
988 case AudioSystem.STREAM_MUSIC:
989 mContentType = CONTENT_TYPE_MUSIC;
990 break;
991 case AudioSystem.STREAM_ALARM:
992 mContentType = CONTENT_TYPE_SONIFICATION;
993 break;
994 case AudioSystem.STREAM_NOTIFICATION:
995 mContentType = CONTENT_TYPE_SONIFICATION;
996 break;
997 case AudioSystem.STREAM_BLUETOOTH_SCO:
998 mContentType = CONTENT_TYPE_SPEECH;
999 mFlags |= FLAG_SCO;
1000 break;
1001 case AudioSystem.STREAM_DTMF:
1002 mContentType = CONTENT_TYPE_SONIFICATION;
1003 break;
1004 case AudioSystem.STREAM_TTS:
1005 mContentType = CONTENT_TYPE_SONIFICATION;
1006 mFlags |= FLAG_BEACON;
1007 break;
1008 case AudioSystem.STREAM_ACCESSIBILITY:
1009 mContentType = CONTENT_TYPE_SPEECH;
1010 break;
1011 default:
1012 Log.e(TAG, "Invalid stream type " + streamType + " for AudioAttributes");
1013 }
Jean-Michel Trivid60e8752014-04-18 09:47:08 -07001014 }
Eric Laurente6c89722019-05-01 14:24:40 -07001015 if (mUsage == USAGE_UNKNOWN) {
1016 mUsage = usageForStreamType(streamType);
1017 }
Jean-Michel Trivi701d6ff2014-07-16 07:51:22 -07001018 return this;
1019 }
1020
1021 /**
1022 * @hide
Jean-Michel Trivi701d6ff2014-07-16 07:51:22 -07001023 * Sets the capture preset.
1024 * Use this audio attributes configuration method when building an {@link AudioRecord}
1025 * instance with {@link AudioRecord#AudioRecord(AudioAttributes, AudioFormat, int)}.
1026 * @param preset one of {@link MediaRecorder.AudioSource#DEFAULT},
1027 * {@link MediaRecorder.AudioSource#MIC}, {@link MediaRecorder.AudioSource#CAMCORDER},
ragoa7cc59c2015-12-02 11:31:15 -08001028 * {@link MediaRecorder.AudioSource#VOICE_RECOGNITION},
Eric Laurent0016c5b2019-01-15 18:38:32 -08001029 * {@link MediaRecorder.AudioSource#VOICE_COMMUNICATION},
1030 * {@link MediaRecorder.AudioSource#UNPROCESSED} or
1031 * {@link MediaRecorder.AudioSource#VOICE_PERFORMANCE}
Jean-Michel Trivi701d6ff2014-07-16 07:51:22 -07001032 * @return the same Builder instance.
1033 */
Jean-Michel Trivi1b3541d2014-11-25 12:53:41 -08001034 @SystemApi
Jean-Michel Trivi701d6ff2014-07-16 07:51:22 -07001035 public Builder setCapturePreset(int preset) {
1036 switch (preset) {
1037 case MediaRecorder.AudioSource.DEFAULT:
1038 case MediaRecorder.AudioSource.MIC:
1039 case MediaRecorder.AudioSource.CAMCORDER:
1040 case MediaRecorder.AudioSource.VOICE_RECOGNITION:
1041 case MediaRecorder.AudioSource.VOICE_COMMUNICATION:
ragoa7cc59c2015-12-02 11:31:15 -08001042 case MediaRecorder.AudioSource.UNPROCESSED:
Eric Laurent0016c5b2019-01-15 18:38:32 -08001043 case MediaRecorder.AudioSource.VOICE_PERFORMANCE:
Jean-Michel Trivi701d6ff2014-07-16 07:51:22 -07001044 mSource = preset;
1045 break;
1046 default:
1047 Log.e(TAG, "Invalid capture preset " + preset + " for AudioAttributes");
1048 }
1049 return this;
1050 }
1051
1052 /**
1053 * @hide
Benson Huangce4483c2014-09-17 17:21:02 +08001054 * Same as {@link #setCapturePreset(int)} but authorizes the use of HOTWORD,
Eric Laurent0016c5b2019-01-15 18:38:32 -08001055 * REMOTE_SUBMIX, RADIO_TUNER, VOICE_DOWNLINK, VOICE_UPLINK, VOICE_CALL and ECHO_REFERENCE.
Jean-Michel Trivi701d6ff2014-07-16 07:51:22 -07001056 * @param preset
1057 * @return the same Builder instance.
1058 */
Eric Laurent00a00922015-03-09 09:25:45 -07001059 @SystemApi
Jean-Michel Trivi701d6ff2014-07-16 07:51:22 -07001060 public Builder setInternalCapturePreset(int preset) {
1061 if ((preset == MediaRecorder.AudioSource.HOTWORD)
Benson Huangce4483c2014-09-17 17:21:02 +08001062 || (preset == MediaRecorder.AudioSource.REMOTE_SUBMIX)
Nadav Bar33f4f682017-11-21 12:21:13 +02001063 || (preset == MediaRecorder.AudioSource.RADIO_TUNER)
1064 || (preset == MediaRecorder.AudioSource.VOICE_DOWNLINK)
1065 || (preset == MediaRecorder.AudioSource.VOICE_UPLINK)
Eric Laurent0016c5b2019-01-15 18:38:32 -08001066 || (preset == MediaRecorder.AudioSource.VOICE_CALL)
1067 || (preset == MediaRecorder.AudioSource.ECHO_REFERENCE)) {
Jean-Michel Trivi701d6ff2014-07-16 07:51:22 -07001068 mSource = preset;
1069 } else {
1070 setCapturePreset(preset);
1071 }
Jean-Michel Trivid60e8752014-04-18 09:47:08 -07001072 return this;
1073 }
jiabin41584392019-02-26 12:57:57 -08001074
1075 /**
1076 * Specifying if haptic should be muted or not when playing audio-haptic coupled data.
Eric Laurentc9d353d2019-04-03 16:16:14 -07001077 * By default, haptic channels are disabled.
jiabin41584392019-02-26 12:57:57 -08001078 * @param muted true to force muting haptic channels.
1079 * @return the same Builder instance.
1080 */
jiabin3b180112019-04-09 16:13:38 -07001081 public @NonNull Builder setHapticChannelsMuted(boolean muted) {
jiabin41584392019-02-26 12:57:57 -08001082 mMuteHapticChannels = muted;
1083 return this;
1084 }
Eric Laurent64ed2ec2020-01-13 16:29:16 -08001085
1086 /**
1087 * @hide
1088 * Indicates if an AudioRecord build with this AudioAttributes is privacy sensitive or not.
1089 * See {@link AudioRecord.Builder#setPrivacySensitive(boolean)}.
1090 * @param privacySensitive True if capture must be marked as privacy sensitive,
1091 * false otherwise.
1092 * @return the same Builder instance.
1093 */
1094 public @NonNull Builder setPrivacySensitive(boolean privacySensitive) {
1095 mPrivacySensitive =
1096 privacySensitive ? PRIVACY_SENSITIVE_ENABLED : PRIVACY_SENSITIVE_DISABLED;
1097 return this;
1098 }
Jean-Michel Trivid60e8752014-04-18 09:47:08 -07001099 };
1100
Jean-Michel Trivib45c2732014-06-03 16:06:48 -07001101 @Override
1102 public int describeContents() {
1103 return 0;
1104 }
1105
Jean-Michel Trivi8df982d2014-06-26 12:05:16 -07001106 /**
1107 * @hide
1108 * Used to indicate that when parcelling, the tags should be parcelled through the flattened
1109 * formatted string, not through the array of strings.
1110 * Keep in sync with frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp
1111 * see definition of kAudioAttributesMarshallTagFlattenTags
1112 */
1113 public final static int FLATTEN_TAGS = 0x1;
Jean-Michel Trivif82f7462016-02-05 15:20:35 -08001114
1115 private final static int ATTR_PARCEL_IS_NULL_BUNDLE = -1977;
1116 private final static int ATTR_PARCEL_IS_VALID_BUNDLE = 1980;
1117
Jean-Michel Trivi8df982d2014-06-26 12:05:16 -07001118 /**
1119 * When adding tags for writeToParcel(Parcel, int), add them in the list of flags (| NEW_FLAG)
1120 */
1121 private final static int ALL_PARCEL_FLAGS = FLATTEN_TAGS;
Jean-Michel Trivib45c2732014-06-03 16:06:48 -07001122 @Override
1123 public void writeToParcel(Parcel dest, int flags) {
1124 dest.writeInt(mUsage);
1125 dest.writeInt(mContentType);
Jean-Michel Trivi701d6ff2014-07-16 07:51:22 -07001126 dest.writeInt(mSource);
Jean-Michel Trivib45c2732014-06-03 16:06:48 -07001127 dest.writeInt(mFlags);
Jean-Michel Trivi8df982d2014-06-26 12:05:16 -07001128 dest.writeInt(flags & ALL_PARCEL_FLAGS);
1129 if ((flags & FLATTEN_TAGS) == 0) {
1130 String[] tagsArray = new String[mTags.size()];
1131 mTags.toArray(tagsArray);
1132 dest.writeStringArray(tagsArray);
1133 } else if ((flags & FLATTEN_TAGS) == FLATTEN_TAGS) {
1134 dest.writeString(mFormattedTags);
1135 }
Jean-Michel Trivif82f7462016-02-05 15:20:35 -08001136 if (mBundle == null) {
1137 dest.writeInt(ATTR_PARCEL_IS_NULL_BUNDLE);
1138 } else {
1139 dest.writeInt(ATTR_PARCEL_IS_VALID_BUNDLE);
1140 dest.writeBundle(mBundle);
1141 }
Jean-Michel Trivib45c2732014-06-03 16:06:48 -07001142 }
1143
1144 private AudioAttributes(Parcel in) {
1145 mUsage = in.readInt();
1146 mContentType = in.readInt();
Jean-Michel Trivi701d6ff2014-07-16 07:51:22 -07001147 mSource = in.readInt();
Jean-Michel Trivib45c2732014-06-03 16:06:48 -07001148 mFlags = in.readInt();
Jean-Michel Trivi8df982d2014-06-26 12:05:16 -07001149 boolean hasFlattenedTags = ((in.readInt() & FLATTEN_TAGS) == FLATTEN_TAGS);
Jean-Michel Trivib45c2732014-06-03 16:06:48 -07001150 mTags = new HashSet<String>();
Jean-Michel Trivi8df982d2014-06-26 12:05:16 -07001151 if (hasFlattenedTags) {
Jean-Michel Trivicc58c762014-07-30 16:03:41 -07001152 mFormattedTags = new String(in.readString());
1153 mTags.add(mFormattedTags);
Jean-Michel Trivi8df982d2014-06-26 12:05:16 -07001154 } else {
1155 String[] tagsArray = in.readStringArray();
1156 for (int i = tagsArray.length - 1 ; i >= 0 ; i--) {
1157 mTags.add(tagsArray[i]);
1158 }
Jean-Michel Trivicc58c762014-07-30 16:03:41 -07001159 mFormattedTags = TextUtils.join(";", mTags);
Jean-Michel Trivib45c2732014-06-03 16:06:48 -07001160 }
Jean-Michel Trivif82f7462016-02-05 15:20:35 -08001161 switch (in.readInt()) {
1162 case ATTR_PARCEL_IS_NULL_BUNDLE:
1163 mBundle = null;
1164 break;
1165 case ATTR_PARCEL_IS_VALID_BUNDLE:
1166 mBundle = new Bundle(in.readBundle());
1167 break;
1168 default:
1169 Log.e(TAG, "Illegal value unmarshalling AudioAttributes, can't initialize bundle");
1170 }
Jean-Michel Trivib45c2732014-06-03 16:06:48 -07001171 }
1172
Jeff Sharkey9e8f83d2019-02-28 12:06:45 -07001173 public static final @android.annotation.NonNull Parcelable.Creator<AudioAttributes> CREATOR
Jean-Michel Trivib45c2732014-06-03 16:06:48 -07001174 = new Parcelable.Creator<AudioAttributes>() {
1175 /**
1176 * Rebuilds an AudioAttributes previously stored with writeToParcel().
1177 * @param p Parcel object to read the AudioAttributes from
1178 * @return a new AudioAttributes created from the data in the parcel
1179 */
1180 public AudioAttributes createFromParcel(Parcel p) {
1181 return new AudioAttributes(p);
1182 }
1183 public AudioAttributes[] newArray(int size) {
1184 return new AudioAttributes[size];
1185 }
1186 };
1187
Jean-Michel Trivie9c19a52014-07-29 13:04:41 -07001188 @Override
1189 public boolean equals(Object o) {
1190 if (this == o) return true;
1191 if (o == null || getClass() != o.getClass()) return false;
1192
1193 AudioAttributes that = (AudioAttributes) o;
1194
1195 return ((mContentType == that.mContentType)
1196 && (mFlags == that.mFlags)
1197 && (mSource == that.mSource)
1198 && (mUsage == that.mUsage)
1199 //mFormattedTags is never null due to assignment in Builder or unmarshalling
1200 && (mFormattedTags.equals(that.mFormattedTags)));
1201 }
1202
1203 @Override
1204 public int hashCode() {
Jean-Michel Trivif82f7462016-02-05 15:20:35 -08001205 return Objects.hash(mContentType, mFlags, mSource, mUsage, mFormattedTags, mBundle);
Jean-Michel Trivie9c19a52014-07-29 13:04:41 -07001206 }
1207
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07001208 @Override
1209 public String toString () {
1210 return new String("AudioAttributes:"
Jean-Michel Trivi3120059d2017-08-28 12:40:55 -07001211 + " usage=" + usageToString()
1212 + " content=" + contentTypeToString()
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07001213 + " flags=0x" + Integer.toHexString(mFlags).toUpperCase()
Jean-Michel Trivif82f7462016-02-05 15:20:35 -08001214 + " tags=" + mFormattedTags
1215 + " bundle=" + (mBundle == null ? "null" : mBundle.toString()));
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07001216 }
1217
Jean-Michel Trivi998ff752014-07-11 10:01:00 -07001218 /** @hide */
Jeffrey Huangcb782852019-12-05 11:28:11 -08001219 public void dumpDebug(ProtoOutputStream proto, long fieldId) {
Kweku Adamsbc84aec2018-01-23 13:33:12 -08001220 final long token = proto.start(fieldId);
1221
Kweku Adams62b42242017-09-25 12:54:02 -07001222 proto.write(AudioAttributesProto.USAGE, mUsage);
1223 proto.write(AudioAttributesProto.CONTENT_TYPE, mContentType);
1224 proto.write(AudioAttributesProto.FLAGS, mFlags);
1225 // mFormattedTags is never null due to assignment in Builder or unmarshalling.
1226 for (String t : mFormattedTags.split(";")) {
1227 t = t.trim();
1228 if (t != "") {
1229 proto.write(AudioAttributesProto.TAGS, t);
1230 }
1231 }
1232 // TODO: is the data in mBundle useful for debugging?
Kweku Adamsbc84aec2018-01-23 13:33:12 -08001233
1234 proto.end(token);
Kweku Adams62b42242017-09-25 12:54:02 -07001235 }
1236
1237 /** @hide */
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07001238 public String usageToString() {
John Spurlock7b414672014-07-18 13:02:39 -04001239 return usageToString(mUsage);
1240 }
1241
1242 /** @hide */
1243 public static String usageToString(int usage) {
1244 switch(usage) {
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07001245 case USAGE_UNKNOWN:
1246 return new String("USAGE_UNKNOWN");
1247 case USAGE_MEDIA:
1248 return new String("USAGE_MEDIA");
1249 case USAGE_VOICE_COMMUNICATION:
1250 return new String("USAGE_VOICE_COMMUNICATION");
1251 case USAGE_VOICE_COMMUNICATION_SIGNALLING:
Zach Johnson45228bf2015-08-24 16:33:16 -07001252 return new String("USAGE_VOICE_COMMUNICATION_SIGNALLING");
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07001253 case USAGE_ALARM:
1254 return new String("USAGE_ALARM");
1255 case USAGE_NOTIFICATION:
1256 return new String("USAGE_NOTIFICATION");
Jean-Michel Trivi89c3b292014-07-20 11:41:02 -07001257 case USAGE_NOTIFICATION_RINGTONE:
Zach Johnson45228bf2015-08-24 16:33:16 -07001258 return new String("USAGE_NOTIFICATION_RINGTONE");
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07001259 case USAGE_NOTIFICATION_COMMUNICATION_REQUEST:
Zach Johnson45228bf2015-08-24 16:33:16 -07001260 return new String("USAGE_NOTIFICATION_COMMUNICATION_REQUEST");
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07001261 case USAGE_NOTIFICATION_COMMUNICATION_INSTANT:
1262 return new String("USAGE_NOTIFICATION_COMMUNICATION_INSTANT");
1263 case USAGE_NOTIFICATION_COMMUNICATION_DELAYED:
1264 return new String("USAGE_NOTIFICATION_COMMUNICATION_DELAYED");
1265 case USAGE_NOTIFICATION_EVENT:
1266 return new String("USAGE_NOTIFICATION_EVENT");
1267 case USAGE_ASSISTANCE_ACCESSIBILITY:
1268 return new String("USAGE_ASSISTANCE_ACCESSIBILITY");
1269 case USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:
1270 return new String("USAGE_ASSISTANCE_NAVIGATION_GUIDANCE");
1271 case USAGE_ASSISTANCE_SONIFICATION:
1272 return new String("USAGE_ASSISTANCE_SONIFICATION");
1273 case USAGE_GAME:
1274 return new String("USAGE_GAME");
Jean-Michel Trivi0c8855d02016-12-29 10:33:29 -08001275 case USAGE_ASSISTANT:
1276 return new String("USAGE_ASSISTANT");
Eric Laurent0eb901b2019-12-06 18:15:28 -08001277 case USAGE_CALL_ASSISTANT:
1278 return new String("USAGE_CALL_ASSISTANT");
Hayden Gomesfe2c8772019-12-23 11:37:23 -08001279 case USAGE_EMERGENCY:
1280 return new String("USAGE_EMERGENCY");
1281 case USAGE_SAFETY:
1282 return new String("USAGE_SAFETY");
1283 case USAGE_VEHICLE_STATUS:
1284 return new String("USAGE_VEHICLE_STATUS");
1285 case USAGE_ANNOUNCEMENT:
1286 return new String("USAGE_ANNOUNCEMENT");
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07001287 default:
John Spurlock7b414672014-07-18 13:02:39 -04001288 return new String("unknown usage " + usage);
1289 }
1290 }
1291
Hayden Gomesc164f6a2020-11-05 16:28:21 -08001292 /** @hide **/
1293 @TestApi
1294 @NonNull
1295 public static String usageToXsdString(@AttributeUsage int usage) {
1296 switch (usage) {
1297 case AudioAttributes.USAGE_UNKNOWN:
1298 return AudioUsage.AUDIO_USAGE_UNKNOWN.toString();
1299 case AudioAttributes.USAGE_MEDIA:
1300 return AudioUsage.AUDIO_USAGE_MEDIA.toString();
1301 case AudioAttributes.USAGE_VOICE_COMMUNICATION:
1302 return AudioUsage.AUDIO_USAGE_VOICE_COMMUNICATION.toString();
1303 case AudioAttributes.USAGE_VOICE_COMMUNICATION_SIGNALLING:
1304 return AudioUsage.AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING.toString();
1305 case AudioAttributes.USAGE_ALARM:
1306 return AudioUsage.AUDIO_USAGE_ALARM.toString();
1307 case AudioAttributes.USAGE_NOTIFICATION:
1308 return AudioUsage.AUDIO_USAGE_NOTIFICATION.toString();
1309 case AudioAttributes.USAGE_NOTIFICATION_RINGTONE:
1310 return AudioUsage.AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE.toString();
1311 case AudioAttributes.USAGE_ASSISTANCE_ACCESSIBILITY:
1312 return AudioUsage.AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY.toString();
1313 case AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:
1314 return AudioUsage.AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE.toString();
1315 case AudioAttributes.USAGE_ASSISTANCE_SONIFICATION:
1316 return AudioUsage.AUDIO_USAGE_ASSISTANCE_SONIFICATION.toString();
1317 case AudioAttributes.USAGE_GAME:
1318 return AudioUsage.AUDIO_USAGE_GAME.toString();
1319 case AudioAttributes.USAGE_VIRTUAL_SOURCE:
1320 return AudioUsage.AUDIO_USAGE_VIRTUAL_SOURCE.toString();
1321 case AudioAttributes.USAGE_ASSISTANT:
1322 return AudioUsage.AUDIO_USAGE_ASSISTANT.toString();
1323 case AudioAttributes.USAGE_CALL_ASSISTANT:
1324 return AudioUsage.AUDIO_USAGE_CALL_ASSISTANT.toString();
1325 case AudioAttributes.USAGE_EMERGENCY:
1326 return AudioUsage.AUDIO_USAGE_EMERGENCY.toString();
1327 case AudioAttributes.USAGE_SAFETY:
1328 return AudioUsage.AUDIO_USAGE_SAFETY.toString();
1329 case AudioAttributes.USAGE_VEHICLE_STATUS:
1330 return AudioUsage.AUDIO_USAGE_VEHICLE_STATUS.toString();
1331 case AudioAttributes.USAGE_ANNOUNCEMENT:
1332 return AudioUsage.AUDIO_USAGE_ANNOUNCEMENT.toString();
1333 default:
1334 Log.w(TAG, "Unknown usage value " + usage);
1335 return AudioUsage.AUDIO_USAGE_UNKNOWN.toString();
1336 }
1337 }
1338
1339 private static final Map<String, Integer> sXsdStringToUsage = new HashMap<>();
1340
1341 static {
1342 sXsdStringToUsage.put(AudioUsage.AUDIO_USAGE_UNKNOWN.toString(), USAGE_UNKNOWN);
1343 sXsdStringToUsage.put(AudioUsage.AUDIO_USAGE_UNKNOWN.toString(), USAGE_UNKNOWN);
1344 sXsdStringToUsage.put(AudioUsage.AUDIO_USAGE_MEDIA.toString(), USAGE_MEDIA);
1345 sXsdStringToUsage.put(AudioUsage.AUDIO_USAGE_VOICE_COMMUNICATION.toString(),
1346 USAGE_VOICE_COMMUNICATION);
1347 sXsdStringToUsage.put(AudioUsage.AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING.toString(),
1348 USAGE_VOICE_COMMUNICATION_SIGNALLING);
1349 sXsdStringToUsage.put(AudioUsage.AUDIO_USAGE_ALARM.toString(), USAGE_ALARM);
1350 sXsdStringToUsage.put(AudioUsage.AUDIO_USAGE_NOTIFICATION.toString(), USAGE_NOTIFICATION);
1351 sXsdStringToUsage.put(AudioUsage.AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE.toString(),
1352 USAGE_NOTIFICATION_RINGTONE);
1353 sXsdStringToUsage.put(AudioUsage.AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY.toString(),
1354 USAGE_ASSISTANCE_ACCESSIBILITY);
1355 sXsdStringToUsage.put(AudioUsage.AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE.toString(),
1356 USAGE_ASSISTANCE_NAVIGATION_GUIDANCE);
1357 sXsdStringToUsage.put(AudioUsage.AUDIO_USAGE_ASSISTANCE_SONIFICATION.toString(),
1358 USAGE_ASSISTANCE_SONIFICATION);
1359 sXsdStringToUsage.put(AudioUsage.AUDIO_USAGE_GAME.toString(), USAGE_GAME);
1360 sXsdStringToUsage.put(AudioUsage.AUDIO_USAGE_VIRTUAL_SOURCE.toString(),
1361 USAGE_VIRTUAL_SOURCE);
1362 sXsdStringToUsage.put(AudioUsage.AUDIO_USAGE_ASSISTANT.toString(), USAGE_ASSISTANT);
1363 sXsdStringToUsage.put(AudioUsage.AUDIO_USAGE_CALL_ASSISTANT.toString(),
1364 USAGE_CALL_ASSISTANT);
1365 sXsdStringToUsage.put(AudioUsage.AUDIO_USAGE_EMERGENCY.toString(), USAGE_EMERGENCY);
1366 sXsdStringToUsage.put(AudioUsage.AUDIO_USAGE_SAFETY.toString(), USAGE_SAFETY);
1367 sXsdStringToUsage.put(AudioUsage.AUDIO_USAGE_VEHICLE_STATUS.toString(),
1368 USAGE_VEHICLE_STATUS);
1369 sXsdStringToUsage.put(AudioUsage.AUDIO_USAGE_ANNOUNCEMENT.toString(), USAGE_ANNOUNCEMENT);
1370 }
1371
1372 /** @hide **/
1373 @TestApi
1374 public static @AttributeUsage int xsdStringToUsage(@NonNull String xsdUsage) {
1375 if (sXsdStringToUsage.containsKey(xsdUsage)) {
1376 return sXsdStringToUsage.get(xsdUsage);
1377 } else {
1378 Log.w(TAG, "Usage name not found in AudioUsage enum: " + xsdUsage);
1379 return USAGE_UNKNOWN;
1380 }
1381 }
1382
Jean-Michel Trivi3120059d2017-08-28 12:40:55 -07001383 /** @hide */
1384 public String contentTypeToString() {
1385 switch(mContentType) {
1386 case CONTENT_TYPE_UNKNOWN:
1387 return new String("CONTENT_TYPE_UNKNOWN");
1388 case CONTENT_TYPE_SPEECH: return new String("CONTENT_TYPE_SPEECH");
1389 case CONTENT_TYPE_MUSIC: return new String("CONTENT_TYPE_MUSIC");
1390 case CONTENT_TYPE_MOVIE: return new String("CONTENT_TYPE_MOVIE");
1391 case CONTENT_TYPE_SONIFICATION: return new String("CONTENT_TYPE_SONIFICATION");
1392 default: return new String("unknown content type " + mContentType);
1393 }
1394 }
1395
Jean-Michel Trivi3f0945a2016-11-11 10:05:18 -08001396 private static int usageForStreamType(int streamType) {
John Spurlock7b414672014-07-18 13:02:39 -04001397 switch(streamType) {
1398 case AudioSystem.STREAM_VOICE_CALL:
1399 return USAGE_VOICE_COMMUNICATION;
1400 case AudioSystem.STREAM_SYSTEM_ENFORCED:
1401 case AudioSystem.STREAM_SYSTEM:
1402 return USAGE_ASSISTANCE_SONIFICATION;
1403 case AudioSystem.STREAM_RING:
Jean-Michel Trivi89c3b292014-07-20 11:41:02 -07001404 return USAGE_NOTIFICATION_RINGTONE;
John Spurlock7b414672014-07-18 13:02:39 -04001405 case AudioSystem.STREAM_MUSIC:
1406 return USAGE_MEDIA;
1407 case AudioSystem.STREAM_ALARM:
1408 return USAGE_ALARM;
1409 case AudioSystem.STREAM_NOTIFICATION:
1410 return USAGE_NOTIFICATION;
1411 case AudioSystem.STREAM_BLUETOOTH_SCO:
1412 return USAGE_VOICE_COMMUNICATION;
1413 case AudioSystem.STREAM_DTMF:
1414 return USAGE_VOICE_COMMUNICATION_SIGNALLING;
Jean-Michel Trivi3f0945a2016-11-11 10:05:18 -08001415 case AudioSystem.STREAM_ACCESSIBILITY:
John Spurlock7b414672014-07-18 13:02:39 -04001416 return USAGE_ASSISTANCE_ACCESSIBILITY;
Jean-Michel Trivi3f0945a2016-11-11 10:05:18 -08001417 case AudioSystem.STREAM_TTS:
John Spurlock7b414672014-07-18 13:02:39 -04001418 default:
1419 return USAGE_UNKNOWN;
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07001420 }
1421 }
Jean-Michel Trivie67bc4d2017-03-27 11:52:18 -07001422
Jean-Michel Trivi3d22bf02015-02-03 10:15:08 -08001423 /**
Hayden Gomesfe2c8772019-12-23 11:37:23 -08001424 * @param usage one of {@link AttributeSystemUsage},
1425 * {@link AttributeSystemUsage#USAGE_CALL_ASSISTANT},
1426 * {@link AttributeSystemUsage#USAGE_EMERGENCY},
1427 * {@link AttributeSystemUsage#USAGE_SAFETY},
1428 * {@link AttributeSystemUsage#USAGE_VEHICLE_STATUS},
1429 * {@link AttributeSystemUsage#USAGE_ANNOUNCEMENT}
1430 * @return boolean indicating if the usage is a system usage or not
1431 * @hide
1432 */
1433 @SystemApi
1434 public static boolean isSystemUsage(@AttributeSystemUsage int usage) {
1435 return (usage == USAGE_CALL_ASSISTANT
1436 || usage == USAGE_EMERGENCY
1437 || usage == USAGE_SAFETY
1438 || usage == USAGE_VEHICLE_STATUS
1439 || usage == USAGE_ANNOUNCEMENT);
1440 }
1441
1442 /**
Jean-Michel Trivie67bc4d2017-03-27 11:52:18 -07001443 * Returns the stream type matching this {@code AudioAttributes} instance for volume control.
1444 * Use this method to derive the stream type needed to configure the volume
1445 * control slider in an {@link android.app.Activity} with
1446 * {@link android.app.Activity#setVolumeControlStream(int)} for playback conducted with these
1447 * attributes.
1448 * <BR>Do not use this method to set the stream type on an audio player object
1449 * (e.g. {@link AudioTrack}, {@link MediaPlayer}) as this is deprecated,
1450 * use {@code AudioAttributes} instead.
1451 * @return a valid stream type for {@code Activity} or stream volume control that matches
1452 * the attributes, or {@link AudioManager#USE_DEFAULT_STREAM_TYPE} if there isn't a direct
1453 * match. Note that {@code USE_DEFAULT_STREAM_TYPE} is not a valid value
1454 * for {@link AudioManager#setStreamVolume(int, int, int)}.
1455 */
1456 public int getVolumeControlStream() {
1457 return toVolumeStreamType(true /*fromGetVolumeControlStream*/, this);
1458 }
1459
1460 /**
Jean-Michel Trivi3d22bf02015-02-03 10:15:08 -08001461 * @hide
1462 * Only use to get which stream type should be used for volume control, NOT for audio playback
1463 * (all audio playback APIs are supposed to take AudioAttributes as input parameters)
1464 * @param aa non-null AudioAttributes.
1465 * @return a valid stream type for volume control that matches the attributes.
1466 */
Mathew Inwood473b9d52018-08-17 09:07:01 +01001467 @UnsupportedAppUsage
Jean-Michel Trivid1d5a0a2015-05-18 11:50:50 -07001468 public static int toLegacyStreamType(@NonNull AudioAttributes aa) {
1469 return toVolumeStreamType(false /*fromGetVolumeControlStream*/, aa);
1470 }
1471
1472 private static int toVolumeStreamType(boolean fromGetVolumeControlStream, AudioAttributes aa) {
Jean-Michel Trivi09818c12014-07-18 17:19:03 -07001473 // flags to stream type mapping
1474 if ((aa.getFlags() & FLAG_AUDIBILITY_ENFORCED) == FLAG_AUDIBILITY_ENFORCED) {
Jean-Michel Trivid1d5a0a2015-05-18 11:50:50 -07001475 return fromGetVolumeControlStream ?
1476 AudioSystem.STREAM_SYSTEM : AudioSystem.STREAM_SYSTEM_ENFORCED;
Jean-Michel Trivi09818c12014-07-18 17:19:03 -07001477 }
Par-Gunnar Hjalmdahl96e68bc2015-05-28 10:02:43 +02001478 if ((aa.getAllFlags() & FLAG_SCO) == FLAG_SCO) {
Jean-Michel Trivid1d5a0a2015-05-18 11:50:50 -07001479 return fromGetVolumeControlStream ?
1480 AudioSystem.STREAM_VOICE_CALL : AudioSystem.STREAM_BLUETOOTH_SCO;
Jean-Michel Trivi09818c12014-07-18 17:19:03 -07001481 }
Tomoharu Kasaharabe0103c2018-09-11 19:14:39 +09001482 if ((aa.getAllFlags() & FLAG_BEACON) == FLAG_BEACON) {
1483 return fromGetVolumeControlStream ?
1484 AudioSystem.STREAM_MUSIC : AudioSystem.STREAM_TTS;
1485 }
Jean-Michel Trivi09818c12014-07-18 17:19:03 -07001486
Hayden Gomes6d69bde2019-04-04 13:10:13 -07001487 if (AudioProductStrategy.getAudioProductStrategies().size() > 0) {
1488 return AudioProductStrategy.getLegacyStreamTypeForStrategyWithAudioAttributes(aa);
François Gaffiee6d280d2018-03-21 16:08:33 +01001489 }
Jean-Michel Trivi09818c12014-07-18 17:19:03 -07001490 // usage to stream type mapping
1491 switch (aa.getUsage()) {
1492 case USAGE_MEDIA:
1493 case USAGE_GAME:
Jean-Michel Trivi09818c12014-07-18 17:19:03 -07001494 case USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:
Jean-Michel Trivi0c8855d02016-12-29 10:33:29 -08001495 case USAGE_ASSISTANT:
Jean-Michel Trivi09818c12014-07-18 17:19:03 -07001496 return AudioSystem.STREAM_MUSIC;
1497 case USAGE_ASSISTANCE_SONIFICATION:
1498 return AudioSystem.STREAM_SYSTEM;
1499 case USAGE_VOICE_COMMUNICATION:
Eric Laurent0eb901b2019-12-06 18:15:28 -08001500 case USAGE_CALL_ASSISTANT:
Jean-Michel Trivi09818c12014-07-18 17:19:03 -07001501 return AudioSystem.STREAM_VOICE_CALL;
1502 case USAGE_VOICE_COMMUNICATION_SIGNALLING:
Jean-Michel Trivid1d5a0a2015-05-18 11:50:50 -07001503 return fromGetVolumeControlStream ?
1504 AudioSystem.STREAM_VOICE_CALL : AudioSystem.STREAM_DTMF;
Jean-Michel Trivi09818c12014-07-18 17:19:03 -07001505 case USAGE_ALARM:
1506 return AudioSystem.STREAM_ALARM;
Jean-Michel Trivi89c3b292014-07-20 11:41:02 -07001507 case USAGE_NOTIFICATION_RINGTONE:
Jean-Michel Trivi09818c12014-07-18 17:19:03 -07001508 return AudioSystem.STREAM_RING;
1509 case USAGE_NOTIFICATION:
1510 case USAGE_NOTIFICATION_COMMUNICATION_REQUEST:
1511 case USAGE_NOTIFICATION_COMMUNICATION_INSTANT:
1512 case USAGE_NOTIFICATION_COMMUNICATION_DELAYED:
1513 case USAGE_NOTIFICATION_EVENT:
1514 return AudioSystem.STREAM_NOTIFICATION;
Jean-Michel Trivi3f0945a2016-11-11 10:05:18 -08001515 case USAGE_ASSISTANCE_ACCESSIBILITY:
1516 return AudioSystem.STREAM_ACCESSIBILITY;
Hayden Gomesfe2c8772019-12-23 11:37:23 -08001517 case USAGE_EMERGENCY:
1518 case USAGE_SAFETY:
1519 case USAGE_VEHICLE_STATUS:
1520 case USAGE_ANNOUNCEMENT:
Jean-Michel Trivi09818c12014-07-18 17:19:03 -07001521 case USAGE_UNKNOWN:
Jean-Michel Trivi6d38a1b2018-04-09 10:54:36 -07001522 return AudioSystem.STREAM_MUSIC;
Jean-Michel Trivi09818c12014-07-18 17:19:03 -07001523 default:
Jean-Michel Trivid1d5a0a2015-05-18 11:50:50 -07001524 if (fromGetVolumeControlStream) {
1525 throw new IllegalArgumentException("Unknown usage value " + aa.getUsage() +
1526 " in audio attributes");
1527 } else {
1528 return AudioSystem.STREAM_MUSIC;
1529 }
Jean-Michel Trivi09818c12014-07-18 17:19:03 -07001530 }
1531 }
1532
jiabinb33f3692019-12-23 13:09:58 -08001533 /**
1534 * @hide
1535 */
1536 public static int capturePolicyToFlags(@CapturePolicy int capturePolicy, int flags) {
Kevin Rocard7919c2a2019-03-21 10:28:01 -07001537 switch (capturePolicy) {
1538 case ALLOW_CAPTURE_BY_NONE:
1539 flags |= FLAG_NO_MEDIA_PROJECTION | FLAG_NO_SYSTEM_CAPTURE;
1540 break;
1541 case ALLOW_CAPTURE_BY_SYSTEM:
1542 flags |= FLAG_NO_MEDIA_PROJECTION;
1543 flags &= ~FLAG_NO_SYSTEM_CAPTURE;
1544 break;
1545 case ALLOW_CAPTURE_BY_ALL:
1546 flags &= ~FLAG_NO_SYSTEM_CAPTURE & ~FLAG_NO_MEDIA_PROJECTION;
1547 break;
1548 default:
1549 throw new IllegalArgumentException("Unknown allow playback capture policy");
1550 }
1551 return flags;
1552 }
1553
Jean-Michel Trivi09818c12014-07-18 17:19:03 -07001554 /** @hide */
Jean-Michel Trivid60e8752014-04-18 09:47:08 -07001555 @IntDef({
Hayden Gomesfe2c8772019-12-23 11:37:23 -08001556 USAGE_CALL_ASSISTANT,
1557 USAGE_EMERGENCY,
1558 USAGE_SAFETY,
1559 USAGE_VEHICLE_STATUS,
1560 USAGE_ANNOUNCEMENT
1561 })
1562 @Retention(RetentionPolicy.SOURCE)
1563 public @interface AttributeSystemUsage {}
1564
1565 /** @hide */
1566 @IntDef({
1567 USAGE_UNKNOWN,
1568 USAGE_MEDIA,
1569 USAGE_VOICE_COMMUNICATION,
1570 USAGE_VOICE_COMMUNICATION_SIGNALLING,
1571 USAGE_ALARM,
1572 USAGE_NOTIFICATION,
1573 USAGE_NOTIFICATION_RINGTONE,
1574 USAGE_NOTIFICATION_COMMUNICATION_REQUEST,
1575 USAGE_NOTIFICATION_COMMUNICATION_INSTANT,
1576 USAGE_NOTIFICATION_COMMUNICATION_DELAYED,
1577 USAGE_NOTIFICATION_EVENT,
1578 USAGE_ASSISTANCE_ACCESSIBILITY,
1579 USAGE_ASSISTANCE_NAVIGATION_GUIDANCE,
1580 USAGE_ASSISTANCE_SONIFICATION,
1581 USAGE_GAME,
1582 USAGE_ASSISTANT,
1583 })
1584 @Retention(RetentionPolicy.SOURCE)
1585 public @interface AttributeSdkUsage {}
1586
1587 /** @hide */
1588 @IntDef({
Jean-Michel Trivid60e8752014-04-18 09:47:08 -07001589 USAGE_UNKNOWN,
1590 USAGE_MEDIA,
1591 USAGE_VOICE_COMMUNICATION,
1592 USAGE_VOICE_COMMUNICATION_SIGNALLING,
1593 USAGE_ALARM,
1594 USAGE_NOTIFICATION,
Jean-Michel Trivi89c3b292014-07-20 11:41:02 -07001595 USAGE_NOTIFICATION_RINGTONE,
Jean-Michel Trivid60e8752014-04-18 09:47:08 -07001596 USAGE_NOTIFICATION_COMMUNICATION_REQUEST,
1597 USAGE_NOTIFICATION_COMMUNICATION_INSTANT,
1598 USAGE_NOTIFICATION_COMMUNICATION_DELAYED,
1599 USAGE_NOTIFICATION_EVENT,
1600 USAGE_ASSISTANCE_ACCESSIBILITY,
1601 USAGE_ASSISTANCE_NAVIGATION_GUIDANCE,
1602 USAGE_ASSISTANCE_SONIFICATION,
Jean-Michel Trivi0c8855d02016-12-29 10:33:29 -08001603 USAGE_GAME,
1604 USAGE_ASSISTANT,
Eric Laurent0eb901b2019-12-06 18:15:28 -08001605 USAGE_CALL_ASSISTANT,
Hayden Gomesfe2c8772019-12-23 11:37:23 -08001606 USAGE_EMERGENCY,
1607 USAGE_SAFETY,
1608 USAGE_VEHICLE_STATUS,
1609 USAGE_ANNOUNCEMENT,
Jean-Michel Trivid60e8752014-04-18 09:47:08 -07001610 })
1611 @Retention(RetentionPolicy.SOURCE)
1612 public @interface AttributeUsage {}
1613
1614 /** @hide */
1615 @IntDef({
1616 CONTENT_TYPE_UNKNOWN,
1617 CONTENT_TYPE_SPEECH,
1618 CONTENT_TYPE_MUSIC,
1619 CONTENT_TYPE_MOVIE,
1620 CONTENT_TYPE_SONIFICATION
1621 })
1622 @Retention(RetentionPolicy.SOURCE)
1623 public @interface AttributeContentType {}
1624}