• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.compat.annotation.UnsupportedAppUsage;
20 import android.os.Build;
21 
22 import java.util.ArrayList;
23 import java.util.Arrays;
24 import java.util.HashSet;
25 import java.util.List;
26 import java.util.Set;
27 import java.util.stream.Collectors;
28 
29 /**
30  * An audio port is a node of the audio framework or hardware that can be connected to or
31  * disconnect from another audio node to create a specific audio routing configuration.
32  * Examples of audio ports are an output device (speaker) or an output mix (see AudioMixPort).
33  * All attributes that are relevant for applications to make routing selection are described
34  * in an AudioPort,  in particular:
35  * - possible channel mask configurations.
36  * - audio format (PCM 16bit, PCM 24bit...)
37  * - gain: a port can be associated with one or more gain controllers (see AudioGain).
38  *
39  * This object is always created by the framework and read only by applications.
40  * A list of all audio port descriptors currently available for applications to control
41  * is obtained by AudioManager.listAudioPorts().
42  * An application can obtain an AudioPortConfig for a valid configuration of this port
43  * by calling AudioPort.buildConfig() and use this configuration
44  * to create a connection between audio sinks and sources with AudioManager.connectAudioPatch()
45  *
46  * @hide
47  */
48 public class AudioPort {
49     private static final String TAG = "AudioPort";
50 
51     /**
52      * For use by the audio framework.
53      */
54     public static final int ROLE_NONE = 0;
55     /**
56      * The audio port is a source (produces audio)
57      */
58     public static final int ROLE_SOURCE = 1;
59     /**
60      * The audio port is a sink (consumes audio)
61      */
62     public static final int ROLE_SINK = 2;
63 
64     /**
65      * audio port type for use by audio framework implementation
66      */
67     public static final int TYPE_NONE = 0;
68     /**
69      */
70     public static final int TYPE_DEVICE = 1;
71     /**
72      */
73     public static final int TYPE_SUBMIX = 2;
74     /**
75      */
76     public static final int TYPE_SESSION = 3;
77 
78 
79     @UnsupportedAppUsage
80     AudioHandle mHandle;
81     @UnsupportedAppUsage
82     protected final int mRole;
83     private final String mName;
84     private final int[] mSamplingRates;
85     private final int[] mChannelMasks;
86     private final int[] mChannelIndexMasks;
87     private final int[] mFormats;
88     private final List<AudioProfile> mProfiles;
89     private final List<AudioDescriptor> mDescriptors;
90     @UnsupportedAppUsage
91     private final AudioGain[] mGains;
92     @UnsupportedAppUsage
93     private AudioPortConfig mActiveConfig;
94 
95     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
AudioPort(AudioHandle handle, int role, String name, int[] samplingRates, int[] channelMasks, int[] channelIndexMasks, int[] formats, AudioGain[] gains)96     AudioPort(AudioHandle handle, int role, String name,
97             int[] samplingRates, int[] channelMasks, int[] channelIndexMasks,
98             int[] formats, AudioGain[] gains) {
99         mHandle = handle;
100         mRole = role;
101         mName = name;
102         mSamplingRates = samplingRates;
103         mChannelMasks = channelMasks;
104         mChannelIndexMasks = channelIndexMasks;
105         mFormats = formats;
106         mGains = gains;
107         mProfiles = new ArrayList<>();
108         if (mFormats != null) {
109             for (int format : mFormats) {
110                 mProfiles.add(new AudioProfile(
111                         format, samplingRates, channelMasks, channelIndexMasks,
112                         AudioProfile.AUDIO_ENCAPSULATION_TYPE_NONE));
113             }
114         }
115         mDescriptors = new ArrayList<>();
116     }
117 
AudioPort(AudioHandle handle, int role, String name, List<AudioProfile> profiles, AudioGain[] gains, List<AudioDescriptor> descriptors)118     AudioPort(AudioHandle handle, int role, String name,
119               List<AudioProfile> profiles, AudioGain[] gains,
120               List<AudioDescriptor> descriptors) {
121         mHandle = handle;
122         mRole = role;
123         mName = name;
124         mProfiles = profiles;
125         mDescriptors = descriptors;
126         mGains = gains;
127         Set<Integer> formats = new HashSet<>();
128         Set<Integer> samplingRates = new HashSet<>();
129         Set<Integer> channelMasks = new HashSet<>();
130         Set<Integer> channelIndexMasks = new HashSet<>();
131         for (AudioProfile profile : profiles) {
132             formats.add(profile.getFormat());
133             samplingRates.addAll(Arrays.stream(profile.getSampleRates()).boxed()
134                     .collect(Collectors.toList()));
135             channelMasks.addAll(Arrays.stream(profile.getChannelMasks()).boxed()
136                     .collect(Collectors.toList()));
137             channelIndexMasks.addAll(Arrays.stream(profile.getChannelIndexMasks()).boxed()
138                     .collect(Collectors.toList()));
139         }
140         mSamplingRates = samplingRates.stream().mapToInt(Number::intValue).toArray();
141         mChannelMasks = channelMasks.stream().mapToInt(Number::intValue).toArray();
142         mChannelIndexMasks = channelIndexMasks.stream().mapToInt(Number::intValue).toArray();
143         mFormats = formats.stream().mapToInt(Number::intValue).toArray();
144     }
145 
handle()146     AudioHandle handle() {
147         return mHandle;
148     }
149 
150     /**
151      * Get the system unique device ID.
152      */
153     @UnsupportedAppUsage
id()154     public int id() {
155         return mHandle.id();
156     }
157 
158 
159     /**
160      * Get the audio port role
161      */
162     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
role()163     public int role() {
164         return mRole;
165     }
166 
167     /**
168      * Get the human-readable name of this port. Perhaps an internal
169      * designation or an physical device.
170      */
name()171     public String name() {
172         return mName;
173     }
174 
175     /**
176      * Get the list of supported sampling rates
177      * Empty array if sampling rate is not relevant for this audio port
178      */
samplingRates()179     public int[] samplingRates() {
180         return mSamplingRates;
181     }
182 
183     /**
184      * Get the list of supported channel mask configurations
185      * (e.g AudioFormat.CHANNEL_OUT_STEREO)
186      * Empty array if channel mask is not relevant for this audio port
187      */
channelMasks()188     public int[] channelMasks() {
189         return mChannelMasks;
190     }
191 
192     /**
193      * Get the list of supported channel index mask configurations
194      * (e.g 0x0003 means 2 channel, 0x000F means 4 channel....)
195      * Empty array if channel index mask is not relevant for this audio port
196      */
channelIndexMasks()197     public int[] channelIndexMasks() {
198         return mChannelIndexMasks;
199     }
200 
201     /**
202      * Get the list of supported audio format configurations
203      * (e.g AudioFormat.ENCODING_PCM_16BIT)
204      * Empty array if format is not relevant for this audio port
205      */
formats()206     public int[] formats() {
207         return mFormats;
208     }
209 
210     /**
211      * Get the list of supported audio profiles
212      */
profiles()213     public List<AudioProfile> profiles() {
214         return mProfiles;
215     }
216 
217     /**
218      * Get the list of audio descriptor
219      */
audioDescriptors()220     public List<AudioDescriptor> audioDescriptors() {
221         return mDescriptors;
222     }
223 
224     /**
225      * Get the list of gain descriptors
226      * Empty array if this port does not have gain control
227      */
gains()228     public AudioGain[] gains() {
229         return mGains;
230     }
231 
232     /**
233      * Get the gain descriptor at a given index
234      */
gain(int index)235     AudioGain gain(int index) {
236         if (index < 0 || index >= mGains.length) {
237             return null;
238         }
239         return mGains[index];
240     }
241 
242     /**
243      * Build a specific configuration of this audio port for use by methods
244      * like AudioManager.connectAudioPatch().
245      * @param samplingRate
246      * @param channelMask The desired channel mask. AudioFormat.CHANNEL_OUT_DEFAULT if no change
247      * from active configuration requested.
248      * @param format The desired audio format. AudioFormat.ENCODING_DEFAULT if no change
249      * from active configuration requested.
250      * @param gain The desired gain. null if no gain changed requested.
251      */
buildConfig(int samplingRate, int channelMask, int format, AudioGainConfig gain)252     public AudioPortConfig buildConfig(int samplingRate, int channelMask, int format,
253                                         AudioGainConfig gain) {
254         return new AudioPortConfig(this, samplingRate, channelMask, format, gain);
255     }
256 
257     /**
258      * Get currently active configuration of this audio port.
259      */
activeConfig()260     public AudioPortConfig activeConfig() {
261         return mActiveConfig;
262     }
263 
264     @Override
equals(Object o)265     public boolean equals(Object o) {
266         if (o == null || !(o instanceof AudioPort)) {
267             return false;
268         }
269         AudioPort ap = (AudioPort)o;
270         return mHandle.equals(ap.handle());
271     }
272 
273     @Override
hashCode()274     public int hashCode() {
275         return mHandle.hashCode();
276     }
277 
278     @Override
toString()279     public String toString() {
280         String role = Integer.toString(mRole);
281         switch (mRole) {
282             case ROLE_NONE:
283                 role = "NONE";
284                 break;
285             case ROLE_SOURCE:
286                 role = "SOURCE";
287                 break;
288             case ROLE_SINK:
289                 role = "SINK";
290                 break;
291         }
292         return "{mHandle: " + mHandle
293                 + ", mRole: " + role
294                 + "}";
295     }
296 }
297