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 "ability_manager_errors.h"
21 #include "accesstoken_kit.h"
22 #include "exit_info_data_manager.h"
23 #include "os_account_manager_wrapper.h"
24
25 namespace OHOS {
26 namespace AbilityRuntime {
27 namespace {
28 constexpr int32_t CHECK_INTERVAL = 100000; // 100ms
29 constexpr int32_t MAX_TIMES = 5; // 5 * 100ms = 500ms
30 constexpr const char *APP_EXIT_REASON_STORAGE_DIR = "/data/service/el1/public/database/app_exit_reason";
31 const std::string JSON_KEY_REASON = "reason";
32 const std::string JSON_KEY_EXIT_MSG = "exit_msg";
33 const std::string JSON_KEY_KILL_MSG = "kill_msg";
34 const std::string JSON_KEY_TIME_STAMP = "time_stamp";
35 const std::string JSON_KEY_ABILITY_LIST = "ability_list";
36 const std::string KEY_RECOVER_INFO_PREFIX = "recover_info";
37 const std::string JSON_KEY_RECOVER_INFO_LIST = "recover_info_list";
38 const std::string JSON_KEY_SESSION_ID_LIST = "session_id_list";
39 const std::string JSON_KEY_EXTENSION_NAME = "extension_name";
40 const std::string JSON_KEY_ACCESSTOKENId = "access_token_id";
41 const std::string SEPARATOR = ":";
42 const std::string KEY_KILL_PROCESS_REASON_PREFIX = "process_exit_detail_info";
43 const std::string JSON_KEY_SUB_KILL_REASON = "sub_kill_reason";
44 const std::string JSON_KEY_PID = "pid";
45 const std::string JSON_KEY_UID = "uid";
46 const std::string JSON_KEY_PROCESS_NAME = "process_name";
47 const std::string JSON_KEY_PSS_VALUE = "pss_value";
48 const std::string JSON_KEY_RSS_VALUE = "rss_value";
49 } // namespace
AppExitReasonDataManager()50 AppExitReasonDataManager::AppExitReasonDataManager() {}
51
~AppExitReasonDataManager()52 AppExitReasonDataManager::~AppExitReasonDataManager()
53 {
54 if (kvStorePtr_ != nullptr) {
55 dataManager_.CloseKvStore(appId_, kvStorePtr_);
56 }
57 }
58
GetKvStore()59 DistributedKv::Status AppExitReasonDataManager::GetKvStore()
60 {
61 DistributedKv::Options options = { .createIfMissing = true,
62 .encrypt = false,
63 .autoSync = true,
64 .syncable = false,
65 .securityLevel = DistributedKv::SecurityLevel::S2,
66 .area = DistributedKv::EL1,
67 .kvStoreType = DistributedKv::KvStoreType::SINGLE_VERSION,
68 .baseDir = APP_EXIT_REASON_STORAGE_DIR };
69
70 DistributedKv::Status status = dataManager_.GetSingleKvStore(options, appId_, storeId_, kvStorePtr_);
71 if (status != DistributedKv::Status::SUCCESS) {
72 TAG_LOGE(AAFwkTag::ABILITYMGR, "return error: %{public}d", status);
73 } else {
74 TAG_LOGI(AAFwkTag::ABILITYMGR, "get kvStore success");
75 }
76 return status;
77 }
78
CheckKvStore()79 bool AppExitReasonDataManager::CheckKvStore()
80 {
81 TAG_LOGD(AAFwkTag::ABILITYMGR, "AppExitReasonDataManager::CheckKvStore start");
82 if (kvStorePtr_ != nullptr) {
83 return true;
84 }
85 int32_t tryTimes = MAX_TIMES;
86 while (tryTimes > 0) {
87 DistributedKv::Status status = GetKvStore();
88 if (status == DistributedKv::Status::SUCCESS && kvStorePtr_ != nullptr) {
89 return true;
90 }
91 TAG_LOGD(AAFwkTag::ABILITYMGR, "try times: %{public}d", tryTimes);
92 usleep(CHECK_INTERVAL);
93 tryTimes--;
94 }
95 return kvStorePtr_ != nullptr;
96 }
97
SetAppExitReason(const std::string & bundleName,uint32_t accessTokenId,const std::vector<std::string> & abilityList,const AAFwk::ExitReason & exitReason,const AppExecFwk::RunningProcessInfo & processInfo,bool withKillMsg)98 int32_t AppExitReasonDataManager::SetAppExitReason(const std::string &bundleName, uint32_t accessTokenId,
99 const std::vector<std::string> &abilityList, const AAFwk::ExitReason &exitReason,
100 const AppExecFwk::RunningProcessInfo &processInfo, bool withKillMsg)
101 {
102 if (bundleName.empty() || accessTokenId == Security::AccessToken::INVALID_TOKENID) {
103 TAG_LOGW(AAFwkTag::ABILITYMGR, "invalid value");
104 return ERR_INVALID_VALUE;
105 }
106 TAG_LOGD(AAFwkTag::ABILITYMGR, "bundleName: %{public}s, tokenId: %{private}u", bundleName.c_str(), accessTokenId);
107 std::string keyStr = std::to_string(accessTokenId);
108 {
109 std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
110 if (!CheckKvStore()) {
111 TAG_LOGE(AAFwkTag::ABILITYMGR, "null kvStore");
112 return ERR_NO_INIT;
113 }
114 }
115
116 DistributedKv::Key key(keyStr);
117 DistributedKv::Value value = ConvertAppExitReasonInfoToValue(abilityList, exitReason, processInfo, withKillMsg);
118 DistributedKv::Status status;
119 {
120 std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
121 status = kvStorePtr_->Put(key, value);
122 }
123
124 if (status != DistributedKv::Status::SUCCESS) {
125 TAG_LOGE(AAFwkTag::ABILITYMGR, "insert data err: %{public}d", status);
126 return ERR_INVALID_OPERATION;
127 }
128 TAG_LOGI(AAFwkTag::ABILITYMGR, "set reason info: %{public}s", value.ToString().c_str());
129 return ERR_OK;
130 }
131
132
DeleteAppExitReason(const std::string & bundleName,int32_t uid,int32_t appIndex)133 int32_t AppExitReasonDataManager::DeleteAppExitReason(const std::string &bundleName, int32_t uid, int32_t appIndex)
134 {
135 int32_t userId;
136 if (DelayedSingleton<AppExecFwk::OsAccountManagerWrapper>::GetInstance()->
137 GetOsAccountLocalIdFromUid(uid, userId) != ERR_OK) {
138 TAG_LOGE(AAFwkTag::ABILITYMGR, "get GetOsAccountLocalIdFromUid failed");
139 return ERR_INVALID_VALUE;
140 }
141 TAG_LOGD(AAFwkTag::ABILITYMGR,
142 "userId: %{public}d, bundleName: %{public}s, appIndex: %{public}d", userId, bundleName.c_str(), appIndex);
143 uint32_t accessTokenId = Security::AccessToken::AccessTokenKit::GetHapTokenID(userId, bundleName, appIndex);
144 return DeleteAppExitReason(bundleName, accessTokenId);
145 }
146
DeleteAppExitReason(const std::string & bundleName,uint32_t accessTokenId)147 int32_t AppExitReasonDataManager::DeleteAppExitReason(const std::string &bundleName, uint32_t accessTokenId)
148 {
149 auto accessTokenIdStr = std::to_string(accessTokenId);
150 if (bundleName.empty() || accessTokenId == Security::AccessToken::INVALID_TOKENID) {
151 TAG_LOGW(AAFwkTag::ABILITYMGR, "invalid value");
152 return ERR_INVALID_VALUE;
153 }
154
155 TAG_LOGD(AAFwkTag::ABILITYMGR, "bundleName: %{public}s, tokenId: %{private}u", bundleName.c_str(), accessTokenId);
156 {
157 std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
158 if (!CheckKvStore()) {
159 TAG_LOGE(AAFwkTag::ABILITYMGR, "null kvStore");
160 return ERR_NO_INIT;
161 }
162 }
163
164 std::string keyUiExten = bundleName + SEPARATOR;
165 std::vector<DistributedKv::Entry> allEntries;
166 DistributedKv::Status status = kvStorePtr_->GetEntries(nullptr, allEntries);
167 if (status != DistributedKv::Status::SUCCESS) {
168 TAG_LOGE(AAFwkTag::ABILITYMGR, "error: %{public}d", status);
169 return ERR_INVALID_OPERATION;
170 }
171
172 for (const auto &item : allEntries) {
173 const auto &keyValue = item.key.ToString();
174 if (keyValue.find(accessTokenIdStr) == std::string::npos &&
175 keyValue.find(keyUiExten) == std::string::npos) {
176 continue;
177 }
178
179 std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
180 auto errCode = kvStorePtr_->Delete(item.key);
181 status = (errCode != DistributedKv::Status::SUCCESS) ? errCode : status;
182 }
183
184 if (status != DistributedKv::Status::SUCCESS) {
185 TAG_LOGE(AAFwkTag::ABILITYMGR, "error: %{public}d", status);
186 return ERR_INVALID_OPERATION;
187 }
188 return ERR_OK;
189 }
190
GetAppExitReason(const std::string & bundleName,uint32_t accessTokenId,const std::string & abilityName,bool & isSetReason,AAFwk::ExitReason & exitReason,AppExecFwk::RunningProcessInfo & processInfo,int64_t & time_stamp,bool & withKillMsg)191 int32_t AppExitReasonDataManager::GetAppExitReason(const std::string &bundleName, uint32_t accessTokenId,
192 const std::string &abilityName, bool &isSetReason, AAFwk::ExitReason &exitReason,
193 AppExecFwk::RunningProcessInfo &processInfo, int64_t &time_stamp, bool &withKillMsg)
194 {
195 auto accessTokenIdStr = std::to_string(accessTokenId);
196 if (bundleName.empty() || accessTokenId == Security::AccessToken::INVALID_TOKENID) {
197 TAG_LOGW(AAFwkTag::ABILITYMGR, "invalid value");
198 return ERR_INVALID_VALUE;
199 }
200 TAG_LOGD(AAFwkTag::ABILITYMGR, "bundleName: %{public}s, tokenId: %{private}u, abilityName: %{public}s.",
201 bundleName.c_str(), accessTokenId, abilityName.c_str());
202 {
203 std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
204 if (!CheckKvStore()) {
205 TAG_LOGE(AAFwkTag::ABILITYMGR, "null kvStore");
206 return ERR_NO_INIT;
207 }
208 }
209
210 std::vector<DistributedKv::Entry> allEntries;
211 DistributedKv::Status status = kvStorePtr_->GetEntries(nullptr, allEntries);
212 if (status != DistributedKv::Status::SUCCESS) {
213 TAG_LOGE(AAFwkTag::ABILITYMGR, "get entries error: %{public}d", status);
214 return ERR_INVALID_VALUE;
215 }
216
217 std::vector<std::string> abilityList;
218 for (const auto &item : allEntries) {
219 if (item.key.ToString() == accessTokenIdStr) {
220 ConvertAppExitReasonInfoFromValue(item.value, exitReason, time_stamp, abilityList, processInfo,
221 withKillMsg);
222 auto pos = std::find(abilityList.begin(), abilityList.end(), abilityName);
223 if (pos != abilityList.end()) {
224 isSetReason = true;
225 abilityList.erase(std::remove(abilityList.begin(), abilityList.end(), abilityName), abilityList.end());
226 UpdateAppExitReason(accessTokenId, abilityList, exitReason, processInfo, withKillMsg);
227 }
228 TAG_LOGI(AAFwkTag::ABILITYMGR, "current bundle name: %{public}s, tokenId:%{private}u, reason: %{public}d,"
229 " exitMsg: %{public}s, abilityName:%{public}s isSetReason:%{public}d",
230 bundleName.c_str(), accessTokenId, exitReason.reason, exitReason.exitMsg.c_str(),
231 abilityName.c_str(), isSetReason);
232 if (abilityList.empty()) {
233 InnerDeleteAppExitReason(accessTokenIdStr);
234 }
235 break;
236 }
237 }
238
239 return ERR_OK;
240 }
241
UpdateAppExitReason(uint32_t accessTokenId,const std::vector<std::string> & abilityList,const AAFwk::ExitReason & exitReason,const AppExecFwk::RunningProcessInfo & processInfo,bool withKillMsg)242 void AppExitReasonDataManager::UpdateAppExitReason(uint32_t accessTokenId, const std::vector<std::string> &abilityList,
243 const AAFwk::ExitReason &exitReason, const AppExecFwk::RunningProcessInfo &processInfo, bool withKillMsg)
244 {
245 if (kvStorePtr_ == nullptr) {
246 TAG_LOGE(AAFwkTag::ABILITYMGR, "null kvStorePtr_");
247 return;
248 }
249
250 DistributedKv::Key key(std::to_string(accessTokenId));
251 DistributedKv::Status status;
252 {
253 std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
254 status = kvStorePtr_->Delete(key);
255 }
256 if (status != DistributedKv::Status::SUCCESS) {
257 TAG_LOGE(AAFwkTag::ABILITYMGR, "error: %{public}d", status);
258 return;
259 }
260
261 DistributedKv::Value value = ConvertAppExitReasonInfoToValue(abilityList, exitReason, processInfo, withKillMsg);
262 {
263 std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
264 status = kvStorePtr_->Put(key, value);
265 }
266 if (status != DistributedKv::Status::SUCCESS) {
267 TAG_LOGE(AAFwkTag::ABILITYMGR, "error: %{public}d", status);
268 }
269 }
270
RecordSignalReason(int32_t pid,int32_t uid,int32_t signal,std::string & bundleName)271 int32_t AppExitReasonDataManager::RecordSignalReason(int32_t pid, int32_t uid, int32_t signal, std::string &bundleName)
272 {
273 std::vector<DistributedKv::Entry> allEntries;
274 DistributedKv::Status status = DistributedKv::SUCCESS;
275 {
276 std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
277 if (!CheckKvStore()) {
278 TAG_LOGE(AAFwkTag::ABILITYMGR, "null kvStore");
279 return ERR_NO_INIT;
280 }
281 status = kvStorePtr_->GetEntries(nullptr, allEntries);
282 }
283 if (status != DistributedKv::Status::SUCCESS) {
284 TAG_LOGE(AAFwkTag::ABILITYMGR, "get entries error: %{public}d", status);
285 {
286 std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
287 status = RestoreKvStore(status);
288 }
289 return ERR_INVALID_VALUE;
290 }
291 uint32_t accessTokenId = 0;
292 ExitCacheInfo cacheInfo = {};
293 if (!ExitInfoDataManager::GetInstance().GetExitInfo(pid, uid, accessTokenId, cacheInfo)) {
294 TAG_LOGE(AAFwkTag::ABILITYMGR, "not found, pid: %{public}d, uid: %{public}d", pid, uid);
295 return AAFwk::ERR_GET_EXIT_INFO_FAILED;
296 }
297 auto ret = 0;
298 AAFwk::ExitReason exitReason = {};
299 exitReason.reason = AAFwk::REASON_SIGNAL;
300 exitReason.subReason = signal;
301 AppExecFwk::RunningProcessInfo processInfo = {};
302 processInfo.pid_ = cacheInfo.exitInfo.pid;
303 processInfo.uid_ = cacheInfo.exitInfo.uid;
304 processInfo.rssValue = cacheInfo.exitInfo.rss;
305 processInfo.pssValue = cacheInfo.exitInfo.pss;
306 processInfo.processName_ = cacheInfo.exitInfo.processName;
307
308 for (const auto &item : allEntries) {
309 if (item.key.ToString() == std::to_string(accessTokenId)) {
310 TAG_LOGI(AAFwkTag::ABILITYMGR, "record exist, not record signal reason any more");
311 return 0;
312 }
313 }
314 TAG_LOGI(AAFwkTag::ABILITYMGR, "key: %{public}s", std::to_string(accessTokenId).c_str());
315 ret = SetAppExitReason(cacheInfo.bundleName, accessTokenId, cacheInfo.abilityNames, exitReason,
316 processInfo, false);
317 if (ret != 0) {
318 TAG_LOGE(AAFwkTag::ABILITYMGR, "SetAppExitReason failed, ret: %{public}d", ret);
319 return AAFwk::ERR_RECORD_SIGNAL_REASON_FAILED;
320 }
321 return ret;
322 }
323
ConvertAppExitReasonInfoToValue(const std::vector<std::string> & abilityList,const AAFwk::ExitReason & exitReason,const AppExecFwk::RunningProcessInfo & processInfo,bool withKillMsg)324 DistributedKv::Value AppExitReasonDataManager::ConvertAppExitReasonInfoToValue(
325 const std::vector<std::string> &abilityList, const AAFwk::ExitReason &exitReason,
326 const AppExecFwk::RunningProcessInfo &processInfo, bool withKillMsg)
327 {
328 std::chrono::milliseconds nowMs =
329 std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch());
330 std::string killMsg = "";
331 std::string exitMsg = exitReason.exitMsg;
332 if (withKillMsg) {
333 killMsg = exitReason.exitMsg;
334 }
335 nlohmann::json jsonObject = nlohmann::json {
336 { JSON_KEY_PID, processInfo.pid_ },
337 { JSON_KEY_UID, processInfo.uid_ },
338 { JSON_KEY_REASON, exitReason.reason },
339 { JSON_KEY_SUB_KILL_REASON, exitReason.subReason },
340 { JSON_KEY_EXIT_MSG, exitMsg },
341 { JSON_KEY_KILL_MSG, killMsg },
342 { JSON_KEY_RSS_VALUE, processInfo.rssValue },
343 { JSON_KEY_PSS_VALUE, processInfo.pssValue },
344 { JSON_KEY_PROCESS_NAME, processInfo.processName_ },
345 { JSON_KEY_TIME_STAMP, nowMs.count() },
346 { JSON_KEY_ABILITY_LIST, abilityList },
347 };
348 DistributedKv::Value value(jsonObject.dump());
349 return value;
350 }
351
ConvertAppExitReasonInfoFromValue(const DistributedKv::Value & value,AAFwk::ExitReason & exitReason,int64_t & time_stamp,std::vector<std::string> & abilityList,AppExecFwk::RunningProcessInfo & processInfo,bool & withKillMsg)352 void AppExitReasonDataManager::ConvertAppExitReasonInfoFromValue(const DistributedKv::Value &value,
353 AAFwk::ExitReason &exitReason, int64_t &time_stamp, std::vector<std::string> &abilityList,
354 AppExecFwk::RunningProcessInfo &processInfo, bool &withKillMsg)
355 {
356 nlohmann::json jsonObject = nlohmann::json::parse(value.ToString(), nullptr, false);
357 if (jsonObject.is_discarded()) {
358 TAG_LOGE(AAFwkTag::ABILITYMGR, "parse json sting failed");
359 return;
360 }
361 if (jsonObject.contains(JSON_KEY_PID) && jsonObject[JSON_KEY_PID].is_number_integer()) {
362 processInfo.pid_ = jsonObject.at(JSON_KEY_PID).get<int32_t>();
363 }
364 if (jsonObject.contains(JSON_KEY_UID) && jsonObject[JSON_KEY_UID].is_number_integer()) {
365 processInfo.uid_ = jsonObject.at(JSON_KEY_UID).get<int32_t>();
366 }
367 ConvertReasonFromValue(jsonObject, exitReason, withKillMsg);
368 if (jsonObject.contains(JSON_KEY_RSS_VALUE) && jsonObject[JSON_KEY_RSS_VALUE].is_number_integer()) {
369 processInfo.rssValue = jsonObject.at(JSON_KEY_RSS_VALUE).get<int32_t>();
370 }
371 if (jsonObject.contains(JSON_KEY_PSS_VALUE) && jsonObject[JSON_KEY_PSS_VALUE].is_number_integer()) {
372 processInfo.pssValue = jsonObject.at(JSON_KEY_PSS_VALUE).get<int32_t>();
373 }
374 if (jsonObject.contains(JSON_KEY_PROCESS_NAME) && jsonObject[JSON_KEY_PROCESS_NAME].is_string()) {
375 processInfo.processName_ = jsonObject.at(JSON_KEY_PROCESS_NAME).get<std::string>();
376 }
377 if (jsonObject.contains(JSON_KEY_TIME_STAMP) && jsonObject[JSON_KEY_TIME_STAMP].is_number_integer()) {
378 time_stamp = jsonObject.at(JSON_KEY_TIME_STAMP).get<int64_t>();
379 }
380 if (jsonObject.contains(JSON_KEY_ABILITY_LIST) && jsonObject[JSON_KEY_ABILITY_LIST].is_array()) {
381 abilityList.clear();
382 auto size = jsonObject[JSON_KEY_ABILITY_LIST].size();
383 for (size_t i = 0; i < size; i++) {
384 if (jsonObject[JSON_KEY_ABILITY_LIST][i].is_string()) {
385 abilityList.emplace_back(jsonObject[JSON_KEY_ABILITY_LIST][i]);
386 }
387 }
388 }
389 }
390
ConvertReasonFromValue(const nlohmann::json & jsonObject,AAFwk::ExitReason & exitReason,bool & withKillMsg)391 void AppExitReasonDataManager::ConvertReasonFromValue(const nlohmann::json &jsonObject, AAFwk::ExitReason &exitReason,
392 bool &withKillMsg)
393 {
394 if (jsonObject.contains(JSON_KEY_REASON) && jsonObject[JSON_KEY_REASON].is_number_integer()) {
395 exitReason.reason = jsonObject.at(JSON_KEY_REASON).get<AAFwk::Reason>();
396 }
397 if (jsonObject.contains(JSON_KEY_SUB_KILL_REASON) && jsonObject[JSON_KEY_SUB_KILL_REASON].is_number_integer()) {
398 exitReason.subReason = jsonObject.at(JSON_KEY_SUB_KILL_REASON).get<int32_t>();
399 }
400 if (jsonObject.contains(JSON_KEY_EXIT_MSG) && jsonObject[JSON_KEY_EXIT_MSG].is_string()) {
401 exitReason.exitMsg = jsonObject.at(JSON_KEY_EXIT_MSG).get<std::string>();
402 }
403 if (jsonObject.contains(JSON_KEY_KILL_MSG) && jsonObject[JSON_KEY_KILL_MSG].is_string()) {
404 auto killMsg = jsonObject.at(JSON_KEY_KILL_MSG).get<std::string>();
405 if (!killMsg.empty()) {
406 exitReason.exitMsg = killMsg;
407 withKillMsg = true;
408 }
409 }
410 }
411
InnerDeleteAppExitReason(const std::string & keyName)412 void AppExitReasonDataManager::InnerDeleteAppExitReason(const std::string &keyName)
413 {
414 if (kvStorePtr_ == nullptr) {
415 TAG_LOGE(AAFwkTag::ABILITYMGR, "null kvStorePtr_");
416 return;
417 }
418
419 DistributedKv::Key key(keyName);
420 DistributedKv::Status status;
421 {
422 std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
423 status = kvStorePtr_->Delete(key);
424 }
425
426 if (status != DistributedKv::Status::SUCCESS) {
427 TAG_LOGE(AAFwkTag::ABILITYMGR, "error: %{public}d", status);
428 }
429 }
430
AddAbilityRecoverInfo(uint32_t accessTokenId,const std::string & moduleName,const std::string & abilityName,const int & sessionId)431 int32_t AppExitReasonDataManager::AddAbilityRecoverInfo(uint32_t accessTokenId,
432 const std::string &moduleName, const std::string &abilityName, const int &sessionId)
433 {
434 TAG_LOGI(AAFwkTag::ABILITYMGR,
435 "AddAbilityRecoverInfo tokenId %{private}u module %{public}s ability %{public}s id %{public}d ",
436 accessTokenId, moduleName.c_str(), abilityName.c_str(), sessionId);
437 {
438 std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
439 if (!CheckKvStore()) {
440 TAG_LOGE(AAFwkTag::ABILITYMGR, "null kvStore");
441 return ERR_NO_INIT;
442 }
443 }
444
445 DistributedKv::Key key = GetAbilityRecoverInfoKey(accessTokenId);
446 DistributedKv::Value value;
447 DistributedKv::Status status;
448 {
449 std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
450 status = kvStorePtr_->Get(key, value);
451 }
452 if (status != DistributedKv::Status::SUCCESS && status != DistributedKv::Status::KEY_NOT_FOUND) {
453 TAG_LOGE(AAFwkTag::ABILITYMGR, "AddAbilityRecoverInfo get error: %{public}d", status);
454 return ERR_INVALID_VALUE;
455 }
456
457 std::vector<std::string> recoverInfoList;
458 std::vector<int> sessionIdList;
459 std::string recoverInfo = moduleName + abilityName;
460 if (status == DistributedKv::Status::SUCCESS) {
461 ConvertAbilityRecoverInfoFromValue(value, recoverInfoList, sessionIdList);
462 auto pos = std::find(recoverInfoList.begin(), recoverInfoList.end(), recoverInfo);
463 if (pos != recoverInfoList.end()) {
464 TAG_LOGW(AAFwkTag::ABILITYMGR, "AddAbilityRecoverInfo recoverInfo already record");
465 int index = std::distance(recoverInfoList.begin(), pos);
466 sessionIdList[index] = sessionId;
467 return ERR_OK;
468 }
469 }
470
471 recoverInfoList.emplace_back(recoverInfo);
472 sessionIdList.emplace_back(sessionId);
473 value = ConvertAbilityRecoverInfoToValue(recoverInfoList, sessionIdList);
474 {
475 std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
476 status = kvStorePtr_->Put(key, value);
477 }
478
479 if (status != DistributedKv::Status::SUCCESS) {
480 TAG_LOGE(AAFwkTag::ABILITYMGR, "error : %{public}d", status);
481 return ERR_INVALID_OPERATION;
482 }
483 InnerAddSessionId(sessionId, accessTokenId);
484
485 TAG_LOGI(AAFwkTag::ABILITYMGR, "AddAbilityRecoverInfo finish");
486 return ERR_OK;
487 }
488
DeleteAllRecoverInfoByTokenId(uint32_t tokenId)489 int32_t AppExitReasonDataManager::DeleteAllRecoverInfoByTokenId(uint32_t tokenId)
490 {
491 TAG_LOGI(AAFwkTag::ABILITYMGR, "tokenId: %{private}u", tokenId);
492 {
493 std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
494 if (!CheckKvStore()) {
495 TAG_LOGE(AAFwkTag::ABILITYMGR, "null kvStore");
496 return ERR_NO_INIT;
497 }
498 }
499
500 DistributedKv::Key key = GetAbilityRecoverInfoKey(tokenId);
501 DistributedKv::Value value;
502 DistributedKv::Status status;
503 {
504 std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
505 status = kvStorePtr_->Get(key, value);
506 }
507 if (status != DistributedKv::Status::SUCCESS) {
508 TAG_LOGE(AAFwkTag::ABILITYMGR, "failed:%{public}d", status);
509 return ERR_INVALID_VALUE;
510 }
511
512 std::vector<std::string> recoverInfoList;
513 std::vector<int> sessionIdList;
514 ConvertAbilityRecoverInfoFromValue(value, recoverInfoList, sessionIdList);
515 if (!sessionIdList.empty()) {
516 for (auto sessionId : sessionIdList) {
517 InnerDeleteSessionId(sessionId);
518 }
519 }
520
521 InnerDeleteAbilityRecoverInfo(tokenId);
522 return ERR_OK;
523 }
524
DeleteAbilityRecoverInfoBySessionId(const int32_t sessionId)525 int32_t AppExitReasonDataManager::DeleteAbilityRecoverInfoBySessionId(const int32_t sessionId)
526 {
527 TAG_LOGI(AAFwkTag::ABILITYMGR, "sessionId %{public}d", sessionId);
528 {
529 std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
530 if (!CheckKvStore()) {
531 TAG_LOGE(AAFwkTag::ABILITYMGR, "null kvStore");
532 return ERR_NO_INIT;
533 }
534 }
535
536 uint32_t accessTokenId = GetTokenIdBySessionID(sessionId);
537 DistributedKv::Key key = GetAbilityRecoverInfoKey(accessTokenId);
538 DistributedKv::Value value;
539 DistributedKv::Status status;
540 {
541 std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
542 status = kvStorePtr_->Get(key, value);
543 }
544 if (status != DistributedKv::Status::SUCCESS) {
545 TAG_LOGE(AAFwkTag::ABILITYMGR, "failed:%{public}d", status);
546 return ERR_INVALID_VALUE;
547 }
548
549 std::vector<std::string> recoverInfoList;
550 std::vector<int> sessionIdList;
551 ConvertAbilityRecoverInfoFromValue(value, recoverInfoList, sessionIdList);
552 auto pos = std::find(sessionIdList.begin(), sessionIdList.end(), sessionId);
553 if (pos != sessionIdList.end()) {
554 sessionIdList.erase(std::remove(sessionIdList.begin(), sessionIdList.end(), sessionId),
555 sessionIdList.end());
556 int index = std::distance(sessionIdList.begin(), pos);
557 recoverInfoList.erase(std::remove(recoverInfoList.begin(), recoverInfoList.end(), recoverInfoList[index]),
558 recoverInfoList.end());
559 InnerDeleteSessionId(sessionId);
560 UpdateAbilityRecoverInfo(accessTokenId, recoverInfoList, sessionIdList);
561 TAG_LOGI(AAFwkTag::ABILITYMGR, "DeleteAbilityRecoverInfoBySessionId remove recoverInfo succeed");
562 }
563 if (sessionIdList.empty()) {
564 InnerDeleteAbilityRecoverInfo(accessTokenId);
565 }
566
567 TAG_LOGI(AAFwkTag::ABILITYMGR, "DeleteAbilityRecoverInfoBySessionId finished");
568 return ERR_OK;
569 }
570
DeleteAbilityRecoverInfo(uint32_t accessTokenId,const std::string & moduleName,const std::string & abilityName)571 int32_t AppExitReasonDataManager::DeleteAbilityRecoverInfo(
572 uint32_t accessTokenId, const std::string &moduleName, const std::string &abilityName)
573 {
574 TAG_LOGI(AAFwkTag::ABILITYMGR, "tokenId %{private}u module %{public}s ability %{public}s ",
575 accessTokenId, moduleName.c_str(), abilityName.c_str());
576 {
577 std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
578 if (!CheckKvStore()) {
579 TAG_LOGE(AAFwkTag::ABILITYMGR, "null kvStore");
580 return ERR_NO_INIT;
581 }
582 }
583
584 DistributedKv::Key key = GetAbilityRecoverInfoKey(accessTokenId);
585 DistributedKv::Value value;
586 DistributedKv::Status status;
587 {
588 std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
589 status = kvStorePtr_->Get(key, value);
590 }
591 if (status != DistributedKv::Status::SUCCESS) {
592 TAG_LOGE(AAFwkTag::ABILITYMGR, "failed:%{public}d", status);
593 return ERR_INVALID_VALUE;
594 }
595
596 std::vector<std::string> recoverInfoList;
597 std::vector<int> sessionIdList;
598 std::string recoverInfo = moduleName + abilityName;
599 ConvertAbilityRecoverInfoFromValue(value, recoverInfoList, sessionIdList);
600 auto pos = std::find(recoverInfoList.begin(), recoverInfoList.end(), recoverInfo);
601 if (pos != recoverInfoList.end()) {
602 recoverInfoList.erase(std::remove(recoverInfoList.begin(), recoverInfoList.end(), recoverInfo),
603 recoverInfoList.end());
604 int index = std::distance(recoverInfoList.begin(), pos);
605 sessionIdList.erase(std::remove(sessionIdList.begin(), sessionIdList.end(), sessionIdList[index]),
606 sessionIdList.end());
607 InnerDeleteSessionId(sessionIdList[index]);
608 UpdateAbilityRecoverInfo(accessTokenId, recoverInfoList, sessionIdList);
609 TAG_LOGI(AAFwkTag::ABILITYMGR, "DeleteAbilityRecoverInfo remove recoverInfo succeed");
610 }
611 if (recoverInfoList.empty()) {
612 InnerDeleteAbilityRecoverInfo(accessTokenId);
613 }
614
615 TAG_LOGI(AAFwkTag::ABILITYMGR, "DeleteAbilityRecoverInfo finished");
616 return ERR_OK;
617 }
618
GetAbilityRecoverInfo(uint32_t accessTokenId,const std::string & moduleName,const std::string & abilityName,bool & hasRecoverInfo)619 int32_t AppExitReasonDataManager::GetAbilityRecoverInfo(
620 uint32_t accessTokenId, const std::string &moduleName, const std::string &abilityName, bool &hasRecoverInfo)
621 {
622 TAG_LOGI(AAFwkTag::ABILITYMGR, "tokenId %{private}u module %{public}s abillity %{public}s",
623 accessTokenId, moduleName.c_str(), abilityName.c_str());
624 hasRecoverInfo = false;
625 {
626 std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
627 if (!CheckKvStore()) {
628 TAG_LOGE(AAFwkTag::ABILITYMGR, "null kvStore");
629 return ERR_NO_INIT;
630 }
631 }
632
633 DistributedKv::Key key = GetAbilityRecoverInfoKey(accessTokenId);
634 DistributedKv::Value value;
635 DistributedKv::Status status;
636 {
637 std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
638 status = kvStorePtr_->Get(key, value);
639 }
640 if (status != DistributedKv::Status::SUCCESS) {
641 if (status == DistributedKv::Status::KEY_NOT_FOUND) {
642 TAG_LOGW(AAFwkTag::ABILITYMGR, "KEY_NOT_FOUND");
643 } else {
644 TAG_LOGE(AAFwkTag::ABILITYMGR, "error:%{public}d", status);
645 }
646 return ERR_INVALID_VALUE;
647 }
648
649 std::vector<std::string> recoverInfoList;
650 std::vector<int> sessionIdList;
651 std::string recoverInfo = moduleName + abilityName;
652 ConvertAbilityRecoverInfoFromValue(value, recoverInfoList, sessionIdList);
653 auto pos = std::find(recoverInfoList.begin(), recoverInfoList.end(), recoverInfo);
654 if (pos != recoverInfoList.end()) {
655 hasRecoverInfo = true;
656 TAG_LOGI(AAFwkTag::ABILITYMGR, "GetAbilityRecoverInfo hasRecoverInfo found info");
657 }
658 return ERR_OK;
659 }
660
GetTokenIdBySessionID(const int32_t sessionId)661 uint32_t AppExitReasonDataManager::GetTokenIdBySessionID(const int32_t sessionId)
662 {
663 if (kvStorePtr_ == nullptr) {
664 TAG_LOGE(AAFwkTag::ABILITYMGR, "null kvStorePtr_");
665 return ERR_NO_INIT;
666 }
667 DistributedKv::Key key = GetAbilityRecoverInfoKey(sessionId);
668 DistributedKv::Value value;
669 DistributedKv::Status status;
670 {
671 std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
672 status = kvStorePtr_->Get(key, value);
673 }
674 if (status != DistributedKv::Status::SUCCESS) {
675 TAG_LOGE(AAFwkTag::ABILITYMGR, "failed:%{public}d", status);
676 return ERR_INVALID_VALUE;
677 }
678 uint32_t accessTokenId;
679 ConvertAccessTokenIdFromValue(value, accessTokenId);
680 return accessTokenId;
681 }
682
SetUIExtensionAbilityExitReason(const std::string & bundleName,const std::vector<std::string> & extensionList,const AAFwk::ExitReason & exitReason,const AppExecFwk::RunningProcessInfo & processInfo,bool withKillMsg)683 int32_t AppExitReasonDataManager::SetUIExtensionAbilityExitReason(
684 const std::string &bundleName, const std::vector<std::string> &extensionList, const AAFwk::ExitReason &exitReason,
685 const AppExecFwk::RunningProcessInfo &processInfo, bool withKillMsg)
686 {
687 TAG_LOGD(AAFwkTag::ABILITYMGR, "called");
688 if (bundleName.empty()) {
689 TAG_LOGW(AAFwkTag::ABILITYMGR, "invalid bundle name");
690 return ERR_INVALID_VALUE;
691 }
692
693 {
694 std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
695 if (!CheckKvStore()) {
696 TAG_LOGE(AAFwkTag::ABILITYMGR, "null kvStorePtr_");
697 return ERR_NO_INIT;
698 }
699 }
700
701 for (const auto &extension : extensionList) {
702 std::string keyEx = bundleName + SEPARATOR + extension;
703 DistributedKv::Key key(keyEx);
704 DistributedKv::Value value = ConvertAppExitReasonInfoToValueOfExtensionName(extension, exitReason,
705 processInfo, withKillMsg);
706 DistributedKv::Status status;
707 {
708 std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
709 status = kvStorePtr_->Put(key, value);
710 }
711
712 if (status != DistributedKv::Status::SUCCESS) {
713 TAG_LOGW(AAFwkTag::ABILITYMGR, "error: %{public}d", status);
714 }
715 }
716
717 return ERR_OK;
718 }
719
GetUIExtensionAbilityExitReason(const std::string & keyEx,AAFwk::ExitReason & exitReason,AppExecFwk::RunningProcessInfo & processInfo,int64_t & time_stamp,bool & withKillMsg)720 bool AppExitReasonDataManager::GetUIExtensionAbilityExitReason(const std::string &keyEx,
721 AAFwk::ExitReason &exitReason, AppExecFwk::RunningProcessInfo &processInfo, int64_t &time_stamp,
722 bool &withKillMsg)
723 {
724 TAG_LOGD(AAFwkTag::ABILITYMGR, "called");
725 {
726 std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
727 if (!CheckKvStore()) {
728 TAG_LOGE(AAFwkTag::ABILITYMGR, "null kvStorePtr_");
729 return false;
730 }
731 }
732
733 std::vector<DistributedKv::Entry> allEntries;
734 DistributedKv::Status status = kvStorePtr_->GetEntries(nullptr, allEntries);
735 if (status != DistributedKv::Status::SUCCESS) {
736 TAG_LOGE(AAFwkTag::ABILITYMGR, "error: %{public}d", status);
737 return false;
738 }
739 std::vector<std::string> abilityList;
740 bool isHaveReason = false;
741 for (const auto &item : allEntries) {
742 if (item.key.ToString() == keyEx) {
743 ConvertAppExitReasonInfoFromValue(item.value, exitReason, time_stamp, abilityList,
744 processInfo, withKillMsg);
745 isHaveReason = true;
746 InnerDeleteAppExitReason(keyEx);
747 break;
748 }
749 }
750
751 return isHaveReason;
752 }
753
UpdateAbilityRecoverInfo(uint32_t accessTokenId,const std::vector<std::string> & recoverInfoList,const std::vector<int> & sessionIdList)754 void AppExitReasonDataManager::UpdateAbilityRecoverInfo(uint32_t accessTokenId,
755 const std::vector<std::string> &recoverInfoList, const std::vector<int> &sessionIdList)
756 {
757 if (kvStorePtr_ == nullptr) {
758 TAG_LOGE(AAFwkTag::ABILITYMGR, "null kvStorePtr_");
759 return;
760 }
761
762 DistributedKv::Key key = GetAbilityRecoverInfoKey(accessTokenId);
763 DistributedKv::Status status;
764 {
765 std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
766 status = kvStorePtr_->Delete(key);
767 }
768 if (status != DistributedKv::Status::SUCCESS) {
769 TAG_LOGE(AAFwkTag::ABILITYMGR, "error: %{public}d", status);
770 return;
771 }
772
773 DistributedKv::Value value = ConvertAbilityRecoverInfoToValue(recoverInfoList, sessionIdList);
774 {
775 std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
776 status = kvStorePtr_->Put(key, value);
777 }
778 if (status != DistributedKv::Status::SUCCESS) {
779 TAG_LOGE(AAFwkTag::ABILITYMGR, "failed: %{public}d", status);
780 }
781 }
782
ConvertAbilityRecoverInfoToValue(const std::vector<std::string> & recoverInfoList,const std::vector<int> & sessionIdList)783 DistributedKv::Value AppExitReasonDataManager::ConvertAbilityRecoverInfoToValue(
784 const std::vector<std::string> &recoverInfoList, const std::vector<int> &sessionIdList)
785 {
786 nlohmann::json jsonObject = nlohmann::json {
787 { JSON_KEY_RECOVER_INFO_LIST, recoverInfoList },
788 { JSON_KEY_SESSION_ID_LIST, sessionIdList },
789 };
790 DistributedKv::Value value(jsonObject.dump());
791 TAG_LOGI(AAFwkTag::ABILITYMGR, "ConvertAbilityRecoverInfoToValue value: %{public}s", value.ToString().c_str());
792 return value;
793 }
794
ConvertAbilityRecoverInfoFromValue(const DistributedKv::Value & value,std::vector<std::string> & recoverInfoList,std::vector<int> & sessionIdList)795 void AppExitReasonDataManager::ConvertAbilityRecoverInfoFromValue(const DistributedKv::Value &value,
796 std::vector<std::string> &recoverInfoList, std::vector<int> &sessionIdList)
797 {
798 nlohmann::json jsonObject = nlohmann::json::parse(value.ToString(), nullptr, false);
799 if (jsonObject.is_discarded()) {
800 TAG_LOGE(AAFwkTag::ABILITYMGR, "parse json sting failed");
801 return;
802 }
803 if (jsonObject.contains(JSON_KEY_RECOVER_INFO_LIST)
804 && jsonObject[JSON_KEY_RECOVER_INFO_LIST].is_array()) {
805 recoverInfoList.clear();
806 auto size = jsonObject[JSON_KEY_RECOVER_INFO_LIST].size();
807 for (size_t i = 0; i < size; i++) {
808 if (jsonObject[JSON_KEY_RECOVER_INFO_LIST][i].is_string()) {
809 recoverInfoList.emplace_back(jsonObject[JSON_KEY_RECOVER_INFO_LIST][i]);
810 }
811 }
812 }
813 if (jsonObject.contains(JSON_KEY_SESSION_ID_LIST)
814 && jsonObject[JSON_KEY_SESSION_ID_LIST].is_array()) {
815 sessionIdList.clear();
816 auto size = jsonObject[JSON_KEY_SESSION_ID_LIST].size();
817 for (size_t i = 0; i < size; i++) {
818 if (jsonObject[JSON_KEY_SESSION_ID_LIST][i].is_number_integer()) {
819 sessionIdList.emplace_back(jsonObject[JSON_KEY_SESSION_ID_LIST][i]);
820 }
821 }
822 }
823 }
824
ConvertAccessTokenIdFromValue(const DistributedKv::Value & value,uint32_t & accessTokenId)825 void AppExitReasonDataManager::ConvertAccessTokenIdFromValue(const DistributedKv::Value &value,
826 uint32_t &accessTokenId)
827 {
828 nlohmann::json jsonObject = nlohmann::json::parse(value.ToString(), nullptr, false);
829 if (jsonObject.is_discarded()) {
830 TAG_LOGE(AAFwkTag::ABILITYMGR, "parse json sting failed");
831 return;
832 }
833 if (jsonObject.contains(JSON_KEY_ACCESSTOKENId)) {
834 accessTokenId=jsonObject[JSON_KEY_ACCESSTOKENId];
835 }
836 }
837
InnerDeleteAbilityRecoverInfo(uint32_t accessTokenId)838 void AppExitReasonDataManager::InnerDeleteAbilityRecoverInfo(uint32_t accessTokenId)
839 {
840 if (kvStorePtr_ == nullptr) {
841 TAG_LOGE(AAFwkTag::ABILITYMGR, "null kvStorePtr_");
842 return;
843 }
844
845 DistributedKv::Key key = GetAbilityRecoverInfoKey(accessTokenId);
846 DistributedKv::Status status;
847 {
848 std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
849 status = kvStorePtr_->Delete(key);
850 }
851
852 if (status != DistributedKv::Status::SUCCESS) {
853 TAG_LOGE(AAFwkTag::ABILITYMGR, "error: %{public}d", status);
854 }
855 }
856
InnerAddSessionId(const int sessionId,uint32_t accessTokenId)857 void AppExitReasonDataManager::InnerAddSessionId(const int sessionId, uint32_t accessTokenId)
858 {
859 if (kvStorePtr_ == nullptr) {
860 TAG_LOGE(AAFwkTag::ABILITYMGR, "null kvStorePtr_");
861 return;
862 }
863
864 DistributedKv::Key key = GetSessionIdKey(sessionId);
865 DistributedKv::Value value = ConvertAccessTokenIdToValue(accessTokenId);
866 DistributedKv::Status status;
867 {
868 std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
869 status = kvStorePtr_->Put(key, value);
870 }
871 if (status != DistributedKv::Status::SUCCESS) {
872 TAG_LOGE(AAFwkTag::ABILITYMGR, "AddSessionId error : %{public}d", status);
873 return;
874 }
875 }
876
InnerDeleteSessionId(const int sessionId)877 void AppExitReasonDataManager::InnerDeleteSessionId(const int sessionId)
878 {
879 if (kvStorePtr_ == nullptr) {
880 TAG_LOGE(AAFwkTag::ABILITYMGR, "null kvStorePtr_");
881 return;
882 }
883
884 DistributedKv::Key key = GetSessionIdKey(sessionId);
885 DistributedKv::Status status;
886 {
887 std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
888 status = kvStorePtr_->Delete(key);
889 }
890
891 if (status != DistributedKv::Status::SUCCESS) {
892 TAG_LOGE(AAFwkTag::ABILITYMGR, "DeleteSessionId error: %{public}d", status);
893 }
894 }
895
GetAbilityRecoverInfoKey(uint32_t accessTokenId)896 DistributedKv::Key AppExitReasonDataManager::GetAbilityRecoverInfoKey(uint32_t accessTokenId)
897 {
898 return DistributedKv::Key(KEY_RECOVER_INFO_PREFIX + std::to_string(accessTokenId));
899 }
900
GetSessionIdKey(const int sessionId)901 DistributedKv::Key AppExitReasonDataManager::GetSessionIdKey(const int sessionId)
902 {
903 return DistributedKv::Key(KEY_RECOVER_INFO_PREFIX + std::to_string(sessionId));
904 }
905
ConvertAccessTokenIdToValue(uint32_t accessTokenId)906 DistributedKv::Value AppExitReasonDataManager::ConvertAccessTokenIdToValue(uint32_t accessTokenId)
907 {
908 nlohmann::json jsonObject = nlohmann::json {
909 { JSON_KEY_ACCESSTOKENId, accessTokenId },
910 };
911 DistributedKv::Value value(jsonObject.dump());
912 TAG_LOGI(AAFwkTag::ABILITYMGR, "ConvertAccessTokenIdToValue value: %{public}s", value.ToString().c_str());
913 return value;
914 }
915
ConvertAppExitReasonInfoToValueOfExtensionName(const std::string & extensionListName,const AAFwk::ExitReason & exitReason,const AppExecFwk::RunningProcessInfo & processInfo,bool withKillMsg)916 DistributedKv::Value AppExitReasonDataManager::ConvertAppExitReasonInfoToValueOfExtensionName(
917 const std::string &extensionListName, const AAFwk::ExitReason &exitReason,
918 const AppExecFwk::RunningProcessInfo &processInfo, bool withKillMsg)
919 {
920 TAG_LOGD(AAFwkTag::ABILITYMGR, "called");
921 std::chrono::milliseconds nowMs =
922 std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch());
923 std::string killMsg = "";
924 std::string exitMsg = exitReason.exitMsg;
925 if (withKillMsg) {
926 killMsg = exitReason.exitMsg;
927 }
928 nlohmann::json jsonObject = nlohmann::json {
929 { JSON_KEY_PID, processInfo.pid_ },
930 { JSON_KEY_UID, processInfo.uid_ },
931 { JSON_KEY_REASON, exitReason.reason },
932 { JSON_KEY_SUB_KILL_REASON, exitReason.subReason },
933 { JSON_KEY_EXIT_MSG, exitMsg },
934 { JSON_KEY_KILL_MSG, killMsg },
935 { JSON_KEY_RSS_VALUE, processInfo.rssValue },
936 { JSON_KEY_PSS_VALUE, processInfo.pssValue },
937 { JSON_KEY_PROCESS_NAME, processInfo.processName_ },
938 { JSON_KEY_TIME_STAMP, nowMs.count() },
939 { JSON_KEY_EXTENSION_NAME, extensionListName },
940 };
941
942 DistributedKv::Value value(jsonObject.dump());
943 TAG_LOGI(AAFwkTag::ABILITYMGR, "value: %{public}s", value.ToString().c_str());
944 return value;
945 }
946
RestoreKvStore(DistributedKv::Status status)947 DistributedKv::Status AppExitReasonDataManager::RestoreKvStore(DistributedKv::Status status)
948 {
949 if (status != DistributedKv::Status::DATA_CORRUPTED) {
950 return status;
951 }
952 DistributedKv::Options options = {
953 .createIfMissing = true,
954 .encrypt = false,
955 .autoSync = true,
956 .syncable = false,
957 .securityLevel = DistributedKv::SecurityLevel::S2,
958 .area = DistributedKv::EL1,
959 .kvStoreType = DistributedKv::KvStoreType::SINGLE_VERSION,
960 .baseDir = APP_EXIT_REASON_STORAGE_DIR,
961 };
962 TAG_LOGI(AAFwkTag::ABILITYMGR, "corrupted, deleting db");
963 dataManager_.DeleteKvStore(appId_, storeId_, options.baseDir);
964 TAG_LOGI(AAFwkTag::ABILITYMGR, "deleted corrupted db, recreating db");
965 status = dataManager_.GetSingleKvStore(options, appId_, storeId_, kvStorePtr_);
966 TAG_LOGI(AAFwkTag::ABILITYMGR, "recreate db result:%{public}d", status);
967
968 return status;
969 }
970
GetRecordAppAbilityNames(const uint32_t accessTokenId,std::vector<std::string> & abilityLists)971 int32_t AppExitReasonDataManager::GetRecordAppAbilityNames(const uint32_t accessTokenId,
972 std::vector<std::string> &abilityLists)
973 {
974 auto accessTokenIdStr = std::to_string(accessTokenId);
975 if (accessTokenId == Security::AccessToken::INVALID_TOKENID) {
976 TAG_LOGW(AAFwkTag::ABILITYMGR, "invalid value");
977 return AAFwk::ERR_INVALID_ACCESS_TOKEN;
978 }
979 {
980 std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
981 if (!CheckKvStore()) {
982 TAG_LOGE(AAFwkTag::ABILITYMGR, "null kvStore");
983 return AAFwk::ERR_GET_KV_STORE_HANDLE_FAILED;
984 }
985 }
986
987 std::vector<DistributedKv::Entry> allEntries;
988 DistributedKv::Status status = kvStorePtr_->GetEntries(nullptr, allEntries);
989 if (status != DistributedKv::Status::SUCCESS) {
990 TAG_LOGE(AAFwkTag::ABILITYMGR, "get entries error: %{public}d", status);
991 return AAFwk::ERR_GET_EXIT_INFO_FAILED;
992 }
993
994 AAFwk::ExitReason exitReason = {};
995 int64_t timeStamp = 0;
996 AppExecFwk::RunningProcessInfo processInfo = {};
997 bool withKillMsg = false;
998 for (const auto &item : allEntries) {
999 if (item.key.ToString() == accessTokenIdStr) {
1000 ConvertAppExitReasonInfoFromValue(item.value, exitReason, timeStamp, abilityLists, processInfo,
1001 withKillMsg);
1002 }
1003 }
1004
1005 return ERR_OK;
1006 }
1007 } // namespace AbilityRuntime
1008 } // namespace OHOS
1009