使用Perfetto进行Settings中网络热点开启后anr分析的整体流程记录

目录

一.背景

二.Perfetto使用流程

[阶段一:抓取 Perfetto Trace 文件](#阶段一:抓取 Perfetto Trace 文件)

[1. 指令核心解析](#1. 指令核心解析)

[2. 数据源功能详解 (这些是抓取的"维度")](#2. 数据源功能详解 (这些是抓取的“维度”))

[3. 该指令的作用场景](#3. 该指令的作用场景)

[阶段二:导入并认识 Perfetto UI 面板](#阶段二:导入并认识 Perfetto UI 面板)

[1. 致命异常:Duration: (Did not end)](#1. 致命异常:Duration: (Did not end))

[2. 定位到的业务范围](#2. 定位到的业务范围)

[1. 核心异常:CPU 4 被 dnsmasq 进程占满](#1. 核心异常:CPU 4 被 dnsmasq 进程占满)

[2. 线程唤醒关系:system_server 在"垂死挣扎"](#2. 线程唤醒关系:system_server 在“垂死挣扎”)

[3. 渲染线程 (RenderThread) 的反常表现](#3. 渲染线程 (RenderThread) 的反常表现)

综合诊断结果:

三.结合日志排查

[1. 核心含义:dnsmasq 疯了(CPU 占用接近 100%)](#1. 核心含义:dnsmasq 疯了(CPU 占用接近 100%))

[2. 为什么会导致 Settings ANR?](#2. 为什么会导致 Settings ANR?)

[3. dnsmasq 是干什么的?](#3. dnsmasq 是干什么的?)

[TetherOffload HAL 与 dnsmasq](#TetherOffload HAL 与 dnsmasq)

[1. 技术背景:为什么需要 TetherOffload?](#1. 技术背景:为什么需要 TetherOffload?)

[2. TetherOffload 的作用](#2. TetherOffload 的作用)

[3. 两者的具体协作与区别](#3. 两者的具体协作与区别)

协作流程:

[4. 总结:它们是互补的](#4. 总结:它们是互补的)

[四.修复TetherOffload 相关内容后](#四.修复TetherOffload 相关内容后)


一.背景

测试提了一个问题,Settings中打开热点后直接卡死然后anr,之前我一般都是通过日志和AndroidStudio Profile进行分析的,需要看我之前分析流程的可以参考如下资料:

https://blog.csdn.net/gongjdde/article/details/134859886

本次使用Perfetto结合日志进行排查

二.Perfetto使用流程

阶段一:抓取 Perfetto Trace 文件

抓取数据主要有两种方式,对于排查系统层面的服务死锁和底层阻塞,强烈推荐使用命令行方式,因为你可以精确配置需要监控的数据源。

1. 命令行方式(推荐) 通过 adb 连接你的测试设备,在终端输入以下命令。这个命令会抓取 CPU 调度、系统调用、Binder 通信以及核心系统服务的状态。

bash 复制代码
adb shell perfetto -o /data/misc/perfetto-traces/trace_file.perfetto-trace -t 15s sched freqs idle am wm gfx view binder_driver hal dalvik res

-t 15s 表示持续抓取 15 秒。你可以先敲下回车开始录制,然后在手机上迅速复现那个"打开网络设置导致卡顿"的操作。

以下是对该指令各部分的详细拆解:

1. 指令核心解析

  • adb shell: 通过 ADB 在 Android 设备内部执行命令。
  • perfetto: 调用系统中的性能跟踪程序。
  • -o /data/misc/perfetto-traces/trace_file.perfetto-trace :
    • 指定输出文件的存储路径。
    • 路径通常位于 /data/misc/perfetto-traces/,因为该目录具有合适的读写权限,抓取完毕后可以用 adb pull 将文件传回电脑进行分析。
  • -t 15s: 指定跟踪时长为 15 秒。执行后,系统会立即开始记录,15 秒后自动停止并保存文件。
  • [数据源列表] : 紧跟在末尾的参数(sched freqs idle am wm gfx view binder_driver hal dalvik res)是数据源(Data Sources),用于指定需要记录哪些内核和应用层的事件。

2. 数据源功能详解 (这些是抓取的"维度")

这些参数决定了 Trace 文件中包含哪些信息:

  • sched : 调度器事件。记录 CPU 线程的调度信息(Task 切换、唤醒、休眠)。这是分析"卡顿"最核心的数据。
  • freqs : 频率信息。记录 CPU 频率(CPU Freq)的变化。用于分析是否存在 CPU 降频导致性能不足。
  • idle : 空闲状态。记录 CPU 进入 Idle 状态的时间点,分析功耗问题。
  • am (Activity Manager): 记录 Android 系统的 Activity 启动、生命周期事件。
  • wm (Window Manager): 记录窗口管理器的相关事件,比如窗口的显示、隐藏、Layer 的刷新。
  • gfx (Graphics) : 图形相关。记录 SurfaceFlinger、Vsync、渲染帧等关键信息,分析掉帧(Jank)必备。
  • view : View 系统事件。记录 Android UI 控件的 Measure、Layout、Draw 流程。
  • binder_driver : Binder 驱动事件。记录进程间通信(IPC)的详细耗时,分析是哪个服务调用导致了阻塞。
  • hal : HAL 层事件。记录硬件抽象层(如 Camera、传感器、音频 HAL)的调用,分析硬件驱动层的延迟。
  • dalvik : 虚拟机事件。记录 GC(垃圾回收)、JIT 编译等事件。
  • res : 资源加载。记录一些资源加载、系统属性的变化。

3. 该指令的作用场景

这个指令通常用于排查性能卡顿(Jank/Lag)或功耗异常

  • 场景 1:分析 UI 卡顿
    • 通过 gfxview 可以看到 UI 刷新是否掉帧。
    • 通过 schedbinder_driver 可以分析是否因为某个线程一直抢占 CPU 或被某个 Binder 调用阻塞导致界面无法及时响应。
  • 场景 2:分析应用启动慢
    • 通过 amwm 可以看到 Activity 启动的完整过程,配合 binder_driver 找出在哪个通信环节耗时过长。
  • 场景 3:分析功耗或发热
    • 通过 freqsidle 结合 sched,查看 CPU 是否一直保持高频,或者频繁进行不必要的线程唤醒。

完成后,将生成的 Trace 文件 pull 到电脑上:

bash 复制代码
adb pull /data/misc/perfetto-traces/trace_file.perfetto-trace .

阶段二:导入并认识 Perfetto UI 面板

拿到 Trace 文件后,我们需要使用 Google 提供的网页端工具来可视化分析。

1. 打开网页加载数据 在浏览器(推荐 Chrome 或 Edge)中打开官方分析工具:ui.perfetto.dev 将刚才导出的 .perfetto-trace 文件直接拖拽进网页中央。

2. 核心操作快捷键(必记) Perfetto 的界面信息量极其庞大,单纯依靠鼠标拖拽效率很低,熟练使用以下快捷键是必备技能:

  • W / S:放大 / 缩小时间轴(Zoom In / Out)。这在精确定位毫秒级耗时时非常有用。

  • A / D:向左 / 向右平移时间轴。

  • M:高亮选中一段区域。鼠标框选一段时间后按 M,可以固定高亮,用于查看这段时间内的系统整体负载。

如下是将trace文件导入到网页后的界面

1. 致命异常:Duration: (Did not end)

这是最核心的发现。

  • 含义performCreate 这个方法一直没有执行完

  • 分析 :在 Perfetto 录制的这段时间里(甚至直到录制结束),主线程都卡在这个方法内部。按照 Android 机制,主线程被阻塞超过 5 秒就会触发 ANR。你这里的阻塞长度已经贯穿了整个 Trace 视图,说明主线程彻底"死"在了 SubSettings 的创建过程中。

2. 定位到的业务范围

  • Name : performCreate:com.android.settings.SubSettings

  • 分析 :这说明点击设置项(大概率是网络相关的二级菜单)后,系统尝试初始化 SubSettings 页面。所有该页面的 Fragment 初始化、onCreate 生命周期逻辑、以及各种 Preference 状态的获取都在这个方法里同步执行。

然后我们继续看上面有没有什么异常

1. 核心异常:CPU 4 被 dnsmasq 进程占满

在第二张图的 CPU 4 Scheduling 轨道上,你可以看到大段的橙黄色块 ,上面标注着进程名为 dnsmasq [5252]

  • 现象dnsmasq 在 CPU 4 上几乎是持续运行的,这意味着它在进行高强度的任务。

  • 关联性dnsmasq 通常与 热点(Tethering)和 DNS 转发 相关。结合你之前日志里提到的 tetheroffload 报错,这说明在你打开设置页面的那一刻,热点相关的网络后台进程正在发生严重的异常(可能是死循环或大量的网络包处理)。

2. 线程唤醒关系:system_server 在"垂死挣扎"

查看右下角的 Scheduling Latency 面板:

  • Wakeup 信息显示:RenderThread 4589 是被 system_server [1926] 里的 binder:1926_5 唤醒的。

  • 分析 :这证实了 system_server 一直在试图与 Settings 进程通信。但由于 dnsmasq 占用了大量资源,或者 dnsmasq 阻塞了某种系统级的网络锁(Mutex),导致通信效率极低。

3. 渲染线程 (RenderThread) 的反常表现

  • 现象 :第一张图显示 main thread 卡死在 performCreate(紫色长条),但下方的 RenderThread 却有密集的绿条和 prepareAndDraw

  • 解释 :这说明 Settings 的 UI 逻辑层(主线程)已经彻底瘫痪了,但渲染层(RenderThread)还在尝试刷新画面(比如显示一个进度条或者处理上一次的绘制请求)。这种"主线程死锁,渲染线程还在跑"的现象是典型的 同步逻辑阻塞


综合诊断结果:

这是一个由网络子系统(dnsmasq/Tethering)引起的系统级阻塞导致的 ANR。

  1. 根源dnsmasq 进程异常,占用了核心 CPU 资源。

  2. 连锁反应 :当你进入 SubSettings(网络设置页面)时,主线程发起了一个同步请求去获取热点或网络配置。

  3. 死锁 :由于 dnsmasq 处于异常状态,或者它持有了某个底层的硬件访问锁,导致 Settings 发出的请求永远得不到回应。

  4. 结果 :主线程在 performCreate 阶段永久等待,5 秒后触发 ANR。

上述是整个Perfetto的排查流程,它排查出可能是**网络子系统(dnsmasq/Tethering)引起的系统级阻塞导致的 ANR。**然后我们继续结合日志进行后续排查

三.结合日志排查

首先抓取 dnsmasq 日志 : 执行 adb logcat | grep dnsmasq,看看有没有 timeoutfailed to bind 之类的报错。

这几行日志是 ANR(应用无响应)调查的"冒烟证据" 。它解释了为什么你的 Settings 进程会卡死:系统资源被耗尽了。

具体分析如下:

1. 核心含义:dnsmasq 疯了(CPU 占用接近 100%)

日志显示 dnsmasq(进程号 5252)持续占用了 95% - 98% 的 CPU 资源。

  • User (用户态) vs Kernel (内核态)

    • 00:00:47 之后的记录中,dnsmasqKernel 占用高达 85% 左右

    • 这说明dnsmasq 并不是在做复杂的计算,而是陷入了某种严重的内核级阻塞或死循环。它可能在不停地尝试读写一个损坏的网卡接口、处理海量的恶意网络包,或者在不停地申请/释放内核锁。

2. 为什么会导致 Settings ANR?

结合你之前的 Perfetto 图表,逻辑链条现在闭合了:

  1. 抢占资源dnsmasq 几乎吃光了 CPU 资源(尤其是你截图里看到的 CPU 4)。

  2. Binder 响应超时 :当你在 Settings 里打开网络设置时,主线程需要通过 Binder 去问 system_server 现在的网络状态。由于 CPU 被 dnsmasq 占满,加上可能存在的内核锁竞争,这个 Binder 请求发不出去或者回不来。

  3. 主线程挂起 :主线程在 performCreate 阶段等不到数据,直接卡死。

3. dnsmasq 是干什么的?

在 Android 中,dnsmasq 主要负责:

  • 热点(Tethering):为连接到你手机热点的设备分配 IP 地址(DHCP)和解析域名(DNS)。

  • 如果你当时开启了热点,或者有设备正在频繁尝试连接你的热点,可能触发了它的 Bug。

然后我们看下logcat中关键的日志,如下日志是一直反复出现:

bash 复制代码
2025-09-10 14:20:31.719  3214-3251  HidlServiceManagement   com.android.networkstack.process     W  Waited one second for android.hardware.tetheroffload.config@1.0::IOffloadConfig/default
2025-09-10 14:20:31.719   692-692   hwservicemanager        hwservicemanager                     I  Since android.hardware.tetheroffload.config@1.0::IOffloadConfig/default is not registered, trying to start it as a lazy HAL (if it's not configured to be a lazy HAL, it may be stuck starting or still starting).
2025-09-10 14:20:31.720  3214-3251  HidlServiceManagement   com.android.networkstack.process     I  getService: Trying again for android.hardware.tetheroffload.config@1.0::IOffloadConfig/default...
2025-09-10 14:20:31.720  1929-6233  system_server           system_server                        I  libdebuggerd_client: started dumping process 1529
2025-09-10 14:20:31.721   692-6363  libc                    hwservicemanager                     W  Unable to set property "ctl.interface_start" to "android.hardware.tetheroffload.config@1.0::IOffloadConfig/default": error code: 0x20
2025-09-10 14:20:31.722   692-6363  hwservicemanager        hwservicemanager                     I  Tried to start android.hardware.tetheroffload.config@1.0::IOffloadConfig/default as a lazy service, but was unable to. Usually this happens when a service is not installed, but if the service is intended to be used as a lazy service, then it may be configured incorrectly.

日志中提到 android.hardware.tetheroffload.config 服务启动失败,虽不一定是直接原因,但这类驱动或 HAL 层的异常往往会导致 system_server 挂起,进而引发连锁反应导致应用 ANR。

然后我们找一下TetherOffload HALdnsmasq 的关系

TetherOffload HALdnsmasq

1. 技术背景:为什么需要 TetherOffload?

在传统的 Android 热点共享模式下,数据包的转发路径是: 客户端 -> 手机 Wi-Fi 网卡 -> 内核网络协议栈 -> 用户空间的 dnsmasq/netd -> 内核协议栈 -> 移动网络 (LTE/5G)

  • 问题所在 :数据包需要在"内核态"和"用户态"之间来回切换(Context Switching)。如果手机开启热点且连接设备较多,CPU 需要处理大量中断和数据拷贝,导致耗电增加、发热严重、带宽受限

2. TetherOffload 的作用

TetherOffload(全称 Tethering Offload HAL)旨在将这些繁重的"数据转发"任务从 CPU 卸载到 硬件(如基带芯片、网络加速引擎或专门的 SoC 卸载模块) 上处理。

  • 它的核心逻辑:只要连接状态和路由规则稳定,后续的数据包就不再经过用户空间的软件栈,直接由硬件电路在 Wi-Fi 网卡和蜂窝数据网卡之间进行"物理转发"。

3. 两者的具体协作与区别

特性 dnsmasq TetherOffload HAL
定位 控制平面 (Control Plane) 数据平面 (Data Plane)
职责 负责 DHCP 分配、DNS 缓存、路由表维护 负责实际的数据报文转发、NAT 映射
运行层级 用户空间 (User Space) 内核空间 (Kernel) + 硬件驱动
存在意义 告诉网络"谁是谁,去哪儿" 告诉硬件"怎么飞速传输数据"
协作流程:
  1. 启动阶段dnsmasq(或 Android 现在的 netd 方案)首先运行,处理 DHCP 请求,为连接的设备分配 IP,并设置防火墙规则(iptables/nftables)。
  2. 配置阶段 :Android 系统将这些连接信息和转发规则通过 TetherOffload HAL 下发给底层的硬件驱动。
  3. 运行阶段 :一旦连接稳定,TetherOffload 激活。此时,绝大部分数据流绕过用户空间的 dnsmasq,由硬件直接处理;只有极少数控制指令或不符合卸载规则的流量,才会回退到软件栈处理。

4. 总结:它们是互补的

  • dnsmasq 是"大脑":负责处理逻辑复杂但频率不高的网络控制任务(比如刚连上热点时 IP 怎么发、域名怎么解析)。
  • TetherOffload 是"肌肉":负责处理极其枯燥、耗费资源的纯数据流转发任务。

简而言之: 在现代 Android 系统中,TetherOffload 极大地降低了对 dnsmasq 处理高并发数据流的依赖。 现在的 Android 倾向于让 dnsmasq 只负责轻量级的 IP 分配,而将沉重的流量处理交给 TetherOffload 以提升系统性能。如果你的设备关闭了 TetherOffload(例如在某些深度定制的系统或极客修改环境下),你会明显感觉到热点速度下降且手机发热加剧,因为所有的流量压力都回到了 CPU 和软件进程上。

可以看出来TetherOffload异常可能就会导致dnsmasq异常

四.修复TetherOffload相关内容后

由于TetherOffload这块是hal层逻辑,所以是其他同事修复的,然后我们就看修复后的变化,有没有解决问题

首先点击界面没有anr看了,然后我们看看Perfetto界面的变化

如下是修复后的Perfetto界面

可以看出来Settings的performCreate:com.android.settings.SubSettings耗时56ms,时间大大缩短了,不会导致anr

然后继续看

可以看出来几乎没有dnsmasq 进程占用cpu了,所以综合分析是TetherOffload 异常导致dnsmasq 进程一直在疯狂吃cpu,导致Settings没法响应了

相关推荐
23zhgjx-zgx2 小时前
华为ensp:配置Local区域的安全策略及ASPF配置
网络·华为
半壶清水2 小时前
[软考网规考点笔记]-局域网之HDLC 协议
网络·笔记·网络协议·考试
123过去3 小时前
pixiewps使用教程
linux·网络·测试工具·算法·哈希算法
RMB Player3 小时前
Spring Boot 集成飞书推送超详细教程:文本消息、签名校验、封装工具类一篇搞定
java·网络·spring boot·后端·spring·飞书
JicasdC123asd5 小时前
CGNet上下文引导网络改进YOLOv26下采样特征保留能力
网络·yolo
Name_NaN_None5 小时前
Linux 使用 Remmina 连接 Windows 远程桌面 ——「小白教程」
linux·网络·电脑·远程工作
2401_865721336 小时前
WEB 学习框架搭建
网络·学习·web
LlNingyu6 小时前
文艺复兴, 什么是XSS,常见形式(三)
网络·安全·xss
123过去6 小时前
reaver使用教程
linux·网络·测试工具·智能路由器