当调用AudioManager的setParameters方法后,AudioManager会通过AudioSystem调用到AudioFlinger的setParameters:
//frameworks/av/services/audioflinger/AudioFlinger.cpp
status_t AudioFlinger::setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs)
{
ALOGV("setParameters(): io %d, keyvalue %s, calling pid %d calling uid %d",
ioHandle, keyValuePairs.string(),
IPCThreadState::self()->getCallingPid(), IPCThreadState::self()->getCallingUid());
// check calling permissions
if (!settingsAllowed()) {
return PERMISSION_DENIED;
}
String8 filteredKeyValuePairs = keyValuePairs;
filterReservedParameters(filteredKeyValuePairs, IPCThreadState::self()->getCallingUid());
ALOGV("%s: filtered keyvalue %s", __func__, filteredKeyValuePairs.string());
// AUDIO_IO_HANDLE_NONE means the parameters are global to the audio hardware interface
if (ioHandle == AUDIO_IO_HANDLE_NONE) {
Mutex::Autolock _l(mLock);
// result will remain NO_INIT if no audio device is present
status_t final_result = NO_INIT;
{
AutoMutex lock(mHardwareLock);
mHardwareStatus = AUDIO_HW_SET_PARAMETER;
for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
sp<DeviceHalInterface> dev = mAudioHwDevs.valueAt(i)->hwDevice(); //取得DeviceHalInterface
status_t result = dev->setParameters(filteredKeyValuePairs); //调用DeviceHalInterface的setParameters方法
// return success if at least one audio device accepts the parameters as not all
// HALs are requested to support all parameters. If no audio device supports the
// requested parameters, the last error is reported.
if (final_result != NO_ERROR) {
final_result = result;
}
}
mHardwareStatus = AUDIO_HW_IDLE;
}
// disable AEC and NS if the device is a BT SCO headset supporting those pre processings
// 如果设备是支持这些预处理的 BT SCO 耳机,请禁用 AEC 和 NS
AudioParameter param = AudioParameter(filteredKeyValuePairs);
String8 value;
if (param.get(String8(AudioParameter::keyBtNrec), value) == NO_ERROR) {
bool btNrecIsOff = (value == AudioParameter::valueOff);
if (mBtNrecIsOff.exchange(btNrecIsOff) != btNrecIsOff) {
for (size_t i = 0; i < mRecordThreads.size(); i++) {
mRecordThreads.valueAt(i)->checkBtNrec();
}
}
}
String8 screenState;
if (param.get(String8(AudioParameter::keyScreenState), screenState) == NO_ERROR) {
bool isOff = (screenState == AudioParameter::valueOff);
if (isOff != (AudioFlinger::mScreenState & 1)) {
AudioFlinger::mScreenState = ((AudioFlinger::mScreenState & ~1) + 2) | isOff;
}
}
return final_result;
}
// hold a strong ref on thread in case closeOutput() or closeInput() is called
// and the thread is exited once the lock is released
sp<ThreadBase> thread;
{
Mutex::Autolock _l(mLock);
thread = checkPlaybackThread_l(ioHandle);
if (thread == 0) {
thread = checkRecordThread_l(ioHandle);
if (thread == 0) {
thread = checkMmapThread_l(ioHandle);
}
} else if (thread == primaryPlaybackThread_l()) {
// indicate output device change to all input threads for pre processing
AudioParameter param = AudioParameter(filteredKeyValuePairs);
int value;
if ((param.getInt(String8(AudioParameter::keyRouting), value) == NO_ERROR) &&
(value != 0)) {
broadcastParametersToRecordThreads_l(filteredKeyValuePairs);
}
}
}
if (thread != 0) {
status_t result = thread->setParameters(filteredKeyValuePairs);
forwardParametersToDownstreamPatches_l(thread->id(), filteredKeyValuePairs);
return result;
}
return BAD_VALUE;
}
调用DeviceHalInterface的setParameters方法,DeviceHalInterface由DeviceHalHidl继承:
//frameworks/av/media/libaudiohal/impl/DeviceHalHidl.h
class DeviceHalHidl : public DeviceHalInterface, public CoreConversionHelperHidl
//frameworks/av/media/libaudiohal/impl/DeviceHalHidl.cpp
status_t DeviceHalHidl::setParameters(const String8& kvPairs) {
TIME_CHECK();
if (mDevice == 0) return NO_INIT;
hidl_vec<ParameterValue> hidlParams;
status_t status = parametersFromHal(kvPairs, &hidlParams);
if (status != OK) return status;
// TODO: change the API so that context and kvPairs are separated
return processReturn("setParameters",
utils::setParameters(mDevice, {} /* context */, hidlParams));
}
调用ParamentrUtils.h的setParameters方法:
//frameworks/av/media/libaudiohal/impl/ParamentrUtils.h
Return<Result> setParameters(T& object, hidl_vec<ParameterValue> context,
hidl_vec<ParameterValue> keys) {
return object->setParameters(context, keys);
}
在这之后就是AudioHAL的处理了。