赞
踩
Audioflinger负责管理android的所有音频设备,包括输入和输出。在Android Audio系统中,AudioFlinger起到承上启下的作用,上接AudioTrack/AudioRecord/AudioSystem等,下接AudioHal。AudioFlnger对上层会提供各种功能接口调用,对下层会对每个AudioHal设备开启一个独立线程,负责音频数据的管理。本文就依据AudioFlinger的作用来分析部分主要代码。
frameworks\av\media\audioserver\main_audioserver.cpp
int main(int argc __unused, char **argv)
{
...
sp<IServiceManager> sm = defaultServiceManager();
ALOGI("ServiceManager: %p", sm.get());
AudioFlinger::instantiate();------------------audioflinger service注册
...
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
...
}
audioflinger注册后,client就可以使用IAudioFlinger声明的功能了,最主要的功能无非就是获取track和record对象,播放或者录取音频数据,设置或查询音量及其他参数等。
对于每个播放设备,audioflinger都会创建一个线程来循环向hal层传输音频数据,具体的接口是openOutput,然后调用openOutput_l来具体创建线程
sp<AudioFlinger::ThreadBase> AudioFlinger::openOutput_l(audio_module_handle_t module, audio_io_handle_t *output, audio_config_t *config, audio_devices_t deviceType, const String8& address, audio_output_flags_t flags) { AudioHwDevice *outHwDev = findSuitableHwDev_l(module, deviceType);--------1.查询hal音频设备 ... if (*output == AUDIO_IO_HANDLE_NONE) { *output = nextUniqueId(AUDIO_UNIQUE_ID_USE_OUTPUT);-------------------2.分配唯一id ... AudioStreamOut *outputStream = NULL; status_t status = outHwDev->openOutputStream( &outputStream,----------------------------------------------------3.获取stream *output, deviceType, flags, config, address.string()); mHardwareStatus = AUDIO_HW_IDLE; if (status == NO_ERROR) { ... } else { sp<PlaybackThread> thread; ... } else {---------------------------------------------------------4.创建playback线程 thread = new MixerThread(this, outputStream, *output, mSystemReady); ALOGV("openOutput_l() created mixer output: ID %d thread %p", *output, thread.get()); } mPlaybackThreads.add(*output, thread);---------------------------5.加入vector ... } } ... }
线程第一次被引用的时候线程就会运行起来,如下
void AudioFlinger::PlaybackThread::onFirstRef()
{
run(mThreadName, ANDROID_PRIORITY_URGENT_AUDIO);
}
对于不同类型的设备会创建不同的线程,flag和thread的对应关系如下表:
flag | thread |
---|---|
AUDIO_OUTPUT_FLAG_MMAP_NOIRQ | MmapPlaybackThread |
AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD | OffloadThread |
AUDIO_OUTPUT_FLAG_DIRECT | DirectOutputThread |
default | MixerThread |
来看下两个典型的类继承关系:
线程运行起来会一直在threadLoop中保持循环,playback最主要的功能就是在这里了,这个函数比较长,我们分段来看下
bool AudioFlinger::PlaybackThread::threadLoop() { ... // loopCount is used for statistics and diagnostics. for (int64_t loopCount = 0; !exitPending(); ++loopCount) { ... } threadLoop_exit(); if (!mStandby) { threadLoop_standby(); mStandby = true; } releaseWakeLock(); ... }
{ // scope for mLock Mutex::Autolock _l(mLock);------作用域内的lock ... if (mSignalPending) { // A signal was raised while we were unlocked mSignalPending = false; } else if (waitingAsyncCallback_l()) { if (exitPending()) { break; } bool released = false; if (!keepWakeLock()) { releaseWakeLock_l(); released = true; } ... continue; } if ((mActiveTracks.isEmpty() && systemTime() > mStandbyTimeNs) || isSuspended()) { // put audio hardware into standby after short delay if (shouldStandby_l()) { threadLoop_standby(); ... } if (mActiveTracks.isEmpty() && mConfigEvents.isEmpty()) { // we're about to wait, flush the binder command buffer IPCThreadState::self()->flushCommands(); clearOutputTracks(); if (exitPending()) { break; } ... mWaitWorkCV.wait(mLock); ALOGV("%s waking up", myName.string()); acquireWakeLock_l(); ... continue; } } // mMixerStatusIgnoringFastTracks is also updated internally mMixerStatus = prepareTracks_l(&tracksToRemove); ... activeTracks.insert(activeTracks.end(), mActiveTracks.begin(), mActiveTracks.end()); } // mLock scope ends
if (mBytesRemaining == 0) { mCurrentWriteLength = 0; if (mMixerStatus == MIXER_TRACKS_READY) { // threadLoop_mix() sets mCurrentWriteLength threadLoop_mix(); } else if ((mMixerStatus != MIXER_DRAIN_TRACK) && (mMixerStatus != MIXER_DRAIN_ALL)) { ... if (mSleepTimeUs == 0) { mCurrentWriteLength = mSinkBufferSize; ... } } // Either threadLoop_mix() or threadLoop_sleepTime() should have set // mMixerBuffer with data if mMixerBufferValid is true and mSleepTimeUs == 0. // Merge mMixerBuffer data into mEffectBuffer (if any effects are valid) // or mSinkBuffer (if there are no effects). // // This is done pre-effects computation; if effects change to // support higher precision, this needs to move. // // mMixerBufferValid is only set true by MixerThread::prepareTracks_l(). // TODO use mSleepTimeUs == 0 as an additional condition. if (mMixerBufferValid) { ... memcpy_by_audio_format(buffer, format, mMixerBuffer, mMixerBufferFormat, mNormalFrameCount * (mChannelCount + mHapticChannelCount)); ... } mBytesRemaining = mCurrentWriteLength; ... // only process effects if we're going to write if (mSleepTimeUs == 0 && mType != OFFLOAD) { ... } }
if (!waitingAsyncCallback()) { // mSleepTimeUs == 0 means we must write to audio hardware if (mSleepTimeUs == 0) { ... if (mBytesRemaining) { ... ret = threadLoop_write();----------------------传输数据 const int64_t lastIoEndNs = systemTime(); if (ret < 0) { mBytesRemaining = 0; } else if (ret > 0) { mBytesWritten += ret; mBytesRemaining -= ret; ... } } else if ((mMixerStatus == MIXER_DRAIN_TRACK) || (mMixerStatus == MIXER_DRAIN_ALL)) { threadLoop_drain(); } if (mType == MIXER && !mStandby) { ... } } else { ATRACE_BEGIN("sleep"); ... ATRACE_END(); } }
threadLoop_removeTracks(tracksToRemove);
tracksToRemove.clear();
clearOutputTracks();
effectChains.clear();
创建Record线程的函数为openInput->openInput_l
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 String8& address, audio_source_t source, audio_input_flags_t flags, audio_devices_t outputDevice, const String8& outputDeviceAddress) { AudioHwDevice *inHwDev = findSuitableHwDev_l(module, devices);---------------查询hal设备 ... if (*input == AUDIO_IO_HANDLE_NONE) { *input = nextUniqueId(AUDIO_UNIQUE_ID_USE_INPUT);------------------------分配唯一id } else if (audio_unique_id_get_use(*input) != AUDIO_UNIQUE_ID_USE_INPUT) { ... } ... status_t status = inHwHal->openInputStream(---------------------------------打开stream *input, devices, &halconfig, flags, address.string(), source, outputDevice, outputDeviceAddress, &inStream); ... if (status == NO_ERROR && inStream != 0) { AudioStreamIn *inputStream = new AudioStreamIn(inHwDev, inStream, flags); if ((flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0) { ... } else { ... sp<RecordThread> thread = new RecordThread(this, inputStream, *input, mSystemReady);-----创建线程 mRecordThreads.add(*input, thread);------------------------------加入vector ... } } ... }
Record线程根据设备的类型可以分两种
flag | thread |
---|---|
AUDIO_INPUT_FLAG_MMAP_NOIRQ | MmapCaptureThread |
default | RecordThread |
这两种类型的类继承关系如下 | |
Record线程的threadloop也是在一个大循环中,读取音频数据然后分别分发给RecordTrack |
用户要播放音频,就要创建一个AudioTrack对象,具体调用步骤为AudioTrack@AudioTrack->set@AudioTrack->createTrack_l@AudioTrack
status_t AudioTrack::createTrack_l()
{
...
const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger();
...
sp<IAudioTrack> track = audioFlinger->createTrack(input,
output,
&status);
...
mAudioTrack = track;
...
}
IAudioTrack封装了binder通信的接口,这里通过binder通信机制来获取binder句柄,最终来和service端通信,这个还是要看一下
virtual sp<IAudioTrack> createTrack(const CreateTrackInput& input, CreateTrackOutput& output, status_t *status) { Parcel data, reply; sp<IAudioTrack> track; data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); if (status == nullptr) { return track; } input.writeToParcel(&data); status_t lStatus = remote()->transact(CREATE_TRACK, data, &reply);----通过AudioFlinger获取数据 if (lStatus != NO_ERROR) { ALOGE("createTrack transaction error %d", lStatus); *status = DEAD_OBJECT; return track; } *status = reply.readInt32(); if (*status != NO_ERROR) { ALOGE("createTrack returned error %d", *status); return track; } track = interface_cast<IAudioTrack>(reply.readStrongBinder());-------数据转化为binder句柄 if (track == 0) { ALOGE("createTrack returned an NULL IAudioTrack with status OK"); *status = DEAD_OBJECT; return track; } output.readFromParcel(&reply); return track; }
接下来看AudioFlinger那边的实现
sp<IAudioTrack> AudioFlinger::createTrack(const CreateTrackInput& input, CreateTrackOutput& output, status_t *status) { ... { ... track = thread->createTrack_l(client, streamType, localAttr, &output.sampleRate, input.config.format, input.config.channel_mask, &output.frameCount, &output.notificationFrameCount, input.notificationsPerBuffer, input.speed, input.sharedBuffer, sessionId, &output.flags, callingPid, input.clientInfo.clientTid, clientUid, &lStatus, portId); ... } ... // return handle to client trackHandle = new TrackHandle(track); ... return trackHandle; }
然后需要把track对象加入到PlaybackThread的vector中,调用的函数为start,最终会调用到Bn端的start实现,我们来看下Bn端继承的对象
status_t AudioFlinger::TrackHandle::start() {
return mTrack->start();--------mTrack的类型为PlaybackThread::Track
}
status_t AudioFlinger::PlaybackThread::Track::start(AudioSystem::sync_event_t event __unused,
audio_session_t triggerSession __unused)
{
...
if (thread != 0) {
...
PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
...
status = playbackThread->addTrack_l(this);
...
} else {
status = BAD_VALUE;
}
...
}
调用PlaybackThread来加入到线程中
status_t AudioFlinger::PlaybackThread::addTrack_l(const sp<Track>& track)
{
status_t status = ALREADY_EXISTS;
if (mActiveTracks.indexOf(track) < 0) {
...
mActiveTracks.add(track);---------正式加入到线程中
...
}
...
}
对于AudioRecord就直接来看start的实现
status_t AudioFlinger::RecordThread::start(RecordThread::RecordTrack* recordTrack,
AudioSystem::sync_event_t event,
audio_session_t triggerSession)
{
...
{
...
mActiveTracks.add(recordTrack);
...
}
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。