问题背景:开发者手机OHOS 5.0版本切换
平台:展锐7885

1. 问题汇总

版本变更,新增HDI接口
版本变更,graphic架构变化
ld-musl-namespace-aarch64.ini文件相关patch打错位置
so打开失败问题

  • libsync.z.so依赖冲突
  • 沙盒配置问题,导致so打开失败

render_service相关crash,导致系统无法进入launcher

2. 版本变更,新增HDI接口

7885显示功能,调用了OHOS的HDI接口。如:gralloc内存分配、gfx硬件合成、drm驱动等。
由于展锐相关部分代码闭源,所以目前显示相关HDI接口适配分为了两部分:

2.1 sig工程部分

sig部分是7885开源部分,详细介绍如下:

sig工程display目录结构
    device/soc/spreadtrum/common/hardware/display/
    ├── BUILD.gn
    ├── include
    └── src
        ├── display_device
        │   ├── composer
        │   ├── core
        │   ├── drm
        │   ├── fbdev
        │   └── vsync
        ├── display_layer_video
        └── utils

1. display_device:这个目录包含了与显示设备直接相关的代码。它进一步分为几个子目录,分别处理不同的显示后端或技术。
composer:处理图像合成的代码,包括硬件加速的图像合成(如HDI Composer)和图形合成(如HDI GFX Composition)。
core:显示系统的核心功能,如设备接口(HDI Device Interface)、显示(HDI Display)、图层(HDI Layer)和会话(HDI Session)管理等。
drm:处理与Direct Rendering Manager(DRM)相关的显示功能,包括 Connector、CRTC、Encoder和 Plane等。
fbdev:处理基于帧缓冲设备(Framebuffer Device)的显示功能。
vsync:处理垂直同步(VSync)相关的功能,如软件模拟的VSync(Soft VSync)。
2. display_layer_video:这个目录包含了处理视频图层相关的代码,涉及到视频解码后的图层管理或显示。
3. utils:这个目录包含了工具类或辅助类的代码,如显示适配器(Display Adapter),用于加载显示模块的辅助函数(Display Module Loader)。

2.2 laval工程部分

laval部分是7885闭源部分,详细介绍如下:

laval工程display目录结构
    device/platform/soc/common/hardware/display/src/
    ├── display_gfx
    │   ├── display_gfx.cpp
    │   └── gsp
    ├── display_gralloc
    │   ├── allocator.cpp
    │   ├── allocator.h
    │   ├── allocator_manager.cpp
    │   ├── allocator_manager.h
    │   ├── display_buffer_vdi_impl.cpp
    │   ├── display_buffer_vdi_impl.h
    │   ├── display_gralloc.cpp
    │   ├── dmabufferheap_allocator.cpp
    │   ├── dmabufferheap_allocator.h
    │   ├── drm_allocator.cpp
    │   ├── drm_allocator.h
    │   ├── framebuffer_allocator.cpp
    │   ├── framebuffer_allocator.h
    │   ├── hisilicon_drm.h
    │   ├── sprd_allocator.cpp
    │   └── sprd_allocator.h
    └── utils
        ├── display_adapter.cpp
        ├── display_adapter.h
        └── display_module_loader.h

1. display_gfx:实现了图形显示的核心功能,如图像渲染、图层合成等。
gsp:这个子目录包含了与图形处理单元(GPU)或图形子系统(GSP)相关的代码。
2. display_gralloc:这个目录包含针对Spreadtrum平台的图形内存分配器(gralloc)相关的代码。
allocator_manager.cpp 和 allocator_manager.h:管理不同内存分配器的代码,负责根据需求选择合适的分配器。
display_buffer_vdi_impl.cpp 和 display_buffer_vdi_impl.h:实现了显示缓冲区的虚拟设备接口(VDI)实现。
display_gralloc.cpp:是display_gralloc模块的主文件,负责初始化和管理内存分配器。
dmabufferheap_allocator.cpp 和 dmabufferheap_allocator.h:实现了基于DMA缓冲区的堆内存分配器。
drm_allocator.cpp 和 drm_allocator.h:实现了基于Direct Rendering Manager(DRM)的内存分配器。
framebuffer_allocator.cpp 和 framebuffer_allocator.h:实现了基于帧缓冲区的内存分配器。
sprd_allocator.cpp 和 sprd_allocator.h:实现了针对Spreadtrum平台的内存分配器。
3. utils:这个目录包含了工具类或辅助类的代码。
display_adapter.cpp 和 display_adapter.h:实现了显示适配器,用于适配不同的显示设备或后端。
display_module_loader.h:包含了用于加载显示系统模块的辅助函数声明。

