当手机有来电时,先听到铃声,过了比较长的一段时间(3-4s)屏幕才点亮并显示来电界面。
Platform:MT6581
Android版本:4.4KK
BuildType:userdebug
系统软件版本:SWC1E+UP
系统RAM:512M
整个流程主要分为3个部分:
1、framework部分,其主要通过RIL与Modem进行通信,当有来电的时候Modem会通知RIL,RIL则将基础数据和信息进行解析和封装后继续向上通知,大概流程为:RIL->GsmCallTracker->GSMPhone->PhoneBase->CallManager,具体过程如下图:
2、TeleService部分,这部分是由android4.4之前的PhoneAPP改造而来的,其功能基本与之前的PhoneAPP相同,主要负责与framework层的telephony进行通信,并处理在应用层的与Phone相关的状态维护、功能实现和服务提供,其大概流程为:CallStateMonitor->CallNotifier->CallModeler->CallHandlerServiceProxy,具体过程如下图:
3、InCallUI部分,这部分是由android4.4之前的PhoneAPP中分离出来的,在源码目录结构中虽然独立了,但是最终编译完成之后却打包到了Dialer中,Dialer也是android4.4才有的,是由android4.4之前的Contacts中的Dalpad独立出来的,InCallUI的大概流程:CallHandlerService->CallList->Answerpresenter->InCallPresenter->CallButtonPresenter->CallCardPresenter->CallCardFragment,具体过程如下图:
开机后不做任何操作的内存使用信息:
Log分析:
如下为在TeleService的CallNotifier部分的时间点及log信息,从07-09 19:28:41.883接收到来电消息到07-09 19:28:42.594消息解析分发给IncallUI的CallHandlerService结束,因为这个分发是异步单向的,所以不会同步阻塞:
07-09 19:28:41.883 896 896 D CallNotifier: RINGING... (new)
07-09 19:28:41.884 896 896 D CallNotifier: onNewRingingConnection(): state = RINGING, conn = { * -> id: 1, num: 15026714486, MT: true, mDisconnected: false }
07-09 19:28:42.594 896 896 D CallNotifier: - onNewRingingConnection() done.
再看InCallUI的CallHandlerService部分的时间点和log信息,从07-09 19:28:42.583开始创建进程到07-09 19:28:43.396的CallHandlerService - onCreate 再到07-09 19:28:43.655CallHandlerService正式收到InComingCall的消息:
07-09 19:28:42.583 666 866 I ActivityManager: Start proc com.android.incallui for service com.android.dialer/com.android.incallui.CallHandlerService: pid=4126 uid=10053 gids={50053, 3003, 1028, 1015, 3002}
07-09 19:28:43.396 4126 4126 I InCall : CallHandlerService - onCreate
07-09 19:28:43.466 896 896 D CallHandlerServiceProxy: onIncoming: Call{mCallId=2, mState=INCOMING
07-09 19:28:43.655 4126 4138 I InCall : CallHandlerService - onIncomingCall: Call{mCallId=2, mState=INCOMING
最后是InCallActivity部分的时间点和log信息,从07-09 19:28:44.144开始onCreate到07-09 19:28:46.869的onResume最终把界面显示出来给用户:
07-09 19:28:44.144 4126 4126 D InCall : InCallActivity - onCreate()... this = com.android.incallui.InCallActivity@41e225e0
07-09 19:28:46.869 4126 4126 I InCall : InCallActivity - onResume()...
Systrace分析:
从systrace的图中可以看到,从incallui的进程起来到incallui的activityResume总共花了4.3s左右,其中启动进程花费804ms左右,具体如下图:
另外进程启动之后,从CallHandlerService的onCreate到ActivityStart的时间为540ms左右,具体如下图:
通过以上分析我们发现每当来电时,整个过程中InCallUI接受TeleService的来电请求的环节最为耗时,因为需要启动InCallUI这个进程。另外Framework中的telephony以及TeleService都是系统中常驻的进程,不会被杀掉,所以响应速度非常快,TeleService进程常驻的相关设置:
android:persistent="true"
而InCallUI这个进程没有以上persistent的设置,所以在执行完通话的操作后会经常被系统LMK回收掉,鉴于以上原因,为了能够让InCallUI像TeleService一样响应的够快,我们给出了以下解决方案:
1、InCallUI不再独立为一个进程,将InCallUI与Dialer合并为一个进程
2、修改Dialer进程的属性,增加persistent=ture,使其常驻,进而实现InCallUI的常驻,缩短响应和加载出界面的时间
3、取消Dialer拨号时到InCallUI的过渡图片,因为Dialer和InCallUI同属一个进程后在执行拨号时的中间过渡(黑屏)时间被缩短,所以不再需要过渡图片,进而能够进一步提升性能和缩短加载InCallUI界面的时间
开机后不做任何操作的内存使用信息:
Dialer进程常驻之后开机会将它启动,Dialer进程所占内存信息如下:
Log分析:
如下为在TeleService的CallNotifier部分的时间点及log信息,从07-09 20:45:01.848接收到来电消息到07-09 20:45:03.959消息解析分发给IncallUI的CallHandlerService结束
07-09 20:45:01.848 900 900 D CallNotifier: RINGING... (new)
07-09 20:45:01.848 900 900 D CallNotifier: onNewRingingConnection(): state = RINGING,
07-09 20:45:03.959 900 900 D CallNotifier: - onNewRingingConnection() done.
再看InCallUI的CallHandlerService部分的时间点和log信息,从07-09 20:45:03.995的CallHandlerService - onCreate到07-09 20:45:04.229CallHandlerService正式收到InComingCall的消息,其中少了创建进程的步骤:
07-09 20:45:03.995 965 965 I InCall : CallHandlerService - onCreate
07-09 20:45:04.190 900 900 D CallHandlerServiceProxy: onIncoming: Call{mCallId=3, mState=INCOMING
07-09 20:45:04.229 965 983 I InCall : CallHandlerService - onIncomingCall: Call{mCallId=3, mState=INCOMING
最后是InCallActivity部分的时间点和log信息,从07-09 20:45:04.445开始onCreate到07-09 20:45:05.742的onResume最终把界面显示出来给用户:
07-09 20:45:04.445 965 965 D InCall : InCallActivity - onCreate()... this = com.android.incallui.InCallActivity@41e894c0
07-09 20:45:05.742 965 965 I InCall : InCallActivity - onResume()...
Systrace分析:
因为没有了创建进程的过程,所以InCallUI的整个过程只有service的create到activity的resume,由上图可以看到用时1.809s左右。
由以上的log分析、systrace分析以及应用解决方案之后的对比分析,我们可以发现不管是从用户的感觉还是实际的性能参数数据上看,整个过程的性能都得到了很大提升,时间上缩短了很多。另外虽然dialer进程常驻内存,但是其本身占用的内存比较少,基本上在10MB以下,所以对整个系统来讲影响比较小。
#analysed by jinshi.song from SWD2 Framework team.
#201407101558