04-05-06 深入理解Android内核设计思想 第6章:Android显示系统

Android 16 (API 36, “Baklava”) 更新版

核心知识点速查

1. 显示系统架构(应用到硬件的完整链路)

┌─────────────────────────────────────┐
│  Application (Java/Kotlin)           │  ← Activity, View, RenderNode
│  └── Canvas.draw() / HardwareRenderer│
├─────────────────────────────────────┤
│  SkiaGraphRenderer (C++)             │  ← Android 16 新渲染管线
│  └── frameworks/native/libs/renderscript/
├─────────────────────────────────────┤
│  SurfaceFlinger (C++)                │  ← BLAST-Sync 同步机制
│  └── frameworks/native/services/     │
│      surfaceflinger/                 │
├─────────────────────────────────────┤
│  HWC3 (HWComposer 3.0)              │  ← AIDL 硬件合成器接口
│  └── hardware/interfaces/            │
│      graphics/composer3/             │
├─────────────────────────────────────┤
│  Gralloc HAL (AIDL)                 │  ← AIDL 缓冲区分配
│  └── hardware/interfaces/            │
│      graphics/allocator/aidl/        │
├─────────────────────────────────────┤
│  DRM/KMS 显示驱动                    │  ← 内核唯一标准(FB已移除)
│  └── drivers/gpu/drm/                │
├─────────────────────────────────────┤
│  Display Hardware (LCD/OLED/HDMI)   │  ← VRR/LTPO 自适应刷新率
└─────────────────────────────────────┘

2. 关键概念

Surface
├── 应用的绘图表面
├── 双缓冲/三缓冲 + BLAST-Sync 异步同步
├── 通过 Binder + AIDL 传递给 SurfaceFlinger
└── Android 16: Buffer-Less Async Sync 减少合成延迟

SurfaceFlinger
├── 系统唯一的显示合成服务
├── 管理所有应用的 Surface
├── 执行图层合成(HWC3 / GPU  fallback)
├── VSync 同步 + VRR 可变刷新率
└── Android 16: BLAST-Sync 默认启用

GraphicBuffer
├── 图形缓冲区
├── 由 Gralloc HAL (AIDL) 分配
├── 支持 DMA-BUF 跨进程/跨设备共享
└── 支持多种格式(RGBA、YUV、ASTC 压缩纹理等)

VSync(垂直同步)
├── 屏幕刷新信号(60Hz/90Hz/120Hz/144Hz 可变)
├── VRR (Variable Refresh Rate) 动态调整
├── LTPO 屏幕可低至 1Hz(AOD 场景)
└── 同步应用绘制、合成、屏幕刷新

HWC3 (HWComposer 3.0)
├── AIDL 接口(替代 HIDL)
├── 硬件 Overlay 合成
├── 支持 VRR 和 HDR 合成
└── 决定哪些 Layer 由硬件合成,哪些由 GPU 合成

3. 显示流程时间线(Android 16 BLAST-Sync)

VSync 信号到来(T0)
  ↓
App 开始绘制(T0 + 1ms)
  ├── measure, layout, draw
  └── 填充 GraphicBuffer
  ↓
dequeueBuffer 获取空闲缓冲区(T0 + 3ms)  ← BLAST-Sync 优化
  ↓
GPU 渲染(T0 + 8ms)
  ↓
queueBuffer 提交缓冲区(T0 + 10ms)  ← 异步提交,不等 VSync
  ↓
SurfaceFlinger 合成(T0 + 12ms)  ← BLAST-Sync 无缓冲异步
  ├── 收集所有 Layer 的 Buffer
  ├── HWC3 硬件合成(优先)
  └── SkiaGraphRenderer GPU fallback
  ↓
显示到屏幕(T0 + 14ms,同帧内完成)  ← 减少一个 VSync 周期

DRM/KMS 显示驱动(Android 16 唯一标准)

重要变更:Android 16 (API 36) 彻底移除了 Framebuffer (fbdev) 支持,DRM/KMS 成为内核显示驱动的唯一标准。/dev/fb* 设备节点不再存在,所有显示操作必须通过 DRM ioctl 完成。

1. DRM/KMS 基本概念

DRM (Direct Rendering Manager)
├── 设备节点:/dev/dri/card0, /dev/dri/renderD128
├── 支持复杂场景(多显示器、热插拔、VRR)
├── KMS (Kernel Mode Setting)
│   ├── CRTC(Cathode Ray Tube Controller,显示控制器)
│   ├── Encoder(编码器:HDMI、DP、DSI、LVDS)
│   ├── Connector(连接器:物理接口)
│   └── Plane(图层平面:Primary / Overlay / Cursor)
├── GEM (Graphics Execution Manager)
│   └── 图形缓冲区管理
├── DMA-BUF / Prime
│   └── 跨设备/跨驱动缓冲区共享
└── Android 16 新增
    ├── VRR (Variable Refresh Rate) ioctl 支持
    ├── HDR 元数据传递(HDR10、HLG、Dolby Vision)
    └── 自适应刷新率(LTPO 1Hz-120Hz)

关键 ioctl 调用:
├── DRM_IOCTL_MODE_GETRESOURCES      → 获取 CRTC/Encoder/Connector
├── DRM_IOCTL_MODE_GETCONNECTOR      → 获取连接器状态(EDID、模式)
├── DRM_IOCTL_MODE_GETCRTC           → 获取 CRTC 信息
├── DRM_IOCTL_MODE_SETPLANE          → 配置 Plane(图层)
├── DRM_IOCTL_MODE_SETCRTC           → 设置显示模式 + 绑定 Plane
├── DRM_IOCTL_MODE_OBJ_GETPROPERTIES → 获取属性(VRR、HDR 等)
├── DRM_IOCTL_MODE_OBJ_SETPROPERTY   → 设置属性
├── DRM_IOCTL_PRIME_HANDLE_TO_FD     → GEM handle → DMA-BUF fd
└── DRM_IOCTL_MODE_PAGE_FLIP         → 页面翻转(双缓冲切换)

2. DRM/KMS 驱动完整示例

// drivers/gpu/drm/T8000/T8000_drm_drv.c

#include <drm/drm_drv.h>
#include <drm/drm_plane.h>
#include <drm/drm_crtc.h>
#include <drm/drm_encoder.h>
#include <drm/drm_connector.h>
#include <drm/drm_fb_helper.h>
#include <drm/drm_gem.h>
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_vblank.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>

struct T8000_drm_device {
    struct drm_device drm;
    void __iomem *regs;
    struct drm_plane primary_plane;
    struct drm_crtc crtc;
    struct drm_encoder encoder;
    struct drm_connector connector;
    struct drm_gem_object *fb_obj;
    struct completion flip_done;
};

#define to_T8000_drm(x) container_of(x, struct T8000_drm_device, x)

/* ==================== Plane 实现 ==================== */

static int T8000_plane_atomic_check(struct drm_plane *plane,
                                     struct drm_atomic_state *state)
{
    struct drm_plane_state *plane_state =
        drm_atomic_get_new_plane_state(state, plane);

    if (!plane_state->crtc && !plane_state->fb)
        return 0;  // Plane 禁用

    if (!plane_state->crtc || !plane_state->fb)
        return -EINVAL;  // 必须同时有 CRTC 和 FB

    /* 检查分辨率上限 */
    if (plane_state->crtc_w > 3840 || plane_state->crtc_h > 2160)
        return -EINVAL;

    return 0;
}

static void T8000_plane_atomic_update(struct drm_plane *plane,
                                       struct drm_atomic_state *state)
{
    struct T8000_drm_device *priv = to_T8000_drm(drm);
    struct drm_plane_state *state = plane->state;
    struct drm_gem_dma_object *dma_obj;
    dma_addr_t addr;

    if (!state->fb)
        return;

    dma_obj = to_drm_gem_dma_obj(state->fb->obj[0]);
    addr = dma_obj->dma_addr;

