• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     DebugLog("HandleTagFound fieldOnCheckInterval_ = %{public}d", fieldOnCheckInterval_);
169 
170     ndefCbRes_ = false;
171     std::string ndefMsg = nciTagProxy_.lock()->FindNdefTech(tagDiscId);
172     std::shared_ptr<KITS::NdefMessage> ndefMessage = KITS::NdefMessage::GetNdefMessage(ndefMsg);
173     KITS::TagInfoParcelable* tagInfo = nullptr;
174     do {
175         if (ndefMessage == nullptr) {
176             if (!nciTagProxy_.lock()->Reconnect(tagDiscId)) {
177                 nciTagProxy_.lock()->Disconnect(tagDiscId);
178                 ErrorLog("HandleTagFound bad connection, tag disconnected");
179                 break;
180             }
181         }
182         lastNdefMsg_ = ndefMsg;
183         nciTagProxy_.lock()->StartFieldOnChecking(tagDiscId, fieldOnCheckInterval_);
184         tagInfo = GetTagInfoParcelableFromTag(tagDiscId);
185         if (nfcService_->GetNfcPollingManager().lock()->IsReaderModeEnabled()) {
186             nfcService_->GetNfcPollingManager().lock()->SendTagToReaderApp(tagInfo);
187             break;
188         }
189         if (nfcService_->GetNfcPollingManager().lock()->IsForegroundEnabled()) {
190             nfcService_->GetNfcPollingManager().lock()->SendTagToForeground(tagInfo);
191             break;
192         }
193         ExternalDepsProxy::GetInstance().RegNotificationCallback(nfcService_);
194         if (HandleNdefDispatch(tagDiscId, ndefMsg)) {
195             break;
196         }
197         PublishTagNotification(tagDiscId, isIsoDep);
198         DispatchTag(tagDiscId);
199         break;
200     } while (0);
201     if (tagInfo != nullptr) {
202         delete tagInfo;
203         tagInfo = nullptr;
204     }
205 #ifndef NFC_VIBRATOR_DISABLED
206     StartVibratorOnce();
207 #endif
208 }
209 
StartVibratorOnce()210 void TagDispatcher::StartVibratorOnce()
211 {
212     if (!ndefCbRes_) {
213         ExternalDepsProxy::GetInstance().StartVibratorOnce();
214     }
215 }
HandleTagLost(uint32_t tagDiscId)216 void TagDispatcher::HandleTagLost(uint32_t tagDiscId)
217 {
218     InfoLog("HandleTagLost, tagDiscId: %{public}d", tagDiscId);
219 }
220 
GetTagInfoFromTag(uint32_t tagDiscId)221 std::shared_ptr<KITS::TagInfo> TagDispatcher::GetTagInfoFromTag(uint32_t tagDiscId)
222 {
223     if (nciTagProxy_.expired()) {
224         ErrorLog("nciTagProxy_ nullptr");
225         return nullptr;
226     }
227     std::vector<int> techList = nciTagProxy_.lock()->GetTechList(tagDiscId);
228     std::string tagUid = nciTagProxy_.lock()->GetTagUid(tagDiscId);
229     std::vector<AppExecFwk::PacMap> tagTechExtras = nciTagProxy_.lock()->GetTechExtrasData(tagDiscId);
230     DebugLog("GetTagInfoFromTag: tag uid = %{public}s, techListLen = %{public}zu, extrasLen = %{public}zu,"
231         "rfID = %{public}d", KITS::NfcSdkCommon::CodeMiddlePart(tagUid).c_str(),
232         techList.size(), tagTechExtras.size(), tagDiscId);
233     return std::make_shared<KITS::TagInfo>(techList, tagTechExtras, tagUid, tagDiscId,
234         nfcService_->GetTagServiceIface());
235 }
236 
GetTagInfoParcelableFromTag(uint32_t tagDiscId)237 KITS::TagInfoParcelable* TagDispatcher::GetTagInfoParcelableFromTag(uint32_t tagDiscId)
238 {
239     if (nciTagProxy_.expired()) {
240         ErrorLog("nciTagProxy_ nullptr");
241         return nullptr;
242     }
243     std::vector<int> techList = nciTagProxy_.lock()->GetTechList(tagDiscId);
244     std::string tagUid = nciTagProxy_.lock()->GetTagUid(tagDiscId);
245     std::vector<AppExecFwk::PacMap> tagTechExtras = nciTagProxy_.lock()->GetTechExtrasData(tagDiscId);
246     DebugLog("GetTagInfoParcelableFromTag: tag uid = %{public}s, techListLen = %{public}zu, extrasLen = %{public}zu,"
247         "rfID = %{public}d", KITS::NfcSdkCommon::CodeMiddlePart(tagUid).c_str(),
248         techList.size(), tagTechExtras.size(), tagDiscId);
249 
250     // tagInfo should be deleted at where it is used (HandleTagFound)
251     KITS::TagInfoParcelable* tagInfo = new (std::nothrow) KITS::TagInfoParcelable(techList, tagTechExtras,
252         tagUid, tagDiscId, nfcService_->GetTagServiceIface());
253     return tagInfo;
254 }
255 
DispatchTag(uint32_t tagDiscId)256 void TagDispatcher::DispatchTag(uint32_t tagDiscId)
257 {
258     tagInfo_ = GetTagInfoFromTag(tagDiscId);
259     if (tagInfo_ == nullptr) {
260         ErrorLog("DispatchTag: taginfo is null");
261         return;
262     }
263 
264     // select the matched applications, try start ability
265     std::vector<int> techList = nciTagProxy_.lock()->GetTechList(tagDiscId);
266     // Record types of read tags.
267     ExternalDepsProxy::GetInstance().WriteTagFoundHiSysEvent(techList);
268 }
269 
HandleTagDebounce()270 void TagDispatcher::HandleTagDebounce()
271 {
272     DebugLog("HandleTagDebounce, unimplemented...");
273 }
274 
OnNotificationButtonClicked(int notificationId)275 void TagDispatcher::OnNotificationButtonClicked(int notificationId)
276 {
277     InfoLog("notificationId[%{public}d]", notificationId);
278     switch (notificationId) {
279         case NFC_TRANSPORT_CARD_NOTIFICATION_ID: {
280             // start application ability for tag found.
281             if (nfcService_) {
282                 ExternalDepsProxy::GetInstance().DispatchTagAbility(tagInfo_, nfcService_->GetTagServiceIface());
283                 nfcService_->NotifyMessageToVendor(KITS::TAG_DISPATCH_KEY, "");
284             }
285             break;
286         }
287         case NFC_WIFI_NOTIFICATION_ID: {
288 #ifdef NDEF_WIFI_ENABLED
289             if (nfcService_ && nfcService_->eventHandler_) {
290                 nfcService_->eventHandler_->SendEvent(static_cast<uint32_t>(NfcCommonEvent::MSG_WIFI_NTF_CLICKED));
291             }
292 #endif
293             break;
294         }
295         case NFC_BT_NOTIFICATION_ID: {
296 #ifdef NDEF_BT_ENABLED
297             if (nfcService_ && nfcService_->eventHandler_) {
298                 nfcService_->eventHandler_->SendEvent(static_cast<uint32_t>(NfcCommonEvent::MSG_BT_NTF_CLICKED));
299             }
300 #endif
301             break;
302         }
303         case NFC_TAG_DEFAULT_NOTIFICATION_ID:
304             // start application ability for tag found.
305             if (nfcService_) {
306                 ExternalDepsProxy::GetInstance().DispatchTagAbility(tagInfo_, nfcService_->GetTagServiceIface());
307                 nfcService_->NotifyMessageToVendor(KITS::TAG_DISPATCH_KEY, "");
308             }
309             break;
310         case NFC_NO_HAP_SUPPORTED_NOTIFICATION_ID:
311             // start AppGallery
312             if (!nciTagProxy_.expired() && nfcService_) {
313                 std::string appGalleryBundleName = nciTagProxy_.lock()->GetVendorAppGalleryBundleName();
314                 ExternalDepsProxy::GetInstance().DispatchAppGallery(nfcService_->GetTagServiceIface(),
315                                                                     appGalleryBundleName);
316             }
317             break;
318         default:
319             WarnLog("unknown notification Id");
320             break;
321     }
322 }
323 
PublishTagNotification(uint32_t tagDiscId,bool isIsoDep)324 void TagDispatcher::PublishTagNotification(uint32_t tagDiscId, bool isIsoDep)
325 {
326     NfcNotificationId notificationId = NFC_TAG_DEFAULT_NOTIFICATION_ID;
327     std::string cardName = "";
328     uint8_t cardIndex = INVALID_CARD_INDEX;
329     int balance = INVALID_BALANCE;
330     if (isIsoDep && isodepCardHandler_ != nullptr) {
331         isodepCardHandler_->InitTransportCardInfo();
332         if (isodepCardHandler_->IsSupportedTransportCard(tagDiscId, cardIndex)) {
333             isodepCardHandler_->GetBalance(tagDiscId, cardIndex, balance);
334             if (balance < 0) {
335                 WarnLog("failed to get card balance.");
336             } else {
337                 isodepCardHandler_->GetCardName(cardIndex, cardName);
338                 notificationId = NFC_TRANSPORT_CARD_NOTIFICATION_ID;
339             }
340         }
341     }
342     ExternalDepsProxy::GetInstance().PublishNfcNotification(notificationId, cardName, balance);
343 }
344 }  // namespace TAG
345 }  // namespace NFC
346 }  // namespace OHOS
347