1 /*
2 * Copyright (c) 2022-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 "module_sched/sched_scheduler.h"
17
18 #include <atomic>
19 #include <cstdint>
20 #include <cstdio>
21 #include <fcntl.h>
22 #include <tuple>
23 #include <utility>
24
25 #include <sys/stat.h>
26
27 #include <directory_ex.h>
28 #include <unique_fd.h>
29
30 #include "b_error/b_error.h"
31 #include "b_ohos/startup/backup_para.h"
32 #include "b_radar/b_radar.h"
33 #include "filemgmt_libhilog.h"
34 #include "iservice_registry.h"
35 #include "module_external/bms_adapter.h"
36 #include "module_ipc/service.h"
37 #include "module_ipc/svc_session_manager.h"
38 #include "system_ability_definition.h"
39
40 namespace OHOS::FileManagement::Backup {
41 using namespace std;
42
ExtDiedClearFailRadarReport(const string & bundleName,IServiceReverse::Scenario scenario,ErrCode res)43 void ExtDiedClearFailRadarReport(const string& bundleName, IServiceReverse::Scenario scenario, ErrCode res)
44 {
45 if (res == ERR_OK) {
46 return;
47 }
48 AppRadar::Info info(bundleName, "", "");
49 if (scenario == IServiceReverse::Scenario::RESTORE) {
50 AppRadar::GetInstance().RecordRestoreFuncRes(info, "SchedScheduler::ExecutingQueueTasks",
51 AppRadar::GetInstance().GetUserId(), BizStageRestore::BIZ_STAGE_EXTENSION_ABNORMAL_EXIT_CLEAR_FAIL, res);
52 } else if (scenario == IServiceReverse::Scenario::BACKUP) {
53 AppRadar::GetInstance().RecordBackupFuncRes(info, "SchedScheduler::ExecutingQueueTasks",
54 AppRadar::GetInstance().GetUserId(), BizStageBackup::BIZ_STAGE_EXTENSION_ABNORMAL_EXIT_CLEAR_FAIL, res);
55 }
56 }
57
Sched(string bundleName)58 void SchedScheduler::Sched(string bundleName)
59 {
60 if (bundleName == "") {
61 if (sessionPtr_ == nullptr) {
62 HILOGE("Sched bundle %{public}s error, sessionPtr is empty", bundleName.c_str());
63 return;
64 }
65 if (!sessionPtr_->GetSchedBundleName(bundleName)) {
66 return;
67 }
68 }
69 HILOGE("Sched bundleName %{public}s", bundleName.data());
70 auto callStart = [schedPtr {wptr(this)}, bundleName]() {
71 try {
72 auto ptr = schedPtr.promote();
73 if (ptr == nullptr) {
74 HILOGE("Sched bundle %{public}s error, ptr is empty", bundleName.c_str());
75 return;
76 }
77 ptr->ExecutingQueueTasks(bundleName);
78 } catch (const BError &e) {
79 HILOGE("%{public}s", e.what());
80 } catch (const exception &e) {
81 HILOGE("%{public}s", e.what());
82 } catch (...) {
83 HILOGE("");
84 }
85 };
86 threadPool_.AddTask(callStart);
87 }
88
ExecutingQueueTasks(const string & bundleName)89 void SchedScheduler::ExecutingQueueTasks(const string &bundleName)
90 {
91 if (sessionPtr_ == nullptr) {
92 HILOGE("ExecutingQueueTasks bundle %{public}s error, sessionPtr is empty", bundleName.c_str());
93 return;
94 }
95 BConstants::ServiceSchedAction action = sessionPtr_->GetServiceSchedAction(bundleName);
96 if (action == BConstants::ServiceSchedAction::START) {
97 // register timer for connect extension
98 auto callStart = [reversePtr {reversePtr_}, bundleName]() {
99 HILOGE("Extension connect failed = %{public}s", bundleName.data());
100 auto ptr = reversePtr.promote();
101 if (ptr) {
102 ptr->ExtConnectFailed(bundleName, BError(BError::Codes::SA_BOOT_EXT_TIMEOUT));
103 }
104 };
105 auto iTime = extTime_.Register(callStart, BConstants::EXT_CONNECT_MAX_TIME, true);
106 unique_lock<shared_mutex> lock(lock_);
107 bundleTimeVec_.emplace_back(make_tuple(bundleName, iTime));
108 lock.unlock();
109 // launch extension
110 if (reversePtr_ != nullptr) {
111 ErrCode errCode = reversePtr_->LaunchBackupExtension(bundleName);
112 if (errCode) {
113 reversePtr_->ExtConnectFailed(bundleName, errCode);
114 }
115 }
116 } else if (action == BConstants::ServiceSchedAction::RUNNING) {
117 HILOGI("Current bundle %{public}s process is running", bundleName.data());
118 unique_lock<shared_mutex> lock(lock_);
119 auto iter = find_if(bundleTimeVec_.begin(), bundleTimeVec_.end(), [&bundleName](auto &obj) {
120 auto &[bName, iTime] = obj;
121 return bName == bundleName;
122 });
123 if (iter == bundleTimeVec_.end()) {
124 throw BError(BError::Codes::SA_INVAL_ARG, "Failed to find timer");
125 }
126 auto &[bName, iTime] = *iter;
127 // unregister timer
128 extTime_.Unregister(iTime);
129 lock.unlock();
130 //notify AppGallery to start restore
131 if (reversePtr_ != nullptr) {
132 reversePtr_->StartRunningTimer(bundleName);
133 reversePtr_->SendStartAppGalleryNotify(bundleName);
134 reversePtr_->ExtStart(bundleName);
135 }
136 } else if (action == BConstants::ServiceSchedAction::CLEAN) {
137 HILOGI("Current bundle %{public}s process is cleaning", bundleName.data());
138 ErrCode res = reversePtr_->ClearResidualBundleData(bundleName);
139 IServiceReverse::Scenario scenario = sessionPtr_->GetScenario();
140 ExtDiedClearFailRadarReport(bundleName, scenario, res);
141 }
142 }
143
RemoveExtConn(const string & bundleName)144 void SchedScheduler::RemoveExtConn(const string &bundleName)
145 {
146 unique_lock<shared_mutex> lock(lock_);
147 auto iter = find_if(bundleTimeVec_.begin(), bundleTimeVec_.end(), [&bundleName](auto &obj) {
148 auto &[bName, iTime] = obj;
149 return bName == bundleName;
150 });
151 if (iter != bundleTimeVec_.end()) {
152 auto &[bName, iTime] = *iter;
153 HILOGE("bundleName = %{public}s , iTime = %{public}d", bName.data(), iTime);
154 extTime_.Unregister(iTime);
155 bundleTimeVec_.erase(iter);
156 }
157 }
158
StartTimer()159 void SchedScheduler::StartTimer()
160 {
161 extTime_.Setup();
162 TryUnloadServiceTimer();
163 }
164
TryUnloadServiceTimer(bool force)165 void SchedScheduler::TryUnloadServiceTimer(bool force)
166 {
167 auto tryUnload = [sessionPtr {sessionPtr_}]() {
168 auto ptr = sessionPtr.promote();
169 if (ptr && ptr->GetSessionCnt() > 0) {
170 return;
171 }
172 HILOGI("Unload system ability");
173 sptr<ISystemAbilityManager> saManager =
174 OHOS::SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
175 if (saManager == nullptr) {
176 HILOGE("UnloadSA, GetSystemAbilityManager is null.");
177 return;
178 }
179 int32_t result = saManager->UnloadSystemAbility(FILEMANAGEMENT_BACKUP_SERVICE_SA_ID);
180 if (result != ERR_OK) {
181 HILOGE("UnloadSA, UnloadSystemAbility result: %{public}d", result);
182 return;
183 }
184 };
185
186 static atomic<uint32_t> timerEventId;
187 // When force is false, only one timer is allowed to be registered.
188 if (!force) {
189 if (timerEventId != 0) {
190 return;
191 }
192 constexpr int checkingIntervalInMs = 30000;
193 auto tmpTimerEventId = extTime_.Register(tryUnload, checkingIntervalInMs);
194 uint32_t tmp = 0;
195 if (timerEventId.compare_exchange_strong(tmp, tmpTimerEventId)) {
196 return;
197 }
198 extTime_.Unregister(tmpTimerEventId);
199 }
200
201 tryUnload();
202 }
203
TryUnloadService()204 void SchedScheduler::TryUnloadService()
205 {
206 auto tryUnload = []() {
207 HILOGI("Unload system ability");
208 sptr<ISystemAbilityManager> saManager =
209 OHOS::SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
210 if (saManager == nullptr) {
211 HILOGE("UnloadSA, GetSystemAbilityManager is null.");
212 return;
213 }
214 int32_t result = saManager->UnloadSystemAbility(FILEMANAGEMENT_BACKUP_SERVICE_SA_ID);
215 if (result != ERR_OK) {
216 HILOGE("UnloadSA, UnloadSystemAbility result: %{public}d", result);
217 return;
218 }
219 };
220 threadPool_.AddTask(tryUnload);
221 }
222
ClearSchedulerData()223 void SchedScheduler::ClearSchedulerData()
224 {
225 unique_lock<shared_mutex> lock(lock_);
226 for (auto &bundleTime : bundleTimeVec_) {
227 auto &[bName, iTime] = bundleTime;
228 extTime_.Unregister(iTime);
229 }
230 bundleTimeVec_.clear();
231 }
232 }; // namespace OHOS::FileManagement::Backup
233