Android 44 Kitkat Phone MT来电流程分析.docx
- 文档编号:25565919
- 上传时间:2023-06-09
- 格式:DOCX
- 页数:15
- 大小:166.81KB
Android 44 Kitkat Phone MT来电流程分析.docx
《Android 44 Kitkat Phone MT来电流程分析.docx》由会员分享,可在线阅读,更多相关《Android 44 Kitkat Phone MT来电流程分析.docx(15页珍藏版)》请在冰豆网上搜索。
Android44KitkatPhoneMT来电流程分析
Android4.4KitkatPhone工作流程浅析之MT(来电)流程分析
目录(?
)[-]
1前置文章
2概述
3Telephonyframework处理
3RegistrantList消息处理
4TeleService消息处理
5InCallUI界面更新
6小结
本文代码以MTK平台Android4.4为分析对象,与Google原生AOSP有些许差异,请读者知悉。
概述
实际上MTK对于RILJ的改动还是较大的,添加了很多request和respone类型。
对于MT(来电)来讲,首先还是会由Modem接收到信息,然后发给RILC,RILC再发送给RILJ,并在RILJ的RILReceiver中接收到并进行处理。
MTK对于Modem侧的AT指令进行一些定制,这和AOSP原生使用CLCC方式后去来电信息不同,MTK这里使用了自己添加的AT指令ECPI来反馈通话状态改变的信息。
后面会针对MTK的log进行一个简单的分析,根据log来分析MO/MT流程,其中会涉及ATlog和mainlog。
我们知道RILJ会从RILC收到Solicited和Unsolicited信息,并对之进行处理之后向上反馈。
本次分析的MT(来电)流程,就属于Unsolicited信息,而信息从RILJ中的RILReceiver的run方法中开始。
首先我们先看到RILJ与RILC的简单交互图,当RILJ收到RILC的Unsolicited信息时,RILReceiver开始处理。
先来看看MT(来电)的整个流程图:
通过上图可以知道,整个MT(来电)过程分为三个部分:
Telephonyframework、TeleService、InCallUI。
来电信息通过处理并逐层传递,最终显示到界面上。
界面主要包括:
CallCardFragment、CallButtonFragment、AnswerFragment内容的更新。
Telephonyframework处理
通过RILReceiver接收到MT(来电)信息,RILC将相关来电信息通过socket发送给RILJ,RILReceiver接收到之后进行读取并打包进行上报。
整个流程如下图:
整个过程看起来比较清晰,但实际跟踪起来还是比较麻烦的,这里运用到了观察者模式也就是RegistrantList和Registrant,使用handler来传递信息。
RegistrantList消息处理
这里实际上使用的是观察者模式,即:
RegistrantList:
通知者
通过add()/addUnique()、remove()方法负责添加、删除通知者,使用notifyRegistrants()方法发出通知;
Registrant:
观察者
通过internalNotifyRegistrant()响应通知者发出的通知;
RegistrantList的工作流程大致如下:
(1).RegistrantList通过registerForXXX方法注册观察者Registrant的方法;
在BaseCommands.java中可以看到registerForCallProgressInfo()方法,如下:
[java]viewplaincopy
7protectedRegistrantListmCallProgressInfoRegistrants=newRegistrantList();
8//注册观察者
9publicvoidregisterForCallProgressInfo(Handlerh,intwhat,Objectobj){
10Registrantr=newRegistrant(h,what,obj);
11mCallProgressInfoRegistrants.add(r);
12}
13//取消注册观察者
14publicvoidunregisterForCallProgressInfo(Handlerh){
15mCallProgressInfoRegistrants.remove(h);
16}
这是对Registrant对象进行了赋值:
[java]viewplaincopy
17WeakReferencerefH;
18intwhat;
19ObjectuserObj;
20
21publicRegistrant(Handlerh,intwhat,Objectobj){
22refH=newWeakReference(h);
23this.what=what;
24userObj=obj;
25}
那么这个registerForCallProgressInfo在哪里调用的呢?
在GsmCallTracker的构造方法中可以看到:
[java]viewplaincopy
26mCi.registerForCallProgressInfo(this,EVENT_CALL_PROGRESS_INFO,null);
也就是说在GsmCallTracker初始化的时候完成了注册过程。
(2).调用notifyRegistrants触发Handler的handleMessage回调;
注册完毕之后又是如何触发的呢?
我们在RIL.java的ProcessUnsolicited方法中,来电时会上报以下RIL_UNSOL_CALL_PROGRESS_INFO信息,该信息由底层上报,并执行以下方法:
[java]viewplaincopy
27mCallProgressInfoRegistrants.notifyRegistrants(newAsyncResult(null,ret,null));
这里的notifyRegistrants实际为RegistrantList的方法:
[java]viewplaincopy
28publicvoidnotifyRegistrants(AsyncResultar){
29internalNotifyRegistrants(ar.result,ar.exception);
30}
31privatesynchronizedvoidinternalNotifyRegistrants(Objectresult,Throwableexception){
32for(inti=0,s=registrants.size();i
33Registrantr=(Registrant)registrants.get(i);
34r.internalNotifyRegistrant(result,exception);
35}
36}
通过registrants.get(i)方法获取其中的Registrant对象,并调用Registrant的internalNotifyRegistrant方法,其中registrant为ArrayList对象,通过其中的add方法添加:
[java]viewplaincopy
37publicsynchronizedvoidadd(Registrantr){
38removeCleared();
39registrants.add(r);
40}
在前面有提到registerForCallProgressInfo方法调用了add方法。
继续查看r.internalNotifyRegistrant方法,在Registrant.java中:
[java]viewplaincopy
41internalNotifyRegistrant(Objectresult,Throwableexception){
42Handlerh=getHandler();
43if(h==null){
44clear();
45Log.d("Registrant","internalNotifyRegistrant():
Warning!
Handlerisnull,itcouldbealreadyGCed.(what="+what+",userObj="+userObj+",result="+result+",exception="+exception+")");
46}else{
47Messagemsg=Message.obtain();
48msg.what=what;
49msg.obj=newAsyncResult(userObj,result,exception);
50h.sendMessage(msg);
51}
52}
看到这里后,我们知道了最后消息的传递是使用handler的sendMessage()方法。
经过了上面的种种之后,整个Registrant的工作流程如下:
通过观察者模式,消息逐步传递到了GsmCallTracker中,在这里一方面继续将信息向上传递,另一方面这里调用了updatePhoneState()方法,该方法最后会使用broadcast的方式,发出TelephonyManager.ACTION_PHONE_STATE_CHANGE的广播,该广播用于通知Phone状态改变,API中提供监听PhoneState改变的广播就是这里负责通知的。
TeleService消息处理
经过Telephonyframework中的各种处理后,来电信息就传递到了TeleService中。
在TeleService中会查询来电号码的信息,比如归属地,是否是已知联系人等,将这些查询到的消息保存到Connection对象中,再将其传递给InCallUI进行最后的显示。
整个处理流程如下:
这一块原来是放在Phone中进行处理的,在4.4中Phone一分为二,TeleService在后台负责相关数据的查询和获取,InCallUI负责取出TeleService中的数据并进行界面显示更新。
这里的CallStateMonitor正如其名,用于注册监听Phone的状态改变并统一发起通知。
CallNotifier和CallModeler均添加了CallStateMonitor的Listener,一旦Phone状态改变即可通过Handler的handleMessage回调到相关注册类中,并进行一些处理。
因为我们这里仅分析MT(来电)流程,其中附带的响铃以及点亮屏幕等流程这里就不详述,在来电的时候并不是直说只有EVENT_NEW_RINGING_CONNECTION,还有EVENT_PRECISE_CALL_STATE_CHANGED和EVENT_INCOMING_RING等,每一个状态对应一种处理。
这些状态在CallManager中处理之后便通过CallStateMonitor进行回调处理。
startIncomingCallQuery()方法负责查询来电号码的相关信息,CallModeler将查询结果放入Connection对象中,并触发Listener的回调方法onIncoming()。
CallModeler中包含了很多重要的方法,CallModeler继承自Handler,CallHandlerServiceProxy注册了其Listener,CallModeler处理完Connection之后会回调到CallHandlerServiceProxy中。
CallModeler主要对Connection进行处理,并且用Connection来标识一个通话,在代码顶部的注释中可以发现:
[java]viewplaincopy
53/**
54*CreatesaCallmodelfromCallstateanddatareceivedfromthetelephony
55*layer.Thetelephonylayermaintains3conceptualobjects:
Phone,Call,
56*Connection.
57*
58*Phonerepresentstheradioandthereisanimplementationpertechnology
59*typesuchasGSMPhone,SipPhone,CDMAPhone,etc.Generally,wewillonlyever
60*dealwithoneinstanceofthisobjectforthelifetimeofthisclass.
61*
62*Thereare3Callinstancesthatexistforthelifetimeofthisclasswhich
63*arecreatedbyCallTracker.ThethreeareRingingCall,ForegroundCall,and
64*BackgroundCall.
65*
66*AConnectionmostcloselyresembleswhatthelaypersonwouldconsideracall.
67*AConnectioniscreatedwhenauserdialsanditis"owned"byoneofthe
68*threeCallinstances.WhichofthethreeCallsownstheConnectionchanges
69*astheConnectiongoesbetweenACTIVE,HOLD,RINGING,andotherstates.
70*
71*ThisclassmodelsanewCallclassfromConnectionobjectsreceivedfrom
72*thetelephonylayer.WeuseConnectionreferencesasidentifiersforacall;
73*newreference=newcall.
74*
75*TODO:
CreateanewCallclasstoreplacethesimplecallIdints
76*beingusedcurrently.
77*
78*ThenewCallmodelsareparcellablefortransferviatheCallHandlerService
79*API.
80*/
81//大致信息如下:
82//根据从Telephonyframework层返回的Call状态和数据创建一个Callmodel。
Telephonyframework层包含3个概念性的对象:
Phone、Call、Connection;
83
84//Phone包含的类型有:
GSMPhone、SipPhone、CDMAPhone等,一般来讲,在一个生命周期里仅存在三种类型中的其中一种。
85
86//在一个生命周期中Call有三个引用:
RingingCall、ForegroundCall、BackgroundCall。
87
88//一般来说Connection被用来表示通话。
当用户拨号时便会创建Connection,其隶属于三种类型的Call。
Connection的状态包含:
ACTIVE、HOLD、RINGING等。
89
90//Modeler中的Connection对象 Arial,Helvetica,sans-serif;">来自于 Arial,Helvetica,sans-serif;">从telephonyframework层,并且,使用Connection的引用来标识一个通话。 91 92//Modeler将相关数据通过CallHandlerService传递给InCallUI。 完成以上处理之后就进入了CallHandlerServiceProxy中,通过其名称我们大致可以推断是一个代理类。 它主要完成信息的传输,代码如下: 93@Override 94publicvoidonIncoming(Callcall){ 95//清空重链接计数. 96resetConnectRetryCount(); 97synchronized(mServiceAndQueueLock){ 98if(mCallHandlerServiceGuarded==null){ 99if(DBG){ 100Log.d(TAG,"CallHandlerServicenotconnected.Enqueueincoming."); 101} 102//设置操作类型为QueueParams.METHOD_INCOMING 103enqueueIncoming(call); 104//与InCallUI中的CallHandlerService建立连接,使用bindService 105setupServiceConnection(); 106return; 107} 108} 109//第二次再处理来电信息,第一次如果没有建立连接则会先执行上面的代码 110processIncoming(call); 111} 整个过程分解为以下三步: (1).设置界面处理类型; 因为这里是来电,因此类型为QueueParams.METHOD_INCOMING。 112enqueueIncoming(call); 113privatevoidenqueueIncoming(Callcall){ 114getQueue().add(newQueueParams(QueueParams.METHOD_INCOMING,newCall(call))); 115} (2).与CallHandlerService建立连接; 使用的是bindService来建立Service的连接。 116if(! mContext.bindService(serviceIntent,mConnection,Context.BIND_AUTO_CREATE)){ 117//Thishappenswhenthein-callpackageisinthemiddleofbeinginstalled 118Log.w(TAG,"Couldnotbindtodefaultcallhandlerservice: "+serviceIntent.getComponent()); 119failedConnection=true; 120} (3).处理来电操作processIncoming; 执行上面两步之后会return,但来电信息并不是只有一次上报,因此在建立CallHandlerService连接之后再执行processIncoming。 121privatevoidprocessIncoming(Callcall){ 122//......省略 123synchronized(mServiceAndQueueLock){ 124if(mCallHandlerServiceGuarded! =null){ 125mCallHandlerServiceGuarded.onIncoming(call, 126RejectWithTextMessageManager.loadCannedResponses()); 127} 128//.......省略 129} 130 131privatevoidonCallHandlerServiceConnected(ICallHandlerServicecallHandlerService){ 132//......省略 133mCallHandlerServiceGuarded=callHandlerService; 134//......省略 135} 136 137onCallHandlerServiceConnected(ICallHandlerService.Stub.asInterface(service)); 通过以上步骤之后所以的数据已经获取完毕,接下来需要更新界面UI了。 InCallUI界面更新 经过前面Telephoneyframework和TeleService处理之后,已经获取到了UI界面所需要的数据,在InCallUI中要做的仅仅是将相关数据更新的界面上。 整个流程如图: 在CallHandlerService中,首先会执行onIncoming()方法,并进而跳转到CallList中。 138mCallList.onIncoming(entry.getKey(),entry.getValue()); 这里的CallList包含了各种call的处理方法,并将处理结果通知感兴趣的类(也就是注册了其Listener的类),主要是InCallPresenter。 这里还会去更新call的id信息,这个id信息存储在HashMap中,比如当需要使用或者查找call可以根据id来查找,CallList主要是对Call进行列表化。 在完成call列表化之后便会通知相应的presenter,这里是MT(来电)流程。 所以主要涉及到两个presenter即AnswerPresenter和InCallPresenter。 前者负责来电接听/拒接控件的更新显示,后者负责CallCard和CallButton以及VTCall(MTK加入的VideoCall)的界面更新显示。 通过CallCardPresenter中的onStateChange()方法,回调到CallCardFragment,并使用ui.setXXX()方法设置界面元素的内容。 小结 MT(来电)从Modem端发起,最终显示到界面上,整个过程的传递大致可以分为以下三个步骤: 1.Telephonyframewor
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Android 44 Kitkat Phone MT来电流程分析 MT 来电 流程 分析