当前位置:网站首页>Audio device strategy audio device output and input selection is based on 7.0 code
Audio device strategy audio device output and input selection is based on 7.0 code
2022-07-07 17:36:00 【QXXXD】
The archive , I don't want to stay here , Not much All in Enginee.cpp It says in the
1. Output selection
Overall process
First, we will get the current collection of devices availableOutputDevices
And then according to the incoming strategty Type to match
Before selecting, it will check whether it is under special circumstances ( If on the phone )
Finally, match the equipment according to priority .
The strategy for audio device selection is defined in AudioPolicyManager Medium getDeviceForStrategy() Method , The most suitable equipment will be selected according to the current equipment status and connected equipment , The concrete realization is frameworks/av/services/audiopolicy/enginedefault/src/Engine.cpp in .
The following notes explain clearly , Parameter is strategy and fromCache, If fromCache = true, From mDeviceForStrategy[] choice , Otherwise keep going down .
mDeviceForStrategy[NUM_STRATEGIES] Is an array .
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 The specific implementation of
frameworks/av/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
The following logic involves getDeviceForStrategy Call to
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); // Still call 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);
}
The concrete realization is Engine.cpp in
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 in the light of STRATEGY_MEDIA analysis , The priority of playback device is as follows
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES( Ordinary Bluetooth headset )
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER( Bluetooth speaker ) // This place belongs to setForceUse Forced queue jumping (if FORCE_SPEAKER)AUDIO_DEVICE_OUT_SPEAKER( The speaker )
- AUDIO_DEVICE_OUT_WIRED_HEADPHONE( Regular headphones , I can only listen to , Can't manipulate the playback )
- AUDIO_DEVICE_OUT_LINE
- AUDIO_DEVICE_OUT_WIRED_HEADSET( Line control earphone )
- AUDIO_DEVICE_OUT_USB_HEADSET(USB The headset )
case STRATEGY_MEDIA: {
uint32_t device2 = AUDIO_DEVICE_NONE;
if (isInCall() && (device == AUDIO_DEVICE_NONE)) { // For calls
// when in call, get the device for Phone strategy
device = getDeviceForStrategy(STRATEGY_PHONE);
break;
}
if (strategy != STRATEGY_SONIFICATION) {// And tips for special treatment
// 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; // Bluetooth headset
}
if (device2 == AUDIO_DEVICE_NONE) {
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER; // Bluetooth speakers
}
}
if ((device2 == AUDIO_DEVICE_NONE) &&
(mForceUse[AUDIO_POLICY_FORCE_FOR_MEDIA] == AUDIO_POLICY_FORCE_SPEAKER)) {// If force speker The speaker horn
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER;
}
if (device2 == AUDIO_DEVICE_NONE) {
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_WIRED_HEADPHONE; // Ordinary wired headphones Without a microphone
}
if (device2 == AUDIO_DEVICE_NONE) {
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_LINE;
}
if (device2 == AUDIO_DEVICE_NONE) {
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_WIRED_HEADSET; // Wired headset with microphone
}
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 equipment
}
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; // Exorcism The speaker horn
}
int device3 = AUDIO_DEVICE_NONE;
if (strategy == STRATEGY_MEDIA) {/// If arc,spdif,aux_line You can use , Assign a value to 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. Input selection
Audio Device Strategy Audio devices Input selection 7.0
1. Input device selection
1.1 MediaRecorder java layer setAudioSource
With MediaRecorder For example , Don't think about anything else .setAudioSource Set input source
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);// Set up the microphone
frameworks/base/media/java/android/media/MediaRecorder.java
AudioSource The following categories are defined
/** Default audio source **/
public static final int DEFAULT = 0; // Default
/** Microphone audio source */
public static final int MIC = 1; // mike
/** Voice call uplink (Tx) audio source */
public static final int VOICE_UPLINK = 2; // The phone goes up
/** Voice call downlink (Rx) audio source */
public static final int VOICE_DOWNLINK = 3; // The phone goes down
/** Voice call uplink + downlink audio source */
public static final int VOICE_CALL = 4; // Telephone recording
/** Microphone audio source with same orientation as camera if available, the main
* device microphone otherwise */
public static final int CAMCORDER = 5; // Camera Mike
public static final int VOICE_RECOGNITION = 6; // speech recognition
public static final int VOICE_COMMUNICATION = 7;// Internet phone
public static final int REMOTE_SUBMIX = 8; // For recording
public static final int UNPROCESSED = 9; // Raw sound not processed
@SystemApi
public static final int RADIO_TUNER = 1998; // radio broadcast
@SystemApi
public static final int HOTWORD = 1999;
Continue to look at MediaRecorder
public native void setAudioSource(int audio_source)
throws IllegalStateException;
adopt JNI Call to 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 Who is it?
Looking at mMediaRecorder example , It's a IMediaPlayerService Of service object , Called 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
Here is the obvious binder operation ,BnMediaPlayerService It is defined as follows
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 Inherit BnMediaPlayerService
frameworks/av/media/libmediaplayerservice/MediaPlayerService.h
class MediaPlayerService : public BnMediaPlayerService
This is through binder Arrived MediaRecorderClient, You know recorder Object is 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 Of setAudioSource
Here you can continue to see setAudioSource 了
frameworks/av/media/libmediaplayerservice/MediaRecorderClient.cpp
status_t MediaRecorderClient::setAudioSource(int as) {
return mRecorder->setAudioSource((audio_source_t)as);
}
MediaRecorderBase *mRecorder;
mRecorder by MediaRecorderBase example ,StagefrightRecorder Inherited from MediaRecorderBase, Here we continue to see 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 According to mAudioSource To create 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 Has created AudioRecord
frameworks/av/media/libstagefright/AudioSource.cpp
mRecord = new AudioRecord(inputSource, sampleRate, AUDIO_FORMAT_PCM_16_BIT,
The following code is AudioRecord In the construction method of ,inputsource It's the parameter we passed in above .
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 Method
set(){
if (pAttributes == NULL) {
mAttributes.source = inputSource;
}
}
mAttributes Apply to openRecord_l In the method , You can see AudioSystem Called 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
Focus on aps, yes IAudioPolicyService. Click in and find it again 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 Inherit BnAudioPolicyService,BnAudioPolicyService To achieve in AudioPolicyInterface,AudioPolicyManager Inherit again AudioPolicyInterface. Finally came AudioPolicyManager.cpp
1.4 AudioPolicyManager.cpp Strategy in
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);
}
Here are the specific strategies
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) && // If Bluetooth is forced Priority Bluetooth headset
(availableDeviceTypes & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET)) {
device = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET;
} else if (availableDeviceTypes & AUDIO_DEVICE_IN_WIRED_HEADSET) {// Wired Bluetooth
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) { // Mobile phone comes with 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 And setAudioSource
[Android Two ways to change the audio output / How to enter the equipment
=
边栏推荐
猜你喜欢
【可信计算】第十二次课:TPM授权与会话
Skimage learning (2) -- RGB to grayscale, RGB to HSV, histogram matching
【TPM2.0原理及应用指南】 9、10、11章
第3章业务功能开发(用户登录)
99%的人都不知道|私有化部署还永久免费的即时通讯软件!
Sator launched Web3 game "satorspace" and launched hoobi
Matplotlib绘图界面设置
让保险更“保险”!麒麟信安一云多芯云桌面中标中国人寿, 助力金融保险信息技术创新发展
alertDialog創建对话框
Is AI more fair than people in the distribution of wealth? Research on multiplayer game from deepmind
随机推荐
阿富汗临时政府安全部队对极端组织“伊斯兰国”一处藏匿点展开军事行动
Flask build API service SQL configuration file
电脑无法加域,ping域名显示为公网IP,这是什么问题?怎么解决?
责任链模式 - Unity
【网络攻防原理与技术】第4章:网络扫描技术
mysql官网下载:Linux的mysql8.x版本(图文详解)
使用 xml资源文件定义菜单
【可信计算】第十次课:TPM密码资源管理(二)
How to add aplayer music player in blog
字符串 - string(Lua)
专精特新软件开发类企业实力指数发布,麒麟信安荣誉登榜
NeRF:DeepFake的最终替代者?
第3章业务功能开发(安全退出)
Seaborn data visualization
【源码解读】| LiveListenerBus源码解读
LeetCode 648(C#)
Solidity 开发环境搭建
actionBar 导航栏学习
防火墙系统崩溃、文件丢失的修复方法,材料成本0元
DevOps 的运营和商业利益指南