AAOS 音频焦点请求

文章目录

      • 前言
      • 基本概念
      • 提供给应用来获取音频焦点的api
      • AAOS中的音频焦点管理
      • 交互矩阵
      • duck的实现流程
      • AAOS 测试应用kitchensink焦点相关

前言

本文章的目标是首先了解Android中音频焦点的基本概念,理解代码中相关音频焦点的使用方法。其次理解AAOS 中相关交互矩阵概念,理解其实现焦点管理的流程。

基本概念

  • 音频焦点的目标是 是确保在多个应用程序同时播放音频时,用户能够顺利地听到他们想要听的声音,并防止多个应用同时混合输出声音,造成用户困扰。也就是每次要去播放某个声音的时候 先去请求焦点,请求到焦点 后才能开始播放。

  • 音频焦点是在Android API 8中引入的一个概念。它用于表示用户一次只能专注于一个音频流,比如听音乐或播客,但不能同时进行。在某些情况下,多个音频流可以同时播放,但用户只会真正聆听(专注于)其中一个,而其他音频在后台播放。例如,在导航提示播放时,同时降低音量播放音乐。当应用程序请求音频焦点时,它表示希望“拥有”音频焦点来播放音频。

提供给应用来获取音频焦点的api

android 的audioManager 提供了requestAudioFocus 的接口来获取焦点

        AudioFocusRequest mFocusRequest = new AudioFocusRequest.Builder(focusRequest).setAudioAttributes(mAttrib).setOnAudioFocusChangeListener(mFocusListener).setForceDucking(false).setWillPauseWhenDucked(false).setAcceptsDelayedFocusGain(false).build();ret = mAudioManager.requestAudioFocus(mFocusRequest);

mFocusRequest 的构造有几个参数可以传递

  1. attribute可以认为是音频播放的原因如 USAGE_MEDIA或者 USAGE_VOICE_COMMUNICATION等等建议为请求使用与音频/媒体播放相同的AudioAttributes。 如果未设置任何属性,则会使用默认属性AudioAttributes.USAGE_MEDIA。
  2. AudioFocusChangeListener延时焦点注册的回调,当延时焦点获取到的时候会回调到注册的函数中。
  3. 是否强制降低音量
  4. 当焦点被duck的时候 是否进行pause操作
  5. 是否接受获取到焦点是延时焦点

当然还支持其他不同的参数设置,这些参数设置是为了满足不同的场景来使用。比如:在用户听音频书籍或播客时,设备播放导航提示时,用户希望音频暂停而不是降低音量,因为同时听导航提示和语音内容会让人难以理解。因此,系统不会自动对播放音频书籍或博客的应用程序进行降低音量。 如果应用程序想要需要暂停而不是降低音量,可以使用Builder.setWillPauseWhenDucked(true) 设置之后 在其他应用占用了焦点后框架不会自动为应用降低音量而是回调到应用注册的函数中。

不同类型的焦点请求:

  • AudioManager.AUDIOFOCUS_GAIN:表示您的应用程序现在是用户正在听取的唯一音频源。音频播放的持续时间未知,可能非常长:在用户完成与您的应用程序的交互后,不希望其他音频流继续播放。这种焦点通常用于音乐播放、游戏或视频播放器。
  • AudioManager.AUDIOFOCUS_GAIN_TRANSIENT:用于在应用程序暂时从当前拥有者那里获取焦点,但用户期望一旦应用程序不再需要音频焦点时,播放会回到之前的状态。例如,用于播放闹钟或进行VoIP通话。播放是有限的:闹钟会超时或被取消,VoIP通话有开始和结束。当其中任何事件结束时,如果用户在开始时正在听音乐,则用户希望音乐恢复,而不希望同时听两者。
  • AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK:这种焦点请求类型与AUDIOFOCUS_GAIN_TRANSIENT相似,都是临时性的焦点请求。但其还表示在拥有焦点的同时,允许另一个应用以降低的音量(“ducked”)继续播放。例如,在播放导航提示或通知时,允许音乐继续播放,但音量不足以妨碍用户听清导航提示。典型的"ducked"应用程序的衰减率为0.2f(或-14dB),例如播放时可以使用**MediaPlayer.setVolume(0.2f)**来实现。
  • AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE:也用于临时请求,但还表示应用程序希望设备在此期间不播放任何其他内容。这通常用于音频录制或语音识别等情况,在此期间不希望系统播放通知等内容。

AAOS中的音频焦点管理

