• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 int32_t ERMS_ISALLOW_RESULTCODE = 10;
32 constexpr int32_t ERMS_ISALLOW_EMBED_RESULTCODE = 1;
33 }
DoProcess(AbilityInterceptorParam param)34 ErrCode EcologicalRuleInterceptor::DoProcess(AbilityInterceptorParam param)
35 {
36     HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
37     if (StartAbilityUtils::skipErms) {
38         StartAbilityUtils::skipErms = false;
39         return ERR_OK;
40     }
41     if (param.want.GetStringParam(Want::PARAM_RESV_CALLER_BUNDLE_NAME) ==
42         param.want.GetElement().GetBundleName()) {
43         TAG_LOGD(AAFwkTag::ECOLOGICAL_RULE, "same bundle");
44         return ERR_OK;
45     }
46     ErmsCallerInfo callerInfo;
47     ExperienceRule rule;
48     AAFwk::Want newWant = param.want;
49     newWant.RemoveAllFd();
50     if (param.isStartAsCaller) {
51         callerInfo.isAsCaller = true;
52     }
53     InitErmsCallerInfo(newWant, param.abilityInfo, callerInfo, param.userId, param.callerToken);
54 
55     int ret = IN_PROCESS_CALL(AbilityEcologicalRuleMgrServiceClient::GetInstance()->QueryStartExperience(newWant,
56         callerInfo, rule));
57     if (ret != ERR_OK) {
58         TAG_LOGD(AAFwkTag::ECOLOGICAL_RULE, "check ecological rule failed");
59         return ERR_OK;
60     }
61     TAG_LOGD(AAFwkTag::ECOLOGICAL_RULE, "query erms suc, isBackSkuExempt: %{public}d.", rule.isBackSkuExempt);
62     StartAbilityUtils::ermsResultCode = rule.resultCode;
63     StartAbilityUtils::ermsSupportBackToCallerFlag = rule.isBackSkuExempt;
64     if (rule.resultCode == ERMS_ISALLOW_RESULTCODE) {
65         TAG_LOGD(AAFwkTag::ECOLOGICAL_RULE, "allow ecological rule");
66         return ERR_OK;
67     }
68 
69     std::string supportErms = OHOS::system::GetParameter(ABILITY_SUPPORT_ECOLOGICAL_RULEMGRSERVICE, "true");
70     if (supportErms == "false") {
71         TAG_LOGE(AAFwkTag::ECOLOGICAL_RULE, "not support erms");
72         return ERR_OK;
73     }
74 #ifdef SUPPORT_GRAPHICS
75     if (param.isWithUI && rule.replaceWant) {
76         (const_cast<Want &>(param.want)) = *rule.replaceWant;
77         (const_cast<Want &>(param.want)).SetParam("queryWantFromErms", true);
78     }
79 #endif
80     return ERR_ECOLOGICAL_CONTROL_STATUS;
81 }
82 
DoProcess(Want & want,int32_t userId)83 bool EcologicalRuleInterceptor::DoProcess(Want &want, int32_t userId)
84 {
85     HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
86     if (want.GetStringParam(Want::PARAM_RESV_CALLER_BUNDLE_NAME) == want.GetElement().GetBundleName()) {
87         TAG_LOGD(AAFwkTag::ECOLOGICAL_RULE, "same bundle");
88         return true;
89     }
90     std::string supportErms = OHOS::system::GetParameter(ABILITY_SUPPORT_ECOLOGICAL_RULEMGRSERVICE, "true");
91     if (supportErms == "false") {
92         TAG_LOGE(AAFwkTag::ECOLOGICAL_RULE, "not support erms");
93         return true;
94     }
95 
96     auto bundleMgrHelper = AbilityUtil::GetBundleManagerHelper();
97     CHECK_POINTER_AND_RETURN(bundleMgrHelper, false);
98     Want launchWant;
99     auto errCode = IN_PROCESS_CALL(bundleMgrHelper->GetLaunchWantForBundle(want.GetBundle(), launchWant, userId));
100     if (errCode != ERR_OK) {
101         TAG_LOGE(AAFwkTag::ECOLOGICAL_RULE, "GetLaunchWantForBundle err: %{public}d", errCode);
102         return false;
103     }
104     want.SetElement(launchWant.GetElement());
105 
106     int32_t appIndex = 0;
107     auto startAbilityInfo = StartAbilityInfo::CreateStartAbilityInfo(want,
108         userId, appIndex, nullptr);
109     if (startAbilityInfo == nullptr || startAbilityInfo->status != ERR_OK) {
110         TAG_LOGE(AAFwkTag::ECOLOGICAL_RULE, "Get targetApplicationInfo failed");
111         return false;
112     }
113 
114     ErmsCallerInfo callerInfo;
115     InitErmsCallerInfo(want, std::make_shared<AppExecFwk::AbilityInfo>(startAbilityInfo->abilityInfo),
116         callerInfo, userId);
117 
118     ExperienceRule rule;
119     auto ret = IN_PROCESS_CALL(AbilityEcologicalRuleMgrServiceClient::GetInstance()->QueryStartExperience(want,
120         callerInfo, rule));
121     if (ret != ERR_OK) {
122         TAG_LOGD(AAFwkTag::ECOLOGICAL_RULE, "check ecological rule failed");
123         return true;
124     }
125     return rule.resultCode == ERMS_ISALLOW_RESULTCODE;
126 }
127 
QueryAtomicServiceStartupRule(Want & want,sptr<IRemoteObject> callerToken,int32_t userId,AtomicServiceStartupRule & rule,sptr<Want> & replaceWant)128 ErrCode EcologicalRuleInterceptor::QueryAtomicServiceStartupRule(Want &want, sptr<IRemoteObject> callerToken,
129     int32_t userId, AtomicServiceStartupRule &rule, sptr<Want> &replaceWant)
130 {
131     HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
132     CHECK_TRUE_RETURN_RET(want.GetStringParam(Want::PARAM_RESV_CALLER_BUNDLE_NAME) == want.GetElement().GetBundleName(),
133         ERR_INVALID_CALLER, "same bundle");
134     std::string supportErms = OHOS::system::GetParameter(ABILITY_SUPPORT_ECOLOGICAL_RULEMGRSERVICE, "true");
135     CHECK_TRUE_RETURN_RET(supportErms == "false", ERR_CAPABILITY_NOT_SUPPORT, "not support erms");
136 
137     auto bundleMgrHelper = AbilityUtil::GetBundleManagerHelper();
138     CHECK_POINTER_AND_RETURN(bundleMgrHelper, BMS_NOT_CONNECTED);
139     Want launchWant;
140     auto errCode = IN_PROCESS_CALL(bundleMgrHelper->GetLaunchWantForBundle(want.GetBundle(), launchWant, userId));
141     CHECK_RET_RETURN_RET(errCode, "GetLaunchWantForBundle failed");
142     want.SetElement(launchWant.GetElement());
143 
144     int32_t appIndex = 0;
145     StartAbilityUtils::startAbilityInfo = StartAbilityInfo::CreateStartAbilityInfo(want, userId, appIndex, nullptr);
146     CHECK_POINTER_AND_RETURN_LOG(StartAbilityUtils::startAbilityInfo, INNER_ERR, "null startAbilityInfo");
147     CHECK_RET_RETURN_RET(StartAbilityUtils::startAbilityInfo->status, "Get targetApplicationInfo failed");
148 
149     ErmsCallerInfo callerInfo;
150     InitErmsCallerInfo(want, std::make_shared<AppExecFwk::AbilityInfo>(
151         StartAbilityUtils::startAbilityInfo->abilityInfo), callerInfo, userId);
152 
153     ExperienceRule _rule;
154     auto ret = IN_PROCESS_CALL(AbilityEcologicalRuleMgrServiceClient::GetInstance()->QueryStartExperience(want,
155         callerInfo, _rule));
156     CHECK_RET_RETURN_RET(ret, "check ecological rule failed");
157 
158     StartAbilityUtils::ermsResultCode = _rule.resultCode;
159     StartAbilityUtils::ermsSupportBackToCallerFlag = _rule.isBackSkuExempt;
160     rule.isOpenAllowed = _rule.resultCode == ERMS_ISALLOW_RESULTCODE;
161     rule.isEmbeddedAllowed = _rule.embedResultCode == ERMS_ISALLOW_EMBED_RESULTCODE;
162     TAG_LOGI(AAFwkTag::ECOLOGICAL_RULE, "query erms suc, open: %{public}d, hasWant: %{public}d.",
163         rule.isOpenAllowed, _rule.replaceWant != nullptr);
164     if (rule.isOpenAllowed) {
165         return ERR_OK;
166     }
167 
168 #ifdef SUPPORT_GRAPHICS
169     if (_rule.replaceWant != nullptr) {
170         replaceWant = _rule.replaceWant;
171         replaceWant->SetParam("queryWantFromErms", true);
172         return ERR_ECOLOGICAL_CONTROL_STATUS;
173     }
174 #endif
175     return ERR_OK;
176 }
177 
GetEcologicalTargetInfo(const Want & want,const std::shared_ptr<AppExecFwk::AbilityInfo> & abilityInfo,ErmsCallerInfo & callerInfo)178 void EcologicalRuleInterceptor::GetEcologicalTargetInfo(const Want &want,
179     const std::shared_ptr<AppExecFwk::AbilityInfo> &abilityInfo, ErmsCallerInfo &callerInfo)
180 {
181     HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
182     callerInfo.targetLinkFeature = want.GetStringParam("send_to_erms_targetLinkFeature");
183     callerInfo.targetLinkType = want.GetIntParam("send_to_erms_targetLinkType", 0);
184     if (StartAbilityUtils::startAbilityInfo &&
185         StartAbilityUtils::startAbilityInfo->abilityInfo.bundleName == want.GetBundle() &&
186         StartAbilityUtils::startAbilityInfo->abilityInfo.name == want.GetElement().GetAbilityName()) {
187         AppExecFwk::AbilityInfo targetAbilityInfo = StartAbilityUtils::startAbilityInfo->abilityInfo;
188         callerInfo.targetAppDistType = targetAbilityInfo.applicationInfo.appDistributionType;
189         callerInfo.targetAppProvisionType = targetAbilityInfo.applicationInfo.appProvisionType;
190         callerInfo.targetAppType = GetAppTypeByBundleType(static_cast<int32_t>(
191             targetAbilityInfo.applicationInfo.bundleType));
192         callerInfo.targetAbilityType = targetAbilityInfo.type;
193         callerInfo.targetExtensionAbilityType = targetAbilityInfo.extensionAbilityType;
194         callerInfo.targetApplicationReservedFlag = static_cast<int32_t>(
195             targetAbilityInfo.applicationInfo.applicationReservedFlag);
196     } else if (abilityInfo != nullptr) {
197         callerInfo.targetAppDistType = abilityInfo->applicationInfo.appDistributionType;
198         callerInfo.targetAppProvisionType = abilityInfo->applicationInfo.appProvisionType;
199         callerInfo.targetAppType = GetAppTypeByBundleType(static_cast<int32_t>(
200             abilityInfo->applicationInfo.bundleType));
201         callerInfo.targetAbilityType = abilityInfo->type;
202         callerInfo.targetExtensionAbilityType = abilityInfo->extensionAbilityType;
203         callerInfo.targetApplicationReservedFlag = static_cast<int32_t>(
204             abilityInfo->applicationInfo.applicationReservedFlag);
205     }
206 }
207 
GetEcologicalCallerInfo(const Want & want,ErmsCallerInfo & callerInfo,int32_t userId,const sptr<IRemoteObject> & callerToken)208 void EcologicalRuleInterceptor::GetEcologicalCallerInfo(const Want &want, ErmsCallerInfo &callerInfo, int32_t userId,
209     const sptr<IRemoteObject> &callerToken)
210 {
211     HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
212 
213     AppExecFwk::ApplicationInfo callerAppInfo;
214     AppExecFwk::AbilityInfo callerAbilityInfo;
215     if (StartAbilityUtils::GetCallerAbilityInfo(callerToken, callerAbilityInfo)) {
216         callerAppInfo = callerAbilityInfo.applicationInfo;
217         callerInfo.callerAbilityType = callerAbilityInfo.type;
218         callerInfo.callerExtensionAbilityType = callerAbilityInfo.extensionAbilityType;
219     } else {
220         auto bundleMgrHelper = AbilityUtil::GetBundleManagerHelper();
221         if (bundleMgrHelper == nullptr) {
222             TAG_LOGE(AAFwkTag::ECOLOGICAL_RULE, "null bundleMgrHelper");
223             return;
224         }
225 
226         std::string callerBundleName;
227         ErrCode err = IN_PROCESS_CALL(bundleMgrHelper->GetNameForUid(callerInfo.uid, callerBundleName));
228         if (err != ERR_OK) {
229             TAG_LOGE(AAFwkTag::ECOLOGICAL_RULE, "failed,uid: %{public}d", callerInfo.uid);
230             return;
231         }
232         bool getCallerResult = IN_PROCESS_CALL(bundleMgrHelper->GetApplicationInfo(callerBundleName,
233             AppExecFwk::ApplicationFlag::GET_BASIC_APPLICATION_INFO, userId, callerAppInfo));
234         if (!getCallerResult) {
235             TAG_LOGD(AAFwkTag::ECOLOGICAL_RULE, "Get callerAppInfo failed");
236             return;
237         }
238     }
239 
240     callerInfo.callerAppProvisionType = callerAppInfo.appProvisionType;
241     if (callerAppInfo.bundleType == AppExecFwk::BundleType::ATOMIC_SERVICE) {
242         TAG_LOGD(AAFwkTag::ECOLOGICAL_RULE, "atomic service caller type");
243         callerInfo.callerAppType = ErmsCallerInfo::TYPE_ATOM_SERVICE;
244     } else if (callerAppInfo.bundleType == AppExecFwk::BundleType::APP) {
245         TAG_LOGD(AAFwkTag::ECOLOGICAL_RULE, "app caller type");
246         callerInfo.callerAppType = ErmsCallerInfo::TYPE_HARMONY_APP;
247         if (callerInfo.packageName == "" && callerAppInfo.name == BUNDLE_NAME_SCENEBOARD) {
248             callerInfo.packageName = BUNDLE_NAME_SCENEBOARD;
249         }
250     } else if (callerAppInfo.bundleType == AppExecFwk::BundleType::APP_SERVICE_FWK) {
251         TAG_LOGD(AAFwkTag::ECOLOGICAL_RULE, "app service caller type");
252         callerInfo.callerAppType = ErmsCallerInfo::TYPE_APP_SERVICE;
253     }
254 }
255 
InitErmsCallerInfo(const Want & want,const std::shared_ptr<AppExecFwk::AbilityInfo> & abilityInfo,ErmsCallerInfo & callerInfo,int32_t userId,const sptr<IRemoteObject> & callerToken)256 void EcologicalRuleInterceptor::InitErmsCallerInfo(const Want &want,
257     const std::shared_ptr<AppExecFwk::AbilityInfo> &abilityInfo,
258     ErmsCallerInfo &callerInfo, int32_t userId, const sptr<IRemoteObject> &callerToken)
259 {
260     if (callerToken != nullptr) {
261         auto abilityRecord = Token::GetAbilityRecordByToken(callerToken);
262         if (abilityRecord && !abilityRecord->GetAbilityInfo().isStageBasedModel) {
263             TAG_LOGD(AAFwkTag::ECOLOGICAL_RULE, "FA callerModelType");
264             callerInfo.callerModelType = ErmsCallerInfo::MODEL_FA;
265         }
266     }
267     callerInfo.packageName = want.GetStringParam(Want::PARAM_RESV_CALLER_BUNDLE_NAME);
268     callerInfo.uid = want.GetIntParam(Want::PARAM_RESV_CALLER_UID, IPCSkeleton::GetCallingUid());
269     callerInfo.pid = want.GetIntParam(Want::PARAM_RESV_CALLER_PID, IPCSkeleton::GetCallingPid());
270     callerInfo.embedded = want.GetIntParam("send_to_erms_embedded", 0);
271     callerInfo.userId = userId;
272     if (want.GetElement().GetBundleName().empty() && abilityInfo != nullptr) {
273         callerInfo.targetBundleName = abilityInfo->bundleName;
274     }
275 
276     GetEcologicalTargetInfo(want, abilityInfo, callerInfo);
277     GetEcologicalCallerInfo(want, callerInfo, userId, callerToken);
278 
279     TAG_LOGI(AAFwkTag::ECOLOGICAL_RULE, "ERMS's caller{%{public}s_%{public}d_%{public}d}",
280         callerInfo.packageName.c_str(), callerInfo.uid, callerInfo.pid);
281 }
282 
GetAppTypeByBundleType(int32_t bundleType)283 int32_t EcologicalRuleInterceptor::GetAppTypeByBundleType(int32_t bundleType)
284 {
285     if (bundleType == static_cast<int32_t>(AppExecFwk::BundleType::ATOMIC_SERVICE)) {
286         return ErmsCallerInfo::TYPE_ATOM_SERVICE;
287     }
288     if (bundleType == static_cast<int32_t>(AppExecFwk::BundleType::APP)) {
289         return ErmsCallerInfo::TYPE_HARMONY_APP;
290     }
291     if (bundleType == static_cast<int32_t>(AppExecFwk::BundleType::APP_SERVICE_FWK)) {
292         return ErmsCallerInfo::TYPE_APP_SERVICE;
293     }
294     return ErmsCallerInfo::TYPE_INVALID;
295 }
296 } // namespace AAFwk
297 } // namespace OHOS
298