




已阅读5页,还剩31页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
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的启动处理:cpp view plain copy 在CODE上查看代码片派生到我的代码片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(argv0, media.log); sp 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 buffer32; 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 sm = defaultServiceManager(); sp binder = sm-getService(String16(media.log); if (binder != 0) Vector 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, dont kill my parent sp proc(ProcessState:self(); sp 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的继承关系声明如下:cpp view plain copy 在CODE上查看代码片派生到我的代码片class AudioFlinger : public BinderService, public BnAudioFlinger AudioFlinger是一个Binder服务的服务端实现,整个AudioFlinger的Binder服务结构如图所示:继承BnAudioFlinger说明它确实是IAudioFlinger的服务端;而BinderService更像是一个模板工具类,它封装了Binder服务发布、启动的一些方法:cpp view plain copy 在CODE上查看代码片派生到我的代码片template class BinderService public: static status_t publish(bool allowIsolated = false) sp 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 ps(ProcessState:self(); ps-startThreadPool(); ps-giveThreadPoolName(); IPCThreadState:self()-joinThreadPool(); ; BinderService:instantiate()内部会创建AudioFlinger服务实例,并通过ServiceManager将其发布到系统中;其中,AudioFlinger服务注册的名称是“media.audio_flinger”。我们看看IAudioFlinger和AudioFlinger的定义。首先是IAudioFlinger:cpp view plain copy 在CODE上查看代码片派生到我的代码片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 createTrack() = 0;/AudioTrack使用时会涉及到 virtual sp openRecord() = 0; / FIXME Surprisingly, format/latency dont 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中的接口;我们这里只看一些它添加的主要函数定义:cpp view plain copy 在CODE上查看代码片派生到我的代码片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 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 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 thread); void closeInputFinish(sp thread); / no range check, AudioFlinger:mLock held bool streamMute_l(audio_stream_type_t stream) const return mStreamTypesstream.mute; / no range check, doesnt check per-thread stream volume, AudioFlinger:mLock held float streamVolume_l(audio_stream_type_t stream) const return mStreamTypesstream.volume; void ioConfigChanged(audio_io_config_event event, const sp& 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 getEffectThread_l(audio_session_t sessionId, int EffectId); AudioFlinger中定义了许多跟PlaybackThread有关的函数。PlaybackThread是回放线程,定义在Thread.h中;它是AudioFlinger中真正处理音频数据的结构,担任一个任劳任怨的工人角色;PlaybackThread家族还有许多其他的线程子类,它们都对应着一个不同的音频数据处理场景。PlaybackThread相关的内容,后续分析到真正的音频数据处理时在介绍。AudioFlinger中定义了几个内部类:cpp view plain copy 在CODE上查看代码片派生到我的代码片/ server side of the clients IAudioTrack class TrackHandle : public android:BnAudioTrack /使用AudioTrack时会涉及 public: TrackHandle(const sp& track); virtual TrackHandle(); virtual sp 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 mTrack; ; / server side of the clients IAudioRecord class RecordHandle : public android:BnAudioRecord /使用AudioRecord时,会涉及 public: RecordHandle(const sp& 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 mRecordTrack; / for use from destructor void stop_nonvirtual(); ; TrackHandler在分析AudioTrack的时候会介绍;RecordHandler也是如此。另外,AudioFlinger中还有几个重要的集合对象:cpp view plain copy 在CODE上查看代码片派生到我的代码片/保存Audio Interface的一些信息 DefaultKeyedVector mAudioHwDevs; /保存创建的PlaybackThread工作线程 DefaultKeyedVector audio_io_handle_t, sp mPlaybackThreads; /保存创建的RecordThread录音工作线程 DefaultKeyedVector audio_io_handle_t, sp mRecordThreads 这几个集合对象在后续的分析中都会遇到有了对AudioFlinger定义的认识,我们再看它的构造函数。注册AudioFlinger服务时,会创建一个它的实例;此时会调用其构造函数:cpp view plain copy 在CODE上查看代码片派生到我的代码片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 mNextUniqueIdsuse = 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 valuePROPERTY_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()实现是:cpp view plain copy 在CODE上查看代码片派生到我的代码片void AudioFlinger:onFirstRef() Mutex:Autolock _l(mLock); /* TODO: move all this work into an Init() function */ char val_strPROPERTY_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 = kDefaultStandb
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 疾病发病率统计表(按地区)
- 环境化学知识点测验
- 初一写景的作文500字(10篇)
- 英语听说读写技能在商务场合的应用试题
- 医养结合养老院(养老中心)项目可行性研究报告
- 领导力培训-打造高效团队与领导者
- 音乐节庆活动在文化交流与形象传播中的价值研究
- 项目制管理中时间管理的实战经验分享
- 顾客体验优化与消费者忠诚度提升策略
- 非遗传承在文化旅游产品设计中的应用实践
- 2024年陕西水务发展集团招聘笔试真题
- 《造血干细胞移植护理》课件
- 中医经络穴位与按摩疗法展示
- 《玫瑰精油提取工艺设计及生产计算》7000字(论文)
- 2025年非法集资课件:制作与投资者教育新思路
- 高职学前教育专业现代学徒制人才培养实践研究
- 新外研社高中英语选择性必修一单词表
- 《多发性硬化症》课件
- 个人房车租赁合同范例
- 干扰电治疗仪作用
- 《人工智能发展史》课件
评论
0/150
提交评论