04-05-06 深入理解Android内核设计思想 第6章:Android显示系统
·
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_DATA、COMPOSER_BYPASS等 Android 16 新增标志 - Mapper:同样使用 AIDL 接口管理 CPU 映射
问题3:BLAST-Sync 相比旧同步机制有什么优势?
答案- 减少 1 帧延迟:不等 VSync 就触发合成,从 2 帧降到 1 帧
- 异步提交:queueBuffer 后立即通知 SurfaceFlinger,不等下一个 VSync
- 降低 Touch-to-Photon 延迟:触摸到显示的端到端延迟减少 16.6ms(60Hz)
- 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路视频同时显示?
答案- HWC3 硬件 Overlay:8 个 DRM Plane 分别输出 8 路视频
- 视频解码:VPU 并行解码 8 路视频
- Gralloc AIDL:分配 YUV 格式 DMA-BUF 缓冲区
- BLAST-Sync:降低合成延迟,保证实时监控低延迟
- VRR 优化:画面静止时降低刷新率节能
- 输出:通过 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 调用 |
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)