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