概述
在Android 4.4 中,Google 对Telephony_Phone进行了重构,前面也通过一些列文章分析了Android 4.4 中Telephony Phone的工作流程。但在2014年10月15日,Google发布了Android 5.0 预览版,正式版也在一个月之后发布。Android 5.0 变化非常大,无论从UI风格还是功能实现上,Google都进行了大刀阔斧的修改。同时,Telephony_Phone模块的架构也再次进行了调整,调整之后的Telephony_Phone各个模块之间耦合性更低,分工也更为明确,但整个流程却变复杂了许多。
本文来自http://blog.csdn.net/yihongyuelan 转载请务必注明出处
下图是Android 4.2 到5.0,Telephony Phone模块结构变化示意图:
图 1 Android Telephony Phone Architecture Evolution
在Android 4.2 以及之前的版本中,Telephony Phone模块主要涉及Phone和Contacts以及Telephony Framework这几个部分。在Android 4.4 中,Phone模块被InCallUI和TeleService取而代之,其中InCallUI被打包到Dialer.apk中。InCallUI主要负责UI显示部分,TeleService则负责逻辑处理。
Android 5.0 中,Telephony Service也就是原来的TeleService,部分功能被提取到了Telecom Service和Telecom Framework中。整个Telephony Phone模块包括了5个部分:InCallUI、Telecom Service、Telecom Framework、Telephony Service、Telephony Framework。其中新增的Telecom Framework被打包到framework.jar中,Telecom Service则打包到Telecom.apk里。
从Android 4.2到5.0,Telephony Phone模块愈加细化,各个子模块的功能越愈发精简。当然,这符合面向对象的要求,但也导致各个模块间交互也相应增加。整个Telephony Phone演进过程可以简单的概括为:
图 2 Simplified Phone Architecture Evolution
Android 5.0 InCallUI简介
Android 5.0 对InCallUI界面进行了调整以适应Google的Material Design。
图 3 InCallUI InCall process (pictrue from @Eric Li)
图 4 Incoming call (pictrue from @Eric Li)
在Android 5.0中,InCallUI加入了新的呈现方式即Immersive Mode,只要在非LockScreen界面来电,来电信息将显示为一个浮动通知。该通知是一个Heads-up类型的Notification,当触发时会在状态栏弹出以提示用户。任何一个Notification都可以采用Heads-up的方式显示,只需给Notification.builder设置FullScreenIntent属性:
[java] view plaincopy
- builder.setFullScreenIntent(PendingIntent intent, boolean highPriority)
如果弹出Heads-up Notification时系统处于锁屏状态,NotificationMangerService会执行PendingIntent所指定的Action。如:锁屏时来电则会启动InCallActivity,又因为InCallActivity具有以下属性:
[java] view plaincopy
- getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
因此,锁屏会被解除并显示InCallActivity。
图 5 Multiple calls UI (pictrue from @Eric Li)
图 6 Conference calls UI (pictrue from @Eric Li)
Android 4.4与5.0 MO/MT对比
之前已经分析过Android 4.4 的MO/MT过程,具体可以参看:
《Android 4.4 Kitkat Phone工作流程浅析(三)__MO(去电)流程分析》
《Android 4.4 Kitkat Phone工作流程浅析(五)__MT(来电)流程分析》
MO即Mobile Origination Call主叫,也就是去电。主要包括:拨号,启动UI界面,更新通话状态;MT即Mobile Termination Call被叫,也就是来电。主要包括:响铃,启动UI界面,更新通话状态。在Android 4.4 中,整个MO/MT执行流程如图7:
图 7 Android 4.4 MO/MT flowchart
MO关键步骤如下
①. Dial
图中粉色箭头标示。Dial是从Dialer的Dialpad中发起的,发送广播到Telephony Service中继续进行处理。
②. Start InCallUI
图中绿色箭头标示。在Android 4.4中,当Dial发起并到达RIL之后,RIL会将Dial请求下发给Modem端,Modem端则返回DIALING状态。RIL接收到DIALING状态之后将信息反馈给Telephony Service,最终到达InCallUI并根据当前通话状态(DIALING)启动界面并显示相应内容。
③. Update Call State
图中绿色箭头标示。在Android 4.4中,Call状态从IDLE变为DIALING也属于Call State变化范畴,因此Update Call State流程与Start InCallUI流程一致,但Start InCallUI只会执行一次,而Update Call State在通话过程中会多次执行,如Call 状态从ACTIVE转为HOLD等。
MT关键步骤如下
①. Ringing
图中橙色箭头所示。Ringing实际上也是Call 状态的一种类型,因此也是从Modem端发起并传递给RIL,之后逐级上报并最终显示到InCallUI中。与Update Call State唯一不同的是,MT会在CallNotifier中调用Ringer执行播放铃声操作。
在Android 4.4 中,MO流程可以分为两步,即Dial和Update Call State (Start InCallUI包含在Update Call State流程中)。MT流程亦分为两步,即Update Call State和Ringing。
Android 4.4 Telephony Phone架构非常清晰,各个子模块也较为独立。如Telephony Service和InCallUI通过CallHandlerService、CallHandlerServiceProxy以及CallCommandClient、CallCommandService进行交互,主要涉及com.android.incallui(InCallUI)、com.android.dialer(Dialer)、com.android.phone(Telephony Service)三个进程。虽然架构上比较清晰,但InCallUI和Telephony Service绑定得太紧,同时Telephony Service也非常臃肿。
在Android 5.0 中Telephony Service分离了部分功能到Telcom Service和Telecom Framework中。Android 4.4 与 5.0 Telephony Phone架构对比,如下图所示:
图 8 Architecture difference(Simplified)
从图中可以看到Telephony Phone架构从Android 4.4时的三层变成了Android 5.0时的四层,其中Android 5.0 中新增部分由原来的Telephony Service分离而来。从进程模型上分析,在Android 5.0 中,Telephony Phone的工作流程主要包含:com.android.incallui(InCallUI)、com.android.dialer(Dialer)、com.android.server.telecom(Telecom Service)、com.android.phone(Telephony Service)四个进程。
Android 5.0 Telephony Phone MO流程改动较大,关键步骤如下图所示:
图 9 Android 5.0 MO flowchart
MO流程分为三个步骤,即Dial,Start InCallUI,Update Call State。在Android 4.4的流程中,Update Call State包含了Start InCallUI,而在Android 5.0 中很各个步骤非常明确。从上图中可以看到,无论是InCallUI、Telecom Service还是Telephony Service均没有直接交互,所有的交互都是与Framework进行。最重要的一点是:InCallUI不再与Telephony Service或者Telecom Service绑定,各个模块非常独立。
Android 5.0 Telephony Phone MO详细流程如下图所示:
图 10 MO Dial / Start InCallUI /Update Call State Flowchart
Android 5.0 MO详细流程分为四个步骤,即Start InCallUI,执行Dial Action,更新Dialing状态,Call 状态改变更新。从上图可以看到,InCallUI在Call 状态改变之前就已经启动了,在Call 状态改变为Dialing后再次更新界面。
Android 5.0 Telephony Phone MT流程关键步骤以及详细流程,如下图所示:
图 11 Android 5.0 MT Flowchart
图 12 MT Ringing and Update Call State Flowchart
在Android 5.0 Telephony Phone MT流程中,Start InCallUI依然包含在Update Call State流程中,同时在CallsManager中会调用Ringer执行相关响铃的操作。
Telecom简介
在Android 5.0中新增了Telecom Service ( packages/services/Telecomm )和Telecom Framework ( framework/base/telecomm ),这两部分由Telephony Service分离而来,虽然在Android 5.0 中Telephony Service依然存在,但所负责事务却有所改变。
Telecom是对Telecom Service和Telecom Framework的统称,其主要负责所有数据业务。上层APP(InCallUI)接触到的Phone、Call以及Connection对象,实际上是Telecom Framework的Phone、Call和Connection对象,并不是Telephony Framework中的GSMPhone、GsmCall和GsmConnection。
其中,Telecom Framework中的Phone和Call取代了Android 4.4 Telephony Service中的CallCommandService和CallHandlerServiceProxy,负责通话数据的传递以及控制指令的下发。而Telecom Service中的CallsManager则负责所有通话数据以及指令的处理,并将结果传递给Telecom Framework。
Android 4.4与5.0 Call State对比
在之前的博文中有分析Android 4.4中Call 状态( 详见《Android 4.4 Kitkat Phone工作流程浅析(八)__Phone状态分析》 《Android 4.4 Kitkat Phone工作流程浅析(九)__状态通知流程分析》 ),随着Android 5.0中Telephony Phone架构的变更,Call 状态也随之改变。如下图所示为Android 4.4中各个Call状态及其对应关系:
图 13 Android 4.4 Call State Overview (MTK)
其中msg_type是MTK的+ECPI指令中所携带的参数。
Android 5.0 中Call 状态分布以及转换如下图所示:
图 14 Android 5.0 Call State distribution diagram
Android 5.0 中Call State的种类包括:
1. DriverCall.State. 用于描述modem的状态;
2. Call.State (Telephony Framework). 用于描述Call状态,这里的Call包含GsmCall、CdmaCall;
3. Connection (Telecom Framework). 用于描述每一个Connection的状态,每一个Connection状态来源于所属Call的状态;
4. CallState (Telecom Framewok). 由于上层改动引入了PRE_DIAL_WAIT等状态,但这种状态并不存在于Telephony Framework Call.State中,因此使用CallState来转换;
5. Call (Telecom Framework). Telephony Framework Call.State的进一步抽象,来源于CallState的转换,也是InCallUI中Call.State的来源;
6. Call.State (InCallUI). 定义InCallUI中Call的状态;
7. InCallState (InCallPresenter). InCallActivity的状态,用于控制UI的更新;
Telephony Phone中的Call状态由协议规定,对于新增的PRE_DIAL_WAIT是无法在Modem端改动的,因此只能在Framework中进行修改并做相应的处理。Android 5.0 中Call 各个状态及其对应关系如图所示:
图 15 Android 5.0 Call State Overview (AOSP)
通过上面的分析可以知道:
①. InCallState新增两个状态,即PENDING_OUTGOING和WAITING_FOR_ACCOUNT
当用户有多个账户且没有设置默认账户时,拨号后会弹出提示框让用户选择账户(互联网账户/SIM1/SIM2),此时状态就为WAITING_FOR_ACCOUNT即等待用户输入。Android 5.0 中,InCallUI并非等待Call状态改变后再启动,预先启动的InCallUI状态为PENDING_OUTGOING,之后会转为OUTGOING状态。
②. Telephony Framework Call.State和DriverCall.State没有改动
Android 5.0 中,Telephony Framework Call.State 之间的转换关系如下图所示,与Android 4.4 一致:
图 16 Telephony Call.State conversion relationship
小结
Android 5.0 Telephony Phone无论从UI还是架构上都与之前相差很大。架构上的差异主要体现在新增了Telecom Service和Telecom Framework,所有的通话数据业务的处理从Telephony Service转移Telecom中。UI上的差异主要是适应Android 5.0 新引入的Material Design,并引入了Heads-up Notification来电界面。
架构的变化也导致了MO/MT流程的变更,新流程相较于原来更加复杂,但各个子模块更加独立。如InCallUI仅仅依赖于Framework,如果Framewrok公开相应的接口(Call/Phone/InCallServiced等),三方APP可以轻松实现InCallUI的功能。