系统app开发调试方式
平时我们都是使用dumpsys来输出某个服务的相关信息,比如dumpsys SurfaceFlinger,dumpsys window windows等。
这些其实都是系统的service情况信息输出,但是大家是否有想过我们普通的app想要进行dump应该如何呢?比如我想要在查看调试自己写的Activity相关的信息如何查看呢?
这个就是我们今天要来分享的一个dump app的相关相关信息方式。
dump命令使用
命令格式
Activity的dump方式
dumpsys activity xxxx(Activity类名)
这里的xxxx最好写出全类名。

Service的dump方式
比如要dump Launcher的某个service那么格式如下:
adb shell dumpsys activity service xxx(某个Service名字)
案例:
adb shell dumpsys activity service TouchInteractionService
或者
adb shell dumpsys activity service com.android.launcher3/com.android.quickstep.TouchInteractionService
这些Activity名字和Service名字哪里获取呢?
可以使用dumpsys package xxx包名。
比如桌面有哪些Activity和Service
adb shell dumpsys package com.android.launcher3

本文基于 adb shell dumpsys activity QuickstepLauncher 命令的输出,结合 AOSP16-r4 Launcher3
源码,逐段解析每个 dump 信息的作用和调试价值。
1. Activity 生命周期与状态 (ActivityRecord)
TASK null id=23 userId=0 displayId=0(type=INTERNAL)
ACTIVITY com.android.launcher3/.uioverrides.QuickstepLauncher 5bb04f pid=1382 userId=0 uid=10122 displayId=0(type=INTERNAL)
Local Activity 869e2cf State:
mResumed=true mStopped=false mFinished=false
mIsInMultiWindowMode=false mIsInPictureInPictureMode=false
mChangingConfigurations=false
mCurrentConfig={1.0 310mcc260mnc [en_US] ldltr sw360dp w360dp h640dp 480dpi nrml long compactNeeded port ...}
mLoadersStarted=true
来源:Android 框架层 ActivityRecord.dump()(系统侧 dump,非 Launcher 自己控制)。
各字段含义:
| 字段 | 含义 | 调试场景 |
|---|---|---|
TASK null id=23 | Task ID 为 23,null 表示没有关联的 Task 对象引用 | Activity 任务栈跟踪 |
userId=0 | 运行在系统用户 (Owner) | 多用户问题排查 |
displayId=0 | 运行在内置主屏幕 (DEFAULT_DISPLAY) | 多屏/外接显示器排查 |
pid=1382 | Launcher 进程 PID | 进程存活/CPU 占用排查 |
uid=10122 | Launcher 应用 UID | 权限问题排查 |
mResumed=true | Activity 处于 Resumed 状态(前台可见可交互) | Launcher 是否在前台 |
mStopped=false | Activity 未被停止 | onStop() 是否调用 |
mFinished=false | Activity 未结束 | 是否正在退出 |
mIsInMultiWindowMode=false | 未处于多窗口/分屏模式 | 多窗口适配问题 |
mIsInPictureInPictureMode=false | 未处于画中画 | PiP 行为排查 |
mChangingConfigurations=false | 未正在处理配置变更 | 配置变更卡死排查 |
mCurrentConfig | 当前 Configuration 完整快照 | 屏幕密度/语言/屏幕尺寸异常 |
mLoadersStarted=true | Loader 已启动(数据加载或 ContentProvider 就绪) | 数据加载时序问题 |
调试价值:这是第一个要看的区域。如果 Launcher 行为异常,先确认它是否处于预期生命周期状态。
相关源码:
// QuickstepLauncher.java 继承自 Launcher extends BaseActivity
// 生命周期回调在 Launcher.java 中:
// onResume() -> onPause() -> onStop() -> onDestroy()
// 以及 onActivityFlagsChanged() 处理状态标志变化
2. ViewRoot 渲染系统
其实这部分数据就是把我们熟悉的ViewRootImpl.java相关的数据进行输出。
ViewRoot:
mAdded=true mRemoved=false mStopped=false
mPausedForTransition=false
mConsumeBatchedInputScheduled=false
mPendingInputEventCount=0
mTraversalScheduled=false
mReportNextDraw=false
来源:ViewRootImpl.dump(),是每个 Window 的顶层渲染管理器。
各字段含义:
| 字段 | 含义 | 调试场景 |
|---|---|---|
mAdded=true | ViewRoot 已添加到 WindowManager | Window 是否成功添加 |
mRemoved=false | 未被移除 | Window 泄漏排查 |
mStopped=false | 未停止 | Window 是否可见 |
mPausedForTransition=false | 未因转场动画暂停渲染 | 转场动画卡顿排查 |
mPendingInputEventCount=0 | 无待处理输入事件 | 输入事件积压排查 |
mTraversalScheduled=false | 无待执行的 measure/layout/draw | UI 是否空闲 |
mReportNextDraw=false | 不需要报告下一次绘制 | 绘制完成通知 |
调试价值:用于诊断 UI 渲染问题。如果 mTraversalScheduled=true 且长时间不变,
说明可能发生了 measure/layout 死循环或阻塞。
相关源码:
// QuickstepLauncher.java: onCreate()
getWindow().addPrivateFlags(PRIVATE_FLAG_OPTIMIZE_MEASURE);
// PRIVATE_FLAG_OPTIMIZE_MEASURE 优化 measure 过程,减少过度测量
2.1 app层收到事件处理理
android.view.ViewRootImpl$NativePreImeInputStage: mQueueLength=0
android.view.ViewRootImpl$ImeInputStage: mQueueLength=0
android.view.ViewRootImpl$NativePostImeInputStage: mQueueLength=0
含义:三阶段输入管道队列长度均为 0,说明当前没有积压的输入事件。
2.2 Configuration 报告
mLastReportedMergedConfiguration={mGlobalConfig=... mOverrideConfig=...}
mLastConfigurationFromResources={...}
含义:最后一次报告的全局配置与 Override 配置。mOverrideConfig 中
mActivityType=home 表示这是 Home Activity。
3. InsetsController — 窗口边距
InsetsController:
mDisplayFrame=Rect(0, 0 - 1080, 1920)
InsetsSource id=d1660001 type=navigationBars frame=[0,1848][1080,1920] visible=true
InsetsSource id=d6d50000 type=statusBars frame=[0,0][1080,72] visible=true
InsetsSource id=3 type=ime frame=[0,0][0,0] visible=false
来源:InsetsController.dump(),管理系统栏(状态栏、导航栏、输入法)对窗口的边距影响。
关键条目解读:
| 条目 | 含义 |
|---|---|
navigationBars [0,1848][1080,1920] | 导航栏占据底部 72px(1920-1848),在 y=[1848,1920] |
systemGestures [0,0][90,1920] | 左侧 90px 是系统手势区域(返回手势) |
systemGestures [990,0][1080,1920] | 右侧 90px 是系统手势区域 |
statusBars [0,0][1080,72] | 状态栏占据顶部 72px |
mandatorySystemGestures [0,1824][1080,1920] | 底部 96px 强制手势区域(保留区) |
ime frame=[0,0][0,0] visible=false | 输入法未弹出(大小为 0) |
调试价值:
- 确认设备是手势导航还是三键导航(有
systemGestures区域 = 手势导航) - 排查内容被系统栏遮挡的问题
- 确认 IME 弹出/收起状态
4. View Hierarchy — 视图树(最核心)
平时要看View的层级都是需要通过布局抓取工具等来查看,那么这个dump方式也算是最简单的方式来获取。
com.android.internal.policy.DecorView{9104c85}[QuickstepLauncher]
android.widget.LinearLayout
android.widget.FrameLayout #1020002 android:id/content
com.android.launcher3.LauncherRootView #7f0901e3 app:id/launcher
com.android.launcher3.dragndrop.DragLayer #7f090144 app:id/drag_layer
com.android.launcher3.views.AccessibilityActionsView
com.android.launcher3.Workspace #7f090409 app:id/workspace
com.android.launcher3.CellLayout
ShortcutAndWidgetContainer
QsbContainerView #7f0902ef app:id/search_container_workspace
...
com.android.launcher3.Hotseat #7f0901b4 app:id/hotseat
DoubleShadowBubbleTextView (4 icons)
PageIndicator (page_indicator_container)
DropTargetBar #7f090146 (drop_target_bar)
ScrimView #7f0902dd (scrim_view)
LauncherRecentsView #7f090282 (overview_panel)
OverviewActionsView #7f090281
LauncherAllAppsContainerView #7f090098 (apps_view)
含义:完整的 View 层级结构,展示了从 DecorView 到每个子 View 的树状关系。
下面图这个桌面的view展示情况就可以与上面布局完全匹配,偶尔需要自己模拟触摸事件,或者说让ai来模拟点击测试时候,如果ai不知道如何获取控件坐标也可以提醒使用这种dump方式。

