• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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