四 SipPhone
如下是SipPhone实现相关类图。
SipPhone对象虽然也派生自PhoneBase,但实现机制及实例化过程与其它Phone对象大大不同。
SipPhone对象的实例化通过PhoneFactory的makeSipPhone的接口调用SipPhoneFactory的makePhone进行实例化。SipPhone对象的实例化调用也不是在PhoneApp对象中进行,而是在默认电话应用的SipBroadcastReceiver对象的onReceive回调函数或者SipCallOptionHandler对象的createSipPhoneIfNeeded函数中被调用,另外不同的是对SipPhone对象的创建个数也没有限制。
虽然实例化过程和CDMAPhone、GSMPhone对象不同,但实例化的SipPhone对象和CDMAPhone、GSMPhone对象一样也被添加到CallManager对象中进行统一管理。
SipPhone实现机制是通过IP通道实现电话功能,而不是通过无线通讯模块,因此没有采用RIL和RIL daemon,因此框架实现层与CDMAPhone、GSMPhone有很大不同,SipPhone框架实现主要是通过SipService系统服务及调用第三方协议栈来完成。SipService系统服务通过JNI来调用本地nist SIP协议堆栈。
SipPhone对象属于SipService服务的客户端对象,其通过SipManager对象的ISipService接口调用SipService。
每个SipPhone对象都对应一个SipProfile对象(包括SIP帐户,地址连接信息以及服务信息等信息)用来标识通话一方。SipProfile对象在SipPhoneFactory调用makePhone实例化SipPhone对象前根据网络通话的sipUri构建,并作为makePhone的参数传给SipPhone对象。
每个SipPhone对象和其它具体Phone对象相同也包括三个Call对象(SipCall):ringingCall、foregroundCall、backgroundCall,每个SipCall对象也包含一个Connection类型的ArrayList对象,用来维护每个CALL拥有的通话连接。不过和其它Phone对象不同SipPhone对象对每个Call对象拥有的connection个数没有限制,SipCall拥有的connection对象对应具体的SipConnection对象。
SipConnection对象包括主动和被动两种类型,主动类型的SipConnection对象在SipCall对象的dial函数调用时创建,被动类型的SipConnection对象在SipCall对象接收到输入CALL时,其initIncomingCall函数调用时创建。创建的SipConnection对象添加到SipCall对象的Connection类型的ArrayList数组列表中进行管理。
每个SipConnection对象也包括一个SipProfile对象和一个SipAudioCall对象。
被动SipConnection类型的SipProfile对象和SipAudioCall对象从对方获得。被动类型的SipAudioCall对象和initIncomingCall函数传进来的SipAudioCall对象相同,SipProfile对象通过调用SipAudioCall的getPeerProfile函数获得发起通话的对方的SipProfile。
主动SipConnection类型的SipProfile对象在dial函数中调用SipProfile.Builder对象的build函数根据发起的通话URL构建,用来标识本地通话方,SipAudioCall对象在调用dial函数时通过调用SipManager对象的makeAudioCall函数创建。
SipAudioCall对象中包括一个客户端SipSession对象,管理客户端的每一个会话过程,SipSession对象中有一个ISipSession接口成员,通过该接口调用服务端对应的会话对象SipSessionImpl对象(一个实现ISipSession接口的会话桩对象),共同完成通话一方的会话过程,客户端通过ISipSession接口向服务端的SipSessionImpl对象发起IPC调用。
主动类型的SipAudioCall对象对应的SipSession对象在makeAudioCall函数中调用createSipSession进行实例化,在makeAudioCall函数调用新创建SipAudioCall对象的makeCall函数时,SipSession对象作为makeCall函数的参数传给SipAudioCall对象。主动类型的SipSession对象中的ISipSession类型的接口成员在createSipSession中通过调用SipService的createSession函数创建,返回服务端SipSessionImpl对象的远程调用对象接口。
SipService的createSession函数创建一个Sip会话对象的整个过程:
1、首先调用createGroup函数实例化一个SipSessionGroupExt对象,SipSessionGroupExt对象派生自SipSessionAdapter,而SipSessionAdapter是一个实现ISipSessionListener接口的桩类;
2、SipSessionGroupExt对象实例化时又调用createSipSessionGroup函数实例化一个SipSessionGroup对象;
3、SipSessionGroup对象实例化时由SipFactory工厂对象实例化底层协议栈类对象SipStack,并有SipStack对象创建一个SipProvider对象和一个SipHelper对象,SipSessionGroup对象本身登记为SipProvider对象的监听对象;
4、然后调用SipSessionGroupExt对象的createSession函数,内部实际调用SipSessionGroup对象的createSession函数,实例化SipSessionImpl对象,并返回实例化后的SipSessionImpl对象引用。
SipSessionImpl属于SipSessionGroup类的内部类,客户端发起的通话请求都通过服务端的SipSessionImpl对象封装成EventObject类型的命令发起异步处理请求(调用SipSessionImpl对象的doCommandAsync函数,doCommandAsync函数的参数是一个EventObject类型的对象),最终通过SipSessionGroup对象的SipHelper对象调用SIP协议栈的接口与通话对方交互。
每个SipSessionImpl会话对象被放到SipSessionGroup对象的HashMap中进行管理。每个实例化的SipSessionGroupExt对象放到SipService的HashMap中进行管理。
客户端也可以通过SipManager对象的open函数发起一个被动会话请求,过程为:
1、 SipManager对象的open函数调用SipService的open3函数,同时也实例化一个PendingIntent对象通过SipService的open3函数传给服务端的SipSessionGroupExt对象中;
2、 在open3函数中调用createGroup函数实例化SipSessionGroupExt对象,并进一步实例化SipSessionGroup对象;
3、 接着调用SipSessionGroup对象的openToReceiveCalls函数来实例化一个SipSessionCallReceiverImpl对象作为接收会话,SipSessionCallReceiverImpl派生自SipSessionImpl,SipSessionGroupExt对象作为函数参数传进openToReceiveCalls函数,并在SipSessionImpl构造函数时调用内部对象成员mProxy(SipSessionListenerProxy类,一个实现ISipSessionListener接口的桩类)的setListener函数,为内部ISipSessionListener类型的成员赋值。
4、 当接收到底层协议发来的会话请求时,监听底层事件的对象SipSessionGroup的processRequest函数被调用;
5、 接着调用接收会话对象SipSessionCallReceiverImpl的process函数,在process函数中判断接收到的事件请求是Request.INVITE时就调用processNewInviteRequest函数;
6、 在processNewInviteRequest函数中调用createNewSession实例化一个SipSessionImpl对象作为新的会话,新的会话状态为INCOMING_CALL。接着调用接收会话SipSessionCallReceiverImpl对象内部成员mProxy的onRinging函数,在onRinging函数中调用其成员mListener(ISipSessionListener类型)的onRinging函数,实际调用SipSessionGroupExt对象的onRinging函数;
7、 在SipSessionGroupExt对象的onRinging函数中通过SipSessionGroupExt对象内部客户端传进来的PendingIntent对象向客户端发送ACTION_SIP_INCOMING_CALL类型广播消息;
8、 客户端在接收到这个广播调用SipManager的takeAudioCall函数。takeAudioCall函数首先通过SipService接口getPendingSession获得一个服务端会话对象引用;接着实例化一个SipAudioCall对象(SipAudioCall对象对应的SipProfile对象调用服务端会话对象的getLocalProfile函数获得);然后根据服务端会话对象引用实例化一个客户端SipSession对象;并调用SipAudioCall对象的attachCall实现SipSession对象与SipAudioCall对象的绑定;
9、 最后调用现有的SipPhone对象的canTake函数,在SipPhone对象的canTake函数中调用SipPhone对象的ringingCall对象的initIncomingCall函数实例化一个SipConnection对象,完成通话建立过程。
四数据连接
Telephony框架的数据连接模块负责数据连接通道的建立,使电话能够提供数据服务,如上网等,数据连接模块的类图如下图。
DataConnectionTracker是数据连接功能的核心,GsmDataConnectionTracker、CdmaDataConnectionTracker是DataConnectionTracker的两个派生类,实现具体网络的数据连接的建立和管理。
每一个数据连接用一个DataConnection对象表示,DataConnection对应的具体网络的派生类为GsmDataConnection和CdmaDataConnection。DataConnectionTracker中用一个HashMap类型的变量mDataConnections维护每一个数据连接。CDMA同时只能建立一路数据连接,GSM网络则没有限制。
DataConnection对象是一个是一个状态机对象,维护连接的状态,并提供数据连接的LinkProperties和LinkCapabilities等属性。DataConnection对象的状态包括DcDefaultState、DcInactiveState、DcActivatingState、DcActiveState、DcDisconnectingState、DcDisconnectionErrorCreatingConnection六种状态。
对于GsmDataConnectionTracker对象,ApnContext对象提供数据连接的APN上下文,每一个APN类型都对应一个ApnContext对象,ApnContext对象维护对应的APN设置、DataConnectionTracker的状态、对应的DataConnection和DataConnectionAc等。
数据连接通道的建立过程:
1、 数据连接的建立最终都通过GsmDataConnectionTracker和CdmaDataConnectionTracker的trySetupData函数启动数据连接;
2、 trySetupData函数调用setupData函数,设置数据连接参数(如采用的Apn设置参数,连接建立成功响应消息);
3、 然后调用对应的DataConnection对象的bringUp函数发送数据连接消息(EVENT_CONNECT)。
4、 EVENT_CONNECT消息由DataConnection对象的状态机的相应状态对象接收处理,对于开始尚未建立数据连接时,DataConnection对象处于DcInactiveState状态,因此DcInactiveState状态对象接收处理EVENT_CONNECT事件,调用onConnect函数,并转变为DcActivatingState状态。
5、 在具体DataConnection对象的onConnect函数中调用RIL接口setupDataCall函数启动数据连接;
6、 连接建立后RIL层回应EVENT_SETUP_DATA_CONNECTION_DONE请求应答事件,由DataConnection对象的DcActivatingState状态对象接收处理EVENT_SETUP_DATA_CONNECTION_DONE事件,调用onSetupConnectionCompleted函数,并过渡到DcActiveState状态,连接建立成功。
DataConnectionTracker对象采用DataConnectionAc对象(派生自AsyncChannel)与DataConnection对象通讯。
GsmDataConnectionTracker对象在setupData函数调用createDataConnection函数创建时GsmDataConnection对象和DataConnectionAc对象,并通过DataConnectionAc对象与GsmDataConnection对象建立异步通讯连接。GsmDataConnectionTracker对象对于每类ApnContext都可以建立一个GsmDataConnection对象和一个DataConnectionAc对象。
CdmaDataConnectionTracker对象在实例化时调用createAllDataConnectionList函数创建需要的数据连接对象CdmaDataConnection和DataConnectionAc对象。CdmaDataConnectionTracker对象只支持创建一个CdmaDataConnection对象和DataConnectionAc对象。
五事件通知机制
整个Telephony事件通知框架包括三层: RIL消息层、框架事件处理层、应用层。类图如下图,主要是请求应答模式和观察者模式的采用。
整个框架层以PhoneBase为中心,向上通过PhoneNotifier接口向应用层发送框架层产生的的事件,应用层通过TelephonyRegistry接口提供对特定事件的监听,由PhoneNotifier接口的默认实现DefaultPhoneNotifier通过TelephonyRegistry对象向应用层发送事件通知。
向下框架层通过CommandsInterface接口注册Unsolicited事件(主动通知事件)及发起AT命令请求。框架层的事件处理对象包括CDMAPhone和GSMPhone两个对象本身及其包含的SMSDispatcher、IccFileHandler、DataConnectionTracker、IccRecords类型的对象以及PhoneBase中的SmsStorageMonitor对象。
这些对象都是Handler对象,都能够向RIL层注册Unsolicited事件及发起AT命令请求。也能够接收和处理RIL层产生的Unsolicited事件及AT命令的响应。
CDMAPhone和GSMPhone对象中的事件处理对象除了CallTracker及ServiceStateTracker对象外,其它都在PhoneBase中由基类实现。
向RIL层注册的Unsolicited事件都登记添加到BaseCommands类中的RegistrantList类型的对象中或者设置为BaseCommands类中的Registrant类型的对象(根据设置函数的参数实例化具体类型的Registrant类型的对象)。
RIL层产生的Unsolicited事件通过在BaseCommands类中登记的RegistrantList对象或设置的Registrant对象向框架层的事件处理对象发送Unsolicited事件。
框架层的事件处理对象向RIL层发送的命令直接发送给RIL对象的相应函数,向RIL层发送的命令中都带有一个Message类型的应答消息,RIL对象的相应函数把接收到的命令携带的参数封装进RILRequest请求中发送给RIL的RILSender对象并marshall后通过LocalSocket发送给rild进程。
RIL的RILReceiver对象通过相同LocalSocket通道收到AT命令的响应unmarshall后调用processSolicited()函数把应答结果封装进命令携带的应答消息中发送回框架层的事件处理对象。
RILSender对象和RILReceiver对象都实现了接口,在独立线程运行。
欢迎转载,转载时请尊重原创注明出处。