subsys-ota-guide.md 23.3 KB
Newer Older
S
shawn_he 已提交
1
# OTA Update
N
NEEN 已提交
2 3


S
shawn_he 已提交
4
## Introduction
D
duangavin123 已提交
5 6


S
shawn_he 已提交
7
### Overview
N
NEEN 已提交
8

S
shawn_he 已提交
9
With the rapid development of device systems, it has become a critical challenge for device vendors to help their users to access system updates in a timely manner to experience the new features and improve the system stability and security.
D
duangavin123 已提交
10

S
shawn_he 已提交
11
Over the Air (OTA) answers this challenge with the support for remote updating of device systems. By providing unified update APIs externally, the update subsystem shields the differences of underlying chips. After secondary development based on the update APIs, device vendors can easily implement remote updating for their devices, such as IP cameras.
D
duangavin123 已提交
12

N
NEEN 已提交
13

S
shawn_he 已提交
14
### Basic Concepts
N
NEEN 已提交
15

S
shawn_he 已提交
16
- Full package: an update package that packs all images of the target version.
N
NEEN 已提交
17

S
shawn_he 已提交
18
- Differential package: an update package that packs the differential images between the source version and target version.
D
duangavin123 已提交
19 20


S
shawn_he 已提交
21 22 23 24
### Implementation Principle

To implement an OTA update, you first need to use the packaging tool to pack the build version into an update package and upload the update package to the OTA server. Devices integrating the OTA update capability can then detect the update package and download it to implement a remote update.

S
shawn_he 已提交
25
<a href="#ab-update-scenario">A/B Update</a>: a typical application of OTA update. In this update mode, a device has a backup system B. When system A is running, system B is updated silently. After the update is successful, the device restarts and switches to the new system.
S
shawn_he 已提交
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50


### Constraints

- Only the open-source suites for devices powered by Hi3861, Hi3518E V300, and Hi3516D V300 are supported.

- Devices developed based on Hi3518E V300 and Hi3516D V300 must support the SD card in the Virtual Festival of Aerobatic Teams (VFAT) format.

- Generation of update packages can only be performed on the Linux system.

- Currently, the mini and small systems support update using a full package, but not a differential package or an update package with partitions changed.


## Environment Preparation

- On Windows, download and install the OpenSSL tool and configure environment variables.
- Prepare the packaging tool.
- Build version images using the packaging tool.
- On Linux, pack version images to generate the update package.
- To implement an A/B update, ensure that the devices running the standard system support booting from partitions A and B.


## OTA Update Guide


S
shawn_he 已提交
51
### Development Procedure
S
shawn_he 已提交
52

S
shawn_he 已提交
53
<a href="#generating-a-publicprivate-key-pair">1. Use the OpenSSL tool to generate a public/private key pair.
S
shawn_he 已提交
54 55 56

<a href="#making-an-update-package">2. Use the packaging tool to generate an update package.</a>

S
shawn_he 已提交
57
&ensp;&ensp;<a href="#mini-and-small-systems">2.1 Mini and small systems</a>
S
shawn_he 已提交
58

S
shawn_he 已提交
59
&ensp;&ensp;<a href="#standard-system">2.2 Standard system</a>
S
shawn_he 已提交
60

S
shawn_he 已提交
61
<a href="#uploading-the-update-package">3. Upload the update package to the vendor's OTA server.</a>
S
shawn_he 已提交
62 63 64

<a href="#downloading-the-update-package">4. Download the update package from the vendor's OTA server.</a>

S
shawn_he 已提交
65
<a href="#integrating-ota-update-capabilities">5. Integrate the OTA update capability.
S
shawn_he 已提交
66 67 68 69 70 71 72 73

&ensp;&ensp;<a href="#api-application-scenario-default">5.1 API application scenario (default)</a>

&ensp;&ensp;<a href="#api-application-scenario-custom">5.2 API application scenario (custom)</a>

&ensp;&ensp;<a href="#ab-update-scenario">5.3 A/B update scenario</a>


S
shawn_he 已提交
74
### How to Develop
S
shawn_he 已提交
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100


#### Generating a Public/Private Key Pair
1. Use the OpenSSL tool to generate a public/private key pair.

