1# updater部件ux概述 2## 功能简介 3updater部件是在升级模式下的轻量小系统,ux组件是一套系统交互界面,提供OTA升级过程中的界面显示和信息提示,指导用户完成升级流程。组件不依赖ArkUI框架,无需引入JS,具有界面简洁、外部依赖少、跳转清晰的特点。 4## 基本概念 5- UX:User Experience,人机交互体验。<br> 6- 页面:界面交互时一个画面为一个页面。<br> 7- 控件:页面构成的基本单位,如按钮、文本、图片等单元。<br> 8- 引擎:控件显示必要条件,完成资源初始化、队列初始化、开启刷新线程等。<br> 9## 框架介绍 10框架主要由业务层、UX接口层、页面管理层、控件引擎层、设备驱动层组成,总体框架如下图所示:<br> 11 12图1 ux总体框架图<br> 13 14- 业务层<br> 15升级过程中的业务流程,包括读取misc分区信息获取升级包状态、对升级包进行校验、确保升级包合法有效、从升级包中解析出升级的可执行程序、创建子进程并启动升级程序等。 16 17- UX接口层<br> 18其他模块访问ux的统一通道,上层进行交互显示时,通过统一的类对象入口调用ux组件进行更新。接口调用包括进度条刷新、按钮刷新、文本刷新等。 19 20- 页面管理层<br> 21人机交互过程是一组页面的组合。主要负责页面组合管理,包括页面的配置、页面解析并初始化、页面间跳转等,是组件的核心组成部分。 22 23- 控件引擎层<br> 24控件是页面的基本组成单元。主要负责控件管理,包括两部分内容。一部分是完成图像引擎的初始化,包括字体初始化、图片解码初始化、申请显示缓存空间、开启屏幕刷新线程,依赖图形子系统的基础控件库。另外一部分是触控以及点击事件的初始化,可以感知用户点击屏幕和按键按下释放等操作,也是组件的核心组成部分。 25 26- 设备驱动层<br> 27主要完成各种设备类型屏幕设备节点的初始化,以及和引擎层刷新缓存的对接,保证上层的修改可以实时刷新显示。 28## 子模块介绍 291. 接口管理<br> 30在业务中通过唯一的对象实例UPDATER_UI_INSTANCE进行不同接口调用来实现不同界面的刷新。 31 ```c++ 32 if (mode == HOTA_UPDATE) { 33 UPDATER_UI_INSTANCE.ShowFailedPage(); 34 } else { 35 UPDATER_UI_INSTANCE.ShowMainpage(); 36 UPDATER_UI_INSTANCE.Sleep(50); /* wait for page flush 50ms */ 37 UPDATER_UI_INSTANCE.SaveScreen(); 38 } 39 // Wait for user input 40 while (true) { 41 Utils::UsSleep(DISPLAY_TIME); 42 } 43 return 0; 44 ``` 452. 页面管理<br> 46通过配置化进行页面管理,采用分层设计,config为统一入口,包含了不同类型产品的配置定义。product为特定产品的配置定义,包含了所有页面的配置定义。产品适配时可以从该入口开始梳理配置流程。有多个产品类型时,端侧在SelectConfig函数中会根据设备分辨率类型进行匹配,选择对应产品json。页面组成结构如下图所示: 47 ```c++ 48 auto screenW = subCfg[WIDTH_KEY].As<int16_t>(); 49 auto screenH = subCfg[HEIGHT_KEY].As<int16_t>(); 50 if (!screenW.has_value() || !screenH.has_value()) { 51 LOG(ERROR) << "real config file should has screenW and screenH key"; 52 return ""; 53 } 54 if (screenW != Screen::GetInstance().GetWidth() || screenH != Screen::GetInstance().GetHeight()) { 55 LOG(INFO) << "screen size not matched" << subConfigPath; 56 continue; 57 } 58 LOG(INFO) << "select config: " << subConfigPath; 59 return subConfigPath; 60 ``` 61 图2 页面组成结构图<br> 62  633. 控件管理<br> 64控件组织形式是一个树形结构,所有控件通过链表形式组成一颗渲染树,渲染时从最上面的覆盖脏区域的节点开始进行深度优先遍历绘图。RootView会挂载所有页面,类似于绘画时的白纸。UIViewGroup为配置文件中对应的各个page页面,类似于图像的图层。UIView为各个基本的显示控件。控件也是在配置中进行管理,挂载在每个页面下,因此在每个页面的定义中也需要增加控件的配置。控件结构如下图所示:<br> 65图3 控件结构示意图<br> 66 674. 事件管理<br> 68事件管理包含了触控事件响应,输入管理模块PointerInputDevice读取输入位置,根据上报的坐标信息所在的脏区域找到对应的控件,根据上报的状态信息,识别为点击事件,调用控件注册对应的触控回调函数,执行对应的响应。各控件的事件也是通过配置进行管理,如果某控件需要动态响应,需要在配置中添加对应回调函数。按钮响应的流程示例如下图所示:<br> 69图4 按钮响应流程示意图<br> 70 715. 资源管理<br> 72资源文件是ux功能正常运行的必备条件,主要包括字体、图片、文本、配置文件。当前字体的格式为ttf文件,图片资源格式为png,文本类型为string,所有配置文件为json。界面适配主要是定制化资源文件,可以在对应模块中修改适配。资源组成结构如下图所示:<br> 73图5 资源结构示意图<br> 74 75# 适配新产品RK3568 76## 约束与限制 77- 屏幕可以正常亮屏 78- 触控屏可以正常点击感应 79- 屏幕分辨率已知,以RK3568为例长宽的分辨率分别为720和1280 80## 适配流程 81适配过程主要是完成各种资源的初始化,流程如下图所示:<br> 82图6 适配流程图<br> 83 84### 新建rk3568.json 85进入到update_updater/resources/rk3568/pages目录。当前目录新建rk3568.json, 添加到config.json中。 86```json 87{ 88 "config" : "/resources/pages/rk3568.json" 89} 90``` 91### 初始化rk3568.json 92配置产品json文件中的各个字段值,配置列表如下所示:<br> 93 94表1 json各字段配置表 95| 字段 | 值 | 含义 | 备注 | 96|--|--|--|--| 97| screenWidth | 720 | 屏幕宽度分辨率 | 根据实际配置 | 98| screenHeight | 1280 | 屏幕长度分辨率 | 根据实际配置 | 99| dir | /resources/pages | 页面资源在单板的存放路径 | 使用默认 | 100| pages | ["menu.json","confirm.json","upd.json"] | 所有页面的列表 | 使用默认 | 101| enableFoucs | true | 使能焦点 | 使用默认 | 102| entry | menu:normal | 主菜单页面 | 使用默认 | 103| strategy | 见json配置:有default、sdcard、factoryRst、rebootFactoryRst | 默认有4种策略,分别为参数升级、SD卡升级、手动恢厂、参数恢厂 | 使用默认 | 104| locale | 见json配置:有res、localeFile | 单板上提示语资源存放路径、使用多语言的文件名 | 使用默认 | 105| callbacks | 见json配置:有pageId、comId、type、func | 为页面控件绑定回调函数类型,如点击事件和用户进行交互 | 使用默认 | 106 107因为pages字段中配置了3个页面,所以需要分别初始化这3个页面。 108 109### 初始化menu.json 110配置主菜单页面json文件中的各个字段值,配置列表如下所示:<br> 111 112表2 json各字段配置表 113| 字段 | 值 | 含义 | 备注 | 114|--|--|--|--| 115| id | menu | 主菜单页面,**值必须与上一小节中pages字段值保持一致** | 使用默认 | 116| bgColor | "r":0,"g":0,"b":0,"a":255 | 背景颜色为RGBA形式 | 根据实际配置 | 117| subpages | 见json配置:有id,coms,bgColor | 组成了包含的子页面,主菜单会跳转到这些子页面上 | 使用默认 | 118| default | 各控件属性 | 指定了默认控件的属性参数 | 使用默认 | 119| coms | type、id、x、y、w、h、fontSize、fontColor | 页面包含一组控件,定义了每个控件的基本属性,x、y、w、h确定了控件在页面上的唯一位置 | x、y、w、h、fontSize、fontColor需要根据分辨率的实际配置,其他使用默认 | 120 121- 下面举例看看更改这些字段后的效果。 122 ```json 123 "id": "menu", 124 "bgColor" : "#000000ff", 125 "subpages" : [ 126 { 127 "id":"normal", 128 "bgColor" : "#f1f3f5ff" 129 ``` 130 131 图7 修改前效果图<br> 132  133- rk3568.json中entry字段配置为menu:normal,修改subpages中id为normal的背景色配置bgColor字段,改为绿色不透明: 134 ```json 135 "id": "menu", 136 "bgColor" : "#000000ff", 137 "subpages" : [ 138 { 139 "id":"normal", 140 "bgColor" : "#00ff00ff" 141 ``` 142 143 修改后效果:<br> 144 图8 修改后效果图<br> 145  146- 接下来再更改LOGO图片的位置,当前配置如上图所示: 147 ```json 148 "coms": [ 149 { 150 "type": "UIImageView", 151 "id": "HarmonyOSIcon_Image", 152 "x": 120, 153 "y": 426, 154 "w": 480, 155 "h": 60, 156 ``` 157 158 现在通过修改w、h、x、y属性移动到屏幕顶部左上角: 159 ```json 160 "coms": [ 161 { 162 "type": "UIImageView", 163 "id": "HarmonyOSIcon_Image", 164 "x": 0, 165 "y": 0, 166 "w": 480, 167 "h": 60, 168 ``` 169 170 修改后效果:<br> 171 图9 修改后效果图<br> 172 <br> 173其他属性的配置操作都是一样,参照以上配置即可。 174### 初始化confirm.json 175配置确认页面json文件中的各个字段值,配置列表如下所示:<br> 176 177表3 json各字段配置表 178| 字段 | 值 | 含义 | 备注 | 179|--|--|--|--| 180| id | confirm | 确认页面,**值必须与上一小节中pages字段值保持一致** | 使用默认 | 181| bgColor | "r":0,"g":0,"b":0,"a":255 | 背景颜色为RGBA形式 | 根据实际配置 | 182| default | 各控件属性 | 指定了默认控件的属性参数 | 使用默认 | 183| coms | type、id、x、y、w、h、fontSize、fontColor | 页面包含一组控件,定义了每个控件的基本属性,x、y、w、h确定了控件在页面上的唯一位置 | x、y、w、h、fontSize、fontColor需要根据分辨率的实际配置,其他使用默认 | 184 185- 下面举例看看更改这些字段后的效果。<br> 186 ```json 187 "coms": [ 188 { 189 "type": "UILabelButton", 190 "id": "Cancel_Button", 191 "text": "[LABEL_NOTE_CANCEL]", 192 "x": 48, 193 "y": 1130, 194 "w": 624, 195 "h": 80, 196 "fontSize": 32 197 }, 198 { 199 "type": "UILabelButton", 200 "id": "Reset_Button", 201 "text": "[LABEL_USER_DATA_RESET]", 202 "x": 48, 203 "y": 1020, 204 "w": 624, 205 "h": 80, 206 "fontSize": 32 207 } 208 ``` 209 210 图10 修改前效果图<br> 211  212- 页面中有两个按钮,和对应的按钮配置。现在把Cancel_Button取消居中移动到左对齐,字体变大。Reset_Button移动到屏幕底部,同时字体缩小一半,修改后的配置: 213 ```json 214 "coms": [ 215 { 216 "type": "UILabelButton", 217 "id": "Cancel_Button", 218 "text": "[LABEL_NOTE_CANCEL]", 219 "x": 0, 220 "y": 1130, 221 "w": 624, 222 "h": 80, 223 "fontSize": 48 224 }, 225 { 226 "type": "UILabelButton", 227 "id": "Reset_Button", 228 "text": "[LABEL_USER_DATA_RESET]", 229 "x": 48, 230 "y": 1200, 231 "w": 624, 232 "h": 80, 233 "fontSize": 16 234 } 235 ``` 236 237 修改后效果如下:<br> 238 图11 修改后效果图<br> 239  240### 初始化upd.json 241配置更新页面json文件中的各个字段值,配置列表如下所示:<br> 242 243表4 json各字段配置表 244| 字段 | 值 | 含义 | 备注 | 245|--|--|--|--| 246| id | upd | 进度条升级页面,**值必须与上一小节中pages字段值保持一致** | 使用默认 | 247| bgColor | "r":0,"g":0,"b":0,"a":255 | 背景颜色为RGBA形式 | 根据实际配置 | 248| subpages | 见json配置:有id,coms,bgColor | 组成了包含的子页面,主菜单会跳转到这些子页面上,有7个跳转页面 | 使用默认 | 249| default | 各控件属性 | 指定了默认控件的属性参数 | 使用默认 | 250| coms | type、id、x、y、w、h、fontSize、fontColor | 页面包含一组控件,定义了每个控件的基本属性,x、y、w、h确定了控件在页面上的唯一位置 | x、y、w、h、fontSize、fontColor需要根据分辨率的实际配置,其他使用默认 | 251 252- 同类型控件前几个小节已经介绍,下面举例看看更改进度条字段后的效果。**白色背景进度条在非安装包升级模式才有**,对应的控件id为UpdBox_Progress,修改配置时注意区分。<br> 253 ```json 254 "coms": [ 255 { 256 "type": "UIBoxProgress", 257 "id": "UpdBox_Progress", 258 "x": 144, 259 "y": 584, 260 "w": 432, 261 "h": 4, 262 "endPoint" : "FlashPoint_Image", 263 "hasEp" : true 264 }, 265 ``` 266 267 图12 修改前效果图<br> 268  269- 修改配置把进度条移动到LOGO上面,进度条宽度扩大10倍,配置如下: 270 ```json 271 "coms": [ 272 { 273 "type": "UIBoxProgress", 274 "id": "UpdBox_Progress", 275 "x": 144, 276 "y": 200, 277 "w": 432, 278 "h": 40, 279 "endPoint" : "FlashPoint_Image", 280 "hasEp" : true 281 }, 282 ``` 283 284 修改后效果如下:<br> 285 图13 修改后效果图<br> 286  287- **黑色背景进度条在安装包升级模式才有**,对应的控件id为ProgressUpdBoxDark_Progress,修改配置时注意区分。<br> 288 ```json 289 "coms": [ 290 { 291 "type": "UIBoxProgress", 292 "id": "ProgressUpdBoxDark_Progress", 293 "x": 144, 294 "y": 548, 295 "w": 432, 296 "h": 4, 297 "bgColor" : "#262626ff", 298 "fgColor" : "#b4b4b4ff", 299 "endPoint" : "FlashPointDark_Image", 300 "hasEp" : true 301 }, 302 ``` 303 304 图14 修改前效果图<br> 305  306- 修改配置颜色变更为红色,配置如下: 307 ```json 308 "coms": [ 309 { 310 "type": "UIBoxProgress", 311 "id": "ProgressUpdBoxDark_Progress", 312 "x": 144, 313 "y": 548, 314 "w": 432, 315 "h": 4, 316 "bgColor" : "#262626ff", 317 "fgColor" : "#ff0000ff", 318 "endPoint" : "FlashPointDark_Image", 319 "hasEp" : true 320 }, 321 ``` 322 323 修改后效果如下:<br> 324 图15 修改后效果图<br> 325  326### 初始化图片资源 327页面配置完成后,需要对资源images目录进行初始化。json文件中图片控件的resPath字段会配置为图片在设备上的路径,该路径下的资源来源于如下表格中的目录。如果需要更换这些图片资源,在此目录下替换即可。<br> 328 329表5 图片资源目录表 330| 目录 | 含义 | 备注 | 331|--|--|--| 332| resources/rk3568/images/icon | 主菜单LOGO图片资源 | 使用默认 | 333| resources/rk3568/images/progress | 进度条图片资源 | 使用默认 | 334| resources/rk3568/images/warn | 警告图片资源,升级过程中操作不当会触发警告 | 使用默认 | 335 336### 初始化提示语 337images目录适配完成后,需要适配同级目录的string文件夹。提示语通过配置文件string.json进行管理。支持中英文和西班牙语。文本控件以id形式组成一个列表。可以修改提示语值,也可以使用默认。<br> 338 339表6 提示语配置表 340| 字段 | 含义 | 备注 | 341|--|--|--| 342| type | 控件类型一般为文本 | 使用默认 | 343| zh | 中文提示语 | 根据实际配置 | 344| en | 英文提示语 | 根据实际配置 | 345| spa | 西班牙提示语 | 根据实际配置 | 346 347### 初始化字体 348接下来是字体的适配。可以使用默认ttf文件。若当前字体库不满足使用场景,用准备好的ttf字体库文件替换即可,文件在目录resources/font下。 349 350### 输入处理 351最后在HdfInit函数中进行触控屏的报点读取和分发处理。在ReportEventPkgCallback函数中更新坐标点和按压状态。 352```c++ 353for (int i = 0; i < MAX_INPUT_DEVICES; i++) { 354 uint32_t idx = sta[i].devIndex; 355 if ((idx == 0) || (g_inputInterface->iInputManager->OpenInputDevice(idx) == INPUT_FAILURE)) { 356 continue; 357 } 358 359 LOG(INFO) << "hdf devType:" << sta[i].devType << ", devIndex:" << idx; 360} 361 362/* first param not necessary, pass default 1 */ 363g_callback.EventPkgCallback = ReportEventPkgCallback; 364ret = g_inputInterface->iInputReporter->RegisterReportCallback(1, &g_callback); 365if (ret != INPUT_SUCCESS) { 366 LOG(ERROR) << "register callback failed for device 1"; 367 return ret; 368} 369``` 370 371如果输入使用了openharmony的HDF驱动框架,HdfInit函数不用修改即可完成坐标点正常获取。否则请适配该函数完成坐标点和按压状态更新。 372## 调测验证 373适配完成后即可编译版本刷写单板查看效果。 374- 主菜单页面menu.json<br> 375图16 主菜单页面效果图<br> 376 377- 确认页面confirm.json<br> 378图17 确认页面效果图<br> 379 380- 更新页面upd.json<br> 381恢厂更新:<br> 382图18 恢厂更新页面效果图<br> 383<br> 384安装包升级更新:<br> 385图19 安装包更新页面效果图<br> 386 387