• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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("Unexpected exception");
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::UNKNOWN) {
97         HILOGE("Current action is unknown, bundleName:%{public}s", bundleName.c_str());
98         return;
99     }
100     try {
101         HILOGI("Start current bundle task, bundleName:%{public}s, action:%{public}d", bundleName.c_str(), action);
102         StartExecuteBundleTask(bundleName, action);
103     } catch(...) {
104         HILOGE("Unexpected exception");
105         return;
106     }
107 }
108 
RemoveExtConn(const string & bundleName)109 void SchedScheduler::RemoveExtConn(const string &bundleName)
110 {
111     unique_lock<shared_mutex> lock(lock_);
112     auto iter = find_if(bundleTimeVec_.begin(), bundleTimeVec_.end(), [&bundleName](auto &obj) {
113         auto &[bName, iTime] = obj;
114         return bName == bundleName;
115     });
116     if (iter != bundleTimeVec_.end()) {
117         auto &[bName, iTime] = *iter;
118         HILOGE("bundleName = %{public}s , iTime = %{public}d", bName.data(), iTime);
119         extTime_.Unregister(iTime);
120         bundleTimeVec_.erase(iter);
121     }
122 }
123 
StartTimer()124 void SchedScheduler::StartTimer()
125 {
126     extTime_.Setup();
127     TryUnloadServiceTimer();
128 }
129 
TryUnloadServiceTimer(bool force)130 void SchedScheduler::TryUnloadServiceTimer(bool force)
131 {
132     auto tryUnload = [sessionPtr {sessionPtr_}]() {
133         auto ptr = sessionPtr.promote();
134         if (ptr && ptr->GetSessionCnt() > 0) {
135             return;
136         }
137         HILOGI("Unload system ability");
138         sptr<ISystemAbilityManager> saManager =
139             OHOS::SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
140         if (saManager == nullptr) {
141             HILOGE("UnloadSA, GetSystemAbilityManager is null.");
142             return;
143         }
144         int32_t result = saManager->UnloadSystemAbility(FILEMANAGEMENT_BACKUP_SERVICE_SA_ID);
145         if (result != ERR_OK) {
146             HILOGE("UnloadSA, UnloadSystemAbility result: %{public}d", result);
147             return;
148         }
149     };
150 
151     static atomic<uint32_t> timerEventId;
152     // When force is false, only one timer is allowed to be registered.
153     if (!force) {
154         if (timerEventId != 0) {
155             return;
156         }
157         constexpr int checkingIntervalInMs = 30000;
158         auto tmpTimerEventId = extTime_.Register(tryUnload, checkingIntervalInMs);
159         uint32_t tmp = 0;
160         if (timerEventId.compare_exchange_strong(tmp, tmpTimerEventId)) {
161             return;
162         }
163         extTime_.Unregister(tmpTimerEventId);
164     }
165 
166     tryUnload();
167 }
168 
TryUnloadService()169 void SchedScheduler::TryUnloadService()
170 {
171     auto tryUnload = []() {
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     threadPool_.AddTask(tryUnload);
186 }
187 
ClearSchedulerData()188 void SchedScheduler::ClearSchedulerData()
189 {
190     unique_lock<shared_mutex> lock(lock_);
191     for (const auto &bundleTime : bundleTimeVec_) {
192         auto &[bName, iTime] = bundleTime;
193         extTime_.Unregister(iTime);
194     }
195     bundleTimeVec_.clear();
196 }
197 
StartExecuteBundleTask(const std::string & bundleName,BConstants::ServiceSchedAction action)198 void SchedScheduler::StartExecuteBundleTask(const std::string &bundleName, BConstants::ServiceSchedAction action)
199 {
200     if (action == BConstants::ServiceSchedAction::START) {
201         // register timer for connect extension
202         auto callStart = [reversePtr {reversePtr_}, bundleName]() {
203             HILOGE("Extension connect failed = %{public}s", bundleName.data());
204             auto ptr = reversePtr.promote();
205             if (ptr) {
206                 ptr->ExtConnectFailed(bundleName, BError(BError::Codes::SA_BOOT_EXT_TIMEOUT));
207             }
208         };
209         auto iTime = extTime_.Register(callStart, BConstants::EXT_CONNECT_MAX_TIME, true);
210         unique_lock<shared_mutex> lock(lock_);
211         bundleTimeVec_.emplace_back(make_tuple(bundleName, iTime));
212         lock.unlock();
213         // launch extension
214         if (reversePtr_ != nullptr) {
215             ErrCode errCode = reversePtr_->LaunchBackupExtension(bundleName);
216             if (errCode) {
217                 reversePtr_->ExtConnectFailed(bundleName, errCode);
218             }
219         }
220     } else if (action == BConstants::ServiceSchedAction::RUNNING) {
221         HILOGI("Current bundle %{public}s process is running", bundleName.data());
222         unique_lock<shared_mutex> lock(lock_);
223         auto iter = find_if(bundleTimeVec_.begin(), bundleTimeVec_.end(), [&bundleName](auto &obj) {
224             auto &[bName, iTime] = obj;
225             return bName == bundleName;
226         });
227         if (iter == bundleTimeVec_.end()) {
228             throw BError(BError::Codes::SA_INVAL_ARG, "Failed to find timer");
229         }
230         auto &[bName, iTime] = *iter;
231         // unregister timer
232         extTime_.Unregister(iTime);
233         lock.unlock();
234         //notify AppGallery to start restore
235         if (reversePtr_ != nullptr) {
236             reversePtr_->StartRunningTimer(bundleName);
237             reversePtr_->SendStartAppGalleryNotify(bundleName);
238             reversePtr_->ExtStart(bundleName);
239         }
240     } else if (action == BConstants::ServiceSchedAction::CLEAN) {
241         HILOGI("Current bundle %{public}s process is cleaning", bundleName.data());
242         ErrCode res = reversePtr_->ClearResidualBundleData(bundleName);
243         IServiceReverse::Scenario scenario = sessionPtr_->GetScenario();
244         ExtDiedClearFailRadarReport(bundleName, scenario, res);
245     }
246 }
247 }; // namespace OHOS::FileManagement::Backup