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