关键视图与源码对应:
| View 类 | 作用 |
|---|---|
LauncherRootView | Launcher 的根 ViewGroup |
DragLayer | 拖拽事件分发层,所有 TouchController 在此注册 |
Workspace | 主屏幕工作区,包含 CellLayout 页面 |
CellLayout | 单个主屏幕页面,管理图标/Widget 网格布局 |
QsbContainerView | 搜索框容器(Quick Search Box) |
Hotseat | 底部固定快捷栏(Hotseat) |
PageIndicator | 页面指示器(圆点) |
DropTargetBar | 拖拽目标区域(删除/卸载) |
ScrimView | 模糊/暗色遮罩层 |
LauncherRecentsView | 最近任务概览视图(Overview) |
OverviewActionsView | 概览页操作按钮(截图、分屏) |
LauncherAllAppsContainerView | 所有应用列表视图 |
PredictionRowView | 应用预测行 |
相关源码:
// QuickstepLauncher.java: setupViews()
mActionsView = findViewById(R.id.overview_actions_view);
RecentsView overviewPanel = getOverviewPanel();
overviewPanel.init(mActionsView, mSplitSelectStateController, ...);
// Launcher.java: setupViews()
mDragLayer = findViewById(R.id.drag_layer);
mWorkspace = mDragLayer.findViewById(R.id.workspace);
调试价值:这是最重要的调试区域之一:
- 检查 View 是否被正确添加到层级中
- 通过
V.E......等标志查看 View 的 visibility 和 enable 状态 G.ED.....中G= GONE,I= INVISIBLE- 确认视图树结构是否符合预期
如何Activity等dump中加入自定义信息
这个其实Activity,Service等类本身自带了相关的dump方法:
我们只需在自己Activity方法中进行重写dump,然后加入自己的一些自定义想要dump东西

原文地址,更多fw干货获取:
https://mp.weixin.qq.com/s/jufOkfC_OlJqd1U9NyuTYw
464



被折叠的 条评论
为什么被折叠?



