AOSP Android14 Launcher3——远程窗口动画关键类SurfaceControl详解

在 Launcher3 执行涉及其他应用窗口(即"远程窗口")的动画时,例如"点击桌面图标启动应用"或"从应用上滑回到桌面"的过渡动画,SurfaceControl 扮演着至关重要 的角色。它是实现这些跨进程、高性能、精确定制动画的核心技术。

SurfaceControl在源码中的使用

Launcher3中有几处非常经典的使用SurfaceControl的地方。

在分屏应用进入到最近任务,或者从最近任务启动应用时,涉及到分屏应用中间的bar条,这个bar条是属于SystemUI进程的,在Launcher中显示就属于远程窗口,因此需要通过SurfaceControl来进行更新操作。

启动分屏应用时bar条由隐藏到最终显示的过程就是通过SurfaceControl控制bar条的透明度来实现的。

源码如下:

java 复制代码
    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() {
            @Override
            public 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();
                }
            }

            @Override
            public 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 的角色:

  1. 窗口/图层的句柄: 在 Android 图形系统中,每个窗口或可视元素最终都对应一个或多个图层 (Layer) ,这些图层由系统的合成器 (SurfaceFlinger) 负责管理和混合。SurfaceControl 是一个轻量级的句柄 (Handle) ,它代表了 SurfaceFlinger 中的一个图层(Surface)。你可以把它想象成一个指向屏幕上某个"画板"的遥控器。
  2. 直接操作图层属性: 通过 SurfaceControl,一个有权限的进程(在远程动画场景下,通常是 Launcher 或 SystemUI)可以直接、高效地 修改其代表的图层在 SurfaceFlinger 中的各种属性,而无需 与创建这个图层的原始应用进程进行复杂的通信或等待其响应。这些属性包括:
    • 几何变换: 位置 (Position)、缩放 (Scale)、旋转 (Rotation) (通常通过设置变换矩阵 Matrix 实现)。
    • 视觉效果: 透明度 (Alpha)、层级 (Z-order)、裁剪区域 (Window Crop)、圆角半径 (Corner Radius)、阴影 (Shadow Radius)、模糊 (Blur) 等。
  3. 跨进程动画的桥梁: 在远程动画中,系统 (WindowManager) 会将参与动画的窗口(例如正在打开的应用窗口、正在关闭的 Launcher 窗口、壁纸窗口)的 SurfaceControl(通常是一个称为 "Leash" 的特殊控制层)打包在 RemoteAnimationTarget 对象中,传递给动画控制器(Launcher)。
  4. 动画执行者 (SurfaceControl.Transaction) : Launcher 拿到这些 SurfaceControl 后,不会去修改对应应用的 View 属性,而是创建 SurfaceControl.Transaction 对象。在动画的每一帧:
    • Launcher 计算出每个目标窗口图层应该具有的视觉属性(比如,应用窗口从图标大小放大到全屏,透明度从 0 到 1,裁剪区域从无到有,圆角从大变小)。
    • 使用 Transaction 提供的方法(如 setMatrix(), setAlpha(), setWindowCrop(), setCornerRadius())为每个 SurfaceControl 设置这些目标属性。
    • 最后调用 transaction.apply() 原子性地 将这一帧的所有属性变更提交给 SurfaceFlinger
    • SurfaceFlinger 在下一个 VSYNC 信号到来时,根据这些最新的属性来合成并显示屏幕内容,从而驱动了视觉上的动画效果。

为什么在远程动画中使用 SurfaceControl

使用 SurfaceControl 是实现现代 Android 流畅、复杂过渡动画的关键,原因如下:

  1. 高性能 (Performance): 直接在 SurfaceFlinger (系统合成器)层面操作图层属性非常高效,通常能利用硬件加速。这避免了在应用进程内部进行复杂的 View 布局、绘制或属性动画,这些操作可能更耗资源且容易引发卡顿 (Jank)。
  2. 精确同步 (Synchronization): 对于涉及多个应用窗口(跨进程)的过渡动画(如应用启动/关闭、分屏),需要精确地同步它们的动画。通过 SurfaceControl.Transaction,Launcher 可以原子性地更新所有相关图层的属性,确保它们在同一帧内发生变化,实现完美的视觉同步。如果依赖各个应用自己执行动画,几乎不可能做到如此精确的同步。
  3. 强大控制力 (Control): SurfaceControl API 提供了对图层视觉属性的底层、细粒度控制,使得 Launcher 可以实现非常复杂的动画效果,例如从图标到窗口的平滑变形、窗口内容的裁剪、圆角变化等,这些效果很难通过传统的 View 动画或窗口动画(ActivityOptions)实现得如此精细。
  4. 解耦 (Decoupling): 被动画的应用(例如正在启动的应用)不需要 主动参与这个由 Launcher 控制的过渡动画。应用只需要正常地将自己的内容绘制到它的 Surface 上即可。Launcher 通过 SurfaceControl 在外部"指挥"SurfaceFlinger 如何变换和展示这个 Surface。这大大降低了应用和系统过渡动画之间的耦合度。
  5. 无缝体验 (Seamlessness): SurfaceControl 使得元素(如图标)看起来能够"无缝地"跨越进程边界变形成为另一个应用的窗口,提供了非常连贯和自然的视觉体验。

总结:

在 Launcher 对远程窗口执行动画的过程中,SurfaceControl 充当了底层图层(Surface)的直接控制器 。Launcher 通过它,绕开了应用进程,直接与系统合成器 SurfaceFlinger 交互,以高性能、精确同步的方式驱动应用窗口的几何变换和视觉效果,从而实现了流畅、复杂且跨进程的过渡动画。这是现代 Android 系统动画(尤其是 Quickstep 手势动画)的核心技术基础。

相关推荐
贤泽5 天前
Android15 ContentProvider 深度源码分析(上)
android·aosp
贤泽5 天前
Android15 ContentProvider 深度源码分析(下)
android·aosp
贤泽8 天前
android 15 AOSP Broadcast 广播机制源码分析
android·aosp
奔跑吧 android10 天前
【车载Audio】【AudioHal 07】【高通音频架构】【从逻辑策略到物理执行】
音视频·audio·aosp·android15·8295·音频子系统
42nf1 个月前
Android Launcher3添加负一屏
android·launcher3·android负一屏
不会Android的潘潘1 个月前
受限系统环境下的 WebView 能力演进:车载平台 Web 渲染异常的根因分析与优化实践
android·java·前端·aosp
奔跑吧 android1 个月前
【车载audio开发】【Qualcomm PAL 详解 6】【PAL 总体架构与模块交互指南】
audio·aosp·pal·高通音频框架·8155·8295
奔跑吧 android1 个月前
【车载audio开发】【Qualcomm PAL 详解 4】【Session 模块 介绍】
audio·aosp·高通·车载音频
不会Android的潘潘1 个月前
adb指令扩展方案
android·adb·aosp
Just_Paranoid2 个月前
【AOSP】Android Dump 信息快速定位方法
android·adb·framework·service·aosp·dumpsys