2.3 对比社区HDI接口

社区驱动代码新增DisplayBufferVdiImpl::GetImageLayout接口,目前看没有特殊功能,所以按照社区rk3568作为空实现适配。

https://gitee.com/openharmony/drivers_peripheral/issues/I9F8YF

3. 版本变更,graphic架构变化

3.1 变化1 部分graphic_2d组件变更为graphic_surface组件

4.1版本buffer_handle属于graphic_2d组件,5.0变更为graphic_surface组件的一部分。

修改点1:修改graphic_2d的依赖为graphic_surface。
common/hardware/display/BUILD.gn

diff --git a/common/hardware/display/BUILD.gn b/common/hardware/display/BUILD.gn
index 9b828dd911918ad062a440eb363275a7d7d2b3b9..7cedc4f24754a56a3f702cb49891b90fe5e023e6 100644
--- a/common/hardware/display/BUILD.gn
+++ b/common/hardware/display/BUILD.gn
@@ -50,7 +50,7 @@ ohos_shared_library("libdisplay_composer_vdi_impl") {
     "c_utils:utils",
     "drivers_interface_display:display_buffer_idl_headers",
     "drivers_interface_display:display_composer_idl_headers",
-    "graphic_2d:buffer_handle",
+    "graphic_surface:buffer_handle",
     "hilog:libhilog",
     "ipc:ipc_single",
   ]

修改点2:在使用buffer_handle的bundle.json文件中增加graphic_surface组件。
common/bundle.json

