• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 "ability_recovery.h"
17 
18 #include <sys/mman.h>
19 #include <sys/stat.h>
20 #include <sys/types.h>
21 
22 #include <unistd.h>
23 
24 #include "file_ex.h"
25 #include "napi/native_api.h"
26 #include "napi/native_common.h"
27 #include "js_runtime.h"
28 #include "js_runtime_utils.h"
29 
30 #include "ability_manager_client.h"
31 #include "app_recovery_parcel_allocator.h"
32 #include "hilog_wrapper.h"
33 #include "parcel.h"
34 #include "recovery_param.h"
35 #include "string_ex.h"
36 #include "string_wrapper.h"
37 #include "want_params.h"
38 
39 namespace OHOS {
40 namespace AppExecFwk {
41 namespace {
GetSaveAppCachePath(int32_t savedStateId)42 static std::string GetSaveAppCachePath(int32_t savedStateId)
43 {
44     auto context = AbilityRuntime::Context::GetApplicationContext();
45     if (context == nullptr) {
46         return "";
47     }
48 
49     std::string fileDir = context->GetFilesDir();
50     HILOG_DEBUG("AppRecovery GetSaveAppCachePath fileDir %{public}s.", fileDir.c_str());
51     if (fileDir.empty() || !OHOS::FileExists(fileDir)) {
52         HILOG_ERROR("AppRecovery GetSaveAppCachePath fileDir is empty or fileDir is not exists.");
53         return "";
54     }
55 
56     std::string fileName = std::to_string(savedStateId) + ".state";
57     return fileDir + "/" + fileName;
58 }
59 }
60 
AbilityRecovery()61 AbilityRecovery::AbilityRecovery() : isEnable_(false), restartFlag_(RestartFlag::ALWAYS_RESTART),
62     saveOccasion_(SaveOccasionFlag::SAVE_WHEN_ERROR), saveMode_(SaveModeFlag::SAVE_WITH_FILE)
63 {
64 }
65 
~AbilityRecovery()66 AbilityRecovery::~AbilityRecovery()
67 {
68 }
69 
InitAbilityInfo(const std::shared_ptr<Ability> ability,const std::shared_ptr<AbilityInfo> & abilityInfo,const sptr<IRemoteObject> & token)70 bool AbilityRecovery::InitAbilityInfo(const std::shared_ptr<Ability> ability,
71     const std::shared_ptr<AbilityInfo>& abilityInfo, const sptr<IRemoteObject>& token)
72 {
73     isEnable_ = true;
74     ability_ = ability;
75     abilityInfo_ = abilityInfo;
76     token_ = token;
77     auto abilityContext = ability->GetAbilityContext();
78     if (abilityContext != nullptr) {
79         abilityContext->GetMissionId(missionId_);
80     }
81     HILOG_INFO("AppRecovery InitAbilityInfo, missionId_:%{public}d", missionId_);
82     return true;
83 }
84 
EnableAbilityRecovery(uint16_t restartFlag,uint16_t saveFlag,uint16_t saveMode)85 void AbilityRecovery::EnableAbilityRecovery(uint16_t restartFlag, uint16_t saveFlag, uint16_t saveMode)
86 {
87     isEnable_ = true;
88     restartFlag_ = restartFlag;
89     saveOccasion_ = saveFlag;
90     saveMode_ = saveMode;
91 }
92 
IsSameAbility(uintptr_t ability)93 bool AbilityRecovery::IsSameAbility(uintptr_t ability)
94 {
95     return ability == jsAbilityPtr_;
96 }
97 
SetJsAbility(uintptr_t ability)98 void AbilityRecovery::SetJsAbility(uintptr_t ability)
99 {
100     jsAbilityPtr_ = ability;
101 }
102 
SaveAbilityState()103 bool AbilityRecovery::SaveAbilityState()
104 {
105     HILOG_DEBUG("SaveAbilityState begin");
106     auto ability = ability_.lock();
107     auto abilityInfo = abilityInfo_.lock();
108     if (ability == nullptr || abilityInfo == nullptr) {
109         HILOG_ERROR("AppRecovery ability is nullptr");
110         return false;
111     }
112 
113     AAFwk::WantParams wantParams;
114     int32_t status = ability->OnSaveState(AppExecFwk::StateType::APP_RECOVERY, wantParams);
115     if (!(status == AppExecFwk::OnSaveResult::ALL_AGREE || status == AppExecFwk::OnSaveResult::RECOVERY_AGREE)) {
116         HILOG_ERROR("AppRecovery Failed to save user params.");
117         return false;
118     }
119 
120 #ifdef SUPPORT_GRAPHICS
121     std::string pageStack = ability->GetContentInfo();
122     if (!pageStack.empty()) {
123         wantParams.SetParam("pageStack", AAFwk::String::Box(pageStack));
124     } else {
125         HILOG_ERROR("AppRecovery Failed to get page stack.");
126     }
127 #endif
128     if (saveMode_ == SaveModeFlag::SAVE_WITH_FILE) {
129         SerializeDataToFile(missionId_, wantParams);
130     } else if (saveMode_ == SaveModeFlag::SAVE_WITH_SHARED_MEMORY) {
131         params_ = wantParams;
132     }
133     return true;
134 }
135 
SerializeDataToFile(int32_t savedStateId,WantParams & params)136 bool AbilityRecovery::SerializeDataToFile(int32_t savedStateId, WantParams& params)
137 {
138     std::string file = GetSaveAppCachePath(savedStateId);
139     if (file.empty()) {
140         HILOG_ERROR("AppRecovery %{public}s failed to persisted file path.", __func__);
141         return false;
142     }
143     Parcel parcel;
144     if (!params.Marshalling(parcel)) {
145         HILOG_ERROR("AppRecovery %{public}s failed to Marshalling want param. ret", __func__);
146         return false;
147     }
148     int fd = open(file.c_str(), O_RDWR | O_CREAT, (mode_t)0600);
149     if (fd <= 0) {
150         HILOG_ERROR("AppRecovery %{public}s failed to open %{public}s.", __func__, file.c_str());
151         return false;
152     }
153     size_t sz = parcel.GetDataSize();
154     uintptr_t buf = parcel.GetData();
155     if (sz == 0 || buf == 0) {
156         HILOG_ERROR("AppRecovery %{public}s failed to get parcel data.", __func__);
157         close(fd);
158         return false;
159     }
160     ssize_t nwrite = write(fd, reinterpret_cast<uint8_t*>(buf), sz);
161     if (nwrite <= 0) {
162         HILOG_ERROR("AppRecovery%{public}s failed to persist parcel data %{public}d.", __func__, errno);
163     }
164     close(fd);
165     return true;
166 }
167 
ReadSerializeDataFromFile(int32_t savedStateId,WantParams & params)168 bool AbilityRecovery::ReadSerializeDataFromFile(int32_t savedStateId, WantParams& params)
169 {
170     std::string file = GetSaveAppCachePath(savedStateId);
171     if (file.empty()) {
172         HILOG_ERROR("AppRecovery %{public}s failed to persisted file path.", __func__);
173         return false;
174     }
175 
176     char path[PATH_MAX] = {0};
177     if (realpath(file.c_str(), path) == nullptr) {
178         HILOG_ERROR("AppRecovery realpath error, errno is %{public}d.", errno);
179         return false;
180     }
181 
182     int32_t fd = open(path, O_RDONLY);
183     if (fd <= 0) {
184         HILOG_ERROR("AppRecovery fopen error");
185         remove(path);
186         return false;
187     }
188 
189     struct stat statbuf;
190     if (fstat(fd, &statbuf) < 0) {
191         close(fd);
192         remove(path);
193         return false;
194     }
195 
196     auto mapFile = static_cast<uint8_t*>(mmap(NULL, statbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0));
197     if (mapFile == MAP_FAILED) {
198         close(fd);
199         remove(path);
200         return false;
201     }
202 
203     Parcel parcel(new AppRecoveryParcelAllocator()); // do not dealloc mmap area
204     if (!parcel.ParseFrom(reinterpret_cast<uintptr_t>(mapFile), statbuf.st_size)) {
205         munmap(mapFile, statbuf.st_size);
206         close(fd);
207         remove(path);
208         return false;
209     }
210 
211     auto parsedParam = WantParams::Unmarshalling(parcel);
212     if (parsedParam != nullptr) {
213         params = *parsedParam;
214         delete parsedParam;
215     } else {
216         munmap(mapFile, statbuf.st_size);
217         close(fd);
218         remove(path);
219         return false;
220     }
221 
222     munmap(mapFile, statbuf.st_size);
223     close(fd);
224     remove(path);
225     return true;
226 }
227 
ScheduleSaveAbilityState(StateReason reason)228 bool AbilityRecovery::ScheduleSaveAbilityState(StateReason reason)
229 {
230     if (!isEnable_) {
231         HILOG_ERROR("AppRecovery not enable");
232         return false;
233     }
234 
235     if (missionId_ <= 0) {
236         HILOG_ERROR("AppRecovery not save ability missionId_ is invalid");
237         return false;
238     }
239 
240     if (!IsSaveAbilityState(reason)) {
241         HILOG_ERROR("AppRecovery ts not save ability state");
242         return false;
243     }
244 
245     bool ret = SaveAbilityState();
246     if (ret) {
247         auto token = token_.promote();
248         if (token == nullptr) {
249             HILOG_ERROR("AppRecovery token is nullptr");
250             return false;
251         }
252 
253         std::shared_ptr<AAFwk::AbilityManagerClient> abilityMgr = AAFwk::AbilityManagerClient::GetInstance();
254         if (abilityMgr == nullptr) {
255             HILOG_ERROR("AppRecovery ScheduleSaveAbilityState. abilityMgr client is not exist.");
256             return false;
257         }
258         abilityMgr->EnableRecoverAbility(token);
259     }
260     return ret;
261 }
262 
ScheduleRecoverAbility(StateReason reason,const Want * want)263 bool AbilityRecovery::ScheduleRecoverAbility(StateReason reason, const Want *want)
264 {
265     if (!isEnable_) {
266         HILOG_ERROR("AppRecovery not enable");
267         return false;
268     }
269 
270     std::shared_ptr<AAFwk::AbilityManagerClient> abilityMgr = AAFwk::AbilityManagerClient::GetInstance();
271     if (abilityMgr == nullptr) {
272         HILOG_ERROR("AppRecovery ScheduleRecoverApp. abilityMgr client is not exist.");
273         return false;
274     }
275 
276     auto token = token_.promote();
277     if (token == nullptr) {
278         return false;
279     }
280     abilityMgr->ScheduleRecoverAbility(token, reason, want);
281     return true;
282 }
283 
PersistState()284 bool AbilityRecovery::PersistState()
285 {
286     auto abilityInfo = abilityInfo_.lock();
287     if (abilityInfo == nullptr) {
288         HILOG_ERROR("AppRecovery ability is nullptr");
289         return false;
290     }
291     if (missionId_ <= 0) {
292         HILOG_ERROR("AppRecovery PersistState missionId is Invalid");
293         return false;
294     }
295     if (!params_.IsEmpty()) {
296         SerializeDataToFile(missionId_, params_);
297     }
298     return true;
299 }
300 
IsOnForeground()301 bool AbilityRecovery::IsOnForeground()
302 {
303     auto ability = ability_.lock();
304     if (ability == nullptr) {
305         return false;
306     }
307     AbilityLifecycleExecutor::LifecycleState state = ability->GetState();
308     HILOG_INFO("IsOnForeground state: %{public}d", state);
309     if (state == AbilityLifecycleExecutor::LifecycleState::FOREGROUND_NEW) {
310         return true;
311     }
312     return false;
313 }
314 
LoadSavedState(StateReason reason)315 bool AbilityRecovery::LoadSavedState(StateReason reason)
316 {
317     auto abilityInfo = abilityInfo_.lock();
318     if (abilityInfo == nullptr) {
319         HILOG_ERROR("AppRecovery LoadSavedState abilityInfo is nullptr");
320         return false;
321     }
322 
323     if (hasTryLoad_) {
324         return hasLoaded_;
325     }
326     if (missionId_ <= 0) {
327         HILOG_ERROR("AppRecovery LoadSavedState missionId_ is invalid");
328         return false;
329     }
330     hasTryLoad_ = true;
331 
332     HILOG_DEBUG("AppRecovery LoadSavedState,missionId_:%{public}d", missionId_);
333     if (!ReadSerializeDataFromFile(missionId_, params_)) {
334         HILOG_ERROR("AppRecovery LoadSavedState. failed to find record for id:%{public}d", missionId_);
335         hasLoaded_ = false;
336         return hasLoaded_;
337     }
338 
339     auto stringObj = AAFwk::IString::Query(params_.GetParam("pageStack"));
340     if (stringObj != nullptr) {
341         pageStack_ = AAFwk::String::Unbox(stringObj);
342     }
343     hasLoaded_ = true;
344     return hasLoaded_;
345 }
346 
ScheduleRestoreAbilityState(StateReason reason,const Want & want)347 bool AbilityRecovery::ScheduleRestoreAbilityState(StateReason reason, const Want &want)
348 {
349     if (!isEnable_) {
350         HILOG_ERROR("AppRecovery not enable");
351         return false;
352     }
353 
354     if (!IsSaveAbilityState(reason)) {
355         HILOG_ERROR("AppRecovery ts not save ability state");
356         return false;
357     }
358 
359     if (!LoadSavedState(reason)) {
360         HILOG_ERROR("AppRecovery ScheduleRestoreAbilityState no saved state ");
361         return false;
362     }
363 
364     const WantParams &wantParams = want.GetParams();
365     WantParams &wantCurrent = const_cast<WantParams&>(wantParams);
366     for (auto& i : params_.GetParams()) {
367         wantCurrent.SetParam(i.first, i.second.GetRefPtr());
368     }
369     return true;
370 }
371 
GetSavedPageStack(StateReason reason)372 std::string AbilityRecovery::GetSavedPageStack(StateReason reason)
373 {
374     if (!LoadSavedState(reason)) {
375         HILOG_ERROR("AppRecovery GetSavedPageStack no saved state ");
376         return "";
377     }
378 
379     if (pageStack_.empty()) {
380         HILOG_ERROR("AppRecovery GetSavedPageStack empty.");
381     }
382     return pageStack_;
383 }
384 
IsSaveAbilityState(StateReason reason)385 bool AbilityRecovery::IsSaveAbilityState(StateReason reason)
386 {
387     bool ret = false;
388     switch (reason) {
389         case StateReason::DEVELOPER_REQUEST:
390             ret = true;
391             break;
392 
393         case StateReason::LIFECYCLE:
394             if ((saveOccasion_ & SaveOccasionFlag::SAVE_WHEN_BACKGROUND) != 0) {
395                 ret = true;
396             }
397             break;
398 
399         case StateReason::CPP_CRASH:
400         case StateReason::JS_ERROR:
401         case StateReason::APP_FREEZE:
402             if ((saveOccasion_ & SaveOccasionFlag::SAVE_WHEN_ERROR) != 0) {
403                 ret = true;
404             }
405             break;
406 
407         default:
408             ret = false;
409             break;
410     }
411     return ret;
412 }
413 
GetRestartFlag() const414 uint16_t AbilityRecovery::GetRestartFlag() const
415 {
416     return restartFlag_;
417 }
418 
GetSaveOccasionFlag() const419 uint16_t AbilityRecovery::GetSaveOccasionFlag() const
420 {
421     return saveOccasion_;
422 }
423 
GetSaveModeFlag() const424 uint16_t AbilityRecovery::GetSaveModeFlag() const
425 {
426     return saveMode_;
427 }
428 }  // namespace AbilityRuntime
429 }  // namespace OHOS