AudioTrack最终会调用AudioPolicyManager::getOutput();

frameworks\av\services\audiopolicy\managerdefault\AudioPolicyManager.cpp
audio_io_handle_t AudioPolicyManager::getOutput(audio_stream_type_t stream,
uint32_t samplingRate,
audio_format_t format,
audio_channel_mask_t channelMask,
audio_output_flags_t flags,
const audio_offload_info_t *offloadInfo)
{
//APM_AudioPolicyManager: getOutput() device 2, stream 1, samplingRate 0, format 0, channelMask 3, flags 0
// stream = 1, AUDIO_STREAM_SYSTEM, 得到的strategy = STRATEGY_MEDIA
routing_strategy strategy = getStrategy(stream);
// AUDIO_DEVICE_NONE & AUDIO_DEVICE_OUT_SPEAKER
audio_devices_t device = getDeviceForStrategy(strategy, false /*fromCache*/);
//APM_AudioPolicyManager: getOutput() device 2, stream 1, samplingRate 0, format 0, channelMask 3, flags 0
ALOGV("getOutput() device %d, stream %d, samplingRate %d, format %x, channelMask %x, flags %x",
device, stream, samplingRate, format, channelMask, flags);
ALOGE("Liutao getOutput() device %d, stream %d, samplingRate %d, format %x, channelMask %x, flags %x",
device, stream, samplingRate, format, channelMask, flags); return getOutputForDevice(device, AUDIO_SESSION_ALLOCATE, stream, samplingRate, format,
channelMask, flags, offloadInfo);
}

根据stream获取strategy

StreamType指PCM的生成类型。是播放电影产生的?还是通话产生的?

STRATEGY指针对某一中stream,该采用的策略。在策略里面,会根据其他信息来具体选定某一个具体的Audio Devices

routing_strategy AudioPolicyManager::getStrategy(audio_stream_type_t stream) const
{
ALOG_ASSERT(stream != AUDIO_STREAM_PATCH,"getStrategy() called for AUDIO_STREAM_PATCH");
return mEngine->getStrategyForStream(stream);
} // 不同的stream类型对应的stragegy,播放音乐,系统铃声,stream = 1, AUDIO_STREAM_SYSTEM = 1,
frameworks\av\services\audiopolicy\enginedefault\src\Engine.cpp
routing_strategy Engine::getStrategyForStream(audio_stream_type_t stream)
{
// stream to strategy mapping
switch (stream) {
case AUDIO_STREAM_VOICE_CALL:
case AUDIO_STREAM_BLUETOOTH_SCO:
return STRATEGY_PHONE;
case AUDIO_STREAM_RING:
case AUDIO_STREAM_ALARM:
return STRATEGY_SONIFICATION;
case AUDIO_STREAM_NOTIFICATION:
return STRATEGY_SONIFICATION_RESPECTFUL;
case AUDIO_STREAM_DTMF:
return STRATEGY_DTMF;
default:
ALOGE("unknown stream type %d", stream);
case AUDIO_STREAM_SYSTEM:
// NOTE: SYSTEM stream uses MEDIA strategy because muting music and switching outputs
// while key clicks are played produces a poor result
case AUDIO_STREAM_MUSIC:
return STRATEGY_MEDIA;
case AUDIO_STREAM_ENFORCED_AUDIBLE:
return STRATEGY_ENFORCED_AUDIBLE;
case AUDIO_STREAM_TTS:
return STRATEGY_TRANSMITTED_THROUGH_SPEAKER;
case AUDIO_STREAM_ACCESSIBILITY:
return STRATEGY_ACCESSIBILITY;
case AUDIO_STREAM_REROUTING:
return STRATEGY_REROUTING;
}
} frameworks\av\services\audiopolicy\common\include\RoutingStrategy.h
enum routing_strategy {
STRATEGY_MEDIA,
STRATEGY_PHONE,
STRATEGY_SONIFICATION,
STRATEGY_SONIFICATION_RESPECTFUL,
STRATEGY_DTMF,
STRATEGY_ENFORCED_AUDIBLE,
STRATEGY_TRANSMITTED_THROUGH_SPEAKER,
STRATEGY_ACCESSIBILITY,
STRATEGY_REROUTING,
NUM_STRATEGIES
}; // STREAM类型定义
typedef enum {
AUDIO_STREAM_DEFAULT = -1, // (-1)
AUDIO_STREAM_MIN = 0,
AUDIO_STREAM_VOICE_CALL = 0,
AUDIO_STREAM_SYSTEM = 1,
AUDIO_STREAM_RING = 2,
AUDIO_STREAM_MUSIC = 3,
AUDIO_STREAM_ALARM = 4,
AUDIO_STREAM_NOTIFICATION = 5,
AUDIO_STREAM_BLUETOOTH_SCO = 6,
AUDIO_STREAM_ENFORCED_AUDIBLE = 7,
AUDIO_STREAM_DTMF = 8,
AUDIO_STREAM_TTS = 9,
AUDIO_STREAM_ACCESSIBILITY = 10,
AUDIO_STREAM_REROUTING = 11,
AUDIO_STREAM_PATCH = 12,
AUDIO_STREAM_PUBLIC_CNT = 11, // (ACCESSIBILITY + 1)
AUDIO_STREAM_FOR_POLICY_CNT = 12, // PATCH
AUDIO_STREAM_CNT = 13, // (PATCH + 1)
} audio_stream_type_t;