    /* 配置 Overlay 寄存器 */
    writel(addr, priv->regs + PLANE0_ADDR_REG);
    writel(state->crtc_x, priv->regs + PLANE0_X_REG);
    writel(state->crtc_y, priv->regs + PLANE0_Y_REG);
    writel(state->crtc_w, priv->regs + PLANE0_W_REG);
    writel(state->crtc_h, priv->regs + PLANE0_H_REG);
    writel(PLANE_ENABLE, priv->regs + PLANE0_CTRL_REG);
}

static const struct drm_plane_helper_funcs T8000_plane_helper_funcs = {
    .atomic_check = T8000_plane_atomic_check,
    .atomic_update = T8000_plane_atomic_update,
};

static const struct drm_plane_funcs T8000_plane_funcs = {
    .update_plane = drm_atomic_helper_update_plane,
    .disable_plane = drm_atomic_helper_disable_plane,
    .destroy = drm_plane_cleanup,
    .reset = drm_atomic_helper_plane_reset,
    .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
    .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
};

/* ==================== CRTC 实现 ==================== */

static void T8000_crtc_atomic_enable(struct drm_crtc *crtc,
                                      struct drm_atomic_state *state)
{
    struct T8000_drm_device *priv = to_T8000_drm(crtc);
    /* 使能显示控制器 */
    writel(CRTC_ENABLE, priv->regs + CRTC_CTRL_REG);
}

static void T8000_crtc_atomic_disable(struct drm_crtc *crtc,
                                       struct drm_atomic_state *state)
{
    struct T8000_drm_device *priv = to_T8000_drm(crtc);
    writel(0, priv->regs + CRTC_CTRL_REG);
}

static void T8000_crtc_atomic_flush(struct drm_crtc *crtc,
                                     struct drm_atomic_state *state)
{
    struct T8000_drm_device *priv = to_T8000_drm(crtc);
    unsigned long flags;

    spin_lock_irqsave(&crtc->dev->event_lock, flags);
    if (crtc->state->event) {
        /* VBlank 事件回调 */
        drm_crtc_send_vblank_event(crtc, crtc->state->event);
        crtc->state->event = NULL;
    }
    spin_unlock_irqrestore(&crtc->dev->event_lock, flags);

    /* 触发页面翻转 */
    writel(CRTC_FLIP_TRIGGER, priv->regs + CRTC_CMD_REG);
}

static const struct drm_crtc_helper_funcs T8000_crtc_helper_funcs = {
    .atomic_enable = T8000_crtc_atomic_enable,
    .atomic_disable = T8000_crtc_atomic_disable,
    .atomic_flush = T8000_crtc_atomic_flush,
};

static const struct drm_crtc_funcs T8000_crtc_funcs = {
    .reset = drm_atomic_helper_crtc_reset,
    .destroy = drm_crtc_cleanup,
    .set_config = drm_atomic_helper_set_config,
    .page_flip = drm_atomic_helper_page_flip,
    .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
    .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
};

/* ==================== Connector 实现 ==================== */

static int T8000_connector_get_modes(struct drm_connector *connector)
{
    struct T8000_drm_device *priv = to_T8000_drm(connector);
    struct edid *edid;
    int ret;

    /* 读取 EDID(通过 DDC/I2C) */
    edid = drm_get_edid(connector, priv->ddc_adapter);
    if (edid) {
        drm_connector_update_edid_property(connector, edid);
        ret = drm_add_edid_modes(connector, edid);
        kfree(edid);
        return ret;
    }

    /* 无 EDID,使用默认模式 1080p60 */
    return drm_add_modes_noedid(connector, 1920, 1080);
}

static enum drm_mode_status
T8000_connector_mode_valid(struct drm_connector *connector,
                            struct drm_display_mode *mode)
{
    /* VRR 模式验证 */
    if (mode->vrefresh < 1 || mode->vrefresh > 144)
        return MODE_BAD;
    return MODE_OK;
}

static const struct drm_connector_helper_funcs T8000_connector_helper_funcs = {
    .get_modes = T8000_connector_get_modes,
    .mode_valid = T8000_connector_mode_valid,
};

static const struct drm_connector_funcs T8000_connector_funcs = {
    .fill_modes = drm_helper_probe_single_connector_modes,
    .destroy = drm_connector_cleanup,
    .reset = drm_atomic_helper_connector_reset,
    .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
    .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
};

/* ==================== Mode Config ==================== */

static const struct drm_mode_config_funcs T8000_mode_config_funcs = {
    .fb_create = drm_gem_fb_create,
    .atomic_check = drm_atomic_helper_check,
    .atomic_commit = drm_atomic_helper_commit,
};

static const uint32_t T8000_formats[] = {
    DRM_FORMAT_XRGB8888,
    DRM_FORMAT_ARGB8888,
    DRM_FORMAT_XBGR8888,
    DRM_FORMAT_ABGR8888,
    DRM_FORMAT_YUV420,   /* 视频 Overlay 常用 */
    DRM_FORMAT_NV12,
};

static const uint64_t T8000_modifiers[] = {
    DRM_FORMAT_MOD_LINEAR,
    /* 可添加厂商特定 modifier,如 ARM AFBC */
    DRM_FORMAT_MOD_INVALID
};

/* ==================== Probe / 初始化 ==================== */

static int T8000_drm_bind(struct platform_device *pdev)
{
    struct T8000_drm_device *priv;
    struct drm_device *drm;
    struct resource *res;
    int ret;

    priv = devm_drm_dev_alloc(&pdev->dev, &T8000_drm_driver,
                               struct T8000_drm_device, drm);
    if (IS_ERR(priv))
        return PTR_ERR(priv);
    drm = &priv->drm;

    /* 映射寄存器 */
    res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
    priv->regs = devm_ioremap_resource(&pdev->dev, res);
    if (IS_ERR(priv->regs))
        return PTR_ERR(priv->regs);

    platform_set_drvdata(pdev, priv);

    /* Mode config 初始化 */
    drm_mode_config_init(drm);
    drm->mode_config.funcs = &T8000_mode_config_funcs;
    drm->mode_config.min_width = 64;
    drm->mode_config.max_width = 3840;
    drm->mode_config.min_height = 64;
    drm->mode_config.max_height = 2160;
    drm->mode_config.preferred_depth = 24;

    /* 初始化 Primary Plane */
    ret = drm_universal_plane_init(drm, &priv->primary_plane, 1,
                                    &T8000_plane_funcs,
                                    T8000_formats,
                                    ARRAY_SIZE(T8000_formats),
                                    T8000_modifiers,
                                    DRM_PLANE_TYPE_PRIMARY,
                                    NULL);
    if (ret)
        return ret;
    drm_plane_helper_add(&priv->primary_plane, &T8000_plane_helper_funcs);

    /* 初始化 CRTC */
    ret = drm_crtc_init_with_planes(drm, &priv->crtc,
                                     &priv->primary_plane, NULL,
                                     &T8000_crtc_funcs, NULL);
    if (ret)
        return ret;
    drm_crtc_helper_add(&priv->crtc, &T8000_crtc_helper_funcs);

    /* 初始化 Encoder */
    ret = drm_encoder_init(drm, &priv->encoder, NULL,
                           DRM_MODE_ENCODER_TMDS, NULL);
    if (ret)
        return ret;
    priv->encoder.possible_crtcs = 1;
    drm_encoder_helper_add(&priv->encoder, &T8000_encoder_helper_funcs);

    /* 初始化 Connector */
    ret = drm_connector_init(drm, &priv->connector,
                              &T8000_connector_funcs,
                              DRM_MODE_CONNECTOR_HDMIA);
    if (ret)
        return ret;
    drm_connector_helper_add(&priv->connector,
                              &T8000_connector_helper_funcs);

    /* 连接 Encoder 和 Connector */
    drm_connector_attach_encoder(&priv->connector, &priv->encoder);

    /* VBlank 初始化 */
    ret = drm_vblank_init(drm, 1);
    if (ret)
        return ret;

    /* Android 16: VRR 属性支持 */
    drm_connector_attach_vrr_capable_property(&priv->connector);

    /* 注册 DRM 设备 */
    ret = drm_dev_register(drm, 0);
    if (ret)
        return ret;

    /* DRM fbdev 兼容层(仅用于调试,非生产用) */
    drm_fbdev_generic_setup(drm, 32);

    dev_info(&pdev->dev, "T8000 DRM driver registered\n");
    return 0;
}

