1 /*
2  * Copyright (c) 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_helper.h"
17 
18 #include "accesstoken_kit.h"
19 #include "app_exit_reason_data_manager.h"
20 #include "bundle_mgr_helper.h"
21 #include "os_account_manager_wrapper.h"
22 #include "scene_board_judgement.h"
23 
24 namespace OHOS {
25 namespace AAFwk {
26 namespace {
27     constexpr int32_t U0_USER_ID = 0;
28 }
29 
AppExitReasonHelper(std::shared_ptr<SubManagersHelper> subManagersHelper)30 AppExitReasonHelper::AppExitReasonHelper(std::shared_ptr<SubManagersHelper> subManagersHelper)
31     : subManagersHelper_(subManagersHelper) {}
32 
RecordAppExitReason(const ExitReason & exitReason)33 int32_t AppExitReasonHelper::RecordAppExitReason(const ExitReason &exitReason)
34 {
35     if (!IsExitReasonValid(exitReason)) {
36         TAG_LOGE(AAFwkTag::ABILITYMGR, "Exit reason invalid.");
37         return ERR_INVALID_VALUE;
38     }
39     auto uid = IPCSkeleton::GetCallingUid();
40     std::string bundleName;
41     int32_t appIndex = 0;
42     auto ret = IN_PROCESS_CALL(AbilityUtil::GetBundleManagerHelper()->GetNameAndIndexForUid(uid, bundleName,
43         appIndex));
44     if (ret != ERR_OK) {
45         TAG_LOGE(AAFwkTag::ABILITYMGR, "GetNameAndIndexForUid failed, ret:%{public}d", ret);
46         return ret;
47     }
48     // There is a possibility that the PID cannot be obtained when the CPP
49     // process exits. The exit cause is recorded by application.
50     int32_t pid = (exitReason.reason == Reason::REASON_CPP_CRASH) ? NO_PID : IPCSkeleton::GetCallingPid();
51     int32_t resultCode = RecordProcessExtensionExitReason(pid, bundleName, exitReason);
52     if (resultCode != ERR_OK) {
53         TAG_LOGE(AAFwkTag::ABILITYMGR, "Record Process Extension Exit Reason failed.code: %{public}d", resultCode);
54     }
55     CHECK_POINTER_AND_RETURN(subManagersHelper_, ERR_NULL_OBJECT);
56     std::vector<std::string> abilityList;
57     if (Rosen::SceneBoardJudgement::IsSceneBoardEnabled()) {
58         auto uiAbilityManager = subManagersHelper_->GetUIAbilityManagerByUid(uid);
59         CHECK_POINTER_AND_RETURN(uiAbilityManager, ERR_NULL_OBJECT);
60         uiAbilityManager->GetActiveAbilityList(uid, abilityList);
61     } else {
62         auto missionListManager = subManagersHelper_->GetMissionListManagerByUid(uid);
63         CHECK_POINTER_AND_RETURN(missionListManager, ERR_NULL_OBJECT);
64         missionListManager->GetActiveAbilityList(uid, abilityList);
65     }
66 
67     ret = DelayedSingleton<AppScheduler>::GetInstance()->NotifyAppMgrRecordExitReason(IPCSkeleton::GetCallingPid(),
68         exitReason.reason, exitReason.exitMsg);
69     if (ret != ERR_OK) {
70         TAG_LOGE(AAFwkTag::ABILITYMGR, "NotifyAppMgrRecordExitReason failed.code: %{public}d", ret);
71     }
72 
73     if (abilityList.empty()) {
74         TAG_LOGE(AAFwkTag::ABILITYMGR, "Active abilityLists empty.");
75         return ERR_GET_ACTIVE_ABILITY_LIST_EMPTY;
76     }
77     int32_t userId;
78     if (DelayedSingleton<AppExecFwk::OsAccountManagerWrapper>::GetInstance()->
79         GetOsAccountLocalIdFromUid(uid, userId) != ERR_OK) {
80         TAG_LOGE(AAFwkTag::ABILITYMGR, "Get GetOsAccountLocalIdFromUid failed.");
81         return ERR_INVALID_VALUE;
82     }
83     uint32_t accessTokenId = Security::AccessToken::AccessTokenKit::GetHapTokenID(userId, bundleName, appIndex);
84     return DelayedSingleton<AbilityRuntime::AppExitReasonDataManager>::GetInstance()->SetAppExitReason(bundleName,
85         accessTokenId, abilityList, exitReason);
86 }
87 
RecordProcessExitReason(const int32_t pid,const ExitReason & exitReason)88 int32_t AppExitReasonHelper::RecordProcessExitReason(const int32_t pid, const ExitReason &exitReason)
89 {
90     AppExecFwk::ApplicationInfo application;
91     bool debug = false;
92     auto ret = IN_PROCESS_CALL(DelayedSingleton<AppScheduler>::GetInstance()->GetApplicationInfoByProcessID(pid,
93         application, debug));
94     if (ret != ERR_OK) {
95         TAG_LOGE(AAFwkTag::ABILITYMGR, "GetApplicationInfoByProcessID failed.");
96         return ret;
97     }
98     auto bundleName = application.bundleName;
99     int32_t resultCode = RecordProcessExtensionExitReason(pid, bundleName, exitReason);
100     if (resultCode != ERR_OK) {
101         TAG_LOGE(AAFwkTag::ABILITYMGR, "Record Process Extension Exit Reason failed.code: %{public}d", resultCode);
102     }
103 
104     return RecordProcessExitReason(pid, bundleName, application.uid, application.accessTokenId, exitReason);
105 }
106 
RecordAppExitReason(const std::string & bundleName,int32_t uid,int32_t appIndex,const ExitReason & exitReason)107 int32_t AppExitReasonHelper::RecordAppExitReason(const std::string &bundleName, int32_t uid, int32_t appIndex,
108     const ExitReason &exitReason)
109 {
110     int32_t userId;
111     if (DelayedSingleton<AppExecFwk::OsAccountManagerWrapper>::GetInstance()->
112         GetOsAccountLocalIdFromUid(uid, userId) != ERR_OK) {
113         TAG_LOGE(AAFwkTag::ABILITYMGR, "Get GetOsAccountLocalIdFromUid failed.");
114         return ERR_INVALID_VALUE;
115     }
116     uint32_t accessTokenId = Security::AccessToken::AccessTokenKit::GetHapTokenID(userId, bundleName, appIndex);
117     return RecordProcessExitReason(NO_PID, bundleName, uid, accessTokenId, exitReason);
118 }
119 
RecordProcessExitReason(const int32_t pid,const std::string bundleName,const int32_t uid,const uint32_t accessTokenId,const ExitReason & exitReason)120 int32_t AppExitReasonHelper::RecordProcessExitReason(const int32_t pid, const std::string bundleName,
121     const int32_t uid, const uint32_t accessTokenId, const ExitReason &exitReason)
122 {
123     if (!IsExitReasonValid(exitReason)) {
124         TAG_LOGE(AAFwkTag::ABILITYMGR, "Force exit reason invalid.");
125         return ERR_INVALID_VALUE;
126     }
127 
128     int32_t targetUserId;
129     if (DelayedSingleton<AppExecFwk::OsAccountManagerWrapper>::GetInstance()->
130         GetOsAccountLocalIdFromUid(uid, targetUserId) != ERR_OK) {
131         TAG_LOGE(AAFwkTag::ABILITYMGR, "Get GetOsAccountLocalIdFromUid failed.");
132         return ERR_INVALID_VALUE;
133     }
134     std::vector<std::string> abilityLists;
135     if (Rosen::SceneBoardJudgement::IsSceneBoardEnabled()) {
136         GetActiveAbilityListFromUIAbilityManager(uid, abilityLists, pid);
137     } else  {
138         GetActiveAbilityList(uid, abilityLists, pid);
139     }
140 
141     auto ret = DelayedSingleton<AppScheduler>::GetInstance()->NotifyAppMgrRecordExitReason(pid, exitReason.reason,
142         exitReason.exitMsg);
143     if (ret != ERR_OK) {
144         TAG_LOGE(AAFwkTag::ABILITYMGR, "NotifyAppMgrRecordExitReason failed.code: %{public}d", ret);
145     }
146 
147     if (abilityLists.empty()) {
148         TAG_LOGE(AAFwkTag::ABILITYMGR, "Active abilityLists empty.");
149         return ERR_GET_ACTIVE_ABILITY_LIST_EMPTY;
150     }
151     return DelayedSingleton<AbilityRuntime::AppExitReasonDataManager>::GetInstance()->SetAppExitReason(bundleName,
152         accessTokenId, abilityLists, exitReason);
153 }
154 
RecordProcessExtensionExitReason(const int32_t pid,const std::string & bundleName,const ExitReason & exitReason)155 int32_t AppExitReasonHelper::RecordProcessExtensionExitReason(
156     const int32_t pid, const std::string &bundleName, const ExitReason &exitReason)
157 {
158     TAG_LOGD(AAFwkTag::ABILITYMGR, "called");
159     CHECK_POINTER_AND_RETURN(subManagersHelper_, ERR_NULL_OBJECT);
160     auto connectManager = subManagersHelper_->GetCurrentConnectManager();
161     CHECK_POINTER_AND_RETURN(connectManager, ERR_NULL_OBJECT);
162     std::vector<std::string> extensionList;
163     int32_t resultCode = ERR_OK;
164     if (pid <= NO_PID) {
165         resultCode = connectManager->GetActiveUIExtensionList(bundleName, extensionList);
166     } else {
167         resultCode = connectManager->GetActiveUIExtensionList(pid, extensionList);
168     }
169     if (resultCode != ERR_OK) {
170         TAG_LOGD(AAFwkTag::ABILITYMGR, "ResultCode: %{public}d", resultCode);
171         return ERR_GET_ACTIVE_EXTENSION_LIST_EMPTY;
172     }
173 
174     if (extensionList.empty()) {
175         TAG_LOGD(AAFwkTag::ABILITYMGR, "ExtensionList is empty.");
176         return ERR_GET_ACTIVE_EXTENSION_LIST_EMPTY;
177     }
178 
179     auto appExitReasonDataMgr = DelayedSingleton<AbilityRuntime::AppExitReasonDataManager>::GetInstance();
180     if (appExitReasonDataMgr == nullptr) {
181         TAG_LOGE(AAFwkTag::ABILITYMGR, "Get app exit reason data mgr instance is nullptr.");
182         return ERR_INVALID_VALUE;
183     }
184 
185     return appExitReasonDataMgr->SetUIExtensionAbilityExitReason(bundleName, extensionList, exitReason);
186 }
187 
GetActiveAbilityList(int32_t uid,std::vector<std::string> & abilityLists,const int32_t pid)188 void AppExitReasonHelper::GetActiveAbilityList(int32_t uid, std::vector<std::string> &abilityLists,
189     const int32_t pid)
190 {
191     int32_t targetUserId;
192     if (DelayedSingleton<AppExecFwk::OsAccountManagerWrapper>::GetInstance()->
193         GetOsAccountLocalIdFromUid(uid, targetUserId) != ERR_OK) {
194         TAG_LOGE(AAFwkTag::ABILITYMGR, "Get GetOsAccountLocalIdFromUid failed.");
195         return;
196     }
197     CHECK_POINTER(subManagersHelper_);
198     if (targetUserId == U0_USER_ID) {
199         auto missionListManagers = subManagersHelper_->GetMissionListManagers();
200         for (auto& item: missionListManagers) {
201             CHECK_POINTER_CONTINUE(item.second);
202             std::vector<std::string> abilityList;
203             item.second->GetActiveAbilityList(uid, abilityList, pid);
204             if (!abilityList.empty()) {
205                 abilityLists.insert(abilityLists.end(), abilityList.begin(), abilityList.end());
206             }
207         }
208         return;
209     }
210 
211     auto listManager = subManagersHelper_->GetMissionListManagerByUserId(targetUserId);
212     CHECK_POINTER(listManager);
213     listManager->GetActiveAbilityList(uid, abilityLists, pid);
214 }
215 
GetActiveAbilityListFromUIAbilityManager(int32_t uid,std::vector<std::string> & abilityLists,const int32_t pid)216 void AppExitReasonHelper::GetActiveAbilityListFromUIAbilityManager(int32_t uid, std::vector<std::string> &abilityLists,
217     const int32_t pid)
218 {
219     CHECK_POINTER(subManagersHelper_);
220     int32_t targetUserId;
221     if (DelayedSingleton<AppExecFwk::OsAccountManagerWrapper>::GetInstance()->
222         GetOsAccountLocalIdFromUid(uid, targetUserId) != ERR_OK) {
223         TAG_LOGE(AAFwkTag::ABILITYMGR, "Get GetOsAccountLocalIdFromUid failed.");
224         return;
225     }
226     if (targetUserId == U0_USER_ID) {
227         auto uiAbilityManagers = subManagersHelper_->GetUIAbilityManagers();
228         for (auto& item: uiAbilityManagers) {
229             CHECK_POINTER_CONTINUE(item.second);
230             std::vector<std::string> abilityList;
231             item.second->GetActiveAbilityList(uid, abilityList, pid);
232             if (!abilityList.empty()) {
233                 abilityLists.insert(abilityLists.end(), abilityList.begin(), abilityList.end());
234             }
235         }
236         return;
237     }
238 
239     auto uiAbilityManager = subManagersHelper_->GetUIAbilityManagerByUserId(targetUserId);
240     CHECK_POINTER(uiAbilityManager);
241     uiAbilityManager->GetActiveAbilityList(uid, abilityLists, pid);
242 }
243 
IsExitReasonValid(const ExitReason & exitReason)244 bool AppExitReasonHelper::IsExitReasonValid(const ExitReason &exitReason)
245 {
246     const Reason reason = exitReason.reason;
247     return reason >= REASON_MIN && reason <= REASON_MAX;
248 }
249 }  // namespace AppExecFwk
250 }  // namespace OHOS
251