• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023-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 "app_exit_reason_data_manager.h"
17 
18 #include "accesstoken_kit.h"
19 #include "os_account_manager_wrapper.h"
20 
21 namespace OHOS {
22 namespace AbilityRuntime {
23 namespace {
24 constexpr int32_t CHECK_INTERVAL = 100000; // 100ms
25 constexpr int32_t MAX_TIMES = 5;           // 5 * 100ms = 500ms
26 constexpr const char *APP_EXIT_REASON_STORAGE_DIR = "/data/service/el1/public/database/app_exit_reason";
27 const std::string JSON_KEY_REASON = "reason";
28 const std::string JSON_KEY_EXIT_MSG = "exit_msg";
29 const std::string JSON_KEY_TIME_STAMP = "time_stamp";
30 const std::string JSON_KEY_ABILITY_LIST = "ability_list";
31 const std::string KEY_RECOVER_INFO_PREFIX = "recover_info";
32 const std::string JSON_KEY_RECOVER_INFO_LIST = "recover_info_list";
33 const std::string JSON_KEY_SESSION_ID_LIST = "session_id_list";
34 const std::string JSON_KEY_EXTENSION_NAME = "extension_name";
35 const std::string SEPARATOR = ":";
36 } // namespace
AppExitReasonDataManager()37 AppExitReasonDataManager::AppExitReasonDataManager() {}
38 
~AppExitReasonDataManager()39 AppExitReasonDataManager::~AppExitReasonDataManager()
40 {
41     if (kvStorePtr_ != nullptr) {
42         dataManager_.CloseKvStore(appId_, kvStorePtr_);
43     }
44 }
45 
GetKvStore()46 DistributedKv::Status AppExitReasonDataManager::GetKvStore()
47 {
48     DistributedKv::Options options = { .createIfMissing = true,
49         .encrypt = false,
50         .autoSync = true,
51         .syncable = false,
52         .securityLevel = DistributedKv::SecurityLevel::S2,
53         .area = DistributedKv::EL1,
54         .kvStoreType = DistributedKv::KvStoreType::SINGLE_VERSION,
55         .baseDir = APP_EXIT_REASON_STORAGE_DIR };
56 
57     DistributedKv::Status status = dataManager_.GetSingleKvStore(options, appId_, storeId_, kvStorePtr_);
58     if (status != DistributedKv::Status::SUCCESS) {
59         TAG_LOGE(AAFwkTag::ABILITYMGR, "return error: %{public}d", status);
60     } else {
61         TAG_LOGI(AAFwkTag::ABILITYMGR, "get kvStore success");
62     }
63     return status;
64 }
65 
CheckKvStore()66 bool AppExitReasonDataManager::CheckKvStore()
67 {
68     TAG_LOGD(AAFwkTag::ABILITYMGR, "AppExitReasonDataManager::CheckKvStore start");
69     if (kvStorePtr_ != nullptr) {
70         return true;
71     }
72     int32_t tryTimes = MAX_TIMES;
73     while (tryTimes > 0) {
74         DistributedKv::Status status = GetKvStore();
75         if (status == DistributedKv::Status::SUCCESS && kvStorePtr_ != nullptr) {
76             return true;
77         }
78         TAG_LOGD(AAFwkTag::ABILITYMGR, "try times: %{public}d", tryTimes);
79         usleep(CHECK_INTERVAL);
80         tryTimes--;
81     }
82     return kvStorePtr_ != nullptr;
83 }
84 
SetAppExitReason(const std::string & bundleName,uint32_t accessTokenId,const std::vector<std::string> & abilityList,const AAFwk::ExitReason & exitReason)85 int32_t AppExitReasonDataManager::SetAppExitReason(const std::string &bundleName, uint32_t accessTokenId,
86     const std::vector<std::string> &abilityList, const AAFwk::ExitReason &exitReason)
87 {
88     auto accessTokenIdStr = std::to_string(accessTokenId);
89     if (bundleName.empty() || accessTokenId == Security::AccessToken::INVALID_TOKENID) {
90         TAG_LOGW(AAFwkTag::ABILITYMGR, "invalid value");
91         return ERR_INVALID_VALUE;
92     }
93 
94     TAG_LOGD(AAFwkTag::ABILITYMGR, "bundleName: %{public}s, tokenId: %{private}u", bundleName.c_str(), accessTokenId);
95     {
96         std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
97         if (!CheckKvStore()) {
98             TAG_LOGE(AAFwkTag::ABILITYMGR, "kvStore is nullptr");
99             return ERR_NO_INIT;
100         }
101     }
102 
103     DistributedKv::Key key(accessTokenIdStr);
104     DistributedKv::Value value = ConvertAppExitReasonInfoToValue(abilityList, exitReason);
105     DistributedKv::Status status;
106     {
107         std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
108         status = kvStorePtr_->Put(key, value);
109     }
110 
111     if (status != DistributedKv::Status::SUCCESS) {
112         TAG_LOGE(AAFwkTag::ABILITYMGR, "insert data to kvStore error: %{public}d", status);
113         return ERR_INVALID_OPERATION;
114     }
115     return ERR_OK;
116 }
117 
118 
DeleteAppExitReason(const std::string & bundleName,int32_t uid,int32_t appIndex)119 int32_t AppExitReasonDataManager::DeleteAppExitReason(const std::string &bundleName, int32_t uid, int32_t appIndex)
120 {
121     int32_t userId;
122     if (DelayedSingleton<AppExecFwk::OsAccountManagerWrapper>::GetInstance()->
123         GetOsAccountLocalIdFromUid(uid, userId) != ERR_OK) {
124         TAG_LOGE(AAFwkTag::ABILITYMGR, "Get GetOsAccountLocalIdFromUid failed.");
125         return ERR_INVALID_VALUE;
126     }
127     uint32_t accessTokenId = Security::AccessToken::AccessTokenKit::GetHapTokenID(userId, bundleName, appIndex);
128     return DeleteAppExitReason(bundleName, accessTokenId);
129 }
130 
DeleteAppExitReason(const std::string & bundleName,uint32_t accessTokenId)131 int32_t AppExitReasonDataManager::DeleteAppExitReason(const std::string &bundleName, uint32_t accessTokenId)
132 {
133     auto accessTokenIdStr = std::to_string(accessTokenId);
134     if (bundleName.empty() || accessTokenId == Security::AccessToken::INVALID_TOKENID) {
135         TAG_LOGW(AAFwkTag::ABILITYMGR, "invalid value.");
136         return ERR_INVALID_VALUE;
137     }
138 
139     TAG_LOGD(AAFwkTag::ABILITYMGR, "bundleName: %{public}s, tokenId: %{private}u", bundleName.c_str(), accessTokenId);
140     {
141         std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
142         if (!CheckKvStore()) {
143             TAG_LOGE(AAFwkTag::ABILITYMGR, "kvStore is nullptr.");
144             return ERR_NO_INIT;
145         }
146     }
147 
148     std::string keyUiExten = bundleName + SEPARATOR;
149     std::vector<DistributedKv::Entry> allEntries;
150     DistributedKv::Status status = kvStorePtr_->GetEntries(nullptr, allEntries);
151     if (status != DistributedKv::Status::SUCCESS) {
152         TAG_LOGE(AAFwkTag::ABILITYMGR, "Get entries error: %{public}d", status);
153         return ERR_INVALID_OPERATION;
154     }
155 
156     for (const auto &item : allEntries) {
157         const auto &keyValue = item.key.ToString();
158         if (keyValue != accessTokenIdStr && keyValue.find(keyUiExten) == std::string::npos) {
159             continue;
160         }
161 
162         std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
163         auto errCode = kvStorePtr_->Delete(item.key);
164         status = (errCode != DistributedKv::Status::SUCCESS) ? errCode : status;
165     }
166 
167     if (status != DistributedKv::Status::SUCCESS) {
168         TAG_LOGE(AAFwkTag::ABILITYMGR, "delete data from kvStore error: %{public}d", status);
169         return ERR_INVALID_OPERATION;
170     }
171     return ERR_OK;
172 }
173 
GetAppExitReason(const std::string & bundleName,uint32_t accessTokenId,const std::string & abilityName,bool & isSetReason,AAFwk::ExitReason & exitReason)174 int32_t AppExitReasonDataManager::GetAppExitReason(const std::string &bundleName, uint32_t accessTokenId,
175     const std::string &abilityName, bool &isSetReason, AAFwk::ExitReason &exitReason)
176 {
177     auto accessTokenIdStr = std::to_string(accessTokenId);
178     if (bundleName.empty() || accessTokenId == Security::AccessToken::INVALID_TOKENID) {
179         TAG_LOGW(AAFwkTag::ABILITYMGR, "invalid value!");
180         return ERR_INVALID_VALUE;
181     }
182     TAG_LOGD(AAFwkTag::ABILITYMGR, "bundleName: %{public}s, tokenId: %{private}u", bundleName.c_str(), accessTokenId);
183     {
184         std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
185         if (!CheckKvStore()) {
186             TAG_LOGE(AAFwkTag::ABILITYMGR, "kvStore is nullptr!");
187             return ERR_NO_INIT;
188         }
189     }
190 
191     std::vector<DistributedKv::Entry> allEntries;
192     DistributedKv::Status status = kvStorePtr_->GetEntries(nullptr, allEntries);
193     if (status != DistributedKv::Status::SUCCESS) {
194         TAG_LOGE(AAFwkTag::ABILITYMGR, "get entries error: %{public}d", status);
195         return ERR_INVALID_VALUE;
196     }
197 
198     std::vector<std::string> abilityList;
199     int64_t time_stamp;
200     isSetReason = false;
201     for (const auto &item : allEntries) {
202         if (item.key.ToString() == accessTokenIdStr) {
203             ConvertAppExitReasonInfoFromValue(item.value, exitReason, time_stamp, abilityList);
204             auto pos = std::find(abilityList.begin(), abilityList.end(), abilityName);
205             if (pos != abilityList.end()) {
206                 isSetReason = true;
207                 abilityList.erase(std::remove(abilityList.begin(), abilityList.end(), abilityName), abilityList.end());
208                 UpdateAppExitReason(accessTokenId, abilityList, exitReason);
209             }
210             TAG_LOGI(AAFwkTag::ABILITYMGR, "current bundle name: %{public}s, tokenId:%{private}u, reason: %{public}d,"
211                 "  exitMsg: %{public}s, abilityName:%{public}s isSetReason:%{public}d",
212                 bundleName.c_str(), accessTokenId, exitReason.reason, exitReason.exitMsg.c_str(),
213                 abilityName.c_str(), isSetReason);
214             if (abilityList.empty()) {
215                 InnerDeleteAppExitReason(accessTokenIdStr);
216             }
217             break;
218         }
219     }
220 
221     return ERR_OK;
222 }
223 
UpdateAppExitReason(uint32_t accessTokenId,const std::vector<std::string> & abilityList,const AAFwk::ExitReason & exitReason)224 void AppExitReasonDataManager::UpdateAppExitReason(uint32_t accessTokenId, const std::vector<std::string> &abilityList,
225     const AAFwk::ExitReason &exitReason)
226 {
227     if (kvStorePtr_ == nullptr) {
228         TAG_LOGE(AAFwkTag::ABILITYMGR, "kvStore is nullptr.");
229         return;
230     }
231 
232     DistributedKv::Key key(std::to_string(accessTokenId));
233     DistributedKv::Status status;
234     {
235         std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
236         status = kvStorePtr_->Delete(key);
237     }
238     if (status != DistributedKv::Status::SUCCESS) {
239         TAG_LOGE(AAFwkTag::ABILITYMGR, "delete data from kvStore error: %{public}d.", status);
240         return;
241     }
242 
243     DistributedKv::Value value = ConvertAppExitReasonInfoToValue(abilityList, exitReason);
244     {
245         std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
246         status = kvStorePtr_->Put(key, value);
247     }
248     if (status != DistributedKv::Status::SUCCESS) {
249         TAG_LOGE(AAFwkTag::ABILITYMGR, "insert data to kvStore error: %{public}d", status);
250     }
251 }
252 
ConvertAppExitReasonInfoToValue(const std::vector<std::string> & abilityList,const AAFwk::ExitReason & exitReason)253 DistributedKv::Value AppExitReasonDataManager::ConvertAppExitReasonInfoToValue(
254     const std::vector<std::string> &abilityList, const AAFwk::ExitReason &exitReason)
255 {
256     std::chrono::milliseconds nowMs =
257         std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch());
258     nlohmann::json jsonObject = nlohmann::json {
259         { JSON_KEY_REASON, exitReason.reason },
260         { JSON_KEY_EXIT_MSG, exitReason.exitMsg },
261         { JSON_KEY_TIME_STAMP, nowMs.count() },
262         { JSON_KEY_ABILITY_LIST, abilityList },
263     };
264     DistributedKv::Value value(jsonObject.dump());
265     TAG_LOGI(AAFwkTag::ABILITYMGR, "value: %{public}s", value.ToString().c_str());
266     return value;
267 }
268 
ConvertAppExitReasonInfoFromValue(const DistributedKv::Value & value,AAFwk::ExitReason & exitReason,int64_t & time_stamp,std::vector<std::string> & abilityList)269 void AppExitReasonDataManager::ConvertAppExitReasonInfoFromValue(const DistributedKv::Value &value,
270     AAFwk::ExitReason &exitReason, int64_t &time_stamp, std::vector<std::string> &abilityList)
271 {
272     nlohmann::json jsonObject = nlohmann::json::parse(value.ToString(), nullptr, false);
273     if (jsonObject.is_discarded()) {
274         TAG_LOGE(AAFwkTag::ABILITYMGR, "failed to parse json sting.");
275         return;
276     }
277     if (jsonObject.contains(JSON_KEY_REASON) && jsonObject[JSON_KEY_REASON].is_number_integer()) {
278         exitReason.reason = jsonObject.at(JSON_KEY_REASON).get<AAFwk::Reason>();
279     }
280     if (jsonObject.contains(JSON_KEY_EXIT_MSG) && jsonObject[JSON_KEY_EXIT_MSG].is_string()) {
281         exitReason.exitMsg = jsonObject.at(JSON_KEY_EXIT_MSG).get<std::string>();
282     }
283     if (jsonObject.contains(JSON_KEY_TIME_STAMP) && jsonObject[JSON_KEY_TIME_STAMP].is_number_integer()) {
284         time_stamp = jsonObject.at(JSON_KEY_TIME_STAMP).get<int64_t>();
285     }
286     if (jsonObject.contains(JSON_KEY_ABILITY_LIST) && jsonObject[JSON_KEY_ABILITY_LIST].is_array()) {
287         abilityList.clear();
288         auto size = jsonObject[JSON_KEY_ABILITY_LIST].size();
289         for (size_t i = 0; i < size; i++) {
290             if (jsonObject[JSON_KEY_ABILITY_LIST][i].is_string()) {
291                 abilityList.emplace_back(jsonObject[JSON_KEY_ABILITY_LIST][i]);
292             }
293         }
294     }
295 }
296 
InnerDeleteAppExitReason(const std::string & keyName)297 void AppExitReasonDataManager::InnerDeleteAppExitReason(const std::string &keyName)
298 {
299     if (kvStorePtr_ == nullptr) {
300         TAG_LOGE(AAFwkTag::ABILITYMGR, "kvStore is nullptr");
301         return;
302     }
303 
304     DistributedKv::Key key(keyName);
305     DistributedKv::Status status;
306     {
307         std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
308         status = kvStorePtr_->Delete(key);
309     }
310 
311     if (status != DistributedKv::Status::SUCCESS) {
312         TAG_LOGE(AAFwkTag::ABILITYMGR, "delete data from kvStore error: %{public}d", status);
313     }
314 }
315 
AddAbilityRecoverInfo(uint32_t accessTokenId,const std::string & moduleName,const std::string & abilityName,const int & sessionId)316 int32_t AppExitReasonDataManager::AddAbilityRecoverInfo(uint32_t accessTokenId,
317     const std::string &moduleName, const std::string &abilityName, const int &sessionId)
318 {
319     TAG_LOGI(AAFwkTag::ABILITYMGR,
320         "AddAbilityRecoverInfo tokenId %{private}u module %{public}s ability %{public}s id %{public}d ",
321         accessTokenId, moduleName.c_str(), abilityName.c_str(), sessionId);
322     {
323         std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
324         if (!CheckKvStore()) {
325             TAG_LOGE(AAFwkTag::ABILITYMGR, "kvStore is nullptr");
326             return ERR_NO_INIT;
327         }
328     }
329 
330     DistributedKv::Key key = GetAbilityRecoverInfoKey(accessTokenId);
331     DistributedKv::Value value;
332     DistributedKv::Status status = kvStorePtr_->Get(key, value);
333     if (status != DistributedKv::Status::SUCCESS && status != DistributedKv::Status::KEY_NOT_FOUND) {
334         TAG_LOGE(AAFwkTag::ABILITYMGR, "AddAbilityRecoverInfo get error: %{public}d", status);
335         return ERR_INVALID_VALUE;
336     }
337 
338     std::vector<std::string> recoverInfoList;
339     std::vector<int> sessionIdList;
340     std::string recoverInfo = moduleName + abilityName;
341     if (status == DistributedKv::Status::SUCCESS) {
342         ConvertAbilityRecoverInfoFromValue(value, recoverInfoList, sessionIdList);
343         auto pos = std::find(recoverInfoList.begin(), recoverInfoList.end(), recoverInfo);
344         if (pos != recoverInfoList.end()) {
345             TAG_LOGW(AAFwkTag::ABILITYMGR, "AddAbilityRecoverInfo recoverInfo already record");
346             int index = std::distance(recoverInfoList.begin(), pos);
347             sessionIdList[index] = sessionId;
348             return ERR_OK;
349         }
350     }
351 
352     recoverInfoList.emplace_back(recoverInfo);
353     sessionIdList.emplace_back(sessionId);
354     value = ConvertAbilityRecoverInfoToValue(recoverInfoList, sessionIdList);
355     {
356         std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
357         status = kvStorePtr_->Put(key, value);
358     }
359 
360     if (status != DistributedKv::Status::SUCCESS) {
361         TAG_LOGE(AAFwkTag::ABILITYMGR, "insert data to kvStore error : %{public}d", status);
362         return ERR_INVALID_OPERATION;
363     }
364 
365     TAG_LOGI(AAFwkTag::ABILITYMGR, "AddAbilityRecoverInfo finish");
366     return ERR_OK;
367 }
368 
DeleteAbilityRecoverInfo(uint32_t accessTokenId,const std::string & moduleName,const std::string & abilityName)369 int32_t AppExitReasonDataManager::DeleteAbilityRecoverInfo(
370     uint32_t accessTokenId, const std::string &moduleName, const std::string &abilityName)
371 {
372     TAG_LOGI(AAFwkTag::ABILITYMGR, "DeleteAbilityRecoverInfo tokenId %{private}u module %{public}s ability %{public}s ",
373         accessTokenId, moduleName.c_str(), abilityName.c_str());
374     {
375         std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
376         if (!CheckKvStore()) {
377             TAG_LOGE(AAFwkTag::ABILITYMGR, "kvStore is nullptr.");
378             return ERR_NO_INIT;
379         }
380     }
381 
382     DistributedKv::Key key = GetAbilityRecoverInfoKey(accessTokenId);
383     DistributedKv::Value value;
384     DistributedKv::Status status = kvStorePtr_->Get(key, value);
385     if (status != DistributedKv::Status::SUCCESS) {
386         TAG_LOGE(AAFwkTag::ABILITYMGR, "DeleteAbilityRecoverInfo get error: %{public}d", status);
387         return ERR_INVALID_VALUE;
388     }
389 
390     std::vector<std::string> recoverInfoList;
391     std::vector<int> sessionIdList;
392     std::string recoverInfo = moduleName + abilityName;
393     ConvertAbilityRecoverInfoFromValue(value, recoverInfoList, sessionIdList);
394     auto pos = std::find(recoverInfoList.begin(), recoverInfoList.end(), recoverInfo);
395     if (pos != recoverInfoList.end()) {
396         recoverInfoList.erase(std::remove(recoverInfoList.begin(), recoverInfoList.end(), recoverInfo),
397             recoverInfoList.end());
398         int index = std::distance(recoverInfoList.begin(), pos);
399         sessionIdList.erase(std::remove(sessionIdList.begin(), sessionIdList.end(), sessionIdList[index]),
400             sessionIdList.end());
401         UpdateAbilityRecoverInfo(accessTokenId, recoverInfoList, sessionIdList);
402         TAG_LOGI(AAFwkTag::ABILITYMGR, "DeleteAbilityRecoverInfo remove recoverInfo succeed");
403     }
404     if (recoverInfoList.empty()) {
405         InnerDeleteAbilityRecoverInfo(accessTokenId);
406     }
407 
408     TAG_LOGI(AAFwkTag::ABILITYMGR, "DeleteAbilityRecoverInfo finished");
409     return ERR_OK;
410 }
411 
GetAbilityRecoverInfo(uint32_t accessTokenId,const std::string & moduleName,const std::string & abilityName,bool & hasRecoverInfo)412 int32_t AppExitReasonDataManager::GetAbilityRecoverInfo(
413     uint32_t accessTokenId, const std::string &moduleName, const std::string &abilityName, bool &hasRecoverInfo)
414 {
415     TAG_LOGI(AAFwkTag::ABILITYMGR, "GetAbilityRecoverInfo tokenId %{private}u module %{public}s abillity %{public}s ",
416         accessTokenId, moduleName.c_str(), abilityName.c_str());
417     hasRecoverInfo = false;
418     {
419         std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
420         if (!CheckKvStore()) {
421             TAG_LOGE(AAFwkTag::ABILITYMGR, "kvStore is nullptr!");
422             return ERR_NO_INIT;
423         }
424     }
425 
426     DistributedKv::Key key = GetAbilityRecoverInfoKey(accessTokenId);
427     DistributedKv::Value value;
428     DistributedKv::Status status = kvStorePtr_->Get(key, value);
429     if (status != DistributedKv::Status::SUCCESS) {
430         if (status == DistributedKv::Status::KEY_NOT_FOUND) {
431             TAG_LOGW(AAFwkTag::ABILITYMGR, "GetAbilityRecoverInfo KEY_NOT_FOUND.");
432         } else {
433             TAG_LOGE(AAFwkTag::ABILITYMGR, "GetAbilityRecoverInfo error: %{public}d.", status);
434         }
435         return ERR_INVALID_VALUE;
436     }
437 
438     std::vector<std::string> recoverInfoList;
439     std::vector<int> sessionIdList;
440     std::string recoverInfo = moduleName + abilityName;
441     ConvertAbilityRecoverInfoFromValue(value, recoverInfoList, sessionIdList);
442     auto pos = std::find(recoverInfoList.begin(), recoverInfoList.end(), recoverInfo);
443     if (pos != recoverInfoList.end()) {
444         hasRecoverInfo = true;
445         TAG_LOGI(AAFwkTag::ABILITYMGR, "GetAbilityRecoverInfo hasRecoverInfo found info");
446     }
447     return ERR_OK;
448 }
449 
GetAbilitySessionId(uint32_t accessTokenId,const std::string & moduleName,const std::string & abilityName,int & sessionId)450 int32_t AppExitReasonDataManager::GetAbilitySessionId(uint32_t accessTokenId,
451     const std::string &moduleName, const std::string &abilityName, int &sessionId)
452 {
453     TAG_LOGI(AAFwkTag::ABILITYMGR, "GetAbilityRecoverInfo tokenId %{private}u bundle %{public}s bundle %{public}s  ",
454         accessTokenId, moduleName.c_str(), abilityName.c_str());
455     sessionId = 0;
456     {
457         std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
458         if (!CheckKvStore()) {
459             TAG_LOGE(AAFwkTag::ABILITYMGR, "the kvStore is nullptr.");
460             return ERR_NO_INIT;
461         }
462     }
463 
464     DistributedKv::Key key = GetAbilityRecoverInfoKey(accessTokenId);
465     DistributedKv::Value value;
466     DistributedKv::Status status = kvStorePtr_->Get(key, value);
467     if (status != DistributedKv::Status::SUCCESS) {
468         if (status == DistributedKv::Status::KEY_NOT_FOUND) {
469             TAG_LOGW(AAFwkTag::ABILITYMGR, "GetAbilityRecoverInfo KEY_NOT_FOUND");
470         } else {
471             TAG_LOGE(AAFwkTag::ABILITYMGR, "GetAbilityRecoverInfo error: %{public}d", status);
472         }
473         return ERR_INVALID_VALUE;
474     }
475 
476     std::vector<std::string> recoverInfoList;
477     std::vector<int> sessionIdList;
478     std::string recoverInfo = moduleName + abilityName;
479     ConvertAbilityRecoverInfoFromValue(value, recoverInfoList, sessionIdList);
480     auto pos = std::find(recoverInfoList.begin(), recoverInfoList.end(), recoverInfo);
481     if (pos != recoverInfoList.end()) {
482         int index = std::distance(recoverInfoList.begin(), pos);
483         sessionId = sessionIdList[index];
484         TAG_LOGI(AAFwkTag::ABILITYMGR, "GetAbilityRecoverInfo sessionId found info %{public}d ", sessionId);
485     }
486     return ERR_OK;
487 }
488 
SetUIExtensionAbilityExitReason(const std::string & bundleName,const std::vector<std::string> & extensionList,const AAFwk::ExitReason & exitReason)489 int32_t AppExitReasonDataManager::SetUIExtensionAbilityExitReason(
490     const std::string &bundleName, const std::vector<std::string> &extensionList, const AAFwk::ExitReason &exitReason)
491 {
492     TAG_LOGD(AAFwkTag::ABILITYMGR, "called");
493     if (bundleName.empty()) {
494         TAG_LOGW(AAFwkTag::ABILITYMGR, "Invalid bundle name.");
495         return ERR_INVALID_VALUE;
496     }
497 
498     {
499         std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
500         if (!CheckKvStore()) {
501             TAG_LOGE(AAFwkTag::ABILITYMGR, "kvStorePtr_ is nullptr.");
502             return ERR_NO_INIT;
503         }
504     }
505 
506     for (const auto &extension : extensionList) {
507         std::string keyEx = bundleName + SEPARATOR + extension;
508         DistributedKv::Key key(keyEx);
509         DistributedKv::Value value = ConvertAppExitReasonInfoToValueOfExtensionName(extension, exitReason);
510         DistributedKv::Status status;
511         {
512             std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
513             status = kvStorePtr_->Put(key, value);
514         }
515 
516         if (status != DistributedKv::Status::SUCCESS) {
517             TAG_LOGW(AAFwkTag::ABILITYMGR, "Insert data to kvStore error: %{public}d", status);
518         }
519     }
520 
521     return ERR_OK;
522 }
523 
GetUIExtensionAbilityExitReason(const std::string & keyEx,AAFwk::ExitReason & exitReason)524 bool AppExitReasonDataManager::GetUIExtensionAbilityExitReason(const std::string &keyEx,
525     AAFwk::ExitReason &exitReason)
526 {
527     TAG_LOGD(AAFwkTag::ABILITYMGR, "called");
528     {
529         std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
530         if (!CheckKvStore()) {
531             TAG_LOGE(AAFwkTag::ABILITYMGR, "kvStorePtr_ is nullptr.");
532             return false;
533         }
534     }
535 
536     std::vector<DistributedKv::Entry> allEntries;
537     DistributedKv::Status status = kvStorePtr_->GetEntries(nullptr, allEntries);
538     if (status != DistributedKv::Status::SUCCESS) {
539         TAG_LOGE(AAFwkTag::ABILITYMGR, "Get entries error: %{public}d", status);
540         return false;
541     }
542     std::vector<std::string> abilityList;
543     int64_t time_stamp;
544     bool isHaveReason = false;
545     for (const auto &item : allEntries) {
546         if (item.key.ToString() == keyEx) {
547             ConvertAppExitReasonInfoFromValue(item.value, exitReason, time_stamp, abilityList);
548             isHaveReason = true;
549             InnerDeleteAppExitReason(keyEx);
550             break;
551         }
552     }
553 
554     return isHaveReason;
555 }
556 
UpdateAbilityRecoverInfo(uint32_t accessTokenId,const std::vector<std::string> & recoverInfoList,const std::vector<int> & sessionIdList)557 void AppExitReasonDataManager::UpdateAbilityRecoverInfo(uint32_t accessTokenId,
558     const std::vector<std::string> &recoverInfoList, const std::vector<int> &sessionIdList)
559 {
560     if (kvStorePtr_ == nullptr) {
561         TAG_LOGE(AAFwkTag::ABILITYMGR, "kvStore is nullptr.");
562         return;
563     }
564 
565     DistributedKv::Key key = GetAbilityRecoverInfoKey(accessTokenId);
566     DistributedKv::Status status;
567     {
568         std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
569         status = kvStorePtr_->Delete(key);
570     }
571     if (status != DistributedKv::Status::SUCCESS) {
572         TAG_LOGE(AAFwkTag::ABILITYMGR, "delete data from kvStore error: %{public}d", status);
573         return;
574     }
575 
576     DistributedKv::Value value = ConvertAbilityRecoverInfoToValue(recoverInfoList, sessionIdList);
577     {
578         std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
579         status = kvStorePtr_->Put(key, value);
580     }
581     if (status != DistributedKv::Status::SUCCESS) {
582         TAG_LOGE(AAFwkTag::ABILITYMGR, "insert data to kvStore failed: %{public}d", status);
583     }
584 }
585 
ConvertAbilityRecoverInfoToValue(const std::vector<std::string> & recoverInfoList,const std::vector<int> & sessionIdList)586 DistributedKv::Value AppExitReasonDataManager::ConvertAbilityRecoverInfoToValue(
587     const std::vector<std::string> &recoverInfoList, const std::vector<int> &sessionIdList)
588 {
589     nlohmann::json jsonObject = nlohmann::json {
590         { JSON_KEY_RECOVER_INFO_LIST, recoverInfoList },
591         { JSON_KEY_SESSION_ID_LIST, sessionIdList },
592     };
593     DistributedKv::Value value(jsonObject.dump());
594     TAG_LOGI(AAFwkTag::ABILITYMGR, "ConvertAbilityRecoverInfoToValue value: %{public}s", value.ToString().c_str());
595     return value;
596 }
597 
ConvertAbilityRecoverInfoFromValue(const DistributedKv::Value & value,std::vector<std::string> & recoverInfoList,std::vector<int> & sessionIdList)598 void AppExitReasonDataManager::ConvertAbilityRecoverInfoFromValue(const DistributedKv::Value &value,
599     std::vector<std::string> &recoverInfoList, std::vector<int> &sessionIdList)
600 {
601     nlohmann::json jsonObject = nlohmann::json::parse(value.ToString(), nullptr, false);
602     if (jsonObject.is_discarded()) {
603         TAG_LOGE(AAFwkTag::ABILITYMGR, "failed to parse json sting.");
604         return;
605     }
606     if (jsonObject.contains(JSON_KEY_RECOVER_INFO_LIST)
607         && jsonObject[JSON_KEY_RECOVER_INFO_LIST].is_array()) {
608         recoverInfoList.clear();
609         auto size = jsonObject[JSON_KEY_RECOVER_INFO_LIST].size();
610         for (size_t i = 0; i < size; i++) {
611             if (jsonObject[JSON_KEY_RECOVER_INFO_LIST][i].is_string()) {
612                 recoverInfoList.emplace_back(jsonObject[JSON_KEY_RECOVER_INFO_LIST][i]);
613             }
614         }
615     }
616     if (jsonObject.contains(JSON_KEY_SESSION_ID_LIST)
617         && jsonObject[JSON_KEY_SESSION_ID_LIST].is_array()) {
618         sessionIdList.clear();
619         auto size = jsonObject[JSON_KEY_SESSION_ID_LIST].size();
620         for (size_t i = 0; i < size; i++) {
621             if (jsonObject[JSON_KEY_SESSION_ID_LIST][i].is_number_integer()) {
622                 sessionIdList.emplace_back(jsonObject[JSON_KEY_SESSION_ID_LIST][i]);
623             }
624         }
625     }
626 }
627 
InnerDeleteAbilityRecoverInfo(uint32_t accessTokenId)628 void AppExitReasonDataManager::InnerDeleteAbilityRecoverInfo(uint32_t accessTokenId)
629 {
630     if (kvStorePtr_ == nullptr) {
631         TAG_LOGE(AAFwkTag::ABILITYMGR, "kvStore is nullptr");
632         return;
633     }
634 
635     DistributedKv::Key key = GetAbilityRecoverInfoKey(accessTokenId);
636     DistributedKv::Status status;
637     {
638         std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
639         status = kvStorePtr_->Delete(key);
640     }
641 
642     if (status != DistributedKv::Status::SUCCESS) {
643         TAG_LOGE(AAFwkTag::ABILITYMGR, "delete data from kvStore error: %{public}d", status);
644     }
645 }
646 
GetAbilityRecoverInfoKey(uint32_t accessTokenId)647 DistributedKv::Key AppExitReasonDataManager::GetAbilityRecoverInfoKey(uint32_t accessTokenId)
648 {
649     return DistributedKv::Key(KEY_RECOVER_INFO_PREFIX + std::to_string(accessTokenId));
650 }
651 
ConvertAppExitReasonInfoToValueOfExtensionName(const std::string & extensionListName,const AAFwk::ExitReason & exitReason)652 DistributedKv::Value AppExitReasonDataManager::ConvertAppExitReasonInfoToValueOfExtensionName(
653     const std::string &extensionListName, const AAFwk::ExitReason &exitReason)
654 {
655     TAG_LOGD(AAFwkTag::ABILITYMGR, "called");
656     std::chrono::milliseconds nowMs =
657         std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch());
658     nlohmann::json jsonObject = nlohmann::json {
659         { JSON_KEY_REASON, exitReason.reason },
660         { JSON_KEY_EXIT_MSG, exitReason.exitMsg },
661         { JSON_KEY_TIME_STAMP, nowMs.count() },
662         { JSON_KEY_EXTENSION_NAME, extensionListName },
663     };
664     DistributedKv::Value value(jsonObject.dump());
665     return value;
666 }
667 } // namespace AbilityRuntime
668 } // namespace OHOS
669