static void T8000_drm_unbind(struct platform_device *pdev)
{
    struct T8000_drm_device *priv = platform_get_drvdata(pdev);
    drm_dev_unregister(&priv->drm);
    drm_kms_helper_poll_fini(&priv->drm);
    drm_mode_config_cleanup(&priv->drm);
    drm_dev_put(&priv->drm);
}

static const struct of_device_id T8000_drm_of_match[] = {
    { .compatible = "device,T8000-drm" },
    { }
};
MODULE_DEVICE_TABLE(of, T8000_drm_of_match);

static struct platform_driver T8000_drm_driver = {
    .probe = T8000_drm_bind,
    .remove = T8000_drm_unbind,
    .driver = {
        .name = "T8000-drm",
        .of_match_table = T8000_drm_of_match,
    },
};

module_platform_driver(T8000_drm_driver);

MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("T8000 DRM/KMS Display Driver");

Gralloc HAL(图形缓冲区分配)

1. Gralloc的作用

Gralloc(Graphics Allocator)
├── 分配图形缓冲区(GraphicBuffer)
├── 管理显存或 DMA-BUF 共享内存
├── 提供 lock/unlock 接口(CPU 访问)
├── 提供给 GPU、Camera、Video 的 DMA 访问
├── 跨进程共享(通过 DMA-BUF fd)
└── Android 16: 已迁移到 AIDL 接口(替代 HIDL)

2. Gralloc HAL 接口(Android 16 AIDL 版)

Android 16 重要变更:Gralloc HAL 从 HIDL 完全迁移到 AIDL 接口。旧的 hardware/interfaces/graphics/allocator/ HIDL 路径不再使用,新的接口定义在 hardware/interfaces/graphics/allocator/aidl/

// hardware/interfaces/graphics/allocator/aidl/IAllocator.aidl

package android.hardware.graphics.allocator;

import android.hardware.graphics.common.BufferUsage;
import android.hardware.graphics.common.PixelFormat;
import android.hardware.graphics.common.BufferDescription;
import android.hardware.graphics.allocator.AllocatedBuffer;

/**
 * Android 16 AIDL Gralloc 分配器接口
 * 替代旧的 HIDL IAllocator 和 IMapper
 */
interface IAllocator {

    /**
     * 分配图形缓冲区
     * @param description 缓冲区描述(尺寸、格式、usage)
     * @return 分配结果
     */
    Buffer allocate(BufferDescription description);
}

// hardware/interfaces/graphics/allocator/aidl/BufferDescription.aidl

/**
 * 缓冲区描述符,定义要分配的图形缓冲区属性
 */
parcelable BufferDescription {
    int width;           // 宽度(像素)
    int height;          // 高度(像素)
    int layerCount;      // 层数(1=2D,>1=纹理数组)
    PixelFormat format;  // 像素格式(RGBA_8888、YCBCR_420_888 等)
    @utf8in32 String[] compression;  // 压缩格式(如 "ARM_AFBC")
    long usage;          // 使用标志(位掩码)
    @utf8in32 String consumerName;   // 消费者名称标签
}

/**
 * 分配后的缓冲区句柄
 */
parcelable AllocatedBuffer {
    native_handle bufferHandle;  // native handle(含 DMA-BUF fd)
    int stride;                   // 行对齐(像素)
    long byteCount;               // 总字节数
}

/**
 * Usage 标志(Android 16 新增)
 * 定义在 hardware/interfaces/graphics/common/aidl/BufferUsage.aidl
 */
BufferUsage 定义:
    CPU_READ_NEVER          = 0x00000000
    CPU_READ_RARELY         = 0x00000002
    CPU_READ_OFTEN          = 0x00000003
    CPU_WRITE_NEVER         = 0x00000000
    CPU_WRITE_RARELY        = 0x00000020
    CPU_WRITE_OFTEN         = 0x00000030
    GPU_TEXTURE             = 0x00000100   // 用作 GPU 纹理
    GPU_RENDER_TARGET       = 0x00000200   // GPU 渲染目标
    COMPOSER_OVERLAY        = 0x00000800   // HWC Overlay
    COMPOSER_CLIENT_TARGET  = 0x00001000   // HWC Client 目标
    VIDEO_ENCODER           = 0x00010000   // 视频编码输入
    CAMERA_OUTPUT           = 0x00020000   // 相机输出
    RENDERSCRIPT            = 0x00100000   // RenderScript
    VIRTUAL_DISPLAY         = 0x00800000   // 虚拟显示
    PROTECTED               = 0x00004000   // 受保护内容(DRM)
    VIDEO_DECODER           = 0x00008000   // 视频解码输出
    SENSOR_DIRECT_DATA      = 0x00200000   // Android 16 新增:传感器直写
    COMPOSER_BYPASS         = 0x01000000   // Android 16 新增:HWC3 bypass

3. Gralloc HAL AIDL 实现示例

// device/device/gralloc/T8000GrallocService.cpp

#include <aidl/android/hardware/graphics/allocator/IAllocator.h>
#include <aidl/android/hardware/graphics/mapper/IMapper.h>
#include <hardware/hardware.h>
#include <hardware/dma_buf.h>
#include <sys/mman.h>
#include <linux/dma-heap.h>

using aidl::android::hardware::graphics::allocator::IAllocator;
using aidl::android::hardware::graphics::allocator::AllocatedBuffer;
using aidl::android::hardware::graphics::allocator::BufferDescription;

/**
 * Android 16 使用 DMA-Heap 替代 ION 分配内存
 * ION 已在主线内核中移除
 */
class T8000GrallocAllocator : public IAllocator {
public:
    T8000GrallocAllocator() {
        // 打开 DMA-Heap 设备
        mDmaHeapFd = open("/dev/dma_heap/system-uncached", O_RDWR);
        if (mDmaHeapFd < 0) {
            ALOGE("Failed to open DMA-Heap: %s", strerror(errno));
        }
    }

    ~T8000GrallocAllocator() override {
        if (mDmaHeapFd >= 0) {
            close(mDmaHeapFd);
        }
    }

    ndk::ScopedAStatus allocate(const BufferDescription& desc,
                                 AllocatedBuffer* outBuffer) override {
        int bpp = GetBpp(desc.format);
        int align = 64;  // 64 字节对齐(硬件要求)

        // 计算 stride(对齐)
        int stride = ALIGN(desc.width * bpp, align) / bpp;
        int size = stride * desc.height * bpp * desc.layerCount;

        // 通过 DMA-Heap 分配连续物理内存
        struct dma_heap_allocation_data heap_alloc = {
            .len = size,
            .fd_flags = O_RDWR | O_CLOEXEC,
        };

        if (ioctl(mDmaHeapFd, DMA_HEAP_IOCTL_ALLOC, &heap_alloc) < 0) {
            ALOGE("DMA-Heap allocation failed: %s", strerror(errno));
            return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
        }

        // 创建 native_handle(包含 DMA-BUF fd)
        int numFds = 1;
        int numInts = 5;  // size, width, height, stride, format
        native_handle_t* handle = native_handle_create(numFds, numInts);
        handle->data[0] = heap_alloc.fd;     // DMA-BUF fd
        handle->data[1] = size;
        handle->data[2] = desc.width;
        handle->data[3] = desc.height;
        handle->data[4] = stride;
        handle->data[5] = static_cast<int>(desc.format);

        *outBuffer = {
            .bufferHandle = handle,
            .stride = stride,
            .byteCount = static_cast<int64_t>(size),
        };

        ALOGD("Allocated buffer: %dx%d, stride=%d, size=%d, fd=%d",
              desc.width, desc.height, stride, size, handle->data[0]);

        return ndk::ScopedAStatus::ok();
    }

private:
    int mDmaHeapFd = -1;

