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 26namespace android { 27 28HwModule::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 35HwModule::~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 45status_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->mAddress = address; 55 profile->addSupportedDevice(devDesc); 56 57 return addOutputProfile(profile); 58} 59 60status_t HwModule::addOutputProfile(const sp<IOProfile> &profile) 61{ 62 profile->attach(this); 63 mOutputProfiles.add(profile); 64 mPorts.add(profile); 65 return NO_ERROR; 66} 67 68status_t HwModule::addInputProfile(const sp<IOProfile> &profile) 69{ 70 profile->attach(this); 71 mInputProfiles.add(profile); 72 mPorts.add(profile); 73 return NO_ERROR; 74} 75 76status_t HwModule::addProfile(const sp<IOProfile> &profile) 77{ 78 switch (profile->getRole()) { 79 case AUDIO_PORT_ROLE_SOURCE: 80 return addOutputProfile(profile); 81 case AUDIO_PORT_ROLE_SINK: 82 return addInputProfile(profile); 83 case AUDIO_PORT_ROLE_NONE: 84 return BAD_VALUE; 85 } 86 return BAD_VALUE; 87} 88 89void HwModule::setProfiles(const IOProfileCollection &profiles) 90{ 91 for (size_t i = 0; i < profiles.size(); i++) { 92 addProfile(profiles[i]); 93 } 94} 95 96status_t HwModule::removeOutputProfile(const String8& name) 97{ 98 for (size_t i = 0; i < mOutputProfiles.size(); i++) { 99 if (mOutputProfiles[i]->getName() == name) { 100 mOutputProfiles.removeAt(i); 101 break; 102 } 103 } 104 105 return NO_ERROR; 106} 107 108status_t HwModule::addInputProfile(const String8& name, const audio_config_t *config, 109 audio_devices_t device, const String8& address) 110{ 111 sp<IOProfile> profile = new InputProfile(name); 112 profile->addAudioProfile(new AudioProfile(config->format, config->channel_mask, 113 config->sample_rate)); 114 115 sp<DeviceDescriptor> devDesc = new DeviceDescriptor(device); 116 devDesc->mAddress = address; 117 profile->addSupportedDevice(devDesc); 118 119 ALOGV("addInputProfile() name %s rate %d mask 0x%08x", 120 name.string(), config->sample_rate, config->channel_mask); 121 122 return addInputProfile(profile); 123} 124 125status_t HwModule::removeInputProfile(const String8& name) 126{ 127 for (size_t i = 0; i < mInputProfiles.size(); i++) { 128 if (mInputProfiles[i]->getName() == name) { 129 mInputProfiles.removeAt(i); 130 break; 131 } 132 } 133 134 return NO_ERROR; 135} 136 137void HwModule::setDeclaredDevices(const DeviceVector &devices) 138{ 139 mDeclaredDevices = devices; 140 for (size_t i = 0; i < devices.size(); i++) { 141 mPorts.add(devices[i]); 142 } 143} 144 145sp<DeviceDescriptor> HwModule::getRouteSinkDevice(const sp<AudioRoute> &route) const 146{ 147 sp<DeviceDescriptor> sinkDevice = 0; 148 if (route->getSink()->getType() == AUDIO_PORT_TYPE_DEVICE) { 149 sinkDevice = mDeclaredDevices.getDeviceFromTagName(route->getSink()->getTagName()); 150 } 151 return sinkDevice; 152} 153 154DeviceVector HwModule::getRouteSourceDevices(const sp<AudioRoute> &route) const 155{ 156 DeviceVector sourceDevices; 157 for (const auto& source : route->getSources()) { 158 if (source->getType() == AUDIO_PORT_TYPE_DEVICE) { 159 sourceDevices.add(mDeclaredDevices.getDeviceFromTagName(source->getTagName())); 160 } 161 } 162 return sourceDevices; 163} 164 165void HwModule::setRoutes(const AudioRouteVector &routes) 166{ 167 mRoutes = routes; 168 // Now updating the streams (aka IOProfile until now) supported devices 169 refreshSupportedDevices(); 170} 171 172void HwModule::refreshSupportedDevices() 173{ 174 // Now updating the streams (aka IOProfile until now) supported devices 175 for (const auto& stream : mInputProfiles) { 176 DeviceVector sourceDevices; 177 for (const auto& route : stream->getRoutes()) { 178 sp<AudioPort> sink = route->getSink(); 179 if (sink == 0 || stream != sink) { 180 ALOGE("%s: Invalid route attached to input stream", __FUNCTION__); 181 continue; 182 } 183 DeviceVector sourceDevicesForRoute = getRouteSourceDevices(route); 184 if (sourceDevicesForRoute.isEmpty()) { 185 ALOGE("%s: invalid source devices for %s", __FUNCTION__, stream->getName().string()); 186 continue; 187 } 188 sourceDevices.add(sourceDevicesForRoute); 189 } 190 if (sourceDevices.isEmpty()) { 191 ALOGE("%s: invalid source devices for %s", __FUNCTION__, stream->getName().string()); 192 continue; 193 } 194 stream->setSupportedDevices(sourceDevices); 195 } 196 for (const auto& stream : mOutputProfiles) { 197 DeviceVector sinkDevices; 198 for (const auto& route : stream->getRoutes()) { 199 sp<AudioPort> source = route->getSources().findByTagName(stream->getTagName()); 200 if (source == 0 || stream != source) { 201 ALOGE("%s: Invalid route attached to output stream", __FUNCTION__); 202 continue; 203 } 204 sp<DeviceDescriptor> sinkDevice = getRouteSinkDevice(route); 205 if (sinkDevice == 0) { 206 ALOGE("%s: invalid sink device for %s", __FUNCTION__, stream->getName().string()); 207 continue; 208 } 209 sinkDevices.add(sinkDevice); 210 } 211 stream->setSupportedDevices(sinkDevices); 212 } 213} 214 215void HwModule::setHandle(audio_module_handle_t handle) { 216 ALOGW_IF(mHandle != AUDIO_MODULE_HANDLE_NONE, 217 "HwModule handle is changing from %d to %d", mHandle, handle); 218 mHandle = handle; 219} 220 221void HwModule::dump(int fd) 222{ 223 const size_t SIZE = 256; 224 char buffer[SIZE]; 225 String8 result; 226 227 snprintf(buffer, SIZE, " - name: %s\n", getName()); 228 result.append(buffer); 229 snprintf(buffer, SIZE, " - handle: %d\n", mHandle); 230 result.append(buffer); 231 snprintf(buffer, SIZE, " - version: %u.%u\n", getHalVersionMajor(), getHalVersionMinor()); 232 result.append(buffer); 233 write(fd, result.string(), result.size()); 234 if (mOutputProfiles.size()) { 235 write(fd, " - outputs:\n", strlen(" - outputs:\n")); 236 for (size_t i = 0; i < mOutputProfiles.size(); i++) { 237 snprintf(buffer, SIZE, " output %zu:\n", i); 238 write(fd, buffer, strlen(buffer)); 239 mOutputProfiles[i]->dump(fd); 240 } 241 } 242 if (mInputProfiles.size()) { 243 write(fd, " - inputs:\n", strlen(" - inputs:\n")); 244 for (size_t i = 0; i < mInputProfiles.size(); i++) { 245 snprintf(buffer, SIZE, " input %zu:\n", i); 246 write(fd, buffer, strlen(buffer)); 247 mInputProfiles[i]->dump(fd); 248 } 249 } 250 mDeclaredDevices.dump(fd, String8("Declared"), 2, true); 251 mRoutes.dump(fd, 2); 252} 253 254sp <HwModule> HwModuleCollection::getModuleFromName(const char *name) const 255{ 256 for (const auto& module : *this) { 257 if (strcmp(module->getName(), name) == 0) { 258 return module; 259 } 260 } 261 return nullptr; 262} 263 264sp <HwModule> HwModuleCollection::getModuleForDevice(audio_devices_t device) const 265{ 266 for (const auto& module : *this) { 267 const auto& profiles = audio_is_output_device(device) ? 268 module->getOutputProfiles() : module->getInputProfiles(); 269 for (const auto& profile : profiles) { 270 if (profile->supportDevice(device)) { 271 return module; 272 } 273 } 274 } 275 return nullptr; 276} 277 278sp<DeviceDescriptor> HwModuleCollection::getDeviceDescriptor(const audio_devices_t device, 279 const char *device_address, 280 const char *device_name, 281 bool matchAdress) const 282{ 283 String8 address = (device_address == nullptr) ? String8("") : String8(device_address); 284 // handle legacy remote submix case where the address was not always specified 285 if (device_distinguishes_on_address(device) && (address.length() == 0)) { 286 address = String8("0"); 287 } 288 289 for (const auto& hwModule : *this) { 290 DeviceVector declaredDevices = hwModule->getDeclaredDevices(); 291 DeviceVector deviceList = declaredDevices.getDevicesFromTypeAddr(device, address); 292 if (!deviceList.isEmpty()) { 293 return deviceList.itemAt(0); 294 } 295 if (!matchAdress) { 296 deviceList = declaredDevices.getDevicesFromType(device); 297 if (!deviceList.isEmpty()) { 298 return deviceList.itemAt(0); 299 } 300 } 301 } 302 303 sp<DeviceDescriptor> devDesc = new DeviceDescriptor(device); 304 devDesc->setName(String8(device_name)); 305 devDesc->mAddress = address; 306 return devDesc; 307} 308 309status_t HwModuleCollection::dump(int fd) const 310{ 311 const size_t SIZE = 256; 312 char buffer[SIZE]; 313 314 snprintf(buffer, SIZE, "\nHW Modules dump:\n"); 315 write(fd, buffer, strlen(buffer)); 316 for (size_t i = 0; i < size(); i++) { 317 snprintf(buffer, SIZE, "- HW Module %zu:\n", i + 1); 318 write(fd, buffer, strlen(buffer)); 319 itemAt(i)->dump(fd); 320 } 321 return NO_ERROR; 322} 323 324 325} //namespace android 326