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