3. Keep the private key file properly as this file stores the private key used to sign the update package. You need to specify the private key file in the command used for preparing the update package. The public key is used to verify the signature of the update package during the update. For the mini and small systems, the generated public key is preset in the code. You need to implement the **HotaHalGetPubKey** API to obtain the key. For the standard system, the generated public key is stored in the **./device/hisilicon/hi3516dv300/build/updater_config/signing_cert.crt** file.

5. For the mini and small systems that use the Hi3518E V300 or Hi3516D V300 suite, use the content in **public\_arr.txt** to replace the content in **g\_pub\_key** in the **device\hisilicon\third_party\uboot\u-boot-2020.01\product\hiupdate\verify\update\_public\_key.c** file of the U-Boot module.
   Example configuration:

   ```c
   static unsigned char g_pub_key[PUBKEY_LEN] = {
       0x30, 0x82, 0x01, 0x0A, 0x02, 0x82, 0x01, 0x01,
       0x00, 0xBF, 0xAA, 0xA5, 0xB3, 0xC2, 0x78, 0x5E,
   }
   ```


#### Making an Update Package


##### Mini and Small Systems

1. Create the **target\_package** folder with the following directory structure:
     
   ```text
D
duangavin123 已提交
101
    target_package
S
shawn_he 已提交
102 103
    ├── OTA.tag
    ├── config
D
duangavin123 已提交
104 105 106 107 108
    ├── {component_1}
    ├── {component_2}
    ├── ...
    ├── {component_N}
    └── updater_config
S
shawn_he 已提交
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228
        └── updater_specified_config.xml
   ```

2. Place the components to be updated, including the image file (for example, **rootfs.img**), as **{component\_N}** in the root directory of the **target\_package** folder.

3. Configure the **updater\_specified\_config.xml** file in the **updater_config** folder.
   
   Example configuration:

     
   ```xml
   <?xml version="1.0"?>
   <package>
       <head name="Component header information">
           <info fileVersion="01" prdID="hisi" softVersion="OpenHarmony x.x" date="202x.xx.xx" time="xx:xx:xx">head info</info>
       </head>
       <group name="Component information">
       <component compAddr="ota_tag" compId="27" resType="5" compType="0" compVer="1.0">./OTA.tag</component>
       <component compAddr="config" compId="23" resType="5" compType="0" compVer="1.0">./config</component>
       <component compAddr="bootloader" compId="24" resType="5" compType="0" compVer="1.0">./u-boot-xxxx.bin</component>
       </group>
   </package>
   ```


   **Table 1** Description of nodes in the component configuration file
   
   | Type| Node Name| Node Label| Mandatory| Description| 
   | -------- | -------- | -------- | -------- | -------- |
   | Header information (head node)| info| / | Yes| Content of this node: head&nbsp;info| 
   | Header information (head node)| info| fileVersion | Yes| This field is reserved and does not affect the generation of the update package.| 
   | Header information (head node)| info| prdID | Yes| This field is reserved and does not affect the generation of the update package.| 
   | Header information (head node)| info| softVersion | Yes| Software version number, that is, the version number of the update package. The version number must be within the range specified by **VERSION.mbn**. Otherwise, an update package will not be generated.| 
   | Header information (head node)| info| date| Yes| Date when the update package is generated. This field is reserved and does not affect the generation of the update package.| 
   | Header information (head node)| info| time| Yes| Time when the update package is generated. This field is reserved and does not affect the generation of the update package.| 
   | Component information (group node)| component| / | Yes| Content of this node: path of the component or image file to be packed into the update package. It is the root directory of the version package by default.| 
   | Component information (group node)| component| compAddr | Yes| Name of the partition corresponding to the component, for example, **system** or **vendor**.| 
   | Component information (group node)| component| compId | Yes| Component ID, which must be unique.| 
   | Component information (group node)| component| resType | Yes| This field is reserved and does not affect the generation of the update package.| 
   | Component information (group node)| component| compType | Yes| Image type, which can be a full or differential package. The value **0** indicates a full package, and value **1** indicates a differential package.| 

   > **NOTE**
   > As mini and small systems do not support updating with a differential package, **compType** must be set to **0**, other than **1**.
   > 
   > For mini and small systems, an update package cannot be created by changing partitions.

4. Create the **OTA.tag** file, which contains the magic number of the update package. The magic number is fixed, as shown below:
     
   ```text
   package_type:ota1234567890qwertw
   ```

