Android -- Audio Native服务之启动流程分析(一)
Android中的Audio系统是比较庞大、繁杂的一部分内容, 其中会涉及较多的音频编解码、多媒体制式与Android Audio HAL设备管理的知识。随着Android的发展,其所支持的音频设备也变得越来丰富,如扬声器、耳机、听筒等等;这种变化也为Android管理如此丰富的音频设备以及如何正确、合理地切换音频输出提出了更高的要求。面对如此繁杂的管理要求,我们分析Android Audio服务的历程想必也不会轻松。接下来,我们会以Audio Native服务的启动为入口,以其基本实现流程为重点,抓住代码中的各个关键点,循序渐进地学习Android
Audio部分的知识,先让我们对它有一个基本的认识和了解;其他的代码细节分析,则需要我们在工作、学习中花费更多的时间去揣摩和思考了。
Android Audio部分最主要的Native服务有两个:AudioFlinger和AudioPolicyService。
AudioFlinger是Android Audio系统的核心与中枢。从上,它为Android Audio API实现提供具体的功能接口;向下,它与Audio HAL层交互,管理音频设备。我们知道HAL层是Android对各个物理设备的代码抽象。HAL层中封装了操作物理设备的接口,通过调用这些接口,我们就可以操作设备,实现我们自己的功能。又由于AudioFlinger负责管理这些Audio设备,所以我们可以猜测它有一套自己的机制,来区分和管理这些Audio Interface。
同时,AudioFlinger直接与HAL交互,它其中也必然实现了音频数据管理、音频输入输出等功能。我们也要注意,Android中支持多种音频设备,那么就需要有一位大师来管理音频数据到底从哪种设备输入或者输出;这就牵扯到一种策略制定的问题,它指引音频数据的流向,即与哪种物理设备交互。既然是制定策略,那这位大师当然就是AudioPolicyService。基于这种分工,我们可以得出:AudioFlinger是一个工作繁重的服务,它是Audio策略的功能执行者,直接负责音频数据与音频设备的交互;而策略由AudioPolicyService制定,它负责把控AudioFlinger的工作方向。
有了这些概念,我们再去分析AudioFlinger和AudioPolicyService的服务启动过程。与之前不同的是,较新的Android系统中,Audio相关的服务都被移动了audioserver进程中。系统启动的时候,会创建该进程,其中就有AudioFlinger和AudioPolicyService的启动处理:
int main(int argc __unused, char **argv) { signal(SIGPIPE, SIG_IGN); bool doLog = (bool) property_get_bool("ro.test_harness", 0); pid_t childPid; // FIXME The advantage of making the process containing media.log service the parent process of // the process that contains the other audio services, is that it allows us to collect more // detailed information such as signal numbers, stop and continue, resource usage, etc. // But it is also more complex. Consider replacing this by independent processes, and using // binder on death notification instead. if (doLog && (childPid = fork()) != 0) { // media.log service //prctl(PR_SET_NAME, (unsigned long) "media.log", 0, 0, 0); // unfortunately ps ignores PR_SET_NAME for the main thread, so use this ugly hack strcpy(argv[0], "media.log"); sp<ProcessState> proc(ProcessState::self()); MediaLogService::instantiate(); ProcessState::self()->startThreadPool(); IPCThreadState::self()->joinThreadPool(); for (;;) { siginfo_t info; int ret = waitid(P_PID, childPid, &info, WEXITED | WSTOPPED | WCONTINUED); if (ret == EINTR) { continue; } if (ret < 0) { break; } char buffer[32]; const char *code; switch (info.si_code) { case CLD_EXITED: code = "CLD_EXITED"; break; case CLD_KILLED: code = "CLD_KILLED"; break; case CLD_DUMPED: code = "CLD_DUMPED"; break; case CLD_STOPPED: code = "CLD_STOPPED"; break; case CLD_TRAPPED: code = "CLD_TRAPPED"; break; case CLD_CONTINUED: code = "CLD_CONTINUED"; break; default: snprintf(buffer, sizeof(buffer), "unknown (%d)", info.si_code); code = buffer; break; } struct rusage usage; getrusage(RUSAGE_CHILDREN, &usage); ALOG(LOG_ERROR, "media.log", "pid %d status %d code %s user %ld.%03lds sys %ld.%03lds", info.si_pid, info.si_status, code, usage.ru_utime.tv_sec, usage.ru_utime.tv_usec / 1000, usage.ru_stime.tv_sec, usage.ru_stime.tv_usec / 1000); sp<IServiceManager> sm = defaultServiceManager(); sp<IBinder> binder = sm->getService(String16("media.log")); if (binder != 0) { Vector<String16> args; binder->dump(-1, args); } switch (info.si_code) { case CLD_EXITED: case CLD_KILLED: case CLD_DUMPED: { ALOG(LOG_INFO, "media.log", "exiting"); _exit(0); // not reached } default: break; } } } else { // all other services if (doLog) { prctl(PR_SET_PDEATHSIG, SIGKILL); // if parent media.log dies before me, kill me also setpgid(0, 0); // but if I die first, don‘t kill my parent } sp<ProcessState> proc(ProcessState::self()); sp<IServiceManager> sm = defaultServiceManager(); ALOGI("ServiceManager: %p", sm.get()); AudioFlinger::instantiate();//启动AudioFlinger AudioPolicyService::instantiate();//启动AudioPolicyService RadioService::instantiate(); SoundTriggerHwService::instantiate(); ProcessState::self()->startThreadPool(); IPCThreadState::self()->joinThreadPool(); } }
AudioFlinger::instantiate()、AudioPolicyService::instantiate()的调用就是服务的启动过程,下面我们一一分析。
一、AudioFlinger::instantiate()
AudioFlinger的继承关系声明如下:
class AudioFlinger : public BinderService<AudioFlinger>, public BnAudioFlinger
AudioFlinger是一个Binder服务的服务端实现,整个AudioFlinger的Binder服务结构如图所示:
继承BnAudioFlinger说明它确实是IAudioFlinger的服务端;而BinderService更像是一个模板工具类,它封装了Binder服务发布、启动的一些方法:
template<typename SERVICE> class BinderService { public: static status_t publish(bool allowIsolated = false) { sp<IServiceManager> sm(defaultServiceManager()); return sm->addService( String16(SERVICE::getServiceName()), new SERVICE(), allowIsolated); } static void publishAndJoinThreadPool(bool allowIsolated = false) { publish(allowIsolated); joinThreadPool(); } static void instantiate() { publish(); } static status_t shutdown() { return NO_ERROR; } private: static void joinThreadPool() { sp<ProcessState> ps(ProcessState::self()); ps->startThreadPool(); ps->giveThreadPoolName(); IPCThreadState::self()->joinThreadPool(); } };
BinderService::instantiate()内部会创建AudioFlinger服务实例,并通过ServiceManager将其发布到系统中;其中,AudioFlinger服务注册的名称是“media.audio_flinger”。
我们看看IAudioFlinger和AudioFlinger的定义。首先是IAudioFlinger:
class IAudioFlinger : public IInterface { public: DECLARE_META_INTERFACE(AudioFlinger); // invariant on exit for all APIs that return an sp<>: // (return value != 0) == (*status == NO_ERROR) /* create an audio track and registers it with AudioFlinger. * return null if the track cannot be created. */ virtual sp<IAudioTrack> createTrack() = 0;//AudioTrack使用时会涉及到 virtual sp<IAudioRecord> openRecord() = 0; // FIXME Surprisingly, format/latency don‘t work for input handles /* query the audio hardware state. This state never changes, * and therefore can be cached. */ virtual uint32_t sampleRate(audio_io_handle_t ioHandle) const = 0; // reserved; formerly channelCount() virtual audio_format_t format(audio_io_handle_t output) const = 0; virtual size_t frameCount(audio_io_handle_t ioHandle) const = 0; // return estimated latency in milliseconds virtual uint32_t latency(audio_io_handle_t output) const = 0; /* set/get the audio hardware state. This will probably be used by * the preference panel, mostly. */ virtual status_t setMasterVolume(float value) = 0; ...... virtual bool masterMute() const = 0; /* set/get stream type state. This will probably be used by * the preference panel, mostly. */ virtual status_t setStreamVolume(audio_stream_type_t stream, float value, audio_io_handle_t output) = 0; ...... virtual bool streamMute(audio_stream_type_t stream) const = 0; // set audio mode virtual status_t setMode(audio_mode_t mode) = 0; // mic mute/state virtual status_t setMicMute(bool state) = 0; virtual bool getMicMute() const = 0; virtual status_t setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs) = 0; virtual String8 getParameters(audio_io_handle_t ioHandle, const String8& keys) const = 0; virtual status_t openOutput() = 0; virtual audio_io_handle_t openDuplicateOutput() = 0; virtual status_t closeOutput(audio_io_handle_t output) = 0; virtual status_t suspendOutput(audio_io_handle_t output) = 0; virtual status_t restoreOutput(audio_io_handle_t output) = 0; virtual status_t openInput() = 0; virtual status_t closeInput(audio_io_handle_t input) = 0; ...... virtual audio_module_handle_t loadHwModule(const char *name) = 0;//加载Interface ...... };
IAudioFlinger定义了AudioFlinger服务的基本业务函数。我们从中可以看到,它定义了加载Audio Interface、音量设置、音频设备属性获取(采样率、帧信息)、打开音频设备输入、输出流等函数。
AudioFlinger是IAudioFlinger的服务端实现,它必定要实现IAudioFlinger中的接口;我们这里只看一些它添加的主要函数定义:
ThreadBase *checkThread_l(audio_io_handle_t ioHandle) const; PlaybackThread *checkPlaybackThread_l(audio_io_handle_t output) const; MixerThread *checkMixerThread_l(audio_io_handle_t output) const; RecordThread *checkRecordThread_l(audio_io_handle_t input) const; sp<RecordThread> openInput_l(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<PlaybackThread> openOutput_l(audio_module_handle_t module, audio_io_handle_t *output, audio_config_t *config, audio_devices_t devices, const String8& address, audio_output_flags_t flags); void closeOutputFinish(sp<PlaybackThread> thread); void closeInputFinish(sp<RecordThread> thread); // no range check, AudioFlinger::mLock held bool streamMute_l(audio_stream_type_t stream) const { return mStreamTypes[stream].mute; } // no range check, doesn‘t check per-thread stream volume, AudioFlinger::mLock held float streamVolume_l(audio_stream_type_t stream) const { return mStreamTypes[stream].volume; } void ioConfigChanged(audio_io_config_event event, const sp<AudioIoDescriptor>& ioDesc, pid_t pid = 0); // Allocate an audio_unique_id_t. // Specific types are audio_io_handle_t, audio_session_t, effect ID (int), // audio_module_handle_t, and audio_patch_handle_t. // They all share the same ID space, but the namespaces are actually independent // because there are separate KeyedVectors for each kind of ID. // The return value is cast to the specific type depending on how the ID will be used. // FIXME This API does not handle rollover to zero (for unsigned IDs), // or from positive to negative (for signed IDs). // Thus it may fail by returning an ID of the wrong sign, // or by returning a non-unique ID. // This is the internal API. For the binder API see newAudioUniqueId(). audio_unique_id_t nextUniqueId(audio_unique_id_use_t use); status_t moveEffectChain_l(audio_session_t sessionId, PlaybackThread *srcThread, PlaybackThread *dstThread, bool reRegister); // return thread associated with primary hardware device, or NULL PlaybackThread *primaryPlaybackThread_l() const; audio_devices_t primaryOutputDevice_l() const; // return the playback thread with smallest HAL buffer size, and prefer fast PlaybackThread *fastPlaybackThread_l() const; sp<PlaybackThread> getEffectThread_l(audio_session_t sessionId, int EffectId);
AudioFlinger中定义了许多跟PlaybackThread有关的函数。PlaybackThread是回放线程,定义在Thread.h中;它是AudioFlinger中真正处理音频数据的结构,担任一个任劳任怨的工人角色;PlaybackThread家族还有许多其他的线程子类,它们都对应着一个不同的音频数据处理场景。PlaybackThread相关的内容,后续分析到真正的音频数据处理时在介绍。
AudioFlinger中定义了几个内部类:
// server side of the client‘s IAudioTrack class TrackHandle : public android::BnAudioTrack {//使用AudioTrack时会涉及 public: TrackHandle(const sp<PlaybackThread::Track>& track); virtual ~TrackHandle(); virtual sp<IMemory> getCblk() const; virtual status_t start(); virtual void stop(); virtual void flush(); virtual void pause(); virtual status_t attachAuxEffect(int effectId); virtual status_t setParameters(const String8& keyValuePairs); virtual status_t getTimestamp(AudioTimestamp& timestamp); virtual void signal(); // signal playback thread for a change in control block virtual status_t onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags); private: const sp<PlaybackThread::Track> mTrack; }; // server side of the client‘s IAudioRecord class RecordHandle : public android::BnAudioRecord {//使用AudioRecord时,会涉及 public: RecordHandle(const sp<RecordThread::RecordTrack>& recordTrack); virtual ~RecordHandle(); virtual status_t start(int /*AudioSystem::sync_event_t*/ event, audio_session_t triggerSession); virtual void stop(); virtual status_t onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags); private: const sp<RecordThread::RecordTrack> mRecordTrack; // for use from destructor void stop_nonvirtual(); };
TrackHandler在分析AudioTrack的时候会介绍;RecordHandler也是如此。
另外,AudioFlinger中还有几个重要的集合对象:
//保存Audio Interface的一些信息 DefaultKeyedVector<audio_module_handle_t, AudioHwDevice*> mAudioHwDevs; //保存创建的PlaybackThread工作线程 DefaultKeyedVector< audio_io_handle_t, sp<PlaybackThread> > mPlaybackThreads; //保存创建的RecordThread录音工作线程 DefaultKeyedVector< audio_io_handle_t, sp<RecordThread> > mRecordThreads
这几个集合对象在后续的分析中都会遇到
有了对AudioFlinger定义的认识,我们再看它的构造函数。注册AudioFlinger服务时,会创建一个它的实例;此时会调用其构造函数:
AudioFlinger::AudioFlinger() : BnAudioFlinger(), mPrimaryHardwareDev(NULL), mAudioHwDevs(NULL), mHardwareStatus(AUDIO_HW_IDLE), mMasterVolume(1.0f), mMasterMute(false), // mNextUniqueId(AUDIO_UNIQUE_ID_USE_MAX), mMode(AUDIO_MODE_INVALID), mBtNrecIsOff(false), mIsLowRamDevice(true), mIsDeviceTypeKnown(false), mGlobalEffectEnableTime(0), mSystemReady(false) { // unsigned instead of audio_unique_id_use_t, because ++ operator is unavailable for enum for (unsigned use = AUDIO_UNIQUE_ID_USE_UNSPECIFIED; use < AUDIO_UNIQUE_ID_USE_MAX; use++) { // zero ID has a special meaning, so unavailable mNextUniqueIds[use] = AUDIO_UNIQUE_ID_USE_MAX; } getpid_cached = getpid(); const bool doLog = property_get_bool("ro.test_harness", false); if (doLog) { mLogMemoryDealer = new MemoryDealer(kLogMemorySize, "LogWriters", MemoryHeapBase::READ_ONLY); } // reset battery stats. // if the audio service has crashed, battery stats could be left // in bad state, reset the state upon service start. BatteryNotifier::getInstance().noteResetAudio(); #ifdef TEE_SINK char value[PROPERTY_VALUE_MAX]; (void) property_get("ro.debuggable", value, "0"); int debuggable = atoi(value); int teeEnabled = 0; if (debuggable) { (void) property_get("af.tee", value, "0"); teeEnabled = atoi(value); } // FIXME symbolic constants here if (teeEnabled & 1) { mTeeSinkInputEnabled = true; } if (teeEnabled & 2) { mTeeSinkOutputEnabled = true; } if (teeEnabled & 4) { mTeeSinkTrackEnabled = true; } #endif }
AudioFlinger的构造函数并没有做某些复杂的初始化操作,都是一些简单的成员变量赋值等。基于Android强弱指针的知识,我们知道一个对象被sp<>引用时,会调用它的onFirstRef()函数。AudioFlinger也是这样,它的onFirstRef()实现是:
void AudioFlinger::onFirstRef() { Mutex::Autolock _l(mLock); /* TODO: move all this work into an Init() function */ char val_str[PROPERTY_VALUE_MAX] = { 0 }; if (property_get("ro.audio.flinger_standbytime_ms", val_str, NULL) >= 0) { uint32_t int_val; if (1 == sscanf(val_str, "%u", &int_val)) { mStandbyTimeInNsecs = milliseconds(int_val); ALOGI("Using %u mSec as standby time.", int_val); } else { mStandbyTimeInNsecs = kDefaultStandbyTimeInNsecs; ALOGI("Using default %u mSec as standby time.", (uint32_t)(mStandbyTimeInNsecs / 1000000)); } } mPatchPanel = new PatchPanel(this); mMode = AUDIO_MODE_NORMAL; }
函数中的处理也较为简单,可能需要注意的就是这个“ro.audio.flinger_standbytime_ms”属性了。经过了这两个函数调用,AudioFlinger就已经完成了初始化工作,成为了一个有效的对象实体。至此,AudioFlinger服务的启动过程就结束了。
AudioPolicyService::instantiate()
在Audio架构中,AudioFlinger是手,那大脑就是AudioPolicyService了。它制定Audio策略,把控AudioFlinger的工作方向;AudioFlinger按照AudioPolicyService的意志,处理到来的音频数据。
AudioPolicyService的定义如下:
//函数的实现定义在AudioPolicyService.cpp/AudioPolicyServiceImpl.cpp/AudioPolicyServiceImplLegacy.cpp中 class AudioPolicyService : public BinderService<AudioPolicyService>, public BnAudioPolicyService, public IBinder::DeathRecipient
它是IAudioPolicyService的服务实现端,其结构如图所示:
IAudioPolicyService中定义的主要业务函数有:
class IAudioPolicyService : public IInterface { public: DECLARE_META_INTERFACE(AudioPolicyService); virtual status_t setForceUse(audio_policy_force_use_t usage, audio_policy_forced_cfg_t config) = 0; virtual audio_policy_forced_cfg_t getForceUse(audio_policy_force_use_t usage) = 0; virtual audio_io_handle_t getOutput() = 0; virtual status_t getOutputForAttr() = 0; virtual status_t startOutput() = 0; virtual status_t stopOutput() = 0; virtual void releaseOutput() = 0; virtual status_t getInputForAttr() = 0; virtual status_t startInput(audio_io_handle_t input, audio_session_t session) = 0; virtual status_t stopInput(audio_io_handle_t input, audio_session_t session) = 0; virtual void releaseInput(audio_io_handle_t input, audio_session_t session) = 0; virtual uint32_t getStrategyForStream(audio_stream_type_t stream) = 0; virtual audio_devices_t getDevicesForStream(audio_stream_type_t stream) = 0; ...... /* Set audio port configuration */ virtual status_t setAudioPortConfig(const struct audio_port_config *config) = 0; ...... virtual status_t registerPolicyMixes(Vector<AudioMix> mixes, bool registration) = 0; virtual status_t startAudioSource(const struct audio_port_config *source, const audio_attributes_t *attributes, audio_io_handle_t *handle) = 0; virtual status_t stopAudioSource(audio_io_handle_t handle) = 0; };
其中就包括跟策略有关的函数定义;另外,IAudioPolicyService中也定义了一些跟获取、控制音频设备输入输出有关的函数,这看起来跟其策略制定的角色并不搭配。其实这些函数间接都是靠AudioFlinger实现的,IAudioPolicyService中的这些函数只是一个中转站。
AudioPolicyService除了要实现IAudioPolicyService定义的业务函数外,也添加了一些函数定义,这在后面遇到的时候在去分析。
与前面的介绍类似,AudioPolicyService的启动过程其实就是它的创建、初始化过程。我们接着按这个步骤去分析AudioPolicyService。首先看它的构造函数:
AudioPolicyService::AudioPolicyService() : BnAudioPolicyService(), mpAudioPolicyDev(NULL), mpAudioPolicy(NULL), mAudioPolicyManager(NULL), mAudioPolicyClient(NULL), mPhoneState(AUDIO_MODE_INVALID) { }
AudioPolicyService的构造函数处理非常简单,我们再看其onFirstRef()实现:
void AudioPolicyService::onFirstRef() { { Mutex::Autolock _l(mLock); // start tone playback thread mTonePlaybackThread = new AudioCommandThread(String8("ApmTone"), this); // start audio commands thread mAudioCommandThread = new AudioCommandThread(String8("ApmAudio"), this); // start output activity command thread mOutputCommandThread = new AudioCommandThread(String8("ApmOutput"), this); #ifdef USE_LEGACY_AUDIO_POLICY ALOGI("AudioPolicyService CSTOR in legacy mode"); /* instantiate the audio policy manager */ const struct hw_module_t *module; int rc = hw_get_module(AUDIO_POLICY_HARDWARE_MODULE_ID, &module); if (rc) { return; } rc = audio_policy_dev_open(module, &mpAudioPolicyDev); ALOGE_IF(rc, "couldn‘t open audio policy device (%s)", strerror(-rc)); if (rc) { return; } rc = mpAudioPolicyDev->create_audio_policy(mpAudioPolicyDev, &aps_ops, this, &mpAudioPolicy); ALOGE_IF(rc, "couldn‘t create audio policy (%s)", strerror(-rc)); if (rc) { return; } rc = mpAudioPolicy->init_check(mpAudioPolicy); ALOGE_IF(rc, "couldn‘t init_check the audio policy (%s)", strerror(-rc)); if (rc) { return; } ALOGI("Loaded audio policy from %s (%s)", module->name, module->id); #else ALOGI("AudioPolicyService CSTOR in new mode"); //介绍使用新HAL库的情况 mAudioPolicyClient = new AudioPolicyClient(this);//AudioPolicyClinet是AudioPolicyService的内部类;构造AudoPolicyClient实例 //调用createAudioPolicyManager()函数构造AudioPolicyInterface类型的实例, //如果定义了USE_LEGACY_AUDIO_POLICY宏,不会走到该分支 //但此时会调用AudioPolicyManagerDefault.cpp中的实现,返回AudioPolicyManagerBase实例 //如果没有定义该红,说明使用新的实现, //则调用AudioPolicyFactory.cpp中该函数的实现,但它返回的是AudioPolicyManager对象. mAudioPolicyManager = createAudioPolicyManager(mAudioPolicyClient); #endif } // load audio processing modules sp<AudioPolicyEffects>audioPolicyEffects = new AudioPolicyEffects(); { Mutex::Autolock _l(mLock); mAudioPolicyEffects = audioPolicyEffects; } }
从代码中我们看到,整个函数的实现被一个宏定义分割成了两部分。USE_LEGACY_AUDIO_POLICY宏表明我们是否使用老的Audio策略实现,这里我们介绍新策略实现的部分。USE_LEGACY_AUDIO_POLICY如果没有被定义,则AudioPolicyService中导入的头文件会改变:
#ifdef USE_LEGACY_AUDIO_POLICY #include <hardware_legacy/AudioPolicyInterface.h> #endif #include "AudioPolicyEffects.h" #include "managerdefault/AudioPolicyManager.h"
回到onFirstRef()函数中,此时主要的处理过程是:
//介绍使用新HAL库的情况 mAudioPolicyClient = new AudioPolicyClient(this);//AudioPolicyClinet是AudioPolicyService的内部类;构造AudoPolicyClient实例 //调用createAudioPolicyManager()函数构造AudioPolicyInterface类型的实例, //如果定义了USE_LEGACY_AUDIO_POLICY宏,不会走到该分支 //但此时会调用AudioPolicyManagerDefault.cpp中的实现,返回AudioPolicyManagerBase实例 //如果没有定义该红,说明使用新的实现, //则调用AudioPolicyFactory.cpp中该函数的实现,但它返回的是AudioPolicyManager对象. mAudioPolicyManager = createAudioPolicyManager(mAudioPolicyClient);
主要是初始化AudioPolicyService中的两个成员变量:mAudioPolicyClient和mAudioPolicyManager,看它们的类型定义是什么样的:
AudioPolicyInterface *mAudioPolicyManager; AudioPolicyClient *mAudioPolicyClient;
AudioPolicyClient是AudioPolicyService内部定义的一个类,继承自AudioPolicyClientInterface。createAudioPolicyManager()函数以AudioPolicyClient对象为参数,返回的是AudioPolicyInterface类型的实例。这几个类型的继承关系如图所示:
AudioPolicyService::AudioPolicyClient可以看做是AudioPolicyService服务的代理类,当然只是代理一部分实现。AudioPolicyClient的接口都是借助AudioPolicyService和AudioFlinger实现的。AudioPolicyClient的类型定义如下:
//函数实现定义在AudioPolicyClientImpl.cpp/AudioPolicyClientImplLegacy.cpp中 class AudioPolicyClient : public AudioPolicyClientInterface { public: AudioPolicyClient(AudioPolicyService *service) : mAudioPolicyService(service) {} virtual ~AudioPolicyClient() {} // // Audio HW module functions // // loads a HW module. virtual audio_module_handle_t loadHwModule(const char *name); // // Audio output Control functions // // opens an audio output with the requested parameters. The parameter values can indicate to use the default values // in case the audio policy manager has no specific requirements for the output being opened. // When the function returns, the parameter values reflect the actual values used by the audio hardware output stream. // The audio policy manager can check if the proposed parameters are suitable or not and act accordingly. virtual status_t openOutput(audio_module_handle_t module, audio_io_handle_t *output, audio_config_t *config, audio_devices_t *devices, const String8& address, uint32_t *latencyMs, audio_output_flags_t flags); // creates a special output that is duplicated to the two outputs passed as arguments. The duplication is performed by // a special mixer thread in the AudioFlinger. virtual audio_io_handle_t openDuplicateOutput(audio_io_handle_t output1, audio_io_handle_t output2); // closes the output stream virtual status_t closeOutput(audio_io_handle_t output); // suspends the output. When an output is suspended, the corresponding audio hardware output stream is placed in // standby and the AudioTracks attached to the mixer thread are still processed but the output mix is discarded. virtual status_t suspendOutput(audio_io_handle_t output); // restores a suspended output. virtual status_t restoreOutput(audio_io_handle_t output); // // Audio input Control functions // // opens an audio input virtual audio_io_handle_t openInput(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); // closes an audio input virtual status_t closeInput(audio_io_handle_t input); // // misc control functions // // set a stream volume for a particular output. For the same user setting, a given stream type can have different volumes // for each output (destination device) it is attached to. virtual status_t setStreamVolume(audio_stream_type_t stream, float volume, audio_io_handle_t output, int delayMs = 0); // invalidate a stream type, causing a reroute to an unspecified new output virtual status_t invalidateStream(audio_stream_type_t stream); // function enabling to send proprietary informations directly from audio policy manager to audio hardware interface. virtual void setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs, int delayMs = 0); // function enabling to receive proprietary informations directly from audio hardware interface to audio policy manager. virtual String8 getParameters(audio_io_handle_t ioHandle, const String8& keys); // request the playback of a tone on the specified stream: used for instance to replace notification sounds when playing // over a telephony device during a phone call. virtual status_t startTone(audio_policy_tone_t tone, audio_stream_type_t stream); virtual status_t stopTone(); // set down link audio volume. virtual status_t setVoiceVolume(float volume, int delayMs = 0); // move effect to the specified output virtual status_t moveEffects(audio_session_t session, audio_io_handle_t srcOutput, audio_io_handle_t dstOutput); /* Create a patch between several source and sink ports */ virtual status_t createAudioPatch(const struct audio_patch *patch, audio_patch_handle_t *handle, int delayMs); /* Release a patch */ virtual status_t releaseAudioPatch(audio_patch_handle_t handle, int delayMs); /* Set audio port configuration */ virtual status_t setAudioPortConfig(const struct audio_port_config *config, int delayMs); virtual void onAudioPortListUpdate(); virtual void onAudioPatchListUpdate(); virtual void onDynamicPolicyMixStateUpdate(String8 regId, int32_t state); virtual void onRecordingConfigurationUpdate(int event, audio_session_t session, audio_source_t source, const audio_config_base_t *clientConfig, const audio_config_base_t *deviceConfig, audio_patch_handle_t patchHandle); virtual audio_unique_id_t newAudioUniqueId(audio_unique_id_use_t use); private: AudioPolicyService *mAudioPolicyService; };
它的成员mAudioPolicyService会保存当前的AudioPolicyService实例;它内部的许多函数定义基本与AudioPolicyService的一致。
createAudioPolicyManager()函数实现在AudioPolicyFactory.cpp中:
#include "managerdefault/AudioPolicyManager.h" namespace android { extern "C" AudioPolicyInterface* createAudioPolicyManager( AudioPolicyClientInterface *clientInterface) { return new AudioPolicyManager(clientInterface); } extern "C" void destroyAudioPolicyManager(AudioPolicyInterface *interface) { delete interface; } }; // namespace android
以AudioPolicyService::AudioPolicyClient对象为参数创建AudioPolicyManager实例。AudioPolicyManager继承自AudioPolicyInterface,它实现了Audio策略管理的接口。看它的构造函数实现:
// ---------------------------------------------------------------------------- // AudioPolicyManager // ---------------------------------------------------------------------------- uint32_t AudioPolicyManager::nextAudioPortGeneration() { return android_atomic_inc(&mAudioPortGeneration); } AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterface) : #ifdef AUDIO_POLICY_TEST Thread(false), #endif //AUDIO_POLICY_TEST mLimitRingtoneVolume(false), mLastVoiceVolume(-1.0f), mA2dpSuspended(false), mAudioPortGeneration(1), mBeaconMuteRefCount(0), mBeaconPlayingRefCount(0), mBeaconMuted(false), mTtsOutputAvailable(false), mMasterMono(false) { mUidCached = getuid(); mpClientInterface = clientInterface; // TODO: remove when legacy conf file is removed. true on devices that use DRC on the // DEVICE_CATEGORY_SPEAKER path to boost soft sounds, used to adjust volume curves accordingly. // Note: remove also speaker_drc_enabled from global configuration of XML config file. bool speakerDrcEnabled = false; #ifdef USE_XML_AUDIO_POLICY_CONF mVolumeCurves = new VolumeCurvesCollection(); AudioPolicyConfig config(mHwModules, mAvailableOutputDevices, mAvailableInputDevices, mDefaultOutputDevice, speakerDrcEnabled, static_cast<VolumeCurvesCollection *>(mVolumeCurves)); PolicySerializer serializer; if (serializer.deserialize(AUDIO_POLICY_XML_CONFIG_FILE, config) != NO_ERROR) { #else mVolumeCurves = new StreamDescriptorCollection(); AudioPolicyConfig config(mHwModules, mAvailableOutputDevices, mAvailableInputDevices, mDefaultOutputDevice, speakerDrcEnabled); //初始化Vector <HwModule *> mHwModules集合;加载audio_policy.conf中描述的具体音频设备(1.primary;2.a2dp;3.usb.4.etc...),将audio interface的信息组合保存到mHwModules中; //HwModule实例保存了音频接口名称等,内部的IOProfile对象会保存设备的采样率、格式等等信息. //优先加载硬件厂商的配置文件,如果没有则使用默认的配置文件 if ((ConfigParsingUtils::loadConfig(AUDIO_POLICY_VENDOR_CONFIG_FILE, config) != NO_ERROR) && (ConfigParsingUtils::loadConfig(AUDIO_POLICY_CONFIG_FILE, config) != NO_ERROR)) { #endif ALOGE("could not load audio policy configuration file, setting defaults"); config.setDefault(); } // must be done after reading the policy (since conditionned by Speaker Drc Enabling) mVolumeCurves->initializeVolumeCurves(speakerDrcEnabled); // Once policy config has been parsed, retrieve an instance of the engine and initialize it. audio_policy::EngineInstance *engineInstance = audio_policy::EngineInstance::getInstance(); if (!engineInstance) { ALOGE("%s: Could not get an instance of policy engine", __FUNCTION__); return; } // Retrieve the Policy Manager Interface mEngine = engineInstance->queryInterface<AudioPolicyManagerInterface>(); if (mEngine == NULL) { ALOGE("%s: Failed to get Policy Engine Interface", __FUNCTION__); return; } mEngine->setObserver(this); status_t status = mEngine->initCheck(); (void) status; ALOG_ASSERT(status == NO_ERROR, "Policy engine not initialized(err=%d)", status); // mAvailableOutputDevices and mAvailableInputDevices now contain all attached devices // open all output streams needed to access attached devices audio_devices_t outputDeviceTypes = mAvailableOutputDevices.types(); audio_devices_t inputDeviceTypes = mAvailableInputDevices.types() & ~AUDIO_DEVICE_BIT_IN; for (size_t i = 0; i < mHwModules.size(); i++) {//利用loadHwModule()加载audio_policy.conf中解析出的audio interface,即mHwModules数组中的元素 mHwModules[i]->mHandle = mpClientInterface->loadHwModule(mHwModules[i]->getName());//其实是调用AudioFlinger::loadHwModule()函数;name的值主要是:1.primary;2.a2dp;3.usb.4.etc...; if (mHwModules[i]->mHandle == 0) { if (mHwModules[i]->mHandle == 0) { ALOGW("could not open HW module %s", mHwModules[i]->getName()); continue; } // open all output streams needed to access attached devices // except for direct output streams that are only opened when they are actually // required by an app. // This also validates mAvailableOutputDevices list for (size_t j = 0; j < mHwModules[i]->mOutputProfiles.size(); j++)//利用openOutput(),为各个audio interface打开一个输出通道,并创建PlaybackThread工作线程 { const sp<IOProfile> outProfile = mHwModules[i]->mOutputProfiles[j]; if (!outProfile->hasSupportedDevices()) { ALOGW("Output profile contains no device on module %s", mHwModules[i]->getName()); continue; } if ((outProfile->getFlags() & AUDIO_OUTPUT_FLAG_TTS) != 0) { mTtsOutputAvailable = true; } if ((outProfile->getFlags() & AUDIO_OUTPUT_FLAG_DIRECT) != 0) { continue; } audio_devices_t profileType = outProfile->getSupportedDevicesType(); if ((profileType & mDefaultOutputDevice->type()) != AUDIO_DEVICE_NONE) { profileType = mDefaultOutputDevice->type(); } else { // chose first device present in profile‘s SupportedDevices also part of // outputDeviceTypes profileType = outProfile->getSupportedDeviceForType(outputDeviceTypes); } if ((profileType & outputDeviceTypes) == 0) { continue; } sp<SwAudioOutputDescriptor> outputDesc = new SwAudioOutputDescriptor(outProfile, mpClientInterface); const DeviceVector &supportedDevices = outProfile->getSupportedDevices(); const DeviceVector &devicesForType = supportedDevices.getDevicesFromType(profileType); String8 address = devicesForType.size() > 0 ? devicesForType.itemAt(0)->mAddress : String8(""); outputDesc->mDevice = profileType; audio_config_t config = AUDIO_CONFIG_INITIALIZER; config.sample_rate = outputDesc->mSamplingRate; config.channel_mask = outputDesc->mChannelMask; config.format = outputDesc->mFormat; audio_io_handle_t output = AUDIO_IO_HANDLE_NONE; //导致AudioFlinger会为当前的audio interface打开一个输出通道;并根据当前的信息创建一个工作线程,并返回该线程的索引号 status_t status = mpClientInterface->openOutput(outProfile->getModuleHandle(), &output, &config, &outputDesc->mDevice, address, &outputDesc->mLatency, outputDesc->mFlags); if (status != NO_ERROR) { ALOGW("Cannot open output stream for device %08x on hw module %s", outputDesc->mDevice, mHwModules[i]->getName()); } else { outputDesc->mSamplingRate = config.sample_rate; outputDesc->mChannelMask = config.channel_mask; outputDesc->mFormat = config.format; for (size_t k = 0; k < supportedDevices.size(); k++) { ssize_t index = mAvailableOutputDevices.indexOf(supportedDevices[k]); // give a valid ID to an attached device once confirmed it is reachable if (index >= 0 && !mAvailableOutputDevices[index]->isAttached()) { mAvailableOutputDevices[index]->attach(mHwModules[i]); } } if (mPrimaryOutput == 0 && outProfile->getFlags() & AUDIO_OUTPUT_FLAG_PRIMARY) { mPrimaryOutput = outputDesc; } addOutput(output, outputDesc);//AudioPolicyManagerBase维护了一个与设备相关的key/value集合,更新该集合 setOutputDevice(outputDesc, outputDesc->mDevice, true, 0, NULL, address.string());//设置输出设备,就是设置音频流从哪个设备出去 } } // open input streams needed to access attached devices to validate // mAvailableInputDevices list //与之前的处理类似,只不过此时是对于audio interface的输入设备而言的 for (size_t j = 0; j < mHwModules[i]->mInputProfiles.size(); j++) { const sp<IOProfile> inProfile = mHwModules[i]->mInputProfiles[j]; if (!inProfile->hasSupportedDevices()) { ALOGW("Input profile contains no device on module %s", mHwModules[i]->getName()); continue; } // chose first device present in profile‘s SupportedDevices also part of // inputDeviceTypes audio_devices_t profileType = inProfile->getSupportedDeviceForType(inputDeviceTypes); if ((profileType & inputDeviceTypes) == 0) { continue; } sp<AudioInputDescriptor> inputDesc = new AudioInputDescriptor(inProfile); inputDesc->mDevice = profileType; // find the address DeviceVector inputDevices = mAvailableInputDevices.getDevicesFromType(profileType); // the inputs vector must be of size 1, but we don‘t want to crash here String8 address = inputDevices.size() > 0 ? inputDevices.itemAt(0)->mAddress : String8(""); ALOGV(" for input device 0x%x using address %s", profileType, address.string()); ALOGE_IF(inputDevices.size() == 0, "Input device list is empty!"); audio_config_t config = AUDIO_CONFIG_INITIALIZER; config.sample_rate = inputDesc->mSamplingRate; config.channel_mask = inputDesc->mChannelMask; config.format = inputDesc->mFormat; audio_io_handle_t input = AUDIO_IO_HANDLE_NONE; status_t status = mpClientInterface->openInput(inProfile->getModuleHandle(), &input, &config, &inputDesc->mDevice, address, AUDIO_SOURCE_MIC, AUDIO_INPUT_FLAG_NONE); if (status == NO_ERROR) { const DeviceVector &supportedDevices = inProfile->getSupportedDevices(); for (size_t k = 0; k < supportedDevices.size(); k++) { ssize_t index = mAvailableInputDevices.indexOf(supportedDevices[k]); // give a valid ID to an attached device once confirmed it is reachable if (index >= 0) { sp<DeviceDescriptor> devDesc = mAvailableInputDevices[index]; if (!devDesc->isAttached()) { devDesc->attach(mHwModules[i]); devDesc->importAudioPort(inProfile); } } } mpClientInterface->closeInput(input); } else { ALOGW("Cannot open input stream for device %08x on hw module %s", inputDesc->mDevice, mHwModules[i]->getName()); } } } // make sure all attached devices have been allocated a unique ID for (size_t i = 0; i < mAvailableOutputDevices.size();) { if (!mAvailableOutputDevices[i]->isAttached()) { ALOGW("Output device %08x unreachable", mAvailableOutputDevices[i]->type()); mAvailableOutputDevices.remove(mAvailableOutputDevices[i]); continue; } // The device is now validated and can be appended to the available devices of the engine mEngine->setDeviceConnectionState(mAvailableOutputDevices[i], AUDIO_POLICY_DEVICE_STATE_AVAILABLE); i++; } for (size_t i = 0; i < mAvailableInputDevices.size();) { if (!mAvailableInputDevices[i]->isAttached()) { ALOGW("Input device %08x unreachable", mAvailableInputDevices[i]->type()); mAvailableInputDevices.remove(mAvailableInputDevices[i]); continue; } // The device is now validated and can be appended to the available devices of the engine mEngine->setDeviceConnectionState(mAvailableInputDevices[i], AUDIO_POLICY_DEVICE_STATE_AVAILABLE); i++; } // make sure default device is reachable if (mDefaultOutputDevice == 0 || mAvailableOutputDevices.indexOf(mDefaultOutputDevice) < 0) { ALOGE("Default device %08x is unreachable", mDefaultOutputDevice->type()); } ALOGE_IF((mPrimaryOutput == 0), "Failed to open primary output"); updateDevicesAndOutputs();//更新不同策略使用的设备 #ifdef AUDIO_POLICY_TEST if (mPrimaryOutput != 0) { AudioParameter outputCmd = AudioParameter(); outputCmd.addInt(String8("set_id"), 0); mpClientInterface->setParameters(mPrimaryOutput->mIoHandle, outputCmd.toString()); mTestDevice = AUDIO_DEVICE_OUT_SPEAKER; mTestSamplingRate = 44100; mTestFormat = AUDIO_FORMAT_PCM_16_BIT; mTestChannels = AUDIO_CHANNEL_OUT_STEREO; mTestLatencyMs = 0; mCurOutput = 0; mDirectOutput = false; for (int i = 0; i < NUM_TEST_OUTPUTS; i++) { mTestOutputs[i] = 0; } const size_t SIZE = 256; char buffer[SIZE]; snprintf(buffer, SIZE, "AudioPolicyManagerTest"); run(buffer, ANDROID_PRIORITY_AUDIO); } #endif //AUDIO_POLICY_TEST }
首先会将传入的AudioPolicyClient实例起来。后面的工作都跟我们的Audio Interface有关了。首先会去解析audio_policy.conf文件,它描述了硬件支持的音频设备的各种信息;最终将解析得到的Audio
interface信息对象化,并保存到mHwModules集合中。接着会通过AudioFlinger::loadHwModule()函数去为各个接口加载所需的库,并创建对应的Interface对象保存起来:
audio_module_handle_t AudioPolicyService::AudioPolicyClient::loadHwModule(const char *name) { sp<IAudioFlinger> af = AudioSystem::get_audio_flinger(); if (af == 0) { ALOGW("%s: could not get AudioFlinger", __func__); return AUDIO_MODULE_HANDLE_NONE; } return af->loadHwModule(name); }
audio_module_handle_t AudioFlinger::loadHwModule(const char *name) { if (name == NULL) { return AUDIO_MODULE_HANDLE_NONE; } if (!settingsAllowed()) { return AUDIO_MODULE_HANDLE_NONE; } Mutex::Autolock _l(mLock); return loadHwModule_l(name); } // loadHwModule_l() must be called with AudioFlinger::mLock held //加载音频接口 //1.findSuitableHwDev_l()指定的modules为0时,需要load所有潜在的audio interface设备; //2.AudioPolicyManagerBase在构造函数中会预加载所有audio_policy.conf中描述的output设备; //这两种情况都会调用该函数加载audio interface audio_module_handle_t AudioFlinger::loadHwModule_l(const char *name) { //1.是否已经添加过这个Interface; //DefaultKeyedVector<audio_module_handle_t, AudioHwDevice*> mAudioHwDevs; for (size_t i = 0; i < mAudioHwDevs.size(); i++) { if (strncmp(mAudioHwDevs.valueAt(i)->moduleName(), name, strlen(name)) == 0) { ALOGW("loadHwModule() module %s already loaded", name); return mAudioHwDevs.keyAt(i); } } audio_hw_device_t *dev; //2.加载Audio Interface int rc = load_audio_interface(name, &dev);//加载设备所需的库文件,然后打开设备并创建一个audio_hw_device_t实例 if (rc) { ALOGE("loadHwModule() error %d loading module %s", rc, name); return AUDIO_MODULE_HANDLE_NONE; } //3.初始化 mHardwareStatus = AUDIO_HW_INIT; rc = dev->init_check(dev);//确定该audio interface是否已经成功初始化 mHardwareStatus = AUDIO_HW_IDLE; if (rc) { ALOGE("loadHwModule() init check error %d for module %s", rc, name); return AUDIO_MODULE_HANDLE_NONE; } // Check and cache this HAL‘s level of support for master mute and master // volume. If this is the first HAL opened, and it supports the get // methods, use the initial values provided by the HAL as the current // master mute and volume settings. AudioHwDevice::Flags flags = static_cast<AudioHwDevice::Flags>(0); { // scope for auto-lock pattern AutoMutex lock(mHardwareLock); if (0 == mAudioHwDevs.size()) { mHardwareStatus = AUDIO_HW_GET_MASTER_VOLUME; if (NULL != dev->get_master_volume) { float mv; if (OK == dev->get_master_volume(dev, &mv)) { mMasterVolume = mv; } } mHardwareStatus = AUDIO_HW_GET_MASTER_MUTE; if (NULL != dev->get_master_mute) { bool mm; if (OK == dev->get_master_mute(dev, &mm)) { mMasterMute = mm; } } } mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME; if ((NULL != dev->set_master_volume) && (OK == dev->set_master_volume(dev, mMasterVolume))) { flags = static_cast<AudioHwDevice::Flags>(flags | AudioHwDevice::AHWD_CAN_SET_MASTER_VOLUME); } mHardwareStatus = AUDIO_HW_SET_MASTER_MUTE; if ((NULL != dev->set_master_mute) && (OK == dev->set_master_mute(dev, mMasterMute))) { flags = static_cast<AudioHwDevice::Flags>(flags | AudioHwDevice::AHWD_CAN_SET_MASTER_MUTE); } mHardwareStatus = AUDIO_HW_IDLE; } //4.添加到mAudioHwDevs集合中;以唯一的键作为索引 audio_module_handle_t handle = (audio_module_handle_t) nextUniqueId(AUDIO_UNIQUE_ID_USE_MODULE); mAudioHwDevs.add(handle, new AudioHwDevice(handle, name, dev, flags)); ALOGI("loadHwModule() Loaded %s audio interface from %s (%s) handle %d", name, dev->common.module->name, dev->common.module->id, handle); return handle; }
AudioHwDevice封装了Audio Interface的一些信息:
class AudioStreamOut; class AudioHwDevice { public: enum Flags { AHWD_CAN_SET_MASTER_VOLUME = 0x1, AHWD_CAN_SET_MASTER_MUTE = 0x2, }; AudioHwDevice(audio_module_handle_t handle, const char *moduleName, audio_hw_device_t *hwDevice, Flags flags) : mHandle(handle) , mModuleName(strdup(moduleName)) , mHwDevice(hwDevice) , mFlags(flags) { } virtual ~AudioHwDevice() { free((void *)mModuleName); } bool canSetMasterVolume() const { return (0 != (mFlags & AHWD_CAN_SET_MASTER_VOLUME)); } bool canSetMasterMute() const { return (0 != (mFlags & AHWD_CAN_SET_MASTER_MUTE)); } audio_module_handle_t handle() const { return mHandle; } const char *moduleName() const { return mModuleName; } audio_hw_device_t *hwDevice() const { return mHwDevice; } uint32_t version() const { return mHwDevice->common.version; } /** This method creates and opens the audio hardware output stream. * The "address" parameter qualifies the "devices" audio device type if needed. * The format format depends on the device type: * - Bluetooth devices use the MAC address of the device in the form "00:11:22:AA:BB:CC" * - USB devices use the ALSA card and device numbers in the form "card=X;device=Y" * - Other devices may use a number or any other string. */ status_t openOutputStream( AudioStreamOut **ppStreamOut, audio_io_handle_t handle, audio_devices_t devices, audio_output_flags_t flags, struct audio_config *config, const char *address); private: const audio_module_handle_t mHandle; const char * const mModuleName; audio_hw_device_t * const mHwDevice; const Flags mFlags; };
其中的openOutputSream()函数可以在当前的音频设备上打开一个输出流,用以播放音频。mAudioHwDevs是一个集合,它以一个唯一值为键,保存当前的AudioHwDevice实例。这样我们在后面的处理中也可以查询到某个AudioHwDevice对象。
在加载完了各个Interface后,我们会调用openOutput()/openInput()函数分别为它们打开一个输入输出流。调用的过程与之前类似,最后的处理都在AudioFlinger中。
status_t AudioFlinger::openOutput(audio_module_handle_t module, audio_io_handle_t *output, audio_config_t *config, audio_devices_t *devices, const String8& address, uint32_t *latencyMs, audio_output_flags_t flags) { ALOGI("openOutput(), module %d Device %x, SamplingRate %d, Format %#08x, Channels %x, flags %x", module, (devices != NULL) ? *devices : 0, config->sample_rate, config->format, config->channel_mask, flags); if (*devices == AUDIO_DEVICE_NONE) { return BAD_VALUE; } Mutex::Autolock _l(mLock); sp<PlaybackThread> thread = openOutput_l(module, output, config, *devices, address, flags); if (thread != 0) { *latencyMs = thread->latency(); // notify client processes of the new output creation thread->ioConfigChanged(AUDIO_OUTPUT_OPENED); // the first primary output opened designates the primary hw device if ((mPrimaryHardwareDev == NULL) && (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) { ALOGI("Using module %d has the primary audio interface", module); mPrimaryHardwareDev = thread->getOutput()->audioHwDev; AutoMutex lock(mHardwareLock); mHardwareStatus = AUDIO_HW_SET_MODE; mPrimaryHardwareDev->hwDevice()->set_mode(mPrimaryHardwareDev->hwDevice(), mMode); mHardwareStatus = AUDIO_HW_IDLE; } return NO_ERROR; } return NO_INIT; }
//查找相应的audio interface设备 AudioHwDevice* AudioFlinger::findSuitableHwDev_l( audio_module_handle_t module, audio_devices_t devices) { // if module is 0, the request comes from an old policy manager and we should load // well known modules if (module == 0) {//此时需要加载所有的audio interface设备 ALOGW("findSuitableHwDev_l() loading well know audio hw modules"); for (size_t i = 0; i < ARRAY_SIZE(audio_interfaces); i++) { loadHwModule_l(audio_interfaces[i]); } // then try to find a module supporting the requested device. for (size_t i = 0; i < mAudioHwDevs.size(); i++) { AudioHwDevice *audioHwDevice = mAudioHwDevs.valueAt(i); audio_hw_device_t *dev = audioHwDevice->hwDevice(); if ((dev->get_supported_devices != NULL) && (dev->get_supported_devices(dev) & devices) == devices) return audioHwDevice; } } else {//否则,表面我们指定了需要的设备id号;从现有的mAudioHwDevs集合中查找对应的音频接口设备 // check a match for the requested module handle AudioHwDevice *audioHwDevice = mAudioHwDevs.valueFor(module); if (audioHwDevice != NULL) { return audioHwDevice; } } return NULL; } sp<AudioFlinger::PlaybackThread> AudioFlinger::openOutput_l(audio_module_handle_t module, audio_io_handle_t *output, audio_config_t *config, audio_devices_t devices, const String8& address, audio_output_flags_t flags) { AudioHwDevice *outHwDev = findSuitableHwDev_l(module, devices);//查找相应的audio interface设备 if (outHwDev == NULL) { return 0; } if (*output == AUDIO_IO_HANDLE_NONE) { *output = nextUniqueId(AUDIO_UNIQUE_ID_USE_OUTPUT); } else { // Audio Policy does not currently request a specific output handle. // If this is ever needed, see openInput_l() for example code. ALOGE("openOutput_l requested output handle %d is not AUDIO_IO_HANDLE_NONE", *output); return 0; } mHardwareStatus = AUDIO_HW_OUTPUT_OPEN; // FOR TESTING ONLY: // This if statement allows overriding the audio policy settings // and forcing a specific format or channel mask to the HAL/Sink device for testing. if (!(flags & (AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD | AUDIO_OUTPUT_FLAG_DIRECT))) { // Check only for Normal Mixing mode if (kEnableExtendedPrecision) { // Specify format (uncomment one below to choose) //config->format = AUDIO_FORMAT_PCM_FLOAT; //config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED; //config->format = AUDIO_FORMAT_PCM_32_BIT; //config->format = AUDIO_FORMAT_PCM_8_24_BIT; // ALOGV("openOutput_l() upgrading format to %#08x", config->format); } if (kEnableExtendedChannels) { // Specify channel mask (uncomment one below to choose) //config->channel_mask = audio_channel_out_mask_from_count(4); // for USB 4ch //config->channel_mask = audio_channel_mask_from_representation_and_bits( // AUDIO_CHANNEL_REPRESENTATION_INDEX, (1 << 4) - 1); // another 4ch example } } AudioStreamOut *outputStream = NULL; //输出流对象类型 status_t status = outHwDev->openOutputStream( &outputStream, *output, devices, flags, config, address.string());//为该audio interface device打开一个输出流,即打开一个输出通道 mHardwareStatus = AUDIO_HW_IDLE; if (status == NO_ERROR) {//根据传入的flags,创建合适的PlaybackThread线程 PlaybackThread *thread; if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) { thread = new OffloadThread(this, outputStream, *output, devices, mSystemReady); ALOGV("openOutput_l() created offload output: ID %d thread %p", *output, thread); } else if ((flags & AUDIO_OUTPUT_FLAG_DIRECT) || !isValidPcmSinkFormat(config->format) || !isValidPcmSinkChannelMask(config->channel_mask)) { thread = new DirectOutputThread(this, outputStream, *output, devices, mSystemReady); ALOGV("openOutput_l() created direct output: ID %d thread %p", *output, thread); } else { thread = new MixerThread(this, outputStream, *output, devices, mSystemReady); ALOGV("openOutput_l() created mixer output: ID %d thread %p", *output, thread); } mPlaybackThreads.add(*output, thread);//将创建的播放线程添加到mPlaybackThreads键值集合中,供后续查找; return thread; } return 0; }
其中,我们会调用AudioHwDevice的openOutputStream()在此Interface上打开一个输出流,并根据传入的参数创建合适的PlaybackThread工作线程;这些线程用于真正的处理音频数据。最后,我们创建的线程也会被保存到mPlaybackThreads中,它也是一个集合对象。
opentInput()的流程与openOutput()类似,这里就不再赘述。
最后,在AudioPolicyManager的构造函数中会更新一些信息,AudioPolicyManager的创建也就结束了。
AudioPolicyManager对象的创建过程结束后,我们都得到了什么呢?
- 首先我们解析了audio_policy.conf文件,并解析了其中Audio Interface的信息;所有的信息都被保存到了AudioPolicyManager::mHwModules集合中。
- 接着,我们为每个Audio Interface加载了所需的库,同时这些Interface的对象也被保存到了mAudioHwDevs中;在其基础上创建了输出流和工作线程(用来放音);线程的部分,信息会保存到mPlaybackThreads集合中。
- 类似地,最后我们为每个Audio Interface创建了输入流和录音线程(用来录音);线程的部分,信息会保存到mRecordThreads集合中。
这里没有太详细地解释某些内容;一些文字描述,可以参照代码中的注释。
在AudioPolicyService初始化完成后,我们整个Audio系统就可以准备工作了。因为我们已经知道了各个Audio Interface的信息,并已经为它们加载了需要的组件,同时也创建了工作线程;接下来就是等待音频数据处理了。
至此,Audio Native服务的启动过程分析就结束了。