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 #define LOG_TAG "APM::HwModule" 18 //#define LOG_NDEBUG 0 19 20 #include "HwModule.h" 21 #include "IOProfile.h" 22 #include "AudioGain.h" 23 #include <policy.h> 24 #include <system/audio.h> 25 26 namespace android { 27 28 HwModule::HwModule(const char *name, uint32_t halVersionMajor, uint32_t halVersionMinor) 29 : mName(String8(name)), 30 mHandle(AUDIO_MODULE_HANDLE_NONE) 31 { 32 setHalVersion(halVersionMajor, halVersionMinor); 33 } 34 35 HwModule::~HwModule() 36 { 37 for (size_t i = 0; i < mOutputProfiles.size(); i++) { 38 mOutputProfiles[i]->clearSupportedDevices(); 39 } 40 for (size_t i = 0; i < mInputProfiles.size(); i++) { 41 mInputProfiles[i]->clearSupportedDevices(); 42 } 43 } 44 45 status_t HwModule::addOutputProfile(const String8& name, const audio_config_t *config, 46 audio_devices_t device, const String8& address) 47 { 48 sp<IOProfile> profile = new OutputProfile(name); 49 50 profile->addAudioProfile(new AudioProfile(config->format, config->channel_mask, 51 config->sample_rate)); 52 53 sp<DeviceDescriptor> devDesc = new DeviceDescriptor(device); 54 devDesc->setAddress(address); 55 addDynamicDevice(devDesc); 56 // Reciprocally attach the device to the module 57 devDesc->attach(this); 58 profile->addSupportedDevice(devDesc); 59 60 return addOutputProfile(profile); 61 } 62 63 status_t HwModule::addOutputProfile(const sp<IOProfile> &profile) 64 { 65 profile->attach(this); 66 mOutputProfiles.add(profile); 67 mPorts.add(profile); 68 return NO_ERROR; 69 } 70 71 status_t HwModule::addInputProfile(const sp<IOProfile> &profile) 72 { 73 profile->attach(this); 74 mInputProfiles.add(profile); 75 mPorts.add(profile); 76 return NO_ERROR; 77 } 78 79 status_t HwModule::addProfile(const sp<IOProfile> &profile) 80 { 81 switch (profile->getRole()) { 82 case AUDIO_PORT_ROLE_SOURCE: 83 return addOutputProfile(profile); 84 case AUDIO_PORT_ROLE_SINK: 85 return addInputProfile(profile); 86 case AUDIO_PORT_ROLE_NONE: 87 return BAD_VALUE; 88 } 89 return BAD_VALUE; 90 } 91 92 void HwModule::setProfiles(const IOProfileCollection &profiles) 93 { 94 for (size_t i = 0; i < profiles.size(); i++) { 95 addProfile(profiles[i]); 96 } 97 } 98 99 status_t HwModule::removeOutputProfile(const String8& name) 100 { 101 for (size_t i = 0; i < mOutputProfiles.size(); i++) { 102 if (mOutputProfiles[i]->getName() == name) { 103 for (const auto &device : mOutputProfiles[i]->getSupportedDevices()) { 104 removeDynamicDevice(device); 105 } 106 mOutputProfiles.removeAt(i); 107 break; 108 } 109 } 110 111 return NO_ERROR; 112 } 113 114 status_t HwModule::addInputProfile(const String8& name, const audio_config_t *config, 115 audio_devices_t device, const String8& address) 116 { 117 sp<IOProfile> profile = new InputProfile(name); 118 profile->addAudioProfile(new AudioProfile(config->format, config->channel_mask, 119 config->sample_rate)); 120 121 sp<DeviceDescriptor> devDesc = new DeviceDescriptor(device); 122 devDesc->setAddress(address); 123 addDynamicDevice(devDesc); 124 // Reciprocally attach the device to the module 125 devDesc->attach(this); 126 profile->addSupportedDevice(devDesc); 127 128 ALOGV("addInputProfile() name %s rate %d mask 0x%08x", 129 name.string(), config->sample_rate, config->channel_mask); 130 131 return addInputProfile(profile); 132 } 133 134 status_t HwModule::removeInputProfile(const String8& name) 135 { 136 for (size_t i = 0; i < mInputProfiles.size(); i++) { 137 if (mInputProfiles[i]->getName() == name) { 138 for (const auto &device : mInputProfiles[i]->getSupportedDevices()) { 139 removeDynamicDevice(device); 140 } 141 mInputProfiles.removeAt(i); 142 break; 143 } 144 } 145 146 return NO_ERROR; 147 } 148 149 void HwModule::setDeclaredDevices(const DeviceVector &devices) 150 { 151 mDeclaredDevices = devices; 152 for (size_t i = 0; i < devices.size(); i++) { 153 mPorts.add(devices[i]); 154 } 155 } 156 157 sp<DeviceDescriptor> HwModule::getRouteSinkDevice(const sp<AudioRoute> &route) const 158 { 159 sp<DeviceDescriptor> sinkDevice = 0; 160 if (route->getSink()->getType() == AUDIO_PORT_TYPE_DEVICE) { 161 sinkDevice = mDeclaredDevices.getDeviceFromTagName(route->getSink()->getTagName()); 162 } 163 return sinkDevice; 164 } 165 166 DeviceVector HwModule::getRouteSourceDevices(const sp<AudioRoute> &route) const 167 { 168 DeviceVector sourceDevices; 169 for (const auto& source : route->getSources()) { 170 if (source->getType() == AUDIO_PORT_TYPE_DEVICE) { 171 sourceDevices.add(mDeclaredDevices.getDeviceFromTagName(source->getTagName())); 172 } 173 } 174 return sourceDevices; 175 } 176 177 void HwModule::setRoutes(const AudioRouteVector &routes) 178 { 179 mRoutes = routes; 180 // Now updating the streams (aka IOProfile until now) supported devices 181 refreshSupportedDevices(); 182 } 183 184 void HwModule::refreshSupportedDevices() 185 { 186 // Now updating the streams (aka IOProfile until now) supported devices 187 for (const auto& stream : mInputProfiles) { 188 DeviceVector sourceDevices; 189 for (const auto& route : stream->getRoutes()) { 190 sp<AudioPort> sink = route->getSink(); 191 if (sink == 0 || stream != sink) { 192 ALOGE("%s: Invalid route attached to input stream", __FUNCTION__); 193 continue; 194 } 195 DeviceVector sourceDevicesForRoute = getRouteSourceDevices(route); 196 if (sourceDevicesForRoute.isEmpty()) { 197 ALOGE("%s: invalid source devices for %s", __FUNCTION__, stream->getName().string()); 198 continue; 199 } 200 sourceDevices.add(sourceDevicesForRoute); 201 } 202 if (sourceDevices.isEmpty()) { 203 ALOGE("%s: invalid source devices for %s", __FUNCTION__, stream->getName().string()); 204 continue; 205 } 206 stream->setSupportedDevices(sourceDevices); 207 } 208 for (const auto& stream : mOutputProfiles) { 209 DeviceVector sinkDevices; 210 for (const auto& route : stream->getRoutes()) { 211 sp<AudioPort> source = route->getSources().findByTagName(stream->getTagName()); 212 if (source == 0 || stream != source) { 213 ALOGE("%s: Invalid route attached to output stream", __FUNCTION__); 214 continue; 215 } 216 sp<DeviceDescriptor> sinkDevice = getRouteSinkDevice(route); 217 if (sinkDevice == 0) { 218 ALOGE("%s: invalid sink device for %s", __FUNCTION__, stream->getName().string()); 219 continue; 220 } 221 sinkDevices.add(sinkDevice); 222 } 223 stream->setSupportedDevices(sinkDevices); 224 } 225 } 226 227 void HwModule::setHandle(audio_module_handle_t handle) { 228 ALOGW_IF(mHandle != AUDIO_MODULE_HANDLE_NONE, 229 "HwModule handle is changing from %d to %d", mHandle, handle); 230 mHandle = handle; 231 } 232 233 bool HwModule::supportsPatch(const sp<AudioPort> &srcPort, const sp<AudioPort> &dstPort) const { 234 for (const auto &route : mRoutes) { 235 if (route->supportsPatch(srcPort, dstPort)) { 236 return true; 237 } 238 } 239 return false; 240 } 241 242 void HwModule::dump(String8 *dst) const 243 { 244 dst->appendFormat(" - name: %s\n", getName()); 245 dst->appendFormat(" - handle: %d\n", mHandle); 246 dst->appendFormat(" - version: %u.%u\n", getHalVersionMajor(), getHalVersionMinor()); 247 if (mOutputProfiles.size()) { 248 dst->append(" - outputs:\n"); 249 for (size_t i = 0; i < mOutputProfiles.size(); i++) { 250 dst->appendFormat(" output %zu:\n", i); 251 mOutputProfiles[i]->dump(dst); 252 } 253 } 254 if (mInputProfiles.size()) { 255 dst->append(" - inputs:\n"); 256 for (size_t i = 0; i < mInputProfiles.size(); i++) { 257 dst->appendFormat(" input %zu:\n", i); 258 mInputProfiles[i]->dump(dst); 259 } 260 } 261 mDeclaredDevices.dump(dst, String8("Declared"), 2, true); 262 mDynamicDevices.dump(dst, String8("Dynamic"), 2, true); 263 mRoutes.dump(dst, 2); 264 } 265 266 sp <HwModule> HwModuleCollection::getModuleFromName(const char *name) const 267 { 268 for (const auto& module : *this) { 269 if (strcmp(module->getName(), name) == 0) { 270 return module; 271 } 272 } 273 return nullptr; 274 } 275 276 sp <HwModule> HwModuleCollection::getModuleForDeviceTypes(audio_devices_t type, 277 audio_format_t encodedFormat) const 278 { 279 for (const auto& module : *this) { 280 const auto& profiles = audio_is_output_device(type) ? 281 module->getOutputProfiles() : module->getInputProfiles(); 282 for (const auto& profile : profiles) { 283 if (profile->supportsDeviceTypes(type)) { 284 if (encodedFormat != AUDIO_FORMAT_DEFAULT) { 285 DeviceVector declaredDevices = module->getDeclaredDevices(); 286 sp <DeviceDescriptor> deviceDesc = 287 declaredDevices.getDevice(type, String8(), encodedFormat); 288 if (deviceDesc) { 289 return module; 290 } 291 } else { 292 return module; 293 } 294 } 295 } 296 } 297 return nullptr; 298 } 299 300 sp<HwModule> HwModuleCollection::getModuleForDevice(const sp<DeviceDescriptor> &device, 301 audio_format_t encodedFormat) const 302 { 303 return getModuleForDeviceTypes(device->type(), encodedFormat); 304 } 305 306 DeviceVector HwModuleCollection::getAvailableDevicesFromModuleName( 307 const char *name, const DeviceVector &availableDevices) const 308 { 309 sp<HwModule> module = getModuleFromName(name); 310 if (module == nullptr) { 311 return DeviceVector(); 312 } 313 return availableDevices.getDevicesFromHwModule(module->getHandle()); 314 } 315 316 sp<DeviceDescriptor> HwModuleCollection::getDeviceDescriptor(const audio_devices_t deviceType, 317 const char *address, 318 const char *name, 319 const audio_format_t encodedFormat, 320 bool allowToCreate, 321 bool matchAddress) const 322 { 323 String8 devAddress = (address == nullptr || !matchAddress) ? String8("") : String8(address); 324 // handle legacy remote submix case where the address was not always specified 325 if (device_distinguishes_on_address(deviceType) && (devAddress.length() == 0)) { 326 devAddress = String8("0"); 327 } 328 329 for (const auto& hwModule : *this) { 330 DeviceVector moduleDevices = hwModule->getAllDevices(); 331 auto moduleDevice = moduleDevices.getDevice(deviceType, devAddress, encodedFormat); 332 if (moduleDevice) { 333 if (encodedFormat != AUDIO_FORMAT_DEFAULT) { 334 moduleDevice->setEncodedFormat(encodedFormat); 335 } 336 moduleDevice->setAddress(devAddress); 337 if (allowToCreate) { 338 moduleDevice->attach(hwModule); 339 } 340 return moduleDevice; 341 } 342 } 343 if (!allowToCreate) { 344 ALOGV("%s: could not find HW module for device %s %04x address %s", __FUNCTION__, 345 name, deviceType, address); 346 return nullptr; 347 } 348 return createDevice(deviceType, address, name, encodedFormat); 349 } 350 351 sp<DeviceDescriptor> HwModuleCollection::createDevice(const audio_devices_t type, 352 const char *address, 353 const char *name, 354 const audio_format_t encodedFormat) const 355 { 356 sp<HwModule> hwModule = getModuleForDeviceTypes(type, encodedFormat); 357 if (hwModule == 0) { 358 ALOGE("%s: could not find HW module for device %04x address %s", __FUNCTION__, type, 359 address); 360 return nullptr; 361 } 362 sp<DeviceDescriptor> device = new DeviceDescriptor(type, String8(name)); 363 device->setName(String8(name)); 364 device->setAddress(String8(address)); 365 device->setEncodedFormat(encodedFormat); 366 367 // Add the device to the list of dynamic devices 368 hwModule->addDynamicDevice(device); 369 // Reciprocally attach the device to the module 370 device->attach(hwModule); 371 ALOGD("%s: adding dynamic device %s to module %s", __FUNCTION__, 372 device->toString().c_str(), hwModule->getName()); 373 374 const auto &profiles = (audio_is_output_device(type) ? hwModule->getOutputProfiles() : 375 hwModule->getInputProfiles()); 376 for (const auto &profile : profiles) { 377 // Add the device as supported to all profile supporting "weakly" or not the device 378 // according to its type 379 if (profile->supportsDevice(device, false /*matchAdress*/)) { 380 381 // @todo quid of audio profile? import the profile from device of the same type? 382 const auto &isoTypeDeviceForProfile = 383 profile->getSupportedDevices().getDevice(type, String8(), AUDIO_FORMAT_DEFAULT); 384 device->importAudioPort(isoTypeDeviceForProfile, true /* force */); 385 386 ALOGV("%s: adding device %s to profile %s", __FUNCTION__, 387 device->toString().c_str(), profile->getTagName().c_str()); 388 profile->addSupportedDevice(device); 389 } 390 } 391 return device; 392 } 393 394 void HwModuleCollection::cleanUpForDevice(const sp<DeviceDescriptor> &device) 395 { 396 for (const auto& hwModule : *this) { 397 DeviceVector moduleDevices = hwModule->getAllDevices(); 398 if (!moduleDevices.contains(device)) { 399 continue; 400 } 401 402 // removal of remote submix devices associated with a dynamic policy is 403 // handled by removeOutputProfile() and removeInputProfile() 404 if (audio_is_remote_submix_device(device->type()) && device->address() != "0") { 405 continue; 406 } 407 408 device->detach(); 409 // Only remove from dynamic list, not from declared list!!! 410 if (!hwModule->getDynamicDevices().contains(device)) { 411 return; 412 } 413 hwModule->removeDynamicDevice(device); 414 ALOGV("%s: removed dynamic device %s from module %s", __FUNCTION__, 415 device->toString().c_str(), hwModule->getName()); 416 417 const IOProfileCollection &profiles = audio_is_output_device(device->type()) ? 418 hwModule->getOutputProfiles() : hwModule->getInputProfiles(); 419 for (const auto &profile : profiles) { 420 // For cleanup, strong match is required 421 if (profile->supportsDevice(device, true /*matchAdress*/)) { 422 ALOGV("%s: removing device %s from profile %s", __FUNCTION__, 423 device->toString().c_str(), profile->getTagName().c_str()); 424 profile->removeSupportedDevice(device); 425 } 426 } 427 } 428 } 429 430 void HwModuleCollection::dump(String8 *dst) const 431 { 432 dst->append("\nHW Modules dump:\n"); 433 for (size_t i = 0; i < size(); i++) { 434 dst->appendFormat("- HW Module %zu:\n", i + 1); 435 itemAt(i)->dump(dst); 436 } 437 } 438 439 440 } //namespace android 441