Android系統可以通過配置audio_policy.conf文件,來實現不同產品的差異化,audio_policy.conf文件中,配置了當前項目audio策略中支持的輸入輸出設備,對應的播放模式,采樣率,采樣精度,聲道數等等。例如下面:
1 Primary { 2 sampling_rates 44100|48000 3 channel_masks AUDIO_CHANNEL_OUT_STEREO 4 formats AUDIO_FORMAT_PCM_16_BIT 5 devices AUDIO_DEVICE_OUT_EARPIECE|AUDIO_DEVICE_OUT_SPEAKER|AUDIO_DEVICE_OUT_WIRED_HEADSET|AUDIO_DEVICE_OUT_WIRED_HEADPHONE|AUDIO_DEVICE_OUT_ALL_SCO|AUDIO_DEVICE_OUT_PROXY|AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET|AUDIO_DEVICE_OUT_FM|AUDIO_DEVICE_OUT_FM_TX 6 flags AUDIO_OUTPUT_FLAG_PRIMARY 7 } 8 low_latency { 9 sampling_rates 44100|48000 10 channel_masks AUDIO_CHANNEL_OUT_STEREO 11 formats AUDIO_FORMAT_PCM_16_BIT 12 devices AUDIO_DEVICE_OUT_SPEAKER|AUDIO_DEVICE_OUT_EARPIECE|AUDIO_DEVICE_OUT_WIRED_HEADSET|AUDIO_DEVICE_OUT_WIRED_HEADPHONE|AUDIO_DEVICE_OUT_ALL_SCO|AUDIO_DEVICE_OUT_PROXY|AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET|AUDIO_DEVICE_OUT_FM|AUDIO_DEVICE_OUT_FM_TX 13 flags AUDIO_OUTPUT_FLAG_FAST 14 } 15 compress_offload { 16 sampling_rates 8000|11025|16000|22050|32000|44100|48000 17 channel_masks AUDIO_CHANNEL_OUT_MONO|AUDIO_CHANNEL_OUT_STEREO 18 formats AUDIO_FORMAT_MP3|AUDIO_FORMAT_AAC_LC|AUDIO_FORMAT_AAC_HE_V1|AUDIO_FORMAT_AAC_HE_V2 19 devices AUDIO_DEVICE_OUT_SPEAKER|AUDIO_DEVICE_OUT_EARPIECE|AUDIO_DEVICE_OUT_WIRED_HEADSET|AUDIO_DEVICE_OUT_WIRED_HEADPHONE|AUDIO_DEVICE_OUT_ALL_SCO|AUDIO_DEVICE_OUT_PROXY|AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET|AUDIO_DEVICE_OUT_FM_TX 20 flags AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD|AUDIO_OUTPUT_FLAG_NON_BLOCKING 21 }
1 a2dp { 2 outputs { 3 a2dp { 4 sampling_rates 44100 5 channel_masks AUDIO_CHANNEL_OUT_STEREO 6 formats AUDIO_FORMAT_PCM_16_BIT 7 devices AUDIO_DEVICE_OUT_ALL_A2DP 8 } 9 } 10 } 11 usb { 12 outputs { 13 usb_accessory { 14 sampling_rates 44100 15 channel_masks AUDIO_CHANNEL_OUT_STEREO 16 formats AUDIO_FORMAT_PCM_16_BIT 17 devices AUDIO_DEVICE_OUT_USB_ACCESSORY 18 } 19 usb_device { 20 sampling_rates dynamic 21 channel_masks dynamic 22 formats dynamic 23 devices AUDIO_DEVICE_OUT_USB_DEVICE 24 } 25 } 26 inputs { 27 usb_device { 28 sampling_rates dynamic 29 channel_masks AUDIO_CHANNEL_IN_STEREO 30 formats AUDIO_FORMAT_PCM_16_BIT 31 devices AUDIO_DEVICE_IN_USB_DEVICE 32 } 33 } 34 }
在AudioPolicyManager中會解析此文件,獲取此信息,那什么時候會需要修改此文件呢,例如:如果所在項目沒有聽筒設備,所以在接聽電話的時候需要默認切換到喇叭輸出,這個時候就需要修改此文件,把聽筒設備AUDIO_DEVICE_OUT_EARPIECE從所有場景下支持的輸出設備中刪除,這樣的話,就會切換到默認輸出設備喇叭下。這個文件的信息,也可以通過指令
adb shell dumpsys media.audio_policy 打印出來,如下:
1 HW Modules dump: 2 - HW Module 1: 3 - name: primary 4 - handle: 1 5 - version: 2.0 6 - outputs: 7 output 0: 8 - name: primary 9 - sampling rates: 44100, 48000 10 - channel masks: 0x0003 11 - formats: AUDIO_FORMAT_PCM_16_BIT 12 - flags: 0x0002 13 - devices: 14 Device 1: 15 - type: AUDIO_DEVICE_OUT_EARPIECE 16 Device 2: 17 - type: AUDIO_DEVICE_OUT_SPEAKER 18 Device 3: 19 - type: AUDIO_DEVICE_OUT_WIRED_HEADSET 20 Device 4: 21 - type: AUDIO_DEVICE_OUT_WIRED_HEADPHONE 22 Device 5: 23 - type: AUDIO_DEVICE_OUT_ALL_SCO 24 Device 6: 25 - type: AUDIO_DEVICE_OUT_PROXY 26 Device 7: 27 - type: AUDIO_DEVICE_OUT_AUX_DIGITAL 28 Device 8: 29 - type: AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET 30 Device 9: 31 - type: AUDIO_DEVICE_OUT_FM 32 Device 10: 33 - type: AUDIO_DEVICE_OUT_FM_TX 34 output 1: 35 - name: low_latency 36 - sampling rates: 44100, 48000 37 - channel masks: 0x0003 38 - formats: AUDIO_FORMAT_PCM_16_BIT 39 - flags: 0x0004 40 - devices: 41 Device 1: 42 - type: AUDIO_DEVICE_OUT_SPEAKER 43 Device 2: 44 - type: AUDIO_DEVICE_OUT_EARPIECE 45 Device 3: 46 - type: AUDIO_DEVICE_OUT_WIRED_HEADSET 47 Device 4: 48 - type: AUDIO_DEVICE_OUT_WIRED_HEADPHONE 49 Device 5: 50 - type: AUDIO_DEVICE_OUT_ALL_SCO 51 Device 6: 52 - type: AUDIO_DEVICE_OUT_AUX_DIGITAL 53 Device 7: 54 - type: AUDIO_DEVICE_OUT_PROXY 55 Device 8: 56 - type: AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET 57 Device 9: 58 - type: AUDIO_DEVICE_OUT_FM 59 Device 10:
在文件系統里,有兩個地方存放此文件/system/etc/audio_policy.conf 和 /vendor/etc/audio_policy.conf, 在創建AudioPolicyManager的時候會加載此配置文件:
1 AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterface) 2 { 3 /*將默認輸出設備設置成SPEAKER*/ 4 mDefaultOutputDevice = new DeviceDescriptor(String8(""), AUDIO_DEVICE_OUT_SPEAKER); 5 /*加載audio_policy.conf文件,先默認去加載vendor目錄下的文件,如果找不到就去加載system目錄下的*/ 6 if (loadAudioPolicyConfig(AUDIO_POLICY_VENDOR_CONFIG_FILE) != NO_ERROR) { 7 if (loadAudioPolicyConfig(AUDIO_POLICY_CONFIG_FILE) != NO_ERROR) { 8 ALOGE("could not load audio policy configuration file, setting defaults"); 9 /*如果兩個目錄都沒有找到,就去加載一個默認的配置,默認的配置中會創建一個Primary module, 10 為它創建一個默認的輸出設備speaker和默認輸出設備主Mic. 11 */ 12 defaultAudioPolicyConfig(); 13 } 14 } 15 16 /*把所有的輸入輸出設備都會操作打開一遍,檢查該設備是否是有效的*/ 17 // open all output streams needed to access attached devices 18 audio_devices_t outputDeviceTypes = mAvailableOutputDevices.types(); 19 audio_devices_t inputDeviceTypes = mAvailableInputDevices.types() & ~AUDIO_DEVICE_BIT_IN; 20 for (size_t i = 0; i < mHwModules.size(); i++) { 21 mHwModules[i]->mHandle = mpClientInterface->loadHwModule(mHwModules[i]->mName); 22 if (mHwModules[i]->mHandle == 0) { 23 ALOGW("could not open HW module %s", mHwModules[i]->mName); 24 continue; 25 } 26 // open all output streams needed to access attached devices 27 // except for direct output streams that are only opened when they are actually 28 // required by an app. 29 // This also validates mAvailableOutputDevices list 30 for (size_t j = 0; j < mHwModules[i]->mOutputProfiles.size(); j++) 31 { 32 const sp<IOProfile> outProfile = mHwModules[i]->mOutputProfiles[j]; 33 34 if (outProfile->mSupportedDevices.isEmpty()) { 35 ALOGW("Output profile contains no device on module %s", mHwModules[i]->mName); 36 continue; 37 } 38 39 if ((outProfile->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) != 0) { 40 continue; 41 } 42 audio_devices_t profileType = outProfile->mSupportedDevices.types(); 43 if ((profileType & mDefaultOutputDevice->mDeviceType) != AUDIO_DEVICE_NONE) { 44 profileType = mDefaultOutputDevice->mDeviceType; 45 } else { 46 // chose first device present in mSupportedDevices also part of 47 // outputDeviceTypes 48 for (size_t k = 0; k < outProfile->mSupportedDevices.size(); k++) { 49 profileType = outProfile->mSupportedDevices[k]->mDeviceType; 50 if ((profileType & outputDeviceTypes) != 0) { 51 break; 52 } 53 } 54 } 55 if ((profileType & outputDeviceTypes) == 0) { 56 continue; 57 } 58 sp<AudioOutputDescriptor> outputDesc = new AudioOutputDescriptor(outProfile); 59 60 outputDesc->mDevice = profileType; 61 audio_config_t config = AUDIO_CONFIG_INITIALIZER; 62 config.sample_rate = outputDesc->mSamplingRate; 63 config.channel_mask = outputDesc->mChannelMask; 64 config.format = outputDesc->mFormat; 65 audio_io_handle_t output = AUDIO_IO_HANDLE_NONE; 66 status_t status = mpClientInterface->openOutput(outProfile->mModule->mHandle, 67 &output, 68 &config, 69 &outputDesc->mDevice, 70 String8(""), 71 &outputDesc->mLatency, 72 outputDesc->mFlags); 73 74 if (status != NO_ERROR) { 75 ALOGW("Cannot open output stream for device %08x on hw module %s", 76 outputDesc->mDevice, 77 mHwModules[i]->mName); 78 } else { 79 outputDesc->mSamplingRate = config.sample_rate; 80 outputDesc->mChannelMask = config.channel_mask; 81 outputDesc->mFormat = config.format; 82 83 for (size_t k = 0; k < outProfile->mSupportedDevices.size(); k++) { 84 audio_devices_t type = outProfile->mSupportedDevices[k]->mDeviceType; 85 ssize_t index = 86 mAvailableOutputDevices.indexOf(outProfile->mSupportedDevices[k]); 87 /*如果打開的輸出設備有效,為它分配一個 有效的ID,賦值對應的module*/ 88 // give a valid ID to an attached device once confirmed it is reachable 89 if ((index >= 0) && (mAvailableOutputDevices[index]->mId == 0)) { 90 mAvailableOutputDevices[index]->mId = nextUniqueId(); 91 mAvailableOutputDevices[index]->mModule = mHwModules[i]; 92 } 93 } 94 if (mPrimaryOutput == 0 && 95 outProfile->mFlags & AUDIO_OUTPUT_FLAG_PRIMARY) { 96 mPrimaryOutput = output; 97 } 98 addOutput(output, outputDesc); 99 setOutputDevice(output, 100 outputDesc->mDevice, 101 true); 102 } 103 } 104 // open input streams needed to access attached devices to validate 105 // mAvailableInputDevices list 106 for (size_t j = 0; j < mHwModules[i]->mInputProfiles.size(); j++) 107 { 108 const sp<IOProfile> inProfile = mHwModules[i]->mInputProfiles[j]; 109 110 if (inProfile->mSupportedDevices.isEmpty()) { 111 ALOGW("Input profile contains no device on module %s", mHwModules[i]->mName); 112 continue; 113 } 114 // chose first device present in mSupportedDevices also part of 115 // inputDeviceTypes 116 audio_devices_t profileType = AUDIO_DEVICE_NONE; 117 for (size_t k = 0; k < inProfile->mSupportedDevices.size(); k++) { 118 profileType = inProfile->mSupportedDevices[k]->mDeviceType; 119 if (profileType & inputDeviceTypes) { 120 break; 121 } 122 } 123 if ((profileType & inputDeviceTypes) == 0) { 124 continue; 125 } 126 sp<AudioInputDescriptor> inputDesc = new AudioInputDescriptor(inProfile); 127 128 inputDesc->mInputSource = AUDIO_SOURCE_MIC; 129 inputDesc->mDevice = profileType; 130 131 // find the address 132 DeviceVector inputDevices = mAvailableInputDevices.getDevicesFromType(profileType); 133 // the inputs vector must be of size 1, but we don't want to crash here 134 String8 address = inputDevices.size() > 0 ? inputDevices.itemAt(0)->mAddress 135 : String8(""); 136 ALOGV(" for input device 0x%x using address %s", profileType, address.string()); 137 ALOGE_IF(inputDevices.size() == 0, "Input device list is empty!"); 138 139 audio_config_t config = AUDIO_CONFIG_INITIALIZER; 140 config.sample_rate = inputDesc->mSamplingRate; 141 config.channel_mask = inputDesc->mChannelMask; 142 config.format = inputDesc->mFormat; 143 audio_io_handle_t input = AUDIO_IO_HANDLE_NONE; 144 status_t status = mpClientInterface->openInput(inProfile->mModule->mHandle, 145 &input, 146 &config, 147 &inputDesc->mDevice, 148 address, 149 AUDIO_SOURCE_MIC, 150 AUDIO_INPUT_FLAG_NONE); 151 152 if (status == NO_ERROR) { 153 for (size_t k = 0; k < inProfile->mSupportedDevices.size(); k++) { 154 audio_devices_t type = inProfile->mSupportedDevices[k]->mDeviceType; 155 ssize_t index = 156 mAvailableInputDevices.indexOf(inProfile->mSupportedDevices[k]); 157 // give a valid ID to an attached device once confirmed it is reachable 158 if ((index >= 0) && (mAvailableInputDevices[index]->mId == 0)) { 159 mAvailableInputDevices[index]->mId = nextUniqueId(); 160 mAvailableInputDevices[index]->mModule = mHwModules[i]; 161 } 162 } 163 mpClientInterface->closeInput(input); 164 } else { 165 ALOGW("Cannot open input stream for device %08x on hw module %s", 166 inputDesc->mDevice, 167 mHwModules[i]->mName); 168 } 169 } 170 } 171 172 /*確認mAvailableOutputDevices設備列表中的所有輸出設備的id是有效的,如果無效,移除該設備*/ 173 // make sure all attached devices have been allocated a unique ID 174 for (size_t i = 0; i < mAvailableOutputDevices.size();) { 175 if (mAvailableOutputDevices[i]->mId == 0) { 176 ALOGW("Input device %08x unreachable", mAvailableOutputDevices[i]->mDeviceType); 177 mAvailableOutputDevices.remove(mAvailableOutputDevices[i]); 178 continue; 179 } 180 i++; 181 } 182 for (size_t i = 0; i < mAvailableInputDevices.size();) { 183 if (mAvailableInputDevices[i]->mId == 0) { 184 ALOGW("Input device %08x unreachable", mAvailableInputDevices[i]->mDeviceType); 185 mAvailableInputDevices.remove(mAvailableInputDevices[i]); 186 continue; 187 } 188 i++; 189 } 190 191 /*確認默認輸出設備是有效的*/ 192 // make sure default device is reachable 193 if (mAvailableOutputDevices.indexOf(mDefaultOutputDevice) < 0) { 194 ALOGE("Default device %08x is unreachable", mDefaultOutputDevice->mDeviceType); 195 } 196 197 ALOGE_IF((mPrimaryOutput == 0), "Failed to open primary output"); 198 199 /*更新下音頻策略*/ 200 updateDevicesAndOutputs(); 201 }
在創建AudioPolicyManager的時候,會load audio_policy.conf文件建立起有效輸出設備列表mAvailableOutputDevices 和有效輸入設備列表mAvailableInputDevices。
1 status_t AudioPolicyManager::loadAudioPolicyConfig(const char *path) 2 { 3 cnode *root; 4 char *data; 5 6 data = (char *)load_file(path, NULL); 7 if (data == NULL) { 8 return -ENODEV; 9 } 10 root = config_node("", ""); 11 config_load(root, data); 12 13 /*根據配置文件支持的module,分別load audio.<primary/a2dp/usb>.<device>.so 這三個so文件 */ 14 loadHwModules(root); 15 // legacy audio_policy.conf files have one global_configuration section 16 /*加載audio_policy.conf 中的global_configuration 配置*/ 17 loadGlobalConfig(root, getModuleFromName(AUDIO_HARDWARE_MODULE_ID_PRIMARY)); 18 config_free(root); 19 free(root); 20 free(data); 21 22 ALOGI("loadAudioPolicyConfig() loaded %s\n", path); 23 } 24 25
配置文件中可以看到,一般平台都會支持primary, a2dp, usb三中輸出方式,所以,這里會分別load三個module的so文件。如果兩個地方配置文件找不到,也會創建一個默認的primary module來進行音頻的輸入輸出。
為什么會想到看這個呢,是因為在播放的音樂的時候,選用播放模式的時候,會判斷是否可以用compress_offload模式,其中,有一項判斷,就是判斷它的設置是否在compress_offload支持的范圍,而compress_offload支持的參數,就是在此conf文件中配置的。
例如,它支持8k~48k之間的采樣率,支持MP3,AAC格式,支持常見的喇叭,聽筒,耳機等輸出,如果設置的參數,不在此配置內,就不能使用compress_offload模式進行播放
1 compress_offload { 2 sampling_rates 8000|11025|16000|22050|32000|44100|48000 3 channel_masks AUDIO_CHANNEL_OUT_MONO|AUDIO_CHANNEL_OUT_STEREO 4 formats AUDIO_FORMAT_MP3|AUDIO_FORMAT_AAC_LC|AUDIO_FORMAT_AAC_HE_V1|AUDIO_FORMAT_AAC_HE_V2 5 devices AUDIO_DEVICE_OUT_SPEAKER|AUDIO_DEVICE_OUT_EARPIECE|AUDIO_DEVICE_OUT_WIRED_HEADSET|AUDIO_DEVICE_OUT_WIRED_HEADPHONE|AUDIO_DEVICE_OUT_ALL_SCO|AUDIO_DEVICE_OUT_PROXY|AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET|AUDIO_DEVICE_OUT_FM_TX 6 flags AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD|AUDIO_OUTPUT_FLAG_NON_BLOCKING
2018/03/14 補充:
在舊的平台中,所有的音頻策略的配置都是在audio_policy.conf文件中配置的,但新的平台改到audio_policy_configuration.xml文件中配置了,大致內容一致。具體使用哪個文件是由USE_XML_AUDIO_POLICY_CONF 宏來控制,文件的解析和讀取是在AudioPolicyManager.cpp構造函數中。下面針對此做些小總結:
- USE_XML_AUDIO_POLICY_CONF 宏定義在hardware/qcom/audio/configs/sdm845/sdm845.mk 文件中
- audio_policy.conf和audio_policy_configuration.xml文件默認都放在源碼的 hardware/qcom/audio/configs/sdm845/目錄下
- 在解析讀取中,會依次讀取/odm/etc/, /vendor/etc/audio/, /vendor/etc/, /system/etc/這四個目錄
- 編譯的時候拷貝的是哪個目錄下面的配置文件,具體可參考hardware/qcom/audio/configs/sdm845/sdm845.mk文件
- 每次修改完文件,可以使用dumpsys media.audio_policy 查看修改是否已經生效,再進行測試。
- 關於audio_policy配置文件作用,audio_policy文件為音頻策略配置文件,里面配置此機器支持的輸入輸出設備即及對應支持的采樣率,聲道數和采樣精度。可根據項目具體 需求對其做一定程度的更改