性能优化比拼:app启动流程之冷热启动Activity的SnapshotWindow
背景
前面文章有对冷启动的Splash Window进行了详细的,但是大家是否有想过稳启动时候的是否也需要有类似的Splash Window呢?
答案是肯定的,具体可以通过WinScope或者Perfetto抓取暖启动的过程来验证:
其实桌面的暖启动也会有一个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:1filepulled,0skipped.19.7MB/s(86913bytesin0.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()
原文地址:
https://mp.weixin.qq.com/s/mtcG-00_KS-NyVs4bL5zEw
更多fw实战干货请关注下面“千里马学框架”