前言
本文旨在帮助开发者完成底座升级,文中主要以OpenHarmony 3.2 release 升级至OpenHarmony 4.0 release为模板描述。
一、流程概览:
1.1 准备工作
在准备阶段,需要完整收集所有的定制化修改,明确修改人;并且要将模块责任田细化明确,确保每个模块都有相应责任人。
1.2 切换阶段
在切换阶段,以编译构建与屏幕点亮的工作量最大,难度最高。
小版本(如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.使用当前产品化版本(3.2 release)中的关键仓库直接在4.0 release中进行替换;然后参考社区在4.0 release中的改动,进行接口适配。2.直接使用社区版本(4.0 release),并根据产品特性的修改记录,进行新一轮适配。
1.3 验证阶段
与常规项目类似,即开发自验证与测试验证,确保升级后的各功能质量。
二、编译问题处理
整体编译产品,执行编译命令后,处理编译报错问题。易现的编译问题:
1、未适配的产品模块容易出现编译报错。
2、新增的白名单规则导致的编译报错。
3、更严格的模块依赖规范导致的编译报错。
4、产品组件编译后并未安装到out下的产品目录导致运行错误。
5、更严格的语法检查规范容易导致语法检查错误。
2.1 屏蔽非点亮模块编译
在碰到编译中暂时无法解决的错误,如非产品点亮相关,可暂时屏蔽改模块的编译。
1、屏蔽产品组件,修改BUILD.gn文件,例如从group属性中删除某组件
文件路径:vendor/[manufacturerName]/产品名/modules/BUILD.gn
文件路径:vendor/[manufacturerName]/产品名/modules/BUILD.gngroup("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]"
}
2.2 白名单问题处理
开发者手机项目中以前用的代码底座是3.2release的,当前要切换社区4.0release的代码位底座,切换后,新增的部分代码报了很多依赖错误,未改动的模块也报了很多依赖问题,如:
2.2.1. 对于未改动的模块报的依赖错误
已确定不影响当前功能,没必要改,可待后续代码升级时自动修复;若需修改,可参考下面的修改方法
2.2.2 对于开发手机修改或添加的相关代码的依赖报错
2.2.2.1 修改适配位置//device/soc
- 当前适配了新芯片,位置在//device/soc/[manufacturerName]/[productName]/hardware,可在//build/subsystem_config.json添加新子系统的配置如:
"soc_[manufacturerName]": {"path": "device/soc/[manufacturerName]/[productName]/hardware","name": "soc_[productName]"}
其中,soc_[manufacturerName]代表子系统名称,soc_[productName]代表部件名称
- 在device/soc/[manufacturerName]/[productName]/hardware目录下,没特殊情况时各gni,gn文件中配置的子系统名称,部件名称改为上一步配置的名称,如:
subsystem_name = "soc_[manufacturerName]"part_name = "soc_[productName]"
- 新增部件(一个部件只能属于一个子系统)定义文件//device/soc/[manufacturerName]/[productName]/hardware/bundle.json
{"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": []}}
}
- 添加//device/soc/[manufacturerName]/[productName]/hardware/ohos.build文件,定义子系统包含的部件,编译入口配置文件
{"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"]}}
}
2.2.2.2 修改适配位置//device/board
-
修改//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"]}}
}
2.2.2.3 修改适配位置vendor
-
修改//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": []}]}
- 修改//vendor/[manufacturerName]/[productName]/modules/BUILD.gn中相关子系统名称和部件名称
因为此文件中相关编译目标所属的group(“modules”)在//device/board/[manufacturerName]/[productName]/BUILD.gn中定义(“//vendor/[manufacturerName]/[productName]/modules:modules”)。
为何此时,vendor下的子系统名部件名没有配置为product_[productName]也没有报依赖错误?因为此时gn文件中用的是ohos_prebuilt_executable这种,只是用来拷贝文件
2.2.3 临时屏蔽依赖报错,绕过依赖检查,继续编译
...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()函数第二个抛异常语句
-
此方法只能临时使用,后续其他模块的依赖错误或依赖不规范问题也是需要整改的
2.3 基于4.0的模块依赖规范的修改:
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": []}}}
2.4 产品仓模块编译配置修改
产品仓模块编译后没有安装到对应的产品目录,需确认:
1、 确认模块编译文件BUILD.gn,将部件名和子系统名改为产品目录对应的部件名和子系统名
产品路径:device/board/产品名/camera/vdi_impl/v4l2/BUILD.gn
产品路径:device/board/产品名/camera/vdi_impl/v4l2/BUILD.gnohos_shared_library("camera_host_vdi_impl_1.0") {...install_enable = truepart_name = "device_laphone" //这里改为产品部件名subsystem_name = "device_laphone" //这里改为产品子系统名
}group("camera_board_vdi_impl") { //包含在groupdeps = [":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": []}}}
- feature配置问题:
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 = falsedrivers_peripheral_audio_feature_hal_notsupport_pathselect = falsedrivers_peripheral_audio_feature_hdf_proxy_stub = truedrivers_peripheral_audio_feature_user_mode = falsedrivers_peripheral_audio_feature_full_test_suite = falsedrivers_peripheral_audio_feature_policy_config = truedrivers_peripheral_audio_feature_alsa_lib = truedrivers_peripheral_audio_feature_rich_device = falsedrivers_peripheral_audio_feature_community = truedrivers_peripheral_audio_feature_effect = false
}
2.5 解决部分编译报错问题
语法问题导致的编译警告报错:
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基础适配及点屏上存在较大差异,所以应先了解差异点再进行点亮。
3.1 进程调用关系变化
3.1.1 进程数量变化
新增加两个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";}}
}
3.1.2 拉起关系变化
- composer
以前版本composer由render_service通过单例拉起,现在通过composer service拉起接口实现层libdisplay_composer_vdi_impl.z.so,对外提供标准的IPC服务.
- allocator
进程名字由disp_gralloc_host变更成allocator_host。通过allocator_service拉起接口实现层libdisplay_buffer_vdi_impl.z.so,对外提供标准的IPC服务。
3.2 接口协议更新
3.2.1 接口更新
结构体定义由原来的.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中的接口,并按自己的实际情况完成实现。
3.2.2 其它头文件更新
- BufferHandle
新结构体去掉了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有关联。要解耦,不要使用。
3.3 开机动画
在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
3.4 hello_composer编译报错
合入如下修改解决:
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<std::string> &runArgs)sleep(1);std::shared_ptr<OHOS::AppExecFwk::EventRunner> runner = OHOS::AppExecFwk::EventRunner::Create(false);mainThreadHandler_ = std::make_shared<OHOS::AppExecFwk::EventHandler>(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> surface, const struct PrepaclientCount++;}}
+ LOGI("clientCount:%{public}d");auto addr = static_cast<uint8_t *>(fbBuffer->GetVirAddr());if (hasClient) {
3.5 问题列举
本次实战主要是把产品从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
《鸿蒙 (Harmony OS)开发学习手册》
入门必看:https://qr21.cn/FV7h05
- 应用开发导读(ArkTS)
- ……
HarmonyOS 概念:https://qr21.cn/FV7h05
- 系统定义
- 技术架构
- 技术特性
- 系统安全
如何快速入门?:https://qr21.cn/FV7h05
- 基本概念
- 构建第一个ArkTS应用
- 构建第一个JS应用
- ……
开发基础知识:https://qr21.cn/FV7h05
- 应用基础知识
- 配置文件
- 应用数据管理
- 应用安全管理
- 应用隐私保护
- 三方应用调用管控机制
- 资源分类与访问
- 学习ArkTS语言
- ……
基于ArkTS 开发: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.……