Android ANR
文章目录
- Android ANR
- 1.ANR简单介绍
- 1.1 产生ANR的场景
- 1.2 ANR具体时间定义
- 2.ANR触发分析
- 2.1 Input相关
- 2.2 Service相关
- 2.3Broadcast相关
- 2.4 ContentProvider相关
- 参考资料
1.ANR简单介绍
1.1 产生ANR的场景
- ANR:应用程序无响应(Application Not Responding)
1.2 ANR具体时间定义
- InputDispatching Timeout:5秒内无法响应屏幕触摸事件或键盘输入事件。
- Service Timeout:前台服务20秒内内没有执行完毕。
- BroadcastQueue Timeout:在执行前台广播10秒没有处理完成。
- ContentProvider Timeout :ContentProvider的publish在10秒内没进行完。
2.ANR触发分析 2.1 Input相关
- Service Timeout相关:(ActiveServices.java)
// How long we wait for a service to finish executing. static final int SERVICE_TIMEOUT = 20*1000; // How long we wait for a service to finish executing. static final int SERVICE_BACKGROUND_TIMEOUT = SERVICE_TIMEOUT * 10; // How long the startForegroundService() grace period is to get around to // calling startForeground() before we ANR + stop it. static final int SERVICE_START_FOREGROUND_TIMEOUT = 10*1000;
- 前台服务20s。
- 后台服务200s。
- BroadcastQueue Timeout相关:(ActivityManagerService.java)
// How long we allow a receiver to run before giving up on it. static final int BROADCAST_FG_TIMEOUT = 10*1000; static final int BROADCAST_BG_TIMEOUT = 60*1000;
- 前台广播10s。
- 后台广播60s。
- ContentProvider Timeout相关:
// How long we wait for an attached process to publish its content providers // before we decide it must be hung. static final int CONTENT_PROVIDER_PUBLISH_TIMEOUT = 10*1000;
2.2 Service相关
- ANR检测区间主要指:当前事件dispatch过程中执行**findFocusedWindowTargetsLocked()方法到下一次执行resetANRTimeoutsLocked()**的时间区间。
- Input ANR 的实现是通过将InputManagerService加入到Watchdog的monitor队列,定时监测是否发生死锁。
超时设置:
超时移除:
- Service进程attach到system_server进程的过程中会调用**realStartServiceLocked()**方法。
- realStartServiceLocked()方法中会调用**bumpServiceExecutingLocked()**方法。
- bumpServiceExecutingLocked()方法又会调用**scheduleServiceTimeoutLocked()**方法。
// scheduleServiceTimeoutLocked方法节选 mAm.mHandler.sendMessageDelayed(msg, proc.execServicesFg ? SERVICE_TIMEOUT : SERVICE_BACKGROUND_TIMEOUT);
- scheduleServiceTimeoutLocke()方法通过delay消息(SERVICE_TIMEOUT_MSG)设置了服务超时。
- 如果不能在规定时间内移除该消息(SERVICE_TIMEOUT_MSG),则会触发ANR。
ANR触发:
- (ActivityThread.java)目标进程主线程会调用**handleCreateService()**方法。
// handleCreateService方法节选 ... try { // 创建ContextImpl对象 ContextImpl context = ContextImpl.createAppContext(this, packageInfo); context.setOuterContext(service); // 创建Application对象 Application app = packageInfo.makeApplication(false, mInstrumentation); service.attach(context, this, data.info.name, data.token, app, ActivityManager.getService()); // 调用服务的onService()方法 service.onCreate(); mServices.put(data.token, service); try { // 移除超时消息 ActivityManager.getService().serviceDoneExecuting( data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } ...
- **serviceDoneExecuting()**方法中会从消息队列中将消息(SERVICE_TIMEOUT_MSG)异常。
// 位于ActivieService.java private void serviceDoneExecutingLocked(){ ... mAm.mHandler.removeMessages(ActivityManagerService.SERVICE_TIMEOUT_MSG, r.app); ... }
- 移除后则不会触发ANR。
2.3Broadcast相关
- 当AMS(ActivityManagerService)收到SERVICE_TIMEOUT_MSG消息,调用serviceTimeout()方法。
... case SERVICE_TIMEOUT_MSG: { mServices.serviceTimeout((ProcessRecord)msg.obj); } break; ...
- serviceTimeout()方法会调用**appNotResponding()**方法。
... if (anrMessage != null) { proc.appNotResponding(null, null, null, null, false, anrMessage); } ...
- 至此触发了ANR异常。
超时设置:
- 调用**processNextBroadcast()**方法来处理广播。
- 通过调用**setBroadcastTimeoutLocked()**方法设置超时消息(BROADCAST_TIMEOUT_MSG)。
- 当广播接收者等待时间过长,会调用**broadcastTimeoutLocked(false)**方法。
- 当广播执行完,会调用**cancelBroadcastTimeoutLocked()**方法,取消超时消息。
超时移除:
ANR触发:
- 与Service大致相同,但是通过静态注册的广播超时会受SharedPreference的影响,动态注册的广播不会受到影响。
- 当SharedPreference有未同步到磁盘的工作,则需等待其完成,才告知系统已完成该广播。
2.4 ContentProvider相关
- (BroadcastQueue.java)BroadcastHandler处理超时消息(BROADCAST_TIMEOUT_MSG)会调用**broadcastTimeoutLocked(true)**方法。
- 在 broadcastTimeoutLocked()方法中:
- mOrderedBroadcasts已处理完成,则不会ANR。
- 在执行dexopt,则不会ANR。
- 系统还没有进入ready状态(mProcessesReady=false),则不会ANR。
- 如果当前正在执行的receiver没有超时,则重新设置广播超时,不会ANR。
- 否则触发ANR异常。
超时设置:
超时移除:
- Provider启动,在进程创建后会调用**attachApplicationLocked()**进入system_server进程。
- attachApplicationLocked()方法中会设置超时消息(CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG)。
【Android学习笔记|Android ANR】ANR触发:
- provider成功publish之后,会移除超时消息。
参考资料
- (ActivityManagerService.java)MainHandler处理超时消息(CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG),调用**processContentProviderPublishTimedOutLocked()**方法。
- processContentProviderPublishTimedOutLocked()方法会调用**cleanupAppInLaunchingProvidersLocked()方法和removeProcessLocked()**方法。
- cleanupAppInLaunchingProvidersLocked()方法会调用**removeDyingProviderLocked()**方法。
- removeDyingProviderLocked()方法会:
- 对于stable类型的provider(即conn.stableCount > 0),会杀掉所有跟该provider建立stable连接的非persistent进程。
- 对于unstable类的provider(即conn.unstableCount > 0),不会导致client进程被级联所杀。
- removeProcessLocked()方法终止进程,不会弹出ANR的对话框。
- 理解Android ANR的触发原理
- Android ANR:原理分析及解决办法
- Input系统—ANR原理分析