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