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/disposed_rule_interceptor.h"
17
18 #include "ability_record.h"
19 #include "global_constant.h"
20 #include "hitrace_meter.h"
21 #include "iservice_registry.h"
22 #include "modal_system_ui_extension.h"
23
24 namespace OHOS {
25 namespace AAFwk {
26 namespace {
27 constexpr const char* UNREGISTER_EVENT_TASK = "unregister event task";
28 constexpr const char* UNREGISTER_TIMEOUT_OBSERVER_TASK = "unregister timeout observer task";
29 constexpr int UNREGISTER_OBSERVER_MICRO_SECONDS = 5000;
30 constexpr const char* UIEXTENSION_MODAL_TYPE = "ability.want.params.modalType";
31 constexpr const char* INTERCEPT_PARAMETERS = "intercept_parammeters";
32 constexpr const char* INTERCEPT_BUNDLE_NAME = "intercept_bundleName";
33 constexpr const char* INTERCEPT_ABILITY_NAME = "intercept_abilityName";
34 constexpr const char* INTERCEPT_MODULE_NAME = "intercept_moduleName";
35 constexpr const char* IS_FROM_PARENTCONTROL = "ohos.ability.isFromParentControl";
36 }
37
DoProcess(AbilityInterceptorParam param)38 ErrCode DisposedRuleInterceptor::DoProcess(AbilityInterceptorParam param)
39 {
40 TAG_LOGD(AAFwkTag::ABILITYMGR, "Call");
41 AppExecFwk::DisposedRule disposedRule;
42 if (CheckControl(param.want, param.userId, disposedRule, param.appIndex)) {
43 TAG_LOGI(AAFwkTag::ABILITYMGR,
44 "The target ability is intercpted, disposedType is %{public}d, controlType is %{public}d, "
45 "componentType is %{public}d.", disposedRule.disposedType, disposedRule.controlType,
46 disposedRule.componentType);
47 #ifdef SUPPORT_GRAPHICS
48 if (!param.isWithUI || disposedRule.want == nullptr
49 || disposedRule.disposedType == AppExecFwk::DisposedType::NON_BLOCK) {
50 TAG_LOGE(AAFwkTag::ABILITYMGR, "Can not start disposed want");
51 return AbilityUtil::EdmErrorType(disposedRule.isEdm);
52 }
53 if (disposedRule.want->GetBundle() == param.want.GetBundle()) {
54 TAG_LOGE(AAFwkTag::ABILITYMGR, "Can not start disposed want with same bundleName");
55 return AbilityUtil::EdmErrorType(disposedRule.isEdm);
56 }
57 SetInterceptInfo(param.want, disposedRule);
58 if (disposedRule.componentType == AppExecFwk::ComponentType::UI_ABILITY) {
59 int ret = IN_PROCESS_CALL(AbilityManagerClient::GetInstance()->StartAbility(*disposedRule.want,
60 param.requestCode, param.userId));
61 if (ret != ERR_OK) {
62 TAG_LOGE(AAFwkTag::ABILITYMGR, "DisposedRuleInterceptor start ability failed.");
63 return ret;
64 }
65 }
66 if (disposedRule.componentType == AppExecFwk::ComponentType::UI_EXTENSION) {
67 int ret = CreateModalUIExtension(*disposedRule.want, param.callerToken);
68 if (ret != ERR_OK) {
69 TAG_LOGE(AAFwkTag::ABILITYMGR, "failed to start disposed UIExtension");
70 return ret;
71 }
72 }
73 #endif
74 return AbilityUtil::EdmErrorType(disposedRule.isEdm);
75 }
76 if (disposedRule.disposedType != AppExecFwk::DisposedType::NON_BLOCK) {
77 return ERR_OK;
78 }
79 return StartNonBlockRule(param.want, disposedRule);
80 }
81
CheckControl(const Want & want,int32_t userId,AppExecFwk::DisposedRule & disposedRule,int32_t appIndex)82 bool DisposedRuleInterceptor::CheckControl(const Want &want, int32_t userId,
83 AppExecFwk::DisposedRule &disposedRule, int32_t appIndex)
84 {
85 HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
86 // get bms
87 auto bundleMgrHelper = AbilityUtil::GetBundleManagerHelper();
88 if (bundleMgrHelper == nullptr) {
89 TAG_LOGE(AAFwkTag::ABILITYMGR, "The bundleMgrHelper is nullptr.");
90 return false;
91 }
92
93 // get disposed status
94 std::string bundleName = want.GetBundle();
95 auto appControlMgr = bundleMgrHelper->GetAppControlProxy();
96 if (appControlMgr == nullptr) {
97 TAG_LOGE(AAFwkTag::ABILITYMGR, "The appControlMgr is nullptr.");
98 return false;
99 }
100 std::vector<AppExecFwk::DisposedRule> disposedRuleList;
101 {
102 HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, "GetAbilityRunningControlRule");
103 int32_t ret = ERR_OK;
104 if (appIndex > 0 && appIndex <= AbilityRuntime::GlobalConstant::MAX_APP_CLONE_INDEX) {
105 ret = IN_PROCESS_CALL(appControlMgr->GetAbilityRunningControlRule(bundleName,
106 userId, disposedRuleList, appIndex));
107 } else {
108 ret = IN_PROCESS_CALL(appControlMgr->GetAbilityRunningControlRule(bundleName,
109 userId, disposedRuleList, 0));
110 }
111 if (ret != ERR_OK || disposedRuleList.empty()) {
112 TAG_LOGD(AAFwkTag::ABILITYMGR, "Get No DisposedRule");
113 return false;
114 }
115 }
116
117 for (auto &rule:disposedRuleList) {
118 if (CheckDisposedRule(want, rule)) {
119 disposedRule = rule;
120 return true;
121 }
122 }
123 int priority = -1;
124 for (auto &rule : disposedRuleList) {
125 if (rule.disposedType != AppExecFwk::DisposedType::NON_BLOCK) {
126 return false;
127 }
128 if (rule.priority > priority) {
129 priority = rule.priority;
130 disposedRule = rule;
131 }
132 }
133 return false;
134 }
135
CheckDisposedRule(const Want & want,AppExecFwk::DisposedRule & disposedRule)136 bool DisposedRuleInterceptor::CheckDisposedRule(const Want &want, AppExecFwk::DisposedRule &disposedRule)
137 {
138 if (disposedRule.disposedType == AppExecFwk::DisposedType::NON_BLOCK) {
139 return false;
140 }
141 bool isAllowed = disposedRule.controlType == AppExecFwk::ControlType::ALLOWED_LIST;
142 if (disposedRule.disposedType == AppExecFwk::DisposedType::BLOCK_APPLICATION) {
143 return !isAllowed;
144 }
145
146 std::string moduleName = want.GetElement().GetModuleName();
147 std::string abilityName = want.GetElement().GetAbilityName();
148
149 for (auto elementName : disposedRule.elementList) {
150 if (moduleName == elementName.GetModuleName()
151 && abilityName == elementName.GetAbilityName()) {
152 return !isAllowed;
153 }
154 }
155 return isAllowed;
156 }
157
StartNonBlockRule(const Want & want,AppExecFwk::DisposedRule & disposedRule)158 ErrCode DisposedRuleInterceptor::StartNonBlockRule(const Want &want, AppExecFwk::DisposedRule &disposedRule)
159 {
160 HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
161 TAG_LOGI(AAFwkTag::ABILITYMGR, "not block");
162 if (disposedRule.want == nullptr) {
163 TAG_LOGE(AAFwkTag::ABILITYMGR, "Can not start disposed app, want is nullptr");
164 return ERR_OK;
165 }
166 if (disposedRule.want->GetBundle() == want.GetBundle()) {
167 TAG_LOGE(AAFwkTag::ABILITYMGR, "Can not start disposed app with same bundleName");
168 return ERR_OK;
169 }
170 SetInterceptInfo(want, disposedRule);
171 std::string bundleName = want.GetBundle();
172 {
173 std::lock_guard<ffrt::mutex> guard(observerLock_);
174 if (disposedObserverMap_.find(bundleName) != disposedObserverMap_.end()) {
175 TAG_LOGD(AAFwkTag::ABILITYMGR, "start same disposed app, do not need to register again");
176 return ERR_OK;
177 }
178 }
179 auto disposedObserver = sptr<DisposedObserver>::MakeSptr(disposedRule, shared_from_this());
180 CHECK_POINTER_AND_RETURN(disposedObserver, ERR_INVALID_VALUE);
181 sptr<OHOS::AppExecFwk::IAppMgr> appManager = GetAppMgr();
182 CHECK_POINTER_AND_RETURN(appManager, ERR_INVALID_VALUE);
183 std::vector<std::string> bundleNameList;
184 bundleNameList.push_back(bundleName);
185 int32_t ret = IN_PROCESS_CALL(appManager->RegisterApplicationStateObserver(disposedObserver, bundleNameList));
186 if (ret != 0) {
187 TAG_LOGE(AAFwkTag::ABILITYMGR, "register to appmanager failed. err:%{public}d", ret);
188 disposedObserver = nullptr;
189 return ret;
190 }
191 {
192 std::lock_guard<ffrt::mutex> guard(observerLock_);
193 disposedObserverMap_.emplace(bundleName, disposedObserver);
194 }
195 auto unregisterTask = [appManager, bundleName, interceptor = shared_from_this()] () {
196 std::lock_guard<ffrt::mutex> guard{interceptor->observerLock_};
197 auto iter = interceptor->disposedObserverMap_.find(bundleName);
198 if (iter != interceptor->disposedObserverMap_.end()) {
199 TAG_LOGE(AAFwkTag::ABILITYMGR, "start disposed app time out, need to unregister observer");
200 IN_PROCESS_CALL(appManager->UnregisterApplicationStateObserver(iter->second));
201 interceptor->disposedObserverMap_.erase(iter);
202 }
203 };
204 taskHandler_->SubmitTask(unregisterTask, UNREGISTER_TIMEOUT_OBSERVER_TASK, UNREGISTER_OBSERVER_MICRO_SECONDS);
205 return ERR_OK;
206 }
207
GetAppMgr()208 sptr<OHOS::AppExecFwk::IAppMgr> DisposedRuleInterceptor::GetAppMgr()
209 {
210 OHOS::sptr<OHOS::ISystemAbilityManager> systemAbilityManager =
211 OHOS::SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
212 if (!systemAbilityManager) {
213 TAG_LOGE(AAFwkTag::ABILITYMGR, "get systemAbilityManager failed");
214 return nullptr;
215 }
216 OHOS::sptr<OHOS::IRemoteObject> object = systemAbilityManager->GetSystemAbility(OHOS::APP_MGR_SERVICE_ID);
217 if (!object) {
218 TAG_LOGE(AAFwkTag::ABILITYMGR, "get systemAbilityManager failed");
219 return nullptr;
220 }
221 sptr<OHOS::AppExecFwk::IAppMgr> appMgr = iface_cast<AppExecFwk::IAppMgr>(object);
222 if (!appMgr || !appMgr->AsObject()) {
223 return nullptr;
224 }
225 return appMgr;
226 }
227
UnregisterObserver(const std::string & bundleName)228 void DisposedRuleInterceptor::UnregisterObserver(const std::string &bundleName)
229 {
230 TAG_LOGD(AAFwkTag::ABILITYMGR, "Call");
231 taskHandler_->CancelTask(UNREGISTER_TIMEOUT_OBSERVER_TASK);
232 auto unregisterTask = [bundleName, interceptor = shared_from_this()] () {
233 std::lock_guard<ffrt::mutex> guard{interceptor->observerLock_};
234 auto iter = interceptor->disposedObserverMap_.find(bundleName);
235 if (iter == interceptor->disposedObserverMap_.end()) {
236 TAG_LOGE(AAFwkTag::ABILITYMGR, "Can not find observer");
237 } else {
238 auto disposedObserver = iter->second;
239 CHECK_POINTER(disposedObserver);
240 sptr<OHOS::AppExecFwk::IAppMgr> appManager = interceptor->GetAppMgr();
241 CHECK_POINTER(appManager);
242 IN_PROCESS_CALL(appManager->UnregisterApplicationStateObserver(disposedObserver));
243 interceptor->disposedObserverMap_.erase(iter);
244 }
245 };
246 taskHandler_->SubmitTask(unregisterTask, UNREGISTER_EVENT_TASK);
247 }
248
CreateModalUIExtension(const Want & want,const sptr<IRemoteObject> & callerToken)249 ErrCode DisposedRuleInterceptor::CreateModalUIExtension(const Want &want, const sptr<IRemoteObject> &callerToken)
250 {
251 HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
252 auto abilityRecord = Token::GetAbilityRecordByToken(callerToken);
253 if (abilityRecord == nullptr || abilityRecord->GetAbilityInfo().type != AppExecFwk::AbilityType::PAGE) {
254 auto systemUIExtension = std::make_shared<OHOS::Rosen::ModalSystemUiExtension>();
255 (const_cast<Want &>(want)).SetParam(UIEXTENSION_MODAL_TYPE, 1);
256 return IN_PROCESS_CALL(systemUIExtension->CreateModalUIExtension(want)) ? ERR_OK : INNER_ERR;
257 } else {
258 return abilityRecord->CreateModalUIExtension(want);
259 }
260 }
261
SetInterceptInfo(const Want & want,AppExecFwk::DisposedRule & disposedRule)262 void DisposedRuleInterceptor::SetInterceptInfo(const Want &want, AppExecFwk::DisposedRule &disposedRule)
263 {
264 if (disposedRule.want == nullptr) {
265 TAG_LOGW(AAFwkTag::ABILITYMGR, "disposedWant is nullptr");
266 return;
267 }
268 if (disposedRule.want->GetBoolParam(IS_FROM_PARENTCONTROL, false)) {
269 disposedRule.want->SetParam(INTERCEPT_BUNDLE_NAME, want.GetElement().GetBundleName());
270 disposedRule.want->SetParam(INTERCEPT_ABILITY_NAME, want.GetElement().GetAbilityName());
271 disposedRule.want->SetParam(INTERCEPT_MODULE_NAME, want.GetElement().GetModuleName());
272 }
273 }
274 } // namespace AAFwk
275 } // namespace OHOS