1 /* 2 * Copyright (C) 2020 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.NonNull; 21 22 import java.lang.annotation.Retention; 23 import java.lang.annotation.RetentionPolicy; 24 import java.util.Arrays; 25 import java.util.stream.Collectors; 26 27 /** 28 * An AudioProfile is specific to an audio format and lists supported sampling rates and 29 * channel masks for that format. An {@link AudioDeviceInfo} has a list of supported AudioProfiles. 30 * There can be multiple profiles whose encoding format is the same. This usually happens when 31 * an encoding format is only supported when it is encapsulated by some particular encapsulation 32 * types. If there are multiple encapsulation types that can carry this encoding format, they will 33 * be reported in different audio profiles. The application can choose any of the encapsulation 34 * types. 35 */ 36 public class AudioProfile { 37 /** 38 * No encapsulation type is specified. 39 */ 40 public static final int AUDIO_ENCAPSULATION_TYPE_NONE = 0; 41 /** 42 * Encapsulation format is defined in standard IEC 61937. 43 */ 44 public static final int AUDIO_ENCAPSULATION_TYPE_IEC61937 = 1; 45 46 /** @hide */ 47 @IntDef({ 48 AUDIO_ENCAPSULATION_TYPE_NONE, 49 AUDIO_ENCAPSULATION_TYPE_IEC61937, 50 }) 51 @Retention(RetentionPolicy.SOURCE) 52 public @interface EncapsulationType {} 53 54 private final int mFormat; 55 private final int[] mSamplingRates; 56 private final int[] mChannelMasks; 57 private final int[] mChannelIndexMasks; 58 private final int mEncapsulationType; 59 AudioProfile(int format, @NonNull int[] samplingRates, @NonNull int[] channelMasks, @NonNull int[] channelIndexMasks, int encapsulationType)60 AudioProfile(int format, @NonNull int[] samplingRates, @NonNull int[] channelMasks, 61 @NonNull int[] channelIndexMasks, 62 int encapsulationType) { 63 mFormat = format; 64 mSamplingRates = samplingRates; 65 mChannelMasks = channelMasks; 66 mChannelIndexMasks = channelIndexMasks; 67 mEncapsulationType = encapsulationType; 68 } 69 70 /** 71 * @return the encoding format for this AudioProfile. 72 */ getFormat()73 public @AudioFormat.Encoding int getFormat() { 74 return mFormat; 75 } 76 77 /** 78 * @return an array of channel position masks that are associated with the encoding format. 79 */ getChannelMasks()80 public @NonNull int[] getChannelMasks() { 81 return mChannelMasks; 82 } 83 84 /** 85 * @return an array of channel index masks that are associated with the encoding format. 86 */ getChannelIndexMasks()87 public @NonNull int[] getChannelIndexMasks() { 88 return mChannelIndexMasks; 89 } 90 91 /** 92 * @return an array of sample rates that are associated with the encoding format. 93 */ getSampleRates()94 public @NonNull int[] getSampleRates() { 95 return mSamplingRates; 96 } 97 98 /** 99 * The encapsulation type indicates what encapsulation type is required when the framework is 100 * using this format when playing to a device exposing this audio profile. 101 * When encapsulation is required, only playback with {@link android.media.AudioTrack} API is 102 * supported. But playback with {@link android.media.MediaPlayer} is not. 103 * When an encapsulation type is required, the {@link AudioFormat} encoding selected when 104 * creating the {@link AudioTrack} must match the encapsulation type, e.g 105 * AudioFormat.ENCODING_IEC61937 for AUDIO_ENCAPSULATION_TYPE_IEC61937. 106 * 107 * @return an integer representing the encapsulation type 108 * 109 * @see #AUDIO_ENCAPSULATION_TYPE_NONE 110 * @see #AUDIO_ENCAPSULATION_TYPE_IEC61937 111 */ getEncapsulationType()112 public @EncapsulationType int getEncapsulationType() { 113 return mEncapsulationType; 114 } 115 116 @Override toString()117 public String toString() { 118 StringBuilder sb = new StringBuilder("{"); 119 sb.append(AudioFormat.toLogFriendlyEncoding(mFormat)); 120 if (mSamplingRates != null && mSamplingRates.length > 0) { 121 sb.append(", sampling rates=").append(Arrays.toString(mSamplingRates)); 122 } 123 if (mChannelMasks != null && mChannelMasks.length > 0) { 124 sb.append(", channel masks=").append(toHexString(mChannelMasks)); 125 } 126 if (mChannelIndexMasks != null && mChannelIndexMasks.length > 0) { 127 sb.append(", channel index masks=").append(Arrays.toString(mChannelIndexMasks)); 128 } 129 sb.append("}"); 130 return sb.toString(); 131 } 132 toHexString(int[] ints)133 private static String toHexString(int[] ints) { 134 if (ints == null || ints.length == 0) { 135 return ""; 136 } 137 return Arrays.stream(ints).mapToObj(anInt -> String.format("0x%02X", anInt)) 138 .collect(Collectors.joining(", ")); 139 } 140 } 141