1 /* 2 * Copyright (C) 2015 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 #pragma once 18 19 #include "DeviceDescriptor.h" 20 #include "PolicyAudioPort.h" 21 #include "policy.h" 22 #include <media/AudioContainers.h> 23 #include <utils/String8.h> 24 #include <system/audio.h> 25 26 namespace android { 27 28 class HwModule; 29 30 // the IOProfile class describes the capabilities of an output or input stream. 31 // It is currently assumed that all combination of listed parameters are supported. 32 // It is used by the policy manager to determine if an output or input is suitable for 33 // a given use case, open/close it accordingly and connect/disconnect audio tracks 34 // to/from it. 35 class IOProfile : public AudioPort, public PolicyAudioPort 36 { 37 public: 38 IOProfile(const std::string &name, audio_port_role_t role); 39 40 virtual ~IOProfile() = default; 41 42 // For a Profile aka MixPort, tag name and name are equivalent. getTagName()43 virtual const std::string getTagName() const { return getName(); } 44 addAudioProfile(const sp<AudioProfile> & profile)45 virtual void addAudioProfile(const sp<AudioProfile> &profile) { 46 addAudioProfileAndSort(mProfiles, profile); 47 } 48 asAudioPort()49 virtual sp<AudioPort> asAudioPort() const { 50 return static_cast<AudioPort*>(const_cast<IOProfile*>(this)); 51 } 52 53 // FIXME: this is needed because shared MMAP stream clients use the same audio session. 54 // Once capture clients are tracked individually and not per session this can be removed 55 // MMAP no IRQ input streams do not have the default limitation of one active client 56 // max as they can be used in shared mode by the same application. 57 // NOTE: Please consider moving to AudioPort when addressing the FIXME 58 // NOTE: this works for explicit values set in audio_policy_configuration.xml because 59 // flags are parsed before maxActiveCount by the serializer. setFlags(uint32_t flags)60 void setFlags(uint32_t flags) override 61 { 62 AudioPort::setFlags(flags); 63 if (getRole() == AUDIO_PORT_ROLE_SINK && (flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0) { 64 maxActiveCount = 0; 65 } 66 refreshMixerBehaviors(); 67 } 68 getMixerBehaviors()69 const MixerBehaviorSet& getMixerBehaviors() const { 70 return mMixerBehaviors; 71 } 72 73 /** 74 * NO_MATCH: Both config and flags are not compatible. 75 * PARTIAL_MATCH: Both config and flags are partially matched. 76 * PARTIAL_MATCH_WITH_CONFIG: Partial match with flags(e.g. fast flags) and exact match with 77 * config. 78 * PARTIAL_MATCH_WITH_FLAG: Partial match with config and exact match with flags. 79 * EXACT_MATCH: Both config and flags are exactly matched. 80 */ 81 enum CompatibilityScore{ 82 NO_MATCH = 0, 83 PARTIAL_MATCH = 1, 84 PARTIAL_MATCH_WITH_CONFIG = 2, 85 PARTIAL_MATCH_WITH_FLAG = 3, 86 EXACT_MATCH = 4 87 }; 88 89 /** 90 * @brief compatibilityScore: This method is used for input and direct output, 91 * and is not used for other output. 92 * Return the compatibility score to measure how much the IO profile is compatible 93 * with specified parameters. 94 * For input, flags is interpreted as audio_input_flags_t. 95 * TODO: merge audio_output_flags_t and audio_input_flags_t. 96 * 97 * @param devices vector of devices to be checked for compatibility 98 * @param samplingRate to be checked for compatibility. Must be specified 99 * @param updatedSamplingRate if non-NULL, it is assigned the actual sample rate. 100 * @param format to be checked for compatibility. Must be specified 101 * @param updatedFormat if non-NULL, it is assigned the actual format 102 * @param channelMask to be checked for compatibility. Must be specified 103 * @param updatedChannelMask if non-NULL, it is assigned the actual channel mask 104 * @param flags to be checked for compatibility 105 * @return how the IO profile is compatible with the given parameters. 106 */ 107 CompatibilityScore getCompatibilityScore(const DeviceVector &devices, 108 uint32_t samplingRate, 109 uint32_t *updatedSamplingRate, 110 audio_format_t format, 111 audio_format_t *updatedFormat, 112 audio_channel_mask_t channelMask, 113 audio_channel_mask_t *updatedChannelMask, 114 // FIXME parameter type 115 uint32_t flags) const; 116 117 /** 118 * @brief areAllDevicesSupported: Checks if the given devices are supported by the IO profile. 119 * 120 * @param devices vector of devices to be checked for compatibility 121 * @return true if all devices are supported, false otherwise. 122 */ 123 bool areAllDevicesSupported(const DeviceVector &devices) const; 124 125 /** 126 * @brief isCompatibleProfileForFlags: Checks if the IO profile is compatible with 127 * specified flags. 128 * 129 * @param flags to be checked for compatibility 130 * @return true if the profile is compatible, false otherwise. 131 */ 132 bool isCompatibleProfileForFlags(uint32_t flags) const; 133 134 void dump(String8 *dst, int spaces) const; 135 void log(); 136 hasSupportedDevices()137 bool hasSupportedDevices() const { return !mSupportedDevices.isEmpty(); } 138 supportsDeviceTypes(const DeviceTypeSet & deviceTypes)139 bool supportsDeviceTypes(const DeviceTypeSet& deviceTypes) const 140 { 141 const bool areOutputDevices = Intersection(deviceTypes, getAudioDeviceInAllSet()).empty(); 142 const bool devicesSupported = !mSupportedDevices.getDevicesFromTypes(deviceTypes).empty(); 143 return devicesSupported && 144 (!areOutputDevices || devicesSupportEncodedFormats(deviceTypes)); 145 } 146 147 /** 148 * @brief getTag 149 * @param deviceTypes to be considered 150 * @return tagName of first matching device for the considered types, empty string otherwise. 151 */ getTag(const DeviceTypeSet & deviceTypes)152 std::string getTag(const DeviceTypeSet& deviceTypes) const 153 { 154 if (supportsDeviceTypes(deviceTypes)) { 155 return mSupportedDevices.getDevicesFromTypes(deviceTypes).itemAt(0)->getTagName(); 156 } 157 return {}; 158 } 159 160 /** 161 * @brief supportsDevice 162 * @param device to be checked against 163 * forceCheckOnAddress if true, check on type and address whatever the type, otherwise 164 * the address enforcement is limited to "offical devices" that distinguishe on address 165 * @return true if the device is supported by type (for non bus / remote submix devices), 166 * true if the device is supported (both type and address) for bus / remote submix 167 * false otherwise 168 */ 169 bool supportsDevice(const sp<DeviceDescriptor> &device, bool forceCheckOnAddress = false) const 170 { 171 if (!device_distinguishes_on_address(device->type()) && !forceCheckOnAddress) { 172 return supportsDeviceTypes(DeviceTypeSet({device->type()})); 173 } 174 return mSupportedDevices.contains(device); 175 } 176 devicesSupportEncodedFormats(DeviceTypeSet deviceTypes)177 bool devicesSupportEncodedFormats(DeviceTypeSet deviceTypes) const 178 { 179 if (deviceTypes.empty()) { 180 return true; // required for getOffloadSupport() check 181 } 182 DeviceVector deviceList = 183 mSupportedDevices.getDevicesFromTypes(deviceTypes); 184 for (const auto& device : deviceList) { 185 if (device->hasCurrentEncodedFormat()) { 186 return true; 187 } 188 } 189 return false; 190 } 191 192 bool containsSingleDeviceSupportingEncodedFormats(const sp<DeviceDescriptor>& device) const; 193 clearSupportedDevices()194 void clearSupportedDevices() { mSupportedDevices.clear(); } addSupportedDevice(const sp<DeviceDescriptor> & device)195 void addSupportedDevice(const sp<DeviceDescriptor> &device) 196 { 197 mSupportedDevices.add(device); 198 } removeSupportedDevice(const sp<DeviceDescriptor> & device)199 void removeSupportedDevice(const sp<DeviceDescriptor> &device) 200 { 201 ssize_t ret = mSupportedDevices.indexOf(device); 202 if (ret >= 0 && !mSupportedDevices.itemAt(ret)->isDynamic()) { 203 // devices equality checks only type, address, name and format 204 // Prevents from removing non dynamically added devices 205 return; 206 } 207 mSupportedDevices.remove(device); 208 } setSupportedDevices(const DeviceVector & devices)209 void setSupportedDevices(const DeviceVector &devices) 210 { 211 mSupportedDevices = devices; 212 } 213 getSupportedDevices()214 const DeviceVector &getSupportedDevices() const { return mSupportedDevices; } 215 canOpenNewIo()216 bool canOpenNewIo() { 217 if (maxOpenCount == 0 || curOpenCount < maxOpenCount) { 218 return true; 219 } 220 return false; 221 } 222 canStartNewIo()223 bool canStartNewIo() { 224 if (maxActiveCount == 0 || curActiveCount < maxActiveCount) { 225 return true; 226 } 227 return false; 228 } 229 230 void toSupportedMixerAttributes(std::vector<audio_mixer_attributes_t>* mixerAttributes) const; 231 232 status_t readFromParcelable(const media::AudioPortFw& parcelable); 233 234 void importAudioPort(const audio_port_v7& port) override; 235 236 // Number of streams currently opened for this profile. 237 uint32_t curOpenCount; 238 // Number of streams currently active for this profile. This is not the number of active clients 239 // (AudioTrack or AudioRecord) but the number of active HAL streams. 240 uint32_t curActiveCount; 241 242 private: 243 void refreshMixerBehaviors(); 244 CompatibilityScore getFlagsCompatibleScore(uint32_t flags) const; 245 246 DeviceVector mSupportedDevices; // supported devices: this input/output can be routed from/to 247 248 MixerBehaviorSet mMixerBehaviors; 249 }; 250 251 class InputProfile : public IOProfile 252 { 253 public: InputProfile(const std::string & name)254 explicit InputProfile(const std::string &name) : IOProfile(name, AUDIO_PORT_ROLE_SINK) {} 255 }; 256 257 class OutputProfile : public IOProfile 258 { 259 public: OutputProfile(const std::string & name)260 explicit OutputProfile(const std::string &name) : IOProfile(name, AUDIO_PORT_ROLE_SOURCE) {} 261 }; 262 263 } // namespace android 264