第十八篇 ANDROID的声音管理系统及服务



         声音管理系统用来实现声音的输入和输出、声音的控制和路由等功能,包括主和各种音源的音量调节、声音焦点控制,声音外设的检测和状态管理,声音源输入和输出的策略管理、音效的播放、音轨设置和播放、录音设置和启动等功能。

整个声音管理系统相关类图如下:主要由JAVA端的系统服务AudioService及两个本地服务声音输入输出策略管理服务AudioPolicyService及声音输出投射服务AudioFlinger来实现相关功能。

应用主要通过AudioManage接口来使用AudioService提供的服务。系统服务AudioService与两个本地服务之间通过AudioSystem类提供的接口借助JNI进行交互。

     系统服务AudioService使用蓝牙监听对象BluetoothProfile.ServiceListener来监听蓝牙框架服务HeadsetProfileHeadsetProfile的连接,并获得两个蓝牙框架服务的客户端对象BluetoothHeadsetBluetoothA2dp来与对应的蓝牙框架服务实现交互。使用一个AudioServiceBroadcastReceiver广播接收对象来监听基座状态事件、蓝牙连接状态改变事件、外设插拔事件、声音状态改变事件、屏幕打开关闭事件、配置改变事件、用户切换事件等事件并进行相应处理。

           当检测到需要切换声音路由时,由相关应用通过AudioManage接口调用AudioService系统服务提供的setWiredDeviceConnectionState、setBluetoothA2dpDeviceConnectionState()接口来发起或AudioService系统服务本身检测到相关的事件来触发媒体路由切换,并通过IAudioRoutesObserver接口调用dispatchAudioRoutesChanged()函数来通知媒体路由切换相关进程和服务进行相应处理。

          

    

         声音焦点控制主要有AudioService系统服务提供的MediaFocusControl对象进行控制。声音焦点控制实现同时只有一个应用能够获得焦点播放同种类型的声音,ANDROID提供和支持STREAM_VOICE_CALL(电话呼叫)、STREAM_SYSTEM(系统)、STREAM_RING(振铃和消息提示)、STREAM_MUSIC(音乐媒体播放)、STREAM_ALARM(警报声)、STREAM_NOTIFICATION(通知音)、STREAM_BLUETOOTH_SCO(蓝牙电话)、STREAM_SYSTEM_ENFORCED(强制系统声音)、STREAM_DTMFDTMF拨号音)及STREAM_TTS(文本识别音)九种声音流类型,每种类型可以独立的调节声音大小,其中除了STREAM_MUSIC类型是应用播放媒体使用的类型外其它都是系统要处理的声音类型。MediaFocusControl对象的相关类图如下:

      

       本地服务AudioPolicyService提供不同声音流类型对应的输入输出设备的策略获取及策略的选择和控制(输入输出选择、输入输出设备的打开和停止、关闭等)、设置和获取声音设备的连接状态以及不同流类型对应的设备的音量的设置和获取、音频参数的设置、音效设置等功能。类图如下

        

          AudioPolicyService有一个内部线程类AudioCommandThread,顾名思义,所有的命令(音量控制,输入、输出的切换等)最终都会在该线程中排队执行;

         AudioPolicyService实例化时调用audio_policy_dev_open函数打开一个声音策略设备,并通过声音策略设备的create_audio_policy接口返回一个audio_policy策略函数结构体指针,AudioPolicyService对应的函数通过这个audio_policy函数结构体指针调用声音策略设备的对应函数实现设备的策略控制,在AudioPolicyService调用create_audio_policy函数时也把AudioPolicyService内部的一个audio_policy_service_ops函数结构体传给声音策略设备对象,供声音策略设备对象内部调用。声音策略设备使用create_audio_policy函数除了为audio_policy策略函数结构体函数指针赋值以外,还实例了两个对象,一个AudioPolicyClientInterface对象,作为AudioPolicyService客户端使用,声音策略设备使用AudioPolicyClientInterface对象通过AudioPolicyService的内部接口audio_policy_service_op调用AudioPolicyService的相关函数;另外一个对象为具体的实现相关声音策略接口的AudioPolicyInterface对象,这里采用的是设计模式的策略模式,这也是AudioPolicyService称为声音策略服务的原因吧, AudioPolicyInterface接口的具体实例的创建采用了工厂方法。

        下面以AudioPolicyServicegetInput函数为例子具体说明整个调用流程。AudioPolicyServicegetInput函数实现根据函数传进来的声音输入类型、采样率、声音格式、通道掩码参数打开一个输入设备,整个流程为:

  1. AudioPolicyServicegetInput首先通过create_audio_policy获得的audio_policy函数结构体指针调用其get_input函数;

  2. get_input函数然后调用create_audio_policy内部采用工厂方法createAudioPolicyManager创建的具体AudioPolicyInterface对象的getInput函数。

  3. AudioPolicyInterface对象的getInput函数内部首先调用getDeviceForInputSource函数根据函数传进来的输入源类型获得对应的audio_devices_t设备类型,然后调用getInputProfile函数根据传进来的声音采样率、声音格式、通道掩码等参数与获得的设备支持的Input Profile比较返回一个与设备Profile匹配的IOProfile,然后根据返回的IOProfile对象构造一个AudioInputDescriptor对象添加到输入描述数组中,并调用create_audio_policy内部创建的一个具体AudioPolicyClientInterface对象的openInput函数;

  4. AudioPolicyClientInterface对象的openInput函数调用AudioPolicyService内部audio_policy_service_op函数结构体的open_input_on_module函数;

  5. audio_policy_service_op函数结构体的open_input_on_module函数指针指向AudioPolicyServiceaps_open_input_on_module函数,因此调用aps_open_input_on_moduleaps_open_input_on_module内部首先AudioSystem类的get_audio_flinger函数获得IAudioFlinger接口,然后通过IAudioFlinger接口调用AudioFlinger服务的openInput函数,打开选择的输入设备,返回AudioPolicyServicegetInput函数一个audio_io_handle_t句柄;

            AudioPolicyServicegetInput函数接着根据传进来的audioSession参数构造一个InputDesc对象,把getInput函数返回的audio_io_handle_t句柄添加到向量数组中,根据输入源类型从支持的输入源向量列表获得该输入源支持的EffectDesc数组,并对每一个EffectDesc根据EffectDescUuid、返回的audio_io_handle_t句柄及audioSession参数实例化一个AudioEffect对象,并调用AudioEffect对象的setParameter函数为每一个EffectDesc设置声音参数。每个AudioEffect对象也添加到InputDesc对象AudioEffect的数组中。完成整个流程。


                                                                                              版权所有,转载时请尊重原创显要处注明链接,谢谢!


第十七篇 --ANDROID DisplayManager 服务解析一 





      






posted on 2014-03-14 19:10  张大大123  阅读(427)  评论(0编辑  收藏  举报

导航