Call(通话)相关的内容也是属于Telephony模块,Call整体上可以分成两类:
1. CS call,其中CS全称是Circuit Switch,我们平常打电话走的就是CS的流程。
2. IMS PS call,其中PS全称是Packet Switch,走IMS流程的Call有4类,分别是VoLTE(voice over LTE),ViLTE(video over LTE),VoWiFi(voice over wifi),ViWiFi(video over wifi)。
在分析具体的MT(Mobile Termination Call 被叫)/MO(Mobile Origination Call 主叫)流程之前,需要了解更多Call相关的基础知识,日后才可以更好地理解各种通话的流程。
而本文要讲解的就是Call.java对象。在Android源码中一共有5个“Call.java”文件,所以理清它们之间的联系以及学会如何分辨不同的Call对象,这也是分析通话流程的前提之一。
我们需要重点关注的有4个:
1. /packages/apps/Dialer/InCallUI/src/com/android/incallui/Call.java
2. /packages/services/Telecomm/src/com/android/server/telecom/Call.java
3. /frameworks/base/telecomm/java/android/telecom/Call.java
4. /frameworks/opt/telephony/src/java/com/android/internal/telephony/Call.java
整个通话流程可以细分成Dialer(InCallUI),Telecomm Framework,Telecomm Service,Telephony Service,Telephony Framework这5个模块,除了Telephony Service,其他4个模块都有一个自己的Call.java,可想而知,整个通话的过程都会伴随着对Call对象的处理。
本文来自 http://blog.csdn.net/linyongan ,转载请务必注明出处。
一、Dialer(InCallUI)中的Call
在Android N中,InCallUI已经被放置到Dialer目录之下,也许是为了更好地提醒开发者,要编译InCallUI的话,直接编译Dialer就行了。
对于InCallUI Call,
/packages/apps/Dialer/InCallUI/src/com/android/incallui/Call.java
- 1
- 1
它只是一个普通的类,没有父类也没有实现接口。
从它的构造方法来看,InCallUI Call是直接依赖Telecom Call(Telecom Framework中的Call)的
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
InCallUI Call中的State、Phone Account、ChildNumber等信息都来源于Telecom Call。
InCallUI Call被CallList管理着,CallList中有一个Map来存储InCallUI Call
- 1
- 2
- 1
- 2
InCallUI Call是在CallList的onCallAdded()方法被调用的时候创建的
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
CallList还依据Call的状态,将InCallUI Call进行分类,对外提供不同类型的Call对象
所以通过CallList获取到的Call对象都是InCallUI Call。
总结:在Dialer(InCallUI)模块中会见到两种Call对象,基本都是InCallUI Call;另外一种Call就是Telecom Call(Telecom Framework中的Call),Telecom Call会很明显地写成android.telecom.Call
,所以也是很好地分辨的。
二、Telecom Framework中的Call
Telecom Call,
/frameworks/base/telecomm/java/android/telecom/Call.java
- 1
- 1
它是一个被定义成final类型的类,它是在Phone.java (framework\base\telecomm\java\android\telecom) 的internalAddCall()方法中被创建的
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
而ParcelableCall是一个中间者的角色,在InCallController.java中先将Telecom Service中的Call转换成ParcelableCall
- 1
- 2
- 3
- 1
- 2
- 3
然后再把ParcelableCall转换成Telecom Call,这样子就实现了Telecom Service Call向Telecom Call的转变。
三、Telecom Service中的Call
Telecom Service中的Call,
/packages/services/Telecomm/src/com/android/server/telecom/Call.java
- 1
- 1
它实现了CreateConnectionResponse接口,说明它也负责Connection创建之后的一些事情的处理,比如成功创建Connection之后就需要通知UI界面刷新以及状态的更新。
Telecom Service Call是通话流程中最重要的Call对象,它拥有管理一通电话的能力(answer,reject,hold,disconnect等等),它由CallsManager创建和管理。
在通话过程中,CallsManager是这样管理Call的:
不管是MO/MT Call,都是在创建Telecom Service Call之后调用它自身的startCreateConnection()方法来发起创建Connection的动作,以及成功创建Connection之后通知UI刷新界面的处理。
Telecom Service Call每执行一项重要的动作都会输出相应的标志性log
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
log如下,以”Event: Call “为关键字:
14:16:35.776 I/Telecom (24667): Event: Call 8: REQUEST_ACCEPT, null
Telecom Service Call的状态信息源自Telephony Framework Call的State,大致流程是这样的:
1. 先由Connection获取到Telephony Framework Call的State,
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
2.接着将Connection State转换成CallState
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
3.最后由CallsManager调用setCallState()方法把Call的状态set到对应的Telecom Service Call中。
总结:这4个Call的状态转换过程就是这样子的:
Telephony Framework Call—>Telecom Service Call—>Telecom Call—> InCallUI Call.
四、Telephony Framework中的Call
Telephony Framework中的Call,
/frameworks/opt/telephony/src/java/com/android/internal/telephony/Call.java
- 1
- 1
它是一个抽象类,它的继承关系如下:
我们需要关注的是GsmCdmaCall和ImsPhoneCall。
GsmCdmaPhone,GsmCdmaCallTracker,GsmCdmaConnection,GsmCdmaCall四者关系紧密,如下图:
在GsmCdmaPhone初始化的时候会创建GsmCdmaCallTracker,GsmCdmaCallTracker负责管理GsmCdmaConnection和GsmCdmaCall,GsmCdmaCallTracker的内部有一个GsmCdmaConnection的数组:
- 1
- 1
并且有常量控制着mConnections数组数组的大小,一个GsmCdmaConnection代表着一通电话,说明GSM最大允许同时存在19通,CDMA最大同时存在8通。
- 1
- 2
- 3
- 4
- 1
- 2
- 3
- 4
同时,GsmCdmaCallTracker的内部也会创建三个GsmCdmaCall(GsmCdmaCall仅仅会在GsmCdmaCallTracker中被创建,创建之后不会再被重新赋值):
- 1
- 2
- 3
- 4
- 1
- 2
- 3
- 4
Telephony Framework Call的状态有9种:
- 1
- 2
- 3
- 1
- 2
- 3
问题1:那么mRingingCall,mForegroundCall,mBackgroundCall分别对应Call的什么状态呢?
由于Telephony Framework Call的”ACTIVE, HOLDING, DIALING, ALERTING, INCOMING, WAITING”这六种状态跟DriverCall.State是一一对应的
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
在GsmCdmaConnection中有依据DriverCall.State将GsmCdmaCall分类的方法
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
所以mRingingCall,mForegroundCall,mBackgroundCall与GsmCdmaCall.mState的关系如下:
GsmCdmaCall | GsmCdmaCall.mState |
---|---|
mRingingCall | INCOMING,WAITING |
mForegroundCall | ACTIVE,DIALING,ALERTING |
mBackgroundCall | HOLDING |
GsmCdmaCallTracker在初始化的时候就注册监听了Call状态变化的消息,
- 1
- 2
- 3
- 1
- 2
- 3
所以当modem中Call状态发生变化后,便会通知到GsmCdmaCallTracker,GsmCdmaCallTracker通过调用RILJ的getCurrentCalls()方法发起查询modem当前的Call状态列表,modem返回来的结果是DriverCall 集合。
再由GsmCdmaCallTracker的handlePollCalls()方法来对比自身mConnections集合与DriverCall 集合的差异,进而依据DriverCall的信息跟新这对应GsmCdmaCall(mRingingCall,mForegroundCall,mBackgroundCall)的状态,同时将当前GsmCdmaConnection与对应的GsmCdmaCall绑定。
整个过程时序图如下:
五、其他Call
ImsCall在/frameworks/opt/net/ims/src/java/com/android/ims/目录下,与之前介绍的Call不一样,ImsCall继承自IMS call专属的接口ICall,
- 1
- 1
ImsCall拥有处理IMS voice / video call的能力。ImsCall由ImsManager来创建,ImsManager是任意IMS actions的出发点。
原文地址: http://blog.csdn.net/linyongan/article/details/52551248