• 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 #include <functional>
17 #include "ability_manager_client.h"
18 #include "app_data_parser.h"
19 #include "itag_host.h"
20 #include "loghelper.h"
21 #include "ndef_message.h"
22 #include "nfc_sdk_common.h"
23 #include "want.h"
24 #include "vibrator_agent.h"
25 
26 namespace OHOS {
27 using TagHostMapIter = std::map<int, std::shared_ptr<NFC::NCI::ITagHost>>::iterator;
28 namespace NFC {
29 namespace TAG {
30 using OHOS::NFC::KITS::TagTechnology;
TagDispatcher(std::shared_ptr<NFC::INfcService> nfcService)31 TagDispatcher::TagDispatcher(std::shared_ptr<NFC::INfcService> nfcService)
32     : nfcService_(nfcService),
33     lastNdefMsg_("")
34 {
35 }
36 
~TagDispatcher()37 TagDispatcher::~TagDispatcher()
38 {
39     std::lock_guard<std::mutex> guard(mutex_);
40 }
41 
TagDisconnectedCallback(int tagRfDiscId)42 void TagDispatcher::TagDisconnectedCallback(int tagRfDiscId)
43 {
44     UnregisterTagHost(tagRfDiscId);
45     InfoLog("Tag disconnected");
46 }
47 
HandleTagFound(std::shared_ptr<NCI::ITagHost> tag)48 int TagDispatcher::HandleTagFound(std::shared_ptr<NCI::ITagHost> tag)
49 {
50     if (tag == nullptr || nfcService_ == nullptr) {
51         ErrorLog("HandleTagFound, invalid state.");
52         return 0;
53     }
54     static NCI::ITagHost::TagDisconnectedCallBack callback =
55         std::bind(&TagDispatcher::TagDisconnectedCallback, this, std::placeholders::_1);
56     OHOS::Sensors::StartVibratorOnce(DEFAULT_MOTOR_VIBRATOR_ONCE);
57     int fieldOnCheckInterval_ = DEFAULT_FIELD_ON_CHECK_DURATION;
58     if (tag->GetConnectedTech() == static_cast<int>(TagTechnology::NFC_ISODEP_TECH)) {
59         fieldOnCheckInterval_ = DEFAULT_ISO_DEP_FIELD_ON_CHECK_DURATION;
60     }
61     DebugLog("fieldOnCheckInterval_ = %{public}d", fieldOnCheckInterval_);
62 
63     // skip ndef checking for foreground dispatch scenario
64     if (nfcService_->IsForegroundEnabled()) {
65         RegisterTagHost(tag);
66         tag->OnFieldChecking(callback, fieldOnCheckInterval_);
67         nfcService_->SendTagToForeground(GetTagInfoParcelableFromTag(tag));
68         return 0;
69     }
70     std::string ndefMsg = tag->ReadNdef();
71     std::shared_ptr<KITS::NdefMessage> ndefMessage = KITS::NdefMessage::GetNdefMessage(ndefMsg);
72     if (ndefMessage == nullptr) {
73         if (!tag->Reconnect()) {
74             tag->Disconnect();
75             ErrorLog("HandleTagFound bad connection, tag disconnected");
76             return 0;
77         }
78     }
79     lastNdefMsg_ = ndefMsg;
80     RegisterTagHost(tag);
81     tag->OnFieldChecking(callback, fieldOnCheckInterval_);
82     DispatchTag(tag);
83     return 0;
84 }
85 
GetTagInfoFromTag(std::shared_ptr<NCI::ITagHost> tag)86 std::shared_ptr<KITS::TagInfo> TagDispatcher::GetTagInfoFromTag(std::shared_ptr<NCI::ITagHost> tag)
87 {
88     std::vector<int> techList = tag->GetTechList();
89     std::string tagUid = tag->GetTagUid();
90     std::vector<AppExecFwk::PacMap> tagTechExtras = tag->GetTechExtrasData();
91     int tagRfDiscId = tag->GetTagRfDiscId();
92     DebugLog("GetTagInfoFromTag: techListLen = %{public}zu, extrasLen = %{public}zu, tagUid = %{private}s,"
93         " rfID = %{public}d", techList.size(), tagTechExtras.size(), tagUid.c_str(), tagRfDiscId);
94     return std::make_shared<KITS::TagInfo>(techList, tagTechExtras, tagUid, tagRfDiscId,
95         nfcService_->GetTagServiceIface());
96 }
97 
GetTagInfoParcelableFromTag(std::shared_ptr<NCI::ITagHost> tag)98 KITS::TagInfoParcelable TagDispatcher::GetTagInfoParcelableFromTag(std::shared_ptr<NCI::ITagHost> tag)
99 {
100     std::vector<int> techList = tag->GetTechList();
101     std::string tagUid = tag->GetTagUid();
102     std::vector<AppExecFwk::PacMap> tagTechExtras = tag->GetTechExtrasData();
103     int tagRfDiscId = tag->GetTagRfDiscId();
104     DebugLog("GetTagInfoParcelableFromTag: techListLen = %{public}zu, extrasLen = %{public}zu, tagUid = %{private}s,"
105         " rfID = %{public}d", techList.size(), tagTechExtras.size(), tagUid.c_str(), tagRfDiscId);
106     KITS::TagInfoParcelable *tagInfo = new (std::nothrow) KITS::TagInfoParcelable(techList, tagTechExtras,
107         tagUid, tagRfDiscId, nfcService_->GetTagServiceIface());
108     return *(tagInfo);
109 }
110 
DispatchTag(std::shared_ptr<NCI::ITagHost> tag)111 void TagDispatcher::DispatchTag(std::shared_ptr<NCI::ITagHost> tag)
112 {
113     if (tag == nullptr) {
114         ErrorLog("DispatchTag: tag is null");
115         return;
116     }
117     std::shared_ptr<KITS::TagInfo> tagInfo = GetTagInfoFromTag(tag);
118     if (tagInfo == nullptr) {
119         ErrorLog("DispatchTag: taginfo is null");
120         return;
121     }
122 
123     // select the matched applications, try start ability
124     std::vector<int> techList = tag->GetTechList();
125     std::vector<ElementName> elements = AppDataParser::GetInstance().GetDispatchTagAppsByTech(techList);
126     InfoLog("DispatchTag: try start ability elements size = %{public}zu", elements.size());
127     if (elements.size() == 0) {
128         return;
129     }
130     if (elements.size() == TAG_APP_MATCHED_SIZE_SINGLE) {
131         DispatchAbilitySingleApp(elements[0], tagInfo);
132     } else {
133         DispatchAbilityMultiApp(tagInfo);
134     }
135 }
136 
HandleTagDebounce()137 void TagDispatcher::HandleTagDebounce()
138 {
139     DebugLog("HandleTagDebounce, unimplimentation...");
140 }
141 
FindTagHost(int rfDiscId)142 std::weak_ptr<NCI::ITagHost> TagDispatcher::FindTagHost(int rfDiscId)
143 {
144     std::lock_guard<std::mutex> lock(mutex_);
145     TagHostMapIter tagHost = tagHostMap_.find(rfDiscId);
146     if (tagHost == tagHostMap_.end()) {
147         WarnLog("FindTagHost, rfDiscId: %{public}d not found", rfDiscId);
148         return std::shared_ptr<NCI::ITagHost>();
149     }
150     return tagHost->second;
151 }
152 
FindAndRemoveTagHost(int rfDiscId)153 std::shared_ptr<NCI::ITagHost> TagDispatcher::FindAndRemoveTagHost(int rfDiscId)
154 {
155     std::lock_guard<std::mutex> lock(mutex_);
156     TagHostMapIter tagHost = tagHostMap_.find(rfDiscId);
157     std::shared_ptr<NCI::ITagHost> temp = nullptr;
158     if (tagHost == tagHostMap_.end()) {
159         WarnLog("FindAndRemoveTagHost, rfDiscId: %{public}d not found", rfDiscId);
160     } else {
161         temp = tagHost->second;
162         tagHostMap_.erase(rfDiscId);
163         InfoLog("FindAndRemoveTagHost, rfDiscId: %{public}d removed", rfDiscId);
164     }
165     return temp;
166 }
167 
RegisterTagHost(std::shared_ptr<NCI::ITagHost> tag)168 void TagDispatcher::RegisterTagHost(std::shared_ptr<NCI::ITagHost> tag)
169 {
170     std::lock_guard<std::mutex> lock(mutex_);
171     tagHostMap_.insert(make_pair(tag->GetTagRfDiscId(), tag));
172     InfoLog("RegisterTagHost, rfDiscId: %{public}d", tag->GetTagRfDiscId());
173 }
174 
UnregisterTagHost(int rfDiscId)175 void TagDispatcher::UnregisterTagHost(int rfDiscId)
176 {
177     std::lock_guard<std::mutex> lock(mutex_);
178     tagHostMap_.erase(rfDiscId);
179     InfoLog("UnregisterTagHost, rfDiscId: %{public}d", rfDiscId);
180 }
181 
SetWantExtraParam(std::shared_ptr<KITS::TagInfo> & tagInfo,AAFwk::Want & want)182 static void SetWantExtraParam(std::shared_ptr<KITS::TagInfo>& tagInfo, AAFwk::Want &want)
183 {
184     // put extra data for all included technology, extra data used by 3rd party applications.
185     if (tagInfo == nullptr) {
186         ErrorLog("SetWantExtraParam tagInfo is null");
187         return;
188     }
189     want.SetParam("uid", tagInfo->GetTagUid());
190     want.SetParam("technology", tagInfo->GetTagTechList());
191     want.SetParam("tagRfDiscId", tagInfo->GetTagRfDiscId());
192 
193     std::vector<int> techList = tagInfo->GetTagTechList();
194     for (size_t i = 0; i < techList.size(); i++) {
195         AppExecFwk::PacMap extra = tagInfo->GetTechExtrasByIndex(i);
196         if (techList[i] == static_cast<int>(TagTechnology::NFC_A_TECH)) {
197             want.SetParam(KITS::TagInfo::SAK, extra.GetIntValue(KITS::TagInfo::SAK, 0));
198             want.SetParam(KITS::TagInfo::ATQA, extra.GetStringValue(KITS::TagInfo::ATQA, ""));
199         } else if (techList[i] == static_cast<int>(TagTechnology::NFC_B_TECH)) {
200             want.SetParam(KITS::TagInfo::APP_DATA, extra.GetStringValue(KITS::TagInfo::APP_DATA, ""));
201             want.SetParam(KITS::TagInfo::PROTOCOL_INFO, extra.GetStringValue(KITS::TagInfo::PROTOCOL_INFO, ""));
202         } else if (techList[i] == static_cast<int>(TagTechnology::NFC_F_TECH)) {
203             want.SetParam(KITS::TagInfo::NFCF_SC, extra.GetStringValue(KITS::TagInfo::NFCF_SC, ""));
204             want.SetParam(KITS::TagInfo::NFCF_PMM, extra.GetStringValue(KITS::TagInfo::NFCF_PMM, ""));
205         } else if (techList[i] == static_cast<int>(TagTechnology::NFC_V_TECH)) {
206             want.SetParam(KITS::TagInfo::RESPONSE_FLAGS, extra.GetIntValue(KITS::TagInfo::RESPONSE_FLAGS, 0));
207             want.SetParam(KITS::TagInfo::DSF_ID, extra.GetIntValue(KITS::TagInfo::DSF_ID, 0));
208         } else if (techList[i] == static_cast<int>(TagTechnology::NFC_ISODEP_TECH)) {
209             want.SetParam(KITS::TagInfo::HISTORICAL_BYTES, extra.GetStringValue(KITS::TagInfo::HISTORICAL_BYTES, ""));
210             want.SetParam(KITS::TagInfo::HILAYER_RESPONSE, extra.GetStringValue(KITS::TagInfo::HILAYER_RESPONSE, ""));
211         } else if (techList[i] == static_cast<int>(TagTechnology::NFC_MIFARE_ULTRALIGHT_TECH)) {
212             want.SetParam(KITS::TagInfo::MIFARE_ULTRALIGHT_C_TYPE,
213                 extra.GetBooleanValue(KITS::TagInfo::MIFARE_ULTRALIGHT_C_TYPE, false));
214         } else if (techList[i] == static_cast<int>(TagTechnology::NFC_NDEF_TECH)) {
215             // set ndef message/type/max size/read mode for ndef tag
216             want.SetParam(KITS::TagInfo::NDEF_MSG, extra.GetStringValue(KITS::TagInfo::NDEF_MSG, ""));
217             want.SetParam(KITS::TagInfo::NDEF_FORUM_TYPE, extra.GetIntValue(KITS::TagInfo::NDEF_FORUM_TYPE, 0));
218             want.SetParam(KITS::TagInfo::NDEF_TAG_LENGTH, extra.GetIntValue(KITS::TagInfo::NDEF_TAG_LENGTH, 0));
219             want.SetParam(KITS::TagInfo::NDEF_TAG_MODE, extra.GetIntValue(KITS::TagInfo::NDEF_TAG_MODE, 0));
220         }
221     }
222 }
223 
DispatchAbilityMultiApp(std::shared_ptr<KITS::TagInfo> tagInfo)224 void TagDispatcher::DispatchAbilityMultiApp(std::shared_ptr<KITS::TagInfo> tagInfo)
225 {
226     if (tagInfo == nullptr) {
227         ErrorLog("DispatchAbilityMultiApp tagInfo is null");
228         return;
229     }
230 
231     InfoLog("DispatchAbilityMultiApp for app");
232     AAFwk::Want want;
233     want.SetParam("remoteTagService", nfcService_->GetTagServiceIface());
234     SetWantExtraParam(tagInfo, want);
235 
236     // pull multi app page by skill.uris
237     want.SetAction(KITS::ACTION_TAG_FOUND);
238 
239     std::vector<std::string> techArray;
240     const std::string tagTechStr = "tag-tech/"; // exmaple: "tag-tech/NfcA"
241     for (const auto& tagTech : tagInfo->GetTagTechList()) {
242         if (tagTech < static_cast<int>(TagTechnology::NFC_A_TECH) ||
243             tagTech > static_cast<int>(TagTechnology::NFC_MIFARE_ULTRALIGHT_TECH)) {
244             WarnLog("DispatchAbilityMultiApp tagTech(%{public}d) out of range. ", tagTech);
245             continue;
246         }
247         techArray.push_back(tagTechStr + KITS::TagInfo::GetStringTech(tagTech));
248     }
249     want.SetParam(AAFwk::Want::PARAM_ABILITY_URITYPES, techArray);
250 
251     if (AAFwk::AbilityManagerClient::GetInstance() == nullptr) {
252         ErrorLog("DispatchAbilityMultiApp AbilityManagerClient is null");
253         return;
254     }
255 
256     AAFwk::AbilityManagerClient::GetInstance()->StartAbility(want);
257     InfoLog("DispatchAbilityMultiApp call StartAbility end.");
258 }
259 
DispatchAbilitySingleApp(ElementName & element,std::shared_ptr<KITS::TagInfo> tagInfo)260 void TagDispatcher::DispatchAbilitySingleApp(ElementName &element,
261     std::shared_ptr<KITS::TagInfo> tagInfo)
262 {
263     if (element.GetBundleName().empty()) {
264         ErrorLog("DispatchAbilitySingleApp element empty");
265         return;
266     }
267 
268     InfoLog("DispatchAbilitySingleApp for app %{public}s, ability = %{public}s", element.GetBundleName().c_str(),
269         element.GetAbilityName().c_str());
270     AAFwk::Want want;
271     want.SetElement(element);
272     want.SetParam("remoteTagService", nfcService_->GetTagServiceIface());
273     SetWantExtraParam(tagInfo, want);
274 
275     if (AAFwk::AbilityManagerClient::GetInstance() == nullptr) {
276         ErrorLog("DispatchAbilitySingleApp AbilityManagerClient is null");
277         return;
278     }
279 
280     AAFwk::AbilityManagerClient::GetInstance()->StartAbility(want);
281     InfoLog("DispatchAbilitySingleApp call StartAbility end.");
282 }
283 }  // namespace TAG
284 }  // namespace NFC
285 }  // namespace OHOS
286