Android Audio - 支持多應用同時錄音_Android5.1 & Android6.0 修改方法

支持多應用同時錄音_Android5.1 & Android6.0 修改方法

修改方法

源碼路徑: sdk\frameworks\av\services\audiopolicy\managerdefault\AudioPolicyManager.cpp

在 status_t AudioPolicyManager::getInputForAttr()
mpClientInterface->openInput 前添加:
#ifdef ANDROID6_0_SUPPORT_MULIT_CHANNEL_RECORDING
	// Modify Tower 20181118: check wether have an AudioInputDescriptor Use the same profile
	for (size_t input_index = 0; input_index < mInputs.size(); input_index++) {
		sp<AudioInputDescriptor> desc;
		desc = mInputs.valueAt(input_index);
	        if (desc->mProfile == profile) {
	        // desc->mRefCount++               // Modify 20200314 Tower.
			desc->mOpenRefCount++;             // Open reference count add.
			desc->mSessions.add(session);
		    *input = desc->mIoHandle;
			return NO_ERROR;
		} 
	}
#endif

20200314 補丁更新說明: mRefCount 和 mOpenRefCount 的區別

使用 AudioRecord 的流程:
startInput() -> read() -> stopInput() -> releaseInput() -> closeInput().

  • inputDesc->mRefCount (int型, 初始值是0)
    這個值僅僅在 startInput() 和 stopInput() 中起做用, 不會觸發 HAL 層 close_input_stream 的動作.

  • inputDesc->mOpenRefCount (int型, 初始值是1)
    這個值僅在 releaseInput() 函數中起作用, 用於表示當前有幾個 AudioRecord 在使用 inputDesc 指向的HAL, 如果 mOpenRefCount == 0, 則會觸發 closeInput() 調用 HAL::close_input_stream().

我們假定這種場景: 讀同一個聲卡

  1. A 應用啓動 AudioRecord 讀數據,
  2. 接着 B 應用啓動 AudioRecord 讀數據,
  3. 然後 B 應用停止 AudioRecord. 觸發了 stopInput(), 進而觸發 releaseInput(). 這種場景下A會怎麼樣?

如果本補丁對 mRefCount++, 在 B 停止的時候, 由於最後調用 releaseInput() 對 mOpenRefCount–, 等於零的情況會立馬執行 closeInput() 關閉底層聲卡, 導致 A 應用暫停錄音, 這個時候有兩種情況發生:
1: A 應用處於未 AudioRecord::read() 情況下, 後續調用將無效.
2: A 應用處於 AudioRecord::read() 情況下, AudioRecord:: restoreRecord_l("obtainBuffer") 重啓錄音.

如果本補丁對 mOpenRefCount++, 以上的情況不會發生, B 在停止錄音時, 如果當前還有其他應用(A)在使用的情況下, 不會關閉底層聲卡. 規避了上述兩種情況發生. 所以更新補丁.

  • 關鍵代碼片供參考
status_t AudioPolicyManager::stopInput(audio_io_handle_t input,
                                       audio_session_t session)
{
    // ...
    inputDesc->mRefCount--;
    if (inputDesc->mRefCount == 0) {
        // ...
        resetInputDevice(input);
        // ...
        inputDesc->clearPreemptedSessions();
    }
    return NO_ERROR;
}
void AudioPolicyManager::releaseInput(audio_io_handle_t input,
                                      audio_session_t session)
{
    // ...
    inputDesc->mOpenRefCount--;
    if (inputDesc->mOpenRefCount > 0) {
        ALOGV("releaseInput() exit > 0");
        return;
    }

    closeInput(input);
    // ...
    ALOGV("releaseInput() exit");
}

與之相關

Android Audio - 音頻子系統框架簡析
Android Audio - 支持多應用同時錄音_Android4.4修改方法
Android Audio - 支持多應用同時錄音_Android8.1修改方法

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章