    int GetBpp(aidl::android::hardware::graphics::common::PixelFormat fmt) {
        switch (fmt) {
            case PixelFormat::RGBA_8888:
            case PixelFormat::BGRA_8888:
                return 4;
            case PixelFormat::RGB_888:
                return 3;
            case PixelFormat::RGB_565:
                return 2;
            case PixelFormat::YCBCR_420_888:
                return 1;  // Y plane
            default:
                return 4;
        }
    }
};

4. Mapper 接口(CPU 访问缓冲区)

// device/device/gralloc/T8000GrallocMapper.cpp

#include <aidl/android/hardware/graphics/mapper/IMapper.h>
#include <sys/mman.h>
#include <linux/dma-buf.h>

using aidl::android::hardware::graphics::mapper::IMapper;

/**
 * Mapper 负责将缓冲区映射到 CPU 地址空间
 * Android 16: 同样迁移到 AIDL
 */
class T8000GrallocMapper : public IMapper {
public:
    ndk::ScopedAStatus mapBuffer(native_handle_t* handle,
                                  IMapper::Rectangle accessRegion,
                                  IMapper::SyncPolicy syncPolicy,
                                  IMapper::MapBufferDesc* outDesc) override {
        int dmaBufFd = handle->data[0];
        int size = handle->data[1];

        // 同步 DMA 缓冲区
        struct dma_buf_sync sync = {};
        sync.flags = DMA_BUF_SYNC_START | DMA_BUF_SYNC_RW;
        if (ioctl(dmaBufFd, DMA_BUF_IOCTL_SYNC, &sync) < 0) {
            ALOGE("DMA_BUF_IOCTL_SYNC failed");
            return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
        }

        // mmap 映射
        void* vaddr = mmap(nullptr, size,
                           PROT_READ | PROT_WRITE, MAP_SHARED,
                           dmaBufFd, 0);
        if (vaddr == MAP_FAILED) {
            ALOGE("mmap failed: %s", strerror(errno));
            return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
        }

        outDesc->data = vaddr;
        outDesc->dataSize = size;
        outDesc->stride = handle->data[4];

        return ndk::ScopedAStatus::ok();
    }

    ndk::ScopedAStatus unmapBuffer(native_handle_t* handle,
                                    void* data,
                                    int64_t dataSize) override {
        munmap(data, dataSize);

        int dmaBufFd = handle->data[0];
        struct dma_buf_sync sync = {};
        sync.flags = DMA_BUF_SYNC_END | DMA_BUF_SYNC_RW;
        ioctl(dmaBufFd, DMA_BUF_IOCTL_SYNC, &sync);

        return ndk::ScopedAStatus::ok();
    }

    /**
     * 获取缓冲区信息
     */
    ndk::ScopedAStatus get(native_handle_t* handle,
                           IMapper::MetadataType metadataType,
                           std::vector<uint8_t>* outMetadata) override {
        if (metadataType == IMapper::MetadataType_BufferId) {
            // 返回缓冲区唯一 ID
            int64_t bufferId = reinterpret_cast<int64_t>(handle);
            outMetadata->resize(sizeof(bufferId));
            memcpy(outMetadata->data(), &bufferId, sizeof(bufferId));
        }
        return ndk::ScopedAStatus::ok();
    }
};

SurfaceFlinger详解(Android 16 更新版)

SurfaceFlinger核心流程(BLAST-Sync + HWC3)

Android 16 核心变更

  • BLAST-Sync (Buffer-Less Async Sync):新的默认同步机制,消除了旧版 Transaction 机制中的额外 VSync 等待,将合成延迟从 2 帧减少到 1 帧
  • SkiaGraphRenderer:替代旧的 OpenGL ES 合成管线,基于有向无环图 (DAG) 的渲染调度
// frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
// Android 16 (API 36)

class SurfaceFlinger : public aidl::android::hardware::graphics::composer3::IComposerCallback {
public:
    void onMessageReceived(int32_t what);

private:
    // VSync 回调(支持 VRR)
    void onVSyncEvent(nsecs_t timestamp, int64_t expectedVSyncTimeNs);

    // BLAST-Sync: 无缓冲异步合成
    void onAsyncTransactionComplete();

    // 合成所有 Layer
    void composeSurfaces(const Region& dirty);

    // HWC3 AIDL 客户端
    sp<Hwc3Composer> mHwc3Composer;

    // BLAST-Sync 事务管理
    sp<BlastSyncManager> mBlastSyncManager;

    // VRR 自适应刷新率控制
    sp<RefreshRateSelector> mRefreshRateSelector;

    // Layer 列表
    Vector<sp<Layer>> mLayers;
};

// Android 16: VRR 感知的 VSync 处理
void SurfaceFlinger::onVSyncEvent(nsecs_t timestamp, int64_t expectedVSyncTimeNs) {
    // 根据 VRR 调整下一帧的预期时间
    auto currentMode = mActiveMode;
    mEventQueue.invalidate(timestamp, currentMode.refreshRate);

    // LTPO 场景:如果所有 Layer 都静止,降低刷新率
    if (mRefreshRateSelector->shouldLowerRefreshRate()) {
        mHwc3Composer->setActiveConfigWithConstraints(
            mDisplayId,
            RefreshRateConfig::kLowPowerMode,
            { .minRefreshRateNanos = 1'000'000'000LL,  // 1Hz
              .maxRefreshRateNanos = 16'666'666LL }     // 60Hz
        );
    }
}

// Android 16: BLAST-Sync 事务完成回调
void SurfaceFlinger::onAsyncTransactionComplete() {
    // BLAST-Sync: 不等下一个 VSync 就提交
    // 减少了 1 帧的延迟
    handleMessageRefresh();
}

void SurfaceFlinger::onMessageReceived(int32_t what) {
    switch (what) {
    case MessageQueue::INVALIDATE:
        handleMessageTransaction();
        handleMessageInvalidate();
        break;
    case MessageQueue::REFRESH:
        handleMessageRefresh();
        break;
    case MessageQueue::BLAST_SYNC_COMPLETE:
        // Android 16 新增:BLAST-Sync 完成事件
        onAsyncTransactionComplete();
        break;
    }
}

void SurfaceFlinger::handleMessageRefresh() {
    // 预合成
    preComposition();

    // 重建 Layer 栈
    rebuildLayerStacks();

    // HWC3: prepare (AIDL 接口)
    auto [validatedState, compositionChanges] =
        mHwc3Composer->validateDisplay(mDisplayId, mCurrentState);

    // 处理合成变更(哪些 Layer 由 HWC 合成,哪些由 GPU 合成)
    applyCompositionChanges(compositionChanges);

    // 执行合成
    doComposition();

    // 提交到显示器
    postComposition();
}

// Android 16: SkiaGraphRenderer GPU 合成
void SurfaceFlinger::doClientComposition(const Vector<sp<Layer>>& layers) {
    // 使用 SkiaGraphRenderer 替代旧的 OpenGL ES 管线
    SkiaGraphRenderer renderer(mDisplaySurface);

    // 构建渲染图(DAG)
    auto renderGraph = renderer.buildGraph(layers);

    // 拓扑排序 + 并行调度
    renderer.execute(renderGraph);

    // 提交到 HWC3
    mHwc3Composer->presentDisplay(mDisplayId, renderer.getOutputBuffer());
}

void SurfaceFlinger::doComposition() {
    for (const auto& display : mDisplays) {
        const auto& layers = display->getVisibleLayersSortedByZ();

        // HWC3: 检查是否可以全硬件合成
        if (mHwc3Composer->canHandleFullComposition(display)) {
            // 全硬件合成(最优路径,省电)
            mHwc3Composer->commitDisplay(display);
        } else {
            // 部分 GPU 合成(SkiaGraphRenderer)
            doClientComposition(layers);
            mHwc3Composer->presentDisplay(display);
        }
    }
}

