夜雨聆风学习资料网

ARTICLE · 1122300

深入剖析为什么app热启动Activity可以实现秒开体验?

深入剖析为什么app热启动Activity可以实现秒开体验?

背景

昨天国庆放假期间,有vip学员也在学习马哥性能相关课程,有个同学也提出疑问:“热启动虽然很快哪怕耗时100ms,虽然比冷启动短了很多,但那也是有一定时间延时的?但是真实打开热启动的app时候,感觉非常流畅,丝毫没有感觉到有任何的卡顿。”

针对这个问题其实解答起来就需要对冷启动app和热启动app整个过程进行抓取相关的perfetto分析。

perfetto抓取分析对比法

前面课程文章有对冷启动的Splash Window进行了详细的,但是大家是否有想过热启动时候的是否也需要有类似的Splash Window呢? 答案是肯定的,具体可以通过WinScope或者Perfetto抓取暖启动的过程来验证:

暖启动的StartingWindow

其实桌面的暖启动也会有一个StartingWindow,名字叫做SnapshotStartingWindow,他的启动时间明显比冷启动SplashWindow要快很多,几乎为SplashWindow时间的1/2,可以看到点击后,SnapshotStartingWindow在68ms后就进行了上帧。

再看看冷启动的SplashWindow的时间:

可以看出桌面点击后,要118ms才有Splash window的绘制帧数据。

SnapshotStartingWindow数据是啥?

冷启动时候大家都知道SplashWindow数据就是ICON + 背景色的样子但是暖启动时候SnapshotStartingWindow显示内容是啥呢?

实际上他显示内容就是类似最近任务一样的,是activity内容的截图 获取方式: 截图文件保存在:

  /data/system_ce/<userId>/snapshots/<随机UUID>/<taskId>.jpg                                                                                                                                                       
  /data/system_ce/<userId>/snapshots/<随机UUID>/<taskId>.proto                                                                                                                                                     
  /data/system_ce/<userId>/snapshots/<随机UUID>/<taskId>_reduced.jpg      

实战如下:

adb pull /data/system_ce/0/snapshots/09c8fa2d-ff1b-482f-882c-eb1e0b5ca51d/789.jpg
/data/system_ce/0/snapshots/09c8fa2d-ff1b-482f-882c-eb1e0b5ca51d/789.jpg: 1 file pulled, 0 skipped. 19.7 MB/s (86913 bytes in 0.004s)
在这里插入图片描述

为什么感知不到SnapshotStartingWindow存在呢?

其实感知不到SnapshotStartingWindow存在就是系统设计这个SnapshotStartingWindow成功的表现,本身就是想让你无感的点击图标后进入到Activity真实内容,但是因为Activity真实内容显示是需要一定时间的,哪怕暖启动。

那么在真实Activity绘制前这段时间就需要使用SnapshotStartingWindow来显示,他显示的内容是上一次Activity退出的task截图。

感知不到SnapshotStartingWindow存在其实有2个因素: 

1、SnapshotStartingWindow的显示时间非常短暂,可能是100ms左右,相比SplashWindow显示500ms时间短了很多。

2、SnapshotStartingWindow本身就是显示task的截图,所以内容上和Activity的真实显示内容是高度一致的,所以很难感知出他们的变化,除非画面会有大的变化才可能会有跳变感。

整体流程架构总结

system_server (ATMS/WMS)                          Shell (com.android.wm.shell)
══════════════════════════                        ═══════════════════════════════

ActivityRecord.addStartingWindow()
  │
  ├─ getStartingWindowType()
  │     │
  │     ├─ newTask/!processRunning → SPLASH
  │     └─ taskSwitch + snapshot   → SNAPSHOT  ← 温启动命中
  │
  ├─ createSnapshot()
  │     └─ new SnapshotStartingData(snapshot)
  │
  ├─ StartingSurfaceController
  │     .createTaskSnapshotSurface()
  │
  └─ TaskOrganizerController
        .addStartingWindow()                      
 ──Binder IPC──▶  TaskSnapshotWindow.create()
                                                                    │
├─ IWindowSession.addToDisplay()
├─ IWindowSession.relayout()
├─ SnapshotDrawerUtils
│   .drawSnapshotOnSurface()
│     └─ setBuffer(HardwareBuffer)
└─ reportDrawn()

                    ═══════ Snapshot 显示中,App 首帧正在绘制 ═══════

ActivityRecord.onFirstWindowDrawn()
  │
  └─ removeStartingWindow()
       │
       └─ TaskOrganizerController
            .removeStartingWindow()                
──Binder IPC──▶  TaskSnapshotWindow
                                                                      .removeImmediately()
                                                                        └─ IWindowSession.remove()
完整代码调用流程图展示:
在这里插入图片描述

添加路径: ActivityRecord → StartingSurfaceController → TaskOrganizerController → Binder → TaskSnapshotWindow

移除路径: ActivityRecord.onFirstWindowDrawn() → TaskOrganizerController → Binder → TaskSnapshotWindow.removeImmediately()

更多vip干货独享知识讨论,面试题讨论,及面试定制指导上岸fw工程师服务,课程优惠购买成为vip学员进入vip群,积极讨论各种行业难点痛点疑难问题,答疑服务等。

请联系马哥微信:

为什么性能优化是必学课?这些优化成果就是答案
Android Framework开发rom实战合集课表/车载车机手机高级系统开发工程必会技能
重大消息:Hal+perfetto-systrace+SurfaceFlinger合集新专题发布
重大消息:ShellTransition项目实战专题aosp15版本首发优惠获取
开学第一课:安卓音频框架Audio子系统实战专题--首发优惠活动
2026第一课:安卓14-1车机手机三分屏实战专题--首发优惠活动

相关学习资料