# updater部件ux概述 ## 功能简介 updater部件是在升级模式下的轻量小系统,ux组件是一套系统交互界面,提供OTA升级过程中的界面显示和信息提示,指导用户完成升级流程。组件不依赖ArkUI框架,无需引入JS,具有界面简洁、外部依赖少、跳转清晰的特点。 ## 基本概念 - UX:User Experience,人机交互体验。
- 页面:界面交互时一个画面为一个页面。
- 控件:页面构成的基本单位,如按钮、文本、图片等单元。
- 引擎:控件显示必要条件,完成资源初始化、队列初始化、开启刷新线程等。
## 框架介绍 框架主要由业务层、UX接口层、页面管理层、控件引擎层、设备驱动层组成,总体框架如下图所示:
图1 ux总体框架图
![输入图片说明](figures/framework.png) - 业务层
升级过程中的业务流程,包括读取misc分区信息获取升级包状态、对升级包进行校验、确保升级包合法有效、从升级包中解析出升级的可执行程序、创建子进程并启动升级程序等。 - UX接口层
其他模块访问ux的统一通道,上层进行交互显示时,通过统一的类对象入口调用ux组件进行更新。接口调用包括进度条刷新、按钮刷新、文本刷新等。 - 页面管理层
人机交互过程是一组页面的组合。主要负责页面组合管理,包括页面的配置、页面解析并初始化、页面间跳转等,是组件的核心组成部分。 - 控件引擎层
控件是页面的基本组成单元。主要负责控件管理,包括两部分内容。一部分是完成图像引擎的初始化,包括字体初始化、图片解码初始化、申请显示缓存空间、开启屏幕刷新线程,依赖图形子系统的基础控件库。另外一部分是触控以及点击事件的初始化,可以感知用户点击屏幕和按键按下释放等操作,也是组件的核心组成部分。 - 设备驱动层
主要完成各种设备类型屏幕设备节点的初始化,以及和引擎层刷新缓存的对接,保证上层的修改可以实时刷新显示。 ## 子模块介绍 1. 接口管理
在业务中通过唯一的对象实例UPDATER_UI_INSTANCE进行不同接口调用来实现不同界面的刷新。 ```c++ if (mode == HOTA_UPDATE) { UPDATER_UI_INSTANCE.ShowFailedPage(); } else { UPDATER_UI_INSTANCE.ShowMainpage(); UPDATER_UI_INSTANCE.Sleep(50); /* wait for page flush 50ms */ UPDATER_UI_INSTANCE.SaveScreen(); } // Wait for user input while (true) { Utils::UsSleep(DISPLAY_TIME); } return 0; ``` 2. 页面管理
通过配置化进行页面管理,采用分层设计,config为统一入口,包含了不同类型产品的配置定义。product为特定产品的配置定义,包含了所有页面的配置定义。产品适配时可以从该入口开始梳理配置流程。有多个产品类型时,端侧在SelectConfig函数中会根据设备分辨率类型进行匹配,选择对应产品json。页面组成结构如下图所示: ```c++ auto screenW = subCfg[WIDTH_KEY].As(); auto screenH = subCfg[HEIGHT_KEY].As(); if (!screenW.has_value() || !screenH.has_value()) { LOG(ERROR) << "real config file should has screenW and screenH key"; return ""; } if (screenW != Screen::GetInstance().GetWidth() || screenH != Screen::GetInstance().GetHeight()) { LOG(INFO) << "screen size not matched" << subConfigPath; continue; } LOG(INFO) << "select config: " << subConfigPath; return subConfigPath; ``` 图2 页面组成结构图
![输入图片说明](figures/page_manage.png) 3. 控件管理
控件组织形式是一个树形结构,所有控件通过链表形式组成一颗渲染树,渲染时从最上面的覆盖脏区域的节点开始进行深度优先遍历绘图。RootView会挂载所有页面,类似于绘画时的白纸。UIViewGroup为配置文件中对应的各个page页面,类似于图像的图层。UIView为各个基本的显示控件。控件也是在配置中进行管理,挂载在每个页面下,因此在每个页面的定义中也需要增加控件的配置。控件结构如下图所示:
图3 控件结构示意图
![输入图片说明](figures/component_manage.png) 4. 事件管理
事件管理包含了触控事件响应,输入管理模块PointerInputDevice读取输入位置,根据上报的坐标信息所在的脏区域找到对应的控件,根据上报的状态信息,识别为点击事件,调用控件注册对应的触控回调函数,执行对应的响应。各控件的事件也是通过配置进行管理,如果某控件需要动态响应,需要在配置中添加对应回调函数。按钮响应的流程示例如下图所示:
图4 按钮响应流程示意图
![输入图片说明](figures/event_manage.png) 5. 资源管理
资源文件是ux功能正常运行的必备条件,主要包括字体、图片、文本、配置文件。当前字体的格式为ttf文件,图片资源格式为png,文本类型为string,所有配置文件为json。界面适配主要是定制化资源文件,可以在对应模块中修改适配。资源组成结构如下图所示:
图5 资源结构示意图
![输入图片说明](figures/res_manage.png) # 适配新产品RK3568 ## 约束与限制 - 屏幕可以正常亮屏 - 触控屏可以正常点击感应 - 屏幕分辨率已知,以RK3568为例长宽的分辨率分别为720和1280 ## 适配流程 适配过程主要是完成各种资源的初始化,流程如下图所示:
图6 适配流程图
![输入图片说明](figures/develop_process.png) ### 新建rk3568.json 进入到update_updater/resources/rk3568/pages目录。当前目录新建rk3568.json, 添加到config.json中。 ```json { "config" : "/resources/pages/rk3568.json" } ``` ### 初始化rk3568.json 配置产品json文件中的各个字段值,配置列表如下所示:
表1 json各字段配置表 | 字段 | 值 | 含义 | 备注 | |--|--|--|--| | screenWidth | 720 | 屏幕宽度分辨率 | 根据实际配置 | | screenHeight | 1280 | 屏幕长度分辨率 | 根据实际配置 | | dir | /resources/pages | 页面资源在单板的存放路径 | 使用默认 | | pages | ["menu.json","confirm.json","upd.json"] | 所有页面的列表 | 使用默认 | | enableFoucs | true | 使能焦点 | 使用默认 | | entry | menu:normal | 主菜单页面 | 使用默认 | | strategy | 见json配置:有default、sdcard、factoryRst、rebootFactoryRst | 默认有4种策略,分别为参数升级、SD卡升级、手动恢厂、参数恢厂 | 使用默认 | | locale | 见json配置:有res、localeFile | 单板上提示语资源存放路径、使用多语言的文件名 | 使用默认 | | callbacks | 见json配置:有pageId、comId、type、func | 为页面控件绑定回调函数类型,如点击事件和用户进行交互 | 使用默认 | 因为pages字段中配置了3个页面,所以需要分别初始化这3个页面。 ### 初始化menu.json 配置主菜单页面json文件中的各个字段值,配置列表如下所示:
表2 json各字段配置表 | 字段 | 值 | 含义 | 备注 | |--|--|--|--| | id | menu | 主菜单页面,**值必须与上一小节中pages字段值保持一致** | 使用默认 | | bgColor | "r":0,"g":0,"b":0,"a":255 | 背景颜色为RGBA形式 | 根据实际配置 | | subpages | 见json配置:有id,coms,bgColor | 组成了包含的子页面,主菜单会跳转到这些子页面上 | 使用默认 | | default | 各控件属性 | 指定了默认控件的属性参数 | 使用默认 | | coms | type、id、x、y、w、h、fontSize、fontColor | 页面包含一组控件,定义了每个控件的基本属性,x、y、w、h确定了控件在页面上的唯一位置 | x、y、w、h、fontSize、fontColor需要根据分辨率的实际配置,其他使用默认 | - 下面举例看看更改这些字段后的效果。 ```json "id": "menu", "bgColor" : "#000000ff", "subpages" : [ { "id":"normal", "bgColor" : "#f1f3f5ff" ``` 图7 修改前效果图
![输入图片说明](figures/menu_grey.png) - rk3568.json中entry字段配置为menu:normal,修改subpages中id为normal的背景色配置bgColor字段,改为绿色不透明: ```json "id": "menu", "bgColor" : "#000000ff", "subpages" : [ { "id":"normal", "bgColor" : "#00ff00ff" ``` 修改后效果:
图8 修改后效果图
![输入图片说明](figures/menu_green.png) - 接下来再更改LOGO图片的位置,当前配置如上图所示: ```json "coms": [ { "type": "UIImageView", "id": "HarmonyOSIcon_Image", "x": 120, "y": 426, "w": 480, "h": 60, ``` 现在通过修改w、h、x、y属性移动到屏幕顶部左上角: ```json "coms": [ { "type": "UIImageView", "id": "HarmonyOSIcon_Image", "x": 0, "y": 0, "w": 480, "h": 60, ``` 修改后效果:
图9 修改后效果图
![输入图片说明](figures/menu_top.png)
其他属性的配置操作都是一样,参照以上配置即可。 ### 初始化confirm.json 配置确认页面json文件中的各个字段值,配置列表如下所示:
表3 json各字段配置表 | 字段 | 值 | 含义 | 备注 | |--|--|--|--| | id | confirm | 确认页面,**值必须与上一小节中pages字段值保持一致** | 使用默认 | | bgColor | "r":0,"g":0,"b":0,"a":255 | 背景颜色为RGBA形式 | 根据实际配置 | | default | 各控件属性 | 指定了默认控件的属性参数 | 使用默认 | | coms | type、id、x、y、w、h、fontSize、fontColor | 页面包含一组控件,定义了每个控件的基本属性,x、y、w、h确定了控件在页面上的唯一位置 | x、y、w、h、fontSize、fontColor需要根据分辨率的实际配置,其他使用默认 | - 下面举例看看更改这些字段后的效果。
```json "coms": [ { "type": "UILabelButton", "id": "Cancel_Button", "text": "[LABEL_NOTE_CANCEL]", "x": 48, "y": 1130, "w": 624, "h": 80, "fontSize": 32 }, { "type": "UILabelButton", "id": "Reset_Button", "text": "[LABEL_USER_DATA_RESET]", "x": 48, "y": 1020, "w": 624, "h": 80, "fontSize": 32 } ``` 图10 修改前效果图
![输入图片说明](figures/confirm_btn.png) - 页面中有两个按钮,和对应的按钮配置。现在把Cancel_Button取消居中移动到左对齐,字体变大。Reset_Button移动到屏幕底部,同时字体缩小一半,修改后的配置: ```json "coms": [ { "type": "UILabelButton", "id": "Cancel_Button", "text": "[LABEL_NOTE_CANCEL]", "x": 0, "y": 1130, "w": 624, "h": 80, "fontSize": 48 }, { "type": "UILabelButton", "id": "Reset_Button", "text": "[LABEL_USER_DATA_RESET]", "x": 48, "y": 1200, "w": 624, "h": 80, "fontSize": 16 } ``` 修改后效果如下:
图11 修改后效果图
![输入图片说明](figures/confirm_bottom.png) ### 初始化upd.json 配置更新页面json文件中的各个字段值,配置列表如下所示:
表4 json各字段配置表 | 字段 | 值 | 含义 | 备注 | |--|--|--|--| | id | upd | 进度条升级页面,**值必须与上一小节中pages字段值保持一致** | 使用默认 | | bgColor | "r":0,"g":0,"b":0,"a":255 | 背景颜色为RGBA形式 | 根据实际配置 | | subpages | 见json配置:有id,coms,bgColor | 组成了包含的子页面,主菜单会跳转到这些子页面上,有7个跳转页面 | 使用默认 | | default | 各控件属性 | 指定了默认控件的属性参数 | 使用默认 | | coms | type、id、x、y、w、h、fontSize、fontColor | 页面包含一组控件,定义了每个控件的基本属性,x、y、w、h确定了控件在页面上的唯一位置 | x、y、w、h、fontSize、fontColor需要根据分辨率的实际配置,其他使用默认 | - 同类型控件前几个小节已经介绍,下面举例看看更改进度条字段后的效果。**白色背景进度条在非安装包升级模式才有**,对应的控件id为UpdBox_Progress,修改配置时注意区分。
```json "coms": [ { "type": "UIBoxProgress", "id": "UpdBox_Progress", "x": 144, "y": 584, "w": 432, "h": 4, "endPoint" : "FlashPoint_Image", "hasEp" : true }, ``` 图12 修改前效果图
![输入图片说明](figures/upd_progress.png) - 修改配置把进度条移动到LOGO上面,进度条宽度扩大10倍,配置如下: ```json "coms": [ { "type": "UIBoxProgress", "id": "UpdBox_Progress", "x": 144, "y": 200, "w": 432, "h": 40, "endPoint" : "FlashPoint_Image", "hasEp" : true }, ``` 修改后效果如下:
图13 修改后效果图
![输入图片说明](figures/upd_wider.png) - **黑色背景进度条在安装包升级模式才有**,对应的控件id为ProgressUpdBoxDark_Progress,修改配置时注意区分。
```json "coms": [ { "type": "UIBoxProgress", "id": "ProgressUpdBoxDark_Progress", "x": 144, "y": 548, "w": 432, "h": 4, "bgColor" : "#262626ff", "fgColor" : "#b4b4b4ff", "endPoint" : "FlashPointDark_Image", "hasEp" : true }, ``` 图14 修改前效果图
![输入图片说明](figures/upd_black.png) - 修改配置颜色变更为红色,配置如下: ```json "coms": [ { "type": "UIBoxProgress", "id": "ProgressUpdBoxDark_Progress", "x": 144, "y": 548, "w": 432, "h": 4, "bgColor" : "#262626ff", "fgColor" : "#ff0000ff", "endPoint" : "FlashPointDark_Image", "hasEp" : true }, ``` 修改后效果如下:
图15 修改后效果图
![输入图片说明](figures/upd_red.png) ### 初始化图片资源 页面配置完成后,需要对资源images目录进行初始化。json文件中图片控件的resPath字段会配置为图片在设备上的路径,该路径下的资源来源于如下表格中的目录。如果需要更换这些图片资源,在此目录下替换即可。
表5 图片资源目录表 | 目录 | 含义 | 备注 | |--|--|--| | resources/rk3568/images/icon | 主菜单LOGO图片资源 | 使用默认 | | resources/rk3568/images/progress | 进度条图片资源 | 使用默认 | | resources/rk3568/images/warn | 警告图片资源,升级过程中操作不当会触发警告 | 使用默认 | ### 初始化提示语 images目录适配完成后,需要适配同级目录的string文件夹。提示语通过配置文件string.json进行管理。支持中英文和西班牙语。文本控件以id形式组成一个列表。可以修改提示语值,也可以使用默认。
表6 提示语配置表 | 字段 | 含义 | 备注 | |--|--|--| | type | 控件类型一般为文本 | 使用默认 | | zh | 中文提示语 | 根据实际配置 | | en | 英文提示语 | 根据实际配置 | | spa | 西班牙提示语 | 根据实际配置 | ### 初始化字体 接下来是字体的适配。可以使用默认ttf文件。若当前字体库不满足使用场景,用准备好的ttf字体库文件替换即可,文件在目录resources/font下。 ### 输入处理 最后在HdfInit函数中进行触控屏的报点读取和分发处理。在ReportEventPkgCallback函数中更新坐标点和按压状态。 ```c++ for (int i = 0; i < MAX_INPUT_DEVICES; i++) { uint32_t idx = sta[i].devIndex; if ((idx == 0) || (g_inputInterface->iInputManager->OpenInputDevice(idx) == INPUT_FAILURE)) { continue; } LOG(INFO) << "hdf devType:" << sta[i].devType << ", devIndex:" << idx; } /* first param not necessary, pass default 1 */ g_callback.EventPkgCallback = ReportEventPkgCallback; ret = g_inputInterface->iInputReporter->RegisterReportCallback(1, &g_callback); if (ret != INPUT_SUCCESS) { LOG(ERROR) << "register callback failed for device 1"; return ret; } ``` 如果输入使用了openharmony的HDF驱动框架,HdfInit函数不用修改即可完成坐标点正常获取。否则请适配该函数完成坐标点和按压状态更新。 ## 调测验证 适配完成后即可编译版本刷写单板查看效果。 - 主菜单页面menu.json
图16 主菜单页面效果图
![输入图片说明](figures/menu.png) - 确认页面confirm.json
图17 确认页面效果图
![输入图片说明](figures/confirm.png) - 更新页面upd.json
恢厂更新:
图18 恢厂更新页面效果图
![输入图片说明](figures/upd_sd.png)
安装包升级更新:
图19 安装包更新页面效果图
![输入图片说明](figures/upd_zip.png)