BLAST-Sync 详细机制

传统同步机制(Android 15 及更早):
  VSync 1 → App 绘制 → queueBuffer
  VSync 2 → SF 合成 → 显示         ← 需要等下一个 VSync
  VSync 3 → 画面可见

  延迟:2 帧

BLAST-Sync(Android 16 默认):
  VSync 1 → App 绘制 → queueBuffer
         → SF 立即合成(不等 VSync)
         → 显示提交
  VSync 2 → 画面可见                  ← 提前一帧

  延迟:1 帧

BLAST-Sync 核心原理:
1. 应用 dequeueBuffer 时立即获得缓冲区,不等 VSync
2. queueBuffer 后 SurfaceFlinger 收到异步通知
3. SurfaceFlinger 不等 VSync 就触发合成
4. 合成完成立即提交给 HWC3
5. 硬件在下一个 VSync 边界翻转页面

关键优势:
- 减少触摸到显示的延迟(Touch-to-Photon Latency)
- 减少 16.6ms(60Hz)到 8.3ms(120Hz)的延迟
- 对游戏和动画场景感知明显

详细内容参考之前的笔记:SurfaceFlinger机制

HWC3(HWComposer 3.0,Android 16 标准)

1. HWC3 的作用

HWC3(Hardware Composer 3.0)
├── AIDL 接口(替代 HIDL 2.x)
├── 利用硬件 Overlay 合成多个 Layer
├── 避免 GPU 合成(省电、高效)
├── 支持 VRR(可变刷新率)
├── 支持 HDR 元数据(HDR10、HLG、Dolby Vision)
├── 支持 Color Management(BT.709、BT.2020、DCI-P3)
├── 支持多显示器(每显示器独立 VRR)
└── Android 16 新增
    ├── Bypass 模式(直接 DRM 提交)
    ├── Client Target Compression(合成目标压缩)
    └── 增量 Validate(减少 API 调用次数)

2. HWC3 AIDL 接口

// hardware/interfaces/graphics/composer3/aidl/IComposerClient.aidl

package android.hardware.graphics.composer3;

import android.hardware.graphics.composer3.DisplayRequest;
import android.hardware.graphics.composer3.LayerRequest;
import android.hardware.graphics.composer3.VsyncPeriodChangeTiming;

/**
 * HWC3 AIDL 客户端接口
 * 替代 HIDL 的 IComposerClient 2.x
 */
interface IComposerClient {

    /**
     * 设置 Layer 的缓冲区
     */
    setLayerBuffer(Display display, Layer layer, handle buffer, Fence acquireFence);

    /**
     * 设置 Layer 的显示区域
     */
    setLayerDisplayFrame(Display display, Layer layer, Rect frame);

    /**
     * 设置 Layer 的裁剪区域
     */
    setLayerSourceCrop(Display display, Layer layer, FRect crop);

    /**
     * 设置 Layer 的 Z 顺序
     */
    setLayerZOrder(Display display, Layer layer, int z);

    /**
     * 设置 Layer 的混合模式
     */
    setLayerBlendMode(Display display, Layer layer, BlendMode mode);

    /**
     * 设置 Layer 的不透明度
     */
    setLayerAlpha(Display display, Layer layer, float alpha);

    /**
     * 设置 Layer 的合成类型
     */
    setLayerCompositionType(Display display, Layer layer, Composition type);

    /**
     * 设置 VSync 周期(VRR 支持)
     * Android 16: 应用可变刷新率
     */
    setVsyncPeriod(Display display, int periodNs);

    /**
     * 验证显示配置
     * HWC3 增量 validate:只需传递变化的 Layer
     */
    validateDisplay(Display display, ValidateDisplayInput input)
        generates (ValidateDisplayOutput output);

    /**
     * 提交显示
     */
    presentDisplay(Display display, PresentDisplayInput input)
        generates (PresentDisplayOutput output);

    /**
     * Android 16 新增:Bypass 模式
     * 直接将 Layer 提交到 DRM,跳过 HWC 合成
     */
    bypassDisplay(Display display, BypassRequest request)
        generates (BypassResponse response);

    /**
     * Android 16 新增:获取显示器的 HDR 能力
     */
    getHdrCapabilities(Display display) generates (HdrCapabilities caps);
}

/**
 * Composition 类型(HWC 如何合成 Layer)
 */
enum Composition {
    INVALID,          // 无效
    HWC,              // HWC 硬件合成(最优)
    CLIENT,           // Client(GPU/SkiaGraphRenderer)合成
    SIDEBAND,         // 旁路合成(视频流)
    SOLID_COLOR,      // 纯色填充
    BACKDROP,         // 背景(模糊效果)
    CLIENT_BYPASS,    // Android 16: Client 直提交到 DRM
}

3. HWC3 HAL 实现要点

// device/device/hwcomposer/T8000Hwc3Service.cpp

#include <aidl/android/hardware/graphics/composer3/IComposerClient.h>
#include <drm_mode.h>
#include <fcntl.h>
#include <linux/dma-buf.h>
#include <sys/ioctl.h>

using aidl::android::hardware::graphics::composer3::IComposerClient;

/**
 * Android 16 HWC3 实现
 * 直接操作 DRM/KMS 进行硬件合成
 */
class T8000Hwc3Service : public IComposerClient {
public:
    T8000Hwc3Service() {
        // 打开 DRM 设备
        mDrmFd = open("/dev/dri/card0", O_RDWR | O_CLOEXEC);
        if (mDrmFd < 0) {
            ALOGE("Failed to open DRM device");
            return;
        }

        // 获取 DRM 资源
        struct drm_mode_card_res res = {};
        ioctl(mDrmFd, DRM_IOCTL_MODE_GETRESOURCES, &res);

        // 获取 Primary Plane ID
        struct drm_mode_get_plane_res planeRes = {};
        ioctl(mDrmFd, DRM_IOCTL_MODE_GETPLANERESOURCES, &planeRes);

        mPlaneIds.assign(planeRes.plane_ids,
                         planeRes.plane_ids + planeRes.count_planes);

        // T8000 支持 8 个 Overlay Plane
        mMaxOverlayPlanes = std::min(8, planeRes.count_planes);
    }

    ndk::ScopedAStatus validateDisplay(
            Display display,
            const ValidateDisplayInput& input,
            ValidateDisplayOutput* output) override {

        int clientLayers = 0;
        int hwcLayers = 0;

        for (const auto& layer : input.layers) {
            // 判断 Layer 是否可以硬件合成
            if (canHwcComposeLayer(layer)) {
                output->changedLayers.push_back({
                    .layer = layer.layer,
                    .newType = Composition::HWC,
                });
                hwcLayers++;
            } else {
                output->changedLayers.push_back({
                    .layer = layer.layer,
                    .newType = Composition::CLIENT,
                });
                clientLayers++;
            }
        }

        output->numHwcLayers = hwcLayers;
        output->numClientLayers = clientLayers;

        return ndk::ScopedAStatus::ok();
    }

