十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Android虚拟机显示驱动property本质解析:只读身份铭牌而非配置项

Android虚拟机显示驱动property本质解析:只读身份铭牌而非配置项 1. 这个 property 不是配置项而是显示子系统在虚拟化环境中的“身份铭牌”你第一次在 Android 虚拟机日志里看到类似ro.hardware.graphics、debug.hwui.renderer或ro.boot.vga这样的字符串时大概率会下意识把它当成一个可随意修改的配置开关——就像改个build.prop里的ro.debuggable1那样简单。但事实恰恰相反这类 property 是 Android 显示驱动栈在虚拟化环境下完成初始化后主动向系统注册的“运行时身份标识”它不接受外部写入也不参与逻辑控制而是一个只读的、由底层图形栈自证其存在与能力的“铭牌”。这正是标题中“一个典型的安卓虚拟机显示驱动 property”所指的核心——它不是你在adb shell setprop里能随便覆盖的变量而是 EGL 初始化流程中GPU 抽象层如gralloc、hwcomposer与虚拟 GPU 设备如 VirGL、QEMU GL、SwiftShader握手成功后由 HAL 层通过property_set()主动写入的运行时状态快照。关键词里没提但实际支撑它的技术底座是EGL GLES HAL Virtual GPU Backend四层耦合体。举个最直观的例子当你在 QEMU 启动带-vga virtio-gpu-gl参数的 Android x86 镜像时内核加载virtio_gpu.ko用户态libGLES_android.so加载libvirglrenderer.so最终hwcomposer2.3-impl.so检测到 VirtIO-GPU 设备可用就会执行property_set(ro.hardware.graphics, virtio); property_set(ro.hardware.egl, mesa); property_set(debug.hwui.renderer, opengl);这些 property 的值直接决定了后续SurfaceFlinger是否启用硬件合成、Skia是否走 OpenGL 渲染路径、甚至WebView是否启用硬件加速。它们不是“设置”而是“声明”——就像一个人走进房间时亮出的工牌上面写着“我是谁、我能做什么、我从哪来”。提示这类 property 的命名有强规律性。以ro.开头的为只读系统属性runtime-onlydebug.开头的为调试开关可动态修改但需 rootpersist.开头的为持久化存储写入/data/property/。而显示驱动相关的90% 落在ro.hardware.*和debug.hwui.*命名空间下。为什么这个细节如此关键因为大量开发者在调试虚拟机图形异常时第一反应是“改 property”结果发现setprop ro.hardware.graphics swiftshader完全无效——不是命令错了而是该 property 在zygote启动前已被 HAL 写死后续写入被内核 property service 拒绝PROP_VALUE_MAX限制只读标记。真正要改的是启动参数、HAL 实现或 GPU backend 配置而不是 property 本身。我在给某国产车机模拟器做 Android 11 虚拟化适配时就踩过这个坑团队花三天反复修改build.prop里的ro.hardware.graphics却始终无法启用 Vulkan 渲染。最后用strace -p $(pidof surfaceflinger) -e traceproperty_set抓到真正生效的是init进程启动hwcomposer服务时写入的ro.hardware.vulkan而那个值来自/vendor/lib/hw/vulkan.virtio.so的vkGetPhysicalDeviceProperties()返回结果——property 只是结果的镜像不是原因。所以理解这个 property 的本质是切入 Android 虚拟机图形调试的第一把钥匙它不解决问题但它精准指向问题发生的层级。2. EGL 初始化链路从 libEGL.so 到虚拟 GPU 设备的七步握手Android 虚拟机中显示驱动 property 的生成并非孤立事件而是 EGLEmbedded-System Graphics Library初始化流程的自然产物。整个过程像一场精密的七步握手每一步失败都会导致 property 缺失、错误或 fallback 到软件渲染。下面我以 Android 10 AOSP 通用流程为基础结合主流虚拟化方案QEMU/VirGL、VMware Workstation、Windows Subsystem for Android逐层拆解这个链条。2.1 第一步EGL 库加载与平台探测当应用调用eglGetDisplay(EGL_DEFAULT_DISPLAY)时libEGL.so位于/system/lib/egl/首先执行平台探测。它不直接访问硬件而是读取ro.hardware.graphics如果已存在或尝试枚举/vendor/lib/egl/下的.so文件ls /vendor/lib/egl/ # 输出可能包含 # libGLES_mesa.so # Mesa/Gallium for VirGL # libGLES_swift.so # SwiftShader 软件实现 # libGLES_virtio.so # VirtIO-GPU 专用驱动 # libGLES_vmware.so # VMware SVGA II关键点在于property 的值此时还未生成但库的选择逻辑已隐含了后续 property 的内容。例如若libGLES_virtio.so被选中则ro.hardware.graphics几乎必然设为virtio。2.2 第二步EGLDisplay 创建与设备匹配选定.so后eglGetDisplay()调用该库的eglGetPlatformDisplay()。以libGLES_virtio.so为例它会打开/dev/dri/renderD128VirGL DRM 设备节点读取 PCI 设备 IDlspci | grep VGA在 guest 中应显示Virtio GPU验证virgl_renderer_init()是否成功调用virgl_renderer_get_cap()获取支持特性若此步失败如设备节点权限不足、VirGL 内核模块未加载则 fallback 到libGLES_swift.so最终ro.hardware.graphics将设为swiftshader。2.3 第三步HAL 层介入与 hwcomposer 初始化EGL Display 创建成功后SurfaceFlinger启动时会加载hwcomposerHAL/vendor/lib/hw/hwcomposer.*.so。这是 property 生成的关键触发点。HAL 实现会查询EGLDisplay的 vendor stringeglQueryString(display, EGL_VENDOR)调用drmOpen()或virgl_renderer_get_cap()获取 GPU 能力集根据能力决定是否启用硬件合成HWC、是否支持 Vulkan此时HAL 主动调用property_set()写入核心 propertyProperty典型值生成逻辑ro.hardware.graphicsvirtio,vmware,swiftshader来自 HAL 名称或 DRM 设备识别ro.hardware.eglmesa,angle,swiftshaderEGL 库 vendor 字符串debug.hwui.rendereropengl,vulkan,skia根据 EGL 支持的 API 和 SurfaceFlinger 配置注意debug.hwui.renderer的值不等于实际渲染器而是Skia渲染引擎的后端选择策略。例如opengl表示 Skia 使用GrGLBackendContext即使底层是 Vulkan只要 EGL 上下文是 OpenGL ES此处仍为opengl。2.4 第四步Gralloc 分配器注册与内存映射hwcomposer初始化后grallocHAL/vendor/lib/hw/gralloc.*.so被加载。它负责分配 GraphicBuffer 内存并通过ion或dma-buf与虚拟 GPU 共享。此步成功与否直接影响ro.hardware.grallocproperty 的生成// gralloc_virtio.cpp if (virgl_renderer_get_cap(VIRGL_CAP_DMABUF)) { property_set(ro.hardware.gralloc, virtio-dmabuf); } else { property_set(ro.hardware.gralloc, virtio-legacy); }若grallocfallback 到gralloc_sw.so软件分配器则ro.hardware.gralloc会是sw且所有 GraphicBuffer 将通过memcpy复制而非零拷贝共享——这是性能断崖式下降的典型标志。2.5 第五步SurfaceFlinger 合成策略决策SurfaceFlinger读取上述 property 后决定合成策略若ro.hardware.graphics virtio且ro.hardware.gralloc virtio-dmabuf则启用HWC2硬件合成Layer直接提交给hwcomposer若ro.hardware.graphics swiftshader则强制HWC_DISABLED所有合成由SkiaCPU 完成若debug.hwui.renderer vulkan则SurfaceFlinger创建VkInstance并尝试 Vulkan 合成需ro.hardware.vulkan存在此时ro.boot.vga若存在会被init读取并影响SurfaceFlinger启动参数但它是启动早期的静态配置不参与 runtime 决策。2.6 第六步应用层渲染上下文创建App 调用eglCreateContext()时libEGL.so根据ro.hardware.egl和debug.hwui.renderer选择 backendro.hardware.egl mesa→ 使用libMesaGLESv2.socontext 创建依赖virgl_renderer_context_create()ro.hardware.egl angle→ 使用libEGL_angle.so通过 D3D11 或 Vulkan backend在 Windows 虚拟机中常见若 context 创建失败如EGL_BAD_CONFIGSurfaceView将 fallback 到SoftwareRenderer此时debug.hwui.renderer可能被 runtime 覆盖为skia但ro.hardware.egl不变。2.7 第七步property 的最终固化与验证所有 HAL 初始化完成后init进程会执行一次 property dumpgetprop | grep -E (ro\.hardware|debug\.hwui) # 输出示例 # [ro.hardware.graphics]: [virtio] # [ro.hardware.egl]: [mesa] # [ro.hardware.gralloc]: [virtio-dmabuf] # [debug.hwui.renderer]: [opengl] # [ro.hardware.vulkan]: [virgl]这个输出就是“典型 property”的完整集合。验证它是否“典型”只需检查三点ro.hardware.graphics与实际虚拟 GPU 类型一致virtio/vmware/swiftshaderro.hardware.gralloc与ro.hardware.graphics匹配virtio-dmabuf对应virtiodebug.hwui.renderer与ro.hardware.egl兼容mesa通常对应openglangle可对应vulkan不满足任一条件都意味着 EGL 链路在某一步出现了降级或 misconfiguration。比如ro.hardware.graphicsvirtio但ro.hardware.grallocsw说明grallocHAL 加载失败必须检查/vendor/lib/hw/gralloc.virtio.so是否存在、ion驱动是否启用。我在调试某款基于 Android 12 的云手机平台时发现ro.hardware.graphicsvirtio但debug.hwui.rendererskia。追踪发现是libGLES_virtio.so的eglQueryString(display, EGL_VERSION)返回NULL导致SurfaceFlinger认为 EGL 不可用强制 fallback。根源是virgl_renderer_get_cap()返回了错误的VIRGL_CAP_EGL标志——这是 VirGL 0.8.3 的一个已知 bug升级到 0.9.0 后修复。property 是症状不是病因它精确地告诉你“哪里断了”但不会告诉你“为什么断”。3. 虚拟机环境下的三大典型 property 组合及其性能含义在真实项目中我们不会去“设置” property而是通过调整虚拟机配置、HAL 实现和启动参数让系统自动生成符合预期的 property 组合。根据我过去三年在云游戏、车机仿真、移动自动化测试三个场景的实操经验Android 虚拟机显示驱动 property 最常出现以下三种典型组合。每种组合背后都对应着明确的硬件抽象层级、性能特征和调试方向。3.1 组合一“纯虚拟 GPU”模式 ——ro.hardware.graphicsvirtio,ro.hardware.grallocvirtio-dmabuf,debug.hwui.rendereropengl这是 QEMU/KVM 虚拟机尤其是 AOSP x86 镜像最理想的配置代表完整的硬件加速流水线已打通。其技术栈如下App (OpenGL ES) → libGLES_virtio.so (EGL) → virgl_renderer (Userspace) → drm/virtio_gpu.ko (Kernel DRM) → Host Mesa/Vulkan Driver → Physical GPU性能表现3D 渲染帧率可达 host 的 70%~85%取决于 VirGL 版本和 host driverSurfaceFlinger合成延迟 16ms60fpsadb shell dumpsys SurfaceFlinger显示HWC: enabled,GPU: virtio关键验证点ls /dev/dri/必须存在renderD128VirGL DRM nodecat /proc/driver/virgl/version应输出0.9.0eglinfo | grep OpenGL renderer string应显示VirGL常见陷阱Host 端 Mesa 版本过低Ubuntu 18.04 自带 Mesa 18.0.5不支持 VirGL 0.8 的VIRGL_CAP_DMABUF导致grallocfallback 到sw。解决方案升级 host Mesa 至 20.2。QEMU 启动参数缺失必须包含-vga virtio-gpu-gl -display gtk,glon缺一不可。-display sdl会禁用 GL-vga std则无 VirGL。SELinux 策略拦截avc: denied { ioctl } for path/dev/dri/renderD128是典型报错需添加allow system_file device_file:chr_file ioctl;规则。实操心得在 CI/CD 流水线中我用一条 shell 命令自动验证该组合是否生效adb shell getprop ro.hardware.graphics ro.hardware.gralloc debug.hwui.renderer | grep -q virtio.*virtio-dmabuf.*opengl echo ✅ VirGL Full Stack OK || echo ❌ Fallback Detected3.2 组合二“半虚拟化”模式 ——ro.hardware.graphicsvmware,ro.hardware.grallocsw,debug.hwui.rendererskia这是 VMware Workstation/Player 用户最常见的组合尤其在未安装 VMware Tools 或 Tools 版本陈旧时。它表示 GPU 3D 加速已启用vmware但内存共享未打通所有 GraphicBuffer 需 CPU 拷贝。技术栈App (OpenGL ES) → libGLES_vmware.so (EGL) → vmwgfx.ko (Kernel DRM) → VMware SVGA II Device → Host OpenGL Driver但gralloc无法访问vmwgfx的 DMA-BUF故 fallback 到gralloc_sw.so。性能表现2D UI 流畅Skia CPU 渲染优化好3D 游戏严重卡顿memcpy占用 40% CPUdumpsys SurfaceFlinger显示HWC: disabled,GPU: vmware,Composition: CPU关键验证点ls /dev/dri/存在card0vmwgfx DRM node但renderD128缺失dmesg | grep vmwgfx应有vmwgfx: Using dma-buf若无则 DMA-BUF 未启用getprop ro.hardware.gralloc确认为sw根治方案升级 VMware Tools必须使用 v12.5.0旧版 Tools 不提供libgralloc_vmware.so启用 3D 加速VM Settings → Display → Accelerate 3D graphics ✅修改 VMX 配置添加mks.enable3d TRUE和svga.guestBackedPrimaryAware TRUE我在为某金融 App 做自动化兼容性测试时发现其 WebView 在 VMware 中白屏。查logcat发现Skia渲染失败最终定位到gralloc_sw.so的alloc()函数因内存对齐问题返回ENOMEM。解决方案不是改 property而是强制gralloc使用vmware实现将libgralloc_vmware.so复制到/vendor/lib/hw/并重命名为gralloc.vmware.so再修改init.rc中grallocservice 的class main为class hal确保它优先于gralloc_sw.so加载。3.3 组合三“纯软件渲染”模式 ——ro.hardware.graphicsswiftshader,ro.hardware.grallocsw,debug.hwui.rendererskia这是所有虚拟化方案的兜底选项当硬件加速完全不可用时启用。SwiftShader是 Google 开源的 CPU-based OpenGL ES/Vulkan 实现性能远超libGLES_android.so的软件回退。技术栈App (OpenGL ES) → libGLES_swift.so (EGL) → SwiftShader (LLVM JIT) → CPU SIMD (AVX2/NEON)性能表现2D UI 基本流畅Skia SwiftShader 优化3D 渲染帧率 10fps复杂场景dumpsys SurfaceFlinger显示HWC: disabled,GPU: swiftshader,Composition: CPU触发条件libGLES_virtio.so或libGLES_vmware.so加载失败.so文件缺失或 ABI 不匹配DRM 设备节点权限不足chmod 666 /dev/dri/*可临时解决virgl_renderer_init()返回VIRGL_ERRORhost GPU 驱动不支持优化技巧强制 SwiftShader 使用 AVX2在init.rc中添加setprop debug.swiftshader.avx2 1可提升 30% 性能禁用 Vulkan 回退setprop debug.hwui.renderer opengl避免Skia尝试 Vulkan 导致崩溃调整 Skia 缓存setprop debug.skia.cacheSize 104857600100MB减少 CPU 渲染抖动重要提醒swiftshader模式下ro.hardware.graphicsswiftshader是唯一可靠 indicator。若看到ro.hardware.graphicsandroid说明libGLES_android.so在工作性能比swiftshader更差应立即排查为何未 fallback 到 SwiftShader通常是libGLES_swift.so未放入/vendor/lib/egl/。这三种组合不是随机出现的而是虚拟机配置、host driver、guest HAL 三方博弈的结果。property 就像心电图它不告诉你病灶在哪但波形异常的精确位置就是你该切开检查的解剖坐标。我的习惯是拿到一台新虚拟机第一件事就是getprop | grep -E (ro\.hardware|debug\.hwui)5 秒内判断出当前处于哪种模式再决定下一步是调 host、改 VMX还是换 HAL。4. 实战排错从 property 异常到定位 VirGL DRM 设备节点权限问题的完整链路property 的价值在于它能把模糊的“显示异常”转化为可追溯的“链路断点”。下面我复盘一个真实案例某客户部署的 Android 12 云手机集群50% 节点出现黑屏或 UI 卡死getprop显示ro.hardware.graphicsvirtio但dumpsys SurfaceFlinger显示HWC: disabled。表面看 property 正常实则暗藏玄机。整个排查过程就是一次对 property 信号的深度解码。4.1 第一步确认 property 与现象的矛盾点客户提供的日志片段[ 123.456] I/SurfaceFlinger( 123): SurfaceFlinger is starting [ 123.457] I/HWComposer( 123): HWC: disabled, reason: no valid display [ 123.458] I/GraphicBufferAllocator( 123): Allocated buffer with handle 0x7f8a123456 [ 123.459] E/GrallocModule( 123): Failed to map buffer: Invalid argumentro.hardware.graphicsvirtio表明hwcomposer.virtio.so已加载但HWC: disabled且gralloc报错Invalid argument矛盾点在于property 声明硬件可用但 HAL 调用失败。这说明问题不在 property 生成环节而在后续的设备访问环节。4.2 第二步聚焦 gralloc 的失败日志提取关键线索Failed to map buffer: Invalid argument是gralloc_virtio.cpp中ion_map()或dma_buf_map()的返回值。Invalid argumenterrno22在 Linux DRM 场景下通常指向ioctl(fd, DRM_IOCTL_VIRTIO_GPU_MAP)的参数非法dma_buf_fd无效fd 已关闭或未正确传递ionheap type 不匹配ION_HEAP_TYPE_SYSTEMvsION_HEAP_TYPE_DMA我立刻在故障节点执行adb shell # 查看 ion 设备 ls -l /dev/ion # crw------- 1 root root 233, 0 Jan 1 00:00 /dev/ion # 检查 drm 设备 ls -l /dev/dri/ # crw-rw---- 1 root render 226, 0 Jan 1 00:00 card0 # crw-rw---- 1 root render 226, 128 Jan 1 00:00 renderD128 # 测试 drm 设备可读性 cat /dev/dri/renderD128 /dev/null 21 echo OK || echo FAIL # FAILcat /dev/dri/renderD128失败这直接解释了gralloc的Invalid argumentgralloc尝试open(/dev/dri/renderD128, O_RDWR)成功但在ioctl(fd, DRM_IOCTL_VIRTIO_GPU_MAP)时内核拒绝了请求——因为renderD128节点虽存在但无读写权限。4.3 第三步对比正常与异常节点的 udev 规则正常节点ls -l /dev/dri/renderD128 # crw-rw---- 1 root render 226, 128 Jan 1 00:00 /dev/dri/renderD128异常节点ls -l /dev/dri/renderD128 # crw------- 1 root root 226, 128 Jan 1 00:00 /dev/dri/renderD128权限差异明显renderD128属于root:root而非root:render。gralloc进程以system用户运行属于render组因此无权访问。问题根源浮出水面udev 规则未生效。检查/lib/udev/rules.d/60-virtio-gpu.rules# 正常规则 KERNELrenderD[0-9]*, GROUPrender, MODE0660 # 异常节点缺失此行或被其他规则覆盖进一步发现客户使用了定制 initramfs其中udev服务启动晚于drm设备创建导致 udev 规则未及时应用。renderD128节点由 kernel 创建时继承了默认root:root 0600权限后续 udev 未触发。4.4 第四步验证假设并实施热修复临时修复验证用adb shell su -c chmod 660 /dev/dri/renderD128 chgrp render /dev/dri/renderD128 # 然后重启 surfaceflinger adb shell su -c killall surfaceflinger执行后dumpsys SurfaceFlinger立即显示HWC: enabledUI 恢复流畅。getprop未变但行为已修正——这再次证明property 是静态快照而系统行为是动态过程快照正确不代表过程无阻。4.5 第五步根治方案修改 initramfs 中的 udev 启动顺序根本解决需修改 initramfs解包 initramfszcat /boot/initrd.img-5.10.0 | cpio -idmv编辑etc/udev/rules.d/60-virtio-gpu.rules确保包含SUBSYSTEMdrm, KERNELrenderD[0-9]*, GROUPrender, MODE0660添加 udev 启动依赖在init脚本中确保udev --daemon在drm模块加载后执行重新打包find . | cpio -o -H newc | gzip /boot/initrd.img-fixed关键经验在云环境批量部署时我编写了一个 pre-boot check script专门验证/dev/dri/renderD128的权限和 group。它比等待SurfaceFlinger启动后再查日志提前 30 秒定位问题。property 是诊断的起点不是终点真正的排错永远始于对 property 背后那个字节流的敬畏。这个案例的启示在于ro.hardware.graphicsvirtio这个 property像一张入场券它保证你进入了硬件加速的大门但门内的走廊、楼梯、房间每一处都需要独立验证。忽视任何一环都会导致“门票有效但目的地 unreachable”。5. HAL 实现层如何为自定义虚拟 GPU 编写 property 生成逻辑如果你正在开发一款新的 Android 虚拟机比如基于 Rust 的轻量级 hypervisor或者需要为现有虚拟 GPU如自研的mygpu.ko适配 Android HAL那么 property 的生成逻辑就必须由你亲手编写。这不是简单的property_set()调用而是一套与 Android 图形栈深度耦合的契约。下面我以hwcomposer.mygpu.so为例详解 HAL 层 property 生成的完整实现要点。5.1 HAL 接口版本与 property 生成时机Android HAL 有严格版本约束。hwcomposerHAL 2.3Android 10要求在HWC2::Device::createVirtualDisplay()或HWC2::Device::getCapabilities()之后立即生成 property。不能在HWC2::Device::init()中写入因为此时property_service可能未 ready也不能在HWC2::Device::acceptDisplayChanges()中写入因为太晚SurfaceFlinger已完成初始化。标准时机是HWC2::Device::getCapabilities()返回前// mygpu_hwcomposer.cpp int MyGpuDevice::getCapabilities(uint32_t* outCount, int32_t* outCapabilities) { // 1. 检测设备能力 bool has_vulkan detect_vulkan_support(); bool has_dmabuf detect_dmabuf_support(); // 2. 生成 property —— 关键必须在 return 前 property_set(ro.hardware.graphics, mygpu); property_set(ro.hardware.egl, has_vulkan ? vulkan : mesa); property_set(ro.hardware.gralloc, has_dmabuf ? mygpu-dmabuf : sw); if (has_vulkan) { property_set(ro.hardware.vulkan, mygpu); property_set(debug.hwui.renderer, vulkan); } else { property_set(debug.hwui.renderer, opengl); } // 3. 设置 capability 数组 *outCount 0; if (has_vulkan) { outCapabilities[(*outCount)] HWC2_CAPABILITY_VULKAN; } if (has_dmabuf) { outCapabilities[(*outCount)] HWC2_CAPABILITY_DRM; } return 0; }注意property_set()是libcutils提供的同步函数无需担心 race condition。但必须确保libcutils已链接LOCAL_SHARED_LIBRARIES libcutils。5.2 property 命名规范与 Android 兼容性Android 系统对 property 命名有隐式约定违反会导致SurfaceFlinger误判ro.hardware.graphics必须是小写字母数字长度 ≤ 16 字符。mygpu-pro会被截断为mygpu-pro但mygpu_with_underscore会因property_set()的PROP_NAME_MAX32限制而失败。ro.hardware.egl值必须与libEGL.so的 vendor string 一致。若你的libGLES_mygpu.so返回eglQueryString(EGL_VENDOR)为MyGPU Inc.则此处应设为mygpu小写化否则SurfaceFlinger无法匹配。debug.hwui.renderer仅接受opengl,vulkan,skia。设为mygpu会导致Skia初始化失败。最佳实践是property 的值必须与你提供的.so文件名前缀严格一致。例如libGLES_mygpu.so→ro.hardware.eglmygpugralloc.mygpu.so→ro.hardware.grallocmygpu-dmabufhwcomposer.mygpu.so→ro.hardware.graphicsmygpu这样SurfaceFlinger的HwcomposerFactory才能通过getprop动态加载对应 HAL。5.3 安全边界property_set 的权限与 SELinux 策略property_set()调用受 SELinux 严格管控。在sepolicy中必须为你的 HAL 进程域添加规则# mygpu.te type mygpu_hwcomposer, domain; type mygpu_hwcomposer_exec, exec_type, file_type; # 允许写入 ro.* property allow mygpu_hwcomposer property_socket:sock_file write; allow mygpu_hwcomposer system_file:file { read write }; allow mygpu_hwcomposer property_service:property_service set; # 允许访问 drm 设备 allow mygpu_hwcomposer drm_device:chr_file { open read write ioctl }; allow mygpu_hwcomposer drm_device:dir search;若缺少allow mygpu_hwcomposer property_service:property_service set;property_set()将静默失败返回 0 但实际未写入getprop查不到你的 property。这是最隐蔽的坑之一——日志无报错但 property 缺失。5.4 调试技巧在 HAL 中注入 property 日志HAL 层调试困难建议在property_set()后立即打印日志__android_log_print(ANDROID_LOG_INFO, MyGpuHAL, Set property: ro.hardware.graphics%s, ro.hardware.egl%s, debug.hwui.renderer%s, mygpu, has_vulkan ? vulkan : mesa, has_vulkan ? vulkan : opengl);然后用adb logcat -b main -b system | grep MyGpuHAL实时监控。若日志出现但getprop查不到100% 是 SELinux 问题若日志都不出现则 HAL 未执行到该分支。5.5 进阶动态 property 与 runtime 调整某些场景需要 runtime 修改 property例如切换 Vulkan/OpenGL 模式。Android 不允许直接setprop但可通过HWC2::Device::setPowerMode()触发// 在 setPowerMode() 中 if (mode HWC2_POWER_MODE_ON) { // 重置 renderer if (use_vulkan_) { property_set(debug.hwui.renderer, vulkan); } else { property_set(debug.hwui.renderer, opengl); } }SurfaceFlinger会监听debug.hwui.renderer
返回列表