AudioFlinger在进行RecordTrack相关操作时需要先创建RecordTrack,在JAVA层AudioRecord的构造函数中会通过JNI调用C++层AudioRecord的set函数,在AudioRecord的set函数中会调用通过AudioSystem获取IAudioFlinger,然后调用AudioFlinger的createRecord函数,从AudioRecord到IAudioFlinger的部分在AudioRecord已经分析过了,下面我们继续分析AudioFlinger的部分:
RecordTrack在AudioFlinger的createRecord函数中调用:
//frameworks/av/services/audioflinger/AudioFlinger.cpp
status_t AudioFlinger::createRecord(const media::CreateRecordRequest& _input,
media::CreateRecordResponse& _output)
{
CreateRecordInput input = VALUE_OR_RETURN_STATUS(CreateRecordInput::fromAidl(_input));
CreateRecordOutput output;
sp<RecordThread::RecordTrack> recordTrack;
sp<RecordHandle> recordHandle;
sp<Client> client;
status_t lStatus;
audio_session_t sessionId = input.sessionId;
audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE;
output.cblk.clear();
output.buffers.clear();
output.inputId = AUDIO_IO_HANDLE_NONE;
// TODO b/182392553: refactor or clean up
AttributionSourceState adjAttributionSource = input.clientInfo.attributionSource;
bool updatePid = (adjAttributionSource.pid == -1);
const uid_t callingUid = IPCThreadState::self()->getCallingUid();
const uid_t currentUid = VALUE_OR_RETURN_STATUS(legacy2aidl_uid_t_int32_t(
adjAttributionSource.uid));
if (!isAudioServerOrMediaServerUid(callingUid)) {
ALOGW_IF(currentUid != callingUid,
"%s uid %d tried to pass itself off as %d",
__FUNCTION__, callingUid, currentUid);
adjAttributionSource.uid = VALUE_OR_RETURN_STATUS(legacy2aidl_uid_t_int32_t(callingUid));
updatePid = true;
}
const pid_t callingPid = IPCThreadState::self()->getCallingPid();
const pid_t currentPid = VALUE_OR_RETURN_STATUS(aidl2legacy_int32_t_pid_t(
adjAttributionSource.pid));
if (updatePid) {
ALOGW_IF(currentPid != (pid_t)-1 && currentPid != callingPid,
"%s uid %d pid %d tried to pass itself off as pid %d",
__func__, callingUid, callingPid, currentPid);
adjAttributionSource.pid = VALUE_OR_RETURN_STATUS(legacy2aidl_pid_t_int32_t(callingPid));
}
// we don't yet support anything other than linear PCM
if (!audio_is_valid_format(input.config.format) || !audio_is_linear_pcm(input.config.format)) {
ALOGE("createRecord() invalid format %#x", input.config.format);
lStatus = BAD_VALUE;
goto Exit;
}
// further channel mask checks are performed by createRecordTrack_l()
if (!audio_is_input_channel(input.config.channel_mask)) {
ALOGE("createRecord() invalid channel mask %#x", input.config.channel_mask);
lStatus = BAD_VALUE;
goto Exit;
}
if (sessionId == AUDIO_SESSION_ALLOCATE) {
sessionId = (audio_session_t) newAudioUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
} else if (audio_unique_id_get_use(sessionId) != AUDIO_UNIQUE_ID_USE_SESSION) {
lStatus = BAD_VALUE;
goto Exit;
}
output.sessionId = sessionId;
output.selectedDeviceId = input.selectedDeviceId;
output.flags = input.flags;
client = registerPid(VALUE_OR_FATAL(aidl2legacy_int32_t_pid_t(adjAttributionSource.pid)));
// Not a conventional loop, but a retry loop for at most two iterations total.
// Try first maybe with FAST flag then try again without FAST flag if that fails.
// Exits loop via break on no error of got exit on error
// The sp<> references will be dropped when re-entering scope.
// The lack of indentation is deliberate, to reduce code churn and ease merges.
for (;;) {
// release previously opened input if retrying.
if (output.inputId != AUDIO_IO_HANDLE_NONE) {
recordTrack.clear();
AudioSystem::releaseInput(portId);
output.inputId = AUDIO_IO_HANDLE_NONE;
output.selectedDeviceId = input.selectedDeviceId;
portId = AUDIO_PORT_HANDLE_NONE;
}
lStatus = AudioSystem::getInputForAttr(&input.attr, &output.inputId,
input.riid,
sessionId,
// FIXME compare to AudioTrack
adjAttributionSource,
&input.config,
output.flags, &output.selectedDeviceId, &portId);
if (lStatus != NO_ERROR) {
ALOGE("createRecord() getInputForAttr return error %d", lStatus);
goto Exit;
}
{
Mutex::Autolock _l(mLock);
RecordThread *thread = checkRecordThread_l(output.inputId);
if (thread == NULL) {
ALOGW("createRecord() checkRecordThread_l failed, input handle %d", output.inputId);
lStatus = FAILED_TRANSACTION;
goto Exit;
}
ALOGV("createRecord() lSessionId: %d input %d", sessionId, output.inputId);
output.sampleRate = input.config.sample_rate;
output.frameCount = input.frameCount;
output.notificationFrameCount = input.notificationFrameCount;
recordTrack = thread->createRecordTrack_l(client, input.attr, &output.sampleRate, //创建recordTrack
input.config.format, input.config.channel_mask,
&output.frameCount, sessionId,
&output.notificationFrameCount,
callingPid, adjAttributionSource, &output.flags,
input.clientInfo.clientTid,
&lStatus, portId, input.maxSharedAudioHistoryMs);
LOG_ALWAYS_FATAL_IF((lStatus == NO_ERROR) && (recordTrack == 0));
// lStatus == BAD_TYPE means FAST flag was rejected: request a new input from
// audio policy manager without FAST constraint
if (lStatus == BAD_TYPE) {
continue;
}
if (lStatus != NO_ERROR) {
goto Exit;
}
if (recordTrack->isFastTrack()) {
output.serverConfig = {
thread->sampleRate(),
thread->channelMask(),
thread->format()
};
} else {
output.serverConfig = {
recordTrack->sampleRate(),
recordTrack->channelMask(),
recordTrack->format()
};
}
// Check if one effect chain was awaiting for an AudioRecord to be created on this
// session and move it to this thread.
sp<EffectChain> chain = getOrphanEffectChain_l(sessionId);
if (chain != 0) {
Mutex::Autolock _l(thread->mLock);
thread->addEffectChain_l(chain);
}
break;
}
// End of retry loop.
// The lack of indentation is deliberate, to reduce code churn and ease merges.
}
output.cblk = recordTrack->getCblk();
output.buffers = recordTrack->getBuffers();
output.portId = portId;
output.audioRecord = new RecordHandle(recordTrack); //创建RecordHandle
_output = VALUE_OR_FATAL(output.toAidl());
Exit:
if (lStatus != NO_ERROR) {
// remove local strong reference to Client before deleting the RecordTrack so that the
// Client destructor is called by the TrackBase destructor with mClientLock held
// Don't hold mClientLock when releasing the reference on the track as the
// destructor will acquire it.
{
Mutex::Autolock _cl(mClientLock);
client.clear();
}
recordTrack.clear();
if (output.inputId != AUDIO_IO_HANDLE_NONE) {
AudioSystem::releaseInput(portId);
}
}
return lStatus;
}
以上函数有三个关键步骤:
-
调用AudioSystem::getInputForAttr函数获取到匹配的输入设备。
-
调用recordTrack = thread->createRecordTrack_l函数创建RecordTrack。
-
调用new RecordHandle创建TrackHandle。
下面分别进行分析:
AudioSystem getInputForAttr
调用AudioSystem::getInputForAttr函数获取到匹配的输入设备:
//frameworks/av/media/libaudioclient/AudioSystem.cpp
status_t AudioSystem::getInputForAttr(const audio_attributes_t* attr,
audio_io_handle_t* input,
audio_unique_id_t riid,
audio_session_t session,
const AttributionSourceState &attributionSource,
const audio_config_base_t* config,
audio_input_flags_t flags,
audio_port_handle_t* selectedDeviceId,
audio_port_handle_t* portId) {
if (attr == NULL) {
ALOGE("getInputForAttr NULL attr - shouldn't happen");
return BAD_VALUE;
}
if (input == NULL) {
ALOGE("getInputForAttr NULL input - shouldn't happen");
return BAD_VALUE;
}
if (selectedDeviceId == NULL) {
ALOGE("getInputForAttr NULL selectedDeviceId - shouldn't happen");
return BAD_VALUE;
}
if (portId == NULL) {
ALOGE("getInputForAttr NULL portId - shouldn't happen");
return BAD_VALUE;
}
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service(); //取得IAudioPolicyService接口
if (aps == 0) return NO_INIT;
media::AudioAttributesInternal attrAidl = VALUE_OR_RETURN_STATUS(
legacy2aidl_audio_attributes_t_AudioAttributesInternal(*attr));
int32_t inputAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_io_handle_t_int32_t(*input));
int32_t riidAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_unique_id_t_int32_t(riid));
int32_t sessionAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_session_t_int32_t(session));
AudioConfigBase configAidl = VALUE_OR_RETURN_STATUS(
legacy2aidl_audio_config_base_t_AudioConfigBase(*config, true /*isInput*/));
int32_t flagsAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_input_flags_t_int32_t_mask(flags));
int32_t selectedDeviceIdAidl = VALUE_OR_RETURN_STATUS(
legacy2aidl_audio_port_handle_t_int32_t(*selectedDeviceId));
media::GetInputForAttrResponse response;
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
aps->getInputForAttr(attrAidl, inputAidl, riidAidl, sessionAidl, attributionSource, //调用IAudioPolicyService的getInputForAttr函数
configAidl, flagsAidl, selectedDeviceIdAidl, &response)));
*input = VALUE_OR_RETURN_STATUS(aidl2legacy_int32_t_audio_io_handle_t(response.input));
*selectedDeviceId = VALUE_OR_RETURN_STATUS(
aidl2legacy_int32_t_audio_port_handle_t(response.selectedDeviceId));
*portId = VALUE_OR_RETURN_STATUS(aidl2legacy_int32_t_audio_port_handle_t(response.portId));
return OK;
}
AudioPolicyService getInputForAttr
AudioSystem的getInputForAttr函数会调用到AudioPolicyService的getInputForAttr函数:
//frameworks/av/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
Status AudioPolicyService::getInputForAttr(const media::AudioAttributesInternal& attrAidl,
int32_t inputAidl,
int32_t riidAidl,
int32_t sessionAidl,
const AttributionSourceState& attributionSource,
const AudioConfigBase& configAidl,
int32_t flagsAidl,
int32_t selectedDeviceIdAidl,
media::GetInputForAttrResponse* _aidl_return) {
audio_attributes_t attr = VALUE_OR_RETURN_BINDER_STATUS(
aidl2legacy_AudioAttributesInternal_audio_attributes_t(attrAidl));
audio_io_handle_t input = VALUE_OR_RETURN_BINDER_STATUS(
aidl2legacy_int32_t_audio_io_handle_t(inputAidl));
audio_unique_id_t riid = VALUE_OR_RETURN_BINDER_STATUS(
aidl2legacy_int32_t_audio_unique_id_t(riidAidl));
audio_session_t session = VALUE_OR_RETURN_BINDER_STATUS(
aidl2legacy_int32_t_audio_session_t(sessionAidl));
audio_config_base_t config = VALUE_OR_RETURN_BINDER_STATUS(
aidl2legacy_AudioConfigBase_audio_config_base_t(configAidl, true /*isInput*/));
audio_input_flags_t flags = VALUE_OR_RETURN_BINDER_STATUS(

最低0.47元/天 解锁文章
1818

被折叠的 条评论
为什么被折叠?



