1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "firmware_download_executor.h"
17 
18 #include <cinttypes>
19 #include <unistd.h>
20 #include <sys/stat.h>
21 #include <thread>
22 
23 #include "constant.h"
24 #include "dupdate_errno.h"
25 #include "download_info.h"
26 #include "firmware_callback_utils.h"
27 #include "firmware_component_operator.h"
28 #include "firmware_log.h"
29 #include "firmware_task_operator.h"
30 #include "firmware_update_helper.h"
31 #include "progress_thread.h"
32 #include "string_utils.h"
33 
34 namespace OHOS {
35 namespace UpdateEngine {
36 const mode_t MKDIR_MODE = 0777;
Execute()37 void FirmwareDownloadExecutor::Execute()
38 {
39     FIRMWARE_LOGI("FirmwareDownloadExecutor::Execute");
40     std::thread downloadThread([this] { this->DoDownload(); });
41     downloadThread.detach();
42 }
43 
DoDownload()44 void FirmwareDownloadExecutor::DoDownload()
45 {
46     FirmwareComponentOperator().QueryAll(components_);
47     FIRMWARE_LOGI("Execute size %{public}d", CAST_INT(components_.size()));
48     if (components_.size() == 0) {
49         Progress progress;
50         progress.status = UpgradeStatus::DOWNLOAD_FAIL;
51         progress.endReason = "no task";
52         firmwareProgressCallback_.progressCallback(progress);
53         return;
54     }
55 
56     GetTask();
57     if (tasks_.downloadTaskId.empty()) {
58         // 首次触发下载
59         PerformDownload();
60     } else {
61         // 恢复下载
62         Progress progress;
63         progress.status = UpgradeStatus::DOWNLOAD_FAIL;
64         progress.endReason = "not support";
65         firmwareProgressCallback_.progressCallback(progress);
66         return;
67     }
68 }
69 
PerformDownload()70 void FirmwareDownloadExecutor::PerformDownload()
71 {
72     std::vector<DownloadInfo> downLoadInfos;
73     for (const auto &component : components_) {
74         DownloadInfo downloadInfo;
75         downloadInfo.versionId = component.url;
76         downloadInfo.url = component.url;
77         downloadInfo.path = component.spath;
78         downloadInfo.packageSize = component.size;
79         downloadInfo.veriftInfo = component.verifyInfo;
80         downloadInfo.isNeedAutoResume = false;
81         downLoadInfos.push_back(downloadInfo);
82         FIRMWARE_LOGD("downloadInfo %s", downloadInfo.ToString().c_str());
83 
84         if (access(Constant::DUPDATE_ENGINE_PACKAGE_ROOT_PATH.c_str(), 0) == -1) {
85             mkdir(Constant::DUPDATE_ENGINE_PACKAGE_ROOT_PATH.c_str(), MKDIR_MODE);
86         }
87 
88         Progress progress0 = {0, UpgradeStatus::DOWNLOADING, ""};
89 
90         std::string downloadFileName = downloadInfo.path;
91         int64_t localFileLength = static_cast<int64_t>(DownloadThread::GetLocalFileLength(downloadFileName));
92         ENGINE_LOGI("Download %{public}" PRId64 ", %{public}s", localFileLength, downloadFileName.c_str());
93         if (localFileLength == downloadInfo.packageSize && downloadInfo.packageSize != 0) {
94             progress0.percent = DOWNLOAD_FINISH_PERCENT;
95             progress0.status = UpgradeStatus::DOWNLOAD_SUCCESS;
96             DownloadCallback(downloadInfo.url, downloadFileName, progress0);
97         }
98         upgradeStatus_ = UpgradeStatus::DOWNLOADING;
99         downloadThread_ = std::make_shared<DownloadThread>(
100             [&](const std::string serverUrl, const std::string &fileName,
101                 const Progress &progress) -> void {
102                 DownloadCallback(serverUrl, fileName, progress);
103             });
104         int32_t ret = downloadThread_->StartDownload(downloadFileName, downloadInfo.url);
105         if (ret != 0) {
106             progress0 = {};
107             progress0.status = UpgradeStatus::DOWNLOAD_FAIL;
108             progress0.endReason = std::to_string(CAST_INT(DownloadEndReason::FAIL));
109             firmwareProgressCallback_.progressCallback(progress0);
110         }
111     }
112 
113     DelayedSingleton<FirmwareCallbackUtils>::GetInstance()->NotifyEvent(
114         tasks_.taskId, EventId::EVENT_DOWNLOAD_START, UpgradeStatus::DOWNLOADING);
115 }
116 
GetTask()117 void FirmwareDownloadExecutor::GetTask()
118 {
119     FirmwareTaskOperator().QueryTask(tasks_);
120 }
121 
DownloadCallback(std::string serverUrl,std::string packageName,Progress progress)122 void FirmwareDownloadExecutor::DownloadCallback(std::string serverUrl, std::string packageName, Progress progress)
123 {
124     ENGINE_LOGD("FirmwareDownloadExecutor::DownloadCallback progress.status = %{public}d,"
125         " progress.percent = %{public}d", progress.status, progress.percent);
126     Progress downloadProgress {};
127     upgradeStatus_ = UpgradeStatus::DOWNLOADING;
128     if (progress.status == UpgradeStatus::DOWNLOAD_FAIL ||
129         progress.status == UpgradeStatus::DOWNLOAD_SUCCESS) {
130         upgradeStatus_ = progress.status;
131     }
132     downloadProgress.percent = progress.percent;
133     downloadProgress.status = progress.status;
134     downloadProgress.endReason = progress.endReason;
135 
136 #ifdef UPDATER_UT
137     upgradeStatus_ = UpgradeStatus::DOWNLOAD_SUCCESS;
138 #endif
139     std::string fileName = packageName;
140     ENGINE_LOGI("DownloadCallback status: %{public}d progress: %{public}d", progress.status, progress.percent);
141 
142     if (upgradeStatus_ == UpgradeStatus::DOWNLOAD_SUCCESS) {
143         ENGINE_LOGI("DownloadCallback fileName %{public}s", fileName.c_str());
144         if (!VerifyDownloadPkg(fileName, downloadProgress)) {
145             // If the verification fails, delete the corresponding package.
146             remove(fileName.c_str());
147             downloadProgress.status = UpgradeStatus::DOWNLOAD_FAIL;
148             downloadProgress.endReason = std::to_string(DUpdateErrno::DUPDATE_ERR_VERIFY_PACKAGE_FAIL);
149         }
150     }
151 
152     FirmwareComponentOperator firmwareComponentOperator;
153     // 单包进度插入到 component 表
154     ENGINE_LOGI("DownloadCallback serverUrl %s, status %{public}d %{public}d", serverUrl.c_str(),
155         progress.status, progress.percent);
156     firmwareComponentOperator.UpdateProgressByUrl(serverUrl, progress.status, progress.percent);
157     // 整体进度插入到 task 表
158     FirmwareTaskOperator().UpdateProgressByTaskId(tasks_.taskId, downloadProgress.status, downloadProgress.percent);
159     firmwareProgressCallback_.progressCallback(downloadProgress);
160 }
161 
VerifyDownloadPkg(const std::string & pkgName,Progress & progress)162 bool FirmwareDownloadExecutor::VerifyDownloadPkg(const std::string &pkgName, Progress &progress)
163 {
164     std::string verifyInfo = "";
165     for (const auto &component : components_) {
166         if (component.spath == pkgName) {
167             verifyInfo = component.verifyInfo;
168             break;
169         }
170     }
171     ENGINE_LOGI("Start Checking file Sha256 %{public}s, verifyInfo %{public}s", pkgName.c_str(), verifyInfo.c_str());
172     if (!verifyInfo.empty() && !Sha256Utils::CheckFileSha256String(pkgName, verifyInfo)) {
173         ENGINE_LOGE("file sha256 check error, fileName:%{public}s", pkgName.c_str());
174         return false;
175     }
176     return true;
177 }
178 } // namespace UpdateEngine
179 } // namespace OHOS
180