diff --git a/common/bundle.json b/common/bundle.json
index 91df889a3703fcc3e8e222ad88e7db4d05eb6028..31d120a99a7fa2f82f00b00c17fcdfb1ce4ecba6 100644
--- a/common/bundle.json
+++ b/common/bundle.json
@@ -23,6 +23,7 @@
             "components": [                                                   
               "hilog",
               "graphic_2d",
+              "graphic_surface",
               "c_utils",
               "hitrace",
               "drivers_interface_location_gnss",
@@ -58,6 +59,7 @@
         },
         "build": {                                                              
                "sub_component": [                                         
+                "//device/soc/spreadtrum/common/hardware/display:display_composer_model",
                 "//device/soc/spreadtrum/common/startup/reboot_loader:rebootloader"
             ],
             "inner_api": [

3.2 变化2 native_window组件结构体变更

diff --git a/soc/common/hardware/aosp/frameworks/native/libs/nativewindow/ANativeWindow.cpp b/soc/common/hardware/aosp/frameworks/native/libs/nativewindow/ANativeWindow.cpp
index 306a1af013f9dcfc39756f341193ea7ef81f1d3c..8129723b4946ced1302485c4e94e3a1e4a2a15f3 100644
--- a/soc/common/hardware/aosp/frameworks/native/libs/nativewindow/ANativeWindow.cpp
+++ b/soc/common/hardware/aosp/frameworks/native/libs/nativewindow/ANativeWindow.cpp
@@ -108,24 +108,25 @@ int32_t ANativeWindow_getHeight(OHNativeWindow* window) {
 
 int32_t ANativeWindow_getFormat(OHNativeWindow* window) {
     // return query(window, NATIVE_WINDOW_FORMAT);
+    auto config = window->surface->GetWindowConfig();
     int32_t format = PIXEL_FMT_RGBA_8888;
     // change window android_format to oh_format
-    const int32_t windowFormat = window->config.format;
+    const int32_t windowFormat = config->format;
     switch (windowFormat) {
         case HAL_PIXEL_FORMAT_RGBA_8888:
-            window->config.format = PIXEL_FMT_RGBA_8888;
+            config->format = PIXEL_FMT_RGBA_8888;
             break;
         case HAL_PIXEL_FORMAT_RGBX_8888:
-            window->config.format = PIXEL_FMT_RGBX_8888;
+            config->format = PIXEL_FMT_RGBX_8888;
             break;
         case HAL_PIXEL_FORMAT_RGB_888:
-            window->config.format = PIXEL_FMT_RGB_888;
+            config->format = PIXEL_FMT_RGB_888;
             break;
         case HAL_PIXEL_FORMAT_RGB_565:
-            window->config.format = PIXEL_FMT_RGB_565;
+            config->format = PIXEL_FMT_RGB_565;
             break;
         case HAL_PIXEL_FORMAT_YCRCB_420_SP:
-            window->config.format = PIXEL_FMT_YCRCB_420_SP;
+            config->format = PIXEL_FMT_YCRCB_420_SP;
             break;
         default:
             break;

4. ld-musl-namespace-aarch64.ini文件相关patch打错位置

ld-musl-namespace-aarch64.ini是预置的动态链接器配置文件,负责在程序运行时加载共享库(shared library)并解析它们的符号引用,以便程序能够正常执行。

动态链接器提供了一种基于配置和API的命名空间机制,其设计的主要目的是为了在进程中做native库资源访问的管控,以达到安全隔离的目的。例如系统native库允许加载系统目录(/system/lib64;/vendor/lib64等)下的native库,但是普通应用native库仅允许加载普通应用native库和ndk库,而不允许直接加载系统native库。

共享库可以被隔离在不同的命名空间中,这样即使库名相同但符号不同也不会发生冲突。另一方面,命名空间机制提供了灵活性,使得一些共享库可以由一个链接器命名空间导出并由另一个链接器命名空间使用。

4.1 文件内容分析

[section.dir.map]
    acquiescence = /system/bin:/vendor/bin:/data/local/tmp

[acquiescence]
    added.nslist = ndk
    namespace.ndk.lib.paths = /system/lib64/ndk
    namespace.default.lib.paths = /system/lib64:/vendor/lib64:/vendor/lib64/chipsetsdk:/vendor/lib64/chipset-sdk:/system/lib64/chipset-pub-sdk:/system/lib64/chipset-sdk:/system/lib64/platformsdk:/system/lib64/module:/system/lib64/module/data:/system/lib64/module/multimedia:/system/lib64/module/security:/vendor/lib64/hw:/lib64/platformsdk:/lib64/chipset-pub-sdk:/sys_prod/lib64:/system/lib:/lib:/usr/local/lib:/usr/lib:/lib64:/vendor/modem/modem_vendor/lib64:/vendor/soc_platform/lib64:/vendor/soc_platform/lib64/chipsetsdk:/vendor/soc_platform/lib64/hw
    namespace.default.asan.lib.paths = /system/lib64:/system/lib64/module:/vendor/lib64:/vendor/lib64/chipsetsdk:/vendor/lib64/chipset-sdk:/system/lib64/module/data:/system/lib64/module/multimedia:/system/lib64/module/security:/system/lib:/system/lib/module:/system/lib/module/data:/system/lib/module/multimedia:/lib64:/lib:/usr/local/lib:/usr/lib:/vendor/lib64/hw:/lib64/platformsdk:/lib64/chipset-pub-sdk:/sys_prod/lib64:/vendor/soc_platform/lib64:/vendor/soc_platform/lib64/chipsetsdk:/vendor/soc_platform/lib64/hw
    namespace.default.inherits = ndk
    namespace.default.inherit.ndk.shared.libs = allow_all_shared_libs
    namespace.ndk.inherits = default
    namespace.ndk.inherit.default.shared.libs = allow_all_shared_libs

section.dir.map部分:
acquiescence:指定了一系列用于查找可执行文件的默认路径。

acquiescence部分:
added.nslist:指定了要添加的命名空间列表。
namespace.ndk.lib.paths:定义了ndk命名空间下动态链接库的搜索路径。
namespace.default.lib.paths:定义了默认命名空间下动态链接库的搜索路径。
namespace.default.asan.lib.paths:定义了在使用ASan时的默认命名空间下的动态链接库搜索路径。
namespace.default.inherits:指定默认命名空间继承自哪个命名空间。
namespace.default.inherit.ndk.shared.libs:定义了默认命名空间从ndk命名空间继承时,对于共享库的策略,这里是allow_all_shared_libs,即允许所有共享库。
namespace.ndk.inherits:指定ndk命名空间继承自哪个命名空间,这里是default。
namespace.ndk.inherit.default.shared.libs:定义了ndk命名空间从默认命名空间继承时,对于共享库的策略,同样是allow_all_shared_libs。

动态链接器无论是在加载编译依赖中指定的共享库,还是调用dlopen加载指定的共享库,都需要关联到具体的namespace。

4.2 问题分析

4.1版本中,musl相关的patch是针对/third_party/musl/porting/linux/user/config路径下的ld-musl-namespace-aarch64.ini文件生成的。

定位发现5.0镜像烧录后,板子上的ld-musl-namespace-aarch64.ini文件并没有做出对应修改,也就是说修改未生效。

经过搜索对比发现,5.0沿用了之前4.1版本的patch修改,但是5.0版本使用的配置文件发生了变化,5.0使用的是/third_party/musl/config下的ld-musl-namespace-aarch64.ini文件,所以4.1版本的修改在开发板上并未生效。

5. so打开失败问题

生成5.0镜像烧录后,通过hilog分析发现,出现so文件找不到符号或者找不到打开失败问题。

5.1 libsync.z.so依赖冲突

查看log发现,会出现如下打印,"......symbol not found ...... s=sync_wait......"

img

镜像烧录后发现,板子上有两个同名libsync.z.so文件,一个是系统生成,一个是芯片原厂生成。其中系统生成的库中没有"sync_wait"符号,对比结果如下:

sig工程sync库结果

img

laval工程sync库结果

img

结论:显示相关组件调用sync_wait,但是遇到同名so库的时候链接了系统提供的libsync.z.so库,导致找不到符号。应该链接到厂商提供的libsync.z.so库。

解决方法:修改相关的脚本,生成不同名的sync库,同时修改代码中对sync.h头文件的引用,由<sync/sync.h>改为"sync/sync.h",也就是由原本去系统下查找头文件改为去当前目录查找。其他对冲突so有依赖的库,也需要修改依赖、重新生成。

5.2 沙盒配置问题,导致so打开失败

‌沙盒机制‌是一种安全机制,用于为运行中的程序提供一个隔离环境。它通常用于执行那些来源不可信、具破坏力或无法判定程序意图的程序。沙盒机制通过限制程序对系统资源的访问,防止恶意代码对系统造成损害。例如,恶意软件在沙盒环境中运行,其影响被限制在沙盒内,不会影响到系统的核心部分。

沙盒机制通过限制执行指令来防止恶意行为。例如,限制跳转指令的使用,防止恶意代码随意跳转到系统内存中的任意位置;限制应用程序的API接口,控制应用程序可能进行的操作,尤其是那些可能对系统造成危害的操作(如直接访问文件系统或创建新的进程);还可以控制应用程序对文件系统、网络接口或其他资源的访问。

5.2.1 沙盒管理

在init里面创建系统组件沙盒和芯片组件沙盒,native服务根据功能进入system沙盒或者chipset沙盒。在system-sandbox.json、chipset-sandbox.json等配置文件中设置沙盒组件中mount bind 的目录或文件,实现沙盒组件通过mount属性进行隔离。同时,提供了一种沙盒调试工具,当需要在沙盒内验证或者进行沙盒相关开发时,方便对需求进行调试、验证、完善。

参数说明:

表1 沙盒配置文件字段解释

JSON前缀解释
sandbox-root沙盒的根目录
mount-bind-pathsmount一个目录
mount-bind-filesmount一个文件
src-path需要mount的目录/文件路径
sandbox-path沙盒里面需要挂载至的目录/文件
sandbox-flagsmount的挂载标志位, 缺省"bind rec"标志位
ignore 是否忽略mount失败,设置为1则忽略失败,继续往下执行
target-name需要link的目录
link-name沙盒内link后的目录

表2 沙盒配置文件解释

沙盒配置文件解释
chipset-sandbox64.json64位系统的芯片沙盒配置文件
chipset-sandbox.json32位系统的芯片沙盒配置文件
system-sandbox64.json64位系统的系统沙盒配置文件
system-sandbox.json32位系统的系统沙盒配置文件

5.2.2 问题分析

沙盒问题关键日志:

08-05 17:27:29.302   488   488 E C02500/driver_loader_full: get driver entry failed, /vendor/lib/libcamera_host_service_1.0.z.so load fail, Error loading shared library libdisplay_buffer_proxy_1.0.z.so: No such file or directory (needed by /system/lib/chipset-pub-sdk/libdisplay_buffer_hdi_impl.z.so)
08-05 17:27:29.303   488   488 E C02500/devhost_service_full: DevHostServiceAddDevice failed and return -207
08-05 17:27:29.305   488   488 E C02500/devhost_service_stub: Dis patch failed, add service failed and ret is -207
08-05 17:27:29.307   488   488 I C02500/devhost_service_stub: add device 0x7000201
08-05 17:27:29.308   488   488 E C02500/driver_loader_full: /vendor/lib/libhdi_media_layer_service.z.so no valid, errno:2

沙盒问题可以通过在chipset-sandbox64.json、system-sandbox64.json这些文件中添加对应路径解决。

参考链接:https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/subsystems/subsys-boot-init-sandbox.md

6. render_service相关crash,导致系统无法进入launcher

hgm空指针,使得获取版本失败,造成RS出现crash,目前master分支和5.0.1Release分支已经对空指针问题进行修复。

具体内容详见:https://laval.csdn.net/672cb19b522b003a546572cf.html

Logo

社区规范:仅讨论OpenHarmony相关问题。

更多推荐