根据Strategy获取device

audio_devices_t AudioPolicyManager::getDeviceForStrategy(routing_strategy strategy,
bool fromCache)
{
// Routing
// see if we have an explicit route
// scan the whole RouteMap, for each entry, convert the stream type to a strategy
// (getStrategy(stream)).
// if the strategy from the stream type in the RouteMap is the same as the argument above,
// and activity count is non-zero and the device in the route descriptor is available
// then select this device.
for (size_t routeIndex = 0; routeIndex < mOutputRoutes.size(); routeIndex++) {
sp<SessionRoute> route = mOutputRoutes.valueAt(routeIndex);
routing_strategy routeStrategy = getStrategy(route->mStreamType);
// 判断输入的STRAGEGY是否在系统支持的mOutputRoutes列表里面
if ((routeStrategy == strategy) && route->isActive() &&
(mAvailableOutputDevices.indexOf(route->mDeviceDescriptor) >= 0)) {
return route->mDeviceDescriptor->type();
}
} if (fromCache) {
ALOGVV("getDeviceForStrategy() from cache strategy %d, device %x",
strategy, mDeviceForStrategy[strategy]);
return mDeviceForStrategy[strategy];
}
// 传入的stragegy = STRATEGY_MEDIA
return mEngine->getDeviceForStrategy(strategy);
} audio_devices_t Engine::getDeviceForStrategy(routing_strategy strategy) const
{
DeviceVector availableOutputDevices = mApmObserver->getAvailableOutputDevices();
DeviceVector availableInputDevices = mApmObserver->getAvailableInputDevices(); const SwAudioOutputCollection &outputs = mApmObserver->getOutputs(); return getDeviceForStrategyInt(strategy, availableOutputDevices,
availableInputDevices, outputs);
} frameworks\av\services\audiopolicy\enginedefault\src\Engine.cpp
audio_devices_t Engine::getDeviceForStrategyInt(routing_strategy strategy,
DeviceVector availableOutputDevices,
DeviceVector availableInputDevices,
const SwAudioOutputCollection &outputs) const
{
uint32_t device = AUDIO_DEVICE_NONE;
uint32_t availableOutputDevicesType = availableOutputDevices.types();
bool isFmA2dpConcurrencyOn = property_get_bool("vendor.fm.a2dp.conc.disabled", false); // Do not support a2dp device when FM is active based on concurrency property
if (isFmA2dpConcurrencyOn && (availableOutputDevicesType & AUDIO_DEVICE_OUT_FM)) {
ALOGV("FM a2dp concurrency is set, not considering a2dp for device selection");
availableOutputDevicesType = availableOutputDevicesType & ~AUDIO_DEVICE_OUT_ALL_A2DP;
} // 传入的stragegy = STRATEGY_MEDIA = 0
switch (strategy) {
// FIXME: STRATEGY_REROUTING follow STRATEGY_MEDIA for now
case STRATEGY_REROUTING:
case STRATEGY_MEDIA: {
uint32_t device2 = AUDIO_DEVICE_NONE;
// 是否在打电话
if (isInCall() && (device == AUDIO_DEVICE_NONE)) {
// when in call, get the device for Phone strategy
device = getDeviceForStrategy(STRATEGY_PHONE);
break;
} if (strategy != STRATEGY_SONIFICATION) {
// no sonification on remote submix (e.g. WFD)
// 查看是否有远程设备
if (availableOutputDevices.getDevice(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
String8("0")) != 0) {
device2 = availableOutputDevices.types() & AUDIO_DEVICE_OUT_REMOTE_SUBMIX;
}
}
// 打电话, 并且播放音乐还有系统铃声时的处理
if (isInCall() && (strategy == STRATEGY_MEDIA)) {
device = getDeviceForStrategyInt(
STRATEGY_PHONE, availableOutputDevices, availableInputDevices, outputs);
break;
}
// 蓝牙耳机
if ((device2 == AUDIO_DEVICE_NONE) &&
(mForceUse[AUDIO_POLICY_FORCE_FOR_MEDIA] != AUDIO_POLICY_FORCE_NO_BT_A2DP) &&
(outputs.isA2dpOnPrimary() || (outputs.getA2dpOutput() != 0))) {
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP;
if (device2 == AUDIO_DEVICE_NONE) {
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;
}
if (device2 == AUDIO_DEVICE_NONE) {
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER;
}
}
// SPEAKER
if ((device2 == AUDIO_DEVICE_NONE) &&
(mForceUse[AUDIO_POLICY_FORCE_FOR_MEDIA] == AUDIO_POLICY_FORCE_SPEAKER)) {
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER;
}
// 听筒
if (device2 == AUDIO_DEVICE_NONE) {
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_WIRED_HEADPHONE;
}
if (device2 == AUDIO_DEVICE_NONE) {
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_LINE;
}
// 有线耳机
if (device2 == AUDIO_DEVICE_NONE) {
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_WIRED_HEADSET;
}
// USB耳机
if (device2 == AUDIO_DEVICE_NONE) {
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_HEADSET;
}
if (device2 == AUDIO_DEVICE_NONE) {
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_ACCESSORY;
}
if (device2 == AUDIO_DEVICE_NONE) {
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_DEVICE;
}
if (device2 == AUDIO_DEVICE_NONE) {
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET;
}
if ((device2 == AUDIO_DEVICE_NONE) && (strategy != STRATEGY_SONIFICATION) &&
(device == AUDIO_DEVICE_NONE)) {
// no sonification on aux digital (e.g. HDMI)
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_AUX_DIGITAL;
}
if ((device2 == AUDIO_DEVICE_NONE) && (strategy != STRATEGY_SONIFICATION) &&
(mForceUse[AUDIO_POLICY_FORCE_FOR_DOCK] == AUDIO_POLICY_FORCE_ANALOG_DOCK)) {
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET;
}
if ((device2 == AUDIO_DEVICE_NONE) && (strategy != STRATEGY_SONIFICATION) &&
(device == AUDIO_DEVICE_NONE)) {
// no sonification on WFD sink
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_PROXY;
}
if (device2 == AUDIO_DEVICE_NONE) {
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER;
}
int device3 = AUDIO_DEVICE_NONE;
// 几个设备同时输出
if (strategy == STRATEGY_MEDIA) {
// ARC, SPDIF and AUX_LINE can co-exist with others.
device3 = availableOutputDevicesType & AUDIO_DEVICE_OUT_HDMI_ARC;
device3 |= (availableOutputDevicesType & AUDIO_DEVICE_OUT_SPDIF);
device3 |= (availableOutputDevicesType & AUDIO_DEVICE_OUT_AUX_LINE);
} device2 |= device3;
// device is DEVICE_OUT_SPEAKER if we come from case STRATEGY_SONIFICATION or
// STRATEGY_ENFORCED_AUDIBLE, AUDIO_DEVICE_NONE otherwise
device |= device2; // If hdmi system audio mode is on, remove speaker out of output list.
if ((strategy == STRATEGY_MEDIA) &&
(mForceUse[AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO] ==
AUDIO_POLICY_FORCE_HDMI_SYSTEM_AUDIO_ENFORCED)) {
device &= ~AUDIO_DEVICE_OUT_SPEAKER;
} // for STRATEGY_SONIFICATION:
// if SPEAKER was selected, and SPEAKER_SAFE is available, use SPEAKER_SAFE instead
if ((strategy == STRATEGY_SONIFICATION) &&
(device & AUDIO_DEVICE_OUT_SPEAKER) &&
(availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
device |= AUDIO_DEVICE_OUT_SPEAKER_SAFE;
device &= ~AUDIO_DEVICE_OUT_SPEAKER;
}
} break; default:
ALOGW("getDeviceForStrategy() unknown strategy: %d", strategy);
break;
} if (device == AUDIO_DEVICE_NONE) {
ALOGV("getDeviceForStrategy() no device found for strategy %d", strategy);
device = mApmObserver->getDefaultOutputDevice()->type();
ALOGE_IF(device == AUDIO_DEVICE_NONE,
"getDeviceForStrategy() no default device defined");
}
ALOGVV("getDeviceForStrategy() strategy %d, device %x", strategy, device);
return device;
}

为设备选择的输出通道

// APM_AudioPolicyManager: getOutput() device 2, stream 1, samplingRate 0, format 0, channelMask 3, flags 0

audio_io_handle_t AudioPolicyManager::getOutputForDevice(
audio_devices_t device,
audio_session_t session,
audio_stream_type_t stream,
uint32_t samplingRate,
audio_format_t format,
audio_channel_mask_t channelMask,
audio_output_flags_t flags,
const audio_offload_info_t *offloadInfo) hardware\qcom\audio\hal\msm8916\platform.c
static int msm_device_to_be_id_internal_codec [][NO_COLS] = {
{AUDIO_DEVICE_OUT_EARPIECE , 34},
{AUDIO_DEVICE_OUT_SPEAKER , 34},
{AUDIO_DEVICE_OUT_WIRED_HEADSET , 34},
{AUDIO_DEVICE_OUT_WIRED_HEADPHONE , 34},
{AUDIO_DEVICE_OUT_BLUETOOTH_SCO , 11},
{AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET , 11},
{AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT , 11},
{AUDIO_DEVICE_OUT_BLUETOOTH_A2DP , -1},
{AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES , -1},
{AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER , -1},
{AUDIO_DEVICE_OUT_AUX_DIGITAL , 4},
{AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET , 9},
{AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET , 9},
{AUDIO_DEVICE_OUT_USB_ACCESSORY , -1},
{AUDIO_DEVICE_OUT_USB_DEVICE , -1},
{AUDIO_DEVICE_OUT_USB_HEADSET , -1},
{AUDIO_DEVICE_OUT_REMOTE_SUBMIX , 9},
{AUDIO_DEVICE_OUT_PROXY , 9},
{AUDIO_DEVICE_OUT_FM , 7},
{AUDIO_DEVICE_OUT_FM_TX , 8},
{AUDIO_DEVICE_OUT_ALL , -1},
{AUDIO_DEVICE_NONE , -1},
{AUDIO_DEVICE_OUT_DEFAULT , -1},
}; static int msm_device_to_be_id_external_codec [][NO_COLS] = {
{AUDIO_DEVICE_OUT_EARPIECE , 2},
{AUDIO_DEVICE_OUT_SPEAKER , 2},
{AUDIO_DEVICE_OUT_WIRED_HEADSET , 41},
{AUDIO_DEVICE_OUT_WIRED_HEADPHONE , 41},
{AUDIO_DEVICE_OUT_BLUETOOTH_SCO , 11},
{AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET , 11},
{AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT , 11},
{AUDIO_DEVICE_OUT_BLUETOOTH_A2DP , -1},
{AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES , -1},
{AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER , -1},
{AUDIO_DEVICE_OUT_AUX_DIGITAL , 4},
{AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET , 9},
{AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET , 9},
{AUDIO_DEVICE_OUT_USB_ACCESSORY , -1},
{AUDIO_DEVICE_OUT_USB_DEVICE , -1},
{AUDIO_DEVICE_OUT_USB_HEADSET , -1},
{AUDIO_DEVICE_OUT_REMOTE_SUBMIX , 9},
{AUDIO_DEVICE_OUT_PROXY , 9},
{AUDIO_DEVICE_OUT_FM , 7},
{AUDIO_DEVICE_OUT_FM_TX , 8},
{AUDIO_DEVICE_OUT_ALL , -1},
{AUDIO_DEVICE_NONE , -1},
{AUDIO_DEVICE_OUT_DEFAULT , -1},
};

Android 8 AudioPolicy 分析的更多相关文章

  1. Android M AudioPolicy 分析

    1.AudioPolicyService基础 AudioPolicy在Android系统中主要负责Audio"策略"相关的问题.它和AudioFlinger一起组成了Android ...

  2. Android APP性能分析方法及工具

    近期读到<Speed up your app>一文.这是一篇关于Android APP性能分析.优化的文章.在这篇文章中,作者介绍他的APP分析优化规则.使用的工具和方法.我觉得值得大家借 ...

  3. Android之mtklog分析

    Android之mtklog分析 [海外场测反馈][xxx]动态测试时对比机xxxx拨打测试机xxxxx自动挂断电话 工作中遇到一个掉话的问题,需要分析log,log比较大,我也没法上传,就简答的讲讲 ...

  4. Android源码分析-全面理解Context

    前言 Context在android中的作用不言而喻,当我们访问当前应用的资源,启动一个新的activity的时候都需要提供Context,而这个Context到底是什么呢,这个问题好像很好回答又好像 ...

  5. cocos2d-x for android:SimpleGame分析

    cocos2d-x for android:SimpleGame分析 作为cocos2d-x的标配DEMO,SimpleGame可算是给入门学cocos2d-x的俺们这些新手门学习的对象了,那么来分析 ...

  6. Android内存机制分析1——了解Android堆和栈

    //----------------------------------------------------------------------------------- Android内存机制分析1 ...

  7. Android 内存管理分析(四)

    尊重原创作者,转载请注明出处: http://blog.csdn.net/gemmem/article/details/8920039 最近在网上看了不少Android内存管理方面的博文,但是文章大多 ...

  8. Qualcomm Android display架构分析

    Android display架构分析(一) http://blog.csdn.net/BonderWu/archive/2010/08/12/5805961.aspx http://hi.baidu ...

  9. Android 消息处理源代码分析(1)

    Android 消息处理源代码分析(1) 在Android中,通常被使用的消息队列的代码在文件夹\sources\android-22\android\os下,涉及到下面几个类文件 Handler.j ...

随机推荐

  1. centos7 开启特定的端口

    systemctl是centos7的服务管理工具中主要的工具,它融合之前的service和chkconfig功能于一体; 开机时启动:systemctl enable firewalld.servic ...

  2. Android Dialog-Dialog无法充满横屏且下方有间隔

    自定义一个Dialog,写完布局后运行,发现Dialog无法充满屏幕,就像下边这样: 代码大致如下: Dialog dialog = new Dialog(this); dialog.requestW ...

  3. [Windows Azure] Load Testing in Windows Azure

    The primary goal of a load test is to simulate many users accessing a web application at the same ti ...

  4. sql乘法函数实现方式

    sql中有很多聚合函数,例如 COUNT.SUM.MIN 和 MAX. 但是唯独没有乘法函数,而很多朋友开发中缺需要用到这种函数,今天告诉大家一个不错的解决方案 logx+logy=logx*y 这是 ...

  5. 【机器学习】随机森林(Random Forest)

    随机森林是一个最近比较火的算法 它有很多的优点: 在数据集上表现良好 在当前的很多数据集上,相对其他算法有着很大的优势 它能够处理很高维度(feature很多)的数据,并且不用做特征选择 在训练完后, ...

  6. squid搭建http/https代理服务器

    前言:笔者使用的长城宽带,访问国外网站,比如mysql,nginx等站点的速度.......,你懂得,于是想到使用腾讯云主机搭建squid代理服务器,这里搭建的是一般代理服务器,squid代理服务器分 ...

  7. android之滑屏的实现

    ★理论知识 ●View在屏幕上显示出来要先经过measure(计算)和layout(布局).  ◆当控件的父元素正要放置该控件时调用,父元素会问子控件“你想要用多大的地方?”,然后传入两个参数widt ...

  8. django signal

    @receiver(post_save, sender=User) def create_account(sender, instance=None, **kwargs): if instance i ...

  9. python 中文编码(一)

    我在学python的过程中,遇到的第二个问题,就是中文乱码,如今也算勉强入门了,在这里给大家说说我的经验,也算个新人引导吧.     在文章里,我会重点提到一个概念:有来有去. 即数据从哪里来,到哪里 ...

  10. C# ASP.NET B/S模式下,采用lock语法 实现多用户并发产生不重复递增单号的一种解决方法技术参考

    有时候也好奇,若是老外发个技术文章,会不会到处是有人骂街的?进行人身攻击的?中国人喜欢打击别人,不知道老外是不是也是这个性格?好奇的问一下大家. 往往我们在开发程序.调试程序时,无法模拟多用户同时操作 ...