• 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/disposed_rule_interceptor.h"
17 
18 #include "ability_manager_service.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             "disposedType: %{public}d, controlType: %{public}d, "
45             "componentType: %{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, "no dispose want");
51             return AbilityUtil::EdmErrorType(disposedRule.isEdm);
52         }
53         if (disposedRule.want->GetBundle() == param.want.GetBundle()) {
54             TAG_LOGE(AAFwkTag::ABILITYMGR, "no dispose 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 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, "dispose UIExtension failed");
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     if (param.abilityInfo == nullptr) {
80         TAG_LOGE(AAFwkTag::ABILITYMGR, "disposed abilityInfo is nullptr");
81         return RESOLVE_ABILITY_ERR;
82     }
83     return StartNonBlockRule(param.want, disposedRule, param.abilityInfo->uid);
84 }
85 
CheckControl(const Want & want,int32_t userId,AppExecFwk::DisposedRule & disposedRule,int32_t appIndex)86 bool DisposedRuleInterceptor::CheckControl(const Want &want, int32_t userId,
87     AppExecFwk::DisposedRule &disposedRule, int32_t appIndex)
88 {
89     HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
90     // get bms
91     auto bundleMgrHelper = AbilityUtil::GetBundleManagerHelper();
92     if (bundleMgrHelper == nullptr) {
93         TAG_LOGE(AAFwkTag::ABILITYMGR, "null bundleMgrHelper");
94         return false;
95     }
96 
97     // get disposed status
98     std::string bundleName = want.GetBundle();
99     auto appControlMgr = bundleMgrHelper->GetAppControlProxy();
100     if (appControlMgr == nullptr) {
101         TAG_LOGE(AAFwkTag::ABILITYMGR, "null appControlMgr");
102         return false;
103     }
104     std::vector<AppExecFwk::DisposedRule> disposedRuleList;
105     {
106         HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, "GetAbilityRunningControlRule");
107         int32_t ret = ERR_OK;
108         if (appIndex > 0 && appIndex <= AbilityRuntime::GlobalConstant::MAX_APP_CLONE_INDEX) {
109             ret = IN_PROCESS_CALL(appControlMgr->GetAbilityRunningControlRule(bundleName,
110                 userId, disposedRuleList, appIndex));
111         } else {
112             ret = IN_PROCESS_CALL(appControlMgr->GetAbilityRunningControlRule(bundleName,
113                 userId, disposedRuleList, 0));
114         }
115         if (ret != ERR_OK || disposedRuleList.empty()) {
116             TAG_LOGD(AAFwkTag::ABILITYMGR, "Get No DisposedRule");
117             return false;
118         }
119     }
120 
121     for (auto &rule:disposedRuleList) {
122         if (CheckDisposedRule(want, rule)) {
123             disposedRule = rule;
124             return true;
125         }
126     }
127     int priority = -1;
128     for (auto &rule : disposedRuleList) {
129         if (rule.disposedType != AppExecFwk::DisposedType::NON_BLOCK) {
130             return false;
131         }
132         if (rule.priority > priority) {
133             priority = rule.priority;
134             disposedRule = rule;
135         }
136     }
137     return false;
138 }
139 
CheckDisposedRule(const Want & want,AppExecFwk::DisposedRule & disposedRule)140 bool DisposedRuleInterceptor::CheckDisposedRule(const Want &want, AppExecFwk::DisposedRule &disposedRule)
141 {
142     if (disposedRule.disposedType == AppExecFwk::DisposedType::NON_BLOCK) {
143         return false;
144     }
145     bool isAllowed = disposedRule.controlType == AppExecFwk::ControlType::ALLOWED_LIST;
146     if (disposedRule.disposedType == AppExecFwk::DisposedType::BLOCK_APPLICATION) {
147         return !isAllowed;
148     }
149 
150     std::string moduleName = want.GetElement().GetModuleName();
151     std::string abilityName = want.GetElement().GetAbilityName();
152 
153     for (auto elementName : disposedRule.elementList) {
154         if (moduleName == elementName.GetModuleName()
155             && abilityName == elementName.GetAbilityName()) {
156             return !isAllowed;
157         }
158     }
159     return isAllowed;
160 }
161 
StartNonBlockRule(const Want & want,AppExecFwk::DisposedRule & disposedRule,int32_t uid)162 ErrCode DisposedRuleInterceptor::StartNonBlockRule(const Want &want, AppExecFwk::DisposedRule &disposedRule,
163     int32_t uid)
164 {
165     HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
166     TAG_LOGI(AAFwkTag::ABILITYMGR, "not block");
167     if (disposedRule.want == nullptr) {
168         TAG_LOGE(AAFwkTag::ABILITYMGR, "null want");
169         return ERR_OK;
170     }
171     if (disposedRule.want->GetBundle() == want.GetBundle()) {
172         TAG_LOGE(AAFwkTag::ABILITYMGR, "no dispose app with same bundleName");
173         return ERR_OK;
174     }
175     SetInterceptInfo(want, disposedRule);
176     std::string bundleName = want.GetBundle();
177     sptr<OHOS::AppExecFwk::IAppMgr> appManager = GetAppMgr();
178     CHECK_POINTER_AND_RETURN(appManager, ERR_INVALID_VALUE);
179     {
180         std::lock_guard<ffrt::mutex> guard(observerLock_);
181         if (disposedObserverMap_.find(uid) != disposedObserverMap_.end()) {
182             TAG_LOGD(AAFwkTag::ABILITYMGR, "start same disposed app, do not need to register again");
183             return ERR_OK;
184         }
185         auto disposedObserver = sptr<DisposedObserver>::MakeSptr(disposedRule, shared_from_this(), uid);
186         CHECK_POINTER_AND_RETURN(disposedObserver, ERR_INVALID_VALUE);
187         std::vector<std::string> bundleNameList;
188         bundleNameList.push_back(bundleName);
189         int32_t ret = IN_PROCESS_CALL(appManager->RegisterApplicationStateObserver(disposedObserver, bundleNameList));
190         if (ret != 0) {
191             TAG_LOGE(AAFwkTag::ABILITYMGR, "register failed, err:%{public}d", ret);
192             disposedObserver = nullptr;
193             return ret;
194         }
195         disposedObserverMap_.emplace(uid, disposedObserver);
196     }
197     auto unregisterTask = [appManager, uid, interceptor = shared_from_this()] () {
198         std::lock_guard<ffrt::mutex> guard{interceptor->observerLock_};
199         auto iter = interceptor->disposedObserverMap_.find(uid);
200         if (iter != interceptor->disposedObserverMap_.end()) {
201             TAG_LOGE(AAFwkTag::ABILITYMGR, "time out, unregister observer");
202             IN_PROCESS_CALL(appManager->UnregisterApplicationStateObserver(iter->second));
203             interceptor->disposedObserverMap_.erase(iter);
204         }
205     };
206     CHECK_POINTER_AND_RETURN(taskHandler_, ERR_INVALID_VALUE);
207     taskHandler_->SubmitTask(unregisterTask, UNREGISTER_TIMEOUT_OBSERVER_TASK, UNREGISTER_OBSERVER_MICRO_SECONDS);
208     return ERR_OK;
209 }
210 
GetAppMgr()211 sptr<OHOS::AppExecFwk::IAppMgr> DisposedRuleInterceptor::GetAppMgr()
212 {
213     OHOS::sptr<OHOS::ISystemAbilityManager> systemAbilityManager =
214         OHOS::SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
215     if (!systemAbilityManager) {
216         TAG_LOGE(AAFwkTag::ABILITYMGR, "get systemAbilityManager failed");
217         return nullptr;
218     }
219     OHOS::sptr<OHOS::IRemoteObject> object = systemAbilityManager->GetSystemAbility(OHOS::APP_MGR_SERVICE_ID);
220     if (!object) {
221         TAG_LOGE(AAFwkTag::ABILITYMGR, "get systemAbilityManager failed");
222         return nullptr;
223     }
224     sptr<OHOS::AppExecFwk::IAppMgr> appMgr = iface_cast<AppExecFwk::IAppMgr>(object);
225     if (!appMgr || !appMgr->AsObject()) {
226         return nullptr;
227     }
228     return appMgr;
229 }
230 
UnregisterObserver(int32_t uid)231 void DisposedRuleInterceptor::UnregisterObserver(int32_t uid)
232 {
233     TAG_LOGD(AAFwkTag::ABILITYMGR, "Call");
234     CHECK_POINTER(taskHandler_);
235     taskHandler_->CancelTask(UNREGISTER_TIMEOUT_OBSERVER_TASK);
236     auto unregisterTask = [uid, interceptor = shared_from_this()] () {
237         std::lock_guard<ffrt::mutex> guard{interceptor->observerLock_};
238         auto iter = interceptor->disposedObserverMap_.find(uid);
239         if (iter == interceptor->disposedObserverMap_.end()) {
240             TAG_LOGE(AAFwkTag::ABILITYMGR, "no find observer");
241         } else {
242             auto disposedObserver = iter->second;
243             CHECK_POINTER(disposedObserver);
244             sptr<OHOS::AppExecFwk::IAppMgr> appManager = interceptor->GetAppMgr();
245             CHECK_POINTER(appManager);
246             IN_PROCESS_CALL(appManager->UnregisterApplicationStateObserver(disposedObserver));
247             interceptor->disposedObserverMap_.erase(iter);
248         }
249     };
250     taskHandler_->SubmitTask(unregisterTask, UNREGISTER_EVENT_TASK);
251 }
252 
CreateModalUIExtension(const Want & want,const sptr<IRemoteObject> & callerToken)253 ErrCode DisposedRuleInterceptor::CreateModalUIExtension(const Want &want, const sptr<IRemoteObject> &callerToken)
254 {
255     HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
256     auto abilityRecord = Token::GetAbilityRecordByToken(callerToken);
257     if (abilityRecord == nullptr || abilityRecord->GetAbilityInfo().type != AppExecFwk::AbilityType::PAGE) {
258         auto systemUIExtension = std::make_shared<OHOS::Rosen::ModalSystemUiExtension>();
259         (const_cast<Want &>(want)).SetParam(UIEXTENSION_MODAL_TYPE, 1);
260         return IN_PROCESS_CALL(systemUIExtension->CreateModalUIExtension(want)) ? ERR_OK : INNER_ERR;
261     } else {
262         return abilityRecord->CreateModalUIExtension(want);
263     }
264 }
265 
SetInterceptInfo(const Want & want,AppExecFwk::DisposedRule & disposedRule)266 void DisposedRuleInterceptor::SetInterceptInfo(const Want &want, AppExecFwk::DisposedRule &disposedRule)
267 {
268     if (disposedRule.want == nullptr) {
269         TAG_LOGW(AAFwkTag::ABILITYMGR, "null disposedWant");
270         return;
271     }
272     if (disposedRule.want->GetBoolParam(IS_FROM_PARENTCONTROL, false)) {
273         disposedRule.want->SetParam(INTERCEPT_BUNDLE_NAME, want.GetElement().GetBundleName());
274         disposedRule.want->SetParam(INTERCEPT_ABILITY_NAME, want.GetElement().GetAbilityName());
275         disposedRule.want->SetParam(INTERCEPT_MODULE_NAME, want.GetElement().GetModuleName());
276     }
277 }
278 } // namespace AAFwk
279 } // namespace OHOS