1 /*
2 * Copyright (c) 2025 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_stream_installer_install.h"
17
18 #include <dirent.h>
19 #include <iostream>
20 #include <unistd.h>
21
22 #include "isys_installer.h"
23 #include "sys_installer_kits_impl.h"
24
25 #include "config_parse.h"
26 #include "dupdate_errno.h"
27 #include "firmware_constant.h"
28 #include "firmware_log.h"
29 #include "firmware_sys_installer_callback.h"
30 #include "firmware_update_helper.h"
31
32 namespace OHOS {
33 namespace UpdateService {
34
IsComponentLegal(const std::vector<FirmwareComponent> & componentList)35 bool StreamInstallerInstall::IsComponentLegal(const std::vector<FirmwareComponent> &componentList)
36 {
37 return true;
38 }
39
PerformInstall(const std::vector<FirmwareComponent> & componentList,UpgradeStatus & status)40 bool StreamInstallerInstall::PerformInstall(const std::vector<FirmwareComponent> &componentList, UpgradeStatus &status)
41 {
42 FIRMWARE_LOGI("StreamInstallerInstall::PerformInstall");
43 if (componentList.empty()) {
44 return false;
45 }
46 uint32_t successCount = 0;
47 for (const auto &component : componentList) {
48 if (onInstallCallback_.onFirmwareStatus == nullptr) {
49 FIRMWARE_LOGE("StreamInstallerInstall PerformInstall onFirmwareStatus is null");
50 continue;
51 }
52 onInstallCallback_.onFirmwareStatus(UpgradeStatus::INSTALLING);
53 if (InstallComponentWithRetry(component)) {
54 successCount++;
55 }
56 }
57 if (sysInstallProgress_.status != UpgradeStatus::INSTALL_FAIL) {
58 status = downloadProgress_.status;
59 }
60
61 return successCount == static_cast<uint32_t>(componentList.size());
62 }
63
InstallComponentWithRetry(const FirmwareComponent & component)64 bool StreamInstallerInstall::InstallComponentWithRetry(const FirmwareComponent &component)
65 {
66 int16_t retry = 0;
67 while (retry < MAX_RETRY_COUNT) {
68 FIRMWARE_LOGI("InstallComponentWithRetry PerformInstall retry = %{public}d", retry);
69
70 FirmwareComponent refreshComponent;
71 FirmwareComponentOperator().QueryByUrl(component.url, refreshComponent);
72
73 if (DoSysInstall(refreshComponent) == OHOS_SUCCESS) {
74 return true;
75 } else {
76 if (downloadProgress_.status == UpgradeStatus::DOWNLOAD_CANCEL) {
77 return false;
78 }
79 }
80
81 retry++;
82 usleep(RETRY_INTERVAL_TIME);
83 }
84
85 return false;
86 }
87
DoSysInstall(const FirmwareComponent & component)88 int32_t StreamInstallerInstall::DoSysInstall(const FirmwareComponent &component)
89 {
90 #ifndef UPDATER_UT
91 SysInstaller::SysInstallerKitsImpl::GetInstance().StopStreamUpdate();
92 #endif
93 downloadProgress_.status = UpgradeStatus::INIT;
94 sysInstallProgress_.status = UpgradeStatus::INIT;
95 FIRMWARE_LOGI("DoSysInstall, status=%{public}d", component.status);
96 FirmwareComponent firmwareComponent = component;
97
98 int32_t ret = InitSysInstaller(firmwareComponent.versionId);
99 if (ret != OHOS_SUCCESS) {
100 return ret;
101 }
102
103 // Set the callback for the installer
104 ret = SetInstallerCallback(firmwareComponent);
105 if (ret != OHOS_SUCCESS) {
106 return ret;
107 }
108
109 ret = StartInstallProcess(firmwareComponent);
110 if (ret != OHOS_SUCCESS) {
111 return ret;
112 }
113 return WaitInstallResult();
114 }
115
InitSysInstaller(const std::string & versionId)116 int32_t StreamInstallerInstall::InitSysInstaller(const std::string &versionId)
117 {
118 #ifndef UPDATER_UT
119 int32_t ret = SysInstaller::SysInstallerKitsImpl::GetInstance().SysInstallerInit(versionId, true);
120 if (ret != OHOS_SUCCESS) {
121 FIRMWARE_LOGE("sys installer init failed");
122 errMsg_.errorMessage = "sys installer init failed";
123 errMsg_.errorCode = DUPDATE_ERR_IPC_ERROR;
124 return OHOS_FAILURE;
125 }
126 int32_t updateStatus = SysInstaller::SysInstallerKitsImpl::GetInstance().GetUpdateStatus(versionId);
127 if (updateStatus != CAST_INT(SysInstaller::UpdateStatus::UPDATE_STATE_INIT)) {
128 FIRMWARE_LOGE("StartUnpack status: %{public}d , system busy", updateStatus);
129 errMsg_.errorMessage = "sys installer is busy";
130 errMsg_.errorCode = ret;
131 return OHOS_FAILURE;
132 }
133 #endif
134 return OHOS_SUCCESS;
135 }
136
SetInstallerCallback(FirmwareComponent & component)137 int32_t StreamInstallerInstall::SetInstallerCallback(FirmwareComponent &component)
138 {
139 #ifndef UPDATER_UT
140 SysInstallerExecutorCallback callback{[&](const InstallProgress &installProgress) {
141 component.status = installProgress.progress.status;
142 component.recordPoint += installProgress.dealLen;
143 if (component.size > 0) {
144 component.progress = static_cast<double>(component.recordPoint) / component.size * Firmware::ONE_HUNDRED;
145 }
146 if (onInstallCallback_.onFirmwareProgress == nullptr) {
147 FIRMWARE_LOGE("SysInstallerExecutorCallback onFirmwareProgress is null");
148 return;
149 }
150 onInstallCallback_.onFirmwareProgress(component);
151 sysInstallProgress_ = installProgress.progress;
152 if (Firmware::ONE_HUNDRED == component.progress) {
153 sysInstallProgress_.status = UpgradeStatus::INSTALL_SUCCESS;
154 }
155 errMsg_ = installProgress.errMsg;
156 if (component.status == UpgradeStatus::INSTALL_FAIL ||
157 component.status == UpgradeStatus::INSTALL_SUCCESS) {
158 NotifyCondition();
159 }
160 }};
161
162 sptr<SysInstaller::ISysInstallerCallbackFunc> cb = new SysInstallerCallback(callback);
163 if (cb == nullptr) {
164 FIRMWARE_LOGE("sys installer callback is nullptr");
165 errMsg_.errorMessage = "sys installer callback is nullptr";
166 errMsg_.errorCode = DUPDATE_ERR_IPC_ERROR;
167 return OHOS_FAILURE;
168 }
169
170 int32_t ret = SysInstaller::SysInstallerKitsImpl::GetInstance().SetUpdateCallback(component.versionId, cb);
171 if (ret != OHOS_SUCCESS) {
172 FIRMWARE_LOGE("set sys installer callback failed");
173 errMsg_.errorMessage = "set sys installer callback failed";
174 errMsg_.errorCode = ret;
175 }
176 return ret;
177 #else
178 return OHOS_SUCCESS;
179 #endif
180 }
181
StartInstallProcess(FirmwareComponent & component)182 int32_t StreamInstallerInstall::StartInstallProcess(FirmwareComponent &component)
183 {
184 #ifndef UPDATER_UT
185 auto ret = SysInstaller::SysInstallerKitsImpl::GetInstance().StartStreamUpdate();
186 if (ret != OHOS_SUCCESS) {
187 errMsg_.errorMessage = "sys installer StartStreamUpdate failed";
188 errMsg_.errorCode = ret;
189 FIRMWARE_LOGE("sys installer StartStreamUpdate failed ret = %{public}d", ret);
190 return OHOS_FAILURE;
191 }
192 downloadThread_ = std::make_shared<StreamProgressThread>([&](const Progress &progress) -> void {
193 downloadProgress_ = progress;
194 if (downloadProgress_.status == UpgradeStatus::DOWNLOAD_FAIL) {
195 errMsg_.errorMessage = "download fail";
196 errMsg_.errorCode = -1;
197 NotifyCondition();
198 } else if (downloadProgress_.status == UpgradeStatus::DOWNLOAD_CANCEL) {
199 NotifyCondition();
200 } else {
201 }
202 });
203 ret = downloadThread_->StartDownload(component.url, component.size, component.recordPoint);
204 if (ret != OHOS_SUCCESS) {
205 errMsg_.errorMessage = "StartDownload failed";
206 errMsg_.errorCode = ret;
207 FIRMWARE_LOGE("StartDownload failed ret = %{public}d", ret);
208 return OHOS_FAILURE;
209 }
210 #endif
211 return OHOS_SUCCESS;
212 }
213
NotifyCondition()214 void StreamInstallerInstall::NotifyCondition()
215 {
216 std::lock_guard<std::mutex> lock(installMutex_);
217 installCond_.notify_all();
218 }
219
WaitInstallResult()220 int32_t StreamInstallerInstall::WaitInstallResult()
221 {
222 #ifndef UPDATER_UT
223 std::unique_lock<std::mutex> lock(installMutex_);
224 int32_t ret = OHOS_SUCCESS;
225 uint32_t configTime = DelayedSingleton<ConfigParse>::GetInstance()->GetStreamInstallerTimeout();
226 FIRMWARE_LOGI("sysinstaller wait result, max wait time=%{public}u", configTime);
227 if (!installCond_.wait_for(lock, std::chrono::seconds(configTime), [this] {
228 return (sysInstallProgress_.status == UpgradeStatus::INSTALL_SUCCESS) ||
229 (sysInstallProgress_.status == UpgradeStatus::INSTALL_FAIL) ||
230 (downloadProgress_.status == UpgradeStatus::DOWNLOAD_FAIL) ||
231 (downloadProgress_.status == UpgradeStatus::DOWNLOAD_CANCEL);
232 })) {
233 FIRMWARE_LOGE("WaitInstallResult time out");
234 ret = OHOS_FAILURE;
235 } else {
236 if (sysInstallProgress_.status == UpgradeStatus::INSTALL_SUCCESS) {
237 FIRMWARE_LOGI("WaitInstallResult INSTALL_SUCCESS");
238 ret = OHOS_SUCCESS;
239 } else {
240 FIRMWARE_LOGE("WaitInstallResult fail, sysInstallProgress_.status=%{public}d, "
241 "downloadProgress_.status=%{public}d", CAST_INT(sysInstallProgress_.status),
242 CAST_INT(downloadProgress_.status));
243 ret = OHOS_FAILURE;
244 }
245 }
246 // 停止下载线程
247 downloadThread_->StopDownload();
248 // 停止数据处理线程
249 SysInstaller::SysInstallerKitsImpl::GetInstance().StopStreamUpdate();
250 return ret;
251 #else
252 return OHOS_SUCCESS;
253 #endif
254 }
255 } // namespace UpdateService
256 } // namespace OHOS
257