Android中InCallUI显示太慢问题分析

  1. 云栖社区>
  2. 博客>
  3. 正文

Android中InCallUI显示太慢问题分析

宋金时 2015-06-01 17:00:35 浏览1474
展开阅读全文


完整分析流程和详细内容也可以下载PDF文档:

InCallUI_issue_analysis_report


一、问题现象

当手机有来电时,先听到铃声,过了比较长的一段时间(3-4s)屏幕才点亮并显示来电界面。

Platform:MT6581

Android版本:4.4KK

BuildType:userdebug

系统软件版本:SWC1E+UP

系统RAM:512M

二、Android4.4来电及IncallUI显示的流程

整个流程主要分为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.396CallHandlerService - 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进程常驻的相关设置:   

<application android:name="PhoneApp"

           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.995CallHandlerService - onCreate07-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.

#jinshi.song@jrdcom.com

#201407101558


网友评论

登录后评论
0/500
评论