一种Android系统双屏异显的两路音频实现方法

技术领域
[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]
虽然以上描述了本发明的具体实施方式,但是熟悉本技术领域的技术人员应当理
解,我们所描述的具体的实施例只是说明性的,而不是用于对本发明的范围的限定,熟悉本
领域的技术人员在依照本发明的精神所作的等效的修饰以及变化,都应当涵盖在本发明的
权利要求所保护的范围内。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/48444.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Nougat - 学术文档PDF解析(LaTeX数学、表格)

文章目录 一、关于 Nougat二、安装三、获取PDF的预测1、CLI2、API 四、数据集生成数据集 五、训练六、评估七、其它1、常见问题解答2、引文3、致谢4、许可证 一、关于 Nougat Nougat (Neural Optical Understanding for Academic Documents) Nougat是理解LaTeX数学和表格的 学…

Dockerfile相关命令

Dockerfile Dockerfile 是一个用来构建Docker镜像的文本文件,包含了一系列构建镜像所需的指令和参数。 指令详解 Dockerfile 指令说明FROM指定基础镜像,用于后续的指令构建,必须为第一个命令MAINTAINER指定Dockerfile的作者/维护者。&…

CentOS软件安装与vim使用操作

目录 CentOS软件安装 软件生态的概念 CentOS软件安装 CentOS软件卸载 CentOS查看软件包 rz和sz命令 vim多模式文本编辑器 vim 的使用 命令模式 输入模式 底线命令模式 vim 按键说明 第一部分:一般模式可用的光标移动、复制粘贴、搜索替换等 光标移动 …

JUC并发编程01-基础概念

概念 进程 进程可以视为程序的一个实例,进程就是用来加载指令、管理内存、管理I0 线程 一个进程内可以有多个线程,一个线程就是一个指令流。 在Java中,线程作为最小调度单位,进程作为资源分配的最小单位,可以说进程…

Mysql数据库第二次作业

(1)显示所有职工的基本信息。 mysql> select * from t_worker; (2)查询所有职工所属部门的部门号,不显示重复的部门号。 mysql> select distinct department_id from t_worker; (3)求出所有职工的人数。 mysql> select count(1) from t_worker; (4)列…

Figma 中文版指南:获取和安装汉化插件

Figma是一种主流的在线团队合作设计工具,也是一种基于 Web 端的设计工具。在当今的设计时代,Figma 的使用满足了每个人的设计需求,不仅可以实现在线编辑,还可以方便日常管理,有效提高工作效率。然而,相信很…

分页查询与分页条件查询

