【android telecom 框架分析 02】【CallAudioModeStateMachine介绍 1】【CallAudioModeStateMachine 整体介绍】
是 Android AOSP 中负责管理电话音频模式的状态机。它根据当前通话状态(比如是否有来电、是否正在通话、是否是 VoIP 等)动态地切换 AudioManager 的音频模式,以便正确地处理音频焦点、铃声播放、通话音频等。
CallAudioModeStateMachine
1. CallAudioModeStateMachine 的功能概述
这个类基于 构建,用于管理电话系统中音频焦点(Audio Focus)和音频模式(Audio Mode)的状态。它通过以下方式工作:
StateMachine
切换状态以适应通话生命周期:
来电响铃 → 正常通话 → 保持 → 通话结束
根据当前状态设置 AudioManager 的 Mode 和焦点
控制铃声、通话音频、处理特殊场景(如 VoIP、屏幕通话、音频处理等)
2. 状态详解
2.1
UnfocusedState(未聚焦状态)
UnfocusedState
功能:
什么都不做,但占住状态。
只有等 才真正释放 AudioFocus。
AUDIO_OPERATIONS_COMPLETE
不会误释放导致音乐 app 抢到音频焦点。
场景举例: 电话应用未使用音频资源时(无通话), 或者初始状态就是 UnfocusedState。
// src/com/android/server/telecom/CallAudioModeStateMachine.java
// CallAudioModeStateMachine 构造函数
public CallAudioModeStateMachine(SystemStateHelper systemStateHelper,
AudioManager audioManager, Looper looper) {
...
createStates();
}
private void createStates() {
addState(mUnfocusedState);
addState(mRingingFocusState);
addState(mSimCallFocusState);
addState(mVoipCallFocusState);
addState(mAudioProcessingFocusState);
addState(mStreamingFocusState);
addState(mOtherFocusState);
setInitialState(mUnfocusedState); // 这里将 mUnfocusedState 设置为了初始化状态
start();
sendMessage(INITIALIZE, new MessageArgs.Builder()
.setHasActiveOrDialingCalls(false)
.setHasRingingCalls(false)
.setHasHoldingCalls(false)
.setIsTonePlaying(false)
.setForegroundCallIsVoip(false)
.setIsStreaming(false)
.setSession(Log.createSubsession())
.build());
}
private class UnfocusedState extends BaseState {
@Override
public void enter() {
Log.i(LOG_TAG, "Audio focus entering UNFOCUSED state");
mLocalLog.log("Enter UNFOCUSED");
if (mIsInitialized) {
mCallAudioManager.setCallAudioRouteFocusState(CallAudioRouteStateMachine.NO_FOCUS);
mAudioManager.setMode(AudioManager.MODE_NORMAL); // 这里会设置当前 Audio 为 MODE_NORMAL 状态, 代表:
mLocalLog.log("Mode MODE_NORMAL");
mMostRecentMode = AudioManager.MODE_NORMAL;
// Don't release focus here -- wait until we get a signal that any other audio
// operations triggered by this are done before releasing focus.
}
}
这里会设置当前 Audio 为 MODE_NORMAL 状态, 代表:
正常音频模式(非铃声状态且无通话建立),如音乐播放、视频播放等场景
1. 状态切换
public boolean processMessage(Message msg) {
if (super.processMessage(msg) == HANDLED) {
// 这里会首先调用 BaseState.processMessage 处理, 如果 BaseState.processMessage 无法处理, 才会在 UnfocusedState.processMessage 中处理
return HANDLED;
}
MessageArgs args = (MessageArgs) msg.obj;
switch (msg.what) {
case NO_MORE_ACTIVE_OR_DIALING_CALLS:
// Do nothing.
return HANDLED;
case NO_MORE_RINGING_CALLS:
// Do nothing.
return HANDLED;
case NO_MORE_HOLDING_CALLS:
// Do nothing.
return HANDLED;
case NO_MORE_AUDIO_PROCESSING_CALLS:
// Do nothing.
return HANDLED;
case NEW_ACTIVE_OR_DIALING_CALL: // 此时如果有活跃的电话,或者正在拨号
transitionTo(args.foregroundCallIsVoip
? mVoipCallFocusState : mSimCallFocusState); // 如果是网络电话将 切换到 VoipCallFocusState , 如果是 普通的电话 切换到 SimCallFocusState
return HANDLED;
case NEW_RINGING_CALL:
transitionTo(mRingingFocusState); // 如果此时来电 , 将切入 RingingFocusState
return HANDLED;
case NEW_AUDIO_PROCESSING_CALL: // 有新的通话正在进行前处理, 将切入 AudioProcessingFocusState
transitionTo(mAudioProcessingFocusState);
return HANDLED;
case NEW_HOLDING_CALL:
// This really shouldn't happen, but transition to the focused state anyway.
Log.w(LOG_TAG, "Call was surprisingly put into hold from an unknown state." +
" Args are:
" + args.toString());
transitionTo(mOtherFocusState); // 有通话被保持 ,将进入 OtherFocusState
return HANDLED;
case START_CALL_STREAMING:
transitionTo(mStreamingFocusState); // 开始音频流传输 ,将进入 StreamingFocusState
return HANDLED;
case<
© 版权声明
文章版权归作者所有,未经允许请勿转载。
相关文章
暂无评论...



