1. 背景
- 平臺(tái):MTK8189,系統(tǒng)已開(kāi)啟雙 MIC 支持。
- 目標(biāo):上層通過(guò)
AudioManager.setParameters("SET_MIC_CHOOSE=1|2")選擇單路物理 MIC 錄制。-
1:主 MIC -
2:副 MIC
-
2. 現(xiàn)象與問(wèn)題
- APP使用AudioManager.getDevices驗(yàn)證設(shè)置 input device 后仍無(wú)法強(qiáng)制設(shè)置單MIC錄制,實(shí)際還是雙MIC錄音。
- 堵住左 MIC 仍可錄音;
- 堵住右 MIC 仍可錄音;
- 僅同時(shí)堵住兩個(gè) MIC 才明顯無(wú)聲。
- 結(jié)論:實(shí)際采集鏈路仍處于雙 MIC 生效狀態(tài),而非單物理 MIC。
3. 根因分析
3.1 路由設(shè)備與物理單麥并不等價(jià)
- 即使路由為
AUDIO_DEVICE_IN_BUILTIN_MIC,AudioALSAHardwareResourceManager在默認(rèn)場(chǎng)景會(huì)按mNumPhoneMicSupport選擇SingleMic/DualMic/ThreeMic。 - 在雙 MIC 機(jī)型上,默認(rèn)常落到
builtin_Mic_DualMic,仍會(huì)開(kāi)啟左右 ADC。
3.2 BackMic 路徑本身也是雙路配置
-
audio_device.xml中builtin_Mic_BackMic的 turnon 序列同時(shí)打開(kāi)了左右 ADC(ADC_L_Mux+ADC_R_Mux),不滿(mǎn)足“單物理 MIC”目標(biāo)。
4. HAL 修改清單
4.1 修改文件
vendor/vendor/mediatek/proprietary/hardware/audio/common/V3/include/AudioALSAHardware.hvendor/vendor/mediatek/proprietary/hardware/audio/common/V3/aud_drv/AudioALSAHardware.cpp
4.2 修改點(diǎn)
A) 新增全局狀態(tài):mSetMicChoose
- 在
AudioALSAHardware中新增成員:volatile int32_t mSetMicChoose;- 語(yǔ)義:
0=默認(rèn),1=主單麥,2=副單麥。
- 構(gòu)造函數(shù)初始化為
0。
B) 新增參數(shù)鍵:SET_MIC_CHOOSE
- 在
AudioALSAHardware::setParameters()中解析:-
SET_MIC_CHOOSE=1->mSetMicChoose=1 -
SET_MIC_CHOOSE=2->mSetMicChoose=2 - 其他值 ->
mSetMicChoose=0
-
C) 關(guān)鍵增強(qiáng):聯(lián)動(dòng) ResourceManager 選擇單麥序列
- 同時(shí)調(diào)用
AudioALSAHardwareResourceManager::setBuiltInMicSpecificType(...):-
1->BUILTIN_MIC_MIC1_ONLY -
2->BUILTIN_MIC_MIC2_ONLY -
0->BUILTIN_MIC_DEFAULT
-
強(qiáng)制切換到底層“單麥專(zhuān)用 turnon sequence”。
D) 調(diào)整 createAudioPatch() 輸入設(shè)備覆蓋策略
- 當(dāng)
mSetMicChoose=1/2且當(dāng)前輸入為內(nèi)置 MIC 家族時(shí):- 統(tǒng)一覆蓋為
AUDIO_DEVICE_IN_BUILTIN_MIC路由; - 具體主/副區(qū)分由上一步
MIC1_ONLY/MIC2_ONLY控制。
- 統(tǒng)一覆蓋為
- 原先
SET_MIC_CHOOSE=2直接走AUDIO_DEVICE_IN_BACK_MIC,已改為上述方式,避免命中builtin_Mic_BackMic的雙路配置。
5. 修改后實(shí)際生效流程
- APP 調(diào)用:
AudioManager.setParameters("SET_MIC_CHOOSE=1|2")。 - AudioFlinger 全局參數(shù)下發(fā)到 HAL。
-
AudioALSAHardware::setParameters():- 記錄
mSetMicChoose; - 設(shè)置
BuiltInMicSpecificType為MIC1_ONLY或MIC2_ONLY。
- 記錄
- 錄音建鏈
createAudioPatch():- 輸入設(shè)備保持
AUDIO_DEVICE_IN_BUILTIN_MIC; -
StreamManager -> CaptureHandler -> HardwareResourceManager生效。
- 輸入設(shè)備保持
-
AudioALSAHardwareResourceManager::startInputDevice_l():- 命中
BUILTIN_MIC_MIC1_ONLY/BUILTIN_MIC_MIC2_ONLY對(duì)應(yīng) turnon 序列; - 從
audio_device.xml應(yīng)用相應(yīng)kctl,形成單路物理 MIC 采集。
- 命中
6. 關(guān)聯(lián)配置說(shuō)明
- 具體
kctl序列定義文件:vendor/device/mediatek/mt8189/audio_device.xml- 運(yùn)行時(shí)對(duì)應(yīng)
/vendor/etc/audio_device.xml
- 典型路徑:
-
builtin_Mic_Mic1(單路主麥) -
builtin_Mic_Mic2(單路副麥) -
builtin_Mic_DualMic(雙路,非本次目標(biāo)) -
builtin_Mic_BackMic(該路徑配置可同時(shí)啟用左右 ADC)
-
7. 結(jié)果
-
SET_MIC_CHOOSE=1/2不再僅停留在“設(shè)備路由偏好”層面, - 而是下沉到 HAL 側(cè)單麥序列控制,解決“堵單孔仍有聲”的雙 MIC 同時(shí)生效問(wèn)題。
8. 新增/修改代碼(可直接對(duì)照)
8.1 AudioALSAHardware.h
// App sets this through "SET_MIC_CHOOSE=1/2" to force single-mic path.
// 0: default by policy, 1: primary single mic, 2: secondary single mic.
volatile int32_t mSetMicChoose;
8.2 AudioALSAHardware.cpp - 新增 key 定義
// App manual mic selection: 1 = primary single mic, 2 = secondary single mic.
static String8 keySetMicChoose = String8("SET_MIC_CHOOSE");
8.3 AudioALSAHardware.cpp - 構(gòu)造初始化
AudioALSAHardware::AudioALSAHardware() :
...
mSetMicChoose(0),
mFmTxEnable(false),
...
8.4 AudioALSAHardware.cpp - setParameters() 中新增解析
if (param.getInt(keySetMicChoose, value) == NO_ERROR) {
param.remove(keySetMicChoose);
// 0: default routing, 1: primary single mic, 2: secondary single mic
if (value == 1 || value == 2) {
mSetMicChoose = value;
} else {
mSetMicChoose = 0;
}
// Force single physical mic sequence in resource manager.
// 1 -> Mic1 only, 2 -> Mic2 only, 0 -> default policy sequence.
if (mSetMicChoose == 1) {
AudioALSAHardwareResourceManager::getInstance()->setBuiltInMicSpecificType(BUILTIN_MIC_MIC1_ONLY);
} else if (mSetMicChoose == 2) {
AudioALSAHardwareResourceManager::getInstance()->setBuiltInMicSpecificType(BUILTIN_MIC_MIC2_ONLY);
} else {
AudioALSAHardwareResourceManager::getInstance()->setBuiltInMicSpecificType(BUILTIN_MIC_DEFAULT);
}
ALOGD("%s(), %s=%d (effective=%d)", __FUNCTION__,
keySetMicChoose.c_str(), value, (int)mSetMicChoose);
}
8.5 AudioALSAHardware.cpp - createAudioPatch() 中輸入設(shè)備覆蓋
eInputDeviceList = initDeviceVector(sources[0].ext.device.type);
eInputSource = sinks[0].ext.mix.usecase.source;
if (!isEqualDevice(eInputDeviceList, AUDIO_DEVICE_IN_FM_TUNER) &&
!isEqualDevice(eInputDeviceList, AUDIO_DEVICE_IN_TELEPHONY_RX)) {
if (mSetMicChoose == 1 &&
(hasTargetDevice(eInputDeviceList, AUDIO_DEVICE_IN_BUILTIN_MIC) ||
hasTargetDevice(eInputDeviceList, AUDIO_DEVICE_IN_BACK_MIC))) {
eInputDeviceList = initDeviceVector(AUDIO_DEVICE_IN_BUILTIN_MIC);
ALOGD("%s(), force input to primary single mic by %s=1",
__FUNCTION__, keySetMicChoose.c_str());
} else if (mSetMicChoose == 2 &&
(hasTargetDevice(eInputDeviceList, AUDIO_DEVICE_IN_BUILTIN_MIC) ||
hasTargetDevice(eInputDeviceList, AUDIO_DEVICE_IN_BACK_MIC))) {
// Use built-in-mic path with MIC2_ONLY to avoid dual-mic back path.
eInputDeviceList = initDeviceVector(AUDIO_DEVICE_IN_BUILTIN_MIC);
ALOGD("%s(), force input to secondary single mic by %s=2",
__FUNCTION__, keySetMicChoose.c_str());
}
}
8.6 改造目的與這段代碼的對(duì)應(yīng)關(guān)系
-
mSetMicChoose:保存 App 選擇態(tài); -
setBuiltInMicSpecificType(MIC1_ONLY/MIC2_ONLY):把選擇下沉到“單麥 turnon 序列”; -
createAudioPatch統(tǒng)一走BUILTIN_MIC:避免命中BackMic雙路 path; - 最終由
audio_device.xml的builtin_Mic_Mic1/builtin_Mic_Mic2生效單麥控件。