乐于分享
好东西不私藏

系统app开发之桌面调试Launcher3 Dumpsys信息解析

系统app开发之桌面调试Launcher3 Dumpsys信息解析

系统app调试之 Dumpsys 调试信息解析

平时我们都是使用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东西

更多vip免费系统开发经典大厂面试题库获取,课程优惠购买成为vip学员进入vip群,积极讨论各种行业难点痛点疑难问题,答疑服务等。

请联系马哥微信:

目前所有专题课程如下:
1、经典fw的入门到精通实战八件套专题
详细课表:
Android Framework开发rom实战合集课表/车载车机手机高级系统开发工程必会技能
重大消息:Hal+perfetto-systrace+SurfaceFlinger合集新专题发布