【Android】ANR产生源码简介

本文详细介绍了Android应用程序无响应(ANR)的产生机制,从ContentProvider超时到InputDispatcher超时的流程,特别是InputDispatcher中keyDispatchingTimedOut和inputDispatchingTimedOut的情况。当输入事件处理超时时,系统会触发ANR对话框,并通过一系列回调通知Activity Manager Service(AMS)。ANR处理涉及AMS与Window Manager Service(WMS)之间的交互,以及堆栈信息的dump,以帮助开发者诊断问题。
摘要由CSDN通过智能技术生成

一、ANR简介

ANR:全称是Application Not Respond,就是应用程序无响应,这也是经常会发生的一种问题,任何一个应用程序都有主线程,在Android中,因为UI的操作都在主线程中完成,所以主线程也被成为UI线程,UI线程中会做一些和用户交互相关性非常大的工作,所以UI线程不能有明显的卡顿,一般我们不建议在UI线程中执行较耗时的操作。如果一些粗心的开发者在UI线程中做了一些耗时的操作,会有非常明显的卡顿,严重的情况下还会产生ANR。

二、ANR产生机制

硬件收集到的输入事件都会插入到WindowManagerService.mQueue(KeyQ类)中,同时 WindowManagerService.InputDispatcherThread这个线程运行在系统进程中,它循环地处理 mQueue内的消息。InputDispatcherThread在处理事件的过程中,会不断的检测处理过程是否超时,一旦超时,会通过一 系列的回调通知AMS,由AMS控制弹出ANR对话框。

超时检测处理过程实际上是一个wait()/notify()的过程。首先,如果一个输入事件进入检测流程时,发现当前正在处理输入事件,就会调用 wait()阻塞输入事件处理线程,wait的时间为10s。在一个输入事件处理完成时,会调用notify()让输入事件处理线程继续执 行。继续执行时就会计算整个过程一共花了多长时间来判断是否是ANR。

三、流程解析

3.1 ContentProvider处理的时候发生超时

ContentProviderClient中提供了setDetectNotResponding(…)函数来帮助监听ContentProvider的超时情况,不过一般情况下都没有ContentProvider会这么设置,反正Android在这里提供给开发者一种思路,ContentProvider是提供超时保护的。

3.2 InputDispatcher发生超时

但是正常情况下还是第2种发生的次数比较多,第1种目前发生的次数比较少,其实原理都是都是一样的。ContentProvider处理的时候发生超时,就是本地操作本地的content provider发生延时。本文主要从InputDispatcher发生超时讲解。

这要从本地的inputFlinger讲起,Android系统处理input时间的就是inputFlinger,每次处理input 事件的时候,要执行到native的一个方法:
frameworks/native/services/inputflinger/InputDispatcher.cpp中的findFocusedWindowTargetsLocked(…)方法,每次处理input的事件的时候都会走到这个函数中。此函数中在开始的时候有一段关键的判断代码:

if (mFocusedWindowHandle == NULL) {
   

        if (mFocusedApplicationHandle != NULL) {
   

            injectionResult = handleTargetsNotReadyLocked(currentTime, entry,

                    mFocusedApplicationHandle, NULL, nextWakeupTime,

                    "Waiting because no window has focus but there is a "

                    "focused application that may eventually add a window "

                    "when it finishes starting up.");

            goto Unresponsive;

        }

 

        ALOGI("Dropping event because there is no focused window or focused application.");

        injectionResult = INPUT_EVENT_INJECTION_FAILED;

        goto Failed;

    }

 

如果当前没有焦点窗口且没有焦点应用程序,然后放弃事件。继续往下看,执行的handleTargetsNotReadyLocked(…)函数:

int32_t InputDispatcher::handleTargetsNotReadyLocked(nsecs_t currentTime,

        const EventEntry* entry,

        const sp<InputApplicationHandle>& applicationHandle,

        const sp<InputWindowHandle>& windowHandle,

        nsecs_t* nextWakeupTime, const char* reason) {
   

//......

nsecs_t timeout;

            if (windowHandle != NULL) {
   

                timeout = windowHandle->getDispatchingTimeout(DEFAULT_INPUT_DISPATCHING_TIMEOUT);

            } else if (applicationHandle != NULL) {
   

                timeout = applicationHandle->getDispatchingTimeout(

                        DEFAULT_INPUT_DISPATCHING_TIMEOUT);

            } else {
   

                timeout = DEFAULT_INPUT_DISPATCHING_TIMEOUT;

            }

//......

 

if (currentTime >= mInputTargetWaitTimeoutTime) {
   

        onANRLocked(currentTime, applicationHandle, windowHandle,

                entry->eventTime, mInputTargetWaitStartTime, reason);

 

        // Force poll loop to wake up immediately on next iteration once we get the

        // ANR response back from the policy.

        *nextWakeupTime = LONG_LONG_MIN;

        
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值