本文旨在帮助开发者完成底座升级,文中主要以OpenHarmony 3.2 release 升级至OpenHarmony 4.0 release为模板描述。
在准备阶段,需要完整收集所有的定制化修改,明确修改人;并且要将模块责任田细化明确,确保每个模块都有相应责任人。
在切换阶段,以编译构建与屏幕点亮的工作量最大,难度最高。
小版本(如4.0 beta切换至4.0 release)切换较为简单:可以在直接拉取社区4.0 release分支后,将在4.0 beta上的定制化修改一次性合入;解决合入冲突并且编译即可。
大版本(如3.2 release切换至4.0 release)切换相对复杂:需要在拉取社区4.0 release分之后,完成与点亮相关的几个关键仓库的修改与适配(kernel、device_xxx、vendor_xxx),并结合至新分支其他子系统,整编通过,实现点亮。所有其他子系统的定制化修改,需要再点亮完成后再进行。
与常规项目类似,即开发自验证与测试验证,确保升级后的各功能质量。
整体编译产品,执行编译命令后,处理编译报错问题。易现的编译问题:
1、未适配的产品模块容易出现编译报错。
2、新增的白名单规则导致的编译报错。
3、更严格的模块依赖规范导致的编译报错。
4、产品组件编译后并未安装到out下的产品目录导致运行错误。
5、更严格的语法检查规范容易导致语法检查错误。
在碰到编译中暂时无法解决的错误,如非产品点亮相关,可暂时屏蔽改模块的编译。
1、屏蔽产品组件,修改BUILD.gn文件,例如从group属性中删除某组件
文件路径:vendor/[manufacturerName]/产品名/modules/BUILD.gn
文件路径:vendor/[manufacturerName]/产品名/modules/BUILD.gn
group("modules") {
deps = [
":[manufacturerName]_wlan_combo",
# ":sc2355_sdio_wlan",
":[manufacturerName]bt_tty",
":wifi_board_config",
":bt_configure_pskey",
":bt_configure_rf",
":bt_configure_pskey_aa",
":bt_configure_rf_aa",
":wcnmodem",
# ":gnssmodem",
":build_modules",
# "wcn/bluetooth/hal:libbt_vendor", //编译报错,从编译中屏蔽蓝牙模块
":vpu",
":nvt_nt36xxx_spi_ts",
":novatek_ts_fw",
":mali_kbase",
2、屏蔽产品部件,从ohos.build中删除产品部件,也可能需要在config.json中关联的productdefine中的产品配置中删除关联配置
文件路径:vendor/[manufacturerName]/[productName]/ohos.build
{
"parts": {
"product_[productName]": {
"module_list": [
"//device/board/[manufacturerName]/[productName]:[productName]_group",
...
]
},
#################可从该文件中删除modem、radio部件等不影响亮屏的部件##################
# "modem":{
# "module_list": [
# "//vendor/[manufacturerName]/[productName]/modem:modem"
# ]
# },
# "radio":{
# "module_list": [
# "//vendor/[manufacturerName]/[productName]/telephony:radio"
# ]
# }
# },
#####################################################################################
"subsystem": "product_[productName]"
}
开发者手机项目中以前用的代码底座是3.2release的,当前要切换社区4.0release的代码位底座,切换后,新增的部分代码报了很多依赖错误,未改动的模块也报了很多依赖问题,如:
已确定不影响当前功能,没必要改,可待后续代码升级时自动修复;若需修改,可参考下面的修改方法
"soc_[manufacturerName]": {
"path": "device/soc/[manufacturerName]/[productName]/hardware",
"name": "soc_[productName]"
}
其中,soc_[manufacturerName]代表子系统名称,soc_[productName]代表部件名称
subsystem_name = "soc_[manufacturerName]"
part_name = "soc_[productName]"
{
"name": "@ohos/soc_[productName]",
"description": "device [productName] soc components",
"homePage": "",
"version": "3.1",
"license": "Apache License 2.0",
"repository": "",
"publishAs": "code-segment",
"segment": {
"destPath": "device/soc/[manufacturerName]/[productName]/hardware"
},
"dirs": {},
"scripts": {},
"component": {
"name": "soc_[productName]",
"subsystem": "soc_[manufacturerName]",
"syscap": [],
"adapted_system_type": [
"standard" //适配标准系统
],
"rom": "",
"ram": "",
"hisysevent_config": [],
"deps": {
"components": [ //各子组件依赖的库,依据gn文件中的external_deps,deps数据
"hilog",
"graphic_2d",
...
],
"third_party": [ //第三方依赖
"libdrm"
]
},
"build": {
"sub_component": [ //要参与编译的子组件,有的是group,group下可能再包含group,只需添加最上层grou即可
"//device/soc/[manufacturerName]/[productName]/hardware:hardware_group",
"//device/soc/[manufacturerName]/[productName]/hardware/aosp/hardware/interfaces/graphics/common:common-impl",
"//device/soc/[manufacturerName]/[productName]/hardware/omx_il:lib_omx"
],
"inner_kits": [ //如果其他部件有依赖本部件(soc_[productName])中的子组件,如动态库等,需要在此添加如下配置,外部才能引用;----注意:如果外部未引用,而在此添加本部件中的某组件,会导致此组件异常。
{
"header": {
"header_base": "//device/soc/[manufacturerName]/[productName]/hardware/aosp/system/memory/libdmabufheap/include",
"header_files": [
"BufferAllocator/BufferAllocator.h",
"BufferAllocator/BufferAllocatorWrapper.h",
"BufferAllocator/dmabufheap-defs.h"
]
},
"name": "//device/soc/[manufacturerName]/[productName]/hardware/aosp/system/memory/libdmabufheap:libaosp_dmabufheap"
},
...
{
"header": {
"header_base": "//device/soc/[manufacturerName]/[productName]/hardware/aosp/system/memory/libmemion/include",
"header_files": [
"C2UnisocDmaBuffer.h",
"dmaphyaddr-defs.h",
"VideoMemAllocator.h"
]
},
"name": "//device/soc/[manufacturerName]/[productName]/hardware/aosp/system/memory/libmemion:libmemion"
}
],
"test": []
}
}
}
{
"subsystem": "soc_[manufacturerName]", //子系统名
"parts": {
"soc_[productName]": { //部件名称
"module_list": [ //部件包含模块的gn目标
"//device/soc/[manufacturerName]/[productName]/hardware:hardware_group",
"//device/soc/[manufacturerName]/[productName]/hardware/omx_il:lib_omx"
]
}
}
}
修改//device/board/[manufacturerName]/[productName]/BUILD.gn,去掉group(“[productName]_group”)下deps中的//device/soc/[manufacturerName]/[productName]/hardware:hardware_group,此编译目标已在上一步定义过,此处不在需要;
添加//device/board/[manufacturerName]/[productName]/bundle.json部件定义文件(以前没这个文件,当前版本代码不添加这个文件的话,如gn文件中用到了init组件,不在bundle.json中deps下添加的话会报错)
{
"name": "@ohos/device_[productName]",
"description": "device board",
"version": 3.2,
"license": "Apache License 2.0",
"publishAs": "code-segment",
"segment": {
"destPath": "device/board/[manufacturerName]/[productName]"
},
"dirs": {},
"scripts": {},
"component": {
"name": "device_[productName]",
"subsystem": "device_[productName]",
"syscap": [],
"features": [],
"adapted_system_type": [ "standard" ],
"hisysevent_config": [],
"rom": "",
"ram": "",
"deps": {
"components": [
"init" //当前部件中gn文件用到了init组件
],
"third_party": []
},
"build": {
"sub_component": [
"//device/board/[manufacturerName]/[productName]:[productName]_group"
],
"test": []
}
}
}
根据上一步定义的子系统名和部件名device_[productName],修改本部件下各gn中的子系统名和部件名的相关配置
修改//device/board/[manufacturerName]/[productName]/ohos.build
{
"subsystem": "device_[productName]",
"parts": {
"device_[productName]": {
"module_list": [ // ${product_name} 当前就是[productName]
"//device/board/[manufacturerName]/${product_name}:[productName]_group" //改前为"//device/soc/[manufacturerName]/${product_name}/hardware:hardware_group",此模块在前几步已配置
],
"test_list": [
"//kernel/linux/build/test:linuxkerneltest"
]
}
}
}
修改//vendor/[manufacturerName]/[productName]/ohos.build, 去掉module_list下的"//device/board/[manufacturerName]/ p r o d u c t _ n a m e : {product\_name}: product_name:{product_name}_group", 因为前面已配置
添加//vendor/[manufacturerName]/[productName]/bundle.json,参考前面的方法添加即可
修改外部依赖错误(编译时这种错误依赖会报错,可以在发现报错时再改,可能是外部依赖放到了deps,也可能内部依赖放到了external_deps中),如下图所示:
修改部件名称错误,如把不属于此子系统的部件名,配置为了编译目标的部件名,也可在编译报错时再找到对应位置修改
修改//vendor/[manufacturerName]/[productName]/config.json,添加上诉步骤中新增的子系统,如:
{
"subsystem": "soc_[manufacturerName]",
"components": [
{
"component": "soc_[productName]",
"features": []
}
]
}
...
else:
raise Exception(_warning_info)
和check_part_deps()和check()函数中的抛异常语句:
...
else:
raise Exception(message)
在//build/templates/common/check_external_deps.py 中注释掉check_parts_deps() 函数中的两个抛异常语句
在//build/templates/common/check_part_subsystem_name.py 中注释掉check()函数第二个抛异常语句
此方法只能临时使用,后续其他模块的依赖错误或依赖不规范问题也是需要整改的
1、部件编译文件BUILD.gn中使用的外部依赖(非本部件中的组件)不可放在deps属性中,需移到external_deps中
external_deps = [
"c_utils:utils",
"graphic_chipsetsdk:surface",
"hdf_core:libhdf_host",
"hdf_core:libhdf_ipc_adapter",
"hdf_core:libhdf_utils",
"hdf_core:libhdi",
"hilog:libhilog",
"ipc:ipc_single",
]
2、device下产品部件配置文件bundle.json中需添加依赖的系统部件到components下
"component": {
"name": "device_[productName]",
"subsystem": "device_[productName]",
"syscap": [],
"features": [],
"adapted_system_type": [ "standard" ],
"hisysevent_config": [],
"rom": "",
"ram": "",
"deps": {
"components": [
"init",
"c_utils",
"hilog"
],
"third_party": []
},
"build": {
"sub_component": [
"//device/board/[manufacturerName]/[productName]:[productName]_group"
],
"test": []
}
}
}
产品仓模块编译后没有安装到对应的产品目录,需确认:
1、 确认模块编译文件BUILD.gn,将部件名和子系统名改为产品目录对应的部件名和子系统名
产品路径:device/board/产品名/camera/vdi_impl/v4l2/BUILD.gn
产品路径:device/board/产品名/camera/vdi_impl/v4l2/BUILD.gn
ohos_shared_library("camera_host_vdi_impl_1.0") {
...
install_enable = true
part_name = "device_laphone" //这里改为产品部件名
subsystem_name = "device_laphone" //这里改为产品子系统名
}
group("camera_board_vdi_impl") { //包含在group
deps = [
":camera_host_vdi_impl_1.0",
":chipset_build",
]
}
group("[productName]_group") {
deps = [
...
"//device/board/[manufacturerName]/[productName]/camera/vdi_impl/v4l2:camera_board_vdi_impl", //group被包含在另一个group
"//third_party/alsa-lib:libasound",
"//third_party/alsa-utils:alsa-utils",
]
if (is_standard_system) {
deps += [ "startup/reboot_loader:rebootloader" ]
}
}
2、确认vendor下产品的ohos.build的配置是否关联了该模块的编译
文件路径:device/board/[manufacturerName]/***/bundle.json
...
"component": {
"name": "device_[productName]",
"subsystem": "device_[productName]",
"syscap": [],
"features": [],
"adapted_system_type": [ "standard" ],
"hisysevent_config": [],
"rom": "",
"ram": "",
"deps": {
"components": [
"init",
"c_utils",
"hilog"
],
"third_party": []
},
"build": {
"sub_component": [
"//device/board/[manufacturerName]/[productName]:[productName]_group" //包含了上1、中的group
],
"test": []
}
}
}
vendor产品config.json中的feature特性名变更导致的报错,需要确认gni头文件中的变量是否一致。
文件:vendor/[manufacturerName]/产品名/config.json
{
"subsystem": "hdf",
"components": [
{
"component": "drivers_interface_audio",
"features": []
},
{
"component": "drivers_peripheral_audio",
"features": [
"drivers_peripheral_audio_feature_full_test_suite = true",
"drivers_peripheral_audio_feature_alsa_lib = true"
]
},
{
"component": "drivers_peripheral_codec",
"features": []
}
]
}
feature对应gni头文件:drivers/peripheral/audio/audio.gni
declare_args() {
drivers_peripheral_audio_feature_mono_to_stereo = false
drivers_peripheral_audio_feature_hal_notsupport_pathselect = false
drivers_peripheral_audio_feature_hdf_proxy_stub = true
drivers_peripheral_audio_feature_user_mode = false
drivers_peripheral_audio_feature_full_test_suite = false
drivers_peripheral_audio_feature_policy_config = true
drivers_peripheral_audio_feature_alsa_lib = true
drivers_peripheral_audio_feature_rich_device = false
drivers_peripheral_audio_feature_community = true
drivers_peripheral_audio_feature_effect = false
}
语法问题导致的编译警告报错:
1、未使用的临时变量,执行语法屏蔽或删除操作;
2、c代码中定义的无参函数需增加默认参数void;
其他代码也要按语法规范书写,要么通过cflags,cflags_c,cflags_cc等属性添加-Wnoerror类参数屏蔽警告错误。
针对c++使用cflags、cflags_cc 参考:
cflags_cc = [
"-Wall",
"-Wextra",
"-Werror",
"-Wno-error",
"-DGST_DISABLE_DEPRECATED",
"-DHAVE_CONFIG_H",
"-DCOLORSPACE=\"videoconvert\"",
"-fno-strict-aliasing",
"-Wno-sign-compare",
"-Wno-builtin-requires-header",
"-Wno-unused-variable",
"-Wno-unused-label",
"-Wno-implicit-function-declaration",
"-Wno-format",
"-Wno-int-conversion",
"-Wno-unused-function",
"-Wno-thread-safety-attributes",
"-Wno-inconsistent-missing-override",
"-fno-rtti",
"-fno-exceptions",
"-ffunction-sections",
"-fdata-sections",
]
针对c使用cflags_c参考:
cflags_c = [
"-Wall",
"-Wextra",
"-Werror",
"-Wno-predefined-identifier-outside-function",
"-Wno-macro-redefined",
"-Wno-format",
"-Wno-unused-parameter",
"-Wno-unused-variable",
"-fsigned-char",
"-fno-common",
"-fno-strict-aliasing",
]
4.0相对于3.2,在OpenHarmony 4.0图形HDI基础适配及点屏上存在较大差异,所以应先了解差异点再进行点亮。
新增加两个uhdf进程。allocator_host进程及composer_host进程。
删除了disp_gralloc_host 进程,并使用allocator_host替换。
uhdf添加进程配置如下:
display_composer :: host {
hostName = "composer_host";
priority = 40;
processPriority = -8;
threadPriority = 1;
caps = ["SYS_NICE"];
uid = ["composer_host"];
gid = ["composer_host", "graphics", "vendor_mpp_driver"];
composer_device :: device {
device0 :: deviceNode {
policy = 2;
priority = 160;
moduleName = "libdisplay_composer_driver_1.0.z.so";
serviceName = "display_composer_service";
}
}
}
allocator :: host {
hostName = "allocator_host";
priority = 40;
allocator_device :: device {
device0 :: deviceNode {
policy = 2;
priority = 160;
moduleName = "liballocator_driver_1.0.z.so";
serviceName = "allocator_service";
}
}
}
以前版本composer由render_service通过单例拉起,现在通过composer service拉起接口实现层libdisplay_composer_vdi_impl.z.so,对外提供标准的IPC服务.
进程名字由disp_gralloc_host变更成allocator_host。通过allocator_service拉起接口实现层libdisplay_buffer_vdi_impl.z.so,对外提供标准的IPC服务。
结构体定义由原来的.h变为接口描述语言IDL代替,在协议升级过程中,会遇到大量结构体命名空间不一样的冲突,总体解决思路就是去掉原有的.h头文件依赖,增加新的接口头文件即可。
allocator_host
头文件更新:由display_type.h 更新成v1_0/display_buffer_type.h。由DisplayBufferType.idl生成在out下
接口协议更新:
由原来的display_gralloc.cpp中提供的接口更换成OHOS::HDI::Display::Buffer::V1_0::IDisplayBufferVdi,并新建接口实现文件:
display_buffer_vdi_impl.cpp/.h。
参考drivers/peripheral/display/hal/default_standard/src/display_gralloc/display_buffer_vdi_impl.cpp中的接口,并按自己的实际情况完成实现。
composer_host
头文件更新:由display_type.h 更新成v1_0/display_composer_type.h。由DisplayComposerType.idl生成在out下
由原来的hdi_session.cpp中提供的接口更换成OHOS::HDI::Display::Composer::V1_0::IDisplayComposerVdi,并新建接口实现文件:
display_composer_vdi_impl.cpp/.h
参考drivers/peripheral/display/hal/default_standard/src/display_device/display_composer_vdi_impl.cpp中的接口,并按自己的实际情况完成实现。
新结构体去掉了key,如果代码中有用到,需要让以下定义保持一致:
drivers/hdf_core/interfaces/inner_api/hdi/base/buffer_handle.h
drivers/peripheral/base/buffer_handle.h
foundation/graphic/graphic_2d/frameworks/surface/include/buffer_handle.h
drivers/peripheral/display/interfaces/include下的头文件与device_type.h有关联。要解耦,不要使用。
在4.0中,开机动画默认使用的是播放视频,对点屏不友好,建议修改成原图片播放方式,修改方法如下:
frameworks/bootanimation/include/boot_animationconfig.h
@@ -33,7 +33,7 @@ public:
bool IsBootVideoEnabled();
private:
BootCustomConfig custConfig_;
- bool bootVideoEnabled_ = true;
+ bool bootVideoEnabled_ = false; //不使用视频开机动画模式
};
} // namespace OHOS
合入如下修改解决:
diff --git a/rosen/samples/composer/hello_composer.cpp b/rosen/samples/composer/hello_composer.cpp
index a907af7db..520da2e38 100644
--- a/rosen/samples/composer/hello_composer.cpp
+++ b/rosen/samples/composer/hello_composer.cpp
@@ -74,7 +74,7 @@ void HelloComposer::Run(const std::vector &runArgs)
sleep(1);
std::shared_ptr runner = OHOS::AppExecFwk::EventRunner::Create(false);
mainThreadHandler_ = std::make_shared(runner);
- g_receiver = new VSyncReceiver(vsyncConnection, mainThreadHandler_);
+ g_receiver = new VSyncReceiver(vsyncConnection, nullptr, mainThreadHandler_);
g_receiver->Init();
mainThreadHandler_->PostTask(std::bind(&HelloComposer::RequestSync, this));
runner->Run();
@@ -473,6 +473,7 @@ void HelloComposer::DoPrepareCompleted(sptr surface, const struct Prepa
clientCount++;
}
}
+ LOGI("clientCount:%{public}d");
auto addr = static_cast(fbBuffer->GetVirAddr());
if (hasClient) {
本次实战主要是把产品从3.2.3-Release升级到4.0-Release。中间看到这些变化,心里有点慌,从而记录下来,并提供给大家参考。框架上遇到的一些问题,前面几节已经给大家说明了,以下是一些升级的步骤及建议。
1、添加接口协议文件、gn编译、hcs配置。
为composer添加display_composer_vdi_impl.cpp/.h
为gralloc添加display_buffer_vdi_impl.cpp/.h。
在gn中添加目标libdisplay_composer_vdi_impl和libdisplay_buffer_vdi_impl。
在device_info.hcs中添加进程配置。
2、编译修改。
这个是工作量比较大的地方。原则上就是去掉drivers/peripheral/display/interfaces/include下的头文件依赖,并添加
#include “v1_0/display_composer_type.h”
#include "v1_0/display_buffer_type.h"
以及命名空间:
using namespace OHOS::HDI::Display::Composer::V1_0;
using namespace OHOS::HDI::Display::Buffer::V1_0;
当然gn中也要添加相应的依赖。
3、调试。
主要使用hello_composer调试,关注hdi_backend.cpp中Repaint函数执行流程,并在hilog中搜索关键命令字:REQUEST_CMD,一个完整的流程必须包含以下命令:
REQUEST_CMD_PREPARE_DISPAY_LATERS
REQUEST_CMD_SET_DISPLAY_CLIENT_DAMAGE
REQUEST_CMD_SET_DISPLAY_CLENT_BUFFER
REQUEST_CMD_COMMIT
如果so没有正常加载,也可以在以下文件中添加打印:
drivers/peripheral/display/buffer/hdi_service/src/allocator_service.cpp
drivers/peripheral/display/composer/hdi_service/src/display_composer_service.cpp
可以为dlopen添加详细错误信息,默认没有添加:
if (libHandle_ == NULL) {
error = dlerror();
DISPLAY_LOGE("composer load path%{public}s, dlopen err=%{public}s", DISPLAY_COMPOSER_VDI_LIBRARY, error);
return HDF_FAILURE;
}
其他模块的合入,需要各个责任田单独负责。后续将有关于audio与camera相关的升级指导。
为了能让大家更好的学习鸿蒙 (Harmony OS) 开发技术,这边特意整理了《鸿蒙 (Harmony OS)开发学习手册》(共计890页),希望对大家有所帮助:https://qr21.cn/FV7h05
https://qr21.cn/FV7h05
https://qr21.cn/FV7h05
https://qr21.cn/FV7h05
https://qr21.cn/FV7h05
https://qr21.cn/FV7h05
1.Ability开发
2.UI开发
3.公共事件与通知
4.窗口管理
5.媒体
6.安全
7.网络与链接
8.电话服务
9.数据管理
10.后台任务(Background Task)管理
11.设备管理
12.设备使用信息统计
13.DFX
14.国际化开发
15.折叠屏系列
16.……