1 /*
2 * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development 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 "app_data_parser.h"
16 #include "common_event_handler.h"
17 #include "common_event_manager.h"
18 #include "iservice_registry.h"
19 #include "system_ability_definition.h"
20 #include "accesstoken_kit.h"
21 #include "permission_tools.h"
22
23 namespace OHOS {
24 namespace NFC {
25 const std::string KEY_TAG_TECH = "tag-tech";
26 const std::string KEY_PAYMENT_AID = "payment-aid";
27 const std::string KEY_OHTER_AID = "other-aid";
28 const int USER_ID = 100;
29 sptr<AppExecFwk::IBundleMgr> bundleMgrProxy_;
30 static AppDataParser appDataParser_;
31
AppDataParser()32 AppDataParser::AppDataParser()
33 {
34 g_tagAppAndTechMap.clear();
35 g_hceAppAndAidMap.clear();
36 }
37
~AppDataParser()38 AppDataParser::~AppDataParser()
39 {
40 }
41
GetInstance()42 AppDataParser& AppDataParser::GetInstance()
43 {
44 return appDataParser_;
45 }
46
GetBundleMgrProxy()47 sptr<AppExecFwk::IBundleMgr> AppDataParser::GetBundleMgrProxy()
48 {
49 sptr<ISystemAbilityManager> systemAbilityManager =
50 SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
51 if (!systemAbilityManager) {
52 ErrorLog("GetBundleMgrProxy, systemAbilityManager is null");
53 return nullptr;
54 }
55 sptr<IRemoteObject> remoteObject = systemAbilityManager->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
56 if (!remoteObject) {
57 ErrorLog("GetBundleMgrProxy, remoteObject is null");
58 return nullptr;
59 }
60 return iface_cast<AppExecFwk::IBundleMgr>(remoteObject);
61 }
62
HandleAppAddOrChangedEvent(std::shared_ptr<EventFwk::CommonEventData> data)63 void AppDataParser::HandleAppAddOrChangedEvent(std::shared_ptr<EventFwk::CommonEventData> data)
64 {
65 if (data == nullptr) {
66 ErrorLog("HandleAppAddOrChangedEvent, invalid data.");
67 return;
68 }
69 ElementName element = data->GetWant().GetElement();
70 std::string bundleName = element.GetBundleName();
71 if (bundleName.empty()) {
72 ErrorLog("HandleAppAddOrChangedEvent, invaid bundleName.");
73 return;
74 }
75 DebugLog("HandleAppAddOrChangedEvent bundlename: %{public}s", bundleName.c_str());
76 UpdateAppListInfo(element, KITS::ACTION_TAG_FOUND);
77 UpdateAppListInfo(element, KITS::ACTION_HOST_APDU_SERVICE);
78 }
79
HandleAppRemovedEvent(std::shared_ptr<EventFwk::CommonEventData> data)80 void AppDataParser::HandleAppRemovedEvent(std::shared_ptr<EventFwk::CommonEventData> data)
81 {
82 if (data == nullptr) {
83 ErrorLog("HandleAppRemovedEvent, invalid data.");
84 return;
85 }
86 ElementName element = data->GetWant().GetElement();
87 std::string bundleName = element.GetBundleName();
88 if (bundleName.empty()) {
89 ErrorLog("HandleAppRemovedEvent, invalid bundleName.");
90 return;
91 }
92 DebugLog("HandleAppRemovedEvent, bundleName %{public}s tag size %{public}zu, hce size %{public}zu",
93 bundleName.c_str(),
94 g_tagAppAndTechMap.size(),
95 g_hceAppAndAidMap.size());
96 RemoveTagAppInfo(element);
97 RemoveHceAppInfo(element);
98 }
99
VerifyHapPermission(const std::string bundleName,const std::string action)100 bool AppDataParser::VerifyHapPermission(const std::string bundleName, const std::string action)
101 {
102 std::string permissionNfc;
103 OHOS::Security::AccessToken::AccessTokenID tokenID;
104 std::map<std::string, std::string> permissionMap = {
105 {KITS::ACTION_TAG_FOUND, TAG_PERM},
106 {KITS::ACTION_HOST_APDU_SERVICE, CARD_EMU_PERM}
107 };
108 std::map<std::string, std::string>::iterator it = permissionMap.find(action.c_str());
109 if (it != permissionMap.end()) {
110 permissionNfc = it->second;
111 } else {
112 ErrorLog("VerifyHapPermission, action no in map!");
113 return false;
114 }
115 tokenID= OHOS::Security::AccessToken::AccessTokenKit::GetHapTokenID(USER_ID, bundleName, 0);
116 int result = OHOS::Security::AccessToken::AccessTokenKit::VerifyAccessToken(tokenID, permissionNfc);
117 if (result != OHOS::Security::AccessToken::PERMISSION_GRANTED) {
118 ErrorLog("bundleName %{public}s no permission %{public}s", bundleName.c_str(), permissionNfc.c_str());
119 return false;
120 }
121 return true;
122 }
123
QueryAbilityInfos(const std::string action,std::vector<AbilityInfo> & abilityInfos,std::vector<ExtensionAbilityInfo> & extensionInfos)124 void AppDataParser::QueryAbilityInfos(const std::string action, std::vector<AbilityInfo> &abilityInfos,
125 std::vector<ExtensionAbilityInfo> &extensionInfos)
126 {
127 if (bundleMgrProxy_ == nullptr) {
128 bundleMgrProxy_ = GetBundleMgrProxy();
129 }
130 if (bundleMgrProxy_ == nullptr) {
131 ErrorLog("QueryAbilityInfos, bundleMgrProxy_ is nullptr.");
132 return;
133 }
134 AAFwk::Want want;
135 want.SetAction(action);
136 want.SetType("*/*"); // skip the type, matched action only.
137 bool withDefault = false;
138 auto abilityInfoFlag = AppExecFwk::AbilityInfoFlag::GET_ABILITY_INFO_DEFAULT
139 | AppExecFwk::AbilityInfoFlag::GET_ABILITY_INFO_WITH_SKILL_URI;
140 if (!bundleMgrProxy_->ImplicitQueryInfos(want, abilityInfoFlag, USER_ID, withDefault,
141 abilityInfos, extensionInfos)) {
142 WarnLog("QueryAbilityInfos, query none for action %{public}s", action.c_str());
143 return;
144 }
145 }
146
UpdateAppListInfo(ElementName & element,const std::string action)147 bool AppDataParser::UpdateAppListInfo(ElementName &element, const std::string action)
148 {
149 if (action.compare(KITS::ACTION_TAG_FOUND) != 0 && action.compare(KITS::ACTION_HOST_APDU_SERVICE) != 0) {
150 ErrorLog("UpdateAppListInfo, ignore action = %{public}s", action.c_str());
151 return false;
152 }
153 std::string bundleName = element.GetBundleName();
154 if (!VerifyHapPermission(bundleName, action)) {
155 ErrorLog("Hap have no permission for action = %{public}s", action.c_str());
156 return false;
157 }
158
159 // query the applications infos that're matched with the acitons.
160 std::vector<AbilityInfo> abilityInfos;
161 std::vector<ExtensionAbilityInfo> extensionAbilityInfos;
162 QueryAbilityInfos(action, abilityInfos, extensionAbilityInfos);
163 for (auto& abilityInfo : abilityInfos) {
164 if (bundleName.empty() || bundleName.compare(abilityInfo.bundleName) != 0) {
165 continue;
166 }
167 if (action.compare(KITS::ACTION_TAG_FOUND) == 0) {
168 UpdateTagAppList(abilityInfo, element);
169 }
170 if (action.compare(KITS::ACTION_HOST_APDU_SERVICE) == 0) {
171 UpdateHceAppList(abilityInfo, element);
172 }
173 }
174 return true;
175 }
176
InitAppListByAction(const std::string action)177 bool AppDataParser::InitAppListByAction(const std::string action)
178 {
179 // query the applications infos that're matched with the acitons.
180 std::vector<AbilityInfo> abilityInfos;
181 std::vector<ExtensionAbilityInfo> extensionAbilityInfos;
182 QueryAbilityInfos(action, abilityInfos, extensionAbilityInfos);
183 if (KITS::ACTION_TAG_FOUND.compare(action) == 0) {
184 for (auto& abilityInfo : abilityInfos) {
185 ElementName element(abilityInfo.deviceId, abilityInfo.bundleName, abilityInfo.name,
186 abilityInfo.moduleName);
187 UpdateTagAppList(abilityInfo, element);
188 }
189 } else if (KITS::ACTION_HOST_APDU_SERVICE.compare(action) == 0) {
190 for (auto& abilityInfo : abilityInfos) {
191 ElementName element(abilityInfo.deviceId, abilityInfo.bundleName, abilityInfo.name,
192 abilityInfo.moduleName);
193 UpdateHceAppList(abilityInfo, element);
194 }
195 } else {
196 WarnLog("InitAppListByAction,unknown action = %{public}s", action.c_str());
197 }
198 return true;
199 }
200
IsMatchedByBundleName(ElementName & src,ElementName & target)201 bool AppDataParser::IsMatchedByBundleName(ElementName &src, ElementName &target)
202 {
203 if (src.GetBundleName().compare(target.GetBundleName()) == 0) {
204 return true;
205 }
206 return false;
207 }
208
GetMatchedTagKeyElement(ElementName & element)209 ElementName AppDataParser::GetMatchedTagKeyElement(ElementName &element)
210 {
211 ElementName emptyElement;
212 std::vector<TagAppTechInfo>::iterator iter;
213 for (iter = g_tagAppAndTechMap.begin(); iter != g_tagAppAndTechMap.end(); ++iter) {
214 if (IsMatchedByBundleName(element, (*iter).element)) {
215 return (*iter).element;
216 }
217 }
218 return emptyElement;
219 }
220
GetMatchedHceKeyElement(ElementName & element)221 ElementName AppDataParser::GetMatchedHceKeyElement(ElementName &element)
222 {
223 ElementName emptyElement;
224 std::vector<HceAppAidInfo>::iterator iter;
225 for (iter = g_hceAppAndAidMap.begin(); iter != g_hceAppAndAidMap.end(); ++iter) {
226 if (IsMatchedByBundleName(element, (*iter).element)) {
227 return (*iter).element;
228 }
229 }
230 return emptyElement;
231 }
232
UpdateTagAppList(AbilityInfo & abilityInfo,ElementName & element)233 void AppDataParser::UpdateTagAppList(AbilityInfo &abilityInfo, ElementName &element)
234 {
235 if (!GetMatchedTagKeyElement(element).GetBundleName().empty()) {
236 WarnLog("UpdateTagAppList, rm duplicated app %{public}s", element.GetBundleName().c_str());
237 RemoveTagAppInfo(element);
238 }
239 std::vector<std::string> valueList;
240 for (auto& data : abilityInfo.metadata) {
241 if (KEY_TAG_TECH.compare(data.name) == 0) {
242 valueList.emplace_back(data.value);
243 DebugLog("UpdateTagAppList from metadata, push tech %{public}s", data.value.c_str());
244 }
245 }
246 for (auto& data : abilityInfo.metaData.customizeData) {
247 if (KEY_TAG_TECH.compare(data.name) == 0) {
248 valueList.emplace_back(data.value);
249 DebugLog("UpdateTagAppList from customizeData, push tech %{public}s", data.value.c_str());
250 }
251 }
252 for (auto& uri : abilityInfo.skillUri) {
253 if (uri.type.empty()) {
254 continue;
255 }
256 // format example: "type": "tag-tech/NfcA"
257 auto pos = uri.type.find("/");
258 if (pos == std::string::npos) {
259 ErrorLog("UpdateTagAppList from skillUri, separator not found %{public}s", uri.type.c_str());
260 continue;
261 }
262 std::string tech = uri.type.substr(0, pos);
263 if (KEY_TAG_TECH.compare(tech) != 0) {
264 ErrorLog("UpdateTagAppList KEY_TAG_TECH for %{public}s", tech.c_str());
265 continue;
266 }
267 std::string nfcType = uri.type.substr(pos + 1, uri.type.size());
268 if (std::find(valueList.begin(), valueList.end(), nfcType) == valueList.end()) {
269 valueList.emplace_back(nfcType);
270 DebugLog("UpdateTagAppList from skillUri, push tech %{public}s", nfcType.c_str());
271 }
272 }
273
274 if (valueList.empty()) {
275 DebugLog("UpdateTagAppList, ignore for app %{public}s %{public}s", element.GetBundleName().c_str(),
276 element.GetAbilityName().c_str());
277 return;
278 }
279
280 TagAppTechInfo tagAppTechInfo;
281 tagAppTechInfo.element = element;
282 tagAppTechInfo.tech = valueList;
283 g_tagAppAndTechMap.push_back(tagAppTechInfo);
284 DebugLog("UpdateTagAppList, push for app %{public}s %{public}s", element.GetBundleName().c_str(),
285 element.GetAbilityName().c_str());
286 }
287
UpdateHceAppList(AbilityInfo & abilityInfo,ElementName & element)288 void AppDataParser::UpdateHceAppList(AbilityInfo &abilityInfo, ElementName &element)
289 {
290 if (!GetMatchedHceKeyElement(element).GetBundleName().empty()) {
291 WarnLog("UpdateHceAppList, rm duplicated app %{public}s", element.GetBundleName().c_str());
292 RemoveHceAppInfo(element);
293 }
294 std::vector<AppDataParser::AidInfo> customDataAidList;
295 AppDataParser::AidInfo customDataAid;
296 for (auto& data : abilityInfo.metadata) {
297 if ((KEY_PAYMENT_AID.compare(data.name) == 0) || (KEY_OHTER_AID.compare(data.name) == 0)) {
298 customDataAid.name = data.name;
299 customDataAid.value = data.value;
300 customDataAidList.emplace_back(customDataAid);
301 DebugLog("UpdateHceAppList from metadata, push aid %{public}s", data.value.c_str());
302 }
303 }
304 for (auto& data : abilityInfo.metaData.customizeData) {
305 if ((KEY_PAYMENT_AID.compare(data.name) == 0) || (KEY_OHTER_AID.compare(data.name) == 0)) {
306 customDataAid.name = data.name;
307 customDataAid.value = data.value;
308 customDataAidList.emplace_back(customDataAid);
309 DebugLog("UpdateHceAppList from customizeData, push aid %{public}s", data.value.c_str());
310 }
311 }
312 if (customDataAidList.empty()) {
313 DebugLog("UpdateHceAppList, ignore for app %{public}s %{public}s", element.GetBundleName().c_str(),
314 element.GetAbilityName().c_str());
315 return;
316 }
317 HceAppAidInfo hceAppAidInfo;
318 hceAppAidInfo.element = element;
319 hceAppAidInfo.customDataAid = customDataAidList;
320 g_hceAppAndAidMap.push_back(hceAppAidInfo);
321 DebugLog("UpdateHceAppList, push for app %{public}s %{public}s", element.GetBundleName().c_str(),
322 element.GetAbilityName().c_str());
323 }
324
RemoveTagAppInfo(ElementName & element)325 void AppDataParser::RemoveTagAppInfo(ElementName &element)
326 {
327 ElementName keyElement = GetMatchedTagKeyElement(element);
328 if (keyElement.GetBundleName().empty()) {
329 WarnLog("RemoveTagAppInfo, keyElement is none, ignore it.");
330 return;
331 }
332 DebugLog("RemoveTagAppInfo, request app %{public}s", keyElement.GetBundleName().c_str());
333 std::vector<TagAppTechInfo>::iterator iter;
334 for (iter = g_tagAppAndTechMap.begin(); iter != g_tagAppAndTechMap.end(); ++iter) {
335 // compare only bundle name to remote the app.
336 if (IsMatchedByBundleName(element, (*iter).element)) {
337 DebugLog("RemoveTagAppInfo, erase app %{public}s", keyElement.GetBundleName().c_str());
338 g_tagAppAndTechMap.erase(iter);
339 break;
340 }
341 }
342 }
343
RemoveHceAppInfo(ElementName & element)344 void AppDataParser::RemoveHceAppInfo(ElementName &element)
345 {
346 ElementName keyElement = GetMatchedHceKeyElement(element);
347 if (keyElement.GetBundleName().empty()) {
348 WarnLog("RemoveHceAppInfo, keyElement is none, ignore it.");
349 return;
350 }
351 DebugLog("RemoveHceAppInfo, app %{public}s", keyElement.GetBundleName().c_str());
352 std::vector<HceAppAidInfo>::iterator iter;
353 for (iter = g_hceAppAndAidMap.begin(); iter != g_hceAppAndAidMap.end(); ++iter) {
354 // compare only bundle name to remote the app.
355 if (IsMatchedByBundleName(element, (*iter).element)) {
356 DebugLog("RemoveHceAppInfo, erase app %{public}s", keyElement.GetBundleName().c_str());
357 g_hceAppAndAidMap.erase(iter);
358 break;
359 }
360 }
361 }
362
InitAppList()363 void AppDataParser::InitAppList()
364 {
365 bundleMgrProxy_ = GetBundleMgrProxy();
366 if (!bundleMgrProxy_) {
367 ErrorLog("InitAppList, bundleMgrProxy_ is nullptr.");
368 return;
369 }
370 InitAppListByAction(KITS::ACTION_TAG_FOUND);
371 InitAppListByAction(KITS::ACTION_HOST_APDU_SERVICE);
372 DebugLog("InitAppList, tag size %{public}zu, hce size %{public}zu", g_tagAppAndTechMap.size(),
373 g_hceAppAndAidMap.size());
374 }
375
GetDispatchTagAppsByTech(std::vector<int> discTechList)376 std::vector<ElementName> AppDataParser::GetDispatchTagAppsByTech(std::vector<int> discTechList)
377 {
378 std::vector<ElementName> elements;
379 for (size_t i = 0; i < discTechList.size(); i++) {
380 std::string discStrTech = KITS::TagInfo::GetStringTech(discTechList[i]);
381 DebugLog("GetDispatchTagAppsByTech, tag size = %{public}zu", g_tagAppAndTechMap.size());
382 if (discStrTech.empty()) {
383 continue;
384 }
385
386 // parse for all installed app that can handle this technology.
387 std::vector<TagAppTechInfo>::iterator iter;
388 for (iter = g_tagAppAndTechMap.begin(); iter != g_tagAppAndTechMap.end(); ++iter) {
389 bool appExisted = false;
390 for (auto item : elements) {
391 if (IsMatchedByBundleName(item, (*iter).element)) {
392 appExisted = true;
393 break;
394 }
395 }
396 if (appExisted) {
397 continue;
398 }
399
400 std::vector<std::string> vectorTech = (*iter).tech;
401 for (size_t i = 0; i < vectorTech.size(); i++) {
402 DebugLog("GetDispatchTagAppsByTech, cmp tech %{public}s vs %{public}s",
403 discStrTech.c_str(), vectorTech[i].c_str());
404 if (discStrTech.compare(vectorTech[i]) == 0) {
405 elements.push_back((*iter).element);
406 break;
407 }
408 }
409 }
410 }
411 return elements;
412 }
413 } // namespace NFC
414 } // namespace OHOS
415