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(
aidl2legacy_int32_t_audio_input_flags_t_mask(flagsAidl));
audio_port_handle_t selectedDeviceId = VALUE_OR_RETURN_BINDER_STATUS(
aidl2legacy_int32_t_audio_port_handle_t(selectedDeviceIdAidl));
audio_port_handle_t portId;
if (mAudioPolicyManager == NULL) {
return binderStatusFromStatusT(NO_INIT);
}
RETURN_IF_BINDER_ERROR(
binderStatusFromStatusT(AudioValidator::validateAudioAttributes(attr, "68953950")));
audio_source_t inputSource = attr.source;
if (inputSource == AUDIO_SOURCE_DEFAULT) {
inputSource = AUDIO_SOURCE_MIC;
}
// already checked by client, but double-check in case the client wrapper is bypassed
if ((inputSource < AUDIO_SOURCE_DEFAULT)
|| (inputSource >= AUDIO_SOURCE_CNT
&& inputSource != AUDIO_SOURCE_HOTWORD
&& inputSource != AUDIO_SOURCE_FM_TUNER
&& inputSource != AUDIO_SOURCE_ECHO_REFERENCE
&& inputSource != AUDIO_SOURCE_ULTRASOUND)) {
return binderStatusFromStatusT(BAD_VALUE);
}
// Make sure attribution source represents the current caller
AttributionSourceState adjAttributionSource = attributionSource;
// TODO b/182392553: refactor or remove
bool updatePid = (attributionSource.pid == -1);
const uid_t callingUid =IPCThreadState::self()->getCallingUid();
const uid_t currentUid = VALUE_OR_RETURN_BINDER_STATUS(aidl2legacy_int32_t_uid_t(
attributionSource.uid));
if (!isAudioServerOrMediaServerUid(callingUid)) {
ALOGW_IF(currentUid != (uid_t)-1 && currentUid != callingUid,
"%s uid %d tried to pass itself off as %d", __FUNCTION__, callingUid,
currentUid);
adjAttributionSource.uid = VALUE_OR_RETURN_BINDER_STATUS(legacy2aidl_uid_t_int32_t(
callingUid));
updatePid = true;
}
if (updatePid) {
const int32_t callingPid = VALUE_OR_RETURN_BINDER_STATUS(legacy2aidl_pid_t_int32_t(
IPCThreadState::self()->getCallingPid()));
ALOGW_IF(attributionSource.pid != -1 && attributionSource.pid != callingPid,
"%s uid %d pid %d tried to pass itself off as pid %d",
__func__, adjAttributionSource.uid, callingPid, attributionSource.pid);
adjAttributionSource.pid = callingPid;
}
RETURN_IF_BINDER_ERROR(binderStatusFromStatusT(validateUsage(attr,
adjAttributionSource)));
// check calling permissions.
// Capturing from the following sources does not require permission RECORD_AUDIO
// as the captured audio does not come from a microphone:
// - FM_TUNER source is controlled by captureTunerAudioInputAllowed() or
// captureAudioOutputAllowed() (deprecated).
// - REMOTE_SUBMIX source is controlled by captureAudioOutputAllowed() if the input
// type is API_INPUT_MIX_EXT_POLICY_REROUTE and by AudioService if a media projection
// is used and input type is API_INPUT_MIX_PUBLIC_CAPTURE_PLAYBACK
// - ECHO_REFERENCE source is controlled by captureAudioOutputAllowed()
if (!(recordingAllowed(adjAttributionSource, inputSource)
|| inputSource == AUDIO_SOURCE_FM_TUNER
|| inputSource == AUDIO_SOURCE_REMOTE_SUBMIX
|| inputSource == AUDIO_SOURCE_ECHO_REFERENCE)) {
ALOGE("%s permission denied: recording not allowed for %s",
__func__, adjAttributionSource.toString().c_str());
return binderStatusFromStatusT(PERMISSION_DENIED);
}
bool canCaptureOutput = captureAudioOutputAllowed(adjAttributionSource);
bool canInterceptCallAudio = callAudioInterceptionAllowed(adjAttributionSource);
bool isCallAudioSource = inputSource == AUDIO_SOURCE_VOICE_UPLINK
|| inputSource == AUDIO_SOURCE_VOICE_DOWNLINK
|| inputSource == AUDIO_SOURCE_VOICE_CALL;
if (isCallAudioSource && !canInterceptCallAudio && !canCaptureOutput) {
return binderStatusFromStatusT(PERMISSION_DENIED);
}
if (inputSource == AUDIO_SOURCE_ECHO_REFERENCE
&& !canCaptureOutput) {
return binderStatusFromStatusT(PERMISSION_DENIED);
}
if (inputSource == AUDIO_SOURCE_FM_TUNER
&& !canCaptureOutput
&& !captureTunerAudioInputAllowed(adjAttributionSource)) {
return binderStatusFromStatusT(PERMISSION_DENIED);
}
bool canCaptureHotword = captureHotwordAllowed(adjAttributionSource);
if ((inputSource == AUDIO_SOURCE_HOTWORD) && !canCaptureHotword) {
return binderStatusFromStatusT(PERMISSION_DENIED);
}
if (((flags & AUDIO_INPUT_FLAG_HW_HOTWORD) != 0)
&& !canCaptureHotword) {
ALOGE("%s: permission denied: hotword mode not allowed"
" for uid %d pid %d", __func__, adjAttributionSource.uid, adjAttributionSource.pid);
return binderStatusFromStatusT(PERMISSION_DENIED);
}
if (attr.source == AUDIO_SOURCE_ULTRASOUND) {
if (!accessUltrasoundAllowed(adjAttributionSource)) {
ALOGE("%s: permission denied: ultrasound not allowed for uid %d pid %d",
__func__, adjAttributionSource.uid, adjAttributionSource.pid);
return binderStatusFromStatusT(PERMISSION_DENIED);
}
}
sp<AudioPolicyEffects>audioPolicyEffects;
{
status_t status;
AudioPolicyInterface::input_type_t inputType;
Mutex::Autolock _l(mLock);
{
AutoCallerClear acc;
// the audio_in_acoustics_t parameter is ignored by get_input()
status = mAudioPolicyManager->getInputForAttr(&attr, &input, riid, session, //调用AudioPolicyManager的getInputForAttr函数
adjAttributionSource, &config,
flags, &selectedDeviceId,
&inputType, &portId);
}
audioPolicyEffects = mAudioPolicyEffects;
if (status == NO_ERROR) {
// enforce permission (if any) required for each type of input
switch (inputType) {
case AudioPolicyInterface::API_INPUT_MIX_PUBLIC_CAPTURE_PLAYBACK:
// this use case has been validated in audio service with a MediaProjection token,
// and doesn't rely on regular permissions
case AudioPolicyInterface::API_INPUT_LEGACY:
break;
case AudioPolicyInterface::API_INPUT_TELEPHONY_RX:
if ((attr.flags & AUDIO_FLAG_CALL_REDIRECTION) != 0
&& canInterceptCallAudio) {
break;
}
// FIXME: use the same permission as for remote submix for now.
FALLTHROUGH_INTENDED;
case AudioPolicyInterface::API_INPUT_MIX_CAPTURE:
if (!canCaptureOutput) {
ALOGE("%s permission denied: capture not allowed", __func__);
status = PERMISSION_DENIED;
}
break;
case AudioPolicyInterface::API_INPUT_MIX_EXT_POLICY_REROUTE:
if (!(modifyAudioRoutingAllowed(adjAttributionSource)
|| ((attr.flags & AUDIO_FLAG_CALL_REDIRECTION) != 0
&& canInterceptCallAudio))) {
ALOGE("%s permission denied for remote submix capture", __func__);
status = PERMISSION_DENIED;
}
break;
case AudioPolicyInterface::API_INPUT_INVALID:
default:
LOG_ALWAYS_FATAL("%s encountered an invalid input type %d",
__func__, (int)inputType);
}
}
if (status != NO_ERROR) {
if (status == PERMISSION_DENIED) {
AutoCallerClear acc;
mAudioPolicyManager->releaseInput(portId);
}
return binderStatusFromStatusT(status);
}
sp<AudioRecordClient> client = new AudioRecordClient(attr, input, session, portId, //创建AudioRecord客户端
selectedDeviceId, adjAttributionSource,
canCaptureOutput, canCaptureHotword,
mOutputCommandThread);
mAudioRecordClients.add(portId, client);
}
if (audioPolicyEffects != 0) {
// create audio pre processors according to input source
status_t status = audioPolicyEffects->addInputEffects(input, inputSource, session);
if (status != NO_ERROR && status != ALREADY_EXISTS) {
ALOGW("Failed to add effects on input %d", input);
}
}
_aidl_return->input = VALUE_OR_RETURN_BINDER_STATUS(
legacy2aidl_audio_io_handle_t_int32_t(input));
_aidl_return->selectedDeviceId = VALUE_OR_RETURN_BINDER_STATUS(
legacy2aidl_audio_port_handle_t_int32_t(selectedDeviceId));
_aidl_return->portId = VALUE_OR_RETURN_BINDER_STATUS(
legacy2aidl_audio_port_handle_t_int32_t(portId));
return Status::ok();
}
AudioPolicyManager getInputForAttr
在AudioPolicyService的getInputForAttr中,会调用AudioPolicyManager的getInputForAttr函数:
//frameworks/av/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
status_t AudioPolicyManager::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,
input_type_t *inputType,
audio_port_handle_t *portId)
{
ALOGV("%s() source %d, sampling rate %d, format %#x, channel mask %#x, session %d, "
"flags %#x attributes=%s requested device ID %d",
__func__, attr->source, config->sample_rate, config->format, config->channel_mask,
session, flags, toString(*attr).c_str(), *selectedDeviceId);
status_t status = NO_ERROR;
audio_attributes_t attributes = *attr;
sp<AudioPolicyMix> policyMix;
sp<DeviceDescriptor> device;
sp<AudioInputDescriptor> inputDesc;
sp<RecordClientDescriptor> clientDesc;
audio_port_handle_t requestedDeviceId = *selectedDeviceId;
uid_t uid = VALUE_OR_RETURN_STATUS(aidl2legacy_int32_t_uid_t(attributionSource.uid));
bool isSoundTrigger;
// The supplied portId must be AUDIO_PORT_HANDLE_NONE
if (*portId != AUDIO_PORT_HANDLE_NONE) {
return INVALID_OPERATION;
}
if (attr->source == AUDIO_SOURCE_DEFAULT) {
attributes.source = AUDIO_SOURCE_MIC;
}
// Explicit routing?
sp<DeviceDescriptor> explicitRoutingDevice =
mAvailableInputDevices.getDeviceFromId(*selectedDeviceId);
// special case for mmap capture: if an input IO handle is specified, we reuse this input if
// possible
if ((flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) == AUDIO_INPUT_FLAG_MMAP_NOIRQ &&
*input != AUDIO_IO_HANDLE_NONE) {
ssize_t index = mInputs.indexOfKey(*input);
if (index < 0) {
ALOGW("getInputForAttr() unknown MMAP input %d", *input);
status = BAD_VALUE;
goto error;
}
sp<AudioInputDescriptor> inputDesc = mInputs.valueAt(index);
RecordClientVector clients = inputDesc->getClientsForSession(session);
if (clients.size() == 0) {
ALOGW("getInputForAttr() unknown session %d on input %d", session, *input);
status = BAD_VALUE;
goto error;
}
// For MMAP mode, the first call to getInputForAttr() is made on behalf of audioflinger.
// The second call is for the first active client and sets the UID. Any further call
// corresponds to a new client and is only permitted from the same UID.
// If the first UID is silenced, allow a new UID connection and replace with new UID
if (clients.size() > 1) {
for (const auto& client : clients) {
// The client map is ordered by key values (portId) and portIds are allocated
// incrementaly. So the first client in this list is the one opened by audio flinger
// when the mmap stream is created and should be ignored as it does not correspond
// to an actual client
if (client == *clients.cbegin()) {
continue;
}
if (uid != client->uid() && !client->isSilenced()) {
ALOGW("getInputForAttr() bad uid %d for client %d uid %d",
uid, client->portId(), client->uid());
status = INVALID_OPERATION;
goto error;
}
}
}
*inputType = API_INPUT_LEGACY;
device = inputDesc->getDevice();
ALOGV("%s reusing MMAP input %d for session %d", __FUNCTION__, *input, session);
goto exit;
}
*input = AUDIO_IO_HANDLE_NONE;
*inputType = API_INPUT_INVALID;
if (attributes.source == AUDIO_SOURCE_REMOTE_SUBMIX &&
strncmp(attributes.tags, "addr=", strlen("addr=")) == 0) {
status = mPolicyMixes.getInputMixForAttr(attributes, &policyMix);
if (status != NO_ERROR) {
ALOGW("%s could not find input mix for attr %s",
__func__, toString(attributes).c_str());
goto error;
}
device = mAvailableInputDevices.getDevice(AUDIO_DEVICE_IN_REMOTE_SUBMIX, //根据attr的source得到对应的device
String8(attr->tags + strlen("addr=")),
AUDIO_FORMAT_DEFAULT);
if (device == nullptr) {
ALOGW("%s could not find in Remote Submix device for source %d, tags %s",
__func__, attributes.source, attributes.tags);
status = BAD_VALUE;
goto error;
}
if (is_mix_loopback_render(policyMix->mRouteFlags)) {
*inputType = API_INPUT_MIX_PUBLIC_CAPTURE_PLAYBACK;
} else {
*inputType = API_INPUT_MIX_EXT_POLICY_REROUTE;
}
} else {
if (explicitRoutingDevice != nullptr) {
device = explicitRoutingDevice;
} else {
// Prevent from storing invalid requested device id in clients
requestedDeviceId = AUDIO_PORT_HANDLE_NONE;
device = mEngine->getInputDeviceForAttributes(attributes, uid, &policyMix);
ALOGV_IF(device != nullptr, "%s found device type is 0x%X",
__FUNCTION__, device->type());
}
if (device == nullptr) {
ALOGW("getInputForAttr() could not find device for source %d", attributes.source);
status = BAD_VALUE;
goto error;
}
if (device->type() == AUDIO_DEVICE_IN_ECHO_REFERENCE) {
*inputType = API_INPUT_MIX_CAPTURE;
} else if (policyMix) {
ALOG_ASSERT(policyMix->mMixType == MIX_TYPE_RECORDERS, "Invalid Mix Type");
// there is an external policy, but this input is attached to a mix of recorders,
// meaning it receives audio injected into the framework, so the recorder doesn't
// know about it and is therefore considered "legacy"
*inputType = API_INPUT_LEGACY;
} else if (audio_is_remote_submix_device(device->type())) {
*inputType = API_INPUT_MIX_CAPTURE;
} else if (device->type() == AUDIO_DEVICE_IN_TELEPHONY_RX) {
*inputType = API_INPUT_TELEPHONY_RX;
} else {
*inputType = API_INPUT_LEGACY;
}
}
*input = getInputForDevice(device, session, attributes, config, flags, policyMix); //根据device去获取Input
if (*input == AUDIO_IO_HANDLE_NONE) {
status = INVALID_OPERATION;
goto error;
}
exit:
*selectedDeviceId = mAvailableInputDevices.contains(device) ?
device->getId() : AUDIO_PORT_HANDLE_NONE;
isSoundTrigger = attributes.source == AUDIO_SOURCE_HOTWORD &&
mSoundTriggerSessions.indexOfKey(session) >= 0;
*portId = PolicyAudioPort::getNextUniqueId();
clientDesc = new RecordClientDescriptor(*portId, riid, uid, session, attributes, *config,
requestedDeviceId, attributes.source, flags,
isSoundTrigger);
inputDesc = mInputs.valueFor(*input);
inputDesc->addClient(clientDesc);
ALOGV("getInputForAttr() returns input %d type %d selectedDeviceId %d for port ID %d",
*input, *inputType, *selectedDeviceId, *portId);
return NO_ERROR;
error:
return status;
}
在getInputForAttr调用了getInputForDevice函数:
//frameworks/av/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
audio_io_handle_t AudioPolicyManager::getInputForDevice(const sp<DeviceDescriptor> &device,
audio_session_t session,
const audio_attributes_t &attributes,
const audio_config_base_t *config,
audio_input_flags_t flags,
const sp<AudioPolicyMix> &policyMix)
{
audio_io_handle_t input = AUDIO_IO_HANDLE_NONE;
audio_source_t halInputSource = attributes.source;
bool isSoundTrigger = false;
// 特殊源处理(语音识别和电话等)
if (attributes.source == AUDIO_SOURCE_HOTWORD) {
ssize_t index = mSoundTriggerSessions.indexOfKey(session);
if (index >= 0) {
input = mSoundTriggerSessions.valueFor(session);
isSoundTrigger = true;
flags = (audio_input_flags_t)(flags | AUDIO_INPUT_FLAG_HW_HOTWORD);
ALOGV("SoundTrigger capture on session %d input %d", session, input);
} else {
halInputSource = AUDIO_SOURCE_VOICE_RECOGNITION;
}
} else if (attributes.source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
audio_is_linear_pcm(config->format)) {
flags = (audio_input_flags_t)(flags | AUDIO_INPUT_FLAG_VOIP_TX);
}
if (attributes.source == AUDIO_SOURCE_ULTRASOUND) {
flags = (audio_input_flags_t)(flags | AUDIO_INPUT_FLAG_ULTRASOUND);
}
// find a compatible input profile (not necessarily identical in parameters)
sp<IOProfile> profile;
// sampling rate and flags may be updated by getInputProfile
uint32_t profileSamplingRate = (config->sample_rate == 0) ?
SAMPLE_RATE_HZ_DEFAULT : config->sample_rate;
audio_format_t profileFormat;
audio_channel_mask_t profileChannelMask = config->channel_mask;
audio_input_flags_t profileFlags = flags;
for (;;) {
profileFormat = config->format; // reset each time through loop, in case it is updated
// 通过采样率,采样格式等参数去和配置文件夹在的那个匹配来获取Profile
profile = getInputProfile(device, profileSamplingRate, profileFormat, profileChannelMask,
profileFlags);
if (profile != 0) {
break; // success
} else if (profileFlags & AUDIO_INPUT_FLAG_RAW) {
profileFlags = (audio_input_flags_t) (profileFlags & ~AUDIO_INPUT_FLAG_RAW); // retry
} else if (profileFlags != AUDIO_INPUT_FLAG_NONE && audio_is_linear_pcm(config->format)) {
profileFlags = AUDIO_INPUT_FLAG_NONE; // retry
} else { // fail
ALOGW("%s could not find profile for device %s, sampling rate %u, format %#x, "
"channel mask 0x%X, flags %#x", __func__, device->toString().c_str(),
config->sample_rate, config->format, config->channel_mask, flags);
return input;
}
}
// Pick input sampling rate if not specified by client
uint32_t samplingRate = config->sample_rate;
if (samplingRate == 0) {
samplingRate = profileSamplingRate;
}
if (profile->getModuleHandle() == 0) {
ALOGE("getInputForAttr(): HW module %s not opened", profile->getModuleName());
return input;
}
// Reuse an already opened input if a client with the same session ID already exists
// on that input
for (size_t i = 0; i < mInputs.size(); i++) {
sp <AudioInputDescriptor> desc = mInputs.valueAt(i);
if (desc->mProfile != profile) {
continue;
}
RecordClientVector clients = desc->clientsList();
for (const auto &client : clients) {
if (session == client->session()) {
return desc->mIoHandle;
}
}
}
if (!profile->canOpenNewIo()) {
for (size_t i = 0; i < mInputs.size(); ) {
sp<AudioInputDescriptor> desc = mInputs.valueAt(i);
if (desc->mProfile != profile) {
i++;
continue;
}
// if sound trigger, reuse input if used by other sound trigger on same session
// else
// reuse input if active client app is not in IDLE state
//
RecordClientVector clients = desc->clientsList();
bool doClose = false;
for (const auto& client : clients) {
if (isSoundTrigger != client->isSoundTrigger()) {
continue;
}
if (client->isSoundTrigger()) {
if (session == client->session()) {
return desc->mIoHandle;
}
continue;
}
if (client->active() && client->appState() != APP_STATE_IDLE) {
return desc->mIoHandle;
}
doClose = true;
}
if (doClose) {
closeInput(desc->mIoHandle);
} else {
i++;
}
}
}
// 创建新的输入对象
sp<AudioInputDescriptor> inputDesc = new AudioInputDescriptor(profile, mpClientInterface);
audio_config_t lConfig = AUDIO_CONFIG_INITIALIZER;
lConfig.sample_rate = profileSamplingRate;
lConfig.channel_mask = profileChannelMask;
lConfig.format = profileFormat;
//打开输入对象
status_t status = inputDesc->open(&lConfig, device, halInputSource, profileFlags, &input);
// only accept input with the exact requested set of parameters
if (status != NO_ERROR || input == AUDIO_IO_HANDLE_NONE ||
(profileSamplingRate != lConfig.sample_rate) ||
!audio_formats_match(profileFormat, lConfig.format) ||
(profileChannelMask != lConfig.channel_mask)) {
ALOGW("getInputForAttr() failed opening input: sampling rate %d"
", format %#x, channel mask %#x",
profileSamplingRate, profileFormat, profileChannelMask);
if (input != AUDIO_IO_HANDLE_NONE) {
inputDesc->close();
}
return AUDIO_IO_HANDLE_NONE;
}
inputDesc->mPolicyMix = policyMix;
addInput(input, inputDesc);
mpClientInterface->onAudioPortListUpdate();
return input;
}
AudioInputDescriptor open
getInputForDevice函数中创建了一个AudioInputDescriptor对象并调用open函数打开这个对象:
//frameworks/av/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
AudioPolicyClientInterface * const mClientInterface;
//frameworks/av/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
status_t AudioInputDescriptor::open(const audio_config_t *config,
const sp<DeviceDescriptor> &device,
audio_source_t source,.
audio_input_flags_t flags,
audio_io_handle_t *input)
{
audio_config_t lConfig;
if (config == nullptr) {
lConfig = AUDIO_CONFIG_INITIALIZER;
lConfig.sample_rate = mSamplingRate;
lConfig.channel_mask = mChannelMask;
lConfig.format = mFormat;
} else {
lConfig = *config;
}
mDevice = device;
ALOGV("opening input for device %s profile %p name %s",
mDevice->toString().c_str(), mProfile.get(), mProfile->getName().c_str());
audio_devices_t deviceType = mDevice->type();
status_t status = mClientInterface->openInput(mProfile->getModuleHandle(), //调用AudioPolicyClientInterface的openInput
input,
&lConfig,
&deviceType,
String8(mDevice->address().c_str()),
source,
flags);
LOG_ALWAYS_FATAL_IF(mDevice->type() != deviceType,
"%s openInput returned device %08x when given device %08x",
__FUNCTION__, mDevice->type(), deviceType);
if (status == NO_ERROR) {
LOG_ALWAYS_FATAL_IF(*input == AUDIO_IO_HANDLE_NONE,
"%s openInput returned input handle %d for device %s",
__FUNCTION__, *input, mDevice->toString().c_str());
mSamplingRate = lConfig.sample_rate;
mChannelMask = lConfig.channel_mask;
mFormat = lConfig.format;
mId = PolicyAudioPort::getNextUniqueId();
mIoHandle = *input;
mProfile->curOpenCount++;
}
return status;
}
调用AudioPolicyClientInterface的openInput函数会调用到AudioPolicyServicee::AudioPolicyClient::openInput函数:
// frameworks/av/services/audiopolicy/service/AudioPolicyClientImpl.cpp
status_t AudioPolicyService::AudioPolicyClient::openInput(audio_module_handle_t module,
audio_io_handle_t *input,
audio_config_t *config,
audio_devices_t *device,
const String8& address,
audio_source_t source,
audio_input_flags_t flags)
{
sp<IAudioFlinger> af = AudioSystem::get_audio_flinger(); //取得IAudioFlinger
if (af == 0) {
ALOGW("%s: could not get AudioFlinger", __func__);
return PERMISSION_DENIED;
}
AudioDeviceTypeAddr deviceTypeAddr(*device, address.c_str());
media::OpenInputRequest request;
request.module = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_module_handle_t_int32_t(module));
request.input = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_io_handle_t_int32_t(*input));
request.config = VALUE_OR_RETURN_STATUS(
legacy2aidl_audio_config_t_AudioConfig(*config, true /*isInput*/));
request.device = VALUE_OR_RETURN_STATUS(legacy2aidl_AudioDeviceTypeAddress(deviceTypeAddr));
request.source = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_source_t_AudioSource(source));
request.flags = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_input_flags_t_int32_t_mask(flags));
media::OpenInputResponse response;
status_t status = af->openInput(request, &response); //调用IAudioFlinger的openOutput
if (status == OK) {
*input = VALUE_OR_RETURN_STATUS(aidl2legacy_int32_t_audio_module_handle_t(response.input));
}
return status;
}
AudioFlinger openInput
调用AudioFlinger的openInput方法:
//frameworks/av/services/audioflinger/AudioFlinger.cpp
status_t AudioFlinger::openInput(const media::OpenInputRequest& request,
media::OpenInputResponse* response)
{
Mutex::Autolock _l(mLock);
AudioDeviceTypeAddr device = VALUE_OR_RETURN_STATUS(
aidl2legacy_AudioDeviceTypeAddress(request.device));
if (device.mType == AUDIO_DEVICE_NONE) {
return BAD_VALUE;
}
audio_io_handle_t input = VALUE_OR_RETURN_STATUS(
aidl2legacy_int32_t_audio_io_handle_t(request.input));
audio_config_t config = VALUE_OR_RETURN_STATUS(
aidl2legacy_AudioConfig_audio_config_t(request.config, true /*isInput*/));
sp<ThreadBase> thread = openInput_l( //调用openInput_l函数
VALUE_OR_RETURN_STATUS(aidl2legacy_int32_t_audio_module_handle_t(request.module)),
&input,
&config,
device.mType,
device.address().c_str(),
VALUE_OR_RETURN_STATUS(aidl2legacy_AudioSource_audio_source_t(request.source)),
VALUE_OR_RETURN_STATUS(aidl2legacy_int32_t_audio_input_flags_t_mask(request.flags)),
AUDIO_DEVICE_NONE,
String8{});
response->input = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_io_handle_t_int32_t(input));
response->config = VALUE_OR_RETURN_STATUS(
legacy2aidl_audio_config_t_AudioConfig(config, true /*isInput*/));
response->device = request.device;
if (thread != 0) {
// notify client processes of the new input creation
thread->ioConfigChanged(AUDIO_INPUT_OPENED);
return NO_ERROR;
}
return NO_INIT;
}
在openInput函数中会调用openInput_l函数:
//frameworks/av/services/audioflinger/AudioFlinger.cpp
sp<AudioFlinger::ThreadBase> AudioFlinger::openInput_l(audio_module_handle_t module,
audio_io_handle_t *input,
audio_config_t *config,
audio_devices_t devices,
const char* address,
audio_source_t source,
audio_input_flags_t flags,
audio_devices_t outputDevice,
const String8& outputDeviceAddress)
{
AudioHwDevice *inHwDev = findSuitableHwDev_l(module, devices); //查找输入硬件设备
if (inHwDev == NULL) {
*input = AUDIO_IO_HANDLE_NONE;
return 0;
}
// Audio Policy can request a specific handle for hardware hotword.
// The goal here is not to re-open an already opened input.
// It is to use a pre-assigned I/O handle.
if (*input == AUDIO_IO_HANDLE_NONE) {
*input = nextUniqueId(AUDIO_UNIQUE_ID_USE_INPUT);
} else if (audio_unique_id_get_use(*input) != AUDIO_UNIQUE_ID_USE_INPUT) {
ALOGE("openInput_l() requested input handle %d is invalid", *input);
return 0;
} else if (mRecordThreads.indexOfKey(*input) >= 0) {
// This should not happen in a transient state with current design.
ALOGE("openInput_l() requested input handle %d is already assigned", *input);
return 0;
}
audio_config_t halconfig = *config;
sp<DeviceHalInterface> inHwHal = inHwDev->hwDevice();
sp<StreamInHalInterface> inStream;
status_t status = inHwHal->openInputStream( //打开输入硬输入设备的输入流
*input, devices, &halconfig, flags, address, source,
outputDevice, outputDeviceAddress, &inStream);
ALOGV("openInput_l() openInputStream returned input %p, devices %#x, SamplingRate %d"
", Format %#x, Channels %#x, flags %#x, status %d addr %s",
inStream.get(),
devices,
halconfig.sample_rate,
halconfig.format,
halconfig.channel_mask,
flags,
status, address);
// If the input could not be opened with the requested parameters and we can handle the
// conversion internally, try to open again with the proposed parameters.
if (status == BAD_VALUE &&
audio_is_linear_pcm(config->format) &&
audio_is_linear_pcm(halconfig.format) &&
(halconfig.sample_rate <= AUDIO_RESAMPLER_DOWN_RATIO_MAX * config->sample_rate) &&
(audio_channel_count_from_in_mask(halconfig.channel_mask) <= FCC_LIMIT) &&
(audio_channel_count_from_in_mask(config->channel_mask) <= FCC_LIMIT)) {
// FIXME describe the change proposed by HAL (save old values so we can log them here)
ALOGV("openInput_l() reopening with proposed sampling rate and channel mask");
inStream.clear();
status = inHwHal->openInputStream(
*input, devices, &halconfig, flags, address, source,
outputDevice, outputDeviceAddress, &inStream);
// FIXME log this new status; HAL should not propose any further changes
}
if (status == NO_ERROR && inStream != 0) {
AudioStreamIn *inputStream = new AudioStreamIn(inHwDev, inStream, flags); //创建Audio输入流
if ((flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0) {
sp<MmapCaptureThread> thread =
new MmapCaptureThread(this, *input, inHwDev, inputStream, mSystemReady); //创建MmapCapture线程
mMmapThreads.add(*input, thread); //加入MmapThreads
ALOGV("openInput_l() created mmap capture thread: ID %d thread %p", *input,
thread.get());
return thread;
} else {
// Start record thread
// RecordThread requires both input and output device indication to forward to audio
// pre processing modules
sp<RecordThread> thread = new RecordThread(this, inputStream, *input, mSystemReady); //创建Record线程
mRecordThreads.add(*input, thread); //加入RecordThreads
ALOGV("openInput_l() created record thread: ID %d thread %p", *input, thread.get());
return thread;
}
}
*input = AUDIO_IO_HANDLE_NONE;
return 0;
}
在openOutput_l中会调用AudioHwDevice 的openOutputStream函数:
//frameworks/av/media/libaudiohal/impl/DeviceHalHidl.h
sp<::android::hardware::audio::CPP_VERSION::IDevice> mDevice;
//frameworks/av/media/libaudiohal/impl/DeviceHalHidl.cpp
status_t DeviceHalHidl::openInputStream(
audio_io_handle_t handle,
audio_devices_t devices,
struct audio_config *config,
audio_input_flags_t flags,
const char *address,
audio_source_t source,
audio_devices_t outputDevice,
const char *outputDeviceAddress,
sp<StreamInHalInterface> *inStream) {
TIME_CHECK();
if (mDevice == 0) return NO_INIT;
DeviceAddress hidlDevice;
if (status_t status = CoreUtils::deviceAddressFromHal(devices, address, &hidlDevice);
status != OK) {
return status;
}
AudioConfig hidlConfig;
if (status_t status = HidlUtils::audioConfigFromHal(*config, true /*isInput*/, &hidlConfig);
status != OK) {
return status;
}
CoreUtils::AudioInputFlags hidlFlags;
#if MAJOR_VERSION <= 5
// Some flags were specific to framework and must not leak to the HAL.
flags = static_cast<audio_input_flags_t>(flags & ~AUDIO_INPUT_FLAG_DIRECT);
#endif
if (status_t status = CoreUtils::audioInputFlagsFromHal(flags, &hidlFlags); status != OK) {
return status;
}
Result retval = Result::NOT_INITIALIZED;
#if MAJOR_VERSION == 2
auto sinkMetadata = AudioSource(source);
#elif MAJOR_VERSION >= 4
// TODO: correctly propagate the tracks sources and volume
// for now, only send the main source at 1dbfs
AudioSource hidlSource;
if (status_t status = HidlUtils::audioSourceFromHal(source, &hidlSource); status != OK) {
return status;
}
SinkMetadata sinkMetadata = {{{ .source = std::move(hidlSource), .gain = 1 }}};
#endif
#if MAJOR_VERSION < 5
(void)outputDevice;
(void)outputDeviceAddress;
#else
#if MAJOR_VERSION >= 7
(void)HidlUtils::audioChannelMaskFromHal(
AUDIO_CHANNEL_NONE, true /*isInput*/, &sinkMetadata.tracks[0].channelMask);
#endif
if (outputDevice != AUDIO_DEVICE_NONE) {
DeviceAddress hidlOutputDevice;
if (status_t status = CoreUtils::deviceAddressFromHal(
outputDevice, outputDeviceAddress, &hidlOutputDevice); status != OK) {
return status;
}
sinkMetadata.tracks[0].destination.device(std::move(hidlOutputDevice));
}
#endif
Return<void> ret = mDevice->openInputStream( //调用AudioHal的inputStream
handle, hidlDevice, hidlConfig, hidlFlags, sinkMetadata,
[&](Result r,
const sp<::android::hardware::audio::CORE_TYPES_CPP_VERSION::IStreamIn>& result,
const AudioConfig& suggestedConfig) {
retval = r;
if (retval == Result::OK) {
*inStream = new StreamInHalHidl(result);
}
HidlUtils::audioConfigToHal(suggestedConfig, config);
});
return processReturn("openInputStream", ret, retval);
}
再向下分析就是AudioHAL部分了,这里就不再继续分析了。
AudioFlinger RecordThread createRecordTrack_l
调用AudioFlinger::RecordThread 的createRecordTrack_l方法:
//frameworks/av/services/audioflinger/Threads.cpp
sp<AudioFlinger::RecordThread::RecordTrack> AudioFlinger::RecordThread::createRecordTrack_l(
const sp<AudioFlinger::Client>& client,
const audio_attributes_t& attr,
uint32_t *pSampleRate,
audio_format_t format,
audio_channel_mask_t channelMask,
size_t *pFrameCount,
audio_session_t sessionId,
size_t *pNotificationFrameCount,
pid_t creatorPid,
const AttributionSourceState& attributionSource,
audio_input_flags_t *flags,
pid_t tid,
status_t *status,
audio_port_handle_t portId,
int32_t maxSharedAudioHistoryMs)
{
size_t frameCount = *pFrameCount;
size_t notificationFrameCount = *pNotificationFrameCount;
sp<RecordTrack> track;
status_t lStatus;
audio_input_flags_t inputFlags = mInput->flags;
audio_input_flags_t requestedFlags = *flags;
uint32_t sampleRate;
AttributionSourceState checkedAttributionSource = AudioFlinger::checkAttributionSourcePackage(
attributionSource);
lStatus = initCheck();
if (lStatus != NO_ERROR) {
ALOGE("createRecordTrack_l() audio driver not initialized");
goto Exit;
}
if (!audio_is_linear_pcm(mFormat) && (*flags & AUDIO_INPUT_FLAG_DIRECT) == 0) {
ALOGE("createRecordTrack_l() on an encoded stream requires AUDIO_INPUT_FLAG_DIRECT");
lStatus = BAD_VALUE;
goto Exit;
}
if (maxSharedAudioHistoryMs != 0) {
if (!captureHotwordAllowed(checkedAttributionSource)) {
lStatus = PERMISSION_DENIED;
goto Exit;
}
if (maxSharedAudioHistoryMs < 0
|| maxSharedAudioHistoryMs > AudioFlinger::kMaxSharedAudioHistoryMs) {
lStatus = BAD_VALUE;
goto Exit;
}
}
if (*pSampleRate == 0) {
*pSampleRate = mSampleRate;
}
sampleRate = *pSampleRate;
// special case for FAST flag considered OK if fast capture is present and access to
// audio history is not required
if (hasFastCapture() && mMaxSharedAudioHistoryMs == 0) {
inputFlags = (audio_input_flags_t)(inputFlags | AUDIO_INPUT_FLAG_FAST);
}
// Check if requested flags are compatible with input stream flags
if ((*flags & inputFlags) != *flags) {
ALOGW("createRecordTrack_l(): mismatch between requested flags (%08x) and"
" input flags (%08x)",
*flags, inputFlags);
*flags = (audio_input_flags_t)(*flags & inputFlags);
}
// client expresses a preference for FAST and no access to audio history,
// but we get the final say
if (*flags & AUDIO_INPUT_FLAG_FAST && maxSharedAudioHistoryMs == 0) {
if (
// we formerly checked for a callback handler (non-0 tid),
// but that is no longer required for TRANSFER_OBTAIN mode
// No need to match hardware format, format conversion will be done in client side.
//
// Frame count is not specified (0), or is less than or equal the pipe depth.
// It is OK to provide a higher capacity than requested.
// We will force it to mPipeFramesP2 below.
(frameCount <= mPipeFramesP2) &&
// PCM data
audio_is_linear_pcm(format) &&
// hardware channel mask
(channelMask == mChannelMask) &&
// hardware sample rate
(sampleRate == mSampleRate) &&
// record thread has an associated fast capture
hasFastCapture() &&
// there are sufficient fast track slots available
mFastTrackAvail
) {
// check compatibility with audio effects.
Mutex::Autolock _l(mLock);
// Do not accept FAST flag if the session has software effects
sp<EffectChain> chain = getEffectChain_l(sessionId);
if (chain != 0) {
audio_input_flags_t old = *flags;
chain->checkInputFlagCompatibility(flags);
if (old != *flags) {
ALOGV("%p AUDIO_INPUT_FLAGS denied by effect old=%#x new=%#x",
this, (int)old, (int)*flags);
}
}
ALOGV_IF((*flags & AUDIO_INPUT_FLAG_FAST) != 0,
"%p AUDIO_INPUT_FLAG_FAST accepted: frameCount=%zu mFrameCount=%zu",
this, frameCount, mFrameCount);
} else {
ALOGV("%p AUDIO_INPUT_FLAG_FAST denied: frameCount=%zu mFrameCount=%zu mPipeFramesP2=%zu "
"format=%#x isLinear=%d mFormat=%#x channelMask=%#x sampleRate=%u mSampleRate=%u "
"hasFastCapture=%d tid=%d mFastTrackAvail=%d",
this, frameCount, mFrameCount, mPipeFramesP2,
format, audio_is_linear_pcm(format), mFormat, channelMask, sampleRate, mSampleRate,
hasFastCapture(), tid, mFastTrackAvail);
*flags = (audio_input_flags_t)(*flags & ~AUDIO_INPUT_FLAG_FAST);
}
}
// If FAST or RAW flags were corrected, ask caller to request new input from audio policy
if ((*flags & AUDIO_INPUT_FLAG_FAST) !=
(requestedFlags & AUDIO_INPUT_FLAG_FAST)) {
*flags = (audio_input_flags_t) (*flags & ~(AUDIO_INPUT_FLAG_FAST | AUDIO_INPUT_FLAG_RAW));
lStatus = BAD_TYPE;
goto Exit;
}
// compute track buffer size in frames, and suggest the notification frame count
if (*flags & AUDIO_INPUT_FLAG_FAST) {
// fast track: frame count is exactly the pipe depth
frameCount = mPipeFramesP2;
// ignore requested notificationFrames, and always notify exactly once every HAL buffer
notificationFrameCount = mFrameCount;
} else {
// not fast track: max notification period is resampled equivalent of one HAL buffer time
// or 20 ms if there is a fast capture
// TODO This could be a roundupRatio inline, and const
size_t maxNotificationFrames = ((int64_t) (hasFastCapture() ? mSampleRate/50 : mFrameCount)
* sampleRate + mSampleRate - 1) / mSampleRate;
// minimum number of notification periods is at least kMinNotifications,
// and at least kMinMs rounded up to a whole notification period (minNotificationsByMs)
static const size_t kMinNotifications = 3;
static const uint32_t kMinMs = 30;
// TODO This could be a roundupRatio inline
const size_t minFramesByMs = (sampleRate * kMinMs + 1000 - 1) / 1000;
// TODO This could be a roundupRatio inline
const size_t minNotificationsByMs = (minFramesByMs + maxNotificationFrames - 1) /
maxNotificationFrames;
const size_t minFrameCount = maxNotificationFrames *
max(kMinNotifications, minNotificationsByMs);
frameCount = max(frameCount, minFrameCount);
if (notificationFrameCount == 0 || notificationFrameCount > maxNotificationFrames) {
notificationFrameCount = maxNotificationFrames;
}
}
*pFrameCount = frameCount;
*pNotificationFrameCount = notificationFrameCount;
{ // scope for mLock
Mutex::Autolock _l(mLock);
int32_t startFrames = -1;
if (!mSharedAudioPackageName.empty()
&& mSharedAudioPackageName == checkedAttributionSource.packageName
&& mSharedAudioSessionId == sessionId
&& captureHotwordAllowed(checkedAttributionSource)) {
startFrames = mSharedAudioStartFrames;
}
track = new RecordTrack(this, client, attr, sampleRate, //创建RecordTrack对象
format, channelMask, frameCount,
nullptr /* buffer */, (size_t)0 /* bufferSize */, sessionId, creatorPid,
checkedAttributionSource, *flags, TrackBase::TYPE_DEFAULT, portId,
startFrames);
lStatus = track->initCheck();
if (lStatus != NO_ERROR) {
ALOGE("createRecordTrack_l() initCheck failed %d; no control block?", lStatus);
// track must be cleared from the caller as the caller has the AF lock
goto Exit;
}
mTracks.add(track); //将RecordTrack对象追加到Tracks
if ((*flags & AUDIO_INPUT_FLAG_FAST) && (tid != -1)) {
pid_t callingPid = IPCThreadState::self()->getCallingPid();
// we don't have CAP_SYS_NICE, nor do we want to have it as it's too powerful,
// so ask activity manager to do this on our behalf
sendPrioConfigEvent_l(callingPid, tid, kPriorityAudioApp, true /*forApp*/);
}
if (maxSharedAudioHistoryMs != 0) {
sendResizeBufferConfigEvent_l(maxSharedAudioHistoryMs);
}
}
lStatus = NO_ERROR;
Exit:
*status = lStatus;
return track;
}
new RecordTrack
在createRecordTrack_l函数中创建RecordTrack对象,会调用RecordTrack构造函数:
//frameworks/av/services/audioflinger/RecordTracks.h
// record track
class RecordTrack : public TrackBase {
public:
RecordTrack(......)
}
//frameworks/av/services/audioflinger/Tracks.cpp
// RecordTrack constructor must be called with AudioFlinger::mLock and ThreadBase::mLock held
AudioFlinger::RecordThread::RecordTrack::RecordTrack(
RecordThread *thread,
const sp<Client>& client,
const audio_attributes_t& attr,
uint32_t sampleRate,
audio_format_t format,
audio_channel_mask_t channelMask,
size_t frameCount,
void *buffer,
size_t bufferSize,
audio_session_t sessionId,
pid_t creatorPid,
const AttributionSourceState& attributionSource,
audio_input_flags_t flags,
track_type type,
audio_port_handle_t portId,
int32_t startFrames)
: TrackBase(thread, client, attr, sampleRate, format,
channelMask, frameCount, buffer, bufferSize, sessionId,
creatorPid,
VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid)),
false /*isOut*/,
(type == TYPE_DEFAULT) ?
((flags & AUDIO_INPUT_FLAG_FAST) ? ALLOC_PIPE : ALLOC_CBLK) :
((buffer == NULL) ? ALLOC_LOCAL : ALLOC_NONE),
type, portId,
std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD) + std::to_string(portId)),
mOverflow(false),
mFramesToDrop(0),
mResamplerBufferProvider(NULL), // initialize in case of early constructor exit
mRecordBufferConverter(NULL),
mFlags(flags),
mSilenced(false),
mStartFrames(startFrames)
{
if (mCblk == NULL) {
return;
}
if (!isDirect()) {
mRecordBufferConverter = new RecordBufferConverter(
thread->mChannelMask, thread->mFormat, thread->mSampleRate,
channelMask, format, sampleRate);
// Check if the RecordBufferConverter construction was successful.
// If not, don't continue with construction.
//
// NOTE: It would be extremely rare that the record track cannot be created
// for the current device, but a pending or future device change would make
// the record track configuration valid.
if (mRecordBufferConverter->initCheck() != NO_ERROR) {
ALOGE("%s(%d): RecordTrack unable to create record buffer converter", __func__, mId);
return;
}
}
mServerProxy = new AudioRecordServerProxy(mCblk, mBuffer, frameCount, //创建AudioRecordServer代理对象
mFrameSize, !isExternalTrack());
mResamplerBufferProvider = new ResamplerBufferProvider(this); //创建重采样缓存提供者
if (flags & AUDIO_INPUT_FLAG_FAST) {
ALOG_ASSERT(thread->mFastTrackAvail);
thread->mFastTrackAvail = false;
} else {
// TODO: only Normal Record has timestamps (Fast Record does not).
mServerLatencySupported = checkServerLatencySupported(mFormat, flags);
}
#ifdef TEE_SINK
mTee.setId(std::string("_") + std::to_string(mThreadIoHandle)
+ "_" + std::to_string(mId)
+ "_R");
#endif
// Once this item is logged by the server, the client can add properties.
mTrackMetrics.logConstructor(creatorPid, uid(), id());
}
new RecordHandle
调用new RecordHandle创建TrackHandle:
待更新