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 "tag_dispatcher.h"
16
17 #include <functional>
18
19 #include "app_data_parser.h"
20 #include "external_deps_proxy.h"
21 #include "loghelper.h"
22 #include "ndef_har_data_parser.h"
23 #include "ndef_har_dispatch.h"
24 #include "ndef_message.h"
25 #include "nfc_hisysevent.h"
26 #include "nfc_sdk_common.h"
27 #include "tag_ability_dispatcher.h"
28
29 #ifdef NDEF_WIFI_ENABLED
30 #include "ndef_wifi_data_parser.h"
31 #include "wifi_connection_manager.h"
32 #endif
33
34 #ifdef NDEF_BT_ENABLED
35 #include "ndef_bt_data_parser.h"
36 #include "bt_connection_manager.h"
37 #endif
38
39 namespace OHOS {
40 namespace NFC {
41 namespace TAG {
42 #define NDEF_TYPE_NORMAL 1
43 #define NDEF_TYPE_BT 2
44 #define NDEF_TYPE_WIFI 3
45
46 using OHOS::NFC::KITS::TagTechnology;
47
TagDispatcher(std::shared_ptr<NFC::NfcService> nfcService)48 TagDispatcher::TagDispatcher(std::shared_ptr<NFC::NfcService> nfcService)
49 : nfcService_(nfcService),
50 lastNdefMsg_(""),
51 ndefCb_(nullptr)
52 {
53 if (nfcService_) {
54 nciTagProxy_ = nfcService_->GetNciTagProxy();
55 if (!nciTagProxy_.expired()) {
56 isodepCardHandler_ = std::make_shared<IsodepCardHandler>(nciTagProxy_);
57 ndefHarDataParser_ = std::make_shared<NdefHarDataParser>(nciTagProxy_);
58 }
59 }
60 }
61
~TagDispatcher()62 TagDispatcher::~TagDispatcher()
63 {
64 }
65
RegNdefMsgCb(const sptr<INdefMsgCallback> & callback)66 void TagDispatcher::RegNdefMsgCb(const sptr<INdefMsgCallback> &callback)
67 {
68 ndefCb_ = callback;
69 }
70
HandleNdefDispatch(uint32_t tagDiscId,std::string & msg)71 bool TagDispatcher::HandleNdefDispatch(uint32_t tagDiscId, std::string &msg)
72 {
73 if (nciTagProxy_.expired()) {
74 ErrorLog("HandleNdefDispatch, nciTagProxy_ expired");
75 return false;
76 }
77 std::string tagUid = nciTagProxy_.lock()->GetTagUid(tagDiscId);
78 int msgType = NDEF_TYPE_NORMAL;
79 std::string ndef = msg;
80 if (ndefCb_ != nullptr) {
81 ndefCbRes_ = ndefCb_->OnNdefMsgDiscovered(tagUid, ndef, msgType);
82 }
83 if (ndefCbRes_) {
84 InfoLog("HandleNdefDispatch, is dispatched by ndefMsg callback");
85 return true;
86 }
87 #ifdef NDEF_BT_ENABLED
88 std::shared_ptr<BtData> btData = NdefBtDataParser::CheckBtRecord(msg);
89 if (btData && btData->isValid_) {
90 msgType = NDEF_TYPE_BT;
91 if (!btData->vendorPayload_.empty() && NdefBtDataParser::IsVendorPayloadValid(btData->vendorPayload_)) {
92 // Bt msg for NdefMsg Callback: bt payload len | bt payload | mac addr | dev name
93 ndef = NfcSdkCommon::IntToHexString(btData->vendorPayload_.length() / HEX_BYTE_LEN);
94 ndef.append(btData->vendorPayload_);
95 ndef.append(btData->macAddrOrg_);
96 ndef.append(NfcSdkCommon::StringToHexString(btData->name_));
97 } else {
98 InfoLog("BT vendor payload invalid");
99 ndef = "";
100 }
101 }
102 #endif
103 #ifdef NDEF_WIFI_ENABLED
104 std::shared_ptr<WifiData> wifiData;
105 if (msgType == NDEF_TYPE_NORMAL) {
106 wifiData = NdefWifiDataParser::CheckWifiRecord(msg);
107 if (wifiData && wifiData->isValid_) {
108 msgType = NDEF_TYPE_WIFI;
109 ndef = wifiData->vendorPayload_;
110 }
111 }
112 #endif
113 InfoLog("HandleNdefDispatch, tagUid = %{public}s, msgType = %{public}d",
114 KITS::NfcSdkCommon::CodeMiddlePart(tagUid).c_str(), msgType);
115 if (ndefCb_ != nullptr) {
116 ndefCbRes_ = ndefCb_->OnNdefMsgDiscovered(tagUid, ndef, msgType);
117 }
118 if (ndefCbRes_) {
119 InfoLog("HandleNdefDispatch, is dispatched by ndefMsg callback");
120 return true;
121 }
122 if (msg.empty()) {
123 ErrorLog("HandleNdefDispatch, ndef msg is empty");
124 return false;
125 }
126 #ifdef NDEF_BT_ENABLED
127 if (msgType == NDEF_TYPE_BT) {
128 BtConnectionManager::GetInstance().Initialize(nfcService_);
129 BtConnectionManager::GetInstance().TryPairBt(btData);
130 return true;
131 }
132 #endif
133 #ifdef NDEF_WIFI_ENABLED
134 if (msgType == NDEF_TYPE_WIFI) {
135 WifiConnectionManager::GetInstance().Initialize(nfcService_);
136 WifiConnectionManager::GetInstance().TryConnectWifi(wifiData);
137 return true;
138 }
139 #endif
140 std::shared_ptr<KITS::TagInfo> tagInfo = GetTagInfoFromTag(tagDiscId);
141 if (ndefHarDataParser_ != nullptr && ndefHarDataParser_->TryNdef(msg, tagInfo)) {
142 return true;
143 }
144 return false;
145 }
146
HandleTagFound(uint32_t tagDiscId)147 void TagDispatcher::HandleTagFound(uint32_t tagDiscId)
148 {
149 if (nfcService_ == nullptr || nciTagProxy_.expired() || nfcService_->GetNfcPollingManager().expired()) {
150 ErrorLog("HandleTagFound, invalid state.");
151 return;
152 }
153
154 bool isIsoDep = false;
155 int fieldOnCheckInterval_ = DEFAULT_FIELD_ON_CHECK_DURATION;
156 if (static_cast<int>(nciTagProxy_.lock()->GetConnectedTech(tagDiscId)) ==
157 static_cast<int>(TagTechnology::NFC_ISODEP_TECH)) {
158 fieldOnCheckInterval_ = DEFAULT_ISO_DEP_FIELD_ON_CHECK_DURATION;
159 isIsoDep = true;
160 }
161 DebugLog("HandleTagFound fieldOnCheckInterval_ = %{public}d", fieldOnCheckInterval_);
162
163 ndefCbRes_ = false;
164 std::string ndefMsg = nciTagProxy_.lock()->FindNdefTech(tagDiscId);
165 std::shared_ptr<KITS::NdefMessage> ndefMessage = KITS::NdefMessage::GetNdefMessage(ndefMsg);
166 KITS::TagInfoParcelable* tagInfo = nullptr;
167 do {
168 if (ndefMessage == nullptr) {
169 if (!nciTagProxy_.lock()->Reconnect(tagDiscId)) {
170 nciTagProxy_.lock()->Disconnect(tagDiscId);
171 ErrorLog("HandleTagFound bad connection, tag disconnected");
172 break;
173 }
174 }
175 lastNdefMsg_ = ndefMsg;
176 nciTagProxy_.lock()->StartFieldOnChecking(tagDiscId, fieldOnCheckInterval_);
177 tagInfo = GetTagInfoParcelableFromTag(tagDiscId);
178 if (nfcService_->GetNfcPollingManager().lock()->IsReaderModeEnabled()) {
179 nfcService_->GetNfcPollingManager().lock()->SendTagToReaderApp(tagInfo);
180 break;
181 }
182 if (nfcService_->GetNfcPollingManager().lock()->IsForegroundEnabled()) {
183 nfcService_->GetNfcPollingManager().lock()->SendTagToForeground(tagInfo);
184 break;
185 }
186 ExternalDepsProxy::GetInstance().RegNotificationCallback(nfcService_);
187 if (HandleNdefDispatch(tagDiscId, ndefMsg)) {
188 break;
189 }
190 PublishTagNotification(tagDiscId, isIsoDep);
191 DispatchTag(tagDiscId);
192 break;
193 } while (0);
194 if (tagInfo != nullptr) {
195 delete tagInfo;
196 tagInfo = nullptr;
197 }
198 StartVibratorOnce();
199 }
200
StartVibratorOnce()201 void TagDispatcher::StartVibratorOnce()
202 {
203 if (!ndefCbRes_) {
204 ExternalDepsProxy::GetInstance().StartVibratorOnce();
205 }
206 }
HandleTagLost(uint32_t tagDiscId)207 void TagDispatcher::HandleTagLost(uint32_t tagDiscId)
208 {
209 InfoLog("HandleTagLost, tagDiscId: %{public}d", tagDiscId);
210 }
211
GetTagInfoFromTag(uint32_t tagDiscId)212 std::shared_ptr<KITS::TagInfo> TagDispatcher::GetTagInfoFromTag(uint32_t tagDiscId)
213 {
214 std::vector<int> techList = nciTagProxy_.lock()->GetTechList(tagDiscId);
215 std::string tagUid = nciTagProxy_.lock()->GetTagUid(tagDiscId);
216 std::vector<AppExecFwk::PacMap> tagTechExtras = nciTagProxy_.lock()->GetTechExtrasData(tagDiscId);
217 DebugLog("GetTagInfoFromTag: tag uid = %{public}s, techListLen = %{public}zu, extrasLen = %{public}zu,"
218 "rfID = %{public}d", KITS::NfcSdkCommon::CodeMiddlePart(tagUid).c_str(),
219 techList.size(), tagTechExtras.size(), tagDiscId);
220 return std::make_shared<KITS::TagInfo>(techList, tagTechExtras, tagUid, tagDiscId,
221 nfcService_->GetTagServiceIface());
222 }
223
GetTagInfoParcelableFromTag(uint32_t tagDiscId)224 KITS::TagInfoParcelable* TagDispatcher::GetTagInfoParcelableFromTag(uint32_t tagDiscId)
225 {
226 std::vector<int> techList = nciTagProxy_.lock()->GetTechList(tagDiscId);
227 std::string tagUid = nciTagProxy_.lock()->GetTagUid(tagDiscId);
228 std::vector<AppExecFwk::PacMap> tagTechExtras = nciTagProxy_.lock()->GetTechExtrasData(tagDiscId);
229 DebugLog("GetTagInfoParcelableFromTag: tag uid = %{public}s, techListLen = %{public}zu, extrasLen = %{public}zu,"
230 "rfID = %{public}d", KITS::NfcSdkCommon::CodeMiddlePart(tagUid).c_str(),
231 techList.size(), tagTechExtras.size(), tagDiscId);
232
233 // tagInfo should be deleted at where it is used (HandleTagFound)
234 KITS::TagInfoParcelable* tagInfo = new (std::nothrow) KITS::TagInfoParcelable(techList, tagTechExtras,
235 tagUid, tagDiscId, nfcService_->GetTagServiceIface());
236 return tagInfo;
237 }
238
DispatchTag(uint32_t tagDiscId)239 void TagDispatcher::DispatchTag(uint32_t tagDiscId)
240 {
241 tagInfo_ = GetTagInfoFromTag(tagDiscId);
242 if (tagInfo_ == nullptr) {
243 ErrorLog("DispatchTag: taginfo is null");
244 return;
245 }
246
247 // select the matched applications, try start ability
248 std::vector<int> techList = nciTagProxy_.lock()->GetTechList(tagDiscId);
249 // Record types of read tags.
250 ExternalDepsProxy::GetInstance().WriteTagFoundHiSysEvent(techList);
251 }
252
HandleTagDebounce()253 void TagDispatcher::HandleTagDebounce()
254 {
255 DebugLog("HandleTagDebounce, unimplemented...");
256 }
257
OnNotificationButtonClicked(int notificationId)258 void TagDispatcher::OnNotificationButtonClicked(int notificationId)
259 {
260 InfoLog("notificationId[%{public}d]", notificationId);
261 switch (notificationId) {
262 case NFC_TRANSPORT_CARD_NOTIFICATION_ID: {
263 // start application ability for tag found.
264 if (nfcService_) {
265 ExternalDepsProxy::GetInstance().DispatchTagAbility(tagInfo_, nfcService_->GetTagServiceIface());
266 nfcService_->NotifyMessageToVendor(KITS::TAG_DISPATCH_KEY, "");
267 }
268 break;
269 }
270 case NFC_WIFI_NOTIFICATION_ID: {
271 #ifdef NDEF_WIFI_ENABLED
272 if (nfcService_ && nfcService_->eventHandler_) {
273 nfcService_->eventHandler_->SendEvent(static_cast<uint32_t>(NfcCommonEvent::MSG_WIFI_NTF_CLICKED));
274 }
275 #endif
276 break;
277 }
278 case NFC_BT_NOTIFICATION_ID: {
279 #ifdef NDEF_BT_ENABLED
280 if (nfcService_ && nfcService_->eventHandler_) {
281 nfcService_->eventHandler_->SendEvent(static_cast<uint32_t>(NfcCommonEvent::MSG_BT_NTF_CLICKED));
282 }
283 #endif
284 break;
285 }
286 case NFC_TAG_DEFAULT_NOTIFICATION_ID:
287 // start application ability for tag found.
288 if (nfcService_) {
289 ExternalDepsProxy::GetInstance().DispatchTagAbility(tagInfo_, nfcService_->GetTagServiceIface());
290 nfcService_->NotifyMessageToVendor(KITS::TAG_DISPATCH_KEY, "");
291 }
292 break;
293 case NFC_BROWSER_NOTIFICATION_ID:
294 NdefHarDispatch::GetInstance().OnBrowserOpenLink();
295 break;
296 case NFC_NO_HAP_SUPPORTED_NOTIFICATION_ID:
297 // start AppGallery
298 if (!nciTagProxy_.expired() && nfcService_) {
299 std::string appGalleryBundleName = nciTagProxy_.lock()->GetVendorAppGalleryBundleName();
300 ExternalDepsProxy::GetInstance().DispatchAppGallery(nfcService_->GetTagServiceIface(),
301 appGalleryBundleName);
302 }
303 break;
304 default:
305 WarnLog("unknown notification Id");
306 break;
307 }
308 }
309
PublishTagNotification(uint32_t tagDiscId,bool isIsoDep)310 void TagDispatcher::PublishTagNotification(uint32_t tagDiscId, bool isIsoDep)
311 {
312 NfcNotificationId notificationId = NFC_TAG_DEFAULT_NOTIFICATION_ID;
313 std::string cardName = "";
314 uint8_t cardIndex = INVALID_CARD_INDEX;
315 int balance = INVALID_BALANCE;
316 if (isIsoDep && isodepCardHandler_ != nullptr) {
317 isodepCardHandler_->InitTransportCardInfo();
318 if (isodepCardHandler_->IsSupportedTransportCard(tagDiscId, cardIndex)) {
319 isodepCardHandler_->GetBalance(tagDiscId, cardIndex, balance);
320 if (balance < 0) {
321 WarnLog("failed to get card balance.");
322 } else {
323 isodepCardHandler_->GetCardName(cardIndex, cardName);
324 notificationId = NFC_TRANSPORT_CARD_NOTIFICATION_ID;
325 }
326 }
327 }
328 ExternalDepsProxy::GetInstance().PublishNfcNotification(notificationId, cardName, balance);
329 }
330 } // namespace TAG
331 } // namespace NFC
332 } // namespace OHOS
333