1fb299fa2Sopenharmony_ci/*
2fb299fa2Sopenharmony_ci * Copyright (c) 2021-2023 Huawei Device Co., Ltd.
3fb299fa2Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4fb299fa2Sopenharmony_ci * you may not use this file except in compliance with the License.
5fb299fa2Sopenharmony_ci * You may obtain a copy of the License at
6fb299fa2Sopenharmony_ci *
7fb299fa2Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8fb299fa2Sopenharmony_ci *
9fb299fa2Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10fb299fa2Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11fb299fa2Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12fb299fa2Sopenharmony_ci * See the License for the specific language governing permissions and
13fb299fa2Sopenharmony_ci * limitations under the License.
14fb299fa2Sopenharmony_ci */
15fb299fa2Sopenharmony_ci#include "updater_main.h"
16fb299fa2Sopenharmony_ci#include <chrono>
17fb299fa2Sopenharmony_ci#include <dirent.h>
18fb299fa2Sopenharmony_ci#include <fcntl.h>
19fb299fa2Sopenharmony_ci#include <getopt.h>
20fb299fa2Sopenharmony_ci#include <libgen.h>
21fb299fa2Sopenharmony_ci#include <string>
22fb299fa2Sopenharmony_ci#include <sys/mount.h>
23fb299fa2Sopenharmony_ci#include <sys/reboot.h>
24fb299fa2Sopenharmony_ci#include <sys/stat.h>
25fb299fa2Sopenharmony_ci#include <sys/statvfs.h>
26fb299fa2Sopenharmony_ci#include <sys/syscall.h>
27fb299fa2Sopenharmony_ci#include <thread>
28fb299fa2Sopenharmony_ci#include <unistd.h>
29fb299fa2Sopenharmony_ci#include <vector>
30fb299fa2Sopenharmony_ci#include "applypatch/partition_record.h"
31fb299fa2Sopenharmony_ci#include "cert_verify.h"
32fb299fa2Sopenharmony_ci#include "flashd/flashd.h"
33fb299fa2Sopenharmony_ci#include "fs_manager/mount.h"
34fb299fa2Sopenharmony_ci#include "include/updater/updater.h"
35fb299fa2Sopenharmony_ci#include "json_node.h"
36fb299fa2Sopenharmony_ci#include "language/language_ui.h"
37fb299fa2Sopenharmony_ci#include "log/dump.h"
38fb299fa2Sopenharmony_ci#include "log/log.h"
39fb299fa2Sopenharmony_ci#include "misc_info/misc_info.h"
40fb299fa2Sopenharmony_ci#include "package/pkg_manager.h"
41fb299fa2Sopenharmony_ci#include "pkg_manager.h"
42fb299fa2Sopenharmony_ci#include "pkg_utils.h"
43fb299fa2Sopenharmony_ci#include "ptable_parse/ptable_process.h"
44fb299fa2Sopenharmony_ci#include "sdcard_update/sdcard_update.h"
45fb299fa2Sopenharmony_ci#include "securec.h"
46fb299fa2Sopenharmony_ci#include "updater/updater_const.h"
47fb299fa2Sopenharmony_ci#include "updater/hwfault_retry.h"
48fb299fa2Sopenharmony_ci#include "updater/updater_preprocess.h"
49fb299fa2Sopenharmony_ci#include "updater_ui_stub.h"
50fb299fa2Sopenharmony_ci#include "utils.h"
51fb299fa2Sopenharmony_ci#include "factory_reset/factory_reset.h"
52fb299fa2Sopenharmony_ci#include "write_state/write_state.h"
53fb299fa2Sopenharmony_ci
54fb299fa2Sopenharmony_cinamespace Updater {
55fb299fa2Sopenharmony_ciusing Utils::String2Int;
56fb299fa2Sopenharmony_ciusing namespace Hpackage;
57fb299fa2Sopenharmony_ciusing namespace Updater::Utils;
58fb299fa2Sopenharmony_ciusing namespace std::literals::chrono_literals;
59fb299fa2Sopenharmony_ci
60fb299fa2Sopenharmony_ci[[maybe_unused]] constexpr int DISPLAY_TIME = 1000 * 1000;
61fb299fa2Sopenharmony_ciconstexpr struct option OPTIONS[] = {
62fb299fa2Sopenharmony_ci    { "update_package", required_argument, nullptr, 0 },
63fb299fa2Sopenharmony_ci    { "retry_count", required_argument, nullptr, 0 },
64fb299fa2Sopenharmony_ci    { "factory_wipe_data", no_argument, nullptr, 0 },
65fb299fa2Sopenharmony_ci    { "user_wipe_data", no_argument, nullptr, 0 },
66fb299fa2Sopenharmony_ci    { "menu_wipe_data", no_argument, nullptr, 0 },
67fb299fa2Sopenharmony_ci    { "sdcard_update", no_argument, nullptr, 0 },
68fb299fa2Sopenharmony_ci    { "upgraded_pkg_num", required_argument, nullptr, 0 },
69fb299fa2Sopenharmony_ci    { "force_update_action", required_argument, nullptr, 0 },
70fb299fa2Sopenharmony_ci    { "night_update", no_argument, nullptr, 0 },
71fb299fa2Sopenharmony_ci    { USB_MODE, no_argument, nullptr, 0 },
72fb299fa2Sopenharmony_ci    { "UPDATE:MAINIMG", no_argument, nullptr, 0 },
73fb299fa2Sopenharmony_ci    { "update_protect", no_argument, nullptr, 0 },
74fb299fa2Sopenharmony_ci    { "factory_sd_update", no_argument, nullptr, 0 },
75fb299fa2Sopenharmony_ci    { "UPDATE:SD", no_argument, nullptr, 0 },
76fb299fa2Sopenharmony_ci    { "UPDATE:SDFROMDEV", no_argument, nullptr, 0 },
77fb299fa2Sopenharmony_ci    { "sdcard_intral_update", optional_argument, nullptr, 0},
78fb299fa2Sopenharmony_ci    {"wipe_data_factory_lowlevel", no_argument, nullptr, 0},
79fb299fa2Sopenharmony_ci    { "wipe_data_at_factoryreset_0", no_argument, nullptr, 0 },
80fb299fa2Sopenharmony_ci    { nullptr, 0, nullptr, 0 },
81fb299fa2Sopenharmony_ci};
82fb299fa2Sopenharmony_ciconstexpr float VERIFY_PERCENT = 0.05;
83fb299fa2Sopenharmony_ciconstexpr double FULL_PERCENT = 100.00;
84fb299fa2Sopenharmony_ci
85fb299fa2Sopenharmony_ciint FactoryReset(FactoryResetMode mode, const std::string &path)
86fb299fa2Sopenharmony_ci{
87fb299fa2Sopenharmony_ci    UpdaterInit::GetInstance().InvokeEvent(FACTORY_RESET_INIT_EVENT);
88fb299fa2Sopenharmony_ci    auto ret = FactoryResetProcess::GetInstance().FactoryResetFunc(mode, path);
89fb299fa2Sopenharmony_ci    if (ret == 0) {
90fb299fa2Sopenharmony_ci        LOG(INFO) << "restorecon for " << path;
91fb299fa2Sopenharmony_ci        RestoreconPath(path); // restore selinux context for /data after factory reset success
92fb299fa2Sopenharmony_ci    }
93fb299fa2Sopenharmony_ci    return ret;
94fb299fa2Sopenharmony_ci}
95fb299fa2Sopenharmony_ci
96fb299fa2Sopenharmony_cistatic int OtaUpdatePreCheck(PkgManager::PkgManagerPtr pkgManager, const std::string &packagePath)
97fb299fa2Sopenharmony_ci{
98fb299fa2Sopenharmony_ci    UPDATER_INIT_RECORD;
99fb299fa2Sopenharmony_ci    if (pkgManager == nullptr) {
100fb299fa2Sopenharmony_ci        LOG(ERROR) << "pkgManager is nullptr";
101fb299fa2Sopenharmony_ci        UPDATER_LAST_WORD(PKG_INVALID_FILE);
102fb299fa2Sopenharmony_ci        return UPDATE_CORRUPT;
103fb299fa2Sopenharmony_ci    }
104fb299fa2Sopenharmony_ci    char realPath[PATH_MAX + 1] = {0};
105fb299fa2Sopenharmony_ci    if (realpath(packagePath.c_str(), realPath) == nullptr) {
106fb299fa2Sopenharmony_ci        LOG(ERROR) << "realpath error";
107fb299fa2Sopenharmony_ci        UPDATER_LAST_WORD(PKG_INVALID_FILE);
108fb299fa2Sopenharmony_ci        return PKG_INVALID_FILE;
109fb299fa2Sopenharmony_ci    }
110fb299fa2Sopenharmony_ci    if (access(realPath, F_OK) != 0) {
111fb299fa2Sopenharmony_ci        LOG(ERROR) << "package does not exist!";
112fb299fa2Sopenharmony_ci        UPDATER_LAST_WORD(PKG_INVALID_FILE);
113fb299fa2Sopenharmony_ci        return PKG_INVALID_FILE;
114fb299fa2Sopenharmony_ci    }
115fb299fa2Sopenharmony_ci
116fb299fa2Sopenharmony_ci    int32_t ret = pkgManager->VerifyOtaPackage(packagePath);
117fb299fa2Sopenharmony_ci    if (ret != PKG_SUCCESS) {
118fb299fa2Sopenharmony_ci        LOG(INFO) << "VerifyOtaPackage fail ret :"<< ret;
119fb299fa2Sopenharmony_ci        UPDATER_LAST_WORD("sign", ret);
120fb299fa2Sopenharmony_ci        return ret;
121fb299fa2Sopenharmony_ci    }
122fb299fa2Sopenharmony_ci
123fb299fa2Sopenharmony_ci    return UPDATE_SUCCESS;
124fb299fa2Sopenharmony_ci}
125fb299fa2Sopenharmony_ci
126fb299fa2Sopenharmony_cistatic UpdaterStatus UpdatePreCheck(UpdaterParams &upParams, const std::string pkgPath)
127fb299fa2Sopenharmony_ci{
128fb299fa2Sopenharmony_ci    UPDATER_INIT_RECORD;
129fb299fa2Sopenharmony_ci    int32_t ret = PreProcess::GetInstance().DoUpdateAuth(pkgPath);
130fb299fa2Sopenharmony_ci    if (ret != 0) {
131fb299fa2Sopenharmony_ci        return UPDATE_ERROR;
132fb299fa2Sopenharmony_ci    }
133fb299fa2Sopenharmony_ci
134fb299fa2Sopenharmony_ci    PkgManager::PkgManagerPtr pkgManager = PkgManager::CreatePackageInstance();
135fb299fa2Sopenharmony_ci    if (pkgManager == nullptr) {
136fb299fa2Sopenharmony_ci        LOG(ERROR) << "CreatePackageInstance fail";
137fb299fa2Sopenharmony_ci        return UPDATE_ERROR;
138fb299fa2Sopenharmony_ci    }
139fb299fa2Sopenharmony_ci    if (GetUpdatePackageInfo(pkgManager, pkgPath) != PKG_SUCCESS) {
140fb299fa2Sopenharmony_ci        PkgManager::ReleasePackageInstance(pkgManager);
141fb299fa2Sopenharmony_ci        LOG(ERROR) << "Verify update bin file Fail!";
142fb299fa2Sopenharmony_ci        UPDATER_LAST_WORD(UPDATE_ERROR);
143fb299fa2Sopenharmony_ci        return UPDATE_ERROR;
144fb299fa2Sopenharmony_ci    }
145fb299fa2Sopenharmony_ci    if (PreProcess::GetInstance().DoUpdatePreProcess(upParams, pkgManager) != PKG_SUCCESS) {
146fb299fa2Sopenharmony_ci        PkgManager::ReleasePackageInstance(pkgManager);
147fb299fa2Sopenharmony_ci        LOG(ERROR) << "Version Check Fail!";
148fb299fa2Sopenharmony_ci        UPDATER_LAST_WORD(UPDATE_ERROR);
149fb299fa2Sopenharmony_ci        return UPDATE_ERROR;
150fb299fa2Sopenharmony_ci    }
151fb299fa2Sopenharmony_ci    if (PreProcess::GetInstance().DoUpdateClear() != 0) {
152fb299fa2Sopenharmony_ci        LOG(ERROR) << "DoUpdateClear Fail!";
153fb299fa2Sopenharmony_ci    }
154fb299fa2Sopenharmony_ci    PkgManager::ReleasePackageInstance(pkgManager);
155fb299fa2Sopenharmony_ci    return UPDATE_SUCCESS;
156fb299fa2Sopenharmony_ci}
157fb299fa2Sopenharmony_ci
158fb299fa2Sopenharmony_ci__attribute__((weak)) int32_t VerifySpecialPkgs([[maybe_unused]]UpdaterParams &upParams)
159fb299fa2Sopenharmony_ci{
160fb299fa2Sopenharmony_ci    return PKG_SUCCESS;
161fb299fa2Sopenharmony_ci}
162fb299fa2Sopenharmony_ci
163fb299fa2Sopenharmony_ci__attribute__((weak)) void UpdaterVerifyFailEntry(bool verifyret)
164fb299fa2Sopenharmony_ci{
165fb299fa2Sopenharmony_ci    LOG(INFO) << "pre verify package info process";
166fb299fa2Sopenharmony_ci    return;
167fb299fa2Sopenharmony_ci}
168fb299fa2Sopenharmony_ci
169fb299fa2Sopenharmony_cistatic UpdaterStatus VerifyPackages(UpdaterParams &upParams)
170fb299fa2Sopenharmony_ci{
171fb299fa2Sopenharmony_ci    LOG(INFO) << "Verify packages start...";
172fb299fa2Sopenharmony_ci    UPDATER_UI_INSTANCE.ShowProgressPage();
173fb299fa2Sopenharmony_ci    UPDATER_UI_INSTANCE.ShowUpdInfo(TR(UPD_VERIFYPKG));
174fb299fa2Sopenharmony_ci
175fb299fa2Sopenharmony_ci    if (upParams.callbackProgress == nullptr) {
176fb299fa2Sopenharmony_ci        UPDATER_UI_INSTANCE.ShowUpdInfo(TR(UPD_VERIFYPKGFAIL), true);
177fb299fa2Sopenharmony_ci        UPDATER_LAST_WORD(UPDATE_CORRUPT);
178fb299fa2Sopenharmony_ci        return UPDATE_CORRUPT;
179fb299fa2Sopenharmony_ci    }
180fb299fa2Sopenharmony_ci    upParams.callbackProgress(0.0);
181fb299fa2Sopenharmony_ci    upParams.installTime.resize(upParams.updatePackage.size(), std::chrono::duration<double>(0));
182fb299fa2Sopenharmony_ci    ReadInstallTime(upParams);
183fb299fa2Sopenharmony_ci    for (unsigned int i = upParams.pkgLocation; i < upParams.updatePackage.size(); i++) {
184fb299fa2Sopenharmony_ci        LOG(INFO) << "Verify package:" << upParams.updatePackage[i];
185fb299fa2Sopenharmony_ci        auto startTime = std::chrono::system_clock::now();
186fb299fa2Sopenharmony_ci        PkgManager::PkgManagerPtr manager = PkgManager::CreatePackageInstance();
187fb299fa2Sopenharmony_ci        if (manager == nullptr) {
188fb299fa2Sopenharmony_ci            LOG(ERROR) << "CreatePackageInstance fail";
189fb299fa2Sopenharmony_ci            return UPDATE_ERROR;
190fb299fa2Sopenharmony_ci        }
191fb299fa2Sopenharmony_ci        int32_t verifyret = OtaUpdatePreCheck(manager, upParams.updatePackage[i]);
192fb299fa2Sopenharmony_ci        PkgManager::ReleasePackageInstance(manager);
193fb299fa2Sopenharmony_ci        if (verifyret == UPDATE_SUCCESS) {
194fb299fa2Sopenharmony_ci            verifyret = UpdatePreCheck(upParams, upParams.updatePackage[i]);
195fb299fa2Sopenharmony_ci        }
196fb299fa2Sopenharmony_ci
197fb299fa2Sopenharmony_ci        if (verifyret != UPDATE_SUCCESS) {
198fb299fa2Sopenharmony_ci            UpdaterVerifyFailEntry((verifyret == PKG_INVALID_DIGEST) && (upParams.updateMode == HOTA_UPDATE));
199fb299fa2Sopenharmony_ci            upParams.pkgLocation = i;
200fb299fa2Sopenharmony_ci            UPDATER_UI_INSTANCE.ShowUpdInfo(TR(UPD_VERIFYPKGFAIL), true);
201fb299fa2Sopenharmony_ci            auto endTime = std::chrono::system_clock::now();
202fb299fa2Sopenharmony_ci            upParams.installTime[i] = endTime - startTime;
203fb299fa2Sopenharmony_ci            return UPDATE_CORRUPT;
204fb299fa2Sopenharmony_ci        }
205fb299fa2Sopenharmony_ci        auto endTime = std::chrono::system_clock::now();
206fb299fa2Sopenharmony_ci        upParams.installTime[i] = endTime - startTime;
207fb299fa2Sopenharmony_ci    }
208fb299fa2Sopenharmony_ci    if (VerifySpecialPkgs(upParams) != PKG_SUCCESS) {
209fb299fa2Sopenharmony_ci        UPDATER_LAST_WORD(UPDATE_CORRUPT);
210fb299fa2Sopenharmony_ci        return UPDATE_CORRUPT;
211fb299fa2Sopenharmony_ci    }
212fb299fa2Sopenharmony_ci    ProgressSmoothHandler(UPDATER_UI_INSTANCE.GetCurrentPercent(),
213fb299fa2Sopenharmony_ci        UPDATER_UI_INSTANCE.GetCurrentPercent() + static_cast<int>(VERIFY_PERCENT * FULL_PERCENT_PROGRESS));
214fb299fa2Sopenharmony_ci    LOG(INFO) << "Verify packages successfull...";
215fb299fa2Sopenharmony_ci    return UPDATE_SUCCESS;
216fb299fa2Sopenharmony_ci}
217fb299fa2Sopenharmony_ci
218fb299fa2Sopenharmony_cibool GetBatteryCapacity(int &capacity)
219fb299fa2Sopenharmony_ci{
220fb299fa2Sopenharmony_ci    const static std::vector<const char *> vec = {
221fb299fa2Sopenharmony_ci        "/sys/class/power_supply/battery/capacity",
222fb299fa2Sopenharmony_ci        "/sys/class/power_supply/Battery/capacity"
223fb299fa2Sopenharmony_ci    };
224fb299fa2Sopenharmony_ci    for (auto &it : vec) {
225fb299fa2Sopenharmony_ci        std::ifstream ifs { it };
226fb299fa2Sopenharmony_ci        if (!ifs.is_open()) {
227fb299fa2Sopenharmony_ci            continue;
228fb299fa2Sopenharmony_ci        }
229fb299fa2Sopenharmony_ci
230fb299fa2Sopenharmony_ci        int tmpCapacity = 0;
231fb299fa2Sopenharmony_ci        ifs >> tmpCapacity;
232fb299fa2Sopenharmony_ci        if ((ifs.fail()) || (ifs.bad())) {
233fb299fa2Sopenharmony_ci            continue;
234fb299fa2Sopenharmony_ci        }
235fb299fa2Sopenharmony_ci
236fb299fa2Sopenharmony_ci        capacity = tmpCapacity;
237fb299fa2Sopenharmony_ci        return true;
238fb299fa2Sopenharmony_ci    }
239fb299fa2Sopenharmony_ci
240fb299fa2Sopenharmony_ci    return false;
241fb299fa2Sopenharmony_ci}
242fb299fa2Sopenharmony_ci
243fb299fa2Sopenharmony_cibool IsBatteryCapacitySufficient()
244fb299fa2Sopenharmony_ci{
245fb299fa2Sopenharmony_ci    if (Utils::CheckUpdateMode(OTA_MODE)) {
246fb299fa2Sopenharmony_ci        LOG(INFO) << "this is OTA update, on need to determine the battery";
247fb299fa2Sopenharmony_ci        return true;
248fb299fa2Sopenharmony_ci    }
249fb299fa2Sopenharmony_ci    static constexpr auto levelIdx = "lowBatteryLevel";
250fb299fa2Sopenharmony_ci    static constexpr auto jsonPath = "/etc/product_cfg.json";
251fb299fa2Sopenharmony_ci
252fb299fa2Sopenharmony_ci    int capacity = 0;
253fb299fa2Sopenharmony_ci    bool ret = GetBatteryCapacity(capacity);
254fb299fa2Sopenharmony_ci    if (!ret) {
255fb299fa2Sopenharmony_ci        return true; /* maybe no battery or err value return default true */
256fb299fa2Sopenharmony_ci    }
257fb299fa2Sopenharmony_ci
258fb299fa2Sopenharmony_ci    JsonNode node { Fs::path { jsonPath }};
259fb299fa2Sopenharmony_ci    auto item = node[levelIdx].As<int>();
260fb299fa2Sopenharmony_ci    if (!item.has_value()) {
261fb299fa2Sopenharmony_ci        return true; /* maybe no value return default true */
262fb299fa2Sopenharmony_ci    }
263fb299fa2Sopenharmony_ci
264fb299fa2Sopenharmony_ci    int lowLevel = *item;
265fb299fa2Sopenharmony_ci    if (lowLevel > 100 || lowLevel < 0) { /* full percent is 100 */
266fb299fa2Sopenharmony_ci        LOG(ERROR) << "load battery level error:" << lowLevel;
267fb299fa2Sopenharmony_ci        return false; /* config err not allow to update */
268fb299fa2Sopenharmony_ci    }
269fb299fa2Sopenharmony_ci
270fb299fa2Sopenharmony_ci    LOG(INFO) << "current capacity:" << capacity << ", low level:" << lowLevel;
271fb299fa2Sopenharmony_ci
272fb299fa2Sopenharmony_ci    return capacity >= lowLevel;
273fb299fa2Sopenharmony_ci}
274fb299fa2Sopenharmony_ci
275fb299fa2Sopenharmony_ciUpdaterStatus InstallUpdaterPackage(UpdaterParams &upParams, PkgManager::PkgManagerPtr manager)
276fb299fa2Sopenharmony_ci{
277fb299fa2Sopenharmony_ci    UpdaterStatus status = UPDATE_UNKNOWN;
278fb299fa2Sopenharmony_ci    STAGE(UPDATE_STAGE_BEGIN) << "Install package";
279fb299fa2Sopenharmony_ci    if (upParams.retryCount == 0) {
280fb299fa2Sopenharmony_ci        // First time enter updater, record retryCount in case of abnormal reset.
281fb299fa2Sopenharmony_ci        if (!PartitionRecord::GetInstance().ClearRecordPartitionOffset()) {
282fb299fa2Sopenharmony_ci            LOG(ERROR) << "ClearRecordPartitionOffset failed";
283fb299fa2Sopenharmony_ci            UPDATER_LAST_WORD(UPDATE_ERROR);
284fb299fa2Sopenharmony_ci            return UPDATE_ERROR;
285fb299fa2Sopenharmony_ci        }
286fb299fa2Sopenharmony_ci        SetMessageToMisc(upParams.miscCmd, upParams.retryCount + 1, "retry_count");
287fb299fa2Sopenharmony_ci    }
288fb299fa2Sopenharmony_ci    if (upParams.updateMode == SDCARD_UPDATE) {
289fb299fa2Sopenharmony_ci        status = DoInstallUpdaterPackage(manager, upParams, SDCARD_UPDATE);
290fb299fa2Sopenharmony_ci    } else {
291fb299fa2Sopenharmony_ci        status = DoInstallUpdaterPackage(manager, upParams, HOTA_UPDATE);
292fb299fa2Sopenharmony_ci    }
293fb299fa2Sopenharmony_ci    if (status != UPDATE_SUCCESS) {
294fb299fa2Sopenharmony_ci        UPDATER_UI_INSTANCE.Sleep(UI_SHOW_DURATION);
295fb299fa2Sopenharmony_ci        UPDATER_UI_INSTANCE.ShowLog(TR(LOG_UPDFAIL));
296fb299fa2Sopenharmony_ci        STAGE(UPDATE_STAGE_FAIL) << "Install failed";
297fb299fa2Sopenharmony_ci        if (status == UPDATE_RETRY) {
298fb299fa2Sopenharmony_ci            HwFaultRetry::GetInstance().DoRetryAction();
299fb299fa2Sopenharmony_ci            UPDATER_UI_INSTANCE.ShowFailedPage();
300fb299fa2Sopenharmony_ci        }
301fb299fa2Sopenharmony_ci    } else {
302fb299fa2Sopenharmony_ci        LOG(INFO) << "Install package success.";
303fb299fa2Sopenharmony_ci        STAGE(UPDATE_STAGE_SUCCESS) << "Install package";
304fb299fa2Sopenharmony_ci    }
305fb299fa2Sopenharmony_ci    return status;
306fb299fa2Sopenharmony_ci}
307fb299fa2Sopenharmony_ci
308fb299fa2Sopenharmony_cistatic UpdaterStatus CalcProgress(const UpdaterParams &upParams,
309fb299fa2Sopenharmony_ci    std::vector<double> &pkgStartPosition, double &updateStartPosition)
310fb299fa2Sopenharmony_ci{
311fb299fa2Sopenharmony_ci    UPDATER_INIT_RECORD;
312fb299fa2Sopenharmony_ci    int64_t allPkgSize = 0;
313fb299fa2Sopenharmony_ci    std::vector<int64_t> everyPkgSize;
314fb299fa2Sopenharmony_ci    if (upParams.pkgLocation == upParams.updatePackage.size()) {
315fb299fa2Sopenharmony_ci        updateStartPosition = VERIFY_PERCENT;
316fb299fa2Sopenharmony_ci        return UPDATE_SUCCESS;
317fb299fa2Sopenharmony_ci    }
318fb299fa2Sopenharmony_ci    for (const auto &path : upParams.updatePackage) {
319fb299fa2Sopenharmony_ci        char realPath[PATH_MAX + 1] = {0};
320fb299fa2Sopenharmony_ci        if (realpath(path.c_str(), realPath) == nullptr) {
321fb299fa2Sopenharmony_ci            LOG(WARNING) << "Can not find updatePackage : " << path;
322fb299fa2Sopenharmony_ci            everyPkgSize.push_back(0);
323fb299fa2Sopenharmony_ci            continue;
324fb299fa2Sopenharmony_ci        }
325fb299fa2Sopenharmony_ci        struct stat st {};
326fb299fa2Sopenharmony_ci        if (stat(realPath, &st) == 0) {
327fb299fa2Sopenharmony_ci            everyPkgSize.push_back(st.st_size);
328fb299fa2Sopenharmony_ci            allPkgSize += st.st_size;
329fb299fa2Sopenharmony_ci            LOG(INFO) << "pkg " << path << " size is:" << st.st_size;
330fb299fa2Sopenharmony_ci        }
331fb299fa2Sopenharmony_ci    }
332fb299fa2Sopenharmony_ci    pkgStartPosition.push_back(VERIFY_PERCENT);
333fb299fa2Sopenharmony_ci    if (allPkgSize == 0) {
334fb299fa2Sopenharmony_ci        LOG(ERROR) << "All packages's size is 0.";
335fb299fa2Sopenharmony_ci        UPDATER_LAST_WORD(UPDATE_ERROR);
336fb299fa2Sopenharmony_ci        return UPDATE_ERROR;
337fb299fa2Sopenharmony_ci    }
338fb299fa2Sopenharmony_ci    int64_t startSize = 0;
339fb299fa2Sopenharmony_ci    for (auto size : everyPkgSize) {
340fb299fa2Sopenharmony_ci        startSize += size;
341fb299fa2Sopenharmony_ci        float percent = static_cast<double>(startSize) / static_cast<double>(allPkgSize) + VERIFY_PERCENT;
342fb299fa2Sopenharmony_ci        percent = (percent > 1.0) ? 1.0 : percent; // 1.0 : 100%
343fb299fa2Sopenharmony_ci        LOG(INFO) << "percent is:" << percent;
344fb299fa2Sopenharmony_ci        pkgStartPosition.push_back(percent);
345fb299fa2Sopenharmony_ci    }
346fb299fa2Sopenharmony_ci
347fb299fa2Sopenharmony_ci    updateStartPosition = pkgStartPosition[upParams.pkgLocation];
348fb299fa2Sopenharmony_ci    return UPDATE_SUCCESS;
349fb299fa2Sopenharmony_ci}
350fb299fa2Sopenharmony_ci
351fb299fa2Sopenharmony_cistatic UpdaterStatus PreUpdatePackages(UpdaterParams &upParams)
352fb299fa2Sopenharmony_ci{
353fb299fa2Sopenharmony_ci    UPDATER_INIT_RECORD;
354fb299fa2Sopenharmony_ci    LOG(INFO) << "start to update packages, start index:" << upParams.pkgLocation;
355fb299fa2Sopenharmony_ci
356fb299fa2Sopenharmony_ci    UpdaterStatus status = UPDATE_UNKNOWN;
357fb299fa2Sopenharmony_ci
358fb299fa2Sopenharmony_ci    upParams.installTime.resize(upParams.updatePackage.size(), std::chrono::duration<double>(0));
359fb299fa2Sopenharmony_ci    if (SetupPartitions() != 0) {
360fb299fa2Sopenharmony_ci        UPDATER_UI_INSTANCE.ShowUpdInfo(TR(UPD_SETPART_FAIL), true);
361fb299fa2Sopenharmony_ci        UPDATER_LAST_WORD(UPDATE_ERROR);
362fb299fa2Sopenharmony_ci        return UPDATE_ERROR;
363fb299fa2Sopenharmony_ci    }
364fb299fa2Sopenharmony_ci    const std::string resultPath = std::string(UPDATER_PATH) + "/" + std::string(UPDATER_RESULT_FILE);
365fb299fa2Sopenharmony_ci    if (access(resultPath.c_str(), F_OK) != -1) {
366fb299fa2Sopenharmony_ci        (void)DeleteFile(resultPath);
367fb299fa2Sopenharmony_ci        LOG(INFO) << "delete last upgrade file";
368fb299fa2Sopenharmony_ci    }
369fb299fa2Sopenharmony_ci
370fb299fa2Sopenharmony_ci    if (upParams.pkgLocation == upParams.updatePackage.size()) {
371fb299fa2Sopenharmony_ci        LOG(WARNING) << "all package has been upgraded, skip pre process";
372fb299fa2Sopenharmony_ci        return UPDATE_SUCCESS;
373fb299fa2Sopenharmony_ci    }
374fb299fa2Sopenharmony_ci
375fb299fa2Sopenharmony_ci    // verify packages first
376fb299fa2Sopenharmony_ci    if (VerifyPackages(upParams) != UPDATE_SUCCESS) {
377fb299fa2Sopenharmony_ci        return UPDATE_CORRUPT; // verify package failed must return UPDATE_CORRUPT, ux need it !!!
378fb299fa2Sopenharmony_ci    }
379fb299fa2Sopenharmony_ci
380fb299fa2Sopenharmony_ci    // Only handle UPATE_ERROR and UPDATE_SUCCESS here.Let package verify handle others.
381fb299fa2Sopenharmony_ci    if (IsSpaceCapacitySufficient(upParams) == UPDATE_ERROR) {
382fb299fa2Sopenharmony_ci        UPDATER_LAST_WORD(status);
383fb299fa2Sopenharmony_ci        return status;
384fb299fa2Sopenharmony_ci    }
385fb299fa2Sopenharmony_ci    if (upParams.retryCount == 0 && !IsBatteryCapacitySufficient()) {
386fb299fa2Sopenharmony_ci        UPDATER_UI_INSTANCE.ShowUpdInfo(TR(LOG_LOWPOWER));
387fb299fa2Sopenharmony_ci        UPDATER_UI_INSTANCE.Sleep(UI_SHOW_DURATION);
388fb299fa2Sopenharmony_ci        UPDATER_LAST_WORD(UPDATE_ERROR);
389fb299fa2Sopenharmony_ci        LOG(ERROR) << "Battery is not sufficient for install package.";
390fb299fa2Sopenharmony_ci        return UPDATE_SKIP;
391fb299fa2Sopenharmony_ci    }
392fb299fa2Sopenharmony_ci
393fb299fa2Sopenharmony_ci#ifdef UPDATER_USE_PTABLE
394fb299fa2Sopenharmony_ci    if (!PtablePreProcess::GetInstance().DoPtableProcess(upParams)) {
395fb299fa2Sopenharmony_ci        LOG(ERROR) << "DoPtableProcess failed";
396fb299fa2Sopenharmony_ci        UPDATER_LAST_WORD(UPDATE_ERROR);
397fb299fa2Sopenharmony_ci        return UPDATE_ERROR;
398fb299fa2Sopenharmony_ci    }
399fb299fa2Sopenharmony_ci#endif
400fb299fa2Sopenharmony_ci    return UPDATE_SUCCESS;
401fb299fa2Sopenharmony_ci}
402fb299fa2Sopenharmony_ci
403fb299fa2Sopenharmony_cistatic UpdaterStatus DoInstallPackages(UpdaterParams &upParams, std::vector<double> &pkgStartPosition)
404fb299fa2Sopenharmony_ci{
405fb299fa2Sopenharmony_ci    UpdaterStatus status = UPDATE_UNKNOWN;
406fb299fa2Sopenharmony_ci    if (upParams.pkgLocation == upParams.updatePackage.size()) {
407fb299fa2Sopenharmony_ci        LOG(WARNING) << "all packages has been installed, directly return success";
408fb299fa2Sopenharmony_ci        upParams.callbackProgress(FULL_PERCENT_PROGRESS);
409fb299fa2Sopenharmony_ci        return UPDATE_SUCCESS;
410fb299fa2Sopenharmony_ci    }
411fb299fa2Sopenharmony_ci    for (; upParams.pkgLocation < upParams.updatePackage.size(); upParams.pkgLocation++) {
412fb299fa2Sopenharmony_ci        PkgManager::PkgManagerPtr manager = PkgManager::CreatePackageInstance();
413fb299fa2Sopenharmony_ci        if (manager == nullptr) {
414fb299fa2Sopenharmony_ci            LOG(ERROR) << "CreatePackageInstance fail";
415fb299fa2Sopenharmony_ci            return UPDATE_ERROR;
416fb299fa2Sopenharmony_ci        }
417fb299fa2Sopenharmony_ci        auto startTime = std::chrono::system_clock::now();
418fb299fa2Sopenharmony_ci        upParams.initialProgress = ((UPDATER_UI_INSTANCE.GetCurrentPercent() / FULL_PERCENT) >
419fb299fa2Sopenharmony_ci            pkgStartPosition[upParams.pkgLocation]) ?
420fb299fa2Sopenharmony_ci            (UPDATER_UI_INSTANCE.GetCurrentPercent() / FULL_PERCENT) : pkgStartPosition[upParams.pkgLocation];
421fb299fa2Sopenharmony_ci        upParams.currentPercentage = pkgStartPosition[upParams.pkgLocation + 1] - upParams.initialProgress;
422fb299fa2Sopenharmony_ci        LOG(INFO) << "InstallUpdaterPackage pkg is " << upParams.updatePackage[upParams.pkgLocation] <<
423fb299fa2Sopenharmony_ci            " percent:" << upParams.initialProgress << "~" << pkgStartPosition[upParams.pkgLocation + 1];
424fb299fa2Sopenharmony_ci
425fb299fa2Sopenharmony_ci        status = InstallUpdaterPackage(upParams, manager);
426fb299fa2Sopenharmony_ci        auto endTime = std::chrono::system_clock::now();
427fb299fa2Sopenharmony_ci        upParams.installTime[upParams.pkgLocation] = upParams.installTime[upParams.pkgLocation] + endTime - startTime;
428fb299fa2Sopenharmony_ci        WriteInstallTime(upParams);
429fb299fa2Sopenharmony_ci        if (status != UPDATE_SUCCESS) {
430fb299fa2Sopenharmony_ci            LOG(ERROR) << "InstallUpdaterPackage failed! Pkg is " << upParams.updatePackage[upParams.pkgLocation];
431fb299fa2Sopenharmony_ci            if (!CheckResultFail()) {
432fb299fa2Sopenharmony_ci                UPDATER_LAST_WORD(status);
433fb299fa2Sopenharmony_ci            }
434fb299fa2Sopenharmony_ci            PkgManager::ReleasePackageInstance(manager);
435fb299fa2Sopenharmony_ci            return status;
436fb299fa2Sopenharmony_ci        }
437fb299fa2Sopenharmony_ci        ProgressSmoothHandler(
438fb299fa2Sopenharmony_ci            static_cast<int>(upParams.initialProgress * FULL_PERCENT_PROGRESS +
439fb299fa2Sopenharmony_ci            upParams.currentPercentage * GetTmpProgressValue()),
440fb299fa2Sopenharmony_ci            static_cast<int>(pkgStartPosition[upParams.pkgLocation + 1] * FULL_PERCENT_PROGRESS));
441fb299fa2Sopenharmony_ci        SetMessageToMisc(upParams.miscCmd, upParams.pkgLocation + 1, "upgraded_pkg_num");
442fb299fa2Sopenharmony_ci        PkgManager::ReleasePackageInstance(manager);
443fb299fa2Sopenharmony_ci    }
444fb299fa2Sopenharmony_ci    return status;
445fb299fa2Sopenharmony_ci}
446fb299fa2Sopenharmony_ci
447fb299fa2Sopenharmony_ciUpdaterStatus DoUpdatePackages(UpdaterParams &upParams)
448fb299fa2Sopenharmony_ci{
449fb299fa2Sopenharmony_ci    UPDATER_INIT_RECORD;
450fb299fa2Sopenharmony_ci    UpdaterStatus status = UPDATE_UNKNOWN;
451fb299fa2Sopenharmony_ci    std::vector<double> pkgStartPosition {};
452fb299fa2Sopenharmony_ci    double updateStartPosition = 0.0;
453fb299fa2Sopenharmony_ci    status = CalcProgress(upParams, pkgStartPosition, updateStartPosition);
454fb299fa2Sopenharmony_ci    if (status != UPDATE_SUCCESS) {
455fb299fa2Sopenharmony_ci        UPDATER_LAST_WORD(status);
456fb299fa2Sopenharmony_ci        return status;
457fb299fa2Sopenharmony_ci    }
458fb299fa2Sopenharmony_ci    for (unsigned int i = 0; i < upParams.updatePackage.size(); i++) {
459fb299fa2Sopenharmony_ci        LOG(INFO) << "package " << i << ":" << upParams.updatePackage[i] <<
460fb299fa2Sopenharmony_ci            " percent:" << upParams.currentPercentage;
461fb299fa2Sopenharmony_ci    }
462fb299fa2Sopenharmony_ci    if (upParams.callbackProgress == nullptr) {
463fb299fa2Sopenharmony_ci        LOG(ERROR) << "CallbackProgress is nullptr";
464fb299fa2Sopenharmony_ci        return UPDATE_CORRUPT;
465fb299fa2Sopenharmony_ci    }
466fb299fa2Sopenharmony_ci    float value = (UPDATER_UI_INSTANCE.GetCurrentPercent() > (updateStartPosition * FULL_PERCENT_PROGRESS)) ?
467fb299fa2Sopenharmony_ci        UPDATER_UI_INSTANCE.GetCurrentPercent() : (updateStartPosition * FULL_PERCENT_PROGRESS);
468fb299fa2Sopenharmony_ci    upParams.callbackProgress(value);
469fb299fa2Sopenharmony_ci    status = DoInstallPackages(upParams, pkgStartPosition);
470fb299fa2Sopenharmony_ci    if (status != UPDATE_SUCCESS) {
471fb299fa2Sopenharmony_ci        UPDATER_LAST_WORD(status);
472fb299fa2Sopenharmony_ci        return status;
473fb299fa2Sopenharmony_ci    }
474fb299fa2Sopenharmony_ci    if (upParams.forceUpdate) {
475fb299fa2Sopenharmony_ci        UPDATER_UI_INSTANCE.ShowLogRes(TR(LABEL_UPD_OK_SHUTDOWN));
476fb299fa2Sopenharmony_ci    }
477fb299fa2Sopenharmony_ci    UPDATER_UI_INSTANCE.ShowSuccessPage();
478fb299fa2Sopenharmony_ci    return status;
479fb299fa2Sopenharmony_ci}
480fb299fa2Sopenharmony_ci
481fb299fa2Sopenharmony_cistatic void PostUpdatePackages(UpdaterParams &upParams, bool updateResult)
482fb299fa2Sopenharmony_ci{
483fb299fa2Sopenharmony_ci    std::string writeBuffer;
484fb299fa2Sopenharmony_ci    std::string buf;
485fb299fa2Sopenharmony_ci    std::string time;
486fb299fa2Sopenharmony_ci    if (!updateResult) {
487fb299fa2Sopenharmony_ci        const std::string resultPath = std::string(UPDATER_PATH) + "/" + std::string(UPDATER_RESULT_FILE);
488fb299fa2Sopenharmony_ci        std::ifstream fin {resultPath};
489fb299fa2Sopenharmony_ci        if (!fin.is_open() || !std::getline(fin, buf)) {
490fb299fa2Sopenharmony_ci            LOG(ERROR) << "read result file error " << resultPath;
491fb299fa2Sopenharmony_ci            buf = "fail|";
492fb299fa2Sopenharmony_ci        }
493fb299fa2Sopenharmony_ci    } else {
494fb299fa2Sopenharmony_ci        buf = "pass|";
495fb299fa2Sopenharmony_ci        upParams.pkgLocation = upParams.pkgLocation == 0 ? upParams.pkgLocation : (upParams.pkgLocation - 1);
496fb299fa2Sopenharmony_ci    }
497fb299fa2Sopenharmony_ci
498fb299fa2Sopenharmony_ci    for (unsigned int i = 0; i < upParams.pkgLocation; i++) {
499fb299fa2Sopenharmony_ci        time = DurationToString(upParams.installTime, i);
500fb299fa2Sopenharmony_ci        writeBuffer += upParams.updatePackage.size() < i + 1 ? "" : upParams.updatePackage[i];
501fb299fa2Sopenharmony_ci        writeBuffer += "|pass||install_time=" + time + "|\n";
502fb299fa2Sopenharmony_ci    }
503fb299fa2Sopenharmony_ci    time = DurationToString(upParams.installTime, upParams.pkgLocation);
504fb299fa2Sopenharmony_ci
505fb299fa2Sopenharmony_ci    writeBuffer += upParams.updatePackage.size() < upParams.pkgLocation + 1 ? "" :
506fb299fa2Sopenharmony_ci        upParams.updatePackage[upParams.pkgLocation];
507fb299fa2Sopenharmony_ci    writeBuffer += "|" + buf + "|install_time=" + time + "|\n";
508fb299fa2Sopenharmony_ci    for (unsigned int i = upParams.pkgLocation + 1; i < upParams.updatePackage.size(); i++) {
509fb299fa2Sopenharmony_ci        writeBuffer += upParams.updatePackage[i] + "\n";
510fb299fa2Sopenharmony_ci    }
511fb299fa2Sopenharmony_ci    if (writeBuffer != "") {
512fb299fa2Sopenharmony_ci        writeBuffer.pop_back();
513fb299fa2Sopenharmony_ci    }
514fb299fa2Sopenharmony_ci    LOG(INFO) << "post over, writeBuffer = " << writeBuffer;
515fb299fa2Sopenharmony_ci    WriteDumpResult(writeBuffer, UPDATER_RESULT_FILE);
516fb299fa2Sopenharmony_ci    DeleteInstallTimeFile();
517fb299fa2Sopenharmony_ci}
518fb299fa2Sopenharmony_ci
519fb299fa2Sopenharmony_cistatic UpdaterStatus PreSdcardUpdatePackages(UpdaterParams &upParams)
520fb299fa2Sopenharmony_ci{
521fb299fa2Sopenharmony_ci    upParams.installTime.resize(upParams.updatePackage.size(), std::chrono::duration<double>(0));
522fb299fa2Sopenharmony_ci    // verify packages first
523fb299fa2Sopenharmony_ci    if (upParams.retryCount == 0 && !IsBatteryCapacitySufficient()) {
524fb299fa2Sopenharmony_ci        UPDATER_UI_INSTANCE.ShowUpdInfo(TR(LOG_LOWPOWER));
525fb299fa2Sopenharmony_ci        UPDATER_UI_INSTANCE.Sleep(UI_SHOW_DURATION);
526fb299fa2Sopenharmony_ci        LOG(ERROR) << "Battery is not sufficient for install package.";
527fb299fa2Sopenharmony_ci        return UPDATE_SKIP;
528fb299fa2Sopenharmony_ci    }
529fb299fa2Sopenharmony_ci
530fb299fa2Sopenharmony_ci    if (VerifyPackages(upParams) != UPDATE_SUCCESS) {
531fb299fa2Sopenharmony_ci        return UPDATE_CORRUPT; // verify package failed must return UPDATE_CORRUPT, ux need it !!!
532fb299fa2Sopenharmony_ci    }
533fb299fa2Sopenharmony_ci#ifdef UPDATER_USE_PTABLE
534fb299fa2Sopenharmony_ci    if (!PtablePreProcess::GetInstance().DoPtableProcess(upParams)) {
535fb299fa2Sopenharmony_ci        LOG(ERROR) << "DoPtableProcess failed";
536fb299fa2Sopenharmony_ci        return UPDATE_ERROR;
537fb299fa2Sopenharmony_ci    }
538fb299fa2Sopenharmony_ci#endif
539fb299fa2Sopenharmony_ci    return UPDATE_SUCCESS;
540fb299fa2Sopenharmony_ci}
541fb299fa2Sopenharmony_ci
542fb299fa2Sopenharmony_cistatic void PostSdcardUpdatePackages(UpdaterParams &upParams, bool updateResult)
543fb299fa2Sopenharmony_ci{
544fb299fa2Sopenharmony_ci    if (Utils::CheckUpdateMode(Updater::SDCARD_INTRAL_MODE)) {
545fb299fa2Sopenharmony_ci        PostUpdatePackages(upParams, updateResult);
546fb299fa2Sopenharmony_ci    }
547fb299fa2Sopenharmony_ci}
548fb299fa2Sopenharmony_ci
549fb299fa2Sopenharmony_ciUpdaterStatus UpdaterFromSdcard(UpdaterParams &upParams)
550fb299fa2Sopenharmony_ci{
551fb299fa2Sopenharmony_ci    UPDATER_INIT_RECORD;
552fb299fa2Sopenharmony_ci    upParams.callbackProgress = [] (float value) { UPDATER_UI_INSTANCE.ShowProgress(value); };
553fb299fa2Sopenharmony_ci    SetMessageToMisc(upParams.miscCmd, 0, "sdcard_update");
554fb299fa2Sopenharmony_ci    if (CheckSdcardPkgs(upParams) != UPDATE_SUCCESS) {
555fb299fa2Sopenharmony_ci        LOG(ERROR) << "can not find sdcard packages";
556fb299fa2Sopenharmony_ci        return UPDATE_ERROR;
557fb299fa2Sopenharmony_ci    }
558fb299fa2Sopenharmony_ci    UpdaterStatus status = PreSdcardUpdatePackages(upParams);
559fb299fa2Sopenharmony_ci    if (status == UPDATE_SUCCESS) {
560fb299fa2Sopenharmony_ci        upParams.initialProgress += VERIFY_PERCENT;
561fb299fa2Sopenharmony_ci        upParams.currentPercentage -= VERIFY_PERCENT;
562fb299fa2Sopenharmony_ci
563fb299fa2Sopenharmony_ci        STAGE(UPDATE_STAGE_BEGIN) << "UpdaterFromSdcard";
564fb299fa2Sopenharmony_ci        LOG(INFO) << "UpdaterFromSdcard start, sdcard updaterPath : " << upParams.updatePackage[upParams.pkgLocation];
565fb299fa2Sopenharmony_ci        UPDATER_UI_INSTANCE.ShowLog(TR(LOG_SDCARD_NOTMOVE));
566fb299fa2Sopenharmony_ci        status = DoUpdatePackages(upParams);
567fb299fa2Sopenharmony_ci    }
568fb299fa2Sopenharmony_ci    PostSdcardUpdatePackages(upParams, status == UPDATE_SUCCESS);
569fb299fa2Sopenharmony_ci    return status;
570fb299fa2Sopenharmony_ci}
571fb299fa2Sopenharmony_ci
572fb299fa2Sopenharmony_ciUpdaterStatus InstallUpdaterPackages(UpdaterParams &upParams)
573fb299fa2Sopenharmony_ci{
574fb299fa2Sopenharmony_ci    UpdaterInit::GetInstance().InvokeEvent(UPDATER_PRE_UPDATE_PACKAGE_EVENT);
575fb299fa2Sopenharmony_ci    UpdaterStatus status = PreUpdatePackages(upParams);
576fb299fa2Sopenharmony_ci    if (status == UPDATE_SUCCESS) {
577fb299fa2Sopenharmony_ci        status = DoUpdatePackages(upParams);
578fb299fa2Sopenharmony_ci    }
579fb299fa2Sopenharmony_ci    PostUpdatePackages(upParams, status == UPDATE_SUCCESS);
580fb299fa2Sopenharmony_ci    UpdaterInit::GetInstance().InvokeEvent(UPDATER_POST_UPDATE_PACKAGE_EVENT);
581fb299fa2Sopenharmony_ci    return status;
582fb299fa2Sopenharmony_ci}
583fb299fa2Sopenharmony_ci
584fb299fa2Sopenharmony_ciUpdaterStatus StartUpdaterEntry(UpdaterParams &upParams)
585fb299fa2Sopenharmony_ci{
586fb299fa2Sopenharmony_ci    UpdaterStatus status = UPDATE_UNKNOWN;
587fb299fa2Sopenharmony_ci    status = PreStartUpdaterEntry(upParams, status);
588fb299fa2Sopenharmony_ci    if (status != UPDATE_SUCCESS) {
589fb299fa2Sopenharmony_ci        LOG(ERROR) << "PreStartUpdaterEntry failed";
590fb299fa2Sopenharmony_ci        return status;
591fb299fa2Sopenharmony_ci    }
592fb299fa2Sopenharmony_ci
593fb299fa2Sopenharmony_ci    status = DoUpdaterEntry(upParams);
594fb299fa2Sopenharmony_ci    if (status != UPDATE_SUCCESS) {
595fb299fa2Sopenharmony_ci        LOG(WARNING) << "DoUpdaterEntry failed";
596fb299fa2Sopenharmony_ci    }
597fb299fa2Sopenharmony_ci
598fb299fa2Sopenharmony_ci    status = PostStartUpdaterEntry(upParams, status);
599fb299fa2Sopenharmony_ci    if (status != UPDATE_SUCCESS) {
600fb299fa2Sopenharmony_ci        LOG(ERROR) << "PostStartUpdaterEntry failed";
601fb299fa2Sopenharmony_ci    }
602fb299fa2Sopenharmony_ci    return status;
603fb299fa2Sopenharmony_ci}
604fb299fa2Sopenharmony_ci
605fb299fa2Sopenharmony_ciUpdaterStatus DoUpdaterEntry(UpdaterParams &upParams)
606fb299fa2Sopenharmony_ci{
607fb299fa2Sopenharmony_ci    UpdaterStatus status = UPDATE_UNKNOWN;
608fb299fa2Sopenharmony_ci    if (upParams.updateMode == SDCARD_UPDATE) {
609fb299fa2Sopenharmony_ci        LOG(INFO) << "start sdcard update";
610fb299fa2Sopenharmony_ci        UPDATER_UI_INSTANCE.ShowProgressPage();
611fb299fa2Sopenharmony_ci        status = UpdaterFromSdcard(upParams);
612fb299fa2Sopenharmony_ci        return status;
613fb299fa2Sopenharmony_ci    } else if (upParams.updatePackage.size() > 0) {
614fb299fa2Sopenharmony_ci        UPDATER_UI_INSTANCE.ShowProgressPage();
615fb299fa2Sopenharmony_ci        status = InstallUpdaterPackages(upParams);
616fb299fa2Sopenharmony_ci    } else if (upParams.factoryResetMode == "factory_wipe_data") {
617fb299fa2Sopenharmony_ci        UPDATER_UI_INSTANCE.ShowProgressPage();
618fb299fa2Sopenharmony_ci        LOG(INFO) << "Factory level FactoryReset begin";
619fb299fa2Sopenharmony_ci        status = UPDATE_SUCCESS;
620fb299fa2Sopenharmony_ci#if !defined(UPDATER_UT) && defined(UPDATER_UI_SUPPORT)
621fb299fa2Sopenharmony_ci        DoProgress();
622fb299fa2Sopenharmony_ci#endif
623fb299fa2Sopenharmony_ci        if (FactoryReset(FACTORY_WIPE_DATA, "/data") != 0) {
624fb299fa2Sopenharmony_ci            LOG(ERROR) << "FactoryReset factory level failed";
625fb299fa2Sopenharmony_ci            status = UPDATE_ERROR;
626fb299fa2Sopenharmony_ci        }
627fb299fa2Sopenharmony_ci        UPDATER_UI_INSTANCE.ShowLogRes(
628fb299fa2Sopenharmony_ci            (status != UPDATE_SUCCESS) ? TR(LOGRES_FACTORY_FAIL) : TR(LOGRES_FACTORY_DONE));
629fb299fa2Sopenharmony_ci    } else if (upParams.factoryResetMode == "user_wipe_data" || upParams.factoryResetMode == "menu_wipe_data") {
630fb299fa2Sopenharmony_ci        UPDATER_UI_INSTANCE.ShowProgressPage();
631fb299fa2Sopenharmony_ci        LOG(INFO) << "User level FactoryReset begin";
632fb299fa2Sopenharmony_ci        status = UPDATE_SUCCESS;
633fb299fa2Sopenharmony_ci#if !defined(UPDATER_UT) && defined(UPDATER_UI_SUPPORT)
634fb299fa2Sopenharmony_ci        DoProgress();
635fb299fa2Sopenharmony_ci#endif
636fb299fa2Sopenharmony_ci        if (FactoryReset(upParams.factoryResetMode == "user_wipe_data" ?
637fb299fa2Sopenharmony_ci            USER_WIPE_DATA : MENU_WIPE_DATA, "/data") != 0) {
638fb299fa2Sopenharmony_ci            LOG(ERROR) << "FactoryReset user level failed";
639fb299fa2Sopenharmony_ci            status = UPDATE_ERROR;
640fb299fa2Sopenharmony_ci        }
641fb299fa2Sopenharmony_ci        if (status != UPDATE_SUCCESS) {
642fb299fa2Sopenharmony_ci            UPDATER_UI_INSTANCE.ShowLogRes(TR(LOGRES_WIPE_FAIL));
643fb299fa2Sopenharmony_ci        } else {
644fb299fa2Sopenharmony_ci            UPDATER_UI_INSTANCE.ShowSuccessPage();
645fb299fa2Sopenharmony_ci            UPDATER_UI_INSTANCE.ShowLogRes(TR(LOGRES_WIPE_FINISH));
646fb299fa2Sopenharmony_ci            ClearUpdaterParaMisc();
647fb299fa2Sopenharmony_ci            std::this_thread::sleep_for(std::chrono::milliseconds(UI_SHOW_DURATION));
648fb299fa2Sopenharmony_ci        }
649fb299fa2Sopenharmony_ci    }
650fb299fa2Sopenharmony_ci    return status;
651fb299fa2Sopenharmony_ci}
652fb299fa2Sopenharmony_ci
653fb299fa2Sopenharmony_cistd::unordered_map<std::string, std::function<void ()>> InitOptionsFuncTab(char* &optarg,
654fb299fa2Sopenharmony_ci    PackageUpdateMode &mode, UpdaterParams &upParams)
655fb299fa2Sopenharmony_ci{
656fb299fa2Sopenharmony_ci    std::unordered_map<std::string, std::function<void ()>> optionsFuncTab {
657fb299fa2Sopenharmony_ci        {"update_package", [&]() -> void
658fb299fa2Sopenharmony_ci        {
659fb299fa2Sopenharmony_ci            upParams.updatePackage.push_back(optarg);
660fb299fa2Sopenharmony_ci            (void)UPDATER_UI_INSTANCE.SetMode(UPDATERMODE_OTA);
661fb299fa2Sopenharmony_ci            mode = HOTA_UPDATE;
662fb299fa2Sopenharmony_ci        }},
663fb299fa2Sopenharmony_ci        {"retry_count", [&]() -> void
664fb299fa2Sopenharmony_ci        {
665fb299fa2Sopenharmony_ci            upParams.retryCount = atoi(optarg);
666fb299fa2Sopenharmony_ci            HwFaultRetry::GetInstance().SetRetryCount(upParams.retryCount);
667fb299fa2Sopenharmony_ci        }},
668fb299fa2Sopenharmony_ci        {"factory_wipe_data", [&]() -> void
669fb299fa2Sopenharmony_ci        {
670fb299fa2Sopenharmony_ci            (void)UPDATER_UI_INSTANCE.SetMode(UPDATERMODE_REBOOTFACTORYRST);
671fb299fa2Sopenharmony_ci            upParams.factoryResetMode = "factory_wipe_data";
672fb299fa2Sopenharmony_ci        }},
673fb299fa2Sopenharmony_ci        {"wipe_data_at_factoryreset_0", [&]() -> void
674fb299fa2Sopenharmony_ci        {
675fb299fa2Sopenharmony_ci            (void)UPDATER_UI_INSTANCE.SetMode(UPDATERMODE_ATFACTORYRST);
676fb299fa2Sopenharmony_ci            upParams.factoryResetMode = "factory_wipe_data";
677fb299fa2Sopenharmony_ci        }},
678fb299fa2Sopenharmony_ci        {"user_wipe_data", [&]() -> void
679fb299fa2Sopenharmony_ci        {
680fb299fa2Sopenharmony_ci            (void)UPDATER_UI_INSTANCE.SetMode(UPDATERMODE_REBOOTFACTORYRST);
681fb299fa2Sopenharmony_ci            upParams.factoryResetMode = "user_wipe_data";
682fb299fa2Sopenharmony_ci        }},
683fb299fa2Sopenharmony_ci        {"wipe_data_factory_lowlevel", [&]() -> void
684fb299fa2Sopenharmony_ci        {
685fb299fa2Sopenharmony_ci            (void)UPDATER_UI_INSTANCE.SetMode(UPDATERMODE_REBOOTFACTORYRST);
686fb299fa2Sopenharmony_ci            upParams.factoryResetMode = "user_wipe_data";
687fb299fa2Sopenharmony_ci        }},
688fb299fa2Sopenharmony_ci        {"menu_wipe_data", [&]() -> void
689fb299fa2Sopenharmony_ci        {
690fb299fa2Sopenharmony_ci            (void)UPDATER_UI_INSTANCE.SetMode(UPDATERMODE_REBOOTFACTORYRST);
691fb299fa2Sopenharmony_ci            upParams.factoryResetMode = "menu_wipe_data";
692fb299fa2Sopenharmony_ci        }},
693fb299fa2Sopenharmony_ci        {"upgraded_pkg_num", [&]() -> void
694fb299fa2Sopenharmony_ci        {
695fb299fa2Sopenharmony_ci            upParams.pkgLocation = static_cast<unsigned int>(atoi(optarg));
696fb299fa2Sopenharmony_ci        }},
697fb299fa2Sopenharmony_ci        {"sdcard_update", [&]() -> void
698fb299fa2Sopenharmony_ci        {
699fb299fa2Sopenharmony_ci            upParams.updateMode = SDCARD_UPDATE;
700fb299fa2Sopenharmony_ci        }},
701fb299fa2Sopenharmony_ci        {"UPDATE:MAINIMG", [&]() -> void
702fb299fa2Sopenharmony_ci        {
703fb299fa2Sopenharmony_ci            upParams.updateMode = SDCARD_UPDATE;
704fb299fa2Sopenharmony_ci            upParams.sdExtMode = SDCARD_MAINIMG;
705fb299fa2Sopenharmony_ci        }},
706fb299fa2Sopenharmony_ci        {"factory_sd_update", [&]() -> void
707fb299fa2Sopenharmony_ci        {
708fb299fa2Sopenharmony_ci            upParams.updateMode = SDCARD_UPDATE;
709fb299fa2Sopenharmony_ci            upParams.sdExtMode = SDCARD_NORMAL_UPDATE;
710fb299fa2Sopenharmony_ci        }},
711fb299fa2Sopenharmony_ci        {"UPDATE:SD", [&]() -> void
712fb299fa2Sopenharmony_ci        {
713fb299fa2Sopenharmony_ci            upParams.updateMode = SDCARD_UPDATE;
714fb299fa2Sopenharmony_ci            upParams.sdExtMode = SDCARD_NORMAL_UPDATE;
715fb299fa2Sopenharmony_ci        }},
716fb299fa2Sopenharmony_ci        {"UPDATE:SDFROMDEV", [&]() -> void
717fb299fa2Sopenharmony_ci        {
718fb299fa2Sopenharmony_ci            upParams.updateMode = SDCARD_UPDATE;
719fb299fa2Sopenharmony_ci            upParams.sdExtMode = SDCARD_UPDATE_FROM_DEV;
720fb299fa2Sopenharmony_ci        }},
721fb299fa2Sopenharmony_ci        {"force_update_action", [&]() -> void
722fb299fa2Sopenharmony_ci        {
723fb299fa2Sopenharmony_ci            if (std::string(optarg) == POWEROFF) {
724fb299fa2Sopenharmony_ci                upParams.forceUpdate = true;
725fb299fa2Sopenharmony_ci            }
726fb299fa2Sopenharmony_ci        }},
727fb299fa2Sopenharmony_ci        {"night_update", [&]() -> void
728fb299fa2Sopenharmony_ci        {
729fb299fa2Sopenharmony_ci            (void)UPDATER_UI_INSTANCE.SetMode(UPDATERMODE_NIGHTUPDATE);
730fb299fa2Sopenharmony_ci            upParams.forceReboot = true;
731fb299fa2Sopenharmony_ci        }},
732fb299fa2Sopenharmony_ci        {"sdcard_intral_update", [&]() -> void
733fb299fa2Sopenharmony_ci        {
734fb299fa2Sopenharmony_ci            upParams.updateMode = SDCARD_UPDATE;
735fb299fa2Sopenharmony_ci        }}
736fb299fa2Sopenharmony_ci    };
737fb299fa2Sopenharmony_ci    return optionsFuncTab;
738fb299fa2Sopenharmony_ci}
739fb299fa2Sopenharmony_ci
740fb299fa2Sopenharmony_ci__attribute__((weak)) bool IsSupportOption([[maybe_unused]] const std::string &option)
741fb299fa2Sopenharmony_ci{
742fb299fa2Sopenharmony_ci    LOG(INFO) << "option: " << option;
743fb299fa2Sopenharmony_ci    return false;
744fb299fa2Sopenharmony_ci}
745fb299fa2Sopenharmony_ci
746fb299fa2Sopenharmony_ci__attribute__((weak)) UpdaterStatus ProcessOtherOption([[maybe_unused]] const std::string &option,
747fb299fa2Sopenharmony_ci    [[maybe_unused]] UpdaterParams &upParams, PackageUpdateMode &mode)
748fb299fa2Sopenharmony_ci{
749fb299fa2Sopenharmony_ci    return UPDATE_UNKNOWN;
750fb299fa2Sopenharmony_ci}
751fb299fa2Sopenharmony_ci
752fb299fa2Sopenharmony_cistatic UpdaterStatus StartUpdater(const std::vector<std::string> &args,
753fb299fa2Sopenharmony_ci    char **argv, PackageUpdateMode &mode, UpdaterParams &upParams)
754fb299fa2Sopenharmony_ci{
755fb299fa2Sopenharmony_ci    std::vector<char *> extractedArgs;
756fb299fa2Sopenharmony_ci    int rc;
757fb299fa2Sopenharmony_ci    int optionIndex;
758fb299fa2Sopenharmony_ci    auto optionsFuncTab = InitOptionsFuncTab(optarg, mode, upParams);
759fb299fa2Sopenharmony_ci
760fb299fa2Sopenharmony_ci    for (const auto &arg : args) {
761fb299fa2Sopenharmony_ci        extractedArgs.push_back(const_cast<char *>(arg.c_str()));
762fb299fa2Sopenharmony_ci        STAGE(UPDATE_STAGE_OUT) << "option:" << arg;
763fb299fa2Sopenharmony_ci        LOG(INFO) << "option:" << arg;
764fb299fa2Sopenharmony_ci    }
765fb299fa2Sopenharmony_ci    extractedArgs.push_back(nullptr);
766fb299fa2Sopenharmony_ci    extractedArgs.insert(extractedArgs.begin(), argv[0]);
767fb299fa2Sopenharmony_ci    while ((rc = getopt_long(extractedArgs.size() - 1, extractedArgs.data(), "", OPTIONS, &optionIndex)) != -1) {
768fb299fa2Sopenharmony_ci        switch (rc) {
769fb299fa2Sopenharmony_ci            case 0: {
770fb299fa2Sopenharmony_ci                std::string option = OPTIONS[optionIndex].name;
771fb299fa2Sopenharmony_ci                if (optionsFuncTab.find(option) != optionsFuncTab.end()) {
772fb299fa2Sopenharmony_ci                    auto optionsFunc = optionsFuncTab.at(option);
773fb299fa2Sopenharmony_ci                    optionsFunc();
774fb299fa2Sopenharmony_ci                } else if (IsSupportOption(option)) {
775fb299fa2Sopenharmony_ci                    return ProcessOtherOption(option, upParams, mode);
776fb299fa2Sopenharmony_ci                }
777fb299fa2Sopenharmony_ci                break;
778fb299fa2Sopenharmony_ci            }
779fb299fa2Sopenharmony_ci            default:
780fb299fa2Sopenharmony_ci                LOG(ERROR) << "Invalid argument.";
781fb299fa2Sopenharmony_ci                break;
782fb299fa2Sopenharmony_ci        }
783fb299fa2Sopenharmony_ci    }
784fb299fa2Sopenharmony_ci    optind = 1;
785fb299fa2Sopenharmony_ci    if (upParams.pkgLocation == 0) {
786fb299fa2Sopenharmony_ci        DeleteInstallTimeFile();
787fb299fa2Sopenharmony_ci    }
788fb299fa2Sopenharmony_ci    // Sanity checks
789fb299fa2Sopenharmony_ci    if (upParams.updateMode == SDCARD_UPDATE) {
790fb299fa2Sopenharmony_ci        (void)UPDATER_UI_INSTANCE.SetMode(UPDATERMODE_SDCARD);
791fb299fa2Sopenharmony_ci        mode = SDCARD_UPDATE;
792fb299fa2Sopenharmony_ci    }
793fb299fa2Sopenharmony_ci    return StartUpdaterEntry(upParams);
794fb299fa2Sopenharmony_ci}
795fb299fa2Sopenharmony_ci
796fb299fa2Sopenharmony_ci// add updater mode
797fb299fa2Sopenharmony_ciREGISTER_MODE(Updater, "updater.hdc.configfs");
798fb299fa2Sopenharmony_ci
799fb299fa2Sopenharmony_ci__attribute__((weak)) bool IsNeedWipe()
800fb299fa2Sopenharmony_ci{
801fb299fa2Sopenharmony_ci    return false;
802fb299fa2Sopenharmony_ci}
803fb299fa2Sopenharmony_ci
804fb299fa2Sopenharmony_civoid RebootAfterUpdateSuccess(const UpdaterParams &upParams)
805fb299fa2Sopenharmony_ci{
806fb299fa2Sopenharmony_ci    if (IsNeedWipe() ||
807fb299fa2Sopenharmony_ci        upParams.sdExtMode == SDCARD_UPDATE_FROM_DEV ||
808fb299fa2Sopenharmony_ci        upParams.sdExtMode == SDCARD_UPDATE_FROM_DATA) {
809fb299fa2Sopenharmony_ci        Utils::UpdaterDoReboot("updater", "Updater wipe data after upgrade success", "--user_wipe_data");
810fb299fa2Sopenharmony_ci        return;
811fb299fa2Sopenharmony_ci    }
812fb299fa2Sopenharmony_ci    if (upParams.factoryResetMode == "factory_wipe_data") {
813fb299fa2Sopenharmony_ci        Utils::SetParameter("odm.factory.updater.succssful_flg", "1");
814fb299fa2Sopenharmony_ci        LOG(INFO) << "factory wipe data, sleep...";
815fb299fa2Sopenharmony_ci        Utils::UsSleep(120 * DISPLAY_TIME); // 120 : 120s
816fb299fa2Sopenharmony_ci    }
817fb299fa2Sopenharmony_ci    upParams.forceUpdate || upParams.factoryResetMode == "factory_wipe_data" ?
818fb299fa2Sopenharmony_ci        Utils::DoShutdown("Updater update success go shut down") :
819fb299fa2Sopenharmony_ci            Utils::UpdaterDoReboot("", "Updater update success");
820fb299fa2Sopenharmony_ci}
821fb299fa2Sopenharmony_ci
822fb299fa2Sopenharmony_ciint UpdaterMain(int argc, char **argv)
823fb299fa2Sopenharmony_ci{
824fb299fa2Sopenharmony_ci    [[maybe_unused]] UpdaterStatus status = UPDATE_UNKNOWN;
825fb299fa2Sopenharmony_ci    UpdaterParams upParams;
826fb299fa2Sopenharmony_ci    upParams.callbackProgress = [] (float value) { UPDATER_UI_INSTANCE.ShowProgress(value); };
827fb299fa2Sopenharmony_ci    UpdaterInit::GetInstance().InvokeEvent(UPDATER_PRE_INIT_EVENT);
828fb299fa2Sopenharmony_ci    std::vector<std::string> args = ParseParams(argc, argv);
829fb299fa2Sopenharmony_ci
830fb299fa2Sopenharmony_ci    LOG(INFO) << "Ready to start";
831fb299fa2Sopenharmony_ci#if !defined(UPDATER_UT) && defined(UPDATER_UI_SUPPORT)
832fb299fa2Sopenharmony_ci    UPDATER_UI_INSTANCE.InitEnv();
833fb299fa2Sopenharmony_ci#endif
834fb299fa2Sopenharmony_ci    UpdaterInit::GetInstance().InvokeEvent(UPDATER_INIT_EVENT);
835fb299fa2Sopenharmony_ci    PackageUpdateMode mode = UNKNOWN_UPDATE;
836fb299fa2Sopenharmony_ci    status = StartUpdater(args, argv, mode, upParams);
837fb299fa2Sopenharmony_ci#if !defined(UPDATER_UT) && defined(UPDATER_UI_SUPPORT)
838fb299fa2Sopenharmony_ci    UPDATER_UI_INSTANCE.Sleep(UI_SHOW_DURATION);
839fb299fa2Sopenharmony_ci    if (status != UPDATE_SUCCESS && status != UPDATE_SKIP) {
840fb299fa2Sopenharmony_ci        if (mode == HOTA_UPDATE) {
841fb299fa2Sopenharmony_ci            UPDATER_UI_INSTANCE.ShowFailedPage();
842fb299fa2Sopenharmony_ci            UpdaterInit::GetInstance().InvokeEvent(UPDATER_POST_INIT_EVENT);
843fb299fa2Sopenharmony_ci            if (upParams.forceReboot) {
844fb299fa2Sopenharmony_ci                Utils::UsSleep(5 * DISPLAY_TIME); // 5 : 5s
845fb299fa2Sopenharmony_ci                PostUpdater(true);
846fb299fa2Sopenharmony_ci                Utils::UpdaterDoReboot("", "Updater night update fail");
847fb299fa2Sopenharmony_ci                return 0;
848fb299fa2Sopenharmony_ci            }
849fb299fa2Sopenharmony_ci        } else if (mode == SDCARD_UPDATE) {
850fb299fa2Sopenharmony_ci            UPDATER_UI_INSTANCE.ShowLogRes(
851fb299fa2Sopenharmony_ci                status == UPDATE_CORRUPT ? TR(LOGRES_VERIFY_FAILED) : TR(LOGRES_UPDATE_FAILED));
852fb299fa2Sopenharmony_ci            UPDATER_UI_INSTANCE.ShowFailedPage();
853fb299fa2Sopenharmony_ci        } else if (upParams.factoryResetMode == "user_wipe_data" ||
854fb299fa2Sopenharmony_ci            upParams.factoryResetMode == "menu_wipe_data" || upParams.factoryResetMode == "factory_wipe_data") {
855fb299fa2Sopenharmony_ci            UPDATER_UI_INSTANCE.ShowFailedPage();
856fb299fa2Sopenharmony_ci        } else if (CheckUpdateMode(USB_UPDATE_FAIL)) {
857fb299fa2Sopenharmony_ci            (void)UPDATER_UI_INSTANCE.SetMode(UPDATERMODE_USBUPDATE);
858fb299fa2Sopenharmony_ci            UPDATER_UI_INSTANCE.ShowFailedPage();
859fb299fa2Sopenharmony_ci        } else {
860fb299fa2Sopenharmony_ci            UPDATER_UI_INSTANCE.ShowMainpage();
861fb299fa2Sopenharmony_ci            UPDATER_UI_INSTANCE.SaveScreen();
862fb299fa2Sopenharmony_ci        }
863fb299fa2Sopenharmony_ci        // Wait for user input
864fb299fa2Sopenharmony_ci        while (true) {
865fb299fa2Sopenharmony_ci            Utils::UsSleep(DISPLAY_TIME);
866fb299fa2Sopenharmony_ci        }
867fb299fa2Sopenharmony_ci        return 0;
868fb299fa2Sopenharmony_ci    }
869fb299fa2Sopenharmony_ci#endif
870fb299fa2Sopenharmony_ci    PostUpdater(true);
871fb299fa2Sopenharmony_ci    RebootAfterUpdateSuccess(upParams);
872fb299fa2Sopenharmony_ci    return 0;
873fb299fa2Sopenharmony_ci}
874fb299fa2Sopenharmony_ci} // Updater
875