Android N Telecom对Audio的管理
Android N,对通话时Audio的管理与M相比发生了比较大的变化,主要是引入了状态机。
CallAudioManager
首先是保留的M上的一个类CallAudioManager,通过名字就能知道是管理Audio的,也就是管理铃声,外放,语音,耳机等。
首先它继承了CallsManagerListenerBase,也就是说会监听CallsManager中Call的变化。
public class CallAudioManager extends CallsManagerListenerBase
然后构造函数,看它都管理什么
public CallAudioManager(CallAudioRouteStateMachine callAudioRouteStateMachine,
CallsManager callsManager,
CallAudioModeStateMachine callAudioModeStateMachine,
InCallTonePlayer.Factory playerFactory,
Ringer ringer,
RingbackPlayer ringbackPlayer,
DtmfLocalTonePlayer dtmfLocalTonePlayer) {
mActiveDialingOrConnectingCalls = new LinkedHashSet<>();
mRingingCalls = new LinkedHashSet<>();
mHoldingCalls = new LinkedHashSet<>();
mCalls = new HashSet<>();
mCallStateToCalls = new SparseArray<LinkedHashSet<Call>>() {
{
put(CallState.CONNECTING, mActiveDialingOrConnectingCalls);
put(CallState.ACTIVE, mActiveDialingOrConnectingCalls);
put(CallState.DIALING, mActiveDialingOrConnectingCalls);
put(CallState.RINGING, mRingingCalls);
put(CallState.ON_HOLD, mHoldingCalls);
}};
mCallAudioRouteStateMachine = callAudioRouteStateMachine;
mCallAudioModeStateMachine = callAudioModeStateMachine;
mCallsManager = callsManager;
mPlayerFactory = playerFactory;
mRinger = ringer;
mRingbackPlayer = ringbackPlayer;
mDtmfLocalTonePlayer = dtmfLocalTonePlayer;
mPlayerFactory.setCallAudioManager(this);
mCallAudioModeStateMachine.setCallAudioManager(this);
}
可以看到首先是初始化了很多的变量,包括各种Call的集合,并且通过mCallStateToCalls可以根据Call的状态拿到不同的Call。播放铃声或者其他声音的mPlayerFactory,mRinger,mRingbackPlayer,mDtmfLocalTonePlayer。两个非常重要的状态机mCallAudioRouteStateMachine,mCallAudioModeStateMachine。
因为它继承了CallsManagerListenerBase并且记录非常多的Call,所以可以认为它很多的工作都是与Call的变化相关的,我们以CallsManagerListenerBase中的方法为线索看看它都干了什么
onCallAdded()
这个方法看起来很简单,就这么几行代码,看看具体干了什么?
@Override
public void onCallAdded(Call call) {
if (shouldIgnoreCallForAudio(call)) {
return; // Don't do audio handling for calls in a conference, or external calls.
}
addCall(call);
}
首先是shouldIgnoreCallForAudio(Call call),看名字就知道是否要忽略这个Call,它的代码也是非常简单:忽略conference或者external的Call
private boolean shouldIgnoreCallForAudio(Call call) {
return call.getParentCall() != null || call.isExternalCall();
}
然后就是这个addCall(Call call)
private void addCall(Call call) {
// 略
if (mCallStateToCalls.get(call.getState()) != null) {
mCallStateToCalls.get(call.getState()).add(call);
}
updateForegroundCall();
mCalls.add(call);
on