Android 7.0 Audio :通话中的音频调用接口
来源:互联网 发布:caj阅读器for mac 编辑:程序博客网 时间:2024/05/11 05:30
对于Audio在通话中的处理,根据不同的功能,有不同的调用路径,
1) 通话中 打开speaker 流程 enableSpeaker
对于在通话中打开扬声器,走图示1的调用路径,
在telephony部分,调用流程如下,
InCallAudioManager. enableSpeaker--telecomAdapter.setAudioRoute(CallAudioState.ROUTE_SPEAKER)/binderIPC-- mInCallService.setAudioRoute(route);-- mPhone.setAudioRoute(route);-- mInCallAdapter.setAudioRoute(route);--mAdapter.setAudioRoute(route);/binder IPC--…--CallsManager.
setAudioRoute --mCallAudioManager.setAudioRoute(route)--CallAudioRouteStateMachine.sendMessageWithSessionInfo / CallAudioRouteStateMachine.USER_SWITCH_SPEAKER/--通过ActiveSpeakerRoute向下..—setSpeakerphoneOn-- mAudioManager.setSpeakerphoneOn(on)
这样,就到了Audio系统了,根据之前的章节,就知道接下来就是AM/AService/ASystem了,
AudioManager.setSpeakerphoneOn/ binder IPC--setSpeakerphoneOn --/ mForcedUseForComm = AudioSystem.FORCE_SPEAKER / sendMsg(mAudioHandler,MSG_SET_FORCE_USE, SENDMSG_QUEUE,
AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, null, 0) /内部handler--setForceUse --setForceUseInt_SyncDevices -- AudioSystem.setForceUse/jni-AudioSystem::setForceUse
在native部分的调用流程如下,
AudioSystem::setForceUse--AudioPolicyService::setForceUse(AudioPolicyInterfaceImpl.cpp)--AudioPolicyManager::setForceUse
APM处理部分如下,
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void AudioPolicyManager::setForceUse(audio_policy_force_use_t usage,
audio_policy_forced_cfg_t config)
{
if (mEngine->setForceUse(usage, config) != NO_ERROR) {
ALOGW("setForceUse() could not set force cfg %d for usage %d", config, usage);
return;
}
checkA2dpSuspend();
checkOutputForAllStrategies();
updateDevicesAndOutputs();
if (mEngine->getPhoneState() == AUDIO_MODE_IN_CALL && hasPrimaryOutput()) {
audio_devices_t newDevice = getNewOutputDevice(mPrimaryOutput, true /*fromCache*/);
updateCallRouting(newDevice);
}
for (size_t i = 0; i < mOutputs.size(); i++) {
sp<SwAudioOutputDescriptor> outputDesc = mOutputs.valueAt(i);
audio_devices_t newDevice = getNewOutputDevice(outputDesc, true /*fromCache*/);
if ((mEngine->getPhoneState() != AUDIO_MODE_IN_CALL) || (outputDesc != mPrimaryOutput)) {
setOutputDevice(outputDesc, newDevice, (newDevice != AUDIO_DEVICE_NONE));
}
if (forceVolumeReeval && (newDevice != AUDIO_DEVICE_NONE)) {
applyStreamVolumes(outputDesc, newDevice, 0, true);
}
}
audio_io_handle_t activeInput = mInputs.getActiveInput();
if (activeInput != 0) {
sp<AudioInputDescriptor> activeDesc = mInputs.valueFor(activeInput);
audio_devices_t newDevice = getNewInputDevice(activeInput);
// Force new input selection if the new device can not be reached via current input
if (activeDesc->mProfile->getSupportedDevices().types() & (newDevice & ~AUDIO_DEVICE_BIT_IN)) {
setInputDevice(activeInput, newDevice);
} else {
closeInput(activeInput);
}
}
}
a)mEngine->setForceUse
实现在Engine.cpp里面,主要是判断当前对设备设置是否合逻辑,并给mForceUse的成员赋值。
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
status_t Engine::setForceUse(audio_policy_force_use_t usage, audio_policy_forced_cfg_t config)
{
switch(usage) {
case AUDIO_POLICY_FORCE_FOR_COMMUNICATION:
if (config != AUDIO_POLICY_FORCE_SPEAKER && config != AUDIO_POLICY_FORCE_BT_SCO &&
config != AUDIO_POLICY_FORCE_NONE) {
ALOGW("setForceUse() invalid config %d for FOR_COMMUNICATION", config);
return BAD_VALUE;
}
mForceUse[usage] = config;
break;
b)checkA2dpSuspend
checkA2dpSuspend--AudioPolicyService::AudioPolicyClient::suspendOutput--AudioFlinger::suspendOutput--thread->suspend
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void suspend() { (void) android_atomic_inc(&mSuspended); }
最终是给&mSuspended赋值。
c)checkOutputForStrategy 根据策略类型和当前设置获取设备类型,并最input和output进行处理,最后invalidateStream。
其中,
AudioPolicyManager::checkOutputForStrategy--audio_devices_tAudioPolicyManager::getDeviceForStrategy--mEngine->getDeviceForStrategy,
Engine.cpp里,
根据strategy为STRATEGY_PHONE,以及刚刚设置的mForceUse[AUDIO_POLICY_FORCE_FOR_COMMUNICATION]为AUDIO_POLICY_FORCE_SPEAKER,匹配到正确的设备类型,刚好为AUDIO_DEVICE_OUT_SPEAKER,
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
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();
switch (strategy) {
case STRATEGY_PHONE:
switch (mForceUse[AUDIO_POLICY_FORCE_FOR_COMMUNICATION]) {
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
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER;
break;
}
break;
d)之后是updateCallRouting,设置device的操作。
2)dtmf音
在telephony模块,调用流程(这里只分析了声音播放,并不包含信令处理)
CallsManager.playDtmfTone --DtmfLocalTonePlayer .playTone--mToneGenerator.startTone
在Audio模块,调用流程
ToneGenerator.startTone--jni--android_media_ToneGenerator_startTone--ToneGenerator::startTone
ToneGenerator则直接使用了AT,先initAudioTrack创建AT实例,prepareWave生成PCM数据,再mpAudioTrack->start()开始,
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool ToneGenerator::startTone(tone_type toneType, int durationMs) {
toneType = getToneForRegion(toneType);
if (mState == TONE_IDLE) {
ALOGV("startTone: try to re-init AudioTrack");
if (!initAudioTrack()) {
return lResult;
}
}
if (mState == TONE_INIT) {
if (prepareWave()) {
ALOGV("Immediate start, time %d", (unsigned int)(systemTime()/1000000));
lResult = true;
mState = TONE_STARTING;
if (clock_gettime(CLOCK_MONOTONIC, &mStartTime) != 0) {
mStartTime.tv_sec = 0;
}
mLock.unlock();
mpAudioTrack->start();
…
}
mLock.unlock();
}
可以看到,initAudioTrack创建AT实例时,使用了AUDIO_OUTPUT_FLAG_FAST的方式播放,通过audioCallback回调完成数据填充。
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool ToneGenerator::initAudioTrack() {
// Open audio track in mono, PCM 16bit, default sampling rate, default buffer size
mpAudioTrack = new AudioTrack();
ALOGV("Create Track: %p", mpAudioTrack.get());
mpAudioTrack->set(mStreamType,
0, // sampleRate
AUDIO_FORMAT_PCM_16_BIT,
AUDIO_CHANNEL_OUT_MONO,
0, // frameCount
AUDIO_OUTPUT_FLAG_FAST,
audioCallback,
this, // user
0, // notificationFrames
0, // sharedBuffer
mThreadCanCallJava,
AUDIO_SESSION_ALLOCATE,
AudioTrack::TRANSFER_CALLBACK);
if (mpAudioTrack->initCheck() != NO_ERROR) {
ALOGE("AudioTrack->initCheck failed");
goto initAudioTrack_exit;
}
mpAudioTrack->setVolume(mVolume);
mState = TONE_INIT;
return true;
initAudioTrack_exit:
ALOGV("Init failed: %p", mpAudioTrack.get());
// Cleanup
mpAudioTrack.clear();
return false;
}
这条通道走的是AF的路径,并不在上图的三个path之中。
3)标记3的场景有,Telephony向Audio设置当前是通话状态,这个会用setMode (MODE_INCALL);向Audio设置当前是VOICE通话还是LTE通话,这个会用AudioSystem::setParameters(),
vendor\qcom\proprietary\qcril\qcril_qmi\qcril_am.cc
- Android 7.0 Audio :通话中的音频调用接口
- 【Android 7.0 Audio】:通话中的音频调用接口
- android audio/linux alsa音频-应用与驱动的接口
- [Audio] Android音频数据传输
- Android 音频焦点(Audio Focus)
- Android Audio 音频输出设备切换
- Android 音频焦点(Audio Focus)
- Android 音频焦点(Audio Focus)
- Android Audio 音频输出设备切换
- Android 音频焦点(Audio Focus)
- Android--Audio播放:竞争Audio之Audio Focus 音频焦点
- android中Sip音频通话调研结果
- android Audio 应用接口
- 音频基础 DAI:Digital Audio Interfaces(音频设备的硬件接口 codec android)
- 掌握HTML5中的多媒体--音频(audio)
- 掌握HTML5中的多媒体--音频(audio)
- 掌握HTML5中的多媒体--音频(audio)
- stream audio on android 音频流 android
- 阿拉伯语状态下TextView如何从右往左显示
- enjoy summer the many year
- 矩阵求逆
- 微信小程序-wx:key理解
- JS组件系列——表格组件神器:bootstrap table(二)
- Android 7.0 Audio :通话中的音频调用接口
- 经典算法(4):K最近邻算法(KNN)
- nginx安装 卸载 虚拟主机 负载均衡
- git format-patch
- JS组件系列——表格组件神器:bootstrap table(三)
- 【Lombok】lombok使用教程
- Android手机监视网络状态的变化--关于权限的一个小问题
- HDU-2054 A==B?
- props数据传递