AAOS请求处理是CarService 这边处理,所谓的处理 就是根据传递进来的请求参数 和目前持有的场景来决定 是否让这个焦点请求成功。 这个具体的规则是基于交互矩阵来实现的。具体来所通过重写 AudioPolicy的相关回调 来截获原来的audioRequest,然后处理完成后设置到AudioManger 中。主要是重写下面的那些实现。

 public static abstract class AudioPolicyFocusListener {public void onAudioFocusGrant(AudioFocusInfo afi, int requestResult) {}public void onAudioFocusLoss(AudioFocusInfo afi, boolean wasNotified) {}/*** Called whenever an application requests audio focus.* Only ever called if the {@link AudioPolicy} was built with* {@link AudioPolicy.Builder#setIsAudioFocusPolicy(boolean)} set to {@code true}.* @param afi information about the focus request and the requester* @param requestResult deprecated after the addition of*     {@link AudioManager#setFocusRequestResult(AudioFocusInfo, int, AudioPolicy)}*     in Android P, always equal to {@link #AUDIOFOCUS_REQUEST_GRANTED}.*/public void onAudioFocusRequest(AudioFocusInfo afi, int requestResult) {}/*** Called whenever an application abandons audio focus.* Only ever called if the {@link AudioPolicy} was built with* {@link AudioPolicy.Builder#setIsAudioFocusPolicy(boolean)} set to {@code true}.* @param afi information about the focus request being abandoned and the original*     requester.*/public void onAudioFocusAbandon(AudioFocusInfo afi) {}}

AAOS中的音频焦点管理具体外部设置focus流程:

  1. 首先在创建外部的audioPolicy时,会设置AudioPolicyFocusListener注册外部的focus处理的handler到policy并设置IsAudioFocusPolicy 为true将外部的 audioPolicy注册到audioManger,实际是注册到audioservice,
  2. 在audioservice中管理焦点请求的类是mMediaFocusControl。在有外部注册的AudioPolicyFocusListener的情况下,所有外部通过audiomanger调用的requestfocus。都会在通过audioPolicy的notifyAudioFocusRequest来处理,这边是一个handler 发送MSG_FOCUS_REQUEST消息 然后处理消息的地方将使用外部注册的mFocusListener.onAudioFocusRequest来处理。这个地方会回调caraudioservice 注册进去的mFocusHandler来处理
  3. mFocusHandler是实现了audiopolicy的AudioPolicyFocusListener的接口主要包括focus grant\loss\request\loss几种情况。
  4. carAudioService 中requestFoces实现的流程,这个流程简单来说就是根据AAOS定义的交互矩阵和当前已经获取的焦点类型和当前请求焦点的类型 来判断 当前的这个焦点请求是可以获取还是拒绝。

交互矩阵

为了支持 AAOS 的需求,系统会根据请求的 CarAudioContext 和当前焦点持有者的 CarAudioContext 之间的预定义交互来处理音频焦点请求。交互类型分以下三种:独占、拒绝和并发。

  • 独占交互

    简单来说就是当前应用持有的焦点会被将要请求焦点的应用占有,当前应用失去焦点。

  • 拒绝交互

    简单来说当前应用持有的焦点会一直保持,其他应用无法获取当前的焦点。

  • 并发交互

    当前应用和其他应用可以同时拥有焦点,AAOS特有的。

    AAOS 最独特的地方就是并发交互。在这种交互模式下,请求音频焦点的车载应用可与其他应用同时持有焦点。若要实现并发交互,必须满足以下条件。即:

    1. 传入的焦点请求的是 AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK

    2. 当前焦点持有者未设置 setPauseWhenDucked(true)

      如果满足上述条件,焦点请求将返回 AUDIOFOCUS_REQUEST_GRANTED,而当前焦点持有者的焦点不会发生任何变化。不过,如果当前焦点持有者选择接收闪避事件或在闪避时暂停,则会失去焦点,就像独占交互一样。

下表显示了由 CarAudioService 定义的交互矩阵。行内容和列内容分别表示当前焦点持有者和传入请求的 CarAudioContext

举例:如果音乐媒体应用目前正持有音频焦点,而导航应用要请求获得焦点,那么通过该矩阵便能知道,这两个交互可以同时进行。

由于并发交互的缘故,可能会存在多个焦点持有者。在这种情况下,系统会将传入的焦点请求与当前的各个焦点持有者进行比较,然后决定应用哪种交互。此时,最保守的交互会胜出(先是拒绝交互,然后是独占交互,最后是并发交互)。

下表罗列了传入焦点请求的 CarAudioContext(列)与现有焦点持有者的上下文(行)之间的焦点交互。每个单元格表示两种上下文的预期交互类型,其中:

  • R 代表拒绝交互

  • E 代表独占交互

  • C 代表并发交互

