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 "interceptor/ecological_rule_interceptor.h"
17
18 #include "ability_record.h"
19 #include "ability_util.h"
20 #include "ecological_rule/ability_ecological_rule_mgr_service.h"
21 #include "hitrace_meter.h"
22 #include "parameters.h"
23 #include "start_ability_utils.h"
24
25 namespace OHOS {
26 namespace AAFwk {
27 namespace {
28 constexpr const char* ABILITY_SUPPORT_ECOLOGICAL_RULEMGRSERVICE =
29 "persist.sys.abilityms.support.ecologicalrulemgrservice";
30 constexpr const char* BUNDLE_NAME_SCENEBOARD = "com.ohos.sceneboard";
31 constexpr const char* START_ABILITY_AS_CALLER_SKIP_ERMS = "ability.params.skipErms";
32 constexpr int32_t ERMS_ISALLOW_RESULTCODE = 10;
33 }
DoProcess(AbilityInterceptorParam param)34 ErrCode EcologicalRuleInterceptor::DoProcess(AbilityInterceptorParam param)
35 {
36 HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
37 if (param.isStartAsCaller && param.want.GetBoolParam(START_ABILITY_AS_CALLER_SKIP_ERMS, false)) {
38 TAG_LOGD(AAFwkTag::ECOLOGICAL_RULE, "start as caller, skip erms");
39 return ERR_OK;
40 }
41 if (StartAbilityUtils::skipErms) {
42 StartAbilityUtils::skipErms = false;
43 return ERR_OK;
44 }
45 if (param.want.GetStringParam(Want::PARAM_RESV_CALLER_BUNDLE_NAME) ==
46 param.want.GetElement().GetBundleName()) {
47 TAG_LOGD(AAFwkTag::ECOLOGICAL_RULE, "same bundle");
48 return ERR_OK;
49 }
50 ErmsCallerInfo callerInfo;
51 ExperienceRule rule;
52 AAFwk::Want newWant = param.want;
53 newWant.RemoveAllFd();
54 InitErmsCallerInfo(newWant, param.abilityInfo, callerInfo, param.userId, param.callerToken);
55
56 int ret = IN_PROCESS_CALL(AbilityEcologicalRuleMgrServiceClient::GetInstance()->QueryStartExperience(newWant,
57 callerInfo, rule));
58 TAG_LOGD(AAFwkTag::ECOLOGICAL_RULE, "isBackSkuExempt: %{public}d.", rule.isBackSkuExempt);
59 if (ret != ERR_OK) {
60 TAG_LOGD(AAFwkTag::ECOLOGICAL_RULE, "check ecological rule failed");
61 return ERR_OK;
62 }
63 TAG_LOGD(AAFwkTag::ECOLOGICAL_RULE, "check ecological rule success");
64 StartAbilityUtils::ermsResultCode = rule.resultCode;
65 StartAbilityUtils::ermsSupportBackToCallerFlag = rule.isBackSkuExempt;
66 if (rule.resultCode == ERMS_ISALLOW_RESULTCODE) {
67 TAG_LOGD(AAFwkTag::ECOLOGICAL_RULE, "allow ecological rule");
68 return ERR_OK;
69 }
70
71 std::string supportErms = OHOS::system::GetParameter(ABILITY_SUPPORT_ECOLOGICAL_RULEMGRSERVICE, "true");
72 if (supportErms == "false") {
73 TAG_LOGE(AAFwkTag::ECOLOGICAL_RULE, "erms between apps not supported");
74 return ERR_OK;
75 }
76 #ifdef SUPPORT_GRAPHICS
77 if (param.isWithUI && rule.replaceWant) {
78 (const_cast<Want &>(param.want)) = *rule.replaceWant;
79 (const_cast<Want &>(param.want)).SetParam("queryWantFromErms", true);
80 }
81 #endif
82 return ERR_ECOLOGICAL_CONTROL_STATUS;
83 }
84
DoProcess(Want & want,int32_t userId)85 bool EcologicalRuleInterceptor::DoProcess(Want &want, int32_t userId)
86 {
87 HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
88 if (want.GetStringParam(Want::PARAM_RESV_CALLER_BUNDLE_NAME) == want.GetElement().GetBundleName()) {
89 TAG_LOGD(AAFwkTag::ECOLOGICAL_RULE, "same bundle");
90 return true;
91 }
92 std::string supportErms = OHOS::system::GetParameter(ABILITY_SUPPORT_ECOLOGICAL_RULEMGRSERVICE, "true");
93 if (supportErms == "false") {
94 TAG_LOGE(AAFwkTag::ECOLOGICAL_RULE, "Erms between apps not supported");
95 return true;
96 }
97
98 auto bundleMgrHelper = AbilityUtil::GetBundleManagerHelper();
99 CHECK_POINTER_AND_RETURN(bundleMgrHelper, false);
100 Want launchWant;
101 auto errCode = IN_PROCESS_CALL(bundleMgrHelper->GetLaunchWantForBundle(want.GetBundle(), launchWant, userId));
102 if (errCode != ERR_OK) {
103 TAG_LOGE(AAFwkTag::ECOLOGICAL_RULE, "GetLaunchWantForBundle err: %{public}d", errCode);
104 return false;
105 }
106 want.SetElement(launchWant.GetElement());
107
108 int32_t appIndex = 0;
109 auto startAbilityInfo = StartAbilityInfo::CreateStartAbilityInfo(want,
110 userId, appIndex);
111 if (startAbilityInfo == nullptr || startAbilityInfo->status != ERR_OK) {
112 TAG_LOGE(AAFwkTag::ECOLOGICAL_RULE, "Get targetApplicationInfo failed");
113 return false;
114 }
115
116 ErmsCallerInfo callerInfo;
117 InitErmsCallerInfo(want, std::make_shared<AppExecFwk::AbilityInfo>(startAbilityInfo->abilityInfo),
118 callerInfo, userId);
119
120 ExperienceRule rule;
121 auto ret = IN_PROCESS_CALL(AbilityEcologicalRuleMgrServiceClient::GetInstance()->QueryStartExperience(want,
122 callerInfo, rule));
123 if (ret != ERR_OK) {
124 TAG_LOGD(AAFwkTag::ECOLOGICAL_RULE, "check ecological rule failed");
125 return true;
126 }
127 return rule.resultCode == ERMS_ISALLOW_RESULTCODE;
128 }
129
GetEcologicalTargetInfo(const Want & want,const std::shared_ptr<AppExecFwk::AbilityInfo> & abilityInfo,ErmsCallerInfo & callerInfo)130 void EcologicalRuleInterceptor::GetEcologicalTargetInfo(const Want &want,
131 const std::shared_ptr<AppExecFwk::AbilityInfo> &abilityInfo, ErmsCallerInfo &callerInfo)
132 {
133 HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
134 callerInfo.targetLinkFeature = want.GetStringParam("send_to_erms_targetLinkFeature");
135 callerInfo.targetLinkType = want.GetIntParam("send_to_erms_targetLinkType", 0);
136 if (StartAbilityUtils::startAbilityInfo &&
137 StartAbilityUtils::startAbilityInfo->abilityInfo.bundleName == want.GetBundle() &&
138 StartAbilityUtils::startAbilityInfo->abilityInfo.name == want.GetElement().GetAbilityName()) {
139 AppExecFwk::AbilityInfo targetAbilityInfo = StartAbilityUtils::startAbilityInfo->abilityInfo;
140 callerInfo.targetAppDistType = targetAbilityInfo.applicationInfo.appDistributionType;
141 callerInfo.targetAppProvisionType = targetAbilityInfo.applicationInfo.appProvisionType;
142 callerInfo.targetAppType = GetAppTypeByBundleType(static_cast<int32_t>(
143 targetAbilityInfo.applicationInfo.bundleType));
144 callerInfo.targetAbilityType = targetAbilityInfo.type;
145 callerInfo.targetExtensionAbilityType = targetAbilityInfo.extensionAbilityType;
146 } else if (abilityInfo != nullptr) {
147 callerInfo.targetAppDistType = abilityInfo->applicationInfo.appDistributionType;
148 callerInfo.targetAppProvisionType = abilityInfo->applicationInfo.appProvisionType;
149 callerInfo.targetAppType = GetAppTypeByBundleType(static_cast<int32_t>(
150 abilityInfo->applicationInfo.bundleType));
151 callerInfo.targetAbilityType = abilityInfo->type;
152 callerInfo.targetExtensionAbilityType = abilityInfo->extensionAbilityType;
153 }
154 }
155
GetEcologicalCallerInfo(const Want & want,ErmsCallerInfo & callerInfo,int32_t userId,const sptr<IRemoteObject> & callerToken)156 void EcologicalRuleInterceptor::GetEcologicalCallerInfo(const Want &want, ErmsCallerInfo &callerInfo, int32_t userId,
157 const sptr<IRemoteObject> &callerToken)
158 {
159 HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
160
161 AppExecFwk::ApplicationInfo callerAppInfo;
162 AppExecFwk::AbilityInfo callerAbilityInfo;
163 if (StartAbilityUtils::GetCallerAbilityInfo(callerToken, callerAbilityInfo)) {
164 callerAppInfo = callerAbilityInfo.applicationInfo;
165 callerInfo.callerAbilityType = callerAbilityInfo.type;
166 callerInfo.callerExtensionAbilityType = callerAbilityInfo.extensionAbilityType;
167 } else {
168 auto bundleMgrHelper = AbilityUtil::GetBundleManagerHelper();
169 if (bundleMgrHelper == nullptr) {
170 TAG_LOGE(AAFwkTag::ECOLOGICAL_RULE, "null bundleMgrHelper");
171 return;
172 }
173
174 std::string callerBundleName;
175 ErrCode err = IN_PROCESS_CALL(bundleMgrHelper->GetNameForUid(callerInfo.uid, callerBundleName));
176 if (err != ERR_OK) {
177 TAG_LOGE(AAFwkTag::ECOLOGICAL_RULE, "Get callerBundleName failed,uid: %{public}d", callerInfo.uid);
178 return;
179 }
180 bool getCallerResult = IN_PROCESS_CALL(bundleMgrHelper->GetApplicationInfo(callerBundleName,
181 AppExecFwk::ApplicationFlag::GET_BASIC_APPLICATION_INFO, userId, callerAppInfo));
182 if (!getCallerResult) {
183 TAG_LOGD(AAFwkTag::ECOLOGICAL_RULE, "Get callerAppInfo failed");
184 return;
185 }
186 }
187
188 callerInfo.callerAppProvisionType = callerAppInfo.appProvisionType;
189 if (callerAppInfo.bundleType == AppExecFwk::BundleType::ATOMIC_SERVICE) {
190 TAG_LOGD(AAFwkTag::ECOLOGICAL_RULE, "atomic service caller type");
191 callerInfo.callerAppType = ErmsCallerInfo::TYPE_ATOM_SERVICE;
192 } else if (callerAppInfo.bundleType == AppExecFwk::BundleType::APP) {
193 TAG_LOGD(AAFwkTag::ECOLOGICAL_RULE, "app caller type");
194 callerInfo.callerAppType = ErmsCallerInfo::TYPE_HARMONY_APP;
195 if (callerInfo.packageName == "" && callerAppInfo.name == BUNDLE_NAME_SCENEBOARD) {
196 callerInfo.packageName = BUNDLE_NAME_SCENEBOARD;
197 }
198 } else if (callerAppInfo.bundleType == AppExecFwk::BundleType::APP_SERVICE_FWK) {
199 TAG_LOGD(AAFwkTag::ECOLOGICAL_RULE, "app service caller type");
200 callerInfo.callerAppType = ErmsCallerInfo::TYPE_APP_SERVICE;
201 }
202 }
203
InitErmsCallerInfo(const Want & want,const std::shared_ptr<AppExecFwk::AbilityInfo> & abilityInfo,ErmsCallerInfo & callerInfo,int32_t userId,const sptr<IRemoteObject> & callerToken)204 void EcologicalRuleInterceptor::InitErmsCallerInfo(const Want &want,
205 const std::shared_ptr<AppExecFwk::AbilityInfo> &abilityInfo,
206 ErmsCallerInfo &callerInfo, int32_t userId, const sptr<IRemoteObject> &callerToken)
207 {
208 if (callerToken != nullptr) {
209 auto abilityRecord = Token::GetAbilityRecordByToken(callerToken);
210 if (abilityRecord && !abilityRecord->GetAbilityInfo().isStageBasedModel) {
211 TAG_LOGD(AAFwkTag::ECOLOGICAL_RULE, "FA callerModelType");
212 callerInfo.callerModelType = ErmsCallerInfo::MODEL_FA;
213 }
214 }
215 callerInfo.packageName = want.GetStringParam(Want::PARAM_RESV_CALLER_BUNDLE_NAME);
216 callerInfo.uid = want.GetIntParam(Want::PARAM_RESV_CALLER_UID, IPCSkeleton::GetCallingUid());
217 callerInfo.pid = want.GetIntParam(Want::PARAM_RESV_CALLER_PID, IPCSkeleton::GetCallingPid());
218 callerInfo.embedded = want.GetIntParam("send_to_erms_embedded", 0);
219 callerInfo.userId = userId;
220
221 GetEcologicalTargetInfo(want, abilityInfo, callerInfo);
222 GetEcologicalCallerInfo(want, callerInfo, userId, callerToken);
223 TAG_LOGI(AAFwkTag::ECOLOGICAL_RULE, "ERMS's %{public}s", callerInfo.ToString().c_str());
224 }
225
GetAppTypeByBundleType(int32_t bundleType)226 int32_t EcologicalRuleInterceptor::GetAppTypeByBundleType(int32_t bundleType)
227 {
228 if (bundleType == static_cast<int32_t>(AppExecFwk::BundleType::ATOMIC_SERVICE)) {
229 return ErmsCallerInfo::TYPE_ATOM_SERVICE;
230 }
231 if (bundleType == static_cast<int32_t>(AppExecFwk::BundleType::APP)) {
232 return ErmsCallerInfo::TYPE_HARMONY_APP;
233 }
234 if (bundleType == static_cast<int32_t>(AppExecFwk::BundleType::APP_SERVICE_FWK)) {
235 return ErmsCallerInfo::TYPE_APP_SERVICE;
236 }
237 return ErmsCallerInfo::TYPE_INVALID;
238 }
239 } // namespace AAFwk
240 } // namespace OHOS