当前位置:网站首页>Audio Device Strategy 音频设备输出、输入 选择 基于7.0 代码
Audio Device Strategy 音频设备输出、输入 选择 基于7.0 代码
2022-07-07 15:40:00 【QXXXD】
存档,不想留本地了,没啥含量 都在Enginee.cpp里写着呢
1. 输出选择
整体流程
首先我们会获取当前存在的设备集合availableOutputDevices
然后根据传入的strategty类型进行匹配选择
在选择之前会先检测是否处于特殊情况下(如通话中)
最后按照优先级匹配设备。
关于音频设备选择的策略定义在AudioPolicyManager中的getDeviceForStrategy()方法,会根据当时设备的状态和连接设备选择最合适的设备,具体实现在frameworks/av/services/audiopolicy/enginedefault/src/Engine.cpp中。
以下注释解释很清楚,参数为strategy和fromCache,如果fromCache = true,则从mDeviceForStrategy[]选择,否则继续往下走。
mDeviceForStrategy[NUM_STRATEGIES] 是一个数组。
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
};
frameworks/av/services/audiopolicy/managerdefault/AudioPolicyManager.h
virtual audio_devices_t getDeviceForStrategy(routing_strategy strategy,
bool fromCache);
1.1 AudioPolicyManager.cpp中的具体实现
frameworks/av/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
以下逻辑均涉及getDeviceForStrategy的调用
void AudioPolicyManager::setPhoneState(audio_mode_t state)
audio_io_handle_t AudioPolicyManager::getOutput(audio_stream_type_t stream —)
status_t AudioPolicyManager::getOutputForAttr
status_t AudioPolicyManager::startOutput(
status_t AudioPolicyManager::getStreamVolumeIndex(audio_stream_type_t stream,int *index audio_devices_t device)
audio_io_handle_t AudioPolicyManager::getOutputForEffect(const effect_descriptor_t *desc)
void AudioPolicyManager::checkStrategyRoute(routing_strategy strategy, audio_io_handle_t ouptutToSkip)
status_t AudioPolicyManager::connectAudioSource(const sp& sourceDesc){
void AudioPolicyManager::checkStrategyRoute(routing_strategy strategy,audio_io_handle_t ouptutToSkip){
void AudioPolicyManager::checkOutputForStrategy(routing_strategy strategy)
audio_devices_t AudioPolicyManager::getNewOutputDevice(const sp& outputDesc, bool fromCache)
audio_devices_t AudioPolicyManager::getDevicesForStream(audio_stream_type_t stream) {
void AudioPolicyManager::updateDevicesAndOutputs()
uint32_t AudioPolicyManager::checkDeviceMuteStrategies(sp
float AudioPolicyManager::computeVolume(audio_stream_type_t stream,
void AudioPolicyManager::handleIncallSonification(audio_stream_type_t stream,bool starting, bool stateChange)
status_t AudioPolicyManager::setDeviceConnectionStateInt(audio_devices_t 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
// the device = the device from the descriptor in the RouteMap, and exit.
for (size_t routeIndex = 0; routeIndex < mOutputRoutes.size(); routeIndex++) {
sp<SessionRoute> route = mOutputRoutes.valueAt(routeIndex);
routing_strategy routeStrategy = getStrategy(route->mStreamType); //仍旧调用getDeviceForStrategy
if ((routeStrategy == strategy) && route->isActive()) {
return route->mDeviceDescriptor->type();
}
}
if (fromCache) {
ALOGVV("getDeviceForStrategy() from cache strategy %d, device %x",
strategy, mDeviceForStrategy[strategy]);
return mDeviceForStrategy[strategy];
}
return mEngine->getDeviceForStrategy(strategy);
}
具体实现在Engine.cpp中
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;
}
}
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);
}
1.2 针对STRATEGY_MEDIA分析,播放设备优先级如下
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES(普通蓝牙耳机)
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER(蓝牙小音箱) //此处属于setForceUse的强制插队 (if FORCE_SPEAKER)AUDIO_DEVICE_OUT_SPEAKER(扬声器)
- AUDIO_DEVICE_OUT_WIRED_HEADPHONE(普通耳机,只能听,不能操控播放)
- AUDIO_DEVICE_OUT_LINE
- AUDIO_DEVICE_OUT_WIRED_HEADSET(线控耳机)
- AUDIO_DEVICE_OUT_USB_HEADSET(USB耳机)
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; //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; //蓝牙音箱
}
}
if ((device2 == AUDIO_DEVICE_NONE) &&
(mForceUse[AUDIO_POLICY_FORCE_FOR_MEDIA] == AUDIO_POLICY_FORCE_SPEAKER)) {//如果force speker 扬声器 喇叭
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; //带麦克风的有线耳机
}
if (device2 == AUDIO_DEVICE_NONE) {
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_ACCESSORY;
}
if (device2 == AUDIO_DEVICE_NONE) {
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_DEVICE; //USB设备
}
if (device2 == AUDIO_DEVICE_NONE) {
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET;
}
if ((strategy != STRATEGY_SONIFICATION) && (device == AUDIO_DEVICE_NONE)
&& (device2 == AUDIO_DEVICE_NONE)) {
// no sonification on aux digital (e.g. HDMI)
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_AUX_DIGITAL;
}
if ((device2 == AUDIO_DEVICE_NONE) &&
(mForceUse[AUDIO_POLICY_FORCE_FOR_DOCK] == AUDIO_POLICY_FORCE_ANALOG_DOCK)
&& (strategy != STRATEGY_SONIFICATION)) {
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET;
}
#ifdef AUDIO_EXTN_AFE_PROXY_ENABLED
if ((strategy != STRATEGY_SONIFICATION) && (device == AUDIO_DEVICE_NONE)
&& (device2 == AUDIO_DEVICE_NONE)) {
// no sonification on WFD sink
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_PROXY;
}
#endif
if (device2 == AUDIO_DEVICE_NONE) {
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER; // 外放 扬声器 喇叭
}
int device3 = AUDIO_DEVICE_NONE;
if (strategy == STRATEGY_MEDIA) {///如果arc,spdif,aux_line可用,赋值给device3
// 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;
}
} break;
2.输入选择
Audio Device Strategy 音频设备 输入选择 7.0
1.输入设备选择
1.1 MediaRecorder java层setAudioSource
以MediaRecorder为例,不考虑其他。setAudioSource设置输入源
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);// 设置麦克风
frameworks/base/media/java/android/media/MediaRecorder.java
AudioSource共定义以下几种
/** Default audio source **/
public static final int DEFAULT = 0; //默认
/** Microphone audio source */
public static final int MIC = 1; //麦克
/** Voice call uplink (Tx) audio source */
public static final int VOICE_UPLINK = 2; //电话上行
/** Voice call downlink (Rx) audio source */
public static final int VOICE_DOWNLINK = 3; //电话下行
/** Voice call uplink + downlink audio source */
public static final int VOICE_CALL = 4; //电话录音
/** Microphone audio source with same orientation as camera if available, the main
* device microphone otherwise */
public static final int CAMCORDER = 5; //摄像头麦克
public static final int VOICE_RECOGNITION = 6; //语音识别
public static final int VOICE_COMMUNICATION = 7;//网络电话
public static final int REMOTE_SUBMIX = 8; //用于内录
public static final int UNPROCESSED = 9; //未处理原始声音
@SystemApi
public static final int RADIO_TUNER = 1998; //广播
@SystemApi
public static final int HOTWORD = 1999;
继续看MediaRecorder
public native void setAudioSource(int audio_source)
throws IllegalStateException;
通过JNI调用到mediarecorder.cpp
frameworks/base/media/jni/android_media_MediaRecorder.cpp
static void
android_media_MediaRecorder_setVideoSource(JNIEnv *env, jobject thiz, jint vs) {
sp<MediaRecorder> mr = getMediaRecorder(env, thiz);
}
frameworks/av/media/libmedia/mediarecorder.cpp
status_t MediaRecorder::setAudioSource(int as){
status_t ret = mMediaRecorder->setAudioSource(as);
}
1.2 mMediaRecorder是谁
在看mMediaRecorder实例,是一个IMediaPlayerService 的service对象,调用了createMediaRecorder()
MediaRecorder::MediaRecorder(const String16& opPackageName) : mSurfaceMediaSource(NULL)
{
const sp<IMediaPlayerService> service(getMediaPlayerService());
if (service != NULL) {
mMediaRecorder = service->createMediaRecorder(opPackageName);
}
}
frameworks/av/media/libmedia/IMediaPlayerService.cpp
下面就是明显的binder操作,BnMediaPlayerService 定义了如下
virtual sp<IMediaRecorder> createMediaRecorder(const String16 &opPackageName) {
Parcel data, reply;
data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
data.writeString16(opPackageName);
remote()->transact(CREATE_MEDIA_RECORDER, data, &reply);
return interface_cast<IMediaRecorder>(reply.readStrongBinder());
}
MediaPlayerService继承BnMediaPlayerService
frameworks/av/media/libmediaplayerservice/MediaPlayerService.h
class MediaPlayerService : public BnMediaPlayerService
这就通过binder来到了MediaRecorderClient,可知recorder对象就是MediaRecorderClient
frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp
sp<IMediaRecorder> MediaPlayerService::createMediaRecorder(const String16 &opPackageName){
sp<MediaRecorderClient> recorder = new MediaRecorderClient(this, pid, opPackageName);
return recorder;
}
1.3 MediaRecorderClient.cpp的setAudioSource
到这里可以继续看setAudioSource了
frameworks/av/media/libmediaplayerservice/MediaRecorderClient.cpp
status_t MediaRecorderClient::setAudioSource(int as) {
return mRecorder->setAudioSource((audio_source_t)as);
}
MediaRecorderBase *mRecorder;
mRecorder为MediaRecorderBase实例,StagefrightRecorder继承于MediaRecorderBase,这里继续看StagefrightRecorder
frameworks/av/media/libmediaplayerservice/StagefrightRecorder.cpp
struct StagefrightRecorder : public MediaRecorderBase {
status_t StagefrightRecorder::setAudioSource(audio_source_t as) {
if (as == AUDIO_SOURCE_DEFAULT) {
mAudioSource = AUDIO_SOURCE_MIC;
} else {
mAudioSource = as;
}
}
}
StagefrightRecorder中会根据mAudioSource去创建audioSource……
sp<MediaCodecSource> StagefrightRecorder::createAudioSource() {
sp<AudioSource> audioSource = AVFactory::get()->createAudioSource(
}
frameworks/av/media/libavextensions/stagefright/AVFactory.cpp
AudioSource* AVFactory::createAudioSource(
return new AudioSource(inputSource, opPackageName, sampleRate,
channels, outSampleRate, clientUid, clientPid);
}
AudioSource中有创建了AudioRecord
frameworks/av/media/libstagefright/AudioSource.cpp
mRecord = new AudioRecord(inputSource, sampleRate, AUDIO_FORMAT_PCM_16_BIT,
以下代码在AudioRecord的构造方法中,inputsource是我们上边传入的参数。
frameworks/av/media/libmedia/AudioRecord.cpp
mStatus = set(inputSource, sampleRate, format, channelMask, frameCount, cbf, user,
notificationFrames, false /*threadCanCallJava*/, sessionId, transferType, flags,
uid, pid, pAttributes);
//set方法
set(){
if (pAttributes == NULL) {
mAttributes.source = inputSource;
}
}
mAttributes应用在openRecord_l方法中,可以看到AudioSystem调用了getInputForAttr
status_t AudioRecord::openRecord_l(const Modulo<uint32_t> &epoch, const String16& opPackageName) {
status = AudioSystem::getInputForAttr(&mAttributes, &input,mSessionId,mClientPid,mClientUid,mSampleRate, mFormat, mChannelMask,
mFlags, mSelectedDeviceId);
}
frameworks/av/media/libmedia/AudioSystem.cpp
status_t AudioSystem::getInputForAttr(const audio_attributes_t *attr,) {
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) return NO_INIT;
return aps->getInputForAttr(
attr, input, session, pid, uid,
samplingRate, format, channelMask, flags, selectedDeviceId);
}
frameworks/av/media/libmedia/IAudioPolicyService.cpp
重点关注aps,是IAudioPolicyService。点进去发现又是binder
virtual status_t getInputForAttr(const audio_attributes_t *attr,){
status_t status = remote()->transact(GET_INPUT_FOR_ATTR, data, &reply);
}
frameworks/av/services/audiopolicy/service/AudioPolicyService.h
class AudioPolicyService :
public BinderService<AudioPolicyService>,
public BnAudioPolicyService,
AudioPolicyService 继承 BnAudioPolicyService,BnAudioPolicyService实现于 AudioPolicyInterface,AudioPolicyManager又继承AudioPolicyInterface。终于来到了AudioPolicyManager.cpp
1.4 AudioPolicyManager.cpp中的策略
frameworks/av/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
device = getDeviceAndMixForInputSource(inputSource, &policyMix);
*input = getInputForDevice(device, address, session, uid, inputSource,
samplingRate, format, channelMask, flags,
policyMix);
audio_devices_t AudioPolicyManager::getDeviceForInputSource(audio_source_t inputSource) {
for (size_t routeIndex = 0; routeIndex < mInputRoutes.size(); routeIndex++) {
sp<SessionRoute> route = mInputRoutes.valueAt(routeIndex);
if (inputSource == route->mSource && route->isActive()) {
return route->mDeviceDescriptor->type();
}
}
return mEngine->getDeviceForInputSource(inputSource);
}
以下为具体策略
frameworks/av/services/audiopolicy/enginedefault/src/Engine.cpp
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;
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) { //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_DEVICE) {//usb
device = AUDIO_DEVICE_IN_USB_DEVICE;
} else if (availableDeviceTypes & AUDIO_DEVICE_IN_BUILTIN_MIC) { //手机自带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<AudioOutputDescriptor> 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_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_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;
}
Android-MediaRecorder之setAudioSource
[Android两种改变音频输出/入设备的方式
=
边栏推荐
- 第3章业务功能开发(实现记住账号密码)
- On Apache Doris Fe processing query SQL source code analysis
- SIGGRAPH 2022最佳技术论文奖重磅出炉!北大陈宝权团队获荣誉提名
- Solidity 开发环境搭建
- 本周小贴士#141:注意隐式转换到bool
- 从DevOps到MLOps:IT工具怎样向AI工具进化?
- The server is completely broken and cannot be repaired. How to use backup to restore it into a virtual machine without damage?
- 【TPM2.0原理及应用指南】 9、10、11章
- [video / audio data processing] Shanghai daoning brings you elecard download, trial and tutorial
- Enum + Validation 的个人最佳实践 demo 分享
猜你喜欢
随机推荐
字符串 - string(Lua)
本周小贴士131:特殊成员函数和`= default`
【网络攻防原理与技术】第3章:网络侦察技术
99% of users often make mistakes in power Bi cloud reports
How to mount the original data disk without damage after the reinstallation of proxmox ve?
Skimage learning (3) -- adapt the gray filter to RGB images, separate colors by immunohistochemical staining, and filter the maximum value of the region
Seaborn data visualization
【饭谈】如何设计好一款测试平台?
Sator推出Web3遊戲“Satorspace” ,並上線Huobi
mysql使用笔记一
User defined view essential knowledge, Android R & D post must ask 30+ advanced interview questions
The mail server is listed in the blacklist. How to unblock it quickly?
从DevOps到MLOps:IT工具怎样向AI工具进化?
2021-06-28
L1-023 输出GPLT(Lua)
VSCode关于C语言的3个配置文件
鲲鹏开发者峰会2022 | 麒麟信安携手鲲鹏共筑计算产业新生态
Leetcode brush questions day49
第二十四届中国科协湖南组委会调研课题组一行莅临麒麟信安调研考察
赋能智慧电力建设 | 麒麟信安高可用集群管理系统,保障用户关键业务连续性