支持多應用同時錄音_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().
我們假定這種場景: 讀同一個聲卡
- A 應用啓動 AudioRecord 讀數據,
- 接着 B 應用啓動 AudioRecord 讀數據,
- 然後 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修改方法