什么是背景ANR?它与 ANR 有什么不同?

问题描述 投票:0回答:1

问题很简单,在我的应用程序的系统日志中,我得到了receiver的背景

ANR
,并且线程ID不是UI。想了解ANR的背景以及可能发生的方式。

android android-anr-dialog
1个回答
0
投票

我在官方手册中没有找到关于“bg anr”的详细解释,但是在android框架的源码中还是有一些线索的:

final void appNotResponding(...) {
    ...
    synchronized (mService) {
        isSilentANR = !showBackground && !isInterestingForBackgroundTraces(app);
        ...
    }
    ...
    File tracesFile = ActivityManagerService.dumpStackTraces(
            true, firstPids,
            (isSilentANR) ? null : processCpuTracker,
            (isSilentANR) ? null : lastPids,
            nativePids);

    synchronized (mService) {
        if (isSilentANR) {
            app.kill("bg anr", true);
            return;
        }
        ...

        //Show anr dialog
        Message msg = Message.obtain();
        msg.what = ActivityManagerService.SHOW_NOT_RESPONDING_UI_MSG;
        msg.obj = new AppNotRespondingDialog.Data(app, activity, aboveSystem);
        mService.mUiHandler.sendMessage(msg);
    }
}

上面代码中的silentANR表示满足以下两个条件:

  • 这是一个bg anr
  • 设备的
  • 开发者选项中未启用显示所有 ANR

而silentANR不会显示ANR对话框,而是直接杀死App进程

所以函数

isInterestingForBackgroundTraces(app)
判断是fg anr还是bg anr,参考https://android.googlesource.com/platform/frameworks/base/+/android-8.0.0_r4/services/core/java /com/android/server/am/AppErrors.java#756

static boolean isInterestingForBackgroundTraces(ProcessRecord app) {
    // The system_server is always considered interesting.
    if (app.pid == MY_PID) {
        return true;
    }
    // A package is considered interesting if any of the following is true :
    //
    // - It's displaying an activity.
    // - It's the SystemUI.
    // - It has an overlay or a top UI visible.
    //
    // NOTE: The check whether a given ProcessRecord belongs to the systemui
    // process is a bit of a kludge, but the same pattern seems repeated at
    // several places in the system server.
    return app.isInterestingToUserLocked() ||
        (app.info != null && "com.android.systemui".equals(app.info.packageName)) ||
        (app.hasTopUi || app.hasOverlayUi);
}

总结一下,判断是fg还是bg anr取决于anr发生时App是否能够被用户感知。例如,具有当前在前台可见的活动的进程,或者具有带前台通知的 fg-service 的进程。这些都是anr发生时用户能够感知到的情况。对用户体验影响很大,所以需要弹出对话框让用户决定是退出还是等待。如果直接杀掉这类fg App,会导致用户莫名其妙的崩溃。

与 fg anr 相比,bg anr 将在后台直接被杀死,无需向用户对话,除非在设备的开发者选项中启用了显示所有 ANR。默认情况下它是禁用的。

还有一些测试结果可以证明这一点:

首先,我在

onReceive()
方法中定义了一个仅休眠 100 秒的广播接收器。

然后用

sendOrderedBroadcast()
sendBroadcast()
进行测试: | | sendOrderedBroadcast(意图,空)|发送广播(意图)| | -------- | -------------- |-------------- | | - 显示活动的应用程序
(无论是否启用显示所有ANR)| anr 发生,并带有对话|完全没有anr| | - 应用程序未显示任何活动
- 显示所有 ANR 已禁用 |出现 anr,应用程序在没有对话框的情况下被杀死|根本没有 anr | | - 应用程序未显示任何活动
- 显示所有 ANR 已启用 |出现 anr,并带有对话框 |根本没有 anr |

顺便说一句,是否是

FLAG_RECEIVER_FOREGROUND
与是fg anr还是bg anr无关。但它决定了时间,这是测试结果: |
intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);

sendOrderedBroadcast(intent, null);
|
// no flag

sendOrderedBroadcast(intent, null);
| | -------- | -------------- | |阻塞10s后出现anr |阻塞60s后出现anr |

  • 测试设备:模拟器 Pixel 5 API 31

感谢Gityuan:

© www.soinside.com 2019 - 2024. All rights reserved.