Android Audio System
开机启动加载多媒体服务位于:
frameworks/base/media/mediaserver/main_mediaserver.cpp
1 int main(int argc, char** argv) 2 { 3 sp<ProcessState> proc(ProcessState::self()); 4 sp<IServiceManager> sm = defaultServiceManager(); 5 LOGI("ServiceManager: %p", sm.get()); 6 AudioFlinger::instantiate(); 7 MediaPlayerService::instantiate(); 8 MemoryDumper::instantiate(); 9 CameraService::instantiate(); 10 AudioPolicyService::instantiate(); 11 ProcessState::self()->startThreadPool(); 12 IPCThreadState::self()->joinThreadPool(); 13 }
由此可知,Android系统开机启动了AudioFlinger、MediaPlayerService、CameraService、AudioPolicyService、MemoryDumper服务。
一、 AudioFlinger
class AudioFlinger : public BinderService<AudioFlinger>, public BnAudioFlinger {
AudioFlinger 继承BinderService<?>,BinderService取得传入类的名字,由BinderService创建并加入服务列表。
template<typename SERVICE> class BinderService { public: static status_t publish() { sp<IServiceManager> sm(defaultServiceManager()); return sm->addService(String16(SERVICE::getServiceName()), new SERVICE()); } static void publishAndJoinThreadPool() { sp<ProcessState> proc(ProcessState::self()); sp<IServiceManager> sm(defaultServiceManager()); sm->addService(String16(SERVICE::getServiceName()), new SERVICE()); ProcessState::self()->startThreadPool(); IPCThreadState::self()->joinThreadPool(); } static void instantiate() { publish(); } static status_t shutdown() { return NO_ERROR; } };
再来看实例化AudioFlinger,并把实例加入服务队列,sm->addService(String16(SERVICE::getServiceName()), new SERVICE());
AudioFlinger::AudioFlinger() : BnAudioFlinger(), // init super class mAudioHardware(0), mMasterVolume(1.0f), mMasterMute(false), mNextUniqueId(1) { mHardwareStatus = AUDIO_HW_IDLE;//init hardware state IDLE // add by chipeng , for fsync mFd =0; int ret = 0 ; ret |= pthread_mutex_init(&Fasyc_Mutex, NULL); if ( ret != 0 ){ LOGE("Failed to initialize pthread Fasyc_Mutex!"); } // create hardware interface mAudioHardware = AudioHardwareInterface::create(); // init hardware state INIT mHardwareStatus = AUDIO_HW_INIT; if (mAudioHardware->initCheck() == NO_ERROR) { // open 16-bit output stream for s/w mixer mMode = AudioSystem::MODE_NORMAL; setMode(mMode); // set volume setMasterVolume(1.0f); // set mute setMasterMute(false); } else { LOGE("Couldn't even initialize the stubbed audio hardware!"); } #ifdef LVMX LifeVibes::init(); mLifeVibesClientPid = -1; #endif
AudioFlinger实例通过如下方法调用
const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger();
该方法实现位于 frameworks/base/media/libmedia/AudioSystem.cpp
// establish binder interface to AudioFlinger service const sp<IAudioFlinger>& AudioSystem::get_audio_flinger() { Mutex::Autolock _l(gLock); if (gAudioFlinger.get() == 0) { // get service manager sp<IServiceManager> sm = defaultServiceManager(); sp<IBinder> binder; do { // get service binder = sm->getService(String16("media.audio_flinger"));
if (binder != 0) break; LOGW("AudioFlinger not published, waiting..."); usleep(500000); // 0.5 s } while(true); if (gAudioFlingerClient == NULL) { gAudioFlingerClient = new AudioFlingerClient(); } else { if (gAudioErrorCallback) { gAudioErrorCallback(NO_ERROR); } } binder->linkToDeath(gAudioFlingerClient); gAudioFlinger = interface_cast<IAudioFlinger>(binder); gAudioFlinger->registerClient(gAudioFlingerClient); } LOGE_IF(gAudioFlinger==0, "no AudioFlinger!?"); return gAudioFlinger; }
创建AudioFlingerClient实例,通过Binder连接服务端与客户端。
构造AudioTrack会调用AudioFlinger如下方法
// IAudioFlinger interface virtual sp<IAudioTrack> createTrack( pid_t pid, int streamType, uint32_t sampleRate, int format, int channelCount, int frameCount, uint32_t flags, const sp<IMemory>& sharedBuffer, int output, int *sessionId, status_t *status);
AudioFlinger类中createTrack实现如下
sp<IAudioTrack> AudioFlinger::createTrack( pid_t pid, int streamType, uint32_t sampleRate, int format, int channelCount, int frameCount, uint32_t flags, const sp<IMemory>& sharedBuffer, int output, int *sessionId, status_t *status) { sp<PlaybackThread::Track> track; sp<TrackHandle> trackHandle; sp<Client> client; wp<Client> wclient; status_t lStatus; int lSessionId; if (streamType >= AudioSystem::NUM_STREAM_TYPES) { LOGE("invalid stream type"); lStatus = BAD_VALUE; goto Exit; } { Mutex::Autolock _l(mLock); PlaybackThread *thread = checkPlaybackThread_l(output); PlaybackThread *effectThread = NULL;
if (thread == NULL) { LOGE("unknown output thread"); lStatus = BAD_VALUE; goto Exit; } wclient = mClients.valueFor(pid); if (wclient != NULL) { client = wclient.promote(); } else { client = new Client(this, pid); mClients.add(pid, client); } LOGV("createTrack() sessionId: %d", (sessionId == NULL) ? -2 : *sessionId); if (sessionId != NULL && *sessionId != AudioSystem::SESSION_OUTPUT_MIX) { for (size_t i = 0; i < mPlaybackThreads.size(); i++) { sp<PlaybackThread> t = mPlaybackThreads.valueAt(i); if (mPlaybackThreads.keyAt(i) != output) { // prevent same audio session on different output threads uint32_t sessions = t->hasAudioSession(*sessionId); if (sessions & PlaybackThread::TRACK_SESSION) { lStatus = BAD_VALUE; goto Exit; } // check if an effect with same session ID is waiting for a track to be created if (sessions & PlaybackThread::EFFECT_SESSION) { effectThread = t.get(); } } } lSessionId = *sessionId; } else { // if no audio session id is provided, create one here lSessionId = nextUniqueId(); if (sessionId != NULL) { *sessionId = lSessionId; } } LOGV("createTrack() lSessionId: %d", lSessionId); track = thread->createTrack_l(client, streamType, sampleRate, format, channelCount, frameCount, sharedBuffer, lSessionId, &lStatus); // move effect chain to this output thread if an effect on same session was waiting // for a track to be created if (lStatus == NO_ERROR && effectThread != NULL) { Mutex::Autolock _dl(thread->mLock); Mutex::Autolock _sl(effectThread->mLock); moveEffectChain_l(lSessionId, effectThread, thread, true); } } if (lStatus == NO_ERROR) { trackHandle = new TrackHandle(track); } else { // remove local strong reference to Client before deleting the Track so that the Client // destructor is called by the TrackBase destructor with mLock held client.clear(); track.clear(); } Exit: if(status) { *status = lStatus; } return trackHandle; }