音频的路由策略:routing_strategy:
frameworks/av/services/audiopolicy/common/include/RoutingStrategy.h
是一个枚举类型,有11种音频路由策略,相对于android5.0系统增加了6种:
#pragma once
namespace android {
// Time in milliseconds after media stopped playing during which we consider that the
// sonification should be as unobtrusive as during the time media was playing.
#define SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY 5000
enum routing_strategy {
STRATEGY_MEDIA,
STRATEGY_PHONE,
STRATEGY_SONIFICATION,
STRATEGY_SONIFICATION_RESPECTFUL,
STRATEGY_DTMF,
STRATEGY_FM,
STRATEGY_ENFORCED_AUDIBLE,
STRATEGY_TRANSMITTED_THROUGH_SPEAKER,
STRATEGY_ACCESSIBILITY,
STRATEGY_REROUTING,
NUM_STRATEGIES
};
}; //namespace android
四个文件引用到这个枚举:
frameworks/av/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
frameworks/av/services/audiopolicy/common/managerdefinitions/include/EffectDescriptor.h
frameworks/av/services/audiopolicy/common/managerdefinitions/include/AudioSourceDescriptor.h
frameworks/av/services/audiopolicy/engine/interface/AudioPolicyManagerInterface.h
重点分析AudioPolicyManagerInterface.h文件,因为Engine.cpp应用到了这个路由策略类型,音频的路由策略类型主要是在Engine.cpp中实现切换,看如下代码:
frameworks/av/services/audiopolicy/enginedefault/src/Engine.h
/* Copy facilities are put private to disable copy. */
Engine(const Engine &object);
Engine &operator=(const Engine &object);
void setObserver(AudioPolicyManagerObserver *observer);
status_t initCheck();
inline bool isInCall() const
{
return is_state_in_call(mPhoneState);
}
//设置电话状态
status_t setPhoneState(audio_mode_t mode);
audio_mode_t getPhoneState() const
{
return mPhoneState;
}
//强制设置音频策略
status_t setForceUse(audio_policy_force_use_t usage, audio_policy_forced_cfg_t config);
audio_policy_forced_cfg_t getForceUse(audio_policy_force_use_t usage) const
{
return mForceUse[usage];
}
//设置默认的音频设备
status_t setDefaultDevice(audio_devices_t device);
//从音频流类型中获取该音频流的路由策略
routing_strategy getStrategyForStream(audio_stream_type_t stream);
//根据音频的用途获取该使用的路由策略
routing_strategy getStrategyForUsage(audio_usage_t usage);
//根据音频路由策略获取相应的输出输入设备
audio_devices_t getDeviceForStrategy(routing_strategy strategy) const;
//根据音频策略获取设备
audio_devices_t getDeviceForStrategyInt(routing_strategy strategy,
DeviceVector availableOutputDevices,
DeviceVector availableInputDevices,
const SwAudioOutputCollection &outputs,
uint32_t outputDeviceTypesToIgnore) const;
//根据输入音频获取设备
audio_devices_t getDeviceForInputSource(audio_source_t inputSource) const;
audio_mode_t mPhoneState; /**< current phone state. */
/** current forced use configuration. */
audio_policy_forced_cfg_t mForceUse[AUDIO_POLICY_FORCE_USE_CNT];
AudioPolicyManagerObserver *mApmObserver;
//这里有一个mApmObserver是从AudioPolicyManager中通过setObserver传递过来的引用地址
实现在Engine.cpp文件中,
这里有枚举类型:第一个:audio_stream_type_t,是一个枚举类型的结构体,代表的是音频流:
system/media/audio/include/system/audio-base.h
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,
#ifndef AUDIO_NO_SYSTEM_DECLARATIONS
/** For dynamic policy output mixes. Only used by the audio policy */
AUDIO_STREAM_REROUTING = 11,
/** For audio flinger tracks volume. Only used by the audioflinger */
AUDIO_STREAM_PATCH = 12,
#endif // AUDIO_NO_SYSTEM_DECLARATIONS
#ifdef SPRD_CUSTOM_AUDIO_POLICY
AUDIO_STREAM_FM = 13, /* For fm stream */
#endif
} audio_stream_type_t;
还定义了好几个类型:
audio_source_t,audio_session_t,audio_format_t,audio_mode_t,audio_output_flags_t,audio_input_flags_t,audio_usage_t,audio_content_type_t,audio_port_role_t,audio_port_type_t,audio_mix_latency_class_t
引用结构
frameworks/av/services/audiopolicy/common/include/policy.h
>system/media/audio/include/system/audio.h
>system/media/audio/include/system/audio-base.h
根据音频流获取音频策略,这个不多说,都是没有什么逻辑可言,是一一对应的关系:
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;
#ifdef SPRD_CUSTOM_AUDIO_POLICY
//modify for FM
case AUDIO_STREAM_FM:
return STRATEGY_FM;
#endif
}
}
根据音频用途获取音频策略也是一一对应的关系,就不多说了,
主要讲解为根据音频路由策略获取音频的输入输出设备getDeviceForStrategy():
audio_devices_t Engine::getDeviceForStrategy(routing_strategy strategy) const
{
// 获取在AudioPolicyManager中对应于的可用输出输入设备集合
DeviceVector availableOutputDevices = mApmObserver->getAvailableOutputDevices();
DeviceVector availableInputDevices = mApmObserver->getAvailableInputDevices();
//获取输出的设备集合
const SwAudioOutputCollection &outputs = mApmObserver->getOutputs();
//根据音频路由策略,输入输出设备,输出的设备集合获取相应的设备
return getDeviceForStrategyInt(strategy, availableOutputDevices,
availableInputDevices, outputs, (uint32_t)AUDIO_DEVICE_NONE);
}
这里的SwAudioOutputCollection集合的定义在AudioOutputDescriptor.h文件中:
frameworks/av/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
class SwAudioOutputCollection :
public DefaultKeyedVector< audio_io_handle_t, sp >
{
public:
bool isStreamActive(audio_stream_type_t stream, uint32_t inPastMs = 0) const;
bool isStreamActiveRemotely(audio_stream_type_t stream, uint32_t inPastMs = 0) const;
bool isStreamActiveLocally(audio_stream_type_t stream, uint32_t inPastMs = 0) const;
audio_io_handle_t getA2dpOutput() const;
bool isA2dpOffloadedOnPrimary() const;
bool isA2dpSupported() const;
sp getOutputFromId(audio_port_handle_t id) const;
sp getPrimaryOutput() const;
bool isAnyOutputActive(audio_stream_type_t streamToIgnore) const;
audio_devices_t getSupportedDevices(audio_io_handle_t handle) const;
status_t dump(int fd) const;
};
继续查看:getDeviceForStrategyInt
audio_devices_t Engine::getDeviceForStrategyInt(routing_strategy strategy,
DeviceVector availableOutputDevices,
DeviceVector availableInputDevices,
const SwAudioOutputCollection &outputs,
uint32_t outputDeviceTypesToIgnore) const
{
uint32_t device = AUDIO_DEVICE_NONE;
uint32_t availableOutputDevicesType =
availableOutputDevices.types() & ~outputDeviceTypesToIgnore;
switch (strategy) {
......
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;
}
这个函数对应着所有根据音频路由策略获取相应的设备信息:
下面一条条来进行分析:
获取的音频输出设备是喇叭:
case STRATEGY_TRANSMITTED_THROUGH_SPEAKER:
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER;
break;
根据通知的音频路由策略获取音频设备:
首先判断是否在通话中,如果是在通话中,则递归执行到 case STRATEGY_SONIFICATION:break;语句:同样也是先判断是否处于通话中这个特殊状态,是的话输出策略设定为STRATEGY_PHONE,然后直接break出来,
case STRATEGY_SONIFICATION_RESPECTFUL:
if (isInCall() || outputs.isStreamActiveLocally(AUDIO_STREAM_VOICE_CALL)) {
device = getDeviceForStrategyInt(
STRATEGY_SONIFICATION, availableOutputDevices, availableInputDevices, outputs,
outputDeviceTypesToIgnore);
} else {
bool media_active_locally =
outputs.isStreamActiveLocally(
AUDIO_STREAM_MUSIC, SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY)
|| outputs.isStreamActiveLocally(
AUDIO_STREAM_ACCESSIBILITY, SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY);
// routing is same as media without the "remote" device
device = getDeviceForStrategyInt(STRATEGY_MEDIA,
availableOutputDevices,
availableInputDevices, outputs,
AUDIO_DEVICE_OUT_REMOTE_SUBMIX | outputDeviceTypesToIgnore);
// if no media is playing on the device, check for mandatory use of "safe" speaker
// when media would have played on speaker, and the safe speaker path is available
if (!media_active_locally
&& (device & AUDIO_DEVICE_OUT_SPEAKER)
&& (availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
device |= AUDIO_DEVICE_OUT_SPEAKER_SAFE;
device &= ~AUDIO_DEVICE_OUT_SPEAKER;
}
}
break;
case STRATEGY_SONIFICATION:
// If incall, just select the STRATEGY_PHONE device: The rest of the behavior is handled by
// handleIncallSonification().
if (isInCall() || outputs.isStreamActiveLocally(AUDIO_STREAM_VOICE_CALL)) {
device = getDeviceForStrategyInt(
STRATEGY_PHONE, availableOutputDevices, availableInputDevices, outputs,
outputDeviceTypesToIgnore);
break;
}
// FALL THROUGH
当不再通话状态则,返回媒体音频策略的设备;在通话状态,走通话状态的策略设备;
case STRATEGY_DTMF:
if (!isInCall()) {
// when off call, DTMF strategy follows the same rules as MEDIA strategy
device = getDeviceForStrategyInt(
STRATEGY_MEDIA, availableOutputDevices, availableInputDevices, outputs,
outputDeviceTypesToIgnore);
break;
}
// when in call, DTMF and PHONE strategies follow the same rules
// FALL THROUGH
音频路由策略为通话状态:
case STRATEGY_PHONE:
// Force use of only devices on primary output if:
// - in call AND
// - cannot route from voice call RX OR
// - audio HAL version is < 3.0 and TX device is on the primary HW module
if (getPhoneState() == AUDIO_MODE_IN_CALL) {
audio_devices_t txDevice = getDeviceForInputSource(AUDIO_SOURCE_VOICE_COMMUNICATION);
sp primaryOutput = outputs.getPrimaryOutput();
audio_devices_t availPrimaryInputDevices =
availableInputDevices.getDevicesFromHwModule(primaryOutput->getModuleHandle());
// TODO: getPrimaryOutput return only devices from first module in
// audio_policy_configuration.xml, hearing aid is not there, but it's
// a primary device
// FIXME: this is not the right way of solving this problem
audio_devices_t availPrimaryOutputDevices =
(primaryOutput->supportedDevices() | AUDIO_DEVICE_OUT_HEARING_AID) &
availableOutputDevices.types();
if (((availableInputDevices.types() &
AUDIO_DEVICE_IN_TELEPHONY_RX & ~AUDIO_DEVICE_BIT_IN) == 0) ||
(((txDevice & availPrimaryInputDevices & ~AUDIO_DEVICE_BIT_IN) != 0) &&
(primaryOutput->getAudioPort()->getModuleVersionMajor() < 3))) {
availableOutputDevicesType = availPrimaryOutputDevices;
}
}
// for phone strategy, we first consider the forced use and then the available devices by
// order of priority
switch (mForceUse[AUDIO_POLICY_FORCE_FOR_COMMUNICATION]) {
case AUDIO_POLICY_FORCE_BT_SCO://强制指定蓝牙设备
if (!isInCall() || strategy != STRATEGY_DTMF) {
//如果没有在通话状态,则查询车载蓝牙是否存在???
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT;
if (device) break;
}
//在检测其他的蓝牙设备,如检测蓝牙耳机是否存在
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET;
if (device) break;
//检测蓝牙设备是否存在
device = availableOutputDevicesType & 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,没有指定强制通话路由的情况下
//耳机模式
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_HEARING_AID;
if (device) break;
// when not in a phone call, phone strategy should route STREAM_VOICE_CALL to A2DP
if (!isInCall() &&
(mForceUse[AUDIO_POLICY_FORCE_FOR_MEDIA] != AUDIO_POLICY_FORCE_NO_BT_A2DP) &&
outputs.isA2dpSupported()) {
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP;
if (device) break;
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;
if (device) break;
}
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_WIRED_HEADPHONE;
if (device) break;
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_WIRED_HEADSET;
if (device) break;
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_LINE;
if (device) break;
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_HEADSET;
if (device) break;
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_DEVICE;
if (device) break;
if (!isInCall()) {
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_ACCESSORY;
if (device) break;
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET;
if (device) break;
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_AUX_DIGITAL;
if (device) break;
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET;
if (device) break;
}
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_EARPIECE;
break;
case AUDIO_POLICY_FORCE_SPEAKER://强制指定喇叭设备
// when not in a phone call, phone strategy should route STREAM_VOICE_CALL to
// A2DP speaker when forcing to speaker output
if (!isInCall() &&
(mForceUse[AUDIO_POLICY_FORCE_FOR_MEDIA] != AUDIO_POLICY_FORCE_NO_BT_A2DP) &&
outputs.isA2dpSupported()) {
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER;
if (device) break;
}
if (!isInCall()) {
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_ACCESSORY;
if (device) break;
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_DEVICE;
if (device) break;
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET;
if (device) break;
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_AUX_DIGITAL;
if (device) break;
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET;
if (device) break;
}
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER;
break;
}
break;
case STRATEGY_ENFORCED_AUDIBLE://指定强制音频设备,上层用户空间设置
......
break;
case STRATEGY_ACCESSIBILITY://设置障碍设备
......
break;
case STRATEGY_REROUTING:
case STRATEGY_MEDIA: //指定媒体设备
.......
break;
case STRATEGY_FM: //指定FM输出设备
......
break;
audio_devices_t Engine::getDeviceForInputSource(audio_source_t inputSource) const
{
const DeviceVector &availableOutputDevices = mApmObserver->getAvailableOutputDevices();
const DeviceVector &availableInputDevices = mApmObserver->getAvailableInputDevices();
const SwAudioOutputCollection &outputs = mApmObserver->getOutputs();
audio_devices_t availableDeviceTypes = availableInputDevices.types() & ~AUDIO_DEVICE_BIT_IN;
uint32_t device = AUDIO_DEVICE_NONE;
// when a call is active, force device selection to match source VOICE_COMMUNICATION
// for most other input sources to avoid rerouting call TX audio
if (isInCall()) {
switch (inputSource) {
case AUDIO_SOURCE_DEFAULT:
case AUDIO_SOURCE_MIC:
case AUDIO_SOURCE_VOICE_RECOGNITION:
case AUDIO_SOURCE_UNPROCESSED:
case AUDIO_SOURCE_HOTWORD:
case AUDIO_SOURCE_CAMCORDER:
inputSource = AUDIO_SOURCE_VOICE_COMMUNICATION;
break;
default:
break;
}
}
switch (inputSource) {
case AUDIO_SOURCE_VOICE_UPLINK:
if (availableDeviceTypes & AUDIO_DEVICE_IN_VOICE_CALL) {
device = AUDIO_DEVICE_IN_VOICE_CALL;
break;
}
break;
case AUDIO_SOURCE_DEFAULT:
case AUDIO_SOURCE_MIC:
if (availableDeviceTypes & AUDIO_DEVICE_IN_BLUETOOTH_A2DP) {
device = AUDIO_DEVICE_IN_BLUETOOTH_A2DP;
} else if ((mForceUse[AUDIO_POLICY_FORCE_FOR_RECORD] == AUDIO_POLICY_FORCE_BT_SCO) &&
(availableDeviceTypes & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET)) {
device = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET;
} else if (availableDeviceTypes & AUDIO_DEVICE_IN_WIRED_HEADSET) {
device = AUDIO_DEVICE_IN_WIRED_HEADSET;
} else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_HEADSET) {
device = AUDIO_DEVICE_IN_USB_HEADSET;
} else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_DEVICE) {
device = AUDIO_DEVICE_IN_USB_DEVICE;
} else if (availableDeviceTypes & AUDIO_DEVICE_IN_BUILTIN_MIC) {
device = AUDIO_DEVICE_IN_BUILTIN_MIC;
}
break;
case AUDIO_SOURCE_VOICE_COMMUNICATION:
// Allow only use of devices on primary input if in call and HAL does not support routing
// to voice call path.
if ((getPhoneState() == AUDIO_MODE_IN_CALL) &&
(availableOutputDevices.types() & AUDIO_DEVICE_OUT_TELEPHONY_TX) == 0) {
sp primaryOutput = outputs.getPrimaryOutput();
availableDeviceTypes =
availableInputDevices.getDevicesFromHwModule(primaryOutput->getModuleHandle())
& ~AUDIO_DEVICE_BIT_IN;
}
switch (mForceUse[AUDIO_POLICY_FORCE_FOR_COMMUNICATION]) {
case AUDIO_POLICY_FORCE_BT_SCO:
// if SCO device is requested but no SCO device is available, fall back to default case
if (availableDeviceTypes & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) {
device = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET;
break;
}
// FALL THROUGH
default: // FORCE_NONE
if (availableDeviceTypes & AUDIO_DEVICE_IN_WIRED_HEADSET) {
device = AUDIO_DEVICE_IN_WIRED_HEADSET;
} else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_HEADSET) {
device = AUDIO_DEVICE_IN_USB_HEADSET;
} else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_DEVICE) {
device = AUDIO_DEVICE_IN_USB_DEVICE;
} else if (availableDeviceTypes & AUDIO_DEVICE_IN_BUILTIN_MIC) {
device = AUDIO_DEVICE_IN_BUILTIN_MIC;
}
break;
case AUDIO_POLICY_FORCE_SPEAKER:
if (availableDeviceTypes & AUDIO_DEVICE_IN_BACK_MIC) {
device = AUDIO_DEVICE_IN_BACK_MIC;
} else if (availableDeviceTypes & AUDIO_DEVICE_IN_BUILTIN_MIC) {
device = AUDIO_DEVICE_IN_BUILTIN_MIC;
}
break;
}
break;
case AUDIO_SOURCE_VOICE_RECOGNITION:
case AUDIO_SOURCE_UNPROCESSED:
case AUDIO_SOURCE_HOTWORD:
if (mForceUse[AUDIO_POLICY_FORCE_FOR_RECORD] == AUDIO_POLICY_FORCE_BT_SCO &&
availableDeviceTypes & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) {
device = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET;
} else if (availableDeviceTypes & AUDIO_DEVICE_IN_WIRED_HEADSET) {
device = AUDIO_DEVICE_IN_WIRED_HEADSET;
} else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_HEADSET) {
device = AUDIO_DEVICE_IN_USB_HEADSET;
} else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_DEVICE) {
device = AUDIO_DEVICE_IN_USB_DEVICE;
} else if (availableDeviceTypes & AUDIO_DEVICE_IN_BUILTIN_MIC) {
device = AUDIO_DEVICE_IN_BUILTIN_MIC;
}
break;
case AUDIO_SOURCE_CAMCORDER:
if (availableDeviceTypes & AUDIO_DEVICE_IN_BACK_MIC) {
device = AUDIO_DEVICE_IN_BACK_MIC;
} else if (availableDeviceTypes & AUDIO_DEVICE_IN_BUILTIN_MIC) {
device = AUDIO_DEVICE_IN_BUILTIN_MIC;
}
break;
case AUDIO_SOURCE_VOICE_DOWNLINK:
case AUDIO_SOURCE_VOICE_CALL:
if (availableDeviceTypes & AUDIO_DEVICE_IN_VOICE_CALL) {
device = AUDIO_DEVICE_IN_VOICE_CALL;
}
break;
case AUDIO_SOURCE_REMOTE_SUBMIX:
if (availableDeviceTypes & AUDIO_DEVICE_IN_REMOTE_SUBMIX) {
device = AUDIO_DEVICE_IN_REMOTE_SUBMIX;
}
break;
case AUDIO_SOURCE_FM_TUNER:
if (availableDeviceTypes & AUDIO_DEVICE_IN_FM_TUNER) {
device = AUDIO_DEVICE_IN_FM_TUNER;
}
break;
default:
ALOGW("getDeviceForInputSource() invalid input source %d", inputSource);
break;
}
if (device == AUDIO_DEVICE_NONE) {
ALOGV("getDeviceForInputSource() no device found for source %d", inputSource);
if (availableDeviceTypes & AUDIO_DEVICE_IN_STUB) {
device = AUDIO_DEVICE_IN_STUB;
}
ALOGE_IF(device == AUDIO_DEVICE_NONE,
"getDeviceForInputSource() no default device defined");
}
ALOGV("getDeviceForInputSource()input source %d, device %08x", inputSource, device);
return device;
}