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