MTK8189 雙 MIC 設(shè)備強(qiáng)制單MIC錄制

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_MICAudioALSAHardwareResourceManager 在默認(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.xmlbuiltin_Mic_BackMic 的 turnon 序列同時(shí)打開(kāi)了左右 ADC(ADC_L_Mux + ADC_R_Mux),不滿(mǎn)足“單物理 MIC”目標(biāo)。

4. HAL 修改清單

4.1 修改文件

  1. vendor/vendor/mediatek/proprietary/hardware/audio/common/V3/include/AudioALSAHardware.h
  2. vendor/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 控制。
  • 原先 SET_MIC_CHOOSE=2 直接走 AUDIO_DEVICE_IN_BACK_MIC,已改為上述方式,避免命中 builtin_Mic_BackMic 的雙路配置。

5. 修改后實(shí)際生效流程

  1. APP 調(diào)用:AudioManager.setParameters("SET_MIC_CHOOSE=1|2")。
  2. AudioFlinger 全局參數(shù)下發(fā)到 HAL。
  3. AudioALSAHardware::setParameters()
    • 記錄 mSetMicChoose;
    • 設(shè)置 BuiltInMicSpecificTypeMIC1_ONLYMIC2_ONLY。
  4. 錄音建鏈 createAudioPatch()
    • 輸入設(shè)備保持 AUDIO_DEVICE_IN_BUILTIN_MIC;
    • StreamManager -> CaptureHandler -> HardwareResourceManager 生效。
  5. 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.xmlbuiltin_Mic_Mic1 / builtin_Mic_Mic2 生效單麥控件。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容