ConfigParsingUtils.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::ConfigParsingUtils" 18//#define LOG_NDEBUG 0 19 20#include "ConfigParsingUtils.h" 21#include "AudioGain.h" 22#include <hardware/audio.h> 23#include <utils/Log.h> 24#include <cutils/misc.h> 25 26namespace android { 27 28//static 29uint32_t ConfigParsingUtils::stringToEnum(const struct StringToEnum *table, 30 size_t size, 31 const char *name) 32{ 33 for (size_t i = 0; i < size; i++) { 34 if (strcmp(table[i].name, name) == 0) { 35 ALOGV("stringToEnum() found %s", table[i].name); 36 return table[i].value; 37 } 38 } 39 return 0; 40} 41 42//static 43const char *ConfigParsingUtils::enumToString(const struct StringToEnum *table, 44 size_t size, 45 uint32_t value) 46{ 47 for (size_t i = 0; i < size; i++) { 48 if (table[i].value == value) { 49 return table[i].name; 50 } 51 } 52 return ""; 53} 54 55//static 56bool ConfigParsingUtils::stringToBool(const char *value) 57{ 58 return ((strcasecmp("true", value) == 0) || (strcmp("1", value) == 0)); 59} 60 61 62// --- audio_policy.conf file parsing 63//static 64uint32_t ConfigParsingUtils::parseOutputFlagNames(char *name) 65{ 66 uint32_t flag = 0; 67 68 // it is OK to cast name to non const here as we are not going to use it after 69 // strtok() modifies it 70 char *flagName = strtok(name, "|"); 71 while (flagName != NULL) { 72 if (strlen(flagName) != 0) { 73 flag |= ConfigParsingUtils::stringToEnum(sOutputFlagNameToEnumTable, 74 ARRAY_SIZE(sOutputFlagNameToEnumTable), 75 flagName); 76 } 77 flagName = strtok(NULL, "|"); 78 } 79 //force direct flag if offload flag is set: offloading implies a direct output stream 80 // and all common behaviors are driven by checking only the direct flag 81 // this should normally be set appropriately in the policy configuration file 82 if ((flag & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) { 83 flag |= AUDIO_OUTPUT_FLAG_DIRECT; 84 } 85 86 return flag; 87} 88 89//static 90uint32_t ConfigParsingUtils::parseInputFlagNames(char *name) 91{ 92 uint32_t flag = 0; 93 94 // it is OK to cast name to non const here as we are not going to use it after 95 // strtok() modifies it 96 char *flagName = strtok(name, "|"); 97 while (flagName != NULL) { 98 if (strlen(flagName) != 0) { 99 flag |= stringToEnum(sInputFlagNameToEnumTable, 100 ARRAY_SIZE(sInputFlagNameToEnumTable), 101 flagName); 102 } 103 flagName = strtok(NULL, "|"); 104 } 105 return flag; 106} 107 108//static 109audio_devices_t ConfigParsingUtils::parseDeviceNames(char *name) 110{ 111 uint32_t device = 0; 112 113 char *devName = strtok(name, "|"); 114 while (devName != NULL) { 115 if (strlen(devName) != 0) { 116 device |= stringToEnum(sDeviceTypeToEnumTable, 117 ARRAY_SIZE(sDeviceTypeToEnumTable), 118 devName); 119 } 120 devName = strtok(NULL, "|"); 121 } 122 return device; 123} 124 125//static 126void ConfigParsingUtils::loadHwModule(cnode *root, HwModuleCollection &hwModules, 127 DeviceVector &availableInputDevices, 128 DeviceVector &availableOutputDevices, 129 sp<DeviceDescriptor> &defaultOutputDevices, 130 bool &isSpeakerDrcEnable) 131{ 132 status_t status = NAME_NOT_FOUND; 133 cnode *node; 134 sp<HwModule> module = new HwModule(root->name); 135 136 node = config_find(root, DEVICES_TAG); 137 if (node != NULL) { 138 node = node->first_child; 139 while (node) { 140 ALOGV("loadHwModule() loading device %s", node->name); 141 status_t tmpStatus = module->loadDevice(node); 142 if (status == NAME_NOT_FOUND || status == NO_ERROR) { 143 status = tmpStatus; 144 } 145 node = node->next; 146 } 147 } 148 node = config_find(root, OUTPUTS_TAG); 149 if (node != NULL) { 150 node = node->first_child; 151 while (node) { 152 ALOGV("loadHwModule() loading output %s", node->name); 153 status_t tmpStatus = module->loadOutput(node); 154 if (status == NAME_NOT_FOUND || status == NO_ERROR) { 155 status = tmpStatus; 156 } 157 node = node->next; 158 } 159 } 160 node = config_find(root, INPUTS_TAG); 161 if (node != NULL) { 162 node = node->first_child; 163 while (node) { 164 ALOGV("loadHwModule() loading input %s", node->name); 165 status_t tmpStatus = module->loadInput(node); 166 if (status == NAME_NOT_FOUND || status == NO_ERROR) { 167 status = tmpStatus; 168 } 169 node = node->next; 170 } 171 } 172 loadGlobalConfig(root, module, availableInputDevices, availableOutputDevices, 173 defaultOutputDevices, isSpeakerDrcEnable); 174 175 if (status == NO_ERROR) { 176 hwModules.add(module); 177 } 178} 179 180//static 181void ConfigParsingUtils::loadHwModules(cnode *root, HwModuleCollection &hwModules, 182 DeviceVector &availableInputDevices, 183 DeviceVector &availableOutputDevices, 184 sp<DeviceDescriptor> &defaultOutputDevices, 185 bool &isSpeakerDrcEnabled) 186{ 187 cnode *node = config_find(root, AUDIO_HW_MODULE_TAG); 188 if (node == NULL) { 189 return; 190 } 191 192 node = node->first_child; 193 while (node) { 194 ALOGV("loadHwModules() loading module %s", node->name); 195 loadHwModule(node, hwModules, availableInputDevices, availableOutputDevices, 196 defaultOutputDevices, isSpeakerDrcEnabled); 197 node = node->next; 198 } 199} 200 201//static 202void ConfigParsingUtils::loadGlobalConfig(cnode *root, const sp<HwModule>& module, 203 DeviceVector &availableInputDevices, 204 DeviceVector &availableOutputDevices, 205 sp<DeviceDescriptor> &defaultOutputDevice, 206 bool &speakerDrcEnabled) 207{ 208 cnode *node = config_find(root, GLOBAL_CONFIG_TAG); 209 210 if (node == NULL) { 211 return; 212 } 213 DeviceVector declaredDevices; 214 if (module != NULL) { 215 declaredDevices = module->mDeclaredDevices; 216 } 217 218 node = node->first_child; 219 while (node) { 220 if (strcmp(ATTACHED_OUTPUT_DEVICES_TAG, node->name) == 0) { 221 availableOutputDevices.loadDevicesFromTag((char *)node->value, 222 declaredDevices); 223 ALOGV("loadGlobalConfig() Attached Output Devices %08x", 224 availableOutputDevices.types()); 225 } else if (strcmp(DEFAULT_OUTPUT_DEVICE_TAG, node->name) == 0) { 226 audio_devices_t device = (audio_devices_t)stringToEnum( 227 sDeviceTypeToEnumTable, 228 ARRAY_SIZE(sDeviceTypeToEnumTable), 229 (char *)node->value); 230 if (device != AUDIO_DEVICE_NONE) { 231 defaultOutputDevice = new DeviceDescriptor(device); 232 } else { 233 ALOGW("loadGlobalConfig() default device not specified"); 234 } 235 ALOGV("loadGlobalConfig() mDefaultOutputDevice %08x", defaultOutputDevice->type()); 236 } else if (strcmp(ATTACHED_INPUT_DEVICES_TAG, node->name) == 0) { 237 availableInputDevices.loadDevicesFromTag((char *)node->value, 238 declaredDevices); 239 ALOGV("loadGlobalConfig() Available InputDevices %08x", availableInputDevices.types()); 240 } else if (strcmp(SPEAKER_DRC_ENABLED_TAG, node->name) == 0) { 241 speakerDrcEnabled = stringToBool((char *)node->value); 242 ALOGV("loadGlobalConfig() mSpeakerDrcEnabled = %d", speakerDrcEnabled); 243 } else if (strcmp(AUDIO_HAL_VERSION_TAG, node->name) == 0) { 244 uint32_t major, minor; 245 sscanf((char *)node->value, "%u.%u", &major, &minor); 246 module->mHalVersion = HARDWARE_DEVICE_API_VERSION(major, minor); 247 ALOGV("loadGlobalConfig() mHalVersion = %04x major %u minor %u", 248 module->mHalVersion, major, minor); 249 } 250 node = node->next; 251 } 252} 253 254//static 255status_t ConfigParsingUtils::loadAudioPolicyConfig(const char *path, 256 HwModuleCollection &hwModules, 257 DeviceVector &availableInputDevices, 258 DeviceVector &availableOutputDevices, 259 sp<DeviceDescriptor> &defaultOutputDevices, 260 bool &isSpeakerDrcEnabled) 261{ 262 cnode *root; 263 char *data; 264 265 data = (char *)load_file(path, NULL); 266 if (data == NULL) { 267 return -ENODEV; 268 } 269 root = config_node("", ""); 270 config_load(root, data); 271 272 loadHwModules(root, hwModules, 273 availableInputDevices, availableOutputDevices, 274 defaultOutputDevices, isSpeakerDrcEnabled); 275 // legacy audio_policy.conf files have one global_configuration section 276 loadGlobalConfig(root, hwModules.getModuleFromName(AUDIO_HARDWARE_MODULE_ID_PRIMARY), 277 availableInputDevices, availableOutputDevices, 278 defaultOutputDevices, isSpeakerDrcEnabled); 279 config_free(root); 280 free(root); 281 free(data); 282 283 ALOGI("loadAudioPolicyConfig() loaded %s\n", path); 284 285 return NO_ERROR; 286} 287 288}; // namespace android 289