ANR机制分析(基于AOSP源码)

297 阅读3分钟

一、ANR机制框架与核心组件

在Android系统中,ANR(Application Not Responding)的监控和触发机制主要由ActivityManagerService(AMS)​InputManagerService(IMS)​BroadcastQueue等核心组件实现,依赖Binder通信和消息队列机制。以下是Framework层的核心流程:

二、ANR触发机制源码解析

1. 消息调度与超时检测
  • 源码路径​:frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

  • 核心逻辑​:

    AMS通过Delayed Message机制监控组件响应时间。以Service为例,当服务启动时,AMS会发送延迟消息到主线程的Handler:

    `// ActiveServices.java
    void scheduleServiceTimeoutLocked(ProcessRecord proc) {
        Message msg = mAm.mHandler.obtainMessage(ActivityManagerService.SERVICE_TIMEOUT_MSG);
        mAm.mHandler.sendMessageAtTime(msg, proc.execServicesFg ? SERVICE_TIMEOUT : SERVICE_BACKGROUND_TIMEOUT);
    }`
    

若服务在20秒(前台)或200秒(后台)内未完成onStartCommand()等生命周期方法,AMS触发serviceTimeout()回调

2. Input事件超时
  • 源码路径​:frameworks/base/services/core/java/com/android/server/input/InputManagerService.java

  • 关键流程​:
    输入事件通过InputDispatcher分发到应用进程,若主线程在5秒内未处理完毕,IMS会记录超时:

    `// InputDispatcher.cpp
    void processNextBroadcast() {
        // 设置超时时间点(当前时间+5秒)
        mAnrTime = now() + INPUT_DISPATCH_TIMEOUT_MS;
        // 若超时未完成,触发ANR
        if (mPendingEvent->deliveryTime > mAnrTime) {
            onAnrLocked(app);
        }
    }`
    

    超时后,系统通过appNotResponding()方法收集进程堆栈和CPU信息

3. BroadcastReceiver超时
  • 源码路径​:frameworks/base/services/core/java/com/android/server/am/BroadcastQueue.java

  • 实现细节​:
    广播处理通过processNextBroadcast()方法监控超时:

    `void processNextBroadcast(boolean fromMsg) {
        // 设置超时时间点(当前时间+10秒/60秒)
        final long timeoutTime = SystemClock.uptimeMillis() + (mQueue.mOrdered ? BROADCAST_TIMEOUT : 0);
        setBroadcastTimeoutLocked(timeoutTime);
        // 执行onReceive()
        performReceiveLocked(...);
    }`
    

    若前台广播超时10秒或后台广播超时60秒,AMS调用broadcastTimeoutLocked()触发ANR

三、ANR触发后的处理流程

1. 堆栈与日志收集
  • 核心方法​:ProcessRecord.appNotResponding()
    该方法位于frameworks/base/services/core/java/com/android/server/am/ProcessRecord.java

    `void appNotResponding(String activityShortComponentName, ...) {
        // 1. 生成traces.txt
        File tracesFile = ActivityManagerService.dumpStackTraces(pid, ...);
        // 2. 记录CPU使用情况
        mService.updateCpuStatsNow();
        // 3. 弹出ANR对话框
        if (showBackground) {
            mService.mUiHandler.sendMessage(Message.obtain(...));
        }
    }`
    
    2. ANR对话框显示
  • 源码路径​:frameworks/base/services/core/java/com/android/server/am/AppNotRespondingDialog.java

  • 触发条件​:
    仅当应用处于前台时显示对话框,后台ANR默认不提示(通过Settings.Secure.ANR_SHOW_BACKGROUND配置)

四、系统级监控架构

1. Watchdog机制
  • 实现类​:frameworks/base/services/core/java/com/android/server/Watchdog.java

  • 作用​:
    监控SystemServer进程是否阻塞,若HandlerThread未按时处理消息,触发系统级ANR(SNR)

2. Binder通信监控
  • 关键点​:
    Binder调用超时(默认30秒)可能引发ANR。AMS通过Binder.setDumpTimeout()设置跨进程调用的最大等待时间:

    `// Binder.java
    public static void setDumpTimeout(IBinder binder, long timeoutMillis) {
        nativeSetDumpTimeout(binder, timeoutMillis);
    }`
    

    若服务端未及时响应,客户端触发TransactionTooLargeException或ANR

五、优化与调试建议

  1. 主线程监控​:
    使用StrictMode检测主线程IO和网络操作:

    `StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
        .detectDiskReads().detectNetwork().penaltyLog().build());`
        
    

    2. ​异步任务管理​:
    通过HandlerThreadExecutorService分离耗时操作,避免阻塞主线程

  2. ANR日志分析工具​:

    • Systrace​:追踪主线程消息队列阻塞点
    • Perfetto​:分析CPU调度和Binder调用链
    • adb命令​:adb bugreport导出完整的ANR日志

六、总结

ANR机制本质是多维度超时检测系统,其核心在于:

  1. 消息调度延迟检测​(AMS的Delayed Message)
  2. 输入事件分发监控​(IMS的InputDispatcher)
  3. 跨进程通信超时管理​(Binder线程池)
    通过分析ProcessRecordActiveServices等关键类,开发者可深入理解ANR触发逻辑,优化应用响应性能。