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