前记

发现好久没写博客了,主要是最近忙着春招,忙着看算法和将以前的知识重新回顾,所以很久没更了,其实一直在写,只是写的不系统,所以没更出来,今天抽空特地更一下。
ps:春招真难,还没找到工作。。。

ANR分析

ANR流程

什么是ANR

ANR是指在Android中,当触摸或者按键事件以及特殊事件没有在规定的时间中完成,那么就会出现ANR(也有可能不会出现ANR),这里的特殊事件就是指ServiceBroadCastReceiverContentProvider

在源码中是如何体现的?

Service为例:
1.在realStartServiceLocked方法中会调用bumpServiceExecutingLocked(r, execInFg, "create");方法,这个函数的作用就是延时发送消息,当在ServiceonCreate方法回调之后,就会调用AMS.serviceDoneExecuting(IBinder token, int type, int startId, int res)来清除之前发送的消息。所以在onCreate()方法中不能超过20S。
2.在AS.sendServiceArgsLocked方法中也会bumpServiceExecutingLocked(r, execInFg, "start");,然后当回调onStartCommand();方法后也会调用AMS.serviceDoneExecuting(IBinder token, int type, int startId, int res)方法来清除之前发送的消息。所以在onStartCommand()中也不能超过20S,同时因为在onStartCommand()会调用onStart(),所以在onStart()中也不能超过20S。
也就是说采用的手法是消息机制,就是在启动的时候延时发送一个消息,如果成功启动,那么就会移除这个消息,反之就会使用AMS中的MainHandler去发送SERVICE_TIMEOUT_MSG这个消息,在MainHandler中的handleMessage来处理消息,最后会调用到AMS.appNotResponding()
BroadCastReceiver为例:
processNextBroadcast方法中调用setBroadcastTimeoutLocked(timeoutTime);方法设置超时时间,当没超时时,调用cancelBroadcastTimeoutLocked();超时时,由BroadcastHandler发送BROADCAST_TIMEOUT_MSG,在BroadcastHandlerhandleMessage中调用broadcastTimeoutLocked(false);来强制结束广播。并且调用mService.appNotResponding(mApp, null, null, false, mAnnotation);使用的依然是handler消息机制。
ContentProvider为例:
ContentProvider发生ANR和其他的都不一样,当使用ContentProvider的时候,若是目标进程不存在,则会创建目标进程,在创建目标进程后会调用AMS.attachApplicationLocked,此时就会延时发送一个消息,延时也是10S,当provider成功publish之后,也就是在AMS.publishContentProviders中会移除这个消息,反之最后会调用到AMS.removeProcessLocked。杀掉ContentProvider所在的进程。
注意:关于CONTENT_PROVIDER_PUBLISH_TIMEOUT超时时机是指在startProcessLocked之后会调用AMS.attachApplicationLocked为起点,一直到AMS.publishContentProviders的过程。
所以对于ContentProvider而言,如果不需要创建新进程,那么就不会出现这个情况,在不需要创建新进程的时候,也可能会出现ANR,并且会调用AMS.appNotResponding()

总结

ANR发生的原因是,在Android的源码中规定了事件或者特殊事件需要在规定时间内完成,提升用户的体验,但是没有完成。在这里事件指触摸或者按键,特殊事件指ServiceBroadCastReceiverContentProvider。 所采取的措施都是通过Handler消息机制。
对于Service而言:在ServiceonCreateonStartonStartCommnand生命周期方法中超时20S。
对于BroadCastReceiver而言:在onReceive()超时10S。
对于ContentProvider而言:从AMS.attachApplicationLockedAMS.publishContentProviders的过程中耗时超过10S。
对于ContentProvider而言,不会走AMS.appNotResponding(),其他的都走。AMS.appNotResponding()处理中主要是将CPU使用情况和进程的trace文件信息,保存到/data/system/dropbox;