1 /*
2 * Copyright (c) 2024 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 "ext_extension.h"
17
18 #include <algorithm>
19 #include <chrono>
20 #include <fstream>
21 #include <iomanip>
22 #include <map>
23 #include <regex>
24 #include <string>
25 #include <thread>
26 #include <tuple>
27 #include <unordered_map>
28 #include <vector>
29
30 #include <directory_ex.h>
31 #include <sys/stat.h>
32 #include <unistd.h>
33
34 #include <directory_ex.h>
35 #include <unique_fd.h>
36
37 #include "accesstoken_kit.h"
38 #include "bundle_mgr_client.h"
39 #include "errors.h"
40 #include "ipc_skeleton.h"
41
42 #include "b_error/b_error.h"
43 #include "b_error/b_excep_utils.h"
44 #include "b_filesystem/b_dir.h"
45 #include "b_filesystem/b_file.h"
46 #include "b_filesystem/b_file_hash.h"
47 #include "b_json/b_json_cached_entity.h"
48 #include "b_jsonutil/b_jsonutil.h"
49 #include "b_ohos/startup/backup_para.h"
50 #include "b_radar/b_radar.h"
51 #include "b_tarball/b_tarball_factory.h"
52 #include "filemgmt_libhilog.h"
53 #include "hitrace_meter.h"
54 #include "i_service.h"
55 #include "sandbox_helper.h"
56 #include "service_proxy.h"
57 #include "tar_file.h"
58 #include "b_anony/b_anony.h"
59
60 namespace OHOS::FileManagement::Backup {
61 const uint32_t MAX_FD_GROUP_USE_TIME = 1000; // 每组打开最大时间1000ms
62
WaitToSendFd(std::chrono::system_clock::time_point & startTime,int & fdSendNum)63 void BackupExtExtension::WaitToSendFd(std::chrono::system_clock::time_point &startTime, int &fdSendNum)
64 {
65 HILOGD("WaitToSendFd Begin");
66 std::unique_lock<std::mutex> lock(startSendMutex_);
67 startSendFdRateCon_.wait(lock, [this] { return sendRate_ > 0; });
68 if (fdSendNum >= sendRate_) {
69 HILOGI("current time fd num is max rate, bundle name:%{public}s, rate:%{public}d", bundleName_.c_str(),
70 sendRate_);
71 auto curTime = std::chrono::system_clock::now();
72 auto useTimeMs = std::chrono::duration_cast<std::chrono::milliseconds>(curTime - startTime).count();
73 if (useTimeMs < MAX_FD_GROUP_USE_TIME) {
74 int32_t sleepTime = MAX_FD_GROUP_USE_TIME - useTimeMs;
75 HILOGI("will wait time:%{public}d ms", sleepTime);
76 std::this_thread::sleep_for(std::chrono::milliseconds(sleepTime));
77 } else {
78 HILOGW("current fd send num exceeds one second");
79 }
80 fdSendNum = 0;
81 startTime = std::chrono::system_clock::now();
82 }
83 HILOGD("WaitToSendFd End");
84 }
85
RefreshTimeInfo(std::chrono::system_clock::time_point & startTime,int & fdSendNum)86 void BackupExtExtension::RefreshTimeInfo(std::chrono::system_clock::time_point &startTime, int &fdSendNum)
87 {
88 auto currentTime = std::chrono::system_clock::now();
89 auto useTime = std::chrono::duration_cast<std::chrono::milliseconds>(currentTime - startTime).count();
90 if (useTime >= MAX_FD_GROUP_USE_TIME) {
91 HILOGI("RefreshTimeInfo Begin, fdSendNum is:%{public}d", fdSendNum);
92 startTime = std::chrono::system_clock::now();
93 fdSendNum = 0;
94 }
95 }
96
SetClearDataFlag(bool isClearData)97 void BackupExtExtension::SetClearDataFlag(bool isClearData)
98 {
99 isClearData_ = isClearData;
100 HILOGI("set clear data flag:%{public}d", isClearData);
101 if (extension_ == nullptr) {
102 HILOGE("Extension handle have been released");
103 return;
104 }
105 if (!extension_->WasFromSpecialVersion() && !extension_->RestoreDataReady()) {
106 DoClear();
107 }
108 }
109
GetBundlePath()110 string BackupExtExtension::GetBundlePath()
111 {
112 if (bundleName_ == BConstants::BUNDLE_FILE_MANAGER) {
113 return string(BConstants::PATH_FILEMANAGE_BACKUP_HOME).append(BConstants::SA_BUNDLE_BACKUP_RESTORE);
114 } else if (bundleName_ == BConstants::BUNDLE_MEDIAL_DATA) {
115 return string(BConstants::PATH_MEDIALDATA_BACKUP_HOME).append(BConstants::SA_BUNDLE_BACKUP_RESTORE);
116 }
117 return string(BConstants::PATH_BUNDLE_BACKUP_HOME).append(BConstants::SA_BUNDLE_BACKUP_RESTORE);
118 }
119
GetIdxFileInfos(bool isSpecialVersion)120 std::map<std::string, off_t> BackupExtExtension::GetIdxFileInfos(bool isSpecialVersion)
121 {
122 string restoreDir = isSpecialVersion ? "" : GetBundlePath();
123 auto extManageInfo = GetExtManageInfo();
124 std::map<std::string, off_t> idxFileInfos;
125 for (size_t i = 0; i < extManageInfo.size(); ++i) {
126 std::string realPath = restoreDir + extManageInfo[i].hashName;
127 idxFileInfos[realPath] = extManageInfo[i].sta.st_size;
128 }
129 return idxFileInfos;
130 }
131
CheckTmpDirFileInfos(bool isSpecialVersion)132 void BackupExtExtension::CheckTmpDirFileInfos(bool isSpecialVersion)
133 {
134 ErrFileInfo errFiles;
135 auto idxFileInfos = GetIdxFileInfos(isSpecialVersion);
136 struct stat attr;
137 for (auto it : idxFileInfos) {
138 if (it.first.size() >= PATH_MAX || stat(it.first.data(), &attr) == -1) {
139 HILOGE("(Debug) Failed to get stat of %{public}s, errno = %{public}d", GetAnonyPath(it.first).c_str(),
140 errno);
141 errFiles[it.first].push_back(errno);
142 } else if (it.second != attr.st_size && (!S_ISDIR(attr.st_mode))) {
143 HILOGE("(Debug) RecFile:%{public}s size err, recSize: %{public}" PRId64 ", idxSize: %{public}" PRId64 "",
144 GetAnonyPath(it.first).c_str(), attr.st_size, it.second);
145 errFiles[it.first] = std::vector<int>();
146 }
147 }
148 HILOGE("(Debug) Temp file check result: Total file: %{public}zu, err file: %{public}zu", idxFileInfos.size(),
149 errFiles.size());
150 if (!errFiles.empty()) {
151 HILOGE("(Debug) The received file and idx is not same");
152 std::stringstream ss;
153 ss << R"("totalFile": )" << idxFileInfos.size() << R"(, "restoreFile": )"
154 << idxFileInfos.size() - errFiles.size() << R"(, "info": "different received file and idx")";
155 AppRadar::Info info (bundleName_, "", ss.str());
156 AppRadar::GetInstance().RecordRestoreFuncRes(info, "BackupExtExtension::CheckTmpDirFileInfos",
157 AppRadar::GetInstance().GetUserId(), BizStageRestore::BIZ_STAGE_CHECK_DATA_FAIL,
158 static_cast<int32_t>(BError::BackupErrorCode::E_UKERR));
159 } else {
160 HILOGI("(Debug) The received file and idx is same");
161 }
162 }
163
CheckRestoreFileInfos()164 tuple<bool, vector<string>> BackupExtExtension::CheckRestoreFileInfos()
165 {
166 vector<string> errFiles;
167 struct stat curFileStat {};
168 for (const auto &it : endFileInfos_) {
169 if (lstat(it.first.c_str(), &curFileStat) != 0) {
170 HILOGE("Failed to lstat %{public}s, err = %{public}d", GetAnonyPath(it.first).c_str(), errno);
171 errFiles.emplace_back(it.first);
172 errFileInfos_[it.first].push_back(errno);
173 } else if (curFileStat.st_size != it.second && (!S_ISDIR(curFileStat.st_mode))) {
174 HILOGE("File size error, file: %{public}s, idx: %{public}" PRId64 ", act: %{public}" PRId64 "",
175 GetAnonyPath(it.first).c_str(), it.second, curFileStat.st_size);
176 errFiles.emplace_back(it.first);
177 errFileInfos_[it.first].push_back(errno);
178 }
179 }
180 for (const auto &it : errFileInfos_) {
181 for (const auto &codeIt : it.second) {
182 HILOGE("(Debug) errfileInfos file = %{public}s -> %{public}d", GetAnonyPath(it.first).c_str(), codeIt);
183 }
184 }
185 HILOGE("(Debug) End file check result Total file: %{public}zu, err file: %{public}zu", endFileInfos_.size(),
186 errFileInfos_.size());
187 if (errFiles.size()) {
188 std::stringstream ss;
189 ss << R"("totalFile": )" << endFileInfos_.size() << R"(, "restoreFile": )"
190 << endFileInfos_.size() - errFileInfos_.size();
191 AppRadar::Info info (bundleName_, "", ss.str());
192 AppRadar::GetInstance().RecordRestoreFuncRes(info, "BackupExtExtension::CheckRestoreFileInfos",
193 AppRadar::GetInstance().GetUserId(), BizStageRestore::BIZ_STAGE_CHECK_DATA_FAIL,
194 static_cast<int32_t>(BError::BackupErrorCode::E_UKERR));
195 return { false, errFiles };
196 }
197 return { true, errFiles };
198 }
199
OnRestoreCallback(wptr<BackupExtExtension> obj)200 std::function<void(ErrCode, std::string)> BackupExtExtension::OnRestoreCallback(wptr<BackupExtExtension> obj)
201 {
202 HILOGI("Begin get full restore onRestore callback");
203 return [obj](ErrCode errCode, std::string errMsg) {
204 auto extensionPtr = obj.promote();
205 if (extensionPtr == nullptr) {
206 HILOGE("Ext extension handle have been released");
207 return;
208 }
209 if (extensionPtr->isExecAppDone_.load()) {
210 HILOGE("Appdone has been executed for the current application");
211 return;
212 }
213 HILOGI("Current bundle will execute app done");
214 if (errCode == ERR_OK) {
215 auto spendTime = extensionPtr->GetOnStartTimeCost();
216 if (spendTime >= BConstants::MAX_TIME_COST) {
217 std::stringstream ss;
218 ss << R"("spendTime": )"<< spendTime << "ms";
219 AppRadar::Info info (extensionPtr->bundleName_, "", ss.str());
220 AppRadar::GetInstance().RecordRestoreFuncRes(info, "BackupExtExtension::OnRestoreCallback",
221 AppRadar::GetInstance().GetUserId(), BizStageRestore::BIZ_STAGE_ON_RESTORE, ERR_OK);
222 }
223 }
224 extensionPtr->FinishOnProcessTask();
225 if (errMsg.empty()) {
226 extensionPtr->AppDone(errCode);
227 } else {
228 std::string errInfo;
229 BJsonUtil::BuildExtensionErrInfo(errInfo, errCode, errMsg);
230 extensionPtr->AppResultReport(errInfo, BackupRestoreScenario::FULL_RESTORE, errCode);
231 }
232 extensionPtr->DoClear();
233 };
234 }
235
OnRestoreExCallback(wptr<BackupExtExtension> obj)236 std::function<void(ErrCode, std::string)> BackupExtExtension::OnRestoreExCallback(wptr<BackupExtExtension> obj)
237 {
238 HILOGI("Begin get full restore onRestoreEx callback");
239 return [obj](ErrCode errCode, const std::string restoreRetInfo) {
240 auto extensionPtr = obj.promote();
241 if (extensionPtr == nullptr) {
242 HILOGE("Ext extension handle have been released");
243 return;
244 }
245 if (extensionPtr->extension_ == nullptr) {
246 HILOGE("Extension handle have been released");
247 return;
248 }
249 if (extensionPtr->isExecAppDone_.load()) {
250 HILOGE("Appdone has been executed for the current application");
251 return;
252 }
253 if (errCode == ERR_OK && !restoreRetInfo.empty()) {
254 auto spendTime = extensionPtr->GetOnStartTimeCost();
255 if (spendTime >= BConstants::MAX_TIME_COST) {
256 std::stringstream ss;
257 ss << R"("spendTime": )"<< spendTime << "ms";
258 AppRadar::Info info (extensionPtr->bundleName_, "", ss.str());
259 AppRadar::GetInstance().RecordRestoreFuncRes(info, "BackupExtExtension::OnRestoreExCallback",
260 AppRadar::GetInstance().GetUserId(), BizStageRestore::BIZ_STAGE_ON_RESTORE, ERR_OK);
261 }
262 }
263 extensionPtr->FinishOnProcessTask();
264 extensionPtr->extension_->InvokeAppExtMethod(errCode, restoreRetInfo);
265 if (errCode == ERR_OK) {
266 if (restoreRetInfo.size()) {
267 HILOGI("Will notify restore result report");
268 extensionPtr->AppResultReport(restoreRetInfo, BackupRestoreScenario::FULL_RESTORE);
269 }
270 return;
271 }
272 if (restoreRetInfo.empty()) {
273 extensionPtr->AppDone(errCode);
274 extensionPtr->DoClear();
275 } else {
276 std::string errInfo;
277 BJsonUtil::BuildExtensionErrInfo(errInfo, errCode, restoreRetInfo);
278 extensionPtr->AppResultReport(errInfo, BackupRestoreScenario::FULL_RESTORE, errCode);
279 extensionPtr->DoClear();
280 }
281 };
282 }
283
AppDoneCallbackEx(wptr<BackupExtExtension> obj)284 std::function<void(ErrCode, std::string)> BackupExtExtension::AppDoneCallbackEx(wptr<BackupExtExtension> obj)
285 {
286 HILOGI("Begin get callback for appDone");
287 return [obj](ErrCode errCode, std::string errMsg) {
288 HILOGI("begin call callBackupExAppDone");
289 auto extensionPtr = obj.promote();
290 if (extensionPtr == nullptr) {
291 HILOGE("Ext extension handle have been released");
292 return;
293 }
294 extensionPtr->AppDone(errCode);
295 extensionPtr->DoClear();
296 };
297 }
298
IncreOnRestoreExCallback(wptr<BackupExtExtension> obj)299 std::function<void(ErrCode, std::string)> BackupExtExtension::IncreOnRestoreExCallback(wptr<BackupExtExtension> obj)
300 {
301 HILOGI("Begin get callback for increment onRestoreEx");
302 return [obj](ErrCode errCode, const std::string restoreRetInfo) {
303 HILOGI("begin call increment restoreEx");
304 auto extensionPtr = obj.promote();
305 if (extensionPtr == nullptr) {
306 HILOGE("Ext extension handle have been released");
307 return;
308 }
309 if (extensionPtr->extension_ == nullptr) {
310 HILOGE("Extension handle have been released");
311 return;
312 }
313 if (extensionPtr->isExecAppDone_.load()) {
314 HILOGE("Appdone has been executed for the current application");
315 return;
316 }
317 if (errCode == ERR_OK && !restoreRetInfo.empty()) {
318 auto spendTime = extensionPtr->GetOnStartTimeCost();
319 if (spendTime >= BConstants::MAX_TIME_COST) {
320 std::stringstream ss;
321 ss << R"("spendTime": )"<< spendTime << "ms";
322 AppRadar::Info info (extensionPtr->bundleName_, "", ss.str());
323 AppRadar::GetInstance().RecordRestoreFuncRes(info, "BackupExtExtension::IncreOnRestoreExCallback",
324 AppRadar::GetInstance().GetUserId(),
325 BizStageRestore::BIZ_STAGE_ON_RESTORE, ERR_OK);
326 }
327 }
328 extensionPtr->FinishOnProcessTask();
329 extensionPtr->extension_->InvokeAppExtMethod(errCode, restoreRetInfo);
330 if (errCode == ERR_OK) {
331 if (restoreRetInfo.size()) {
332 extensionPtr->AppResultReport(restoreRetInfo, BackupRestoreScenario::INCREMENTAL_RESTORE);
333 }
334 return;
335 }
336 if (restoreRetInfo.empty()) {
337 extensionPtr->AppIncrementalDone(errCode);
338 extensionPtr->DoClear();
339 } else {
340 std::string errInfo;
341 BJsonUtil::BuildExtensionErrInfo(errInfo, errCode, restoreRetInfo);
342 extensionPtr->AppResultReport(errInfo, BackupRestoreScenario::INCREMENTAL_RESTORE, errCode);
343 extensionPtr->DoClear();
344 }
345 };
346 }
347
IncreOnRestoreCallback(wptr<BackupExtExtension> obj)348 std::function<void(ErrCode, std::string)> BackupExtExtension::IncreOnRestoreCallback(wptr<BackupExtExtension> obj)
349 {
350 return [obj](ErrCode errCode, std::string errMsg) {
351 auto extensionPtr = obj.promote();
352 if (extensionPtr == nullptr) {
353 HILOGE("Ext extension handle have been released");
354 return;
355 }
356 if (extensionPtr->isExecAppDone_.load()) {
357 HILOGE("Appdone has been executed for the current application");
358 return;
359 }
360 HILOGI("Current bundle will execute app done");
361 if (errCode == ERR_OK) {
362 auto spendTime = extensionPtr->GetOnStartTimeCost();
363 if (spendTime >= BConstants::MAX_TIME_COST) {
364 std::stringstream ss;
365 ss << R"("spendTime": )"<< spendTime << "ms";
366 AppRadar::Info info (extensionPtr->bundleName_, "", ss.str());
367 AppRadar::GetInstance().RecordRestoreFuncRes(info, "BackupExtExtension::IncreOnRestoreCallback",
368 AppRadar::GetInstance().GetUserId(), BizStageRestore::BIZ_STAGE_ON_RESTORE, ERR_OK);
369 }
370 }
371 extensionPtr->FinishOnProcessTask();
372 if (errMsg.empty()) {
373 extensionPtr->AppIncrementalDone(errCode);
374 } else {
375 std::string errInfo;
376 BJsonUtil::BuildExtensionErrInfo(errInfo, errCode, errMsg);
377 extensionPtr->AppResultReport(errInfo, BackupRestoreScenario::INCREMENTAL_RESTORE, errCode);
378 }
379 extensionPtr->DoClear();
380 };
381 }
382
GetOnStartTimeCost()383 int32_t BackupExtExtension::GetOnStartTimeCost()
384 {
385 auto onBackupRestoreEnd = std::chrono::system_clock::now();
386 std::lock_guard<std::mutex> lock(onStartTimeLock_);
387 auto spendTime = std::chrono::duration_cast<std::chrono::milliseconds>(onBackupRestoreEnd - g_onStart).count();
388 return spendTime;
389 }
390
OnBackupCallback(wptr<BackupExtExtension> obj)391 std::function<void(ErrCode, const std::string)> BackupExtExtension::OnBackupCallback(wptr<BackupExtExtension> obj)
392 {
393 HILOGI("Begin get HandleFullBackupCallbackEx");
394 return [obj](ErrCode errCode, std::string errMsg) {
395 HILOGI("begin call backup");
396 auto extensionPtr = obj.promote();
397 if (extensionPtr == nullptr) {
398 HILOGE("Ext extension handle have been released");
399 return;
400 }
401 if (extensionPtr->extension_ == nullptr) {
402 HILOGE("Extension handle have been released");
403 return;
404 }
405 if (extensionPtr->isExecAppDone_.load()) {
406 HILOGE("Appdone has been executed for the current application");
407 return;
408 }
409 extensionPtr->FinishOnProcessTask();
410 if (errCode == ERR_OK) {
411 auto spendTime = extensionPtr->GetOnStartTimeCost();
412 if (spendTime >= BConstants::MAX_TIME_COST) {
413 AppRadar::Info info(extensionPtr->bundleName_, "", string("\"spend_time\":\" ").
414 append(to_string(spendTime)).append(string("ms\"")));
415 AppRadar::GetInstance().RecordBackupFuncRes(info, "BackupExtExtension::OnBackupCallback",
416 AppRadar::GetInstance().GetUserId(), BizStageBackup::BIZ_STAGE_ON_BACKUP,
417 static_cast<int32_t>(ERR_OK));
418 }
419 extensionPtr->AsyncTaskBackup(extensionPtr->extension_->GetUsrConfig());
420 return;
421 }
422 HILOGE("Call extension onBackup failed, errInfo = %{public}s", errMsg.c_str());
423 if (!errMsg.empty()) {
424 std::string errInfo;
425 BJsonUtil::BuildExtensionErrInfo(errInfo, errCode, errMsg);
426 extensionPtr->AppResultReport(errInfo, BackupRestoreScenario::FULL_BACKUP, errCode);
427 }
428 extensionPtr->AppDone(errCode);
429 extensionPtr->DoClear();
430 };
431 }
432
OnBackupExCallback(wptr<BackupExtExtension> obj)433 std::function<void(ErrCode, const std::string)> BackupExtExtension::OnBackupExCallback(wptr<BackupExtExtension> obj)
434 {
435 HILOGI("Begin get HandleFullBackupCallbackEx");
436 return [obj](ErrCode errCode, const std::string backupExRetInfo) {
437 HILOGI("begin call backup");
438 auto extensionPtr = obj.promote();
439 if (extensionPtr == nullptr) {
440 HILOGE("Ext extension handle have been released");
441 return;
442 }
443 if (extensionPtr->extension_ == nullptr) {
444 HILOGE("Extension handle have been released");
445 return;
446 }
447 if (extensionPtr->isExecAppDone_.load()) {
448 HILOGE("Appdone has been executed for the current application");
449 return;
450 }
451 extensionPtr->extension_->InvokeAppExtMethod(errCode, backupExRetInfo);
452 if (errCode == ERR_OK) {
453 if (backupExRetInfo.size()) {
454 auto spendTime = extensionPtr->GetOnStartTimeCost();
455 if (spendTime >= BConstants::MAX_TIME_COST) {
456 AppRadar::Info info(extensionPtr->bundleName_, "", string("\"spend_time\":\" ").
457 append(to_string(spendTime)).append(string("ms\"")));
458 AppRadar::GetInstance().RecordBackupFuncRes(info, "BackupExtExtension::OnBackupExCallback",
459 AppRadar::GetInstance().GetUserId(), BizStageBackup::BIZ_STAGE_ON_BACKUP,
460 static_cast<int32_t>(ERR_OK));
461 }
462 HILOGI("Will notify backup result report");
463 extensionPtr->FinishOnProcessTask();
464 extensionPtr->AsyncTaskBackup(extensionPtr->extension_->GetUsrConfig());
465 extensionPtr->AppResultReport(backupExRetInfo, BackupRestoreScenario::FULL_BACKUP);
466 }
467 return;
468 }
469 HILOGE("Call extension onBackupEx failed, errInfo = %{public}s", backupExRetInfo.c_str());
470 extensionPtr->FinishOnProcessTask();
471 if (!backupExRetInfo.empty()) {
472 std::string errInfo;
473 BJsonUtil::BuildExtensionErrInfo(errInfo, errCode, backupExRetInfo);
474 extensionPtr->AppResultReport(errInfo, BackupRestoreScenario::FULL_BACKUP, errCode);
475 }
476 extensionPtr->AppDone(errCode);
477 extensionPtr->DoClear();
478 };
479 }
480
IncOnBackupCallback(wptr<BackupExtExtension> obj)481 std::function<void(ErrCode, const std::string)> BackupExtExtension::IncOnBackupCallback(wptr<BackupExtExtension> obj)
482 {
483 HILOGI("Begin get IncOnBackupCallback");
484 return [obj](ErrCode errCode, std::string errMsg) {
485 HILOGI("App onbackup end");
486 auto proxy = ServiceProxy::GetInstance();
487 if (proxy == nullptr) {
488 throw BError(BError::Codes::EXT_BROKEN_BACKUP_SA, std::generic_category().message(errno));
489 }
490 auto extPtr = obj.promote();
491 if (extPtr == nullptr) {
492 HILOGE("Current extension execute call backup error, extPtr is empty");
493 return;
494 }
495 if (extPtr->isExecAppDone_.load()) {
496 HILOGE("Appdone has been executed for the current application");
497 return;
498 }
499 HILOGI("Start GetAppLocalListAndDoIncrementalBackup");
500 extPtr->FinishOnProcessTask();
501 if (errCode == ERR_OK) {
502 auto spendTime = extPtr->GetOnStartTimeCost();
503 if (spendTime >= BConstants::MAX_TIME_COST) {
504 AppRadar::Info info(extPtr->bundleName_, "", string("\"spend_time\":\" ").
505 append(to_string(spendTime)).append(string("ms\"")));
506 AppRadar::GetInstance().RecordBackupFuncRes(info, "BackupExtExtension::IncOnBackupCallback",
507 AppRadar::GetInstance().GetUserId(), BizStageBackup::BIZ_STAGE_ON_BACKUP,
508 static_cast<int32_t>(ERR_OK));
509 }
510 proxy->GetAppLocalListAndDoIncrementalBackup();
511 return;
512 }
513 HILOGE("Call extension IncOnBackup failed, errInfo = %{public}s", errMsg.c_str());
514 if (!errMsg.empty()) {
515 std::string errInfo;
516 BJsonUtil::BuildExtensionErrInfo(errInfo, errCode, errMsg);
517 extPtr->AppResultReport(errInfo, BackupRestoreScenario::INCREMENTAL_BACKUP, errCode);
518 }
519 extPtr->AppIncrementalDone(errCode);
520 extPtr->DoClear();
521 };
522 }
523
IncOnBackupExCallback(wptr<BackupExtExtension> obj)524 std::function<void(ErrCode, const std::string)> BackupExtExtension::IncOnBackupExCallback(wptr<BackupExtExtension> obj)
525 {
526 HILOGI("Begin get HandleIncBackupEx callback");
527 return [obj](ErrCode errCode, const std::string backupExRetInfo) {
528 auto proxy = ServiceProxy::GetInstance();
529 if (proxy == nullptr) {
530 throw BError(BError::Codes::EXT_BROKEN_BACKUP_SA, std::generic_category().message(errno));
531 }
532 auto extensionPtr = obj.promote();
533 if (extensionPtr == nullptr) {
534 HILOGE("Ext extension handle have been released");
535 return;
536 }
537 if (extensionPtr->extension_ == nullptr) {
538 HILOGE("Extension handle have been released");
539 return;
540 }
541 if (extensionPtr->isExecAppDone_.load()) {
542 HILOGE("Appdone has been executed for the current application");
543 return;
544 }
545 extensionPtr->extension_->InvokeAppExtMethod(errCode, backupExRetInfo);
546 if (errCode == ERR_OK) {
547 if (backupExRetInfo.size()) {
548 auto spendTime = extensionPtr->GetOnStartTimeCost();
549 if (spendTime >= BConstants::MAX_TIME_COST) {
550 AppRadar::Info info(extensionPtr->bundleName_, "", string("\"spend_time\":\" ").
551 append(to_string(spendTime)).append(string("ms\"")));
552 AppRadar::GetInstance().RecordBackupFuncRes(info, "BackupExtExtension::IncOnBackupExCallback",
553 AppRadar::GetInstance().GetUserId(), BizStageBackup::BIZ_STAGE_ON_BACKUP,
554 static_cast<int32_t>(ERR_OK));
555 }
556 HILOGI("Start GetAppLocalListAndDoIncrementalBackup");
557 extensionPtr->FinishOnProcessTask();
558 proxy->GetAppLocalListAndDoIncrementalBackup();
559 HILOGI("Will notify backup result report");
560 extensionPtr->AppResultReport(backupExRetInfo, BackupRestoreScenario::INCREMENTAL_BACKUP);
561 }
562 return;
563 }
564 HILOGE("Call extension IncOnBackupEx failed, errInfo = %{public}s", backupExRetInfo.c_str());
565 extensionPtr->FinishOnProcessTask();
566 if (!backupExRetInfo.empty()) {
567 std::string errInfo;
568 BJsonUtil::BuildExtensionErrInfo(errInfo, errCode, backupExRetInfo);
569 extensionPtr->AppResultReport(errInfo, BackupRestoreScenario::INCREMENTAL_BACKUP, errCode);
570 }
571 extensionPtr->AppIncrementalDone(errCode);
572 extensionPtr->DoClear();
573 };
574 }
575
ReportAppProcessInfo(const std::string processInfo,BackupRestoreScenario scenario)576 void BackupExtExtension::ReportAppProcessInfo(const std::string processInfo, BackupRestoreScenario scenario)
577 {
578 auto proxy = ServiceProxy::GetInstance();
579 if (proxy == nullptr) {
580 HILOGE("Report app process error, proxy is empty");
581 return;
582 }
583 HILOGI("Will notify backup sa process result");
584 auto ret = proxy->ReportAppProcessInfo(processInfo, scenario);
585 if (ret != ERR_OK) {
586 HILOGE("Report app process error, ipc failed, ret:%{public}d", ret);
587 return;
588 }
589 }
590
StartOnProcessTaskThread(wptr<BackupExtExtension> obj,BackupRestoreScenario scenario)591 ErrCode BackupExtExtension::StartOnProcessTaskThread(wptr<BackupExtExtension> obj, BackupRestoreScenario scenario)
592 {
593 HILOGI("Begin Create onProcess Task Thread");
594 onProcessTimeoutTimer_.Setup();
595 isFirstCallOnProcess_.store(true);
596 StartOnProcessTimeOutTimer(obj, scenario);
597 SyncCallJsOnProcessTask(obj, scenario);
598 if (isExecAppDone_.load()) {
599 HILOGE("Call onProcess timeout, Current extension finished");
600 return BError(BError::Codes::EXT_ABILITY_TIMEOUT);
601 }
602 callJsOnProcessThread_ = std::thread([obj, scenario]() {
603 auto extPtr = obj.promote();
604 if (extPtr == nullptr) {
605 HILOGE("Create onProcess Task thread failed, extPtr is empty");
606 return;
607 }
608 extPtr->ExecCallOnProcessTask(obj, scenario);
609 });
610 HILOGI("End Create onProcess Task End");
611 return BError(BError::Codes::OK);
612 }
613
ExecCallOnProcessTask(wptr<BackupExtExtension> obj,BackupRestoreScenario scenario)614 void BackupExtExtension::ExecCallOnProcessTask(wptr<BackupExtExtension> obj, BackupRestoreScenario scenario)
615 {
616 HILOGI("Begin");
617 isFirstCallOnProcess_.store(false);
618 while (!stopCallJsOnProcess_.load()) {
619 std::unique_lock<std::mutex> lock(onProcessLock_);
620 execOnProcessCon_.wait_for(lock, std::chrono::seconds(BConstants::CALL_APP_ON_PROCESS_TIME_INTERVAL),
621 [this] { return this->stopCallJsOnProcess_.load(); });
622 if (stopCallJsOnProcess_.load()) {
623 HILOGE("Current extension execute js onProcess method finished");
624 return;
625 }
626 HILOGI("Continue call js method onProcess");
627 StartOnProcessTimeOutTimer(obj, scenario);
628 AsyncCallJsOnProcessTask(obj, scenario);
629 }
630 HILOGI("End");
631 }
632
AsyncCallJsOnProcessTask(wptr<BackupExtExtension> obj,BackupRestoreScenario scenario)633 void BackupExtExtension::AsyncCallJsOnProcessTask(wptr<BackupExtExtension> obj, BackupRestoreScenario scenario)
634 {
635 HILOGI("Begin");
636 if (stopCallJsOnProcess_.load()) {
637 HILOGE("Current extension execute finished");
638 return;
639 }
640 auto task = [obj, scenario]() {
641 auto extPtr = obj.promote();
642 if (extPtr == nullptr) {
643 HILOGE("Async Call js onProcess error, extPtr is empty");
644 return;
645 }
646 extPtr->SyncCallJsOnProcessTask(obj, scenario);
647 };
648 onProcessTaskPool_.AddTask([task]() { task(); });
649 HILOGI("End");
650 }
651
SyncCallJsOnProcessTask(wptr<BackupExtExtension> obj,BackupRestoreScenario scenario)652 void BackupExtExtension::SyncCallJsOnProcessTask(wptr<BackupExtExtension> obj, BackupRestoreScenario scenario)
653 {
654 HILOGI("Begin");
655 if (stopCallJsOnProcess_.load()) {
656 HILOGE("Current extension execute finished");
657 return;
658 }
659 auto callBack = ReportOnProcessResultCallback(obj, scenario);
660 auto extenionPtr = obj.promote();
661 if (extenionPtr == nullptr) {
662 HILOGE("Async call js onProcess failed, extenionPtr is empty");
663 return;
664 }
665 ErrCode ret = extenionPtr->extension_->OnProcess(callBack);
666 if (ret != ERR_OK) {
667 HILOGE("Call OnProcess Failed, ret:%{public}d", ret);
668 return;
669 }
670 HILOGI("End");
671 }
672
FinishOnProcessTask()673 void BackupExtExtension::FinishOnProcessTask()
674 {
675 HILOGI("Begin");
676 std::unique_lock<std::mutex> lock(onProcessLock_);
677 stopCallJsOnProcess_.store(true);
678 isFirstCallOnProcess_.store(false);
679 isExecAppDone_.store(false);
680 onProcessTimeoutCnt_ = 0;
681 execOnProcessCon_.notify_one();
682 lock.unlock();
683 if (callJsOnProcessThread_.joinable()) {
684 callJsOnProcessThread_.join();
685 }
686 HILOGI("End");
687 }
688
StartOnProcessTimeOutTimer(wptr<BackupExtExtension> obj,BackupRestoreScenario scenario)689 void BackupExtExtension::StartOnProcessTimeOutTimer(wptr<BackupExtExtension> obj, BackupRestoreScenario scenario)
690 {
691 HILOGI("Begin");
692 if (stopCallJsOnProcess_.load()) {
693 HILOGE("Current extension execute finished");
694 return;
695 }
696 auto timeoutCallback = [obj, scenario]() {
697 auto extPtr = obj.promote();
698 if (extPtr == nullptr) {
699 HILOGE("Start Create timeout callback failed, extPtr is empty");
700 return;
701 }
702 if (extPtr->onProcessTimeoutCnt_.load() >= BConstants::APP_ON_PROCESS_TIMEOUT_MAX_COUNT ||
703 extPtr->isFirstCallOnProcess_.load()) {
704 HILOGE("The extension invokes the onProcess for more than three times or the first invoking of the "
705 "onProcess times out, timeoutCnt:%{public}d", extPtr->onProcessTimeoutCnt_.load());
706 std::unique_lock<std::mutex> lock(extPtr->onProcessLock_);
707 extPtr->stopCallJsOnProcess_.store(true);
708 extPtr->isFirstCallOnProcess_.store(false);
709 extPtr->isExecAppDone_.store(true);
710 extPtr->onProcessTimeoutCnt_ = 0;
711 extPtr->execOnProcessCon_.notify_one();
712 lock.unlock();
713 if (scenario == BackupRestoreScenario::FULL_BACKUP || scenario == BackupRestoreScenario::FULL_RESTORE) {
714 extPtr->AppDone(BError(BError::Codes::EXT_ABILITY_TIMEOUT));
715 } else if (scenario == BackupRestoreScenario::INCREMENTAL_BACKUP ||
716 scenario == BackupRestoreScenario::INCREMENTAL_RESTORE) {
717 extPtr->AppIncrementalDone(BError(BError::Codes::EXT_ABILITY_TIMEOUT));
718 }
719 return;
720 }
721 extPtr->onProcessTimeoutCnt_++;
722 extPtr->onProcessTimeout_.store(true);
723 HILOGE("Extension onProcess timeout, Increase cnt:%{public}d", extPtr->onProcessTimeoutCnt_.load());
724 };
725 int timeout = isFirstCallOnProcess_.load() ? BConstants::FIRST_CALL_APP_ON_PROCESS_MAX_TIMEOUT :
726 BConstants::APP_ON_PROCESS_MAX_TIMEOUT;
727 uint32_t timerId = onProcessTimeoutTimer_.Register(timeoutCallback, timeout, true);
728 onProcessTimeoutTimerId_ = timerId;
729 HILOGI("End");
730 }
731
CloseOnProcessTimeOutTimer()732 void BackupExtExtension::CloseOnProcessTimeOutTimer()
733 {
734 HILOGI("Begin");
735 onProcessTimeoutTimer_.Unregister(onProcessTimeoutTimerId_);
736 HILOGI("End");
737 }
738
AppIncrementalDone(ErrCode errCode)739 void BackupExtExtension::AppIncrementalDone(ErrCode errCode)
740 {
741 HILOGI("Begin");
742 auto proxy = ServiceProxy::GetInstance();
743 if (proxy == nullptr) {
744 HILOGE("Failed to obtain the ServiceProxy handle");
745 DoClear();
746 return;
747 }
748 auto ret = proxy->AppIncrementalDone(errCode);
749 if (ret != ERR_OK) {
750 HILOGE("Failed to notify the app done. err = %{public}d", ret);
751 }
752 }
753
GetBackupInfo(std::string & result)754 ErrCode BackupExtExtension::GetBackupInfo(std::string &result)
755 {
756 auto obj = wptr<BackupExtExtension>(this);
757 auto ptr = obj.promote();
758 if (ptr == nullptr) {
759 HILOGE("Failed to get ext extension.");
760 return BError(BError::Codes::EXT_INVAL_ARG, "extension getBackupInfo exception").GetCode();
761 }
762 if (ptr->extension_ == nullptr) {
763 HILOGE("Failed to get extension.");
764 return BError(BError::Codes::EXT_INVAL_ARG, "extension getBackupInfo exception").GetCode();
765 }
766 auto callBackup = [ptr](ErrCode errCode, const std::string result) {
767 if (ptr == nullptr) {
768 HILOGE("Failed to get ext extension.");
769 return;
770 }
771 HILOGI("GetBackupInfo callBackup start. errCode = %{public}d, result = %{public}s", errCode, result.c_str());
772 if (errCode == ERR_OK) {
773 ptr->backupInfo_ = result;
774 }
775 };
776 auto ret = ptr->extension_->GetBackupInfo(callBackup);
777 if (ret != ERR_OK) {
778 HILOGE("Failed to get backupInfo. err = %{public}d", ret);
779 return BError(BError::Codes::EXT_INVAL_ARG, "extension getBackupInfo exception").GetCode();
780 }
781 HILOGD("backupInfo = %s", backupInfo_.c_str());
782 result = backupInfo_;
783 backupInfo_.clear();
784
785 return ERR_OK;
786 }
787
UpdateFdSendRate(std::string & bundleName,int32_t sendRate)788 ErrCode BackupExtExtension::UpdateFdSendRate(std::string &bundleName, int32_t sendRate)
789 {
790 try {
791 std::lock_guard<std::mutex> lock(updateSendRateLock_);
792 HILOGI("Update SendRate, bundleName:%{public}s, sendRate:%{public}d", bundleName.c_str(), sendRate);
793 VerifyCaller();
794 bundleName_ = bundleName;
795 sendRate_ = sendRate;
796 if (sendRate > 0) {
797 startSendFdRateCon_.notify_one();
798 }
799 return ERR_OK;
800 } catch (...) {
801 HILOGE("Failed to UpdateFdSendRate");
802 return BError(BError::Codes::EXT_BROKEN_IPC).GetCode();
803 }
804 }
805
SetStagingPathProperties()806 bool BackupExtExtension::SetStagingPathProperties()
807 {
808 struct stat curBundleStat {};
809 if (lstat(BConstants::BUNDLE_BASE_DIR.c_str(), &curBundleStat) != 0) {
810 HILOGE("Failed to lstat, err = %{public}d", errno);
811 return false;
812 }
813 if (lchown(string(BConstants::PATH_BUNDLE_BACKUP_HOME).c_str(),
814 curBundleStat.st_uid, curBundleStat.st_gid) != 0) {
815 HILOGE("Failed to lchown, err = %{public}d", errno);
816 return false;
817 }
818 if (lchown(string(BConstants::PATH_BUNDLE_BACKUP_HOME_EL1).c_str(),
819 curBundleStat.st_uid, curBundleStat.st_gid) != 0) {
820 HILOGE("Failed to lchown, err = %{public}d", errno);
821 return false;
822 }
823 return true;
824 }
825
IfAllowToBackupRestore()826 bool BackupExtExtension::IfAllowToBackupRestore()
827 {
828 if (extension_ == nullptr) {
829 HILOGE("Failed to handle backup, extension is nullptr");
830 return false;
831 }
832 string usrConfig = extension_->GetUsrConfig();
833 BJsonCachedEntity<BJsonEntityExtensionConfig> cachedEntity(usrConfig);
834 auto cache = cachedEntity.Structuralize();
835 if (!cache.GetAllowToBackupRestore()) {
836 HILOGE("Application does not allow backup or restore");
837 return false;
838 }
839 return true;
840 }
841
User0OnBackup()842 ErrCode BackupExtExtension::User0OnBackup()
843 {
844 HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
845 if (!IfAllowToBackupRestore()) {
846 return BError(BError::Codes::EXT_FORBID_BACKUP_RESTORE, "Application does not allow backup or restore")
847 .GetCode();
848 }
849 AsyncTaskUser0Backup();
850 return ERR_OK;
851 }
852
AsyncTaskUser0Backup()853 void BackupExtExtension::AsyncTaskUser0Backup()
854 {
855 HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
856 auto task = [obj {wptr<BackupExtExtension>(this)}]() {
857 auto ptr = obj.promote();
858 BExcepUltils::BAssert(ptr, BError::Codes::EXT_BROKEN_FRAMEWORK, "Ext extension handle have been released");
859 const string config = ptr->extension_->GetUsrConfig();
860 try {
861 HILOGI("Do backup, start fwk timer begin.");
862 bool isFwkStart;
863 ptr->StartFwkTimer(isFwkStart);
864 if (!isFwkStart) {
865 HILOGE("Do backup, start fwk timer fail.");
866 return;
867 }
868 HILOGI("Do backup, start fwk timer end.");
869 BJsonCachedEntity<BJsonEntityExtensionConfig> cachedEntity(config);
870 auto cache = cachedEntity.Structuralize();
871 auto ret = ptr->User0DoBackup(cache);
872 if (ret != ERR_OK) {
873 HILOGE("User0DoBackup, err = %{pubilc}d", ret);
874 ptr->AppIncrementalDone(BError::GetCodeByErrno(ret));
875 }
876 } catch (const BError &e) {
877 HILOGE("extension: AsyncTaskBackup error, err code:%{public}d", e.GetCode());
878 ptr->AppIncrementalDone(e.GetCode());
879 } catch (const exception &e) {
880 HILOGE("Catched an unexpected low-level exception %{public}s", e.what());
881 ptr->AppIncrementalDone(BError(BError::Codes::EXT_INVAL_ARG).GetCode());
882 } catch (...) {
883 HILOGE("Failed to restore the ext bundle");
884 ptr->AppIncrementalDone(BError(BError::Codes::EXT_INVAL_ARG).GetCode());
885 }
886 };
887
888 threadPool_.AddTask([task]() {
889 try {
890 task();
891 } catch (...) {
892 HILOGE("Failed to add task to thread pool");
893 }
894 });
895 }
896
DoUser0Backup(const BJsonEntityExtensionConfig & usrConfig)897 void BackupExtExtension::DoUser0Backup(const BJsonEntityExtensionConfig &usrConfig)
898 {
899 HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
900 string path = string(BConstants::PATH_BUNDLE_BACKUP_HOME).append(BConstants::SA_BUNDLE_BACKUP_BACKUP);
901 if (mkdir(path.data(), S_IRWXU) && errno != EEXIST) {
902 throw BError(errno);
903 }
904 vector<string> includes = usrConfig.GetIncludes();
905 vector<string> excludes = usrConfig.GetExcludes();
906 auto task = [obj {wptr<BackupExtExtension>(this)}, includes, excludes]() {
907 auto ptr = obj.promote();
908 BExcepUltils::BAssert(ptr, BError::Codes::EXT_BROKEN_FRAMEWORK, "Ext extension handle have been released");
909 try {
910 auto [bigFile, smallFile] = BDir::GetBackupList(includes, excludes);
911 vector<struct ReportFileInfo> allFiles;
912 vector<struct ReportFileInfo> smallFiles;
913 vector<struct ReportFileInfo> bigFiles;
914 BDir::GetUser0FileStat(move(bigFile), move(smallFile), allFiles, smallFiles, bigFiles);
915 auto ret = ptr->DoIncrementalBackup(allFiles, smallFiles, bigFiles);
916 ptr->AppIncrementalDone(ret);
917 HILOGI("User0 backup app done %{public}d", ret);
918 } catch (const BError &e) {
919 ptr->AppIncrementalDone(e.GetCode());
920 } catch (const exception &e) {
921 ptr->AppIncrementalDone(BError(BError::Codes::EXT_INVAL_ARG).GetCode());
922 } catch (...) {
923 HILOGE("Failed to restore the ext bundle");
924 ptr->AppIncrementalDone(BError(BError::Codes::EXT_INVAL_ARG).GetCode());
925 }
926 };
927
928 threadPool_.AddTask([task]() {
929 try {
930 task();
931 } catch (...) {
932 HILOGE("Failed to add task to thread pool");
933 }
934 });
935 }
936
User0DoBackup(const BJsonEntityExtensionConfig & usrConfig)937 int BackupExtExtension::User0DoBackup(const BJsonEntityExtensionConfig &usrConfig)
938 {
939 HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
940 if (extension_ == nullptr) {
941 HILOGE("Failed to do backup, extension is nullptr");
942 return BError(BError::Codes::EXT_INVAL_ARG);
943 }
944 if (extension_->GetExtensionAction() != BConstants::ExtensionAction::BACKUP) {
945 return EPERM;
946 }
947 DoUser0Backup(usrConfig);
948 return ERR_OK;
949 }
950
ReportOnProcessResultCallback(wptr<BackupExtExtension> obj,BackupRestoreScenario scenario)951 std::function<void(ErrCode, std::string)> BackupExtExtension::ReportOnProcessResultCallback(
952 wptr<BackupExtExtension> obj, BackupRestoreScenario scenario)
953 {
954 return [obj, scenario](ErrCode errCode, const std::string processInfo) {
955 auto extPtr = obj.promote();
956 if (extPtr == nullptr) {
957 HILOGE("Async call js onPreocess callback failed, exPtr is empty");
958 return;
959 }
960 if (extPtr->onProcessTimeout_.load()) {
961 HILOGE("The result of invoking onProcess is timeout.");
962 extPtr->onProcessTimeout_.store(false);
963 return;
964 }
965 extPtr->CloseOnProcessTimeOutTimer();
966 extPtr->isFirstCallOnProcess_.store(false);
967 extPtr->onProcessTimeout_.store(false);
968 if (extPtr->onProcessTimeoutCnt_.load() > 0) {
969 extPtr->onProcessTimeoutCnt_ = 0;
970 HILOGI("onProcess execute success, reset onProcessTimeoutCnt");
971 }
972 if (processInfo.size() == 0) {
973 HILOGE("Current extension has no js method named onProcess.");
974 std::unique_lock<std::mutex> lock(extPtr->onProcessLock_);
975 extPtr->isFirstCallOnProcess_.store(false);
976 extPtr->stopCallJsOnProcess_.store(true);
977 extPtr->execOnProcessCon_.notify_one();
978 lock.unlock();
979 return;
980 }
981 std::string processInfoJsonStr;
982 BJsonUtil::BuildOnProcessRetInfo(processInfoJsonStr, processInfo);
983 auto task = [obj, scenario, processInfoJsonStr]() {
984 auto reportExtPtr = obj.promote();
985 if (reportExtPtr == nullptr) {
986 HILOGE("Report onProcess Result error, reportExtPtr is empty");
987 return;
988 }
989 reportExtPtr->ReportAppProcessInfo(processInfoJsonStr, scenario);
990 };
991 extPtr->reportOnProcessRetPool_.AddTask([task]() { task(); });
992 };
993 }
994 } // namespace OHOS::FileManagement::Backup
995