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