    ndk::ScopedAStatus presentDisplay(
            Display display,
            const PresentDisplayInput& input) override {

        std::vector<drm_mode_plane_set> planeSets;

        // 配置 HWC 合成的 Layer 到 DRM Plane
        for (const auto& layer : input.layers) {
            if (layer.compositionType != Composition::HWC)
                continue;

            drm_mode_plane_set planeSet = {};
            planeSet.plane_id = assignPlane(layer);
            planeSet.crtc_id = mPrimaryCrtcId;
            planeSet.fb_id = getDrmFbIdFromBuffer(layer.buffer);
            planeSet.crtc_x = layer.displayFrame.left;
            planeSet.crtc_y = layer.displayFrame.top;
            planeSet.crtc_w = layer.displayFrame.right - layer.displayFrame.left;
            planeSet.crtc_h = layer.displayFrame.bottom - layer.displayFrame.top;
            planeSet.src_x = layer.sourceCrop.left << 16;   // 16.16 定点数
            planeSet.src_y = layer.sourceCrop.top << 16;
            planeSet.src_w = (layer.sourceCrop.right - layer.sourceCrop.left) << 16;
            planeSet.src_h = (layer.sourceCrop.bottom - layer.sourceCrop.top) << 16;

            planeSets.push_back(planeSet);
        }

        // 批量提交到 DRM
        struct drm_mode_atomic commit = {};
        commit.flags = DRM_MODE_ATOMIC_NONBLOCK | DRM_MODE_PAGE_FLIP_EVENT;
        commit.count_objs = planeSets.size() * 4 + 2;
        commit.objs_ptr = reinterpret_cast<uint64_t>(buildPropertyArray(planeSets));
        commit.props_ptr = reinterpret_cast<uint64_t>(buildValueArray(planeSets));

        if (ioctl(mDrmFd, DRM_IOCTL_MODE_ATOMIC, &commit) < 0) {
            ALOGE("DRM atomic commit failed: %s", strerror(errno));
            return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
        }

        return ndk::ScopedAStatus::ok();
    }

    // Android 16: VRR 支持
    ndk::ScopedAStatus setVsyncPeriod(Display display, int periodNs) override {
        uint32_t vrefresh = 1'000'000'000 / periodNs;

        // 查找匹配的 DRM 显示模式
        struct drm_mode_card_res res = {};
        ioctl(mDrmFd, DRM_IOCTL_MODE_GETRESOURCES, &res);

        for (int i = 0; i < res.count_connectors; i++) {
            uint32_t connId = res.connectors[i];
            struct drm_mode_get_connector conn = {};
            conn.connector_id = connId;

            // 获取 connector 模式列表
            ioctl(mDrmFd, DRM_IOCTL_MODE_GETCONNECTOR, &conn);

            // 找到匹配刷新率的模式
            for (int j = 0; j < conn.count_modes; j++) {
                if (conn.modes[j].vrefresh == vrefresh) {
                    // 设置 CRTC 模式
                    setConnectorMode(connId, conn.modes[j]);
                    break;
                }
            }
        }

        return ndk::ScopedAStatus::ok();
    }

private:
    int mDrmFd = -1;
    std::vector<uint32_t> mPlaneIds;
    uint32_t mPrimaryCrtcId = 0;
    int mMaxOverlayPlanes = 0;

    bool canHwcComposeLayer(const LayerInfo& layer) {
        // T8000 硬件合成约束
        // 1. 最多 8 个 Overlay Plane
        // 2. Overlay 不支持旋转
        // 3. Overlay 支持 YUV 和 RGB 格式
        // 4. 不支持 alpha 混合(需要预乘)
        return true;  // 简化示例
    }

    uint32_t assignPlane(const LayerInfo& layer) {
        // 按 Z-order 分配 Plane ID
        return mPlaneIds[layer.zOrder % mMaxOverlayPlanes];
    }

    uint32_t getDrmFbIdFromBuffer(handle buffer) {
        // 从 GraphicBuffer 创建 DRM Framebuffer
        int dmaBufFd = buffer->data[0];
        int width = buffer->data[2];
        int height = buffer->data[3];
        int stride = buffer->data[4];
        uint32_t format = buffer->data[5];

        uint32_t fbId = 0;
        uint32_t pitches[4] = { stride * 4, 0, 0, 0 };
        uint32_t offsets[4] = { 0, 0, 0, 0 };
        uint32_t handles[4] = { 0 };

        // 导入 DMA-BUF 到 DRM
        struct drm_prime_handle prime = {};
        prime.fd = dmaBufFd;
        ioctl(mDrmFd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &prime);
        handles[0] = prime.handle;

        drmModeAddFB2(mDrmFd, width, height, format,
                      handles, pitches, offsets, &fbId, 0);

        return fbId;
    }
};

与Framework层的关联

应用绘制到显示的完整流程(Android 16)

Activity.onDraw()
  ↓
View.draw(Canvas) / RenderNode.draw()
  ↓ (SkiaGraphRenderer - Android 16 新渲染管线)
填充 GraphicBuffer
  ↓
Surface.queueBuffer()  ← BLAST-Sync 异步提交
  ↓ (Binder + AIDL)
SurfaceFlinger.onFrameAvailable()
  ↓
BLAST-Sync 触发合成(不等 VSync)
  ↓
SurfaceFlinger 合成
  ├── 收集所有 Layer 的 Buffer
  ├── HWC3 硬件合成(优先)
  └── SkiaGraphRenderer GPU fallback
  ↓
DRM/KMS 页面翻转(/dev/dri/card0)
  ↓
显示到屏幕(VRR/LTPO 自适应刷新率)

Android 16 渲染管线变化

组件 Android 15 及更早 Android 16 (API 36)
内核驱动 fbdev 或 DRM 仅 DRM/KMS
Gralloc HAL HIDL AIDL
HWComposer HIDL (HWC2) AIDL (HWC3)
同步机制 Transaction + VSync BLAST-Sync(默认)
GPU 合成 OpenGL ES SkiaGraphRenderer (DAG)
内存分配 ION / dmabuf DMA-Heap
刷新率 固定 / VRR 可选 VRR + LTPO 标配

详细内容参考之前的笔记:

  • SurfaceFlinger机制
  • View绘制流程
  • 硬件加速渲染

调试命令和工具

1. 查看 DRM 显示设备

# Android 16: fbdev 已移除,只查看 DRM 设备
# 查看 DRM 设备节点
adb shell ls -l /dev/dri/
# card0        → 主控制设备
# renderD128   → 渲染设备(GEM/Prime)

# 查看 DRM 状态和所有 CRTC/Plane/Connector
adb shell cat /sys/kernel/debug/dri/0/state

# 查看 DRM 模式列表
adb shell cat /sys/kernel/debug/dri/0/eviction

# 查看 VRR 状态
adb shell cat /sys/kernel/debug/dri/0/vrr

# 查看 DMA-BUF 分配情况
adb shell cat /sys/kernel/debug/dma_buf/bufinfo

# 查看 DMA-Heap 使用量
adb shell cat /sys/kernel/debug/dma_heap/

# 查看 DRM 帧率统计
adb shell cat /sys/kernel/debug/dri/0/vblank

2. dumpsys SurfaceFlinger(Android 16 更新)

# 查看 SurfaceFlinger 完整状态
adb shell dumpsys SurfaceFlinger

# Android 16 输出新增信息:
# - BLAST-Sync 状态(启用/禁用)
# - 每个 Layer 的同步类型(BlastSync / Transaction)
# - HWC3 合成类型(AIDL 接口)
# - VRR 当前刷新率
# - SkiaGraphRenderer GPU 合成统计
# - DMA-BUF 使用量

# 查看 Layer 列表
adb shell dumpsys SurfaceFlinger | grep "Layer name"

# 查看合成类型(HWC3 Composition)
adb shell dumpsys SurfaceFlinger | grep "composition type"

# 查看当前刷新率(VRR)
adb shell dumpsys SurfaceFlinger | grep "refresh rate"

# 查看 BLAST-Sync 状态
adb shell dumpsys SurfaceFlinger | grep -i "blast"

# 查看 VRR 配置
adb shell dumpsys SurfaceFlinger | grep -i "vrr\|variable"

# 查看 DRM 合成信息
adb shell dumpsys SurfaceFlinger | grep -i "drm\|kms"

3. 屏幕截图和录屏

# 截图(通过 DRM 截图)
adb shell screencap /sdcard/screenshot.png
adb pull /sdcard/screenshot.png

# 录屏
adb shell screenrecord /sdcard/demo.mp4
# Ctrl+C 停止
adb pull /sdcard/demo.mp4

# 查看 Gralloc (AIDL) 分配情况
adb shell dumpsys allocator

4. 性能分析(Android 16 增强)

# 查看帧率
adb shell dumpsys SurfaceFlinger | grep "Frame rate"

