音频流, 音频策略, 输出设备之间的关系

只针对 AudioManager.STREAM_VOICE_CALL 音频流类型进行分析

涉及到的类:

hardware/libhardware_legacy/audio/AudioPolicyManagerBase.cpp

frameworks/base/media/java/android/media/AudioManager.java

frameworks/base/media/java/android/media/AudioService.java

frameworks/base/media/java/android/media/AudioSystem.java

涉及到的方法及执行顺序:

AudioPolicyManagerBase.getStrategy(AudioSystem::stream_type stream);

AudioPolicyManagerBase.getDeviceForStrategy(routing_strategy strategy, bool fromCache);

一. 通过音频流的类型获取对应的音频策略

AudioPolicyManagerBase.cpp:

AudioPolicyManagerBase::routing_strategy AudioPolicyManagerBase::getStrategy(AudioSystem::stream_type stream) {

// stream to strategy mapping

switch (stream) {

case AudioSystem::VOICE_CALL:

case AudioSystem::BLUETOOTH_SCO:

return STRATEGY_PHONE;

...

}

}

二. 通过音频策略获取到对应的输出设备

AudioPolicyManagerBase.cpp:

audio_devices_t AudioPolicyManagerBase::getDeviceForStrategy(routing_strategy strategy, bool fromCache) {

uint32_t device = AUDIO_DEVICE_NONE;

... // 省略

switch (strategy) {

... // 省略

case STRATEGY_PHONE:

// for phone strategy, we first consider the forced use and then the available devices by order

// of priority

switch (mForceUse[AudioSystem::FOR_COMMUNICATION]) { // 判断是否有设置在通讯过程中, 强制使用某种输出设备

case AudioSystem::FORCE_BT_SCO: // 强制使用蓝牙, 作为输出设备

if (!isInCall() || strategy != STRATEGY_DTMF) {

device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT;

if (device) break;

}

device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET;

if (device) break;

device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_BLUETOOTH_SCO;

if (device) break;

// if SCO device is requested but no SCO device is available, fall back to default case

// FALL THROUGH

default: // FORCE_NONE 没有设置通讯过程中, 强制使用某种输出设备

// when not in a phone call, phone strategy should route STREAM_VOICE_CALL to A2DP

if (mHasA2dp && !isInCall() &&

(mForceUse[AudioSystem::FOR_MEDIA] != AudioSystem::FORCE_NO_BT_A2DP) &&

(getA2dpOutput() != 0) && !mA2dpSuspended) {

device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP;

if (device) break;

device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;

if (device) break;

}

device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE;

if (device) break;

device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_WIRED_HEADSET;

if (device) break;

if (mPhoneState != AudioSystem::MODE_IN_CALL) {

device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_USB_ACCESSORY;

if (device) break;

device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_USB_DEVICE;

if (device) break;

device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET;

if (device) break;

device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_AUX_DIGITAL;

if (device) break;

device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET;

if (device) break;

}

// 没有设置通讯过程中, 音频的输出设备, 则默认使用听筒作为输出设备

device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_EARPIECE;

if (device) break;

device = mDefaultOutputDevice;

if (device == AUDIO_DEVICE_NONE) {

ALOGE("getDeviceForStrategy() no device found for STRATEGY_PHONE");

}

break;

case AudioSystem::FORCE_SPEAKER: // 强制使用扬声器, 作为输出设备

// when not in a phone call, phone strategy should route STREAM_VOICE_CALL to

// A2DP speaker when forcing to speaker output

if (mHasA2dp && !isInCall() &&

(mForceUse[AudioSystem::FOR_MEDIA] != AudioSystem::FORCE_NO_BT_A2DP) &&

(getA2dpOutput() != 0) && !mA2dpSuspended) {

device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER;

if (device) break;

}

if (mPhoneState != AudioSystem::MODE_IN_CALL) {

device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_USB_ACCESSORY;

if (device) break;

device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_USB_DEVICE;

if (device) break;

device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET;

if (device) break;

device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_AUX_DIGITAL;

if (device) break;

device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET;

if (device) break;

}

device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_SPEAKER;

if (device) break;

device = mDefaultOutputDevice;

if (device == AUDIO_DEVICE_NONE) {

ALOGE("getDeviceForStrategy() no device found for STRATEGY_PHONE, FORCE_SPEAKER");

}

break;

}

break;

// 关于上面default位置的问题, 如果每个case选择(包括default)最终都有break语句, 则default的位置不影响执行顺序

// 当每个case选择(包括default)不一定有break语句时, 如果输入不满足其他选择, 最终执行default. 程序会从default处从上向下执行, 直到遇到break语句停止

// 此处的default位置并不影响执行顺序

... // 省略

}

return device;

}

