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 #include "ndef_har_dispatch.h"
16
17 #include "external_deps_proxy.h"
18 #include "iservice_registry.h"
19 #include "ndef_har_data_parser.h"
20 #include "tag_ability_dispatcher.h"
21 #include "ability_manager_client.h"
22 #include "loghelper.h"
23 #include "bundle_mgr_interface.h"
24 #include "if_system_ability_manager.h"
25 #ifdef NFC_HANDLE_SCREEN_LOCK
26 #include "external_deps_proxy.h"
27 #include "screenlock_common.h"
28 #include "power_mgr_client.h"
29 #include "nfc_sdk_common.h"
30 #endif
31 namespace OHOS {
32 namespace NFC {
33 namespace TAG {
34 const int USER_ID = 100;
35 const int BUNDLE_MGR_SERVICE_SYS_ABILITY_ID = 401;
36 using namespace OHOS::NFC::KITS;
37 #ifdef NFC_HANDLE_SCREEN_LOCK
38 AAFwk::Want g_carrierWant;
39 static std::mutex g_isCarrierModeMutex {};
40 static bool g_isCarrierMode = false;
41 uint64_t g_lastCarrierReportTime;
42 const int SET_UNLOCK_TIMEOUT = 30 * 1000;
43 #endif
44 std::string uri_ {};
45 std::string browserBundleName_ {};
46
47 #ifdef NFC_HANDLE_SCREEN_LOCK
NfcUnlockScreenCallback()48 NfcUnlockScreenCallback::NfcUnlockScreenCallback() {}
~NfcUnlockScreenCallback()49 NfcUnlockScreenCallback::~NfcUnlockScreenCallback() {}
50
OnCallBack(const int32_t screenLockResult)51 void NfcUnlockScreenCallback::OnCallBack(const int32_t screenLockResult)
52 {
53 InfoLog("NfcUnlockScreenCallback OnCallBack enabled. screenLockResult = %{public}d.", screenLockResult);
54 }
55 #endif
56
NdefHarDispatch(std::weak_ptr<NCI::INciNfccInterface> nciNfccProxy)57 NdefHarDispatch::NdefHarDispatch(std::weak_ptr<NCI::INciNfccInterface> nciNfccProxy)
58 : nciNfccProxy_(nciNfccProxy)
59 {
60 }
61
GetBundleMgrProxy()62 sptr<AppExecFwk::IBundleMgr> NdefHarDispatch::GetBundleMgrProxy()
63 {
64 sptr<ISystemAbilityManager> systemAbilityManager =
65 SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
66 if (!systemAbilityManager) {
67 ErrorLog("GetBundleMgrProxy, systemAbilityManager is null");
68 return nullptr;
69 }
70 sptr<IRemoteObject> remoteObject = systemAbilityManager->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
71 if (!remoteObject) {
72 ErrorLog("GetBundleMgrProxy, remoteObject is null");
73 return nullptr;
74 }
75 return iface_cast<AppExecFwk::IBundleMgr>(remoteObject);
76 }
77
78 /* Implicit matching, using mimetype to pull up app */
DispatchMimeType(const std::string & type,const std::shared_ptr<KITS::TagInfo> & tagInfo)79 bool NdefHarDispatch::DispatchMimeType(const std::string &type, const std::shared_ptr<KITS::TagInfo> &tagInfo)
80 {
81 if (type.empty() || tagInfo == nullptr) {
82 ErrorLog("NdefHarDispatch::DispatchMimeType type is empty");
83 return false;
84 }
85 AAFwk::Want want;
86 want.SetType(type);
87 ExternalDepsProxy::GetInstance().SetWantExtraParam(tagInfo, want);
88 if (GetBundleMgrProxy() == nullptr) {
89 ErrorLog("NdefHarDispatch::DispatchMimeType GetBundleMgrProxy is nullptr");
90 return false;
91 }
92 bool withDefault = false;
93 auto abilityInfoFlag = AppExecFwk::AbilityInfoFlag::GET_ABILITY_INFO_DEFAULT
94 | AppExecFwk::AbilityInfoFlag::GET_ABILITY_INFO_WITH_SKILL_URI
95 | AppExecFwk::AbilityInfoFlag::GET_ABILITY_INFO_WITH_METADATA;
96 std::vector<AbilityInfo> abilityInfos;
97 std::vector<ExtensionAbilityInfo> extensionInfos;
98 bool findDefaultApp = false;
99 if (!GetBundleMgrProxy()->ImplicitQueryInfos(
100 want, abilityInfoFlag, USER_ID, withDefault, abilityInfos, extensionInfos, findDefaultApp)) {
101 ErrorLog("NdefHarDispatch::DispatchMimeType ImplicitQueryInfos false");
102 return false;
103 }
104 int32_t errCode = AAFwk::AbilityManagerClient::GetInstance()->StartAbility(want);
105 if (errCode) {
106 ErrorLog("NdefHarDispatch::DispatchMimeType call StartAbility fail. ret = %{public}d", errCode);
107 return false;
108 }
109 ExternalDepsProxy::GetInstance().WriteDispatchToAppHiSysEvent(want.GetElement().GetBundleName(),
110 SubErrorCode::NDEF_HAR_DISPATCH);
111 return true;
112 }
113
114 /* Verify harPackageString as BundleName/ServiceName and call StartExtensionAbility to pull up app */
DispatchBundleExtensionAbility(const std::string & harPackageString,const std::shared_ptr<KITS::TagInfo> & tagInfo,const std::string & mimeType,const std::string & uri)115 bool NdefHarDispatch::DispatchBundleExtensionAbility(const std::string &harPackageString,
116 const std::shared_ptr<KITS::TagInfo> &tagInfo, const std::string &mimeType, const std::string &uri)
117 {
118 std::istringstream iss(harPackageString);
119 std::string bundleName;
120 std::string serviceName;
121 if (!getline(iss, bundleName, '/')) {
122 InfoLog("harPackageString bundleName invalid");
123 return false;
124 }
125 if (!getline(iss, serviceName, '/')) {
126 InfoLog("harPackageString serviceName invalid");
127 return false;
128 }
129 AAFwk::Want want;
130 want.SetElementName(bundleName, serviceName);
131 if (!mimeType.empty()) {
132 want.SetType(mimeType);
133 }
134 if (uri.size() > 0) {
135 want.SetUri(uri);
136 }
137 if (tagInfo != nullptr) {
138 ExternalDepsProxy::GetInstance().SetWantExtraParam(tagInfo, want);
139 }
140 int errCode = AAFwk::AbilityManagerClient::GetInstance()->StartExtensionAbility(want, nullptr);
141 InfoLog("StartExtensionAbility ret = %{public}d, bundleName = %{public}s, serviceName = %{public}s", errCode,
142 bundleName.c_str(), serviceName.c_str());
143 return (errCode == 0);
144 }
145
146 /* Call GetLaunchWantForBundle through bundlename to obtain the want and pull up the app */
DispatchBundleAbility(const std::string & harPackage,const std::shared_ptr<KITS::TagInfo> & tagInfo,const std::string & mimeType,const std::string & uri,OHOS::sptr<IRemoteObject> tagServiceIface)147 bool NdefHarDispatch::DispatchBundleAbility(const std::string &harPackage,
148 const std::shared_ptr<KITS::TagInfo> &tagInfo, const std::string &mimeType, const std::string &uri,
149 OHOS::sptr<IRemoteObject> tagServiceIface)
150 {
151 if (harPackage.empty()) {
152 ErrorLog("NdefHarDispatch::DispatchBundleAbility harPackage is empty");
153 return false;
154 }
155 std::string harPackageString = NfcSdkCommon::HexStringToAsciiString(harPackage);
156 AAFwk::Want want;
157 if (GetBundleMgrProxy() == nullptr) {
158 ErrorLog("GetBundleMgrProxy is nullptr");
159 return false;
160 }
161 int32_t errCode = GetBundleMgrProxy()->GetLaunchWantForBundle(harPackageString, want, USER_ID);
162 if (errCode) {
163 InfoLog("GetLaunchWantForBundle fail. ret = %{public}d, harPackage = %{public}s, try ExtensionAbility instead",
164 errCode, harPackageString.c_str());
165 if (DispatchBundleExtensionAbility(harPackageString, tagInfo, mimeType, uri)) {
166 return true;
167 }
168 return false;
169 }
170 if (!mimeType.empty()) {
171 want.SetType(mimeType);
172 }
173 if (tagServiceIface == nullptr) {
174 WarnLog("tagServiceIface is null");
175 }
176 if (tagInfo != nullptr) {
177 want.SetParam("remoteTagService", tagServiceIface);
178 ExternalDepsProxy::GetInstance().SetWantExtraParam(tagInfo, want);
179 }
180 if (uri.size() > 0) {
181 want.SetUri(uri);
182 }
183 if (!nciNfccProxy_.expired()) {
184 nciNfccProxy_.lock()->UpdateWantExtInfoByVendor(want, uri);
185 }
186 #ifdef NFC_HANDLE_SCREEN_LOCK
187 auto screenLockIface = ScreenLock::ScreenLockManager::GetInstance();
188 if (screenLockIface == nullptr) {
189 ErrorLog("ScreenLock::ScreenLockManager interface invalid");
190 return false;
191 }
192 bool isLocked = false;
193 screenLockIface->IsLocked(isLocked);
194 if (isLocked) {
195 g_carrierWant = want;
196 sptr<NfcUnlockScreenCallback> listener = new (std::nothrow) NfcUnlockScreenCallback();
197 if (listener == nullptr) {
198 ErrorLog("NfcUnlockScreenCallback listener invalid");
199 return false;
200 }
201 screenLockIface->Unlock(ScreenLock::Action::UNLOCKSCREEN, listener);
202 g_lastCarrierReportTime = KITS::NfcSdkCommon::GetCurrentTime();
203 g_isCarrierMode = true;
204 ExternalDepsProxy::GetInstance().StartVibratorOnce();
205 return true;
206 }
207 InfoLog("NdefHarDispatch::DispatchBundleAbility WakeupDevice");
208 PowerMgr::PowerMgrClient::GetInstance().WakeupDevice();
209 #endif
210 errCode = AAFwk::AbilityManagerClient::GetInstance()->StartAbility(want);
211 if (errCode) {
212 ErrorLog("StartAbility fail. ret = %{public}d, harPackage = %{public}s",
213 errCode, harPackageString.c_str());
214 return false;
215 }
216 ExternalDepsProxy::GetInstance().WriteDispatchToAppHiSysEvent(want.GetElement().GetBundleName(),
217 SubErrorCode::NDEF_HAR_DISPATCH);
218 if (!nciNfccProxy_.expired()) {
219 nciNfccProxy_.lock()->NotifyMessageToVendor(KITS::TAG_DISPATCH_HAR_PACKAGE, harPackageString);
220 }
221 return true;
222 }
223
224 #ifdef NFC_HANDLE_SCREEN_LOCK
HandleCarrierReport()225 void NdefHarDispatch::HandleCarrierReport()
226 {
227 InfoLog("NdefHarDispatch::HandleCarrierReport enter.");
228 std::lock_guard<std::mutex> lock(g_isCarrierModeMutex);
229 uint64_t currTime = KITS::NfcSdkCommon::GetCurrentTime();
230 if ((currTime - g_lastCarrierReportTime) < SET_UNLOCK_TIMEOUT && g_isCarrierMode) {
231 InfoLog("Unlock successfully before timeout.");
232 auto abilityManagerClient = AAFwk::AbilityManagerClient::GetInstance();
233 if (abilityManagerClient == nullptr) {
234 g_isCarrierMode = false;
235 ErrorLog("abilityManagerClient is nullptr.");
236 return;
237 }
238 abilityManagerClient->StartAbility(g_carrierWant);
239 }
240 g_isCarrierMode = false;
241 }
242 #endif
243
DispatchUriToBundleAbility(const std::string & uri)244 bool NdefHarDispatch::DispatchUriToBundleAbility(const std::string &uri)
245 {
246 if (uri.empty()) {
247 ErrorLog("NdefHarDispatch::DispatchUriToBundleAbility uri is empty");
248 return false;
249 }
250 bool canOpen = false;
251 if (GetBundleMgrProxy() == nullptr) {
252 ErrorLog("NdefHarDispatch::DispatchUriToBundleAbility GetBundleMgrProxy is nullptr");
253 return false;
254 }
255 int32_t errCode = GetBundleMgrProxy()->CanOpenLink(uri, canOpen);
256 if (!errCode && canOpen) {
257 InfoLog("NdefHarDispatch::DispatchUriToBundleAbility CanOpenLink");
258 }
259 ErrorLog("CanOpenLink fail. errCode = %{public}d, canOpen = %{public}d", errCode, canOpen);
260 return false;
261 }
262
263 /* If the corresponding app has been installed, the system jumps to the corresponding app and starts it.
264 * If the corresponding app is not installed, the default browser is used to open the corresponding page.
265 */
DispatchByAppLinkMode(const std::string & uriSchemeValue,const std::shared_ptr<KITS::TagInfo> & tagInfo,OHOS::sptr<IRemoteObject> tagServiceIface)266 bool NdefHarDispatch::DispatchByAppLinkMode(const std::string &uriSchemeValue,
267 const std::shared_ptr<KITS::TagInfo> &tagInfo, OHOS::sptr<IRemoteObject> tagServiceIface)
268 {
269 std::unique_lock<std::shared_mutex> guard(mutex_);
270 InfoLog("enter");
271 if (uriSchemeValue.empty()) {
272 ErrorLog("uriSchemeValue is empty");
273 return false;
274 }
275 if (tagInfo == nullptr) {
276 ErrorLog("tagInfo is null");
277 return false;
278 }
279 if (tagServiceIface == nullptr) {
280 WarnLog("tagServiceIface is null");
281 }
282 AAFwk::Want want;
283 const std::string PARAM_KEY = "appLinkingOnly"; // Use App Linking Mode
284 want.SetUri(uriSchemeValue);
285 want.SetParam(PARAM_KEY, false);
286 want.SetParam("remoteTagService", tagServiceIface);
287 ExternalDepsProxy::GetInstance().SetWantExtraParam(tagInfo, want);
288 int32_t errCode = AAFwk::AbilityManagerClient::GetInstance()->StartAbility(want);
289 if (errCode) {
290 ErrorLog(
291 "call StartAbility fail. uriSchemeValue = [%{public}s] ret = %{public}d", uriSchemeValue.c_str(), errCode);
292 return false;
293 }
294 ExternalDepsProxy::GetInstance().WriteDispatchToAppHiSysEvent(want.GetElement().GetBundleName(),
295 SubErrorCode::NDEF_URI_BROWSER_DISPATCH);
296 return true;
297 }
298 } // namespace TAG
299 } // namespace NFC
300 } // namespace OHOS