技术领域
[0001]
本发明涉及一种Android系统双屏异显的两路音频实现方法。
背景技术
[0002]
关于Android系统的双屏异显两路音频的实现目前还没有通用的方法,Android系
统的双屏异显两路音频的需求是:主屏的声音从主屏对应的声卡输出、副屏的声音从副屏
对应声卡输出,不能有混音。
[0003]
如图1所示,现有的Android系统音频整个框架包括应用层APP、framework层、lib
层、hal层、驱动以及硬件。
[0004]
应用层APP,这是整个音频体系的最上层,因而并不是Android系统实现异显两路
音频输出的重点。比如厂商根据特定需求自己写的一个音乐播放器,游戏中使用到声音,或
者调节音频的一类软件等等。
[0005]
Framework层,Android提供了两个功能类,AudioTrack和AudioRecorder;除此以
外,A nd r o id系统还为我们控制音频系统提供了 A ud i o Ma na g e r、A ud i o Se r v i c e及
AudioSystem类。这些都是framework为便利上层应用开发所设计的。
[0006]
Libraries层,framework层的很多类,实际上只是应用程序使用Android库文件的
中介 而已。因为上层应用采用java语言编写,它们需要最直接的java接口的支持,这就是
framework层存在的意义之一。而作为 中介 ,它们并不会真正去实现具体的功能,或者只
实现其中的一部分功能 ,而把主要重心放在库中来完成。比如上面的 A ud i o T ra c k、
AudioRecorder等等在库中都能找到相对应的类,这些库多数是C++语言编写的。除了上面
的类库实现外,音频系统还需要一个 核心中控 ,或者用Android中通用的实现来讲,需要
一个系统服务,这就是AudioFlinger和AudioPolicyService。
[0007]
HAL层,从设计上来看,硬件抽象层是AudioFlinger直接访问的对象。这说明了两
个问题,一方面AudioFlinger并不直接调用底层的驱动程序;另一方面,AudioFlinger上层
(包括和它同一层的MediaPlayerService)的模块只需要与它进行交互就可以实现音频相
关的功能了。因而我们可以认为AudioFlinger是Android音频系统中真正的 隔离板 ,无论
下面如何变化,上层的实现都可以保持兼容。音频方面的硬件抽象层主要分为两部分,即
AudioFlinger和AudioPolicyService。实际上后者并不是一个真实的设备,只是采用虚拟
设备的方式来让厂商可以方便地定制出自己的策略。抽象层的任务是将AudioFlinger/
AudioPolicyService真正地与硬件设备关联起来,但又必须提供灵活的结构来应对变
化——特别是对于Android这个更新相当频繁的系统。比如以前Android系统中的Audio系
统依赖于alsa - lib,但后期就变为了tinyalsa,这样的转变不应该对上层造成破坏。因而
AudioHAL提供了统一的接口来定义它与AudioFlinger/AudioPolicyService之间的通信方
式,这就是audio_hw_device、audio_stream_in及audio_stream_out等等存在的目的,这些
S t r u c t数据类型内部大多只是函数指针的定义 ,是一些 。当 A u d i o F l i n g e r /
AudioPolicyService初始化时,它们会去寻找系统中最匹配的实现(这些实现驻留在以
说 明 书
1/9 页
4
CN 108132771 A
4 audio .primary .* ,audio .a2dp .*为名的各种库中)来填充这些 。根据产品的不同,音频
设备存在很大差异,在Android的音频架构中,这些问题都是由HAL层的audio .primary等等
库来解决的,而不需要大规模地修改上层实现。换句话说,厂商在定制时的重点就是如何提
供这部分库的高效实现了。
[0008]
本发明是基于Android系统的双屏异显两路音频的需求以及现有的Android系统
音频整个框架,来实现两路音频输出的。
发明内容
[0009]
本发明要解决的技术问题,在于提供一种Android系统双屏异显的两路音频实现
方法,从而弥补了Android系统的双屏异显两路音频输出的空白。
[0010]
本发明是这样实现的:一种Android系统双屏异显的两路音频实现方法,包括进入
双屏模式过程、播放音频过程和退出双屏模式过程;
[0011]
所述进入双屏模式过程包括:
[0012]
步骤S11、响应用户操作而进入双屏模式,首先模拟上报声卡插入事件;
[0013]
步骤S12、在AudioManager打开第二个声卡;
[0014]
步骤S13、在AudioFlinger创建新的PlaybackThread;
[0015]
所述播放音频过程包括;
[0016]
步骤S21、App要播放声音前先判断是否是主屏播放声音,若是进入步骤S22,若否,
进入步骤S23;
[0017]
步骤S22、设置主屏声音的streamType,根据streamType在第一个声卡播放声音;
[0018]
步骤S23、设置副屏声音的streamType,根据streamType在第二个声卡播放声音;
[0019]
所述退出双屏模式过程包括:
[0020]
步骤S31、响应用户操作而退出双屏模式,首先模拟上报声卡断开事件;
[0021]
步骤S32、在AudioManager关闭第二个声卡;
[0022]
步骤S33、在AudioFlinger销毁第二个PlaybackThread,结束。
[0023]
进 一 步 的 ,所 述 步 骤 S 1 2 实 现 之 前 需 是 在 P h o n e W i n d o w . j a v a 的
superDispatchKeyEvent里面预先添加force_speaker广播,并设置media .audio .device_
policy .db的属性,异显状态下设置该属性为 speaker ,同显状态设置该属性为 hdmi ,然
后在InputManagerService .java的start里面接收广播,收到广播后,触发耳机线控事件。
[0024]
进一步的,所述步骤S12具体是:系统声音默认从hdmi输出,当switchValues为0
时,mHeadState的状态设置成BIT_HDMI_AUDIO;当switchValues的值为1时,mHeadState的
状态设置包括BIT_HDMI_AUDIO和BIT_USB_HEADSET_DGTL,目的是同时打开hdmi和speaker
两路输出,这种情况会触发AudFlinger中的openDuplicateOutput创建两个MixerThread,
从而打开第二个声卡。
[0025]
进一步的 ,所述步骤 S 21中 ,所述 A p p判断是否是主屏播放声音是通过判断
media .audio .device_policy .db的属性来实现,若该属性为 speaker ,则判断为异显状
态,若该属性为 hdmi ,则判断为同显状态。
[0026]
进一步的,本发明方法还包括主副屏切换过程,所述主副屏切换过程是:
[0027]
系统默认从hdmi输出,同屏时声音也从hdmi输出;异显时,副屏的声音从speaker
说 明 书
2/9 页
5
CN 108132771 A
5 输 出 ,主 屏的 声 音 从 h d m i 输 出 ;首 先 获 取 副 屏 上 a c t i v i t y 的 p i d ,并 设 置 为
media .audio .activity .pid 属性的值,同屏时,属性值设置为 - 1
[0028]
在moveTransitionToSecondDisplay中添加
[0029]
SystemProperties .set ("media .audio .activity .pid" ,String .valueOf
(win .mSession .mPid));
[0030]
在updateDisplayShowSynchronization中添加
[0031]
SystemProperties .set("media .audio .activity .pid" ,String .valueOf( - 1));
[0032]
在audiopolicy的Engine .cpp的getDeviceForStrategyInt中添加
[0033]
返回AUDIO_DEVICE_OUT_WIRED_HEADSET表示声音最终从speaker输出;
[0034]
返回AUDIO_DEVICE_OUT_AUX_DIGITAL表示声音最终从hdmi输出。
[0035]
进一步的,本发明方法还包括输出设备的修改过程:
[0036]
修改的文件路径:/device/rockchip/common/audio_policy_rk30board .conf
[0037]
修改的内容包括:
[0038]
(1)更改全局配置里的输出设备,由AUDIO_DEVICE_OUT_SPEAKER改为AUDIO_
DEVICE_OUT_AUX_DIGITAL;
[0039]
(2)更改primary默认输出设备;
[0040]
(3)添加dgtl输出。
[0041]
进一步的,本发明方法还包括增加dgtl库:
[0042]
复制hardware/rockchip/audio/tinyalsa_hal到hardware/rockchip/audio/
tinyalsa_hal_dgtl,并修改Android .mk;
[0043]
将audio_hw .c中connect_hdmi的值改为false,屏蔽hdmi;
[0044]
编译生成audio .dgtl .rk30board .so;
[0045]
最终,如果输出要求是hdmi,AudioFlinger会调用audio .dgtl .primary .so;如果
输出要求是speaker,AudioFlinger会调用audio .dgtl .rk30board .so。
[0046]
本发明具有如下优点:本发明方法通过软件和硬件上的设置,使主屏的声音从主
屏对应的声卡输出、副屏的声音从副屏对应声卡输出,最终实现了Android系统双屏异显的
两路音频输出,填补了这一技术领域的空白。
附图说明
[0047]
下面参照附图结合实施例对本发明作进一步的说明。
[0048]
图1为现有的Android系统的音频框架示意图。
[0049]
图2为本发明方法执行流程图。
具体实施方式
[0050]
请参阅图2所示,本发明的Android系统双屏异显的两路音频实现方法,包括进入
双屏模式过程、播放音频过程和退出双屏模式过程;
[0051]
所述进入双屏模式过程包括:
[0052]
步骤S11、响应用户操作而进入双屏模式,首先模拟上报声卡插入事件;
[0053]
步骤S12、在AudioManager打开第二个声卡;
说 明 书
3/9 页
6
CN 108132771 A
6 [0054]
步骤S13、在AudioFlinger创建新的PlaybackThread;
[0055]
所述播放音频过程包括;
[0056]
步骤S21、App要播放声音前先判断是否是主屏播放声音,若是进入步骤S22,若否,
进入步骤S23;
[0057]
步骤S22、设置主屏声音的streamType,根据streamType在第一个声卡播放声音;
[0058]
步骤S23、设置副屏声音的streamType,根据streamType在第二个声卡播放声音;
[0059]
所述退出双屏模式过程包括:
[0060]
步骤S31、响应用户操作而退出双屏模式,首先模拟上报声卡断开事件;
[0061]
步骤S32、在AudioManager关闭第二个声卡;
[0062]
步骤S33、在AudioFlinger销毁第二个PlaybackThread,结束。
[0063]
所述步骤S12实现之前需是在PhoneWindow .java的superDispatchKeyEvent里面
预先添加force_speaker广播,并设置media .audio .device_policy .db的属性,异显状态下
设置该属性为 speaker ,同显状态设置该属性为 hdmi ,App即可通过该属性来判断是否
是主屏播放声音,添加和设置的具体代码实现过程如下:
[0064]
[0065]
然后在InputManagerService .java的start里面接收广播,收到广播后,触发耳机
说 明 书
4/9 页
7
CN 108132771 A
7 线控事件。具体代码的实现过程是:
[0066]
[0067]
[0068]
所述步骤 S1 2具体是:系统声音默认从 hd m i输出,当 s w i t c h Va l ue s为 0时 ,
mHeadState的状态设置成BIT_HDMI_AUDIO;当switchValues的值为1时,mHeadState的状态
说 明 书
5/9 页
8
CN 108132771 A
8 设置包括BIT_HDMI_AUDIO和BIT_USB_HEADSET_DGTL,目的是同时打开hdmi和speaker两路
输出,这种情况会触发AudioFlinger中的openDuplicateOutput创建两个MixerThread,从
而打开第二个声卡,输出是hdmi还是speaker通过AudioPolicy来进行控制。具体是:
[0069]
MixerThread*thread1=checkMixerThread_l(output1);
[0070]
MixerThread*thread2=checkMixerThread_l(output2);
[0071]
所 述 步 骤 S 2 1 中 ,所 述 A p p 判 断 是 否 是 主 屏 播 放 声 音 是 通 过 判 断
media .audio .device_policy .db的属性来实现,若该属性为 speaker ,则判断为异显状
态,若该属性为 hdmi ,则判断为同显状态。
[0072]
本发明方法还包括主副屏切换过程,所述主副屏切换过程是:
[0073]
系统默认从hdmi输出,同屏时声音也从hdmi输出;异显时,副屏的声音从speaker
输 出 ,主 屏的 声 音 从 h d m i 输 出 ;首 先 获 取 副 屏 上 a c t i v i t y 的 p i d ,并 设 置 为
media .audio .activity .pid 属性的值,同屏时,属性值设置为 - 1。其代码实现过程是:
[0074]
在moveTransitionToSecondDisplay中添加
[0075]
SystemProperties .set ("media .audio .activity .pid" ,String .valueOf
(win .mSession .mPid));
[0076]
在updateDisplayShowSynchronization中添加
[0077]
SystemProperties .set("media .audio .activity .pid" ,String .valueOf( - 1));
[0078]
接着在audiopolicy的Engine .cpp的getDeviceForStrategyInt中获取并解析
m e d i a .a u d i o .d e v i c e _ p o l i c y .d b的属性 ,即在
a u d i o p o l i c y的 E n g i n e .c p p的
getDeviceForStrategyInt中添加:
[0079]
说 明 书
6/9 页
9
CN 108132771 A
9 [0080]
[0081]
如果该属性里面的值是speaker,则返回AUDIO_DEVICE_OUT_WIRED_HEADSET,表示
声音最终从speaker输出;
[0082]
如果该属性里面的值是hdmi,则返回AUDIO_DEVICE_OUT_AUX_DIGITAL,表示声音
最终从hdmi输出。
[0083]
本发明方法还包括输出设备的修改过程:
[0084]
由于原来系统只有一个输出,要满足两路输出,因此需添加一个输出。
[0085]
修改的文件路径:/device/rockchip/common/audio_policy_rk30board .conf
[0086]
修改的内容包括:
[0087]
(1)更改全局配置里的输出设备,由AUDIO_DEVICE_OUT_SPEAKER改为AUDIO_
DEVICE_OUT_AUX_DIGITAL,代码实现过程是:
[0088]
[0089]
(2)更改primary默认输出设备,代码实现过程是:
[0090]
说 明 书
7/9 页
10
CN 108132771 A
10 [0091]
[0092]
(3)添加dgtl输出,即添加一个虚拟输出,代码实现过程是。
[0093]
[0094]
本发明方法还包括增加dgtl库,这个库是硬件抽象层的修改,为了给第二个音频
输出设备使用,实现两路音频设备同时输出声音,互不冲突,代码实现过程是:
[0095]
复制hardware/rockchip/audio/tinyalsa_hal到hardware/rockchip/audio/
tinyalsa_hal_dgtl,并修改Android .mk;具体如下:
[0096]
LOCAL_MODULE:=audio .dgtl .$(TARGET_BOARD_HARDWARE)
[0097]
将audio_hw .c中connect_hdmi的值改为false,屏蔽hdmi;
[0098]
connet_hdmi=false;
说 明 书
8/9 页
11
CN 108132771 A
11 [0099]
编译生成audio .dgtl .rk30board .so;
[0100]
最终,如果输出要求是hdmi,AudioFlinger会调用audio .dgtl .primary .so;如果
输出要求是speaker,AudioFlinger会调用audio .dgtl .rk30board .so。
[0101]
最后打上补丁,这些补丁即前面说明的代码实现过程,最后弄了一个整体完整的
补丁包:
[0102]
在framework/base/下打上补丁Dual_Audio_framework_base .patch;
[0103]
在framework/av/下打上补丁Dual_audio_framework_av .patch;
[0104]
在 h a r d w a r e / l i b h a r d w a r e / 下 打 上 补 丁 D u a l _ a u d i o _ h a r d w a r e _
libhardware .patch。
[0105]
虽然以上描述了本发明的具体实施方式,但是熟悉本技术领域的技术人员应当理
解,我们所描述的具体的实施例只是说明性的,而不是用于对本发明的范围的限定,熟悉本
领域的技术人员在依照本发明的精神所作的等效的修饰以及变化,都应当涵盖在本发明的
权利要求所保护的范围内。
07-21 09:32