HwModule.cpp revision 7288ab87a7aa730ffe97d7dc7e118123107bfcea
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 "ConfigParsingUtils.h" 24#include "audio_policy_conf.h" 25#include <hardware/audio.h> 26#include <policy.h> 27 28namespace android { 29 30HwModule::HwModule(const char *name) 31 : mName(strndup(name, AUDIO_HARDWARE_MODULE_ID_MAX_LEN)), 32 mHalVersion(AUDIO_DEVICE_API_VERSION_MIN), mHandle(0) 33{ 34} 35 36HwModule::~HwModule() 37{ 38 for (size_t i = 0; i < mOutputProfiles.size(); i++) { 39 mOutputProfiles[i]->mSupportedDevices.clear(); 40 } 41 for (size_t i = 0; i < mInputProfiles.size(); i++) { 42 mInputProfiles[i]->mSupportedDevices.clear(); 43 } 44 free((void *)mName); 45} 46 47status_t HwModule::loadInput(cnode *root) 48{ 49 cnode *node = root->first_child; 50 51 sp<IOProfile> profile = new IOProfile(String8(root->name), AUDIO_PORT_ROLE_SINK); 52 53 while (node) { 54 if (strcmp(node->name, SAMPLING_RATES_TAG) == 0) { 55 profile->loadSamplingRates((char *)node->value); 56 } else if (strcmp(node->name, FORMATS_TAG) == 0) { 57 profile->loadFormats((char *)node->value); 58 } else if (strcmp(node->name, CHANNELS_TAG) == 0) { 59 profile->loadInChannels((char *)node->value); 60 } else if (strcmp(node->name, DEVICES_TAG) == 0) { 61 profile->mSupportedDevices.loadDevicesFromTag((char *)node->value, 62 mDeclaredDevices); 63 } else if (strcmp(node->name, FLAGS_TAG) == 0) { 64 profile->mFlags = ConfigParsingUtils::parseInputFlagNames((char *)node->value); 65 } else if (strcmp(node->name, GAINS_TAG) == 0) { 66 profile->loadGains(node); 67 } 68 node = node->next; 69 } 70 ALOGW_IF(profile->mSupportedDevices.isEmpty(), 71 "loadInput() invalid supported devices"); 72 ALOGW_IF(profile->mChannelMasks.size() == 0, 73 "loadInput() invalid supported channel masks"); 74 ALOGW_IF(profile->mSamplingRates.size() == 0, 75 "loadInput() invalid supported sampling rates"); 76 ALOGW_IF(profile->mFormats.size() == 0, 77 "loadInput() invalid supported formats"); 78 if (!profile->mSupportedDevices.isEmpty() && 79 (profile->mChannelMasks.size() != 0) && 80 (profile->mSamplingRates.size() != 0) && 81 (profile->mFormats.size() != 0)) { 82 83 ALOGV("loadInput() adding input Supported Devices %04x", 84 profile->mSupportedDevices.types()); 85 86 profile->attach(this); 87 mInputProfiles.add(profile); 88 return NO_ERROR; 89 } else { 90 return BAD_VALUE; 91 } 92} 93 94status_t HwModule::loadOutput(cnode *root) 95{ 96 cnode *node = root->first_child; 97 98 sp<IOProfile> profile = new IOProfile(String8(root->name), AUDIO_PORT_ROLE_SOURCE); 99 100 while (node) { 101 if (strcmp(node->name, SAMPLING_RATES_TAG) == 0) { 102 profile->loadSamplingRates((char *)node->value); 103 } else if (strcmp(node->name, FORMATS_TAG) == 0) { 104 profile->loadFormats((char *)node->value); 105 } else if (strcmp(node->name, CHANNELS_TAG) == 0) { 106 profile->loadOutChannels((char *)node->value); 107 } else if (strcmp(node->name, DEVICES_TAG) == 0) { 108 profile->mSupportedDevices.loadDevicesFromTag((char *)node->value, 109 mDeclaredDevices); 110 } else if (strcmp(node->name, FLAGS_TAG) == 0) { 111 profile->mFlags = ConfigParsingUtils::parseOutputFlagNames((char *)node->value); 112 } else if (strcmp(node->name, GAINS_TAG) == 0) { 113 profile->loadGains(node); 114 } 115 node = node->next; 116 } 117 ALOGW_IF(profile->mSupportedDevices.isEmpty(), 118 "loadOutput() invalid supported devices"); 119 ALOGW_IF(profile->mChannelMasks.size() == 0, 120 "loadOutput() invalid supported channel masks"); 121 ALOGW_IF(profile->mSamplingRates.size() == 0, 122 "loadOutput() invalid supported sampling rates"); 123 ALOGW_IF(profile->mFormats.size() == 0, 124 "loadOutput() invalid supported formats"); 125 if (!profile->mSupportedDevices.isEmpty() && 126 (profile->mChannelMasks.size() != 0) && 127 (profile->mSamplingRates.size() != 0) && 128 (profile->mFormats.size() != 0)) { 129 130 ALOGV("loadOutput() adding output Supported Devices %04x, mFlags %04x", 131 profile->mSupportedDevices.types(), profile->mFlags); 132 profile->attach(this); 133 mOutputProfiles.add(profile); 134 return NO_ERROR; 135 } else { 136 return BAD_VALUE; 137 } 138} 139 140status_t HwModule::loadDevice(cnode *root) 141{ 142 cnode *node = root->first_child; 143 144 audio_devices_t type = AUDIO_DEVICE_NONE; 145 while (node) { 146 if (strcmp(node->name, APM_DEVICE_TYPE) == 0) { 147 type = ConfigParsingUtils::parseDeviceNames((char *)node->value); 148 break; 149 } 150 node = node->next; 151 } 152 if (type == AUDIO_DEVICE_NONE || 153 (!audio_is_input_device(type) && !audio_is_output_device(type))) { 154 ALOGW("loadDevice() bad type %08x", type); 155 return BAD_VALUE; 156 } 157 sp<DeviceDescriptor> deviceDesc = new DeviceDescriptor(type); 158 deviceDesc->mTag = String8(root->name); 159 160 node = root->first_child; 161 while (node) { 162 if (strcmp(node->name, APM_DEVICE_ADDRESS) == 0) { 163 deviceDesc->mAddress = String8((char *)node->value); 164 } else if (strcmp(node->name, CHANNELS_TAG) == 0) { 165 if (audio_is_input_device(type)) { 166 deviceDesc->loadInChannels((char *)node->value); 167 } else { 168 deviceDesc->loadOutChannels((char *)node->value); 169 } 170 } else if (strcmp(node->name, GAINS_TAG) == 0) { 171 deviceDesc->loadGains(node); 172 } 173 node = node->next; 174 } 175 176 ALOGV("loadDevice() adding device tag %s type %08x address %s", 177 deviceDesc->mTag.string(), type, deviceDesc->mAddress.string()); 178 179 mDeclaredDevices.add(deviceDesc); 180 181 return NO_ERROR; 182} 183 184status_t HwModule::addOutputProfile(String8 name, const audio_config_t *config, 185 audio_devices_t device, String8 address) 186{ 187 sp<IOProfile> profile = new IOProfile(name, AUDIO_PORT_ROLE_SOURCE); 188 189 profile->mSamplingRates.add(config->sample_rate); 190 profile->mChannelMasks.add(config->channel_mask); 191 profile->mFormats.add(config->format); 192 193 sp<DeviceDescriptor> devDesc = new DeviceDescriptor(device); 194 devDesc->mAddress = address; 195 profile->mSupportedDevices.add(devDesc); 196 197 profile->attach(this); 198 mOutputProfiles.add(profile); 199 200 return NO_ERROR; 201} 202 203status_t HwModule::removeOutputProfile(String8 name) 204{ 205 for (size_t i = 0; i < mOutputProfiles.size(); i++) { 206 if (mOutputProfiles[i]->mName == name) { 207 mOutputProfiles.removeAt(i); 208 break; 209 } 210 } 211 212 return NO_ERROR; 213} 214 215status_t HwModule::addInputProfile(String8 name, const audio_config_t *config, 216 audio_devices_t device, String8 address) 217{ 218 sp<IOProfile> profile = new IOProfile(name, AUDIO_PORT_ROLE_SINK); 219 220 profile->mSamplingRates.add(config->sample_rate); 221 profile->mChannelMasks.add(config->channel_mask); 222 profile->mFormats.add(config->format); 223 224 sp<DeviceDescriptor> devDesc = new DeviceDescriptor(device); 225 devDesc->mAddress = address; 226 profile->mSupportedDevices.add(devDesc); 227 228 ALOGV("addInputProfile() name %s rate %d mask 0x08", name.string(), config->sample_rate, config->channel_mask); 229 230 profile->attach(this); 231 mInputProfiles.add(profile); 232 233 return NO_ERROR; 234} 235 236status_t HwModule::removeInputProfile(String8 name) 237{ 238 for (size_t i = 0; i < mInputProfiles.size(); i++) { 239 if (mInputProfiles[i]->mName == name) { 240 mInputProfiles.removeAt(i); 241 break; 242 } 243 } 244 245 return NO_ERROR; 246} 247 248 249void HwModule::dump(int fd) 250{ 251 const size_t SIZE = 256; 252 char buffer[SIZE]; 253 String8 result; 254 255 snprintf(buffer, SIZE, " - name: %s\n", mName); 256 result.append(buffer); 257 snprintf(buffer, SIZE, " - handle: %d\n", mHandle); 258 result.append(buffer); 259 snprintf(buffer, SIZE, " - version: %u.%u\n", mHalVersion >> 8, mHalVersion & 0xFF); 260 result.append(buffer); 261 write(fd, result.string(), result.size()); 262 if (mOutputProfiles.size()) { 263 write(fd, " - outputs:\n", strlen(" - outputs:\n")); 264 for (size_t i = 0; i < mOutputProfiles.size(); i++) { 265 snprintf(buffer, SIZE, " output %zu:\n", i); 266 write(fd, buffer, strlen(buffer)); 267 mOutputProfiles[i]->dump(fd); 268 } 269 } 270 if (mInputProfiles.size()) { 271 write(fd, " - inputs:\n", strlen(" - inputs:\n")); 272 for (size_t i = 0; i < mInputProfiles.size(); i++) { 273 snprintf(buffer, SIZE, " input %zu:\n", i); 274 write(fd, buffer, strlen(buffer)); 275 mInputProfiles[i]->dump(fd); 276 } 277 } 278 if (mDeclaredDevices.size()) { 279 write(fd, " - devices:\n", strlen(" - devices:\n")); 280 for (size_t i = 0; i < mDeclaredDevices.size(); i++) { 281 mDeclaredDevices[i]->dump(fd, 4, i); 282 } 283 } 284} 285 286sp <HwModule> HwModuleCollection::getModuleFromName(const char *name) const 287{ 288 sp <HwModule> module; 289 290 for (size_t i = 0; i < size(); i++) 291 { 292 if (strcmp(itemAt(i)->mName, name) == 0) { 293 return itemAt(i); 294 } 295 } 296 return module; 297} 298 299 300sp <HwModule> HwModuleCollection::getModuleForDevice(audio_devices_t device) const 301{ 302 sp <HwModule> module; 303 304 for (size_t i = 0; i < size(); i++) { 305 if (itemAt(i)->mHandle == 0) { 306 continue; 307 } 308 if (audio_is_output_device(device)) { 309 for (size_t j = 0; j < itemAt(i)->mOutputProfiles.size(); j++) 310 { 311 if (itemAt(i)->mOutputProfiles[j]->mSupportedDevices.types() & device) { 312 return itemAt(i); 313 } 314 } 315 } else { 316 for (size_t j = 0; j < itemAt(i)->mInputProfiles.size(); j++) { 317 if (itemAt(i)->mInputProfiles[j]->mSupportedDevices.types() & 318 device & ~AUDIO_DEVICE_BIT_IN) { 319 return itemAt(i); 320 } 321 } 322 } 323 } 324 return module; 325} 326 327sp<DeviceDescriptor> HwModuleCollection::getDeviceDescriptor(const audio_devices_t device, 328 const char *device_address, 329 const char *device_name) const 330{ 331 String8 address = (device_address == NULL) ? String8("") : String8(device_address); 332 // handle legacy remote submix case where the address was not always specified 333 if (device_distinguishes_on_address(device) && (address.length() == 0)) { 334 address = String8("0"); 335 } 336 337 for (size_t i = 0; i < size(); i++) { 338 const sp<HwModule> hwModule = itemAt(i); 339 if (hwModule->mHandle == 0) { 340 continue; 341 } 342 DeviceVector deviceList = 343 hwModule->mDeclaredDevices.getDevicesFromTypeAddr(device, address); 344 if (!deviceList.isEmpty()) { 345 return deviceList.itemAt(0); 346 } 347 deviceList = hwModule->mDeclaredDevices.getDevicesFromType(device); 348 if (!deviceList.isEmpty()) { 349 return deviceList.itemAt(0); 350 } 351 } 352 353 sp<DeviceDescriptor> devDesc = 354 new DeviceDescriptor(device); 355 devDesc->mName = device_name; 356 devDesc->mAddress = address; 357 return devDesc; 358} 359 360status_t HwModuleCollection::dump(int fd) const 361{ 362 const size_t SIZE = 256; 363 char buffer[SIZE]; 364 365 snprintf(buffer, SIZE, "\nHW Modules dump:\n"); 366 write(fd, buffer, strlen(buffer)); 367 for (size_t i = 0; i < size(); i++) { 368 snprintf(buffer, SIZE, "- HW Module %zu:\n", i + 1); 369 write(fd, buffer, strlen(buffer)); 370 itemAt(i)->dump(fd); 371 } 372 return NO_ERROR; 373} 374 375} //namespace android 376