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