在这里插入图片描述

duck的实现流程

duck指的是两个音频都在播放的时候,其中一个音频主动的降低音量。

  • AOSP legacy模式

    关键代码MediaFocusControl.java、FocusRequester.java

    1. 根据是不是有外部注册的focusPolicy, 使用的是框架的 还是外部的音频焦点请求策略。如果使用框架的,在音频焦点失去的时候,同时本应用的焦点类型是AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK那么就会调用frameworkHandleFocusLoss,这里面会调用mFocusController.duckPlayers进行处理. 这其中会调用addDuck其中会调用applyVolumeShaper, 对进行duck的音频设置曲线。
    2. 在audiotrack的PlaybackThread 线程中 有外部的数据写入的时候 调用mixthread的prepareTracks_l 从volumeShaper这边获取音量,这个音量是经过sharp处理的,duck的时候 就是原来的0.2倍,这个音量最后会乘上音频数据。 从而实现了音量的降低。
  • AAOS 动态路由

    1. AAOS 动态路由目前的实现是所有的焦点的获取都是由外部的CarAudioService 进行处理的。其中在焦点类型为AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK(当前请求焦点的播放需要正在播放的声音能够降低音量)需要调用audioControl hal的onDevicesToDuckChange来降低音量。
    2. 主要是onDevicesToDuckChange起作用, 在carAudioService request policy中会回调这个, 这个调用到AudioControl hal。hal 中调用 set_device_address_is_ducked 这个是属于audio_hw 也就是audio hal 中,在这里面是设置具体的哪个address为duck,设置为duck的 在后面往这边写数据的时候会乘上一个值。相当于是减小音量了。

AAOS 测试应用kitchensink焦点相关

  • 代码位置:packages\services\Car\tests\EmbeddedKitchenSinkApp\src\com\google\android\car\kitchensink\audio\AudioTestFragment.java
  • 首先进行音乐music播放,这个播放是循环的, 然后在在播放过程中可以选择Nav 导航播放 USAGE_ASSISTANCE_NAVIGATION_GUIDANCE ,或者 Vr USAGE_ASSISTANT播放这两个获取的焦点不同。
  • Nav获取的焦点是AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK,也就是music播放还是可以获取到焦点播放不会暂停,但是会降低音量。Vr获取到的是 AUDIOFOCUS_GAIN_TRANSIENT,music音乐播放会完全暂停。其暂停的操作是通过audioservice发送focuschange的消息到请求焦点的回调中。

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

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

相关文章

【Linux】Centos的一些快捷操作

Centos的一些快捷操作 一个窗口多个终端GVIM 一个窗口多个文件 一个窗口多个终端 GVIM 一个窗口多个文件

Hadoop学习指南:探索大数据时代的重要组成——Hadoop概述

前言 在当今大数据时代,处理海量数据成为了一项关键任务。Hadoop作为一种开源的分布式计算框架,为大规模数据处理和存储提供了强大的解决方案。本文将介绍Hadoop的组成和其在大数据处理中的重要作用,让我们一同踏上学习Hadoop的旅程。 Hado…

Jenkins集成SonarQube保姆级教程

Jenkins是自动化部署平台,一个粗眉大眼的糙汉子! SonarQube是代码扫描平台,一个眉目清秀的小女子! 有一天,上天交给我一个任务,去撮合撮合他们! 我抬头看了看天, 不,…

2023-07-30 LeetCode每日一题(环形链表 II)

2023-07-30每日一题 一、题目编号 142. 环形链表 II二、题目链接 点击跳转到题目位置 三、题目描述 给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。 如果链表中有某个节点,可以通过连续跟踪 n…

Centos7中实现脚本使用mysqldump实现分库分表备份

脚本 #!/bash/bin userroot #用户名 password123456 #密码 back_path/backup/db databases_file/backup/databases.list [ -f $databases_file ] || touch /backup/databases.list if [[ ! -s ${databases_file} ]] then while read line do[ -d ${back_path}/$line ] …

【Python】数据分析+数据挖掘——探索Pandas中的数据筛选

1. 前言 当涉及数据处理和分析时,Pandas是Python编程语言中最强大、灵活且广泛使用的工具之一。Pandas提供了丰富的功能和方法,使得数据的选择、筛选和处理变得简单而高效。在本博客中,我们将重点介绍Pandas中数据筛选的关键知识点&#xff…

Git的.gitignore文件、标签管理以及给命令起别名

文章目录 1. 前言2. .gitignore文件3. 标签管理4. 给命令起别名 1. 前言 本文主要讲解Git中容易被忽略但比较重要一些知识:.gitignore文件、标签管理以及给命令起别名. 2. .gitignore文件 在新建仓库时,有一个添加.gitignore 模板: .gitignore 是一个用于指定 Git 忽略特定文…

