在 Launcher3 執行涉及其他應用窗口(即“遠程窗口”)的動畫時,例如“點擊桌面圖標啟動應用”或“從應用上滑回到桌面”的過渡動畫,SurfaceControl
扮演著至關重要的角色。它是實現這些跨進程、高性能、精確定制動畫的核心技術。
SurfaceControl在源碼中的使用
Launcher3中有幾處非常經典的使用SurfaceControl的地方。
在分屏應用進入到最近任務,或者從最近任務啟動應用時,涉及到分屏應用中間的bar條,這個bar條是屬于SystemUI進程的,在Launcher中顯示就屬于遠程窗口,因此需要通過SurfaceControl來進行更新操作。
啟動分屏應用時bar條由隱藏到最終顯示的過程就是通過SurfaceControl控制bar條的透明度來實現的。
源碼如下:
public static ValueAnimator createSplitAuxiliarySurfacesAnimator(@Nullable RemoteAnimationTarget[] nonApps, boolean shown,@Nullable Consumer<ValueAnimator> animatorHandler) {if (nonApps == null || nonApps.length == 0) {return null;}List<SurfaceControl> auxiliarySurfaces = new ArrayList<>();for (RemoteAnimationTarget target : nonApps) {final SurfaceControl leash = target.leash;if (target.windowType == TYPE_DOCK_DIVIDER && leash != null && leash.isValid()) {auxiliarySurfaces.add(leash);}}if (auxiliarySurfaces.isEmpty()) {return null;}SurfaceControl.Transaction t = new SurfaceControl.Transaction();if (animatorHandler == null) {// Apply the visibility directly without fade animation.for (SurfaceControl leash : auxiliarySurfaces) {t.setVisibility(leash, shown);}t.apply();t.close();return null;}ValueAnimator dockFadeAnimator = ValueAnimator.ofFloat(0f, 1f);dockFadeAnimator.addUpdateListener(valueAnimator -> {float progress = valueAnimator.getAnimatedFraction();for (SurfaceControl leash : auxiliarySurfaces) {if (leash != null && leash.isValid()) {t.setAlpha(leash, shown ? progress : 1 - progress);}}t.apply();});dockFadeAnimator.addListener(new AnimatorListenerAdapter() {@Overridepublic void onAnimationStart(Animator animation) {if (shown) {for (SurfaceControl leash : auxiliarySurfaces) {t.setLayer(leash, Integer.MAX_VALUE);t.setAlpha(leash, 0);t.show(leash);}t.apply();}}@Overridepublic void onAnimationEnd(Animator animation) {if (!shown) {for (SurfaceControl leash : auxiliarySurfaces) {if (leash != null && leash.isValid()) {t.hide(leash);}}t.apply();}t.close();}});dockFadeAnimator.setDuration(SPLIT_DIVIDER_ANIM_DURATION);animatorHandler.accept(dockFadeAnimator);return dockFadeAnimator;}
下來來詳解SurfaceControl在Launcher中的角色以及為什么要使用SurfaceControl
SurfaceControl
的角色:
- 窗口/圖層的句柄: 在 Android 圖形系統中,每個窗口或可視元素最終都對應一個或多個圖層 (Layer),這些圖層由系統的合成器 (
SurfaceFlinger
) 負責管理和混合。SurfaceControl
是一個輕量級的句柄 (Handle),它代表了SurfaceFlinger
中的一個圖層(Surface)。你可以把它想象成一個指向屏幕上某個“畫板”的遙控器。 - 直接操作圖層屬性: 通過
SurfaceControl
,一個有權限的進程(在遠程動畫場景下,通常是 Launcher 或 SystemUI)可以直接、高效地修改其代表的圖層在SurfaceFlinger
中的各種屬性,而無需與創建這個圖層的原始應用進程進行復雜的通信或等待其響應。這些屬性包括:- 幾何變換: 位置 (Position)、縮放 (Scale)、旋轉 (Rotation) (通常通過設置變換矩陣
Matrix
實現)。 - 視覺效果: 透明度 (Alpha)、層級 (Z-order)、裁剪區域 (Window Crop)、圓角半徑 (Corner Radius)、陰影 (Shadow Radius)、模糊 (Blur) 等。
- 幾何變換: 位置 (Position)、縮放 (Scale)、旋轉 (Rotation) (通常通過設置變換矩陣
- 跨進程動畫的橋梁: 在遠程動畫中,系統 (
WindowManager
) 會將參與動畫的窗口(例如正在打開的應用窗口、正在關閉的 Launcher 窗口、壁紙窗口)的SurfaceControl
(通常是一個稱為 “Leash” 的特殊控制層)打包在RemoteAnimationTarget
對象中,傳遞給動畫控制器(Launcher)。 - 動畫執行者 (
SurfaceControl.Transaction
): Launcher 拿到這些SurfaceControl
后,不會去修改對應應用的 View 屬性,而是創建SurfaceControl.Transaction
對象。在動畫的每一幀:- Launcher 計算出每個目標窗口圖層應該具有的視覺屬性(比如,應用窗口從圖標大小放大到全屏,透明度從 0 到 1,裁剪區域從無到有,圓角從大變小)。
- 使用
Transaction
提供的方法(如setMatrix()
,setAlpha()
,setWindowCrop()
,setCornerRadius()
)為每個SurfaceControl
設置這些目標屬性。 - 最后調用
transaction.apply()
原子性地將這一幀的所有屬性變更提交給SurfaceFlinger
。 SurfaceFlinger
在下一個 VSYNC 信號到來時,根據這些最新的屬性來合成并顯示屏幕內容,從而驅動了視覺上的動畫效果。
為什么在遠程動畫中使用 SurfaceControl
?
使用 SurfaceControl
是實現現代 Android 流暢、復雜過渡動畫的關鍵,原因如下:
- 高性能 (Performance): 直接在
SurfaceFlinger
(系統合成器)層面操作圖層屬性非常高效,通常能利用硬件加速。這避免了在應用進程內部進行復雜的 View 布局、繪制或屬性動畫,這些操作可能更耗資源且容易引發卡頓 (Jank)。 - 精確同步 (Synchronization): 對于涉及多個應用窗口(跨進程)的過渡動畫(如應用啟動/關閉、分屏),需要精確地同步它們的動畫。通過
SurfaceControl.Transaction
,Launcher 可以原子性地更新所有相關圖層的屬性,確保它們在同一幀內發生變化,實現完美的視覺同步。如果依賴各個應用自己執行動畫,幾乎不可能做到如此精確的同步。 - 強大控制力 (Control):
SurfaceControl
API 提供了對圖層視覺屬性的底層、細粒度控制,使得 Launcher 可以實現非常復雜的動畫效果,例如從圖標到窗口的平滑變形、窗口內容的裁剪、圓角變化等,這些效果很難通過傳統的 View 動畫或窗口動畫(ActivityOptions
)實現得如此精細。 - 解耦 (Decoupling): 被動畫的應用(例如正在啟動的應用)不需要主動參與這個由 Launcher 控制的過渡動畫。應用只需要正常地將自己的內容繪制到它的 Surface 上即可。Launcher 通過
SurfaceControl
在外部“指揮”SurfaceFlinger
如何變換和展示這個 Surface。這大大降低了應用和系統過渡動畫之間的耦合度。 - 無縫體驗 (Seamlessness):
SurfaceControl
使得元素(如圖標)看起來能夠“無縫地”跨越進程邊界變形成為另一個應用的窗口,提供了非常連貫和自然的視覺體驗。
總結:
在 Launcher 對遠程窗口執行動畫的過程中,SurfaceControl
充當了底層圖層(Surface)的直接控制器。Launcher 通過它,繞開了應用進程,直接與系統合成器 SurfaceFlinger
交互,以高性能、精確同步的方式驅動應用窗口的幾何變換和視覺效果,從而實現了流暢、復雜且跨進程的過渡動畫。這是現代 Android 系統動畫(尤其是 Quickstep 手勢動畫)的核心技術基礎。