Audio Device Strategy 音频设备输出输入 选择 基于7.0 代码
Posted QXXXD
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Audio Device Strategy 音频设备输出输入 选择 基于7.0 代码相关的知识,希望对你有一定的参考价值。
存档,不想留本地了,没啥含量 都在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两种改变音频输出/入设备的方式
=
以上是关于Audio Device Strategy 音频设备输出输入 选择 基于7.0 代码的主要内容,如果未能解决你的问题,请参考以下文章
USB AUDIO Device CLASS Requests
深入浅出蓝牙低功耗音频BLE Audio--4 ISO音频流
Failed to open the file:SDL_OpenAudio:DirectSoundCreate:NO audio device found 视频报错这是啥情况