关山初度尘未洗,策马扬鞭再奋蹄!这篇文章主要讲述Android 8 AudioPolicy 分析相关的知识,希望能为你提供帮助。
AudioTrack最终会调用AudioPolicyManager::getOutput();
frameworksavservicesaudiopolicymanagerdefaultAudioPolicyManager.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【Android 8 AudioPolicy 分析】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,
frameworksavservicesaudiopolicyenginedefaultsrcEngine.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;
}
}frameworksavservicesaudiopolicycommonincludeRoutingStrategy.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);
}frameworksavservicesaudiopolicyenginedefaultsrcEngine.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)hardwareqcomaudiohalmsm8916platform.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},
};
推荐阅读
- WPF App.xaml.cs常用模板,包括(异常捕获,App只能启动一次)
- Android媒体解码MediaCodec MediaExtractor学习
- OpenCV for AndroidAndroid Studio集成OpenCV
- Android Native内存泄漏检测方法
- Android平台证件识别系统
- Struts 2正则表达式验证示例
- Struts 2 int验证示例
- Struts 2日期验证示例
- Struts 2电子邮件验证示例