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, abilityName: %{public}s.",
183 bundleName.c_str(), accessTokenId, abilityName.c_str());
184 {
185 std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
186 if (!CheckKvStore()) {
187 TAG_LOGE(AAFwkTag::ABILITYMGR, "kvStore is nullptr!");
188 return ERR_NO_INIT;
189 }
190 }
191
192 std::vector<DistributedKv::Entry> allEntries;
193 DistributedKv::Status status = kvStorePtr_->GetEntries(nullptr, allEntries);
194 if (status != DistributedKv::Status::SUCCESS) {
195 TAG_LOGE(AAFwkTag::ABILITYMGR, "get entries error: %{public}d", status);
196 return ERR_INVALID_VALUE;
197 }
198
199 std::vector<std::string> abilityList;
200 int64_t time_stamp;
201 isSetReason = false;
202 for (const auto &item : allEntries) {
203 if (item.key.ToString() == accessTokenIdStr) {
204 ConvertAppExitReasonInfoFromValue(item.value, exitReason, time_stamp, abilityList);
205 auto pos = std::find(abilityList.begin(), abilityList.end(), abilityName);
206 if (pos != abilityList.end()) {
207 isSetReason = true;
208 abilityList.erase(std::remove(abilityList.begin(), abilityList.end(), abilityName), abilityList.end());
209 UpdateAppExitReason(accessTokenId, abilityList, exitReason);
210 }
211 TAG_LOGI(AAFwkTag::ABILITYMGR, "current bundle name: %{public}s, tokenId:%{private}u, reason: %{public}d,"
212 " exitMsg: %{public}s, abilityName:%{public}s isSetReason:%{public}d",
213 bundleName.c_str(), accessTokenId, exitReason.reason, exitReason.exitMsg.c_str(),
214 abilityName.c_str(), isSetReason);
215 if (abilityList.empty()) {
216 InnerDeleteAppExitReason(accessTokenIdStr);
217 }
218 break;
219 }
220 }
221
222 return ERR_OK;
223 }
224
UpdateAppExitReason(uint32_t accessTokenId,const std::vector<std::string> & abilityList,const AAFwk::ExitReason & exitReason)225 void AppExitReasonDataManager::UpdateAppExitReason(uint32_t accessTokenId, const std::vector<std::string> &abilityList,
226 const AAFwk::ExitReason &exitReason)
227 {
228 if (kvStorePtr_ == nullptr) {
229 TAG_LOGE(AAFwkTag::ABILITYMGR, "kvStore is nullptr.");
230 return;
231 }
232
233 DistributedKv::Key key(std::to_string(accessTokenId));
234 DistributedKv::Status status;
235 {
236 std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
237 status = kvStorePtr_->Delete(key);
238 }
239 if (status != DistributedKv::Status::SUCCESS) {
240 TAG_LOGE(AAFwkTag::ABILITYMGR, "delete data from kvStore error: %{public}d.", status);
241 return;
242 }
243
244 DistributedKv::Value value = ConvertAppExitReasonInfoToValue(abilityList, exitReason);
245 {
246 std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
247 status = kvStorePtr_->Put(key, value);
248 }
249 if (status != DistributedKv::Status::SUCCESS) {
250 TAG_LOGE(AAFwkTag::ABILITYMGR, "insert data to kvStore error: %{public}d", status);
251 }
252 }
253
ConvertAppExitReasonInfoToValue(const std::vector<std::string> & abilityList,const AAFwk::ExitReason & exitReason)254 DistributedKv::Value AppExitReasonDataManager::ConvertAppExitReasonInfoToValue(
255 const std::vector<std::string> &abilityList, const AAFwk::ExitReason &exitReason)
256 {
257 std::chrono::milliseconds nowMs =
258 std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch());
259 nlohmann::json jsonObject = nlohmann::json {
260 { JSON_KEY_REASON, exitReason.reason },
261 { JSON_KEY_EXIT_MSG, exitReason.exitMsg },
262 { JSON_KEY_TIME_STAMP, nowMs.count() },
263 { JSON_KEY_ABILITY_LIST, abilityList },
264 };
265 DistributedKv::Value value(jsonObject.dump());
266 TAG_LOGI(AAFwkTag::ABILITYMGR, "value: %{public}s", value.ToString().c_str());
267 return value;
268 }
269
ConvertAppExitReasonInfoFromValue(const DistributedKv::Value & value,AAFwk::ExitReason & exitReason,int64_t & time_stamp,std::vector<std::string> & abilityList)270 void AppExitReasonDataManager::ConvertAppExitReasonInfoFromValue(const DistributedKv::Value &value,
271 AAFwk::ExitReason &exitReason, int64_t &time_stamp, std::vector<std::string> &abilityList)
272 {
273 nlohmann::json jsonObject = nlohmann::json::parse(value.ToString(), nullptr, false);
274 if (jsonObject.is_discarded()) {
275 TAG_LOGE(AAFwkTag::ABILITYMGR, "failed to parse json sting.");
276 return;
277 }
278 if (jsonObject.contains(JSON_KEY_REASON) && jsonObject[JSON_KEY_REASON].is_number_integer()) {
279 exitReason.reason = jsonObject.at(JSON_KEY_REASON).get<AAFwk::Reason>();
280 }
281 if (jsonObject.contains(JSON_KEY_EXIT_MSG) && jsonObject[JSON_KEY_EXIT_MSG].is_string()) {
282 exitReason.exitMsg = jsonObject.at(JSON_KEY_EXIT_MSG).get<std::string>();
283 }
284 if (jsonObject.contains(JSON_KEY_TIME_STAMP) && jsonObject[JSON_KEY_TIME_STAMP].is_number_integer()) {
285 time_stamp = jsonObject.at(JSON_KEY_TIME_STAMP).get<int64_t>();
286 }
287 if (jsonObject.contains(JSON_KEY_ABILITY_LIST) && jsonObject[JSON_KEY_ABILITY_LIST].is_array()) {
288 abilityList.clear();
289 auto size = jsonObject[JSON_KEY_ABILITY_LIST].size();
290 for (size_t i = 0; i < size; i++) {
291 if (jsonObject[JSON_KEY_ABILITY_LIST][i].is_string()) {
292 abilityList.emplace_back(jsonObject[JSON_KEY_ABILITY_LIST][i]);
293 }
294 }
295 }
296 }
297
InnerDeleteAppExitReason(const std::string & keyName)298 void AppExitReasonDataManager::InnerDeleteAppExitReason(const std::string &keyName)
299 {
300 if (kvStorePtr_ == nullptr) {
301 TAG_LOGE(AAFwkTag::ABILITYMGR, "kvStore is nullptr");
302 return;
303 }
304
305 DistributedKv::Key key(keyName);
306 DistributedKv::Status status;
307 {
308 std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
309 status = kvStorePtr_->Delete(key);
310 }
311
312 if (status != DistributedKv::Status::SUCCESS) {
313 TAG_LOGE(AAFwkTag::ABILITYMGR, "delete data from kvStore error: %{public}d", status);
314 }
315 }
316
AddAbilityRecoverInfo(uint32_t accessTokenId,const std::string & moduleName,const std::string & abilityName,const int & sessionId)317 int32_t AppExitReasonDataManager::AddAbilityRecoverInfo(uint32_t accessTokenId,
318 const std::string &moduleName, const std::string &abilityName, const int &sessionId)
319 {
320 TAG_LOGI(AAFwkTag::ABILITYMGR,
321 "AddAbilityRecoverInfo tokenId %{private}u module %{public}s ability %{public}s id %{public}d ",
322 accessTokenId, moduleName.c_str(), abilityName.c_str(), sessionId);
323 {
324 std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
325 if (!CheckKvStore()) {
326 TAG_LOGE(AAFwkTag::ABILITYMGR, "kvStore is nullptr");
327 return ERR_NO_INIT;
328 }
329 }
330
331 DistributedKv::Key key = GetAbilityRecoverInfoKey(accessTokenId);
332 DistributedKv::Value value;
333 DistributedKv::Status status = kvStorePtr_->Get(key, value);
334 if (status != DistributedKv::Status::SUCCESS && status != DistributedKv::Status::KEY_NOT_FOUND) {
335 TAG_LOGE(AAFwkTag::ABILITYMGR, "AddAbilityRecoverInfo get error: %{public}d", status);
336 return ERR_INVALID_VALUE;
337 }
338
339 std::vector<std::string> recoverInfoList;
340 std::vector<int> sessionIdList;
341 std::string recoverInfo = moduleName + abilityName;
342 if (status == DistributedKv::Status::SUCCESS) {
343 ConvertAbilityRecoverInfoFromValue(value, recoverInfoList, sessionIdList);
344 auto pos = std::find(recoverInfoList.begin(), recoverInfoList.end(), recoverInfo);
345 if (pos != recoverInfoList.end()) {
346 TAG_LOGW(AAFwkTag::ABILITYMGR, "AddAbilityRecoverInfo recoverInfo already record");
347 int index = std::distance(recoverInfoList.begin(), pos);
348 sessionIdList[index] = sessionId;
349 return ERR_OK;
350 }
351 }
352
353 recoverInfoList.emplace_back(recoverInfo);
354 sessionIdList.emplace_back(sessionId);
355 value = ConvertAbilityRecoverInfoToValue(recoverInfoList, sessionIdList);
356 {
357 std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
358 status = kvStorePtr_->Put(key, value);
359 }
360
361 if (status != DistributedKv::Status::SUCCESS) {
362 TAG_LOGE(AAFwkTag::ABILITYMGR, "insert data to kvStore error : %{public}d", status);
363 return ERR_INVALID_OPERATION;
364 }
365
366 TAG_LOGI(AAFwkTag::ABILITYMGR, "AddAbilityRecoverInfo finish");
367 return ERR_OK;
368 }
369
DeleteAllRecoverInfoByTokenId(uint32_t tokenId)370 int32_t AppExitReasonDataManager::DeleteAllRecoverInfoByTokenId(uint32_t tokenId)
371 {
372 TAG_LOGI(AAFwkTag::ABILITYMGR, "tokenId: %{private}u", tokenId);
373 {
374 std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
375 if (!CheckKvStore()) {
376 TAG_LOGE(AAFwkTag::ABILITYMGR, "kvStore is nullptr!");
377 return ERR_NO_INIT;
378 }
379 }
380 InnerDeleteAbilityRecoverInfo(tokenId);
381 return ERR_OK;
382 }
383
DeleteAbilityRecoverInfo(uint32_t accessTokenId,const std::string & moduleName,const std::string & abilityName)384 int32_t AppExitReasonDataManager::DeleteAbilityRecoverInfo(
385 uint32_t accessTokenId, const std::string &moduleName, const std::string &abilityName)
386 {
387 TAG_LOGI(AAFwkTag::ABILITYMGR, "DeleteAbilityRecoverInfo tokenId %{private}u module %{public}s ability %{public}s ",
388 accessTokenId, moduleName.c_str(), abilityName.c_str());
389 {
390 std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
391 if (!CheckKvStore()) {
392 TAG_LOGE(AAFwkTag::ABILITYMGR, "kvStore is nullptr.");
393 return ERR_NO_INIT;
394 }
395 }
396
397 DistributedKv::Key key = GetAbilityRecoverInfoKey(accessTokenId);
398 DistributedKv::Value value;
399 DistributedKv::Status status = kvStorePtr_->Get(key, value);
400 if (status != DistributedKv::Status::SUCCESS) {
401 TAG_LOGE(AAFwkTag::ABILITYMGR, "DeleteAbilityRecoverInfo get error: %{public}d", status);
402 return ERR_INVALID_VALUE;
403 }
404
405 std::vector<std::string> recoverInfoList;
406 std::vector<int> sessionIdList;
407 std::string recoverInfo = moduleName + abilityName;
408 ConvertAbilityRecoverInfoFromValue(value, recoverInfoList, sessionIdList);
409 auto pos = std::find(recoverInfoList.begin(), recoverInfoList.end(), recoverInfo);
410 if (pos != recoverInfoList.end()) {
411 recoverInfoList.erase(std::remove(recoverInfoList.begin(), recoverInfoList.end(), recoverInfo),
412 recoverInfoList.end());
413 int index = std::distance(recoverInfoList.begin(), pos);
414 sessionIdList.erase(std::remove(sessionIdList.begin(), sessionIdList.end(), sessionIdList[index]),
415 sessionIdList.end());
416 UpdateAbilityRecoverInfo(accessTokenId, recoverInfoList, sessionIdList);
417 TAG_LOGI(AAFwkTag::ABILITYMGR, "DeleteAbilityRecoverInfo remove recoverInfo succeed");
418 }
419 if (recoverInfoList.empty()) {
420 InnerDeleteAbilityRecoverInfo(accessTokenId);
421 }
422
423 TAG_LOGI(AAFwkTag::ABILITYMGR, "DeleteAbilityRecoverInfo finished");
424 return ERR_OK;
425 }
426
GetAbilityRecoverInfo(uint32_t accessTokenId,const std::string & moduleName,const std::string & abilityName,bool & hasRecoverInfo)427 int32_t AppExitReasonDataManager::GetAbilityRecoverInfo(
428 uint32_t accessTokenId, const std::string &moduleName, const std::string &abilityName, bool &hasRecoverInfo)
429 {
430 TAG_LOGI(AAFwkTag::ABILITYMGR, "GetAbilityRecoverInfo tokenId %{private}u module %{public}s abillity %{public}s ",
431 accessTokenId, moduleName.c_str(), abilityName.c_str());
432 hasRecoverInfo = false;
433 {
434 std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
435 if (!CheckKvStore()) {
436 TAG_LOGE(AAFwkTag::ABILITYMGR, "kvStore is nullptr!");
437 return ERR_NO_INIT;
438 }
439 }
440
441 DistributedKv::Key key = GetAbilityRecoverInfoKey(accessTokenId);
442 DistributedKv::Value value;
443 DistributedKv::Status status = kvStorePtr_->Get(key, value);
444 if (status != DistributedKv::Status::SUCCESS) {
445 if (status == DistributedKv::Status::KEY_NOT_FOUND) {
446 TAG_LOGW(AAFwkTag::ABILITYMGR, "GetAbilityRecoverInfo KEY_NOT_FOUND.");
447 } else {
448 TAG_LOGE(AAFwkTag::ABILITYMGR, "GetAbilityRecoverInfo error: %{public}d.", status);
449 }
450 return ERR_INVALID_VALUE;
451 }
452
453 std::vector<std::string> recoverInfoList;
454 std::vector<int> sessionIdList;
455 std::string recoverInfo = moduleName + abilityName;
456 ConvertAbilityRecoverInfoFromValue(value, recoverInfoList, sessionIdList);
457 auto pos = std::find(recoverInfoList.begin(), recoverInfoList.end(), recoverInfo);
458 if (pos != recoverInfoList.end()) {
459 hasRecoverInfo = true;
460 TAG_LOGI(AAFwkTag::ABILITYMGR, "GetAbilityRecoverInfo hasRecoverInfo found info");
461 }
462 return ERR_OK;
463 }
464
GetAbilitySessionId(uint32_t accessTokenId,const std::string & moduleName,const std::string & abilityName,int & sessionId)465 int32_t AppExitReasonDataManager::GetAbilitySessionId(uint32_t accessTokenId,
466 const std::string &moduleName, const std::string &abilityName, int &sessionId)
467 {
468 TAG_LOGI(AAFwkTag::ABILITYMGR, "GetAbilityRecoverInfo tokenId %{private}u bundle %{public}s bundle %{public}s ",
469 accessTokenId, moduleName.c_str(), abilityName.c_str());
470 sessionId = 0;
471 {
472 std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
473 if (!CheckKvStore()) {
474 TAG_LOGE(AAFwkTag::ABILITYMGR, "the kvStore is nullptr.");
475 return ERR_NO_INIT;
476 }
477 }
478
479 DistributedKv::Key key = GetAbilityRecoverInfoKey(accessTokenId);
480 DistributedKv::Value value;
481 DistributedKv::Status status = kvStorePtr_->Get(key, value);
482 if (status != DistributedKv::Status::SUCCESS) {
483 if (status == DistributedKv::Status::KEY_NOT_FOUND) {
484 TAG_LOGW(AAFwkTag::ABILITYMGR, "GetAbilityRecoverInfo KEY_NOT_FOUND");
485 } else {
486 TAG_LOGE(AAFwkTag::ABILITYMGR, "GetAbilityRecoverInfo error: %{public}d", status);
487 }
488 return ERR_INVALID_VALUE;
489 }
490
491 std::vector<std::string> recoverInfoList;
492 std::vector<int> sessionIdList;
493 std::string recoverInfo = moduleName + abilityName;
494 ConvertAbilityRecoverInfoFromValue(value, recoverInfoList, sessionIdList);
495 auto pos = std::find(recoverInfoList.begin(), recoverInfoList.end(), recoverInfo);
496 if (pos != recoverInfoList.end()) {
497 int index = std::distance(recoverInfoList.begin(), pos);
498 sessionId = sessionIdList[index];
499 TAG_LOGI(AAFwkTag::ABILITYMGR, "GetAbilityRecoverInfo sessionId found info %{public}d ", sessionId);
500 }
501 return ERR_OK;
502 }
503
SetUIExtensionAbilityExitReason(const std::string & bundleName,const std::vector<std::string> & extensionList,const AAFwk::ExitReason & exitReason)504 int32_t AppExitReasonDataManager::SetUIExtensionAbilityExitReason(
505 const std::string &bundleName, const std::vector<std::string> &extensionList, const AAFwk::ExitReason &exitReason)
506 {
507 TAG_LOGD(AAFwkTag::ABILITYMGR, "called");
508 if (bundleName.empty()) {
509 TAG_LOGW(AAFwkTag::ABILITYMGR, "Invalid bundle name.");
510 return ERR_INVALID_VALUE;
511 }
512
513 {
514 std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
515 if (!CheckKvStore()) {
516 TAG_LOGE(AAFwkTag::ABILITYMGR, "kvStorePtr_ is nullptr.");
517 return ERR_NO_INIT;
518 }
519 }
520
521 for (const auto &extension : extensionList) {
522 std::string keyEx = bundleName + SEPARATOR + extension;
523 DistributedKv::Key key(keyEx);
524 DistributedKv::Value value = ConvertAppExitReasonInfoToValueOfExtensionName(extension, exitReason);
525 DistributedKv::Status status;
526 {
527 std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
528 status = kvStorePtr_->Put(key, value);
529 }
530
531 if (status != DistributedKv::Status::SUCCESS) {
532 TAG_LOGW(AAFwkTag::ABILITYMGR, "Insert data to kvStore error: %{public}d", status);
533 }
534 }
535
536 return ERR_OK;
537 }
538
GetUIExtensionAbilityExitReason(const std::string & keyEx,AAFwk::ExitReason & exitReason)539 bool AppExitReasonDataManager::GetUIExtensionAbilityExitReason(const std::string &keyEx,
540 AAFwk::ExitReason &exitReason)
541 {
542 TAG_LOGD(AAFwkTag::ABILITYMGR, "called");
543 {
544 std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
545 if (!CheckKvStore()) {
546 TAG_LOGE(AAFwkTag::ABILITYMGR, "kvStorePtr_ is nullptr.");
547 return false;
548 }
549 }
550
551 std::vector<DistributedKv::Entry> allEntries;
552 DistributedKv::Status status = kvStorePtr_->GetEntries(nullptr, allEntries);
553 if (status != DistributedKv::Status::SUCCESS) {
554 TAG_LOGE(AAFwkTag::ABILITYMGR, "Get entries error: %{public}d", status);
555 return false;
556 }
557 std::vector<std::string> abilityList;
558 int64_t time_stamp;
559 bool isHaveReason = false;
560 for (const auto &item : allEntries) {
561 if (item.key.ToString() == keyEx) {
562 ConvertAppExitReasonInfoFromValue(item.value, exitReason, time_stamp, abilityList);
563 isHaveReason = true;
564 InnerDeleteAppExitReason(keyEx);
565 break;
566 }
567 }
568
569 return isHaveReason;
570 }
571
UpdateAbilityRecoverInfo(uint32_t accessTokenId,const std::vector<std::string> & recoverInfoList,const std::vector<int> & sessionIdList)572 void AppExitReasonDataManager::UpdateAbilityRecoverInfo(uint32_t accessTokenId,
573 const std::vector<std::string> &recoverInfoList, const std::vector<int> &sessionIdList)
574 {
575 if (kvStorePtr_ == nullptr) {
576 TAG_LOGE(AAFwkTag::ABILITYMGR, "kvStore is nullptr.");
577 return;
578 }
579
580 DistributedKv::Key key = GetAbilityRecoverInfoKey(accessTokenId);
581 DistributedKv::Status status;
582 {
583 std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
584 status = kvStorePtr_->Delete(key);
585 }
586 if (status != DistributedKv::Status::SUCCESS) {
587 TAG_LOGE(AAFwkTag::ABILITYMGR, "delete data from kvStore error: %{public}d", status);
588 return;
589 }
590
591 DistributedKv::Value value = ConvertAbilityRecoverInfoToValue(recoverInfoList, sessionIdList);
592 {
593 std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
594 status = kvStorePtr_->Put(key, value);
595 }
596 if (status != DistributedKv::Status::SUCCESS) {
597 TAG_LOGE(AAFwkTag::ABILITYMGR, "insert data to kvStore failed: %{public}d", status);
598 }
599 }
600
ConvertAbilityRecoverInfoToValue(const std::vector<std::string> & recoverInfoList,const std::vector<int> & sessionIdList)601 DistributedKv::Value AppExitReasonDataManager::ConvertAbilityRecoverInfoToValue(
602 const std::vector<std::string> &recoverInfoList, const std::vector<int> &sessionIdList)
603 {
604 nlohmann::json jsonObject = nlohmann::json {
605 { JSON_KEY_RECOVER_INFO_LIST, recoverInfoList },
606 { JSON_KEY_SESSION_ID_LIST, sessionIdList },
607 };
608 DistributedKv::Value value(jsonObject.dump());
609 TAG_LOGI(AAFwkTag::ABILITYMGR, "ConvertAbilityRecoverInfoToValue value: %{public}s", value.ToString().c_str());
610 return value;
611 }
612
ConvertAbilityRecoverInfoFromValue(const DistributedKv::Value & value,std::vector<std::string> & recoverInfoList,std::vector<int> & sessionIdList)613 void AppExitReasonDataManager::ConvertAbilityRecoverInfoFromValue(const DistributedKv::Value &value,
614 std::vector<std::string> &recoverInfoList, std::vector<int> &sessionIdList)
615 {
616 nlohmann::json jsonObject = nlohmann::json::parse(value.ToString(), nullptr, false);
617 if (jsonObject.is_discarded()) {
618 TAG_LOGE(AAFwkTag::ABILITYMGR, "failed to parse json sting.");
619 return;
620 }
621 if (jsonObject.contains(JSON_KEY_RECOVER_INFO_LIST)
622 && jsonObject[JSON_KEY_RECOVER_INFO_LIST].is_array()) {
623 recoverInfoList.clear();
624 auto size = jsonObject[JSON_KEY_RECOVER_INFO_LIST].size();
625 for (size_t i = 0; i < size; i++) {
626 if (jsonObject[JSON_KEY_RECOVER_INFO_LIST][i].is_string()) {
627 recoverInfoList.emplace_back(jsonObject[JSON_KEY_RECOVER_INFO_LIST][i]);
628 }
629 }
630 }
631 if (jsonObject.contains(JSON_KEY_SESSION_ID_LIST)
632 && jsonObject[JSON_KEY_SESSION_ID_LIST].is_array()) {
633 sessionIdList.clear();
634 auto size = jsonObject[JSON_KEY_SESSION_ID_LIST].size();
635 for (size_t i = 0; i < size; i++) {
636 if (jsonObject[JSON_KEY_SESSION_ID_LIST][i].is_number_integer()) {
637 sessionIdList.emplace_back(jsonObject[JSON_KEY_SESSION_ID_LIST][i]);
638 }
639 }
640 }
641 }
642
InnerDeleteAbilityRecoverInfo(uint32_t accessTokenId)643 void AppExitReasonDataManager::InnerDeleteAbilityRecoverInfo(uint32_t accessTokenId)
644 {
645 if (kvStorePtr_ == nullptr) {
646 TAG_LOGE(AAFwkTag::ABILITYMGR, "kvStore is nullptr");
647 return;
648 }
649
650 DistributedKv::Key key = GetAbilityRecoverInfoKey(accessTokenId);
651 DistributedKv::Status status;
652 {
653 std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
654 status = kvStorePtr_->Delete(key);
655 }
656
657 if (status != DistributedKv::Status::SUCCESS) {
658 TAG_LOGE(AAFwkTag::ABILITYMGR, "delete data from kvStore error: %{public}d", status);
659 }
660 }
661
GetAbilityRecoverInfoKey(uint32_t accessTokenId)662 DistributedKv::Key AppExitReasonDataManager::GetAbilityRecoverInfoKey(uint32_t accessTokenId)
663 {
664 return DistributedKv::Key(KEY_RECOVER_INFO_PREFIX + std::to_string(accessTokenId));
665 }
666
ConvertAppExitReasonInfoToValueOfExtensionName(const std::string & extensionListName,const AAFwk::ExitReason & exitReason)667 DistributedKv::Value AppExitReasonDataManager::ConvertAppExitReasonInfoToValueOfExtensionName(
668 const std::string &extensionListName, const AAFwk::ExitReason &exitReason)
669 {
670 TAG_LOGD(AAFwkTag::ABILITYMGR, "called");
671 std::chrono::milliseconds nowMs =
672 std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch());
673 nlohmann::json jsonObject = nlohmann::json {
674 { JSON_KEY_REASON, exitReason.reason },
675 { JSON_KEY_EXIT_MSG, exitReason.exitMsg },
676 { JSON_KEY_TIME_STAMP, nowMs.count() },
677 { JSON_KEY_EXTENSION_NAME, extensionListName },
678 };
679 DistributedKv::Value value(jsonObject.dump());
680 return value;
681 }
682 } // namespace AbilityRuntime
683 } // namespace OHOS
684