新版负一屏变天了!分享pixel新桌面负一屏技术调研报告

背景

有学员反馈说新版本的pixel负一屏的方案已经不是采用以前的Overlay那种独立Window方式,而是使用的独立的Activity方式,针对学员提出的这个疑问,马哥这边也下载了一个pixel的模拟器进行调研pixel的新版本负一屏方案原理。

直观认识:

主桌面
在这里插入图片描述

负一屏

在这里插入图片描述

拖动中间时候

在这里插入图片描述

调研原理部分

层级结构树部分

使用dumpsys activity containers和sf等查看负一屏情况

 DefaultTaskDisplayArea type=undefined mode=fullscreen override-mode=fullscreen requested-bounds=[0,0][0,0] bounds=[0,0][2076,2152]
            │     ├─ Task=1 type=HOME mode=fullscreen override-mode=fullscreen requested-bounds=[0,0][0,0] bounds=[0,0][2076,2152]
            │     │  └─ Task=3 type=HOME mode=fullscreen override-mode=undefined requested-bounds=[0,0][0,0] bounds=[0,0][2076,2152]
            │     │     ├─ ActivityRecord{6892885 u0 com.google.android.apps.nexuslauncher/.NexusLauncherActivity t3} type=HOME mode=fullscreen override-mode=undefined requested-bounds=[0,0][0,0] bounds=[0,0][2076,2152]
            │     │     │  └─ 6a55d8e com.google.android.apps.nexuslauncher/com.google.android.apps.nexuslauncher.NexusLauncherActivity type=HOME mode=fullscreen override-mode=undefined requested-bounds=[0,0][0,0] bounds=[0,0][2076,2152]
            │     │     └─ TaskFragment{b923527 mode=multi-window} type=HOME mode=MULTI-WINDOW override-mode=MULTI-WINDOW requested-bounds=[0,0][0,0] bounds=[0,0][2076,2152]
            │     │        └─ ActivityRecord{184635947 u0 com.google.android.googlequicksearchbox/com.google.android.apps.search.googleapp.launcher.minusone.activity.MinusOneActivity t3} type=HOME mode=MULTI-WINDOW override-mode=undefined requested-bounds=[0,0][0,0] bounds=[0,0][2076,2152]
            │     │           └─ e843f4 com.google.android.googlequicksearchbox/com.google.android.apps.search.googleapp.launcher.minusone.activity.MinusOneActivity type=HOME mode=MULTI-WINDOW override-mode=undefined requested-bounds=[0,0][0,0] bounds=[0,0][2076,2152]

上面的相比正常的多了一个 TaskFragment{b923527 mode=multi-window}的容器,这个是专门装载负一屏的task。

关键属性

  • TaskFragment 以 WINDOWING_MODE_MULTI_WINDOW 创建,与 fullscreen 的 Launcher Activity 共存于同一 Task
  • TaskFragment 的 organizerUid=10195 (com.google.android.apps.nexuslauncher),由 Launcher 控制
  • MinusOneActivity 进程为 com.google.android.googlequicksearchbox:googleapp (uid=10161),与 Launcher 不同进程

activity的生命周期部分

桌面滑动到负一屏
在这里插入图片描述
桌面滑动到负一屏时候,桌面首先就已经Pasue了,然后负一屏进行resume,彻底滑到负一屏后,桌面进行stop。

负一屏滑动回桌面

在这里插入图片描述可以看到桌面先调研onStart,松手后滑到桌面才是resume,然后负一屏的activity就进行stop。

三种状态与生命周期

1 CLOSED 状态
  • TaskFragment 存在但 setHidden=true
  • MinusOneActivity 未启动(或已 stopped)
  • Launcher 独占显示
2 OPEN 状态
  • TaskFragment setHidden=false, MinusOneActivity RESUMED
  • Launcher Window 仍 VISIBLE 但在 WMS 中 mObscured=true(被 TF 遮挡)
  • Launcher Activity 状态为 PAUSED
  • MinusOneActivity 为 mFocusedWindow
3 MID-DRAG 状态(实验验证)

以下数据来自拖动到中间位置时的实际 dumpsys 实验:

WMS 层面 (dumpsys window)
属性Launcher (Window #9)MinusOne (Window #8)
mViewVisibility0x0 (VISIBLE)0x0 (VISIBLE)
mHasSurfacetruetrue
mObscuredtruefalse
mWindowingModefullscreenmulti-window
SurfaceVRI-NexusLauncherActivity#721VRI-MinusOneActivity#758

关键发现:拖动期间 MinusOne 的 Window mViewVisibility=0x0 (VISIBLE)mHasSurface=true。这与 OPEN 状态一致,说明 MinusOne 的 Window 在整个拖动过程中保持可见。

Activity 层面 (dumpsys activity)
Task{68ab20d #3 type=home}
├─ topResumedActivity = MinusOneActivity     ← ★ 负一屏是 resumed
├─ TaskFragment{b923527 mode=multi-window}
│   └─ MinusOneActivity: state=RESUMED
│       mWindowingMode=multi-window
└─ NexusLauncherActivity: state=PAUSED
    mWindowingMode=fullscreen

关键发现:拖动过程中 MinusOneActivity 已经处于 RESUMED 状态,Launcher 处于 PAUSED。说明一旦开始拖动(ACTION_DOWN),系统就已经完成了 Activity 生命周期的切换。用户拖动的是"已经 RESUME 的 MinusOneActivity 的 Surface 的位置",而不是在拖动过程中做 Activity 切换。

总结部分

Pixel Launcher 的负一屏不是在 Launcher 进程内嵌入一个 View 或 Fragment,而是利用 Android 12+ 的 TaskFragment API,在 Launcher 的 Task 内创建一个独立的 TaskFragment,将 Google App (Velvet) 的 MinusOneActivitymulti-window 模式嵌入其中。

两个 Activity 拥有各自独立的 Window 和 Surface,在 SurfaceFlinger 层面通过 z-order 叠加显示,通过两种不同的偏移机制实现同步滑动:

偏移目标机制层级
Launcher (NexusLauncherActivity)View.setTranslationX()View 层
负一屏 (MinusOneActivity)SurfaceControl.Transaction.setMatrix()Surface 层

上面就是马哥对于新版本负一屏的初步调研方案,后续有时间会进行模仿pixel实现新版本负一屏的demo,欢迎相关vip学员找马哥交流实现方案等。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

千里马学框架

帮助你了,就请我喝杯咖啡

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值