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