Android支持多个应用同时录音
Android 7.x和Android 8.1版本修改
共两个修改点:
(1) 修改函数:audio_io_handle_t AudioPolicyManager::getInputForDevice()
需要在mpClientInterface->openInput前添加如下代码:
#ifdef ANDROIDN_SUPPORT_MULIT_CHANNEL_RECORDING
for (size_t input_index = 0; input_index < mInputs.size(); input_index++) {
sp<AudioInputDescriptor> desc;
desc = mInputs.valueAt(input_index);
if (desc->mProfile == profile) {
audioSession->changeActiveCount(1);
desc->addAudioSession(session, audioSession);
return desc->mIoHandle;
}
}
#endif
(2)修改函数:status_t AudioPolicyManager::startInput()
注释掉以下代码段
#ifndef ANDROIDN_SUPPORT_MULTI_CHANNEL_RECORDING
// virtual input devices are compatible with other input devices
if (!is_virtual_input_device(inputDesc->mDevice)) {
// for a non-virtual input device, check if there is another (non-virtual) active input
audio_io_handle_t activeInput = mInputs.getActiveInput();
if (activeInput != 0 && activeInput != input) {
// If the already active input uses AUDIO_SOURCE_HOTWORD then it is closed,
// otherwise the active input continues and the new input cannot be started.
sp<AudioInputDescriptor> activeDesc = mInputs.valueFor(activeInput);
if ((activeDesc->inputSource() == AUDIO_SOURCE_HOTWORD) &&
!activeDesc->hasPreemptedSession(session)) {
ALOGW("startInput(%d) preempting low-priority input %d", input, activeInput);
//FIXME: consider all active sessions
AudioSessionCollection activeSessions = activeDesc->getActiveAudioSessions();
audio_session_t activeSession = activeSessions.keyAt(0);
SortedVector<audio_session_t> sessions =
activeDesc->getPreemptedSessions();
sessions.add(activeSession);
inputDesc->setPreemptedSessions(sessions);
stopInput(activeInput, activeSession);
releaseInput(activeInput, activeSession);
} else {
ALOGE("startInput(%d) failed: other input %d already started", input, activeInput);
return INVALID_OPERATION;
}
}
// Do not allow capture if an active voice call is using a software patch and
// the call TX source device is on the same HW module.
// FIXME: would be better to refine to only inputs whose profile connects to the
// call TX device but this information is not in the audio patch
if (mCallTxPatch != 0 &&
inputDesc->getModuleHandle() == mCallTxPatch->mPatch.sources[0].ext.device.hw_module) {
return INVALID_OPERATION;
}
}
#endif
补丁如下:
Date: Thu Oct 27 13:41:11 2022 +0800
add support multi audio recorder.
diff --git a/android/frameworks/av/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/android/frameworks/av/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 00fd05a6c1..dcc521712a 100755
--- a/android/frameworks/av/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/android/frameworks/av/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -24,6 +24,7 @@
#define ALOGVV(a...) do { } while(0)
#endif
+#define ANDROIDN_SUPPORT_MULTI_CHANNEL_RECORDING
#define AUDIO_POLICY_XML_CONFIG_FILE "/system/etc/audio_policy_configuration.xml"
#include <inttypes.h>
@@ -1518,12 +1519,12 @@ audio_io_handle_t AudioPolicyManager::getInputForDevice(audio_devices_t device,
policyMix, mpClientInterface);
// TODO enable input reuse
+#ifdef ANDROIDN_SUPPORT_MULTI_CHANNEL_RECORDING
+ // Modify YMF 20221027: check wether have an AudioInputDescriptor Use the same profile
+ for (size_t input_index = 0; input_index < mInputs.size(); input_index++) {
+ sp<AudioInputDescriptor> desc = mInputs.valueAt(input_index);
+ if (desc->mProfile == profile) {
+ audioSession->changeActiveCount(1); // reference count add
+ desc->addAudioSession(session, audioSession);
+ return desc->mIoHandle;
+ }
+ }
+#endif
@@ -1603,6 +1613,9 @@ status_t AudioPolicyManager::startInput(audio_io_handle_t input,
return BAD_VALUE;
}
+ // TODO enable input reuse
+ // Modify YMF 20221027
+#ifndef ANDROIDN_SUPPORT_MULTI_CHANNEL_RECORDING
// virtual input devices are compatible with other input devices
if (!is_virtual_input_device(inputDesc->mDevice)) {
@@ -1640,7 +1653,7 @@ status_t AudioPolicyManager::startInput(audio_io_handle_t input,
return INVALID_OPERATION;
}
}
-
+#endif
// Routing?
mInputRoutes.incRouteActivity(session);
补丁优化(修复百度语音识别可以出现崩溃的情况)
共两个修改点:
(1) 修改函数:audio_io_handle_t AudioPolicyManager::getInputForDevice()
需要在mpClientInterface->openInput前添加如下代码:
// TODO enable input reuse
#ifdef ANDROIDN_SUPPORT_MULTI_CHANNEL_RECORDING
// reuse an open input if possible
for (size_t i = 0; i < mInputs.size(); i++) {
sp<AudioInputDescriptor> desc = mInputs.valueAt(i);
// reuse input if it shares the same profile and same sound trigger attribute
if (profile == desc->mProfile &&
isSoundTrigger == desc->isSoundTrigger()) {
sp<AudioSession> as = desc->getAudioSession(session);
if (as != 0) {
// do not allow unmatching properties on same session
if (as->matches(audioSession)) {
as->changeOpenCount(1);
} else {
ALOGW("getInputForDevice() record with different attributes"
" exists for session %d", session);
return input;
}
} else {
desc->addAudioSession(session, audioSession);
}
ALOGV("getInputForDevice() reusing input %d", mInputs.keyAt(i));
return mInputs.keyAt(i);
}
}
#endif
(2)修改函数:status_t AudioPolicyManager::startInput()
// TODO enable input reuse
// Modify YMF 20221027
// virtual input devices are compatible with other input devices
if (!is_virtual_input_device(inputDesc->mDevice)) {
// for a non-virtual input device, check if there is another (non-virtual) active input
audio_io_handle_t activeInput = mInputs.getActiveInput();
if (activeInput != 0 && activeInput != input) {
// If the already active input uses AUDIO_SOURCE_HOTWORD then it is closed,
// otherwise the active input continues and the new input cannot be started.
sp<AudioInputDescriptor> activeDesc = mInputs.valueFor(activeInput);
#ifndef ANDROIDN_SUPPORT_MULTI_CHANNEL_RECORDING
if ((activeDesc->inputSource() == AUDIO_SOURCE_HOTWORD) &&
!activeDesc->hasPreemptedSession(session)) {
ALOGW("startInput(%d) preempting low-priority input %d", input, activeInput);
//FIXME: consider all active sessions
AudioSessionCollection activeSessions = activeDesc->getActiveAudioSessions();
audio_session_t activeSession = activeSessions.keyAt(0);
SortedVector<audio_session_t> sessions =
activeDesc->getPreemptedSessions();
sessions.add(activeSession);
inputDesc->setPreemptedSessions(sessions);
stopInput(activeInput, activeSession);
releaseInput(activeInput, activeSession);
} else {
ALOGE("startInput(%d) failed: other input %d already started", input, activeInput);
return INVALID_OPERATION;
}
#else
ALOGW("startInput(%d) preempting low-priority input %d", input, activeInput);
//FIXME: consider all active sessions
AudioSessionCollection activeSessions = activeDesc->getActiveAudioSessions();
audio_session_t activeSession = activeSessions.keyAt(0);
SortedVector<audio_session_t> sessions = activeDesc->getPreemptedSessions();
sessions.add(activeSession);
inputDesc->setPreemptedSessions(sessions);
stopInput(activeInput, activeSession);
releaseInput(activeInput, activeSession);
#endif
}
// Do not allow capture if an active voice call is using a software patch and
// the call TX source device is on the same HW module.
// FIXME: would be better to refine to only inputs whose profile connects to the
// call TX device but this information is not in the audio patch
if (mCallTxPatch != 0 &&
inputDesc->getModuleHandle() == mCallTxPatch->mPatch.sources[0].ext.device.hw_module) {
return INVALID_OPERATION;
}
}