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