# 实时显示帧率叠加(Android 16 支持 VRR 显示)
adb shell settings put global show_fps_overlay 1

# GPU 渲染分析(SkiaGraphRenderer)
adb shell setprop debug.hwui.renderer skia_graph  # 启用 DAG 渲染
adb shell setprop debug.hwui.profile visual_bars   # 屏幕渲染柱状图

# Systrace / Perfetto 分析
adb shell perfetto -t 10s -o /data/misc/perfetto-traces/trace.pb \
  gfx view sched freq

# VRR 分析:查看刷新率变化
adb shell dumpsys SurfaceFlinger | grep -E "refresh|vrr" | head -20

# LTPO AOD 刷新率验证(应降至 1Hz)
adb shell dumpsys SurfaceFlinger | grep "active mode"

# BLAST-Sync 延迟分析
adb shell setprop debug.surfaceflinger.blast_sync_log 1
adb logcat -s SurfaceFlinger | grep -i "blast"

5. 调试 Gralloc(AIDL / DMA-Heap)

# 查看 GraphicBuffer 使用情况
adb shell dumpsys meminfo --unreachable [pid]

# 查看 DMA-Heap 分配(替代旧的 ION)
adb shell cat /sys/kernel/debug/dma_heap/system-uncached/

# 查看 DMA-BUF 引用计数
adb shell cat /sys/kernel/debug/dma_buf/dentry

# 查看进程的图形内存
adb shell dumpsys meminfo [package_name] | grep -A 5 "Graphics"

# 查看 Gralloc AIDL 服务状态
adb shell dumpsys allocator
adb shell dumpsys | grep "android.hardware.graphics.allocator"

6. HWC3 调试

# 查看 HWC3 合成策略
adb shell dumpsys SurfaceFlinger | grep -A 3 "HWC"

# 查看哪些 Layer 由 GPU 合成(Client Composition)
adb shell dumpsys SurfaceFlinger | grep "Client"

# 查看 HWC3 AIDL 服务状态
adb shell dumpsys | grep "composer"

# 强制 GPU 合成(调试用,对比性能)
adb shell setprop debug.surfaceflinger.force_gpu_composition 1

# 强制 HWC 合成(测试 HWC3 实现)
adb shell setprop debug.surfaceflinger.force_hwc_composition 1

与T8000项目的关联

T8000显示特性

T8000 显示配置
├── 输出接口:HDMI 1.4 → HDMI 2.1(支持 VRR)
├── 分辨率:1920x1080 @ 60Hz → 支持 4K @ 60Hz
├── VRR:支持(HDMI VRR / FreeSync)
├── 用途:
│   ├── 显示监控画面(主要)
│   ├── OSD叠加(时间、状态)
│   └── UI界面(设置)
└── 特殊需求:
    ├── 多路视频画面合成
    ├── 低延迟(BLAST-Sync 优化)
    ├── 长时间稳定运行
    └── VRR 节能(静态画面降刷新率)

T8000 BoardConfig(Android 16 配置)

# device/device/T8000/BoardConfig.mk

# 屏幕配置
TARGET_SCREEN_WIDTH := 1920
TARGET_SCREEN_HEIGHT := 1080
TARGET_SCREEN_DENSITY := 160  # mdpi

# Android 16: DRM 唯一,移除所有 FB 配置
TARGET_USES_DRM := true
TARGET_USES_FBDEV := false  # 已废弃

# Gralloc HAL (AIDL)
TARGET_USES_AIDL_ALLOCATOR := true
TARGET_USES_DMA_HEAP := true  # 替代 ION

# HWC3
TARGET_USES_HWC3 := true
TARGET_USES_AIDL_COMPOSER := true

# BLAST-Sync
TARGET_USES_BLAST_SYNC := true

# VRR 支持
TARGET_USES_VRR := true
TARGET_SUPPORTS_VARIABLE_REFRESH_RATE := true

# 渲染管线
TARGET_USES_SKIA_GRAPH_RENDERER := true

T8000 DRM 驱动集成

# kernel 配置(Android 16:FB 已移除)
# 移除旧配置
# CONFIG_FB=n               ← 已不存在
# CONFIG_FB_T8000=n         ← 已不存在

# DRM 核心
CONFIG_DRM=y
CONFIG_DRM_T8000=y
CONFIG_DRM_KMS_HELPER=y
CONFIG_DRM_GEM_DMA_HELPER=y
CONFIG_DRM_PANEL=y
CONFIG_DRM_BRIDGE=y

# DMA-BUF / DMA-Heap
CONFIG_DMA_SHARED_BUFFER=y
CONFIG_DMABUF_HEAPS=y
CONFIG_DMABUF_HEAPS_SYSTEM=y
CONFIG_DMABUF_HEAPS_CMA=y

# VRR 支持
CONFIG_DRM_DISPLAY_CONNECTOR=y

# HAL 编译
# device/device/T8000/device.mk
PRODUCT_PACKAGES += \
    android.hardware.graphics.allocator-service.T8000 \
    android.hardware.graphics.composer3-service.T8000 \
    android.hardware.graphics.mapper-service.T8000

T8000多路视频显示策略(Android 16 优化)

多路视频显示架构
├── Camera输入(8路)
│   ├── 硬件解码(VPU)
│   └── YUV 格式输出(NV12 / YUV420)
├── 画面布局
│   ├── 1路全屏
│   ├── 4路分屏(2x2)
│   ├── 8路分屏(3x3,1空位)
│   └── 9路分屏(3x3)
├── 合成方式
│   ├── 优先 HWC3 硬件 Overlay(8 个 Plane)
│   ├── 回退 SkiaGraphRenderer GPU 合成
│   └── BLAST-Sync 降低合成延迟
├── VRR 优化
│   ├── 监控画面变化时 → 60Hz 正常刷新
│   └── 画面静止时 → 降至 10Hz 节能
└── OSD 叠加
    ├── 时间戳(HWC 单独 Plane)
    ├── 摄像头名称(HWC 单独 Plane)
    └── 录像状态指示(HWC 单独 Plane)

T8000 HWC3 实现要点

// device/device/hwcomposer/T8000Hwc3VideoStrategy.cpp

#include <aidl/android/hardware/graphics/composer3/IComposerClient.h>

/**
 * T8000 多路视频 HWC3 合成策略
 * Android 16: 利用 8 个 Overlay Plane 实现 8 路视频直出
 */
class T8000VideoHwcStrategy {
public:
    // 检查是否可以硬件合成(HWC3 validate)
    ndk::ScopedAStatus validateVideoLayers(
            const std::vector<LayerInfo>& videoLayers) {

        // T8000 支持 8 个硬件 Overlay Plane
        int hwcCapable = std::min(8, static_cast<int>(mAvailablePlanes));

        for (int i = 0; i < videoLayers.size(); i++) {
            const auto& layer = videoLayers[i];

            if (i < hwcCapable && isVideoLayer(layer)) {
                // 标记为 HWC Overlay(最优路径)
                layer.compositionType = Composition::HWC;

                // 配置 YUV 格式直接输出(无需色彩转换)
                layer.bufferFormat = PixelFormat::YCBCR_420_888;

                // 设置 HDR 元数据(如果源视频是 HDR)
                if (layer.isHDR) {
                    layer.hdrType = HdrType::HDR10;
                }
            } else {
                // 超过 8 路 → GPU 合成(SkiaGraphRenderer)
                layer.compositionType = Composition::CLIENT;
            }
        }

        return ndk::ScopedAStatus::ok();
    }

    // VRR 策略:根据视频活动调整刷新率
    void adjustRefreshRateForVideo() {
        bool hasActiveVideo = checkVideoActivity();

        if (!hasActiveVideo) {
            // 无活跃视频 → 降低刷新率到 30Hz 节能
            setVsyncPeriod(33'333'333);  // 30Hz
        } else if (hasHighFrameRateVideo()) {
            // 高帧率视频 → 60Hz
            setVsyncPeriod(16'666'666);  // 60Hz
        } else {
            // 普通视频 → 30Hz 足够
            setVsyncPeriod(33'333'333);  // 30Hz
        }
    }

private:
    int mAvailablePlanes = 8;

