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