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