    bool isVideoLayer(const LayerInfo& layer) {
        // 视频 Layer 使用 YUV 格式
        return layer.format == PixelFormat::YCBCR_420_888
            || layer.format == PixelFormat::YCBCR_422_888;
    }
};

T8000启动Logo(Bootanimation)

# 替换启动动画
# device/device/T8000/bootanimation.zip

# 结构
bootanimation.zip
├── desc.txt       # 描述文件
├── part0/         # 第一部分动画
│   ├── 00000.png
│   ├── 00001.png
│   └── ...
└── part1/         # 第二部分动画

# desc.txt内容
1920 1080 60      # 分辨率和帧率
p 1 0 part0       # 播放part0,1次,延迟0帧
p 0 0 part1       # 播放part1,无限循环

# Android 16: 支持 HDR bootanimation
# desc.txt 可加 HDR 标记
1920 1080 60 hdr10

快速回忆检查点

问题1:Android 16 中 DRM/KMS 与 Framebuffer 的关系是什么?

答案
  • Framebuffer 已完全移除/dev/fb* 设备节点不存在,CONFIG_FB 不再用于显示
  • DRM/KMS 是唯一标准:所有显示操作通过 /dev/dri/card0 和 DRM ioctl 完成
  • 关键组件:CRTC(显示控制器)、Encoder(编码器)、Connector(连接器)、Plane(图层)
  • 内存管理:GEM(缓冲区管理)+ DMA-BUF(跨驱动共享)+ DMA-Heap(内存分配)

问题2:Gralloc HAL 在 Android 16 有什么变化?

答案
  • 接口迁移:从 HIDL 完全迁移到 AIDL(hardware/interfaces/graphics/allocator/aidl/
  • 内存分配:从 ION 迁移到 DMA-Heap(/dev/dma_heap/
  • 新用法标志SENSOR_DIRECT_DATACOMPOSER_BYPASS 等 Android 16 新增标志
  • Mapper:同样使用 AIDL 接口管理 CPU 映射

问题3:BLAST-Sync 相比旧同步机制有什么优势?

答案
  1. 减少 1 帧延迟:不等 VSync 就触发合成,从 2 帧降到 1 帧
  2. 异步提交:queueBuffer 后立即通知 SurfaceFlinger,不等下一个 VSync
  3. 降低 Touch-to-Photon 延迟:触摸到显示的端到端延迟减少 16.6ms(60Hz)
  4. Android 16 默认启用:无需手动配置

问题4:HWC3 与 HWC2 的区别是什么?

答案
  • 接口类型:HIDL (2.x) → AIDL (3.0)
  • 新增功能:VRR 支持、HDR 元数据、Bypass 模式、增量 Validate
  • Composition 类型:新增 CLIENT_BYPASS(Client 直提交到 DRM)
  • 验证优化:增量 validate,只需传递变化的 Layer

问题5:VRR 和 LTPO 的区别和应用场景?

答案
  • VRR (Variable Refresh Rate):可变刷新率,在 60/90/120/144Hz 间动态切换
    • 游戏/高帧率场景 → 120Hz+
    • 普通浏览场景 → 60Hz 节能
  • LTPO (Low-Temperature Polycrystalline Oxide):屏幕技术,支持极低刷新率
    • AOD (Always-On Display) → 1Hz
    • 静态内容 → 10Hz
    • 动态内容 → 120Hz
  • 结合使用:LTPO 面板 + VRR 控制 = 1Hz~144Hz 全范围自适应

问题6:SkiaGraphRenderer 是什么?相比旧的 OpenGL 合成有什么改进?

答案
  • DAG 渲染管线:基于有向无环图(Directed Acyclic Graph)的渲染调度
  • 并行优化:拓扑排序后并行执行独立渲染节点
  • 替代 OpenGL ES:更现代的 GPU 合成方案
  • 优势:减少渲染管线切换、更好的内存局部性、支持异步渲染

问题7:T8000如何实现8路视频同时显示?

答案
  1. HWC3 硬件 Overlay:8 个 DRM Plane 分别输出 8 路视频
  2. 视频解码:VPU 并行解码 8 路视频
  3. Gralloc AIDL:分配 YUV 格式 DMA-BUF 缓冲区
  4. BLAST-Sync:降低合成延迟,保证实时监控低延迟
  5. VRR 优化:画面静止时降低刷新率节能
  6. 输出:通过 HDMI 2.1 输出 1080p/4K 画面

问题8:如何查看 Android 16 设备的显示信息?

答案
# 查看 DRM 状态(替代旧的 fbdev)
adb shell cat /sys/kernel/debug/dri/0/state

# 查看 DMA-BUF 分配
adb shell cat /sys/kernel/debug/dma_buf/bufinfo

# 查看 SurfaceFlinger 状态(含 BLAST-Sync、VRR、HWC3)
adb shell dumpsys SurfaceFlinger

# 查看 Layer 列表
adb shell dumpsys SurfaceFlinger | grep "Layer name"

# 查看 VRR 当前刷新率
adb shell dumpsys SurfaceFlinger | grep "refresh rate"

# 查看 BLAST-Sync 状态
adb shell dumpsys SurfaceFlinger | grep -i "blast"

关键概念图谱

Android 16 显示系统 (API 36)
├── 应用层
│   ├── Canvas / RenderNode 绘制
│   ├── Surface(双缓冲/三缓冲 + BLAST-Sync)
│   └── GraphicBuffer(DMA-BUF 跨进程共享)
├── Native 层
│   ├── SurfaceFlinger(BLAST-Sync 异步合成)
│   ├── SkiaGraphRenderer(DAG 渲染管线)
│   ├── HWC3 AIDL(硬件合成器 3.0)
│   └── Gralloc AIDL(DMA-Heap 缓冲区分配)
├── 内核层
│   ├── DRM/KMS(唯一显示标准)
│   │   ├── CRTC(显示控制器)
│   │   ├── Encoder(HDMI/DSI/LVDS)
│   │   ├── Connector(物理接口)
│   │   └── Plane(Primary/Overlay/Cursor)
│   ├── GEM(图形缓冲区管理)
│   └── DMA-BUF / DMA-Heap(内存分配)
└── 关键机制
    ├── VSync + VRR(可变刷新率 1Hz~144Hz)
    ├── LTPO(超低刷新率 AOD 场景)
    ├── BLAST-Sync(无缓冲异步同步,减少1帧延迟)
    ├── HDR 元数据(HDR10/HLG/Dolby Vision)
    ├── Color Management(BT.709/BT.2020/DCI-P3)
    └── 跨进程共享(DMA-BUF fd 传递)

Android 16 (API 36 “Baklava”) 显示系统变更汇总

以下内容已全部融合到上方各章节中,此段作为快速索引。

移除的组件

旧组件 替代方案
Framebuffer (/dev/fb*) DRM/KMS (/dev/dri/card0)
HWC2 (HIDL) HWC3 (AIDL)
Gralloc HIDL Gralloc AIDL
ION 内存分配器 DMA-Heap
OpenGL ES 合成 SkiaGraphRenderer (DAG)
Transaction 同步 BLAST-Sync (默认)

新增的功能

功能 说明
BLAST-Sync Buffer-Less Async Sync,减少 1 帧合成延迟
SkiaGraphRenderer 基于 DAG 的新 GPU 渲染管线
HWC3 AIDL 接口,支持 VRR/HDR/Bypass
VRR 可变刷新率,60/90/120/144Hz 动态切换
LTPO 1Hz~120Hz 自适应刷新率(AOD 场景)
HDR 支持 HDR10、HLG、Dolby Vision 元数据传递
DMA-Heap 替代 ION 的统一内存分配框架
增量 Validate HWC3 只传递变化的 Layer,减少 API 调用
Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