--------------- 无PageHelper插件分页查询 1.创建PageBean实体类 Data NoArgsConstructor AllArgsConstructor public class PageBean<T> {private Long total;//总条数private List<T> items;//当前页数据集合 }类型安全性 泛型&#xff1a;提供了编译时的类型…

【Apache Doris】周FAQ集锦:第 15 期

【Apache Doris】周FAQ集锦&#xff1a;第 15 期 SQL问题数据操作问题运维常见问题其它问题关于社区 欢迎查阅本周的 Apache Doris 社区 FAQ 栏目&#xff01; 在这个栏目中&#xff0c;每周将筛选社区反馈的热门问题和话题&#xff0c;重点回答并进行深入探讨。旨在为广大用户…

JMeter:BeanShell到JSR223迁移中的注意事项

前言 在之前的文章JMeter&#xff1a;BeanShell向JSR223迁移过程遭遇的java标准库不可用问题-如何切换JDK版本中引用了一段使用BeanShell对入参进行加密的脚本&#xff0c;迁移到JSR223&#xff0c;虽然更换JDK后编译通过&#xff0c;看似也可以执行了&#xff0c;但是其实那段…

windows USB 设备驱动开发-开发Type C接口的驱动程序(二)

编写 USB Type C 连接器驱动程序 在以下情况下&#xff0c;需要编写 USB Type-C 连接器驱动程序&#xff1a; 如果 USB Type-C 硬件能够处理电源输送 (PD) 状态机。 否则&#xff0c;请考虑编写 USB Type C 端口控制器驱动程序&#xff1b; 如果硬件没有嵌入式控制器。 否则&…

(10)深入理解pandas的核心数据结构:DataFrame高效数据清洗技巧

目录 前言1. DataFrame数据清洗1.1 处理缺失值&#xff08;NaNs&#xff09;1.1.1 数据准备1.1.2 读取数据1.1.3 查找具有 null 值或缺失值的行和列1.1.4 计算每列缺失值的总数1.1.5 删除包含 null 值或缺失值的行1.1.6 利用 .fillna&#xff08;&#xff09; 方法用Portfolio …

Python本地安装whl文件详解与高级pip命令技巧

有些情况我们pip一下包的时候会报错&#xff0c;可能因为延时或许其他不兼容的情况&#xff0c;这时候我们可以通过去网上下载该包的原文件&#xff0c;进行本地物理pip &#xff0c;在安装网上下载的whl之前&#xff0c;先明白不同后缀的差异&#xff1b;whl下载网址&#xff…

Linux 下部署 syncthing 中继服务器

来自&#x1f96c;&#x1f436;程序员 Truraly | 田园 的博客&#xff0c;最新文章首发于&#xff1a;田园幻想乡 | 原文链接 | github &#xff08;欢迎关注&#xff09; 文章目录 安装apt 安装(Ubuntu/Debian) syncthing 配置发现服务器和中继服务器 Syncthing 是一个连续的…

解答word图标变白

把WPS卸载了之后就变成白色了&#xff0c;然后在注册表中把word的地址改成office word的地址之后图标变成这样了&#xff0c;怎么办 1.winR打开命令提示符 2.输入regedit&#xff0c;打开注册表编辑器 3.找到下面这个路径 计算机\HKEY_CLASSES_ROOT\Word.Document.8\Defaul…

【C#】已知有三个坐标点:P0、P1、P2,当满足P3和P4连成的一条直线 与 P0和P1连成一条直线平行且长度一致,该如何计算P3、P4?

问题描述 已知有三个坐标点&#xff1a;P0、P1、P2&#xff0c;当满足P3和P4连成的一条直线 与 P0和P1连成一条直线平行且长度一致&#xff0c;该如何计算P3、P4&#xff1f; 解决办法 思路一&#xff1a;斜率及点斜式方程 # 示例坐标 x0, y0 1, 1 # P0坐标 x1, y1 4, 4 # …

跟ChatGPT学习go语言--time.Sleep 方法 单位是什么

在 Go 语言中&#xff0c;time.Sleep 方法用于让当前的 Goroutine 休眠一段时间。time.Sleep 方法的参数是一个 time.Duration 类型&#xff0c;表示休眠的时间长度。time.Duration 是一个以纳秒为单位的整数类型。 使用示例 以下是一个简单的示例&#xff0c;展示如何使用 tim…

自适应键盘,自带隐藏键盘的输入框(UITextField)

引言 在iOS开发中&#xff0c;输入框占据着举足轻重的地位。与安卓不同&#xff0c;iOS输入框经常面临键盘遮挡的问题&#xff0c;或者无法方便地取消键盘。为了解决这些问题&#xff0c;有许多针对iOS键盘管理的库&#xff0c;如IQKeyboardManager、TPKeyboardAvoiding和Keyb…

一个PCIe设备可以既是主设备也是从设备吗?主设备与根节点的关系?

PCIe设备也可以既是主设备&#xff08;Master&#xff09;又是从设备&#xff08;Slave&#xff09;&#xff0c;这是因为PCIe总线的设计允许设备在不同的事务中扮演不同的角色&#xff0c;具体取决于设备的功能和总线控制器的支持。以下是几个主要的原因&#xff1a; 灵活性和…

分库分表 [ 技术 ] 指南 ✨

目录 ✨探索 技术 分库分表✨ 数据库分库分表指南 一、什么是分库分表 二、分库分表策略 三、分库分表的实现 四、分库分表的常见问题及解决方案 五、总结 相关面试题目 1. 解释什么是数据库分库分表&#xff0c;以及它的主要目的是什么&#xff1f; 2. 描述垂直分库…

STM32学习(1)--STM32介绍

STM32介绍 1.STM32简介2.ARM3.STM32F103C8T64.外设5.命名规则6.系统结构7.引脚定义8.启动配置9.最小系统电路10.新建工程步骤11.工程架构 课程知识及代码来源均来自b站 江协科技&#xff0c;下学期即将做毕设&#xff0c;需要用到STM32单片机&#xff0c;在这个假期我将持续学…