本文主要介绍介绍一下在Android6.0中,InCallActivity界面上控制speaker开关的一些逻辑和方法,可以让我们大体了解speaker的变化形式,对在通话过程中speaker变化有所了解。
先来看看两张大图
图一
上图主要介绍了CallAudioManager这个类,最终会调用turnOnSpeaker这个方法去打开或者关闭speaker,上图主要画了涉及到调用turnOnSpeaker这个方法的其它方法,通过方法名字我们可以知道,call的添加删除,蓝牙、有线耳机这些的连接断开,call状态的更新,等等方法都有可能触发turnOnSpeaker从而影响到speaker的状态。
图二
上图主要介绍了InCallAudioManager和VideoCallPresenter这两个类,InCallAudioManager是Android6.0新增的类,从名字我们就可以看出这个类主要是在通话过程中对audio的管理
/**
* This class implements QTI audio routing policy for upgrade/downgrade/merge call use cases
* based on the audio policy below.
*
* Audio policy for any user initiated action like making a video call, accepting an upgrade
* request or sending an upgrade/downgrade request is as follows : If any of the above user actions
* indicate a transition to a video call, we route audio to SPEAKER. If any of the above user
* actions indicate a voice call, we route to EARPIECE. For all other non-user initiated actions
* like an incoming downgrade request, we don't change the audio path and respect user's choice.
* For merge calls, we route to SPEAKER only if one of the calls being merged is a video call.
*
* Audio path routing for outgoing calls, incoming calls, add call and call waiting are handled
* in Telecom layer. Same audio policy is followed for those as well. Any user initiated action
* indicating a origin/acceptance of video call routes audio to SPEAKER or to EARPIECE for voice
* calls.
*/
public class InCallAudioManager {
VideoCallPresenter这个类其实就是MVP模式中的P,主要是关于videocall相关的逻辑处理,上图主要的两个方法是enableSpeaker 开启speaker,和enableEarpiece 开启听筒(即关闭speaker),通过这两个函数的调用,在VT call的时候控制speaker的开关,其它的方法都是在某些特定的情况下会涉及到这两个方法,比如:通话的升降级(voice升vido)、通话的merge(会议通话)、VT call状态的改变等等。
CallAudioState 的状态有一下几种
public final class CallAudioState implements Parcelable {
/** Direct the audio stream through the device's earpiece. */
public static final int ROUTE_EARPIECE = 0x00000001;
/** Direct the audio stream through Bluetooth. */
public static final int ROUTE_BLUETOOTH = 0x00000002;
/** Direct the audio stream through a wired headset. */
public static final int ROUTE_WIRED_HEADSET = 0x00000004;
/** Direct the audio stream through the device's speakerphone. */
public static final int ROUTE_SPEAKER = 0x00000008;
/**
* Direct the audio stream through the device's earpiece or wired headset if one is
* connected.
*/
public static final int ROUTE_WIRED_OR_EARPIECE = ROUTE_EARPIECE | ROUTE_WIRED_HEADSET;
/** Bit mask of all possible audio routes. */
private static final int ROUTE_ALL = ROUTE_EARPIECE | ROUTE_BLUETOOTH | ROUTE_WIRED_HEADSET |
ROUTE_SPEAKER;
重要的log信息
07-26 16:49:38.545 29709 29709 V Telecom : CallAudioManager: onCallAdded //添加一个call
07-26 16:49:38.545 29709 29709 I Telecom : CallAudioManager: updateAudioStreamAndMode : mIsRinging: false, mIsTonePlaying: false, call: [25159400, CONNECTING, null, tel:138%208011%208404, A, childs(0), has_parent(false), [[Capabilities:]], false, ComponentInfo{com.android.phone/com.android.services.telephony.TelephonyConnectionService}, 1, UserHandle{0}]
07-26 16:49:38.555 29709 29709 V Telecom : CallAudioManager: updateAudioStreamAndMode : foreground //当前存在一个呼叫选择
07-26 16:49:38.555 29709 29709 V Telecom : CallAudioManager: requestAudioFocusAndSetMode : stream: STEAM_NONE -> STREAM_VOICE_CALL, mode: MODE_IN_CALL //请求的目的
07-26 16:49:38.556 29709 29709 I Telecom : CallAudioManager: requestAudioFocusAndSetMode : requesting stream: STEAM_NONE -> STREAM_VOICE_CALL //请求audiomode从STEAM_NONE变为STREAM_VOICE_CALL
07-26 16:49:38.558 29709 29709 I Telecom : Event: Call 2: AUDIO_ROUTE, EARPIECE
07-26 16:49:52.271 29709 29720 I Telecom : CallAudioManager: setSystemAudioState: changing from [AudioState isMuted: false, route: EARPIECE, supportedRouteMask: EARPIECE, SPEAKER] to [AudioState isMuted: false, route: SPEAKER, supportedRouteMask: EARPIECE, SPEAKER]
07-26 16:49:52.271 29709 29720 I Telecom : Event: Call 2: AUDIO_ROUTE, SPEAKER //手动切换到speaker
07-26 16:50:08.123 6097 6097 D InCall : VideoCallPresenter - enterVideoMode videoCall= android.telecom.VideoCallImpl@be1a1ed videoState: 3 //进入视频模式
07-26 16:50:08.184 6097 6097 D InCall : VideoCallPresenter - Routing audio to speaker //将audio变成speaker模式
07-26 16:50:47.938 6097 6097 D InCall : VideoCallPresenter - exitVideoMode //退出视频模式
07-26 16:50:52.982 6097 6097 D InCall : VideoCallPresenter - enterVideoMode videoCall= android.telecom.VideoCallImpl@be1a1ed videoState: 3
07-26 16:50:53.667 6097 6097 D InCall : VideoCallPresenter - exitVideoMode
07-26 16:51:14.533 29709 30406 V Telecom : CallAudioManager: onCallRemoved
07-26 16:51:14.534 29709 30406 V Telecom : CallAudioManager: all calls removed, resetting system audio to default state
07-26 16:51:14.534 29709 30406 I Telecom : CallAudioManager: setInitialAudioState : audioState = [AudioState isMuted: false, route: EARPIECE, supportedRouteMask: EARPIECE, SPEAKER], call = null
07-26 16:51:14.534 29709 30406 I Telecom : CallAudioManager: setSystemAudioState: changing from [AudioState isMuted: false, route: SPEAKER, supportedRouteMask: EARPIECE, SPEAKER] to [AudioState isMuted: false, route: EARPIECE, supportedRouteMask: EARPIECE, SPEAKER] //设置speaker