1 /*
2 * Copyright (c) 2022-2023 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 #include "implicit_start_processor.h"
16
17 #include <string>
18
19 #include "ability_manager_service.h"
20 #include "ability_util.h"
21 #include "default_app_interface.h"
22 #include "errors.h"
23 #include "event_report.h"
24 #include "hilog_wrapper.h"
25 #include "in_process_call_wrapper.h"
26 #include "parameters.h"
27 #include "want.h"
28 #ifdef SUPPORT_ERMS
29 #include "ecological_rule_mgr_service_client.h"
30 #endif
31
32 namespace OHOS {
33 namespace AAFwk {
34 #ifdef SUPPORT_ERMS
35 using namespace OHOS::EcologicalRuleMgrService;
36
37 constexpr int32_t TYPE_HARMONY_INVALID = 0;
38 constexpr int32_t TYPE_HARMONY_APP = 1;
39 constexpr int32_t TYPE_HARMONY_SERVICE = 2;
40 #else
41 using ErmsCallerInfo = OHOS::AppExecFwk::ErmsParams::CallerInfo;
42 #endif
43
44 const std::string BLACK_ACTION_SELECT_DATA = "ohos.want.action.select";
45 const std::string STR_PHONE = "phone";
46 const std::string STR_DEFAULT = "default";
47 const std::string TYPE_ONLY_MATCH_WILDCARD = "reserved/wildcard";
48 const std::string SHOW_DEFAULT_PICKER_FLAG = "ohos.ability.params.showDefaultPicker";
49
50 const std::vector<std::string> ImplicitStartProcessor::blackList = {
51 std::vector<std::string>::value_type(BLACK_ACTION_SELECT_DATA),
52 };
53
54 const std::unordered_set<AppExecFwk::ExtensionAbilityType> ImplicitStartProcessor::extensionWhiteList = {
55 AppExecFwk::ExtensionAbilityType::FORM,
56 AppExecFwk::ExtensionAbilityType::INPUTMETHOD,
57 AppExecFwk::ExtensionAbilityType::WALLPAPER,
58 AppExecFwk::ExtensionAbilityType::WINDOW,
59 AppExecFwk::ExtensionAbilityType::THUMBNAIL,
60 AppExecFwk::ExtensionAbilityType::PREVIEW
61 };
62
IsImplicitStartAction(const Want & want)63 bool ImplicitStartProcessor::IsImplicitStartAction(const Want &want)
64 {
65 auto element = want.GetElement();
66 if (!element.GetAbilityName().empty()) {
67 return false;
68 }
69
70 if (std::find(blackList.begin(), blackList.end(), want.GetAction()) == blackList.end()) {
71 HILOG_INFO("implicit start, the action is %{public}s", want.GetAction().data());
72 return true;
73 }
74
75 return false;
76 }
77
ImplicitStartAbility(AbilityRequest & request,int32_t userId)78 int ImplicitStartProcessor::ImplicitStartAbility(AbilityRequest &request, int32_t userId)
79 {
80 HILOG_INFO("implicit start ability by type: %{public}d", request.callType);
81 auto sysDialogScheduler = DelayedSingleton<SystemDialogScheduler>::GetInstance();
82 CHECK_POINTER_AND_RETURN(sysDialogScheduler, ERR_INVALID_VALUE);
83
84 std::vector<DialogAppInfo> dialogAppInfos;
85 auto deviceType = OHOS::system::GetDeviceType();
86 HILOG_DEBUG("deviceType is %{public}s", deviceType.c_str());
87 auto ret = GenerateAbilityRequestByAction(userId, request, dialogAppInfos, deviceType, false);
88 if (ret != ERR_OK) {
89 HILOG_ERROR("generate ability request by action failed.");
90 return ret;
91 }
92
93 auto identity = IPCSkeleton::ResetCallingIdentity();
94 auto startAbilityTask = [imp = shared_from_this(), request, userId, identity]
95 (const std::string& bundle, const std::string& abilityName) mutable {
96 HILOG_INFO("implicit start ability call back.");
97
98 // reset calling indentity
99 IPCSkeleton::SetCallingIdentity(identity);
100
101 AAFwk::Want targetWant = request.want;
102 targetWant.SetElementName(bundle, abilityName);
103 auto callBack = [imp, targetWant, request, userId]() -> int32_t {
104 return imp->ImplicitStartAbilityInner(targetWant, request, userId);
105 };
106 return imp->CallStartAbilityInner(userId, targetWant, callBack, request.callType);
107 };
108
109 AAFwk::Want want;
110 auto abilityMgr = DelayedSingleton<AbilityManagerService>::GetInstance();
111 if (dialogAppInfos.size() == 0 && (deviceType == STR_PHONE || deviceType == STR_DEFAULT)) {
112 HILOG_ERROR("implicit query ability infos failed, show tips dialog.");
113 want = sysDialogScheduler->GetTipsDialogWant(request.callerToken);
114 abilityMgr->StartAbility(want);
115 return ERR_IMPLICIT_START_ABILITY_FAIL;
116 } else if (dialogAppInfos.size() == 0 && deviceType != STR_PHONE && deviceType != STR_DEFAULT) {
117 std::vector<DialogAppInfo> dialogAllAppInfos;
118 bool isMoreHapList = true;
119 ret = GenerateAbilityRequestByAction(userId, request, dialogAllAppInfos, deviceType, isMoreHapList);
120 if (ret != ERR_OK) {
121 HILOG_ERROR("generate ability request by action failed.");
122 return ret;
123 }
124 if (dialogAllAppInfos.size() == 0) {
125 Want dialogWant = sysDialogScheduler->GetTipsDialogWant(request.callerToken);
126 abilityMgr->StartAbility(dialogWant);
127 return ERR_IMPLICIT_START_ABILITY_FAIL;
128 }
129 want = sysDialogScheduler->GetPcSelectorDialogWant(dialogAllAppInfos, request.want,
130 TYPE_ONLY_MATCH_WILDCARD, userId, request.callerToken);
131 ret = abilityMgr->StartAbility(want, request.callerToken);
132 // reset calling indentity
133 IPCSkeleton::SetCallingIdentity(identity);
134 return ret;
135 }
136
137 //There is a default opening method add Only one application supports
138 bool defaultPicker = false;
139 defaultPicker = request.want.GetBoolParam(SHOW_DEFAULT_PICKER_FLAG, defaultPicker);
140 if (dialogAppInfos.size() == 1 && (!defaultPicker || deviceType == STR_PHONE || deviceType == STR_DEFAULT)) {
141 auto info = dialogAppInfos.front();
142 HILOG_INFO("ImplicitQueryInfos success, target ability: %{public}s", info.abilityName.data());
143 return IN_PROCESS_CALL(startAbilityTask(info.bundleName, info.abilityName));
144 }
145
146 if (deviceType == STR_PHONE || deviceType == STR_DEFAULT) {
147 HILOG_INFO("ImplicitQueryInfos success, Multiple apps to choose.");
148 want = sysDialogScheduler->GetSelectorDialogWant(dialogAppInfos, request.want, request.callerToken);
149 ret = abilityMgr->StartAbilityAsCaller(want, request.callerToken);
150 // reset calling indentity
151 IPCSkeleton::SetCallingIdentity(identity);
152 return ret;
153 }
154
155 HILOG_INFO("ImplicitQueryInfos success, Multiple apps to choose in pc.");
156 auto type = request.want.GetType();
157 want = sysDialogScheduler->GetPcSelectorDialogWant(dialogAppInfos, request.want, type, userId, request.callerToken);
158 ret = abilityMgr->StartAbilityAsCaller(want, request.callerToken);
159 // reset calling indentity
160 IPCSkeleton::SetCallingIdentity(identity);
161 return ret;
162 }
163
GenerateAbilityRequestByAction(int32_t userId,AbilityRequest & request,std::vector<DialogAppInfo> & dialogAppInfos,std::string & deviceType,bool isMoreHapList)164 int ImplicitStartProcessor::GenerateAbilityRequestByAction(int32_t userId,
165 AbilityRequest &request, std::vector<DialogAppInfo> &dialogAppInfos, std::string &deviceType, bool isMoreHapList)
166 {
167 HILOG_DEBUG("%{public}s", __func__);
168 // get abilityinfos from bms
169 auto bms = GetBundleManager();
170 CHECK_POINTER_AND_RETURN(bms, GET_ABILITY_SERVICE_FAILED);
171 auto abilityInfoFlag = AppExecFwk::AbilityInfoFlag::GET_ABILITY_INFO_DEFAULT
172 | AppExecFwk::AbilityInfoFlag::GET_ABILITY_INFO_WITH_SKILL_URI;
173 std::vector<AppExecFwk::AbilityInfo> abilityInfos;
174 std::vector<AppExecFwk::ExtensionAbilityInfo> extensionInfos;
175 bool withDefault = false;
176 withDefault = request.want.GetBoolParam(SHOW_DEFAULT_PICKER_FLAG, withDefault) ? false : true;
177 IN_PROCESS_CALL_WITHOUT_RET(bms->ImplicitQueryInfos(
178 request.want, abilityInfoFlag, userId, withDefault, abilityInfos, extensionInfos));
179
180 HILOG_INFO("ImplicitQueryInfos, abilityInfo size : %{public}zu, extensionInfos size: %{public}zu",
181 abilityInfos.size(), extensionInfos.size());
182
183 if (abilityInfos.size() + extensionInfos.size() > 1) {
184 HILOG_INFO("More than one target application, filter by erms");
185 bool ret = FilterAbilityList(request.want, abilityInfos, extensionInfos, userId);
186 if (!ret) {
187 HILOG_ERROR("FilterAbilityList failed");
188 }
189 }
190
191 auto isExtension = request.callType == AbilityCallType::START_EXTENSION_TYPE;
192
193 Want implicitwant;
194 implicitwant.SetAction(request.want.GetAction());
195 implicitwant.SetType(TYPE_ONLY_MATCH_WILDCARD);
196 std::vector<AppExecFwk::AbilityInfo> implicitAbilityInfos;
197 std::vector<AppExecFwk::ExtensionAbilityInfo> implicitExtensionInfos;
198 std::vector<std::string> infoNames;
199 if (deviceType != STR_PHONE && deviceType != STR_DEFAULT) {
200 IN_PROCESS_CALL_WITHOUT_RET(bms->ImplicitQueryInfos(implicitwant, abilityInfoFlag, userId,
201 withDefault, implicitAbilityInfos, implicitExtensionInfos));
202 if (implicitAbilityInfos.size() != 0 && request.want.GetType() != TYPE_ONLY_MATCH_WILDCARD) {
203 for (auto implicitAbilityInfo : implicitAbilityInfos) {
204 infoNames.emplace_back(implicitAbilityInfo.bundleName + "#" +
205 implicitAbilityInfo.moduleName + "#" + implicitAbilityInfo.name);
206 }
207 }
208 }
209 for (const auto &info : abilityInfos) {
210 if (isExtension && info.type != AbilityType::EXTENSION) {
211 continue;
212 }
213 if (deviceType != STR_PHONE && deviceType != STR_DEFAULT) {
214 auto isDefaultFlag = false;
215 if (withDefault) {
216 auto defaultMgr = GetDefaultAppProxy();
217 AppExecFwk::BundleInfo bundleInfo;
218 ErrCode ret =
219 IN_PROCESS_CALL(defaultMgr->GetDefaultApplication(userId, request.want.GetType(), bundleInfo));
220 if (ret == ERR_OK) {
221 if (bundleInfo.abilityInfos.size() == 1) {
222 HILOG_INFO("find default ability.");
223 isDefaultFlag = true;
224 } else if (bundleInfo.extensionInfos.size() == 1) {
225 HILOG_INFO("find default extension.");
226 isDefaultFlag = true;
227 } else {
228 HILOG_INFO("GetDefaultApplication failed.");
229 }
230 }
231 }
232 if (!isMoreHapList && !isDefaultFlag) {
233 if (std::find(infoNames.begin(), infoNames.end(),
234 (info.bundleName + "#" + info.moduleName + "#" + info.name)) != infoNames.end()) {
235 continue;
236 }
237 }
238 }
239
240 DialogAppInfo dialogAppInfo;
241 dialogAppInfo.abilityName = info.name;
242 dialogAppInfo.bundleName = info.bundleName;
243 dialogAppInfo.moduleName = info.moduleName;
244 dialogAppInfo.iconId = info.iconId;
245 dialogAppInfo.labelId = info.labelId;
246 dialogAppInfos.emplace_back(dialogAppInfo);
247 }
248
249 for (const auto &info : extensionInfos) {
250 if (!isExtension || !CheckImplicitStartExtensionIsValid(request, info)) {
251 continue;
252 }
253 DialogAppInfo dialogAppInfo;
254 dialogAppInfo.abilityName = info.name;
255 dialogAppInfo.bundleName = info.bundleName;
256 dialogAppInfo.iconId = info.iconId;
257 dialogAppInfo.labelId = info.labelId;
258 dialogAppInfos.emplace_back(dialogAppInfo);
259 }
260
261 return ERR_OK;
262 }
263
CheckImplicitStartExtensionIsValid(const AbilityRequest & request,const AppExecFwk::ExtensionAbilityInfo & extensionInfo)264 bool ImplicitStartProcessor::CheckImplicitStartExtensionIsValid(const AbilityRequest &request,
265 const AppExecFwk::ExtensionAbilityInfo &extensionInfo)
266 {
267 if (!request.want.GetElement().GetBundleName().empty()) {
268 return true;
269 }
270 HILOG_DEBUG("ImplicitStartExtension type: %{public}d.", static_cast<int32_t>(extensionInfo.type));
271 if (extensionWhiteList.find(extensionInfo.type) == extensionWhiteList.end()) {
272 HILOG_ERROR("The extension without UI is not allowed ImplicitStart");
273 return false;
274 }
275 return true;
276 }
277
ImplicitStartAbilityInner(const Want & targetWant,const AbilityRequest & request,int32_t userId)278 int32_t ImplicitStartProcessor::ImplicitStartAbilityInner(const Want &targetWant,
279 const AbilityRequest &request, int32_t userId)
280 {
281 auto abilityMgr = DelayedSingleton<AbilityManagerService>::GetInstance();
282 CHECK_POINTER_AND_RETURN(abilityMgr, ERR_INVALID_VALUE);
283
284 int32_t result = ERR_OK;
285 switch (request.callType) {
286 case AbilityCallType::START_OPTIONS_TYPE: {
287 StartOptions startOptions;
288 auto displayId = targetWant.GetIntParam(Want::PARAM_RESV_DISPLAY_ID, 0);
289 auto windowMode = targetWant.GetIntParam(Want::PARAM_RESV_WINDOW_MODE, 0);
290 startOptions.SetDisplayID(static_cast<int32_t>(displayId));
291 startOptions.SetWindowMode(static_cast<int32_t>(windowMode));
292 result = abilityMgr->StartAbility(
293 targetWant, startOptions, request.callerToken, userId, request.requestCode);
294 break;
295 }
296 case AbilityCallType::START_SETTINGS_TYPE: {
297 CHECK_POINTER_AND_RETURN(request.startSetting, ERR_INVALID_VALUE);
298 result = abilityMgr->StartAbility(
299 targetWant, *request.startSetting, request.callerToken, userId, request.requestCode);
300 break;
301 }
302 case AbilityCallType::START_EXTENSION_TYPE:
303 result = abilityMgr->StartExtensionAbility(
304 targetWant, request.callerToken, userId, request.extensionType);
305 break;
306 default:
307 result = abilityMgr->StartAbilityWrap(
308 targetWant, request.callerToken, request.requestCode, userId);
309 break;
310 }
311
312 return result;
313 }
314
CallStartAbilityInner(int32_t userId,const Want & want,const StartAbilityClosure & callBack,const AbilityCallType & callType)315 int ImplicitStartProcessor::CallStartAbilityInner(int32_t userId,
316 const Want &want, const StartAbilityClosure &callBack, const AbilityCallType &callType)
317 {
318 EventInfo eventInfo;
319 eventInfo.userId = userId;
320 eventInfo.bundleName = want.GetElement().GetBundleName();
321 eventInfo.moduleName = want.GetElement().GetModuleName();
322 eventInfo.abilityName = want.GetElement().GetAbilityName();
323
324 if (callType == AbilityCallType::INVALID_TYPE) {
325 EventReport::SendAbilityEvent(EventName::START_ABILITY, HiSysEventType::BEHAVIOR, eventInfo);
326 }
327
328 HILOG_INFO("ability:%{public}s, bundle:%{public}s", eventInfo.abilityName.c_str(), eventInfo.bundleName.c_str());
329
330 auto ret = callBack();
331 if (ret != ERR_OK) {
332 eventInfo.errCode = ret;
333 if (callType == AbilityCallType::INVALID_TYPE) {
334 EventReport::SendAbilityEvent(EventName::START_ABILITY_ERROR, HiSysEventType::FAULT, eventInfo);
335 }
336 }
337 return ret;
338 }
339
GetBundleManager()340 sptr<AppExecFwk::IBundleMgr> ImplicitStartProcessor::GetBundleManager()
341 {
342 if (iBundleManager_ == nullptr) {
343 iBundleManager_ = AbilityUtil::GetBundleManager();
344 }
345 return iBundleManager_;
346 }
347
GetDefaultAppProxy()348 sptr<AppExecFwk::IDefaultApp> ImplicitStartProcessor::GetDefaultAppProxy()
349 {
350 auto bundleMgr = GetBundleManager();
351 auto defaultAppProxy = bundleMgr->GetDefaultAppProxy();
352 if (defaultAppProxy == nullptr) {
353 HILOG_ERROR("GetDefaultAppProxy failed.");
354 return nullptr;
355 }
356 return defaultAppProxy;
357 }
358
FilterAbilityList(const Want & want,std::vector<AppExecFwk::AbilityInfo> & abilityInfos,std::vector<AppExecFwk::ExtensionAbilityInfo> extensionInfos,int32_t userId)359 bool ImplicitStartProcessor::FilterAbilityList(const Want &want, std::vector<AppExecFwk::AbilityInfo> &abilityInfos,
360 std::vector<AppExecFwk::ExtensionAbilityInfo> extensionInfos, int32_t userId)
361 {
362 #ifdef SUPPORT_ERMS
363 ErmsCallerInfo callerInfo;
364 GetEcologicalCallerInfo(want, callerInfo, userId);
365 int ret = IN_PROCESS_CALL(EcologicalRuleMgrServiceClient::GetInstance()->EvaluateResolveInfos(want, callerInfo, 0,
366 abilityInfos, extensionInfos));
367 #else
368 auto erms = AbilityUtil::CheckEcologicalRuleMgr();
369 if (!erms) {
370 HILOG_ERROR("get ecological rule mgr failed.");
371 return false;
372 }
373
374 ErmsCallerInfo callerInfo;
375 int ret = IN_PROCESS_CALL(erms->EvaluateResolveInfos(want, callerInfo, 0, abilityInfos, extensionInfos));
376 #endif
377 if (ret != ERR_OK) {
378 HILOG_ERROR("Failed to evaluate resolve infos from erms.");
379 return false;
380 }
381 return true;
382 }
383
384 #ifdef SUPPORT_ERMS
GetEcologicalCallerInfo(const Want & want,ErmsCallerInfo & callerInfo,int32_t userId)385 void ImplicitStartProcessor::GetEcologicalCallerInfo(const Want &want, ErmsCallerInfo &callerInfo, int32_t userId)
386 {
387 callerInfo.packageName = want.GetStringParam(Want::PARAM_RESV_CALLER_BUNDLE_NAME);
388 callerInfo.uid = want.GetIntParam(Want::PARAM_RESV_CALLER_UID, IPCSkeleton::GetCallingUid());
389 callerInfo.pid = want.GetIntParam(Want::PARAM_RESV_CALLER_PID, IPCSkeleton::GetCallingPid());
390 callerInfo.targetAppType = TYPE_HARMONY_INVALID;
391 callerInfo.callerAppType = TYPE_HARMONY_INVALID;
392
393 auto bms = AbilityUtil::GetBundleManager();
394 if (!bms) {
395 HILOG_ERROR("GetBundleManager failed");
396 return;
397 }
398
399 std::string targetBundleName = want.GetBundle();
400 AppExecFwk::ApplicationInfo targetAppInfo;
401 bool getTargetResult = IN_PROCESS_CALL(bms->GetApplicationInfo(targetBundleName,
402 AppExecFwk::ApplicationFlag::GET_BASIC_APPLICATION_INFO, userId, targetAppInfo));
403 if (!getTargetResult) {
404 HILOG_ERROR("Get targetAppInfo failed.");
405 } else if (targetAppInfo.bundleType == AppExecFwk::BundleType::ATOMIC_SERVICE) {
406 HILOG_DEBUG("the target type is atomic service");
407 callerInfo.targetAppType = TYPE_HARMONY_SERVICE;
408 } else if (targetAppInfo.bundleType == AppExecFwk::BundleType::APP) {
409 HILOG_DEBUG("the target type is app");
410 callerInfo.targetAppType = TYPE_HARMONY_APP;
411 } else {
412 HILOG_DEBUG("the target type is invalid type");
413 }
414
415 std::string callerBundleName;
416 ErrCode err = IN_PROCESS_CALL(bms->GetNameForUid(callerInfo.uid, callerBundleName));
417 if (err != ERR_OK) {
418 HILOG_ERROR("Get callerBundleName failed.");
419 return;
420 }
421 AppExecFwk::ApplicationInfo callerAppInfo;
422 bool getCallerResult = IN_PROCESS_CALL(bms->GetApplicationInfo(callerBundleName,
423 AppExecFwk::ApplicationFlag::GET_BASIC_APPLICATION_INFO, userId, callerAppInfo));
424 if (!getCallerResult) {
425 HILOG_DEBUG("Get callerAppInfo failed.");
426 } else if (callerAppInfo.bundleType == AppExecFwk::BundleType::ATOMIC_SERVICE) {
427 HILOG_DEBUG("the caller type is atomic service");
428 callerInfo.callerAppType = TYPE_HARMONY_SERVICE;
429 } else if (callerAppInfo.bundleType == AppExecFwk::BundleType::APP) {
430 HILOG_DEBUG("the caller type is app");
431 callerInfo.callerAppType = TYPE_HARMONY_APP;
432 } else {
433 HILOG_DEBUG("the caller type is invalid type");
434 }
435 }
436 #endif
437 } // namespace AAFwk
438 } // namespace OHOS