三. 音频流, 音频策略, 输出设备之间的关系

音频的流类型决定音频的策略, 音频的策略决定输出设备. 但是最终的输出设备的确定, 受强制设置输出设备影响.

四. 分析AudioManager.setSpeakerphoneOn(boolean on)方法, 查看强制设置对音频输出设备选择的影响

涉及到的类及方法:

1. AudioManager.setSpeakerphoneOn(boolean on);

2. AudioService.setSpeakerphoneOn(boolean on);

3. AudioService.AudioHandler.setForceUse(int usage, int config);

4. AudioSystem.setForceUse(int usage, int config);

5. AudioPolicyManagerBase.setForceUse(AudioSystem::force_use usage, AudioSystem::forced_config config);

4.1. AudioManager.java:

public void setSpeakerphoneOn(boolean on){

IAudioService service = getService();

service.setSpeakerphoneOn(on);

}

4.2. AudioService.java:

public void setSpeakerphoneOn(boolean on){

if (on) {

if (mForcedUseForComm == AudioSystem.FORCE_BT_SCO) {

sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE,

AudioSystem.FOR_RECORD, AudioSystem.FORCE_NONE, null, 0);

}

mForcedUseForComm = AudioSystem.FORCE_SPEAKER;

} else if (mForcedUseForComm == AudioSystem.FORCE_SPEAKER){

mForcedUseForComm = AudioSystem.FORCE_NONE;

}

// 从此处可以看到 setSpeakerphoneOn(boolean on) 只针对 AudioSystem.FOR_COMMUNICATION 有效

// 而 AudioSystem.FOR_COMMUNICATION 最终影响到的是输出设备的选择

sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE,

AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, null, 0);

}

private class AudioHandler extends Handler {

@Override

public void handleMessage(Message msg) {

switch (msg.what) {

case MSG_SET_FORCE_USE:

case MSG_SET_FORCE_BT_A2DP_USE:

setForceUse(msg.arg1, msg.arg2);

break;

}

}

private void setForceUse(int usage, int config) {

AudioSystem.setForceUse(usage, config);

}

}

4.3. AudioSystem.java:

public static native int setForceUse(int usage, int config);

4.4. AudioPolicyManagerBase.cpp:

void AudioPolicyManagerBase::setForceUse(AudioSystem::force_use usage, AudioSystem::forced_config config) {

bool forceVolumeReeval = false;

switch(usage) {

case AudioSystem::FOR_COMMUNICATION:

if (config != AudioSystem::FORCE_SPEAKER && config != AudioSystem::FORCE_BT_SCO &&

config != AudioSystem::FORCE_NONE) {

ALOGW("setForceUse() invalid config %d for FOR_COMMUNICATION", config);

return;

}

forceVolumeReeval = true;

// 保存设置到数组中, 最终在 getDeviceForStrategy(routing_strategy strategy, bool fromCache) 中被调用

mForceUse[usage] = config;

break;

... // 省略

}

... // 省略

}

原文出处:https://www.cnblogs.com/firmly-believe/p/10991077.html