5. Create the **config** file, and configure the **bootargs** and **bootcmd** information in the file.
   Example configuration:

     
   ```text
   setenv bootargs 'mem=128M console=ttyAMA0,115200 root=/dev/mmcblk0p3 rw rootfstype=ext4 rootwait blkdevparts=mmcblk0:1M
   (u-boot.bin),9M(kernel.bin),50M(rootfs_ext4.img),50M(userfs.img)' setenv bootcmd 'mmc read 0x0 0x82000000 0x800 0x4800;bootm 0x82000000'
   ```

6. Generate the update package.
     
   ```text
   python build_update.py ./target_package/ ./output_package/ -pk ./rsa_private_key3072.pem -nz -nl2
   ```

   - **./target\_package/**: path of **target\_package**
   - **./output\_package/**: output path of the update package
   - -**pk ./rsa\_private\_key3072.pem**: path of the private key file
   - -**nz**: **not zip** mode
   - -**nl2**: non-standard system mode


##### Standard System

1. Create the **target\_package** folder with the following directory structure:

     
   ```text
   target_package
   ├── {component_1}
   ├── {component_2}
   ├── ...
   ├── {component_N}
   └── updater_config
           ├── BOARD.list
           ├── VERSION.mbn
           └── updater_specified_config.xml
   ```

2. Place the components to be updated, including the image file (for example, **system.img**), as **{component\_N}** in the root directory of the **target\_package** folder.

3. Configure the component configuration file in the **updater\_config** folder.

4. Configure the list of products supported by the current update package in **BOARD.list** in the **updater\_config** folder.

   Example configuration:

     
   ```text
   HI3516
   HI3518
   ```

5. Configure the versions supported by the current update package in **VERSION.mbn** in the **updater\_config** folder.

   Version number format: Hi3516DV300-eng 10 QP1A.XXXXXX.{Major version number (6 digits)}.XXX{Minor version number (3 digits)}

   For example, **Hi3516DV300-eng 10 QP1A.190711.020**, where **190711** is the major version number, and **020** is the minor version number.

   Example configuration:

     
   ```text
   Hi3516DV300-eng 10 QP1A.190711.001
   Hi3516DV300-eng 10 QP1A.190711.020
   Hi3518DV300-eng 10 QP1A.190711.021
   ```

S
shawn_he 已提交
229
6. For an update using the incremental (differential) package, also prepare a source version package (source\_package) in the same format as the target version package (target\_package), and then compress it as a **.zip** file, that is, **source\_package.zip**.
S
shawn_he 已提交
230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300

7. If you create an update package with partitions changed, also provide the partition table file named **partition\_file.xml**. You can specify the file using the **-pf** parameter. For details about the configuration nodes, see the description below.

   The partition table is generated with the image. The format is as follows:

     
   ```xml
   <?xml version="1.0" encoding="GB2312" ?>
   <Partition_Info>
   <Part Sel="1" PartitionName="Image 1" FlashType="Flash type" FileSystem="File system type" Start="Start address of the partition" Length="Size of the partition" SelectFile="Actual path of the image"/>
   <Part Sel="1" PartitionName="Image 2" FlashType="Flash type" FileSystem="File system type" Start="Start address of the partition" Length="Size of the partition" SelectFile="Actual path of the image"/>
   </Partition_Info>
   ```

   **Table 2** Description of labels in the partition table

   | Name | Description | 
   | ---- | ----------- |
   | Sel | Whether the partition is effective. The value **1** indicates that the partition is effective, and value **0** indicates the opposite.| 
   | PartitionName | Partition name, for example, **fastboot** or **boot**.| 
   | FlashType | Flash type, for example, **emmc** or **ufs**.| 
   | FileSystem | File system type, for example, **ext3/4** or **f2fs**. The value can also be **none**.| 
   | Start | Start address of the partition, in MB. The start address of all partitions is **0**.| 
   | Length | Size of the partition, in MB.| 
   | SelectFile | Actual path of the image or file.| 

8. Generate the update package.

   **Full package**

   Run the following command:

     
   ```text
   python build_update.py ./target_package/ ./output_package/ -pk ./rsa_private_key2048.pem
   ```

   - **./target\_package/**: path of **target\_package**
   - **./output\_package/**: output path of the update package
   - -**pk ./rsa\_private\_key3072.pem**: path of the private key file

   **Incremental (differential) package**

   Run the following command:

     
   ```text
   python build_update.py ./target_package/ ./output_package/  -s ./source_package.zip  -pk ./rsa_private_key2048.pem
   ```

   - **./target\_package/**: path of **target\_package**
   - **./output\_package/**: output path of the update package
   - -**s ./source\_package.zip**: path of the **source\_package.zip** file. For update using a differential package, use the **-s** parameter to specify the source version package.
   - -**pk ./rsa\_private\_key3072.pem**: path of the private key file

   **Update package with partitions changed**

   Run the following command:

     
   ```text
   python build_update.py  ./target_package/ ./output_package/  -pk ./rsa_private_key2048.pem  -pf ./partition_file.xml
   ```

   - **./target\_package/**: path of **target_package**
   - **./output\_package/**: output path of the update package
   - -**pk ./rsa\_private_key3072.pem**: path of the private key file
   - -**pf ./partition\_file.xml**: path of the partition table file


#### **Uploading the Update Package**
N
NEEN 已提交
301

D
duangavin123 已提交
302
Upload the update package to the vendor's OTA server.
N
NEEN 已提交
303 304


S
shawn_he 已提交
305 306 307
#### **Downloading the Update Package**

1. Download the update package from the OTA server.
N
NEEN 已提交
308

S
shawn_he 已提交
309
2. (Optional) Insert an SD card (with a capacity greater than 100 MB) if the device is developed based on Hi3518E V300 or Hi3516D V300.
N
NEEN 已提交
310 311


S
shawn_he 已提交
312
#### Integrating OTA Update Capabilities
N
NEEN 已提交
313

S
shawn_he 已提交
314
1. For mini and small systems
N
NEEN 已提交
315

S
shawn_he 已提交
316 317 318 319
   - Call the dynamic library **libhota.so**. The corresponding header files **hota\_partition.h** and **hota\_updater.h** are located in **base\update\ota_lite\interfaces\kits**.
   - The **libhota.so** source code is located in **base\update\ota_lite\frameworks\source**.
   - For details about how to use APIs, see *API Application Scenarios* and update APIs in *API Reference*.
   - If the development board needs to be adapted, see the **base\update\ota_lite\hals\hal\_hota\_board.h** file.
N
NEEN 已提交
320

S
shawn_he 已提交
321
2. For the standard system, see the [JS API Reference](../../application-dev/reference/apis/js-apis-update.md) for details.
N
NEEN 已提交
322 323


S
shawn_he 已提交
324
##### API Application Scenario (Default)
D
duangavin123 已提交
325 326 327 328

The update package is generated by following the instructions provided in Generating a Public/Private Key Pair and Generating an Update Package.


S
shawn_he 已提交
329
###### How to Develop
N
NEEN 已提交
330

S
shawn_he 已提交
331
1. Download the update package for the current device, and then call the **HotaInit** function to initialize the OTA module.
N
NEEN 已提交
332

S
shawn_he 已提交
333
2. Call the **HotaWrite** function to verify, parse, and write data streams for the update into the device.
N
NEEN 已提交
334

S
shawn_he 已提交
335
3. Call the **HotaRestart** function to restart the system for the update to take effect. Call the **HotaCancel** function if you want to cancel the update.
N
NEEN 已提交
336 337


S
shawn_he 已提交
338
###### Sample Code
N
NEEN 已提交
339

S
shawn_he 已提交
340 341 342
  Perform an OTA update using the update package format and verification method provided by OpenHarmony.
  
```cpp
N
NEEN 已提交
343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391
int main(int argc, char **argv)
{
    printf("this is update print!\r\n");
    if (HotaInit(NULL, NULL) < 0) {
        printf("ota update init fail!\r\n");
        return -1;
    }
    int fd = open(OTA_PKG_FILE, O_RDWR, S_IRUSR | S_IWUSR);
    if (fd < 0) {
        printf("file open failed, fd = %d\r\n", fd);
        (void)HotaCancel();
        return -1;
    }
    int offset = 0;
    int fileLen = lseek(fd, 0, SEEK_END);
    int leftLen = fileLen;
    while (leftLen > 0) {
        if (lseek(fd, offset, SEEK_SET) < 0) {
            close(fd);
            printf("lseek fail!\r\n");
            (void)HotaCancel();
            return -1;
        }
        int tmpLen = leftLen >= READ_BUF_LEN ? READ_BUF_LEN : leftLen;
        (void)memset_s(g_readBuf, READ_BUF_LEN, 0, READ_BUF_LEN);
        if (read(fd, g_readBuf, tmpLen) < 0) {
            close(fd);
            printf("read fail!\r\n");
            (void)HotaCancel();
            return -1;
        }
        if (HotaWrite((unsigned char *)g_readBuf, offset, tmpLen) != 0) {
            printf("ota write fail!\r\n");
            close(fd);
            (void)HotaCancel();
            return -1;
        }
        offset += READ_BUF_LEN;
        leftLen -= tmpLen;
    }
    close(fd);
    printf("ota write finish!\r\n");
    printf("device will reboot in 10s...\r\n");
    sleep(10);
    (void)HotaRestart();
    return 0;
}
```

D
duangavin123 已提交
392

S
shawn_he 已提交
393
##### API Application Scenario (Custom)
N
NEEN 已提交
394

S
shawn_he 已提交
395
The update package is generated in other ways instead of following the instructions provided in "Generating a Public/Private Key Pair" and "Generating an Update Package."
N
NEEN 已提交
396 397


S
shawn_he 已提交
398
###### How to Develop
D
duangavin123 已提交
399

S
shawn_he 已提交
400
1. Download the update package for the current device, and then call the **HotaInit** function to initialize the OTA module.
N
NEEN 已提交
401

S
shawn_he 已提交
402
2. Call the **HotaSetPackageType** function to set the package type to **NOT\_USE\_DEFAULT\_PKG**.
D
duangavin123 已提交
403

S
shawn_he 已提交
404
3. Call the **HotaWrite** function to write data streams into the device.
D
duangavin123 已提交
405

S
shawn_he 已提交
406
4. Call the **HotaRead** function to read data. Vendors can choose whether to verify the data.
N
NEEN 已提交
407

S
shawn_he 已提交
408
5. (Optional) Call the **HotaSetBootSettings** function to set the startup tag used for entering the U-Boot mode during system restarting.
N
NEEN 已提交
409

S
shawn_he 已提交
410
6. Call the **HotaRestart** function to restart the system for the update to take effect. Call the **HotaCancel** function if you want to cancel the update.
N
NEEN 已提交
411 412


S
shawn_he 已提交
413 414 415 416 417
###### Sample Code

  Perform an OTA update using the update package format and verification method not provided by OpenHarmony.
  
```cpp
N
NEEN 已提交
418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465
int main(int argc, char **argv)
{
    printf("this is update print!\r\n");
    if (HotaInit(NULL, NULL) < 0) {
        printf("ota update init fail!\r\n");
        (void)HotaCancel();
        return -1;
    }
    (void)HotaSetPackageType(NOT_USE_DEFAULT_PKG);
    int fd = open(OTA_PKG_FILE, O_RDWR, S_IRUSR | S_IWUSR);
    if (fd < 0) {
        printf("file open failed, fd = %d\r\n", fd);
        (void)HotaCancel();
        return -1;
    }
    int offset = 0;
    int fileLen = lseek(fd, 0, SEEK_END);
    int leftLen = fileLen;
    while (leftLen > 0) {
        if (lseek(fd, offset, SEEK_SET) < 0) {
            close(fd);
            printf("lseek fail!\r\n");
            (void)HotaCancel();
            return -1;
        }
        int tmpLen = leftLen >= READ_BUF_LEN ? READ_BUF_LEN : leftLen;
        (void)memset_s(g_readBuf, READ_BUF_LEN, 0, READ_BUF_LEN);
        if (read(fd, g_readBuf, tmpLen) < 0) {
            close(fd);
            printf("read fail!\r\n");
            (void)HotaCancel();
            return -1;
        }
        if (HotaWrite((unsigned char *)g_readBuf, offset, tmpLen) != 0) {
            printf("ota write fail!\r\n");
            close(fd);
            (void)HotaCancel();
            return -1;
        }
        offset += READ_BUF_LEN;
        leftLen -= tmpLen;
    }
    close(fd);
    printf("ota write finish!\r\n");
    leftLen = fileLen;
    while (leftLen > 0) {
        int tmpLen = leftLen >= READ_BUF_LEN ? READ_BUF_LEN : leftLen;
        (void)memset_s(g_readBuf, READ_BUF_LEN, 0, READ_BUF_LEN);
S
shawn_he 已提交
466
        if (HotaRead(offset, READ_BUF_LEN, (unsigned char *)g_readBuf) != 0) {
N
NEEN 已提交
467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484
            printf("ota write fail!\r\n");
            (void)HotaCancel();
            return -1;
        }
        /* do your verify and parse */
        offset += READ_BUF_LEN;
        leftLen -= tmpLen;
    }
    /* set your boot settings */
    (void)HotaSetBootSettings();
    printf("device will reboot in 10s...\r\n");
    sleep(10);
    (void)HotaRestart();
    return 0;
}
```


S
shawn_he 已提交
485
###### System Updating
N
NEEN 已提交
486

S
shawn_he 已提交
487
An application calls APIs of the OTA module to perform functions such as signature verification of the update package, anti-rollback, as well as burning and flushing to disk. After the update is complete, the system automatically restarts.
N
NEEN 已提交
488

S
shawn_he 已提交
489
For the mini and small systems that use the Hi3518E V300 or Hi3516D V300 open source suite, add the value of **LOCAL\_VERSION** to the version that needs to implement the anti-rollback function. For example, for **"ohos default 1.0"-&gt;"ohos default 1.1"**, add the value of **LOCAL\_VERSION** in **device\hisilicon\third\_party\uboot\u-boot-2020.01\product\hiupdate\ota\_update\ota\_local_info.c**.
N
NEEN 已提交
490

S
shawn_he 已提交
491 492 493
  Example configuration:
  
```cpp
N
NEEN 已提交
494 495 496
const char *get_local_version(void)
{
#if defined(CONFIG_TARGET_HI3516EV200) || \
D
duangavin123 已提交
497 498
    defined(CONFIG_TARGET_HI3516DV300) || \
    defined(CONFIG_TARGET_HI3518EV300)
N
NEEN 已提交
499 500 501
#define LOCAL_VERSION "ohos default 1.0" /* increase: default release version */
```

S
shawn_he 已提交
502 503 504 505

##### A/B Update Scenario


S
shawn_he 已提交
506
###### Development Procedure
S
shawn_he 已提交
507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586

1. Download the update package through the update application.
2. Invoke update_service to start the system installation service through SAMGR.
3. Let the system installation service perform a silent update.
4. Activate the new version upon restarting.


###### How to Develop

- Invoke update_service to call JS APIs to implement the related service logic in an A/B update.

   1. Displaying the update package installation progress:
   ```cpp
   on(eventType: "upgradeProgress", callback: UpdateProgressCallback): void;
   ```
   
   2. Setting the activation policy (immediate restart, restart at night, and activation on next restart):
   ```cpp
   upgrade(apply)
   ```


- Invoke update_service to start the system installation service through SAMGR.
   
   1. Start the system installation service and set up an IPC connection.
   ```cpp
   int SysInstallerInit(void * callback)
   ```
   
   2. Install the A/B update package in the specified path.
   ```cpp
   int StartUpdatePackageZip(string path)
   ```
   
   3. Set the update progress callback.
   ```cpp
   int SetUpdateProgressCallback(void * callback)
   ```
   
   4. Obtain the installation status of the update package (0: not started; 1: installing; 2: installed).
   ```cpp
   int GetUpdateStatus()
   ```


- Use HDI APIs to activate the new version.

   1. Obtain the current boot slot to determine the partition to be updated.
   ```cpp
   int GetCurrentSlot()
   ```
   
   2. Upon completion of the update, switch the updated slot and restart the system for the new version to take effect.
   ```cpp
   int SetActiveBootSlot(int slot)
   ```
   
   3. Upon starting of the update, set the slot of the partition to be updated to the **unbootable** state.
   ```cpp
   int setSlotUnbootable(int slot)
   ```
   
   4. Obtain the number of slots. The value **1** indicates a common update, and the value **2** indicates an A/B update.
   ```cpp
   int32 GetSlotNum(void)
   ```


###### FAQs

1. An exception occurs during installation of the update package.
<br>The system keeps running with the current version. It will attempt a new update in the next package search period.

2. An exception occurs during activation of the new version if the update package is installed in a non-boot partition.
<br>Perform a rollback and set the partition to the **unbootable** state so that the system does not boot from this partition.


###### Verification

In normal cases, the device can download the update package from the OTA server in the background, perform a silent update, and then restart according to the preconfigured activation policy for the new version to take effect.