第 356 场力扣周赛题解

A 满足目标工作时长的员工数目 签到题 class Solution { public:int numberOfEmployeesWhoMetTarget(vector<int> &hours, int target) {int res 0;for (auto x: hours)if (x > target)res;return res;} };B 统计完全子数组的数目 枚举子数组&#xff1a;枚举子数…

web-暴力破解密码

Burte Force&#xff08;暴力破解&#xff09;概述 暴力破解”是一攻击具手段&#xff0c;在web攻击中&#xff0c;一般会使用这种手段对应用系统的认证信息进行获取。 其过程就是使用大量的认证信息在认证接口进行尝试登录&#xff0c;直到得到正确的结果。 为了提高效率&…

【iOS】KVOKVC原理

1 KVO 键值监听 1.1 KVO简介 KVO的全称是Key-Value Observing&#xff0c;俗称"键值监听"&#xff0c;可以用于监听摸个对象属性值得改变。 KVO一般通过以下三个步骤使用&#xff1a; // 1. 添加监听 [self.student1 addObserver:self forKeyPath:"age"…

protobuf数据类型

protobuf特殊数据类型 一&#xff0c;特殊数据类型1&#xff0c;enum使用规则注意事项 2&#xff0c;Any3&#xff0c;oneof4&#xff0c;map通讯录demo升级 二&#xff0c;默认值三&#xff0c;更新消息更新规则保留字段reserved未知字段获取未知字段 四&#xff0c;选项optio…

时频分析方法的matlab实现

傅里叶变换 function [ output_args ] example3_7( input_args ) %EXAMPLE3_7 Summary of this function goes here % Detailed explanation goes here clc; clear; fs12800;%采样频率 s1load(Sig1.txt); s2load(Sig2.txt); lslength(s1); figure(1) subplot(211) plot…

Cilium 系列-7-Cilium 的 NodePort 实现从 SNAT 改为 DSR

系列文章 Cilium 系列文章 前言 将 Kubernetes 的 CNI 从其他组件切换为 Cilium, 已经可以有效地提升网络的性能。但是通过对 Cilium 不同模式的切换/功能的启用&#xff0c;可以进一步提升 Cilium 的网络性能。具体调优项包括不限于&#xff1a; 启用本地路由 (Native Rou…

西安市未央区地方财政支出绩效管理研究_kaic

摘 要 目前传统的地方财政绩效管理研究普遍上主要集中在有关收入研究方面上&#xff0c;而对其支出的规模以及各类结构的研究较少。我国大部分地方财政政府的财政收入低下&#xff0c;财政支出效率有限&#xff0c;不能很好的为其地方经济提供较为稳定的社会支撑和经济保障。造…

SQL基础使用

SQL的概述 SQL全称&#xff1a; Structured Query Language&#xff0c;结构化查询语言&#xff0c;用于访问和处理数据库的标准的计算机语言。 SQL语言1974年由Boyce和Chamberlin提出&#xff0c;并首先在IBM公司研制的关系数据库系统SystemR上实现。 经过多年发…

PostgreSQL构建时间

– PostgreSQL构建时间 select make_timestamp(2023,7,27,7,34,16);

K8s-资源管理(二)

文章目录 2. 资源管理2.1 资源管理介绍2.2 YAML语言介绍2.3 资源管理方式2.3.1 命令式对象管理2.3.2 命令式对象配置2.3.3 声明式对象配置 2.4. 模拟使用普通用户来操作2.5 kubectl 一些基本命令2.6 使用个人的 docker 仓库的镜像 2. 资源管理 2.1 资源管理介绍 在kubernetes…

基于深度学习的高精度狗狗检测识别系统(PyTorch+Pyside6+YOLOv5模型)

摘要&#xff1a;基于深度学习的高精度狗狗检测识别系统可用于日常生活中检测与定位120类狗狗目标&#xff0c;利用深度学习算法可实现图片、视频、摄像头等方式的狗狗目标检测识别&#xff0c;另外支持结果可视化与图片或视频检测结果的导出。本系统采用YOLOv5目标检测模型训练…

web漏洞-java安全(41)

这个重点是讲关于java的代码审计&#xff0c;看这些漏洞是怎么在java代码里面产生的。 #Javaweb 代码分析-目录遍历安全问题 这个漏洞原因前面文章有&#xff0c;这次我们看看这个漏洞如何在代码中产生的&#xff0c;打开靶场 解题思路就是通过文件上传&#xff0c;上传文件…