blob: b2c3d9b8922934359b44abac4fb97de565a11902 [file] [log] [blame]
nxpandroid64fd68c2015-09-23 16:45:15 +05301/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
nxpandroid64fd68c2015-09-23 16:45:15 +053016/******************************************************************************
nxf500513a018e72019-04-23 17:11:41 +053017*
18* The original Work has been changed by NXP.
19*
20* Licensed under the Apache License, Version 2.0 (the "License");
21* you may not use this file except in compliance with the License.
22* You may obtain a copy of the License at
23*
24* http://www.apache.org/licenses/LICENSE-2.0
25*
26* Unless required by applicable law or agreed to in writing, software
27* distributed under the License is distributed on an "AS IS" BASIS,
28* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
29* See the License for the specific language governing permissions and
30* limitations under the License.
31*
32* Copyright 2018-2019 NXP
33*
34******************************************************************************/
nxpandroid64fd68c2015-09-23 16:45:15 +053035package com.android.nfc.cardemulation;
36
37import android.util.Log;
38import android.util.SparseArray;
nxf500513a018e72019-04-23 17:11:41 +053039import android.content.Context;
40import android.app.ActivityThread;
41import android.app.ActivityManager;
42import android.app.ActivityManager.RunningTaskInfo;
nxpandroid64fd68c2015-09-23 16:45:15 +053043import com.android.nfc.NfcService;
nxf500513a018e72019-04-23 17:11:41 +053044import android.util.SparseArray;
nxpandroid64fd68c2015-09-23 16:45:15 +053045import java.io.FileDescriptor;
46import java.io.PrintWriter;
47import java.util.Collections;
nxf500513a018e72019-04-23 17:11:41 +053048import java.util.Arrays;
nxpandroid64fd68c2015-09-23 16:45:15 +053049import java.util.HashMap;
50import java.util.HashSet;
51import java.util.Hashtable;
52import java.util.Iterator;
53import java.util.List;
54import java.util.Map;
55import java.util.Set;
Ganesh Devac90b32d2019-07-12 11:53:10 +053056import android.util.StatsLog;
nxf500513a018e72019-04-23 17:11:41 +053057import java.util.List;
nxpandroid64fd68c2015-09-23 16:45:15 +053058import java.util.ArrayList;
nxf500513a018e72019-04-23 17:11:41 +053059import java.util.Hashtable;
60import android.os.SystemProperties;
nxpandroid64fd68c2015-09-23 16:45:15 +053061public class AidRoutingManager {
nxf500513a018e72019-04-23 17:11:41 +053062
nxpandroid64fd68c2015-09-23 16:45:15 +053063 static final String TAG = "AidRoutingManager";
64
nxf500514ff9f422019-03-20 16:28:16 +053065 static final boolean DBG =
nxf500513a018e72019-04-23 17:11:41 +053066 ((SystemProperties.get("persist.nfc.ce_debug").equals("1")) ? true : false);
nxpandroid64fd68c2015-09-23 16:45:15 +053067
68 static final int ROUTE_HOST = 0x00;
69
70 // Every routing table entry is matched exact
71 static final int AID_MATCHING_EXACT_ONLY = 0x00;
72 // Every routing table entry can be matched either exact or prefix
73 static final int AID_MATCHING_EXACT_OR_PREFIX = 0x01;
74 // Every routing table entry is matched as a prefix
75 static final int AID_MATCHING_PREFIX_ONLY = 0x02;
nxpandroidcbf24822017-07-12 21:37:17 +053076 // Every routing table entry can be matched either exact or prefix or subset only
77 static final int AID_MATCHING_EXACT_OR_SUBSET_OR_PREFIX = 0x03;
nxf500513a018e72019-04-23 17:11:41 +053078
79 int mDefaultIsoDepRoute;
80 //Let mDefaultRoute as default aid route
nxpandroid64fd68c2015-09-23 16:45:15 +053081 int mDefaultRoute;
nxf500513a018e72019-04-23 17:11:41 +053082
83 int mMaxAidRoutingTableSize;
84 int mDefaultAidRoute;
85 final byte[] mOffHostRouteUicc;
86 final byte[] mOffHostRouteEse;
87 // Used for backward compatibility in case application doesn't specify the
88 // SE
89 final int mDefaultOffHostRoute;
nxpandroid64fd68c2015-09-23 16:45:15 +053090
91 // How the NFC controller can match AIDs in the routing table;
92 // see AID_MATCHING constants
nxf500513a018e72019-04-23 17:11:41 +053093 final int mAidMatchingSupport;
nxpandroida9a68ba2016-01-14 21:12:17 +053094 private int mAidRoutingTableSize;
nxpandroid64fd68c2015-09-23 16:45:15 +053095 // Maximum AID routing table size
96 final Object mLock = new Object();
nxpandroid34627bd2016-05-27 15:52:30 +053097 //set the status of last AID routes commit to routing table
98 //if true, last commit was successful,
99 //if false, there was an overflow of routing table for commit using last set of AID's in (mRouteForAid)
100 boolean mLastCommitStatus;
nxpandroid64fd68c2015-09-23 16:45:15 +0530101
102 // mAidRoutingTable contains the current routing table. The index is the route ID.
103 // The route can include routes to a eSE/UICC.
104 SparseArray<Set<String>> mAidRoutingTable =
105 new SparseArray<Set<String>>();
106
107 // Easy look-up what the route is for a certain AID
108 HashMap<String, Integer> mRouteForAid = new HashMap<String, Integer>();
109
nxpandroid64fd68c2015-09-23 16:45:15 +0530110 private native int doGetDefaultRouteDestination();
111 private native int doGetDefaultOffHostRouteDestination();
nxf500513a018e72019-04-23 17:11:41 +0530112 private native byte[] doGetOffHostUiccDestination();
113 private native byte[] doGetOffHostEseDestination();
nxpandroid64fd68c2015-09-23 16:45:15 +0530114 private native int doGetAidMatchingMode();
nxf500513a018e72019-04-23 17:11:41 +0530115 private native int doGetDefaultIsoDepRouteDestination();
Suryaprakash Kondurud7f25412018-04-12 12:24:24 +0530116 final ActivityManager mActivityManager;
nxf500513a018e72019-04-23 17:11:41 +0530117 final class AidEntry {
118 boolean isOnHost;
119 String offHostSE;
120 int aidInfo;
121 int powerstate;
122 int route;
123 }
Suryaprakash Kondurud7f25412018-04-12 12:24:24 +0530124
nxpandroid64fd68c2015-09-23 16:45:15 +0530125 public AidRoutingManager() {
126 mDefaultRoute = doGetDefaultRouteDestination();
nxf500513a018e72019-04-23 17:11:41 +0530127 if (DBG)
128 Log.d(TAG, "mDefaultRoute=0x" + Integer.toHexString(mDefaultRoute));
nxpandroid64fd68c2015-09-23 16:45:15 +0530129 mDefaultOffHostRoute = doGetDefaultOffHostRouteDestination();
nxf500513a018e72019-04-23 17:11:41 +0530130 if (DBG)
131 Log.d(TAG, "mDefaultOffHostRoute=0x" + Integer.toHexString(mDefaultOffHostRoute));
132 mOffHostRouteUicc = doGetOffHostUiccDestination();
133 if (DBG)
134 Log.d(TAG, "mOffHostRouteUicc=" + Arrays.toString(mOffHostRouteUicc));
135 mOffHostRouteEse = doGetOffHostEseDestination();
136 if (DBG)
137 Log.d(TAG, "mOffHostRouteEse=" + Arrays.toString(mOffHostRouteEse));
nxpandroid64fd68c2015-09-23 16:45:15 +0530138 mAidMatchingSupport = doGetAidMatchingMode();
139 if (DBG) Log.d(TAG, "mAidMatchingSupport=0x" + Integer.toHexString(mAidMatchingSupport));
nxf500513a018e72019-04-23 17:11:41 +0530140 mDefaultAidRoute = NfcService.getInstance().GetDefaultRouteEntry() >> 0x08;
141 if (DBG)
142 Log.d(TAG, "mDefaultAidRoute=0x" + Integer.toHexString(mDefaultAidRoute));
143 mDefaultIsoDepRoute = doGetDefaultIsoDepRouteDestination();
144 if (DBG) Log.d(TAG, "mDefaultIsoDepRoute=0x" + Integer.toHexString(mDefaultIsoDepRoute));
nxpandroid34627bd2016-05-27 15:52:30 +0530145 mLastCommitStatus = true;
Suryaprakash Kondurud7f25412018-04-12 12:24:24 +0530146
147 Context context = (Context) ActivityThread.currentApplication();
148 mActivityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
nxpandroid64fd68c2015-09-23 16:45:15 +0530149 }
150
151 public boolean supportsAidPrefixRouting() {
152 return mAidMatchingSupport == AID_MATCHING_EXACT_OR_PREFIX ||
nxpandroidcbf24822017-07-12 21:37:17 +0530153 mAidMatchingSupport == AID_MATCHING_PREFIX_ONLY ||
154 mAidMatchingSupport == AID_MATCHING_EXACT_OR_SUBSET_OR_PREFIX;
155 }
156
157 public boolean supportsAidSubsetRouting() {
158 return mAidMatchingSupport == AID_MATCHING_EXACT_OR_SUBSET_OR_PREFIX;
nxpandroid64fd68c2015-09-23 16:45:15 +0530159 }
nxpandroid34627bd2016-05-27 15:52:30 +0530160
nxf500513a018e72019-04-23 17:11:41 +0530161 public int calculateAidRouteSize(HashMap<String, AidEntry> routeCache) {
162 // TAG + ROUTE + LENGTH_BYTE + POWER
163 int AID_HDR_LENGTH = 0x04;
164 int routeTableSize = 0x00;
165 for(Map.Entry<String, AidEntry> aidEntry : routeCache.entrySet()) {
166 String aid = aidEntry.getKey();
167 // removing prefix length
168 if(aid.endsWith("*")) {
169 routeTableSize += ((aid.length() - 0x01) / 0x02) + AID_HDR_LENGTH;
170 } else {
171 routeTableSize += (aid.length() / 0x02)+ AID_HDR_LENGTH;
172 }
173 }
174 if (DBG) Log.d(TAG, "calculateAidRouteSize: " + routeTableSize);
175 return routeTableSize;
nxpandroid34627bd2016-05-27 15:52:30 +0530176 }
nxf500513a018e72019-04-23 17:11:41 +0530177
178 private void clearNfcRoutingTableLocked() {
Nikhil Chhabra27df0f72018-01-11 10:19:11 +0530179 for (Map.Entry<String, Integer> aidEntry : mRouteForAid.entrySet()) {
180 String aid = aidEntry.getKey();
181 if (aid.endsWith("*")) {
182 if (mAidMatchingSupport == AID_MATCHING_EXACT_ONLY) {
183 Log.e(TAG, "Device does not support prefix AIDs but AID [" + aid
184 + "] is registered");
185 } else if (mAidMatchingSupport == AID_MATCHING_PREFIX_ONLY) {
186 if (DBG) Log.d(TAG, "Unrouting prefix AID " + aid);
187 // Cut off '*' since controller anyway treats all AIDs as a prefix
188 aid = aid.substring(0, aid.length() - 1);
189 } else if (mAidMatchingSupport == AID_MATCHING_EXACT_OR_PREFIX ||
190 mAidMatchingSupport == AID_MATCHING_EXACT_OR_SUBSET_OR_PREFIX) {
191 aid = aid.substring(0, aid.length() - 1);
192 if (DBG) Log.d(TAG, "Unrouting prefix AID " + aid);
193 }
194 } else if (aid.endsWith("#")) {
195 if (mAidMatchingSupport == AID_MATCHING_EXACT_ONLY) {
196 Log.e(TAG, "Device does not support subset AIDs but AID [" + aid
197 + "] is registered");
198 } else if (mAidMatchingSupport == AID_MATCHING_PREFIX_ONLY ||
199 mAidMatchingSupport == AID_MATCHING_EXACT_OR_PREFIX) {
200 Log.e(TAG, "Device does not support subset AIDs but AID [" + aid
201 + "] is registered");
202 } else if (mAidMatchingSupport == AID_MATCHING_EXACT_OR_SUBSET_OR_PREFIX) {
203 if (DBG) Log.d(TAG, "Unrouting subset AID " + aid);
204 aid = aid.substring(0, aid.length() - 1);
205 }
206 } else {
207 if (DBG) Log.d(TAG, "Unrouting exact AID " + aid);
208 }
nxf500513a018e72019-04-23 17:11:41 +0530209
Nikhil Chhabra27df0f72018-01-11 10:19:11 +0530210 NfcService.getInstance().unrouteAids(aid);
211 }
nxf500513a018e72019-04-23 17:11:41 +0530212 if (NfcService.getInstance().getNciVersion() != NfcService.getInstance().NCI_VERSION_1_0) {
213 // unRoute EmptyAid
214 NfcService.getInstance().unrouteAids("");
215 }
nxpandroid64fd68c2015-09-23 16:45:15 +0530216 }
217
nxf500513a018e72019-04-23 17:11:41 +0530218 private int getRouteForSecureElement(String se) {
219 if (se == null || se.length() <= 3) {
220 return 0;
221 }
222 try {
223 if (se.startsWith("eSE") && mOffHostRouteEse != null) {
224 int index = Integer.parseInt(se.substring(3));
225 if (mOffHostRouteEse.length >= index && index > 0) {
226 return mOffHostRouteEse[index - 1] & 0xFF;
227 }
228 } else if (se.startsWith("SIM") && mOffHostRouteUicc != null) {
229 int index = Integer.parseInt(se.substring(3));
230 if (mOffHostRouteUicc.length >= index && index > 0) {
231 return mOffHostRouteUicc[index - 1] & 0xFF;
232 }
Ganesh Deva1ad7d6f2019-06-17 11:46:02 +0530233 if (mOffHostRouteEse == null && mOffHostRouteUicc == null)
234 return mDefaultOffHostRoute;
nxf500513a018e72019-04-23 17:11:41 +0530235 }
236 } catch (NumberFormatException e) {
237 }
238 return 0;
nxf500510626e0e2019-02-08 14:57:00 +0530239 }
240
nxf500513a018e72019-04-23 17:11:41 +0530241 public boolean configureRouting(HashMap<String, AidEntry> aidMap, boolean force) {
nxpandroid64fd68c2015-09-23 16:45:15 +0530242 boolean aidRouteResolved = false;
nxf500513a018e72019-04-23 17:11:41 +0530243 HashMap<String, AidEntry> aidRoutingTableCache = new HashMap<String, AidEntry>(aidMap.size());
244 ArrayList<Integer> seList = new ArrayList<Integer>();
nxpandroid64fd68c2015-09-23 16:45:15 +0530245 SparseArray<Set<String>> aidRoutingTable = new SparseArray<Set<String>>(aidMap.size());
246 HashMap<String, Integer> routeForAid = new HashMap<String, Integer>(aidMap.size());
nxpandroidcbf24822017-07-12 21:37:17 +0530247 HashMap<String, Integer> infoForAid = new HashMap<String, Integer>(aidMap.size());
nxf500513a018e72019-04-23 17:11:41 +0530248 HashMap<String, Integer> powerForAid = new HashMap<String, Integer>(aidMap.size());
249 mDefaultRoute = NfcService.getInstance().GetDefaultRouteLoc();
250 mAidRoutingTableSize = NfcService.getInstance().getAidRoutingTableSize();
251 mDefaultAidRoute = NfcService.getInstance().GetDefaultRouteEntry() >> 0x08;
252 Log.e(TAG, "Size of routing table"+mAidRoutingTableSize);
253 seList.add(mDefaultAidRoute);
nxpandroid64fd68c2015-09-23 16:45:15 +0530254 // Then, populate internal data structures first
nxf500513a018e72019-04-23 17:11:41 +0530255 for (Map.Entry<String, AidEntry> aidEntry : aidMap.entrySet()) {
256 int route = ROUTE_HOST;
257 if (!aidEntry.getValue().isOnHost) {
258 String offHostSE = aidEntry.getValue().offHostSE;
259 if (offHostSE == null) {
260 route = mDefaultOffHostRoute;
261 } else {
262 route = getRouteForSecureElement(offHostSE);
263 if (route == 0) {
264 Log.e(TAG, "Invalid Off host Aid Entry " + offHostSE);
265 continue;
266 }
267 }
nxpandroid64fd68c2015-09-23 16:45:15 +0530268 }
nxf500513a018e72019-04-23 17:11:41 +0530269 if (!seList.contains(route))
270 seList.add(route);
271 aidEntry.getValue().route = route;
272 int aidType = aidEntry.getValue().aidInfo;
273 int power = aidEntry.getValue().powerstate;
nxpandroid64fd68c2015-09-23 16:45:15 +0530274 String aid = aidEntry.getKey();
275 Set<String> entries = aidRoutingTable.get(route, new HashSet<String>());
276 entries.add(aid);
277 aidRoutingTable.put(route, entries);
278 routeForAid.put(aid, route);
nxpandroidcbf24822017-07-12 21:37:17 +0530279 infoForAid.put(aid, aidType);
nxf500513a018e72019-04-23 17:11:41 +0530280 powerForAid.put(aid, power);
nxpandroid64fd68c2015-09-23 16:45:15 +0530281 if (DBG) Log.d(TAG, "#######Routing AID " + aid + " to route "
282 + Integer.toString(route) + " with power "+ power);
283 }
nxf500513a018e72019-04-23 17:11:41 +0530284 if (!seList.contains(ROUTE_HOST))
285 seList.add(ROUTE_HOST);
nxpandroid64fd68c2015-09-23 16:45:15 +0530286
287 synchronized (mLock) {
nxf500513a018e72019-04-23 17:11:41 +0530288 if (routeForAid.equals(mRouteForAid) && !force) {
Suhas Sureshac4f88e2019-06-14 18:08:16 +0530289 if (DBG) Log.d(TAG, "Routing table unchanged, not updating");
nxpandroid64fd68c2015-09-23 16:45:15 +0530290 return false;
291 }
nxpandroidebf53fb2016-12-22 18:48:59 +0530292
nxpandroid64fd68c2015-09-23 16:45:15 +0530293 // Otherwise, update internal structures and commit new routing
294 clearNfcRoutingTableLocked();
295 mRouteForAid = routeForAid;
nxpandroid64fd68c2015-09-23 16:45:15 +0530296 mAidRoutingTable = aidRoutingTable;
nxf500513a018e72019-04-23 17:11:41 +0530297 mMaxAidRoutingTableSize = NfcService.getInstance().getAidRoutingTableSize();
298 if (DBG) Log.d(TAG, "mMaxAidRoutingTableSize: " + mMaxAidRoutingTableSize);
299
300 for(int index=0; index < seList.size(); index++) {
301 mDefaultRoute = seList.get(index);
302 if(index != 0)
303 if (DBG) Log.d(TAG, "AidRoutingTable is full, try to switch mDefaultRoute to 0x" + Integer.toHexString(mDefaultRoute));
304
305 aidRoutingTableCache.clear();
306 if (mAidMatchingSupport == AID_MATCHING_PREFIX_ONLY) {
nxpandroid64fd68c2015-09-23 16:45:15 +0530307 /* If a non-default route registers an exact AID which is shorter
308 * than this exact AID, this will create a problem with controllers
309 * that treat every AID in the routing table as a prefix.
310 * For example, if App A registers F0000000041010 as an exact AID,
311 * and App B registers F000000004 as an exact AID, and App B is not
312 * the default route, the following would be added to the routing table:
313 * F000000004 -> non-default destination
314 * However, because in this mode, the controller treats every routing table
315 * entry as a prefix, it means F0000000041010 would suddenly go to the non-default
316 * destination too, whereas it should have gone to the default.
317 *
318 * The only way to prevent this is to add the longer AIDs of the
319 * default route at the top of the table, so they will be matched first.
320 */
321 Set<String> defaultRouteAids = mAidRoutingTable.get(mDefaultRoute);
nxf382934d174fd2018-06-29 13:02:43 +0530322 if (defaultRouteAids != null) {
nxpandroid64fd68c2015-09-23 16:45:15 +0530323 for (String defaultRouteAid : defaultRouteAids) {
324 // Check whether there are any shorted AIDs routed to non-default
325 // TODO this is O(N^2) run-time complexity...
326 for (Map.Entry<String, Integer> aidEntry : mRouteForAid.entrySet()) {
327 String aid = aidEntry.getKey();
328 int route = aidEntry.getValue();
329 if (defaultRouteAid.startsWith(aid) && route != mDefaultRoute) {
330 if (DBG) Log.d(TAG, "Adding AID " + defaultRouteAid + " for default " +
nxf500513a018e72019-04-23 17:11:41 +0530331 "route, because a conflicting shorter AID will be " +
332 "added to the routing table");
333 aidRoutingTableCache.put(defaultRouteAid, aidMap.get(defaultRouteAid));
nxpandroid64fd68c2015-09-23 16:45:15 +0530334 }
335 }
336 }
337 }
338 }
nxf500513a018e72019-04-23 17:11:41 +0530339 // Add AID entries for
340 // 1. all non-default routes
341 // 2. default route but only payment AID
Suhas Sureshce6a3442018-07-30 21:06:36 +0530342 // Add AID entries for all non-default routes
nxpandroid64fd68c2015-09-23 16:45:15 +0530343 for (int i = 0; i < mAidRoutingTable.size(); i++) {
344 int route = mAidRoutingTable.keyAt(i);
Suhas Sureshce6a3442018-07-30 21:06:36 +0530345 if (route != mDefaultRoute) {
346 Set<String> aidsForRoute = mAidRoutingTable.get(route);
347 for (String aid : aidsForRoute) {
nxpandroid64fd68c2015-09-23 16:45:15 +0530348 if (aid.endsWith("*")) {
349 if (mAidMatchingSupport == AID_MATCHING_EXACT_ONLY) {
350 Log.e(TAG, "This device does not support prefix AIDs.");
351 } else if (mAidMatchingSupport == AID_MATCHING_PREFIX_ONLY) {
352 if (DBG) Log.d(TAG, "Routing prefix AID " + aid + " to route "
353 + Integer.toString(route));
354 // Cut off '*' since controller anyway treats all AIDs as a prefix
nxf500513a018e72019-04-23 17:11:41 +0530355 aidRoutingTableCache.put(aid.substring(0,aid.length() - 1), aidMap.get(aid));
356 } else if (mAidMatchingSupport == AID_MATCHING_EXACT_OR_PREFIX ||
357 mAidMatchingSupport == AID_MATCHING_EXACT_OR_SUBSET_OR_PREFIX) {
nxpandroid64fd68c2015-09-23 16:45:15 +0530358 if (DBG) Log.d(TAG, "Routing prefix AID " + aid + " to route "
359 + Integer.toString(route));
nxf500513a018e72019-04-23 17:11:41 +0530360 aidRoutingTableCache.put(aid.substring(0,aid.length() - 1), aidMap.get(aid));
nxpandroidcbf24822017-07-12 21:37:17 +0530361 }
362 } else if (aid.endsWith("#")) {
363 if (mAidMatchingSupport == AID_MATCHING_EXACT_ONLY) {
364 Log.e(TAG, "Device does not support subset AIDs but AID [" + aid
365 + "] is registered");
366 } else if (mAidMatchingSupport == AID_MATCHING_PREFIX_ONLY ||
367 mAidMatchingSupport == AID_MATCHING_EXACT_OR_PREFIX) {
368 Log.e(TAG, "Device does not support subset AIDs but AID [" + aid
369 + "] is registered");
370 } else if (mAidMatchingSupport == AID_MATCHING_EXACT_OR_SUBSET_OR_PREFIX) {
371 if (DBG) Log.d(TAG, "Routing subset AID " + aid + " to route "
372 + Integer.toString(route));
nxf500513a018e72019-04-23 17:11:41 +0530373 aidRoutingTableCache.put(aid.substring(0,aid.length() - 1), aidMap.get(aid));
nxpandroid64fd68c2015-09-23 16:45:15 +0530374 }
375 } else {
376 if (DBG) Log.d(TAG, "Routing exact AID " + aid + " to route "
377 + Integer.toString(route));
nxf500513a018e72019-04-23 17:11:41 +0530378 aidRoutingTableCache.put(aid, aidMap.get(aid));
nxpandroid64fd68c2015-09-23 16:45:15 +0530379 }
nxf500513a018e72019-04-23 17:11:41 +0530380 }
nxpandroid64fd68c2015-09-23 16:45:15 +0530381 }
382 }
nxf500513a018e72019-04-23 17:11:41 +0530383 if( calculateAidRouteSize(aidRoutingTableCache) <= mMaxAidRoutingTableSize) {
nxpandroid64fd68c2015-09-23 16:45:15 +0530384 aidRouteResolved = true;
385 break;
nxf500513a018e72019-04-23 17:11:41 +0530386 }
nxpandroid64fd68c2015-09-23 16:45:15 +0530387 }
nxf500513a018e72019-04-23 17:11:41 +0530388 if(aidRouteResolved == true) {
389 commit(aidRoutingTableCache);
Ganesh Deva49fde922019-05-21 15:07:33 +0530390 NfcService.getInstance().updateDefaultAidRoute(mDefaultRoute);
nxf500513a018e72019-04-23 17:11:41 +0530391 mLastCommitStatus = true;
392 } else {
Ganesh Devac90b32d2019-07-12 11:53:10 +0530393 StatsLog.write(StatsLog.NFC_ERROR_OCCURRED, StatsLog.NFC_ERROR_OCCURRED__TYPE__AID_OVERFLOW, 0, 0);
nxf500513a018e72019-04-23 17:11:41 +0530394 Log.e(TAG, "RoutingTable unchanged because it's full, not updating");
395 NfcService.getInstance().notifyRoutingTableFull();
nxf500513a018e72019-04-23 17:11:41 +0530396 mLastCommitStatus = false;
397 }
nxpandroid64fd68c2015-09-23 16:45:15 +0530398 }
Suhas Suresh8cd37b32019-06-25 16:50:16 +0530399 if (NfcService.getInstance().isNfcEnabled())
400 NfcService.getInstance().commitRouting();
nxpandroid64fd68c2015-09-23 16:45:15 +0530401 return true;
402 }
403
nxf500513a018e72019-04-23 17:11:41 +0530404 private void commit(HashMap<String, AidEntry> routeCache ) {
405 if(routeCache == null)
406 {
407 return;
408 }
409 for (Map.Entry<String, AidEntry> aidEntry : routeCache.entrySet()) {
410 if(aidEntry.getKey().isEmpty())
411 continue;
412 AidEntry element = aidEntry.getValue();
413 if (DBG) Log.d (TAG, element.toString());
414 NfcService.getInstance().routeAids(
415 aidEntry.getKey(),
416 element.route,
417 element.aidInfo,
418 element.powerstate);
nxpandroid64fd68c2015-09-23 16:45:15 +0530419 }
nxf500513a018e72019-04-23 17:11:41 +0530420 AidEntry emptyAidEntry = routeCache.get("");
421 if (emptyAidEntry != null)
422 NfcService.getInstance().routeAids(
423 "", emptyAidEntry.route, emptyAidEntry.aidInfo, emptyAidEntry.powerstate);
nxpandroid64fd68c2015-09-23 16:45:15 +0530424 }
nxpandroid64fd68c2015-09-23 16:45:15 +0530425 /**
426 * This notifies that the AID routing table in the controller
427 * has been cleared (usually due to NFC being turned off).
428 */
429 public void onNfccRoutingTableCleared() {
430 // The routing table in the controller was cleared
431 // To stay in sync, clear our own tables.
432 synchronized (mLock) {
433 mAidRoutingTable.clear();
434 mRouteForAid.clear();
435 }
436 }
437
nxpandroidebf53fb2016-12-22 18:48:59 +0530438 public boolean getLastCommitRoutingStatus() {
439 return mLastCommitStatus;
440 }
441
nxf500513a018e72019-04-23 17:11:41 +0530442 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
443 pw.println("Routing table:");
444 pw.println(" Default route: " + ((mDefaultRoute == 0x00) ? "host" : "secure element"));
445 synchronized (mLock) {
446 for (int i = 0; i < mAidRoutingTable.size(); i++) {
447 Set<String> aids = mAidRoutingTable.valueAt(i);
448 pw.println(" Routed to 0x" + Integer.toHexString(mAidRoutingTable.keyAt(i)) + ":");
449 for (String aid : aids) {
450 pw.println(" \"" + aid + "\"");
nxpandroid64fd68c2015-09-23 16:45:15 +0530451 }
452 }
nxpandroid64fd68c2015-09-23 16:45:15 +0530453 }
nxpandroid64fd68c2015-09-23 16:45:15 +0530454 }
Suryaprakash Kondurud7f25412018-04-12 12:24:24 +0530455
456 // Returns true if AppChooserActivity is foreground to restart RF discovery so that
457 // TapAgainDialog is dismissed when an external reader detects the device.
458 private boolean isProcessingTapAgain() {
459 String appChooserActivityClassName = AppChooserActivity.class.getName();
460 return appChooserActivityClassName.equals(getTopClass());
461 }
462
463 private String getTopClass() {
464 String topClass = null;
465 List<RunningTaskInfo> tasks = mActivityManager.getRunningTasks(1);
466 if (tasks != null && tasks.size() > 0) {
467 topClass = tasks.get(0).topActivity.getClassName();
468 }
469 return topClass;
470 }
nxpandroid64fd68c2015-09-23 16:45:15 +0530471}