android 采集音频输出,Android系统分析之Audio音频流, 音频策略, 输出设备之间的关系...相关推荐

  1. 智能电视只有数字音频输出,传统音响只有模拟音频输入,巧用数字音频转模拟音频转换器,完美解决!

    智能电视已经成为了现代家庭的必备家电设备,它不仅可以播放高清视频,还可以连接网络,享受各种在线资源.但是,智能电视的音质往往不能满足我们的要求,尤其是对于喜欢听音乐或者看大片的用户来说,智能电视的内置 ...

  2. Android开启usb音频输出,Android手机开发人员选项-选择USB配置-音频源,如何使用?...

    更多帖子 此版本的专家点: 24553 GitHub绑定GitHub第三方帐户获取 鸿华2018年12月,大版移动开发专家的月度排名第一 2018年11月,大版移动开发专家的月度排名第一 2018年1 ...

  3. android 控制日志输出,Android日志工具-SLog说明

    作为一个码农,我希望有一天面朝大海,没有bug(想想,就算了),然鹅!!!现实是骨感的. 在东财有段时间了,闲暇之余,决定改造下项目中的日志库.这便是此篇文章的由来,下面 说说主角. 既然要做一个日志 ...

  4. android hal 音频分析,实现车载音频 HAL  |  Android 开源项目  |  Android Open Source Project...

    车载音频实现依赖标准 Android 音频 HAL,其中包括以下内容: IDevice (hardware/interfaces/audio/2.0/IDevice.hal).负责创建输入流和输出流. ...

  5. android格式转化,旭日Android视频格式转换器

    旭日Android视频格式转换器是一款可以帮助安卓手机进行视频格式转换的软件,几乎支持目前所有主流视频格式的转换,具有转换速度快,转换质量高的特点. 相关软件软件大小版本说明下载地址 旭日Androi ...

  6. 简诉android源代码编译过程,Android源码编译过程及原理(二)

    在未来等风也等你 本节主要记录的内容anroid 编译系统的结构 编译中枢中main.mk的基本解析 除非特别说明本节中的目录都是基于android的源码目录 1. android 编译系统的结构 a ...

  7. H5的Audio API音频

    h5出现之前,要进行Web音频的展示,往往需要在浏览器加载flash等插件,h5中新增的<audio>标签允许用户进行一些基本的音频流操作,但是对于一些复杂的音频处理应用,其功能远远不能满 ...

  8. AVAudioSession音频会话(类别选择/音频输出切换)

    简介 音频会话是一个Singleton对象,您可以使用它来设置应用程序的音频上下文环境,并向系统表达您的应用程序音频行为的意图. 使用此类可以: 启用或停用应用程式的音讯工作阶段 设置音频会话类别和模 ...

  9. Android官方开发文档Training系列课程中文版:管理音频播放之音频输出硬件的处理

    原文地址:http://android.xsoftlab.net/training/managing-audio/audio-output.html 当用户使用Android设备享受音频时,它有多重的 ...

最新文章

  1. WinAPI: CreateFontIndirect - 根据字体结构建立逻辑字体
  2. 云网融合 — 云网业务统一管控技术
  3. C++Opengl三维列表堆罗汉源码
  4. Java 面试就业指导,100 % 提高面试成功率
  5. Verilog经验总结
  6. 工作分析文献综述_学术知识| 如何撰写文献综述
  7. web安全day12:PKI
  8. 二叉树最小结构(C++版本)
  9. java 数据结构与算法_数据结构与算法—常用数据结构及其Java实现
  10. 锐起无盘服务器改dns,锐起无盘多配置教程-菜鸟版(老鸟飘过)
  11. java的package怎么用_Java包(Package)的详细用法(转)
  12. 戳这里,誉天胡老师教你如何备考 HCIE-Datacom!考试通关so easy!
  13. CSS真好玩——用纯CSS画一轮新月
  14. android 钉钉考勤日历,vue钉钉考勤日历 vue实现钉钉的考勤日历
  15. CF794E Choosing Carrot
  16. python基础教程(第三版)学习笔记(十八)
  17. Argo workflow 入门
  18. 对抗式学习pythonC day1 菜鸟档案
  19. Windows server 2022安装与激活
  20. 小写数字转化为大写数字

热门文章

  1. 我的世界java地狱更新_【我的世界】我得世界:1.16地狱大年夜更新_玩得好游戏攻略...
  2. 永远不怕IE主页地址被修改
  3. 微信最火html5游戏平台,盘点五个热门HTML5游戏微信公众号
  4. 推荐系统--基于图的推荐算法
  5. 基于QT的商场线上购物管理系统之客户端
  6. 论如何举办一个承载400人的比赛(XUPT新生赛承办小记)
  7. 网络计算机无法连接打印机,网络打印机无法连接怎么办 网络打印机无法连接教程【详解】...
  8. Excel数据透视表经典教程十《值的汇总及显示方式》
  9. 光电效应与光子|走进量子力学(3)
  10. AI智能视频平台EasyCVR新增接口可对接海康安防综合开放平台