16493859b424f65af79e3e13835f7dfed38495c00Martijn Coenen/*
26493859b424f65af79e3e13835f7dfed38495c00Martijn Coenen * Copyright (C) 2013 The Android Open Source Project
36493859b424f65af79e3e13835f7dfed38495c00Martijn Coenen *
46493859b424f65af79e3e13835f7dfed38495c00Martijn Coenen * Licensed under the Apache License, Version 2.0 (the "License");
56493859b424f65af79e3e13835f7dfed38495c00Martijn Coenen * you may not use this file except in compliance with the License.
66493859b424f65af79e3e13835f7dfed38495c00Martijn Coenen * You may obtain a copy of the License at
76493859b424f65af79e3e13835f7dfed38495c00Martijn Coenen *
86493859b424f65af79e3e13835f7dfed38495c00Martijn Coenen *      http://www.apache.org/licenses/LICENSE-2.0
96493859b424f65af79e3e13835f7dfed38495c00Martijn Coenen *
106493859b424f65af79e3e13835f7dfed38495c00Martijn Coenen * Unless required by applicable law or agreed to in writing, software
116493859b424f65af79e3e13835f7dfed38495c00Martijn Coenen * distributed under the License is distributed on an "AS IS" BASIS,
126493859b424f65af79e3e13835f7dfed38495c00Martijn Coenen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136493859b424f65af79e3e13835f7dfed38495c00Martijn Coenen * See the License for the specific language governing permissions and
146493859b424f65af79e3e13835f7dfed38495c00Martijn Coenen * limitations under the License.
156493859b424f65af79e3e13835f7dfed38495c00Martijn Coenen */
16d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenenpackage com.android.nfc.cardemulation;
17d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen
18d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenenimport android.util.Log;
19d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenenimport android.util.SparseArray;
20d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen
21d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenenimport com.android.nfc.NfcService;
22d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen
23af3e301d7820bc0a2447db8af16ab5335e6bd520Martijn Coenenimport java.io.FileDescriptor;
24af3e301d7820bc0a2447db8af16ab5335e6bd520Martijn Coenenimport java.io.PrintWriter;
25d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenenimport java.util.HashMap;
26d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenenimport java.util.HashSet;
27d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenenimport java.util.Map;
28d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenenimport java.util.Set;
29d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen
30d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenenpublic class AidRoutingManager {
31d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen    static final String TAG = "AidRoutingManager";
32d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen
33410f4b955283be0187cd2933bdea07c66e101639Martijn Coenen    static final boolean DBG = false;
3431208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen
3531208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen    static final int ROUTE_HOST = 0x00;
3631208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen
3731208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen    // Every routing table entry is matched exact
3831208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen    static final int AID_MATCHING_EXACT_ONLY = 0x00;
3931208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen    // Every routing table entry can be matched either exact or prefix
4031208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen    static final int AID_MATCHING_EXACT_OR_PREFIX = 0x01;
4131208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen    // Every routing table entry is matched as a prefix
4231208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen    static final int AID_MATCHING_PREFIX_ONLY = 0x02;
43341b2c02da8b4d2a681f3fbcc5657921ad421e32Martijn Coenen
446a707e75739696dde62201047158913411e8cd81Martijn Coenen    // This is the default IsoDep protocol route; it means
456a707e75739696dde62201047158913411e8cd81Martijn Coenen    // that for any AID that needs to be routed to this
466a707e75739696dde62201047158913411e8cd81Martijn Coenen    // destination, we won't need to add a rule to the routing
476a707e75739696dde62201047158913411e8cd81Martijn Coenen    // table, because this destination is already the default route.
486a707e75739696dde62201047158913411e8cd81Martijn Coenen    //
496a707e75739696dde62201047158913411e8cd81Martijn Coenen    // For Nexus devices, the default route is always 0x00.
50ea8f37ee5376e296c3b67f57946b73e48ad88c5cEvan Chu    final int mDefaultRoute;
516a707e75739696dde62201047158913411e8cd81Martijn Coenen
52451ba48faa87d78bfbec0597ff06af1747cf6acbMartijn Coenen    // For Nexus devices, just a static route to the eSE
5389c893312d524f50c47b0d32071f3de8631197f3Martijn Coenen    // OEMs/Carriers could manually map off-host AIDs
544358172f18871d58d5bc2050e4d9d0bf9bc2d5e5Martijn Coenen    // to the correct eSE/UICC based on state they keep.
55ea8f37ee5376e296c3b67f57946b73e48ad88c5cEvan Chu    final int mDefaultOffHostRoute;
5689c893312d524f50c47b0d32071f3de8631197f3Martijn Coenen
5731208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen    // How the NFC controller can match AIDs in the routing table;
5831208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen    // see AID_MATCHING constants
5931208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen    final int mAidMatchingSupport;
6031208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen
614358172f18871d58d5bc2050e4d9d0bf9bc2d5e5Martijn Coenen    final Object mLock = new Object();
624358172f18871d58d5bc2050e4d9d0bf9bc2d5e5Martijn Coenen
63d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen    // mAidRoutingTable contains the current routing table. The index is the route ID.
64d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen    // The route can include routes to a eSE/UICC.
6531208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen    SparseArray<Set<String>> mAidRoutingTable =
6631208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen            new SparseArray<Set<String>>();
67d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen
68d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen    // Easy look-up what the route is for a certain AID
6931208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen    HashMap<String, Integer> mRouteForAid = new HashMap<String, Integer>();
70d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen
71ea8f37ee5376e296c3b67f57946b73e48ad88c5cEvan Chu    private native int doGetDefaultRouteDestination();
72ea8f37ee5376e296c3b67f57946b73e48ad88c5cEvan Chu    private native int doGetDefaultOffHostRouteDestination();
7331208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen    private native int doGetAidMatchingMode();
7431208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen
75d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen    public AidRoutingManager() {
76ea8f37ee5376e296c3b67f57946b73e48ad88c5cEvan Chu        mDefaultRoute = doGetDefaultRouteDestination();
77ea8f37ee5376e296c3b67f57946b73e48ad88c5cEvan Chu        if (DBG) Log.d(TAG, "mDefaultRoute=0x" + Integer.toHexString(mDefaultRoute));
78ea8f37ee5376e296c3b67f57946b73e48ad88c5cEvan Chu        mDefaultOffHostRoute = doGetDefaultOffHostRouteDestination();
79ea8f37ee5376e296c3b67f57946b73e48ad88c5cEvan Chu        if (DBG) Log.d(TAG, "mDefaultOffHostRoute=0x" + Integer.toHexString(mDefaultOffHostRoute));
8031208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen        mAidMatchingSupport = doGetAidMatchingMode();
8131208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen        if (DBG) Log.d(TAG, "mAidMatchingSupport=0x" + Integer.toHexString(mAidMatchingSupport));
82d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen    }
83d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen
8431208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen    public boolean supportsAidPrefixRouting() {
8531208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen        return mAidMatchingSupport == AID_MATCHING_EXACT_OR_PREFIX ||
8631208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen                mAidMatchingSupport == AID_MATCHING_PREFIX_ONLY;
87d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen    }
88d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen
8931208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen    void clearNfcRoutingTableLocked() {
9031208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen        for (Map.Entry<String, Integer> aidEntry : mRouteForAid.entrySet())  {
91c5d3a21bf654bb84f69302bba84acfe42c745b84Paul Chaisson            String aid = aidEntry.getKey();
92c5d3a21bf654bb84f69302bba84acfe42c745b84Paul Chaisson            if (aid.endsWith("*")) {
93c5d3a21bf654bb84f69302bba84acfe42c745b84Paul Chaisson                if (mAidMatchingSupport == AID_MATCHING_EXACT_ONLY) {
94c5d3a21bf654bb84f69302bba84acfe42c745b84Paul Chaisson                    Log.e(TAG, "Device does not support prefix AIDs but AID [" + aid
95c5d3a21bf654bb84f69302bba84acfe42c745b84Paul Chaisson                            + "] is registered");
96c5d3a21bf654bb84f69302bba84acfe42c745b84Paul Chaisson                } else if (mAidMatchingSupport == AID_MATCHING_PREFIX_ONLY) {
97c5d3a21bf654bb84f69302bba84acfe42c745b84Paul Chaisson                    if (DBG) Log.d(TAG, "Unrouting prefix AID " + aid);
98c5d3a21bf654bb84f69302bba84acfe42c745b84Paul Chaisson                    // Cut off '*' since controller anyway treats all AIDs as a prefix
99c5d3a21bf654bb84f69302bba84acfe42c745b84Paul Chaisson                    aid = aid.substring(0, aid.length() - 1);
100c5d3a21bf654bb84f69302bba84acfe42c745b84Paul Chaisson                } else if (mAidMatchingSupport == AID_MATCHING_EXACT_OR_PREFIX) {
101c5d3a21bf654bb84f69302bba84acfe42c745b84Paul Chaisson                    if (DBG) Log.d(TAG, "Unrouting prefix AID " + aid);
102c5d3a21bf654bb84f69302bba84acfe42c745b84Paul Chaisson                }
103c5d3a21bf654bb84f69302bba84acfe42c745b84Paul Chaisson            } else {
104c5d3a21bf654bb84f69302bba84acfe42c745b84Paul Chaisson                if (DBG) Log.d(TAG, "Unrouting exact AID " + aid);
105c5d3a21bf654bb84f69302bba84acfe42c745b84Paul Chaisson            }
106c5d3a21bf654bb84f69302bba84acfe42c745b84Paul Chaisson
107c5d3a21bf654bb84f69302bba84acfe42c745b84Paul Chaisson            NfcService.getInstance().unrouteAids(aid);
108d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen        }
109d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen    }
110d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen
11131208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen    public boolean configureRouting(HashMap<String, Boolean> aidMap) {
11231208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen        SparseArray<Set<String>> aidRoutingTable = new SparseArray<Set<String>>(aidMap.size());
11331208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen        HashMap<String, Integer> routeForAid = new HashMap<String, Integer>(aidMap.size());
11431208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen        // Then, populate internal data structures first
11531208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen        for (Map.Entry<String, Boolean> aidEntry : aidMap.entrySet())  {
11631208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen            int route = aidEntry.getValue() ? ROUTE_HOST : mDefaultOffHostRoute;
11731208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen            String aid = aidEntry.getKey();
11831208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen            Set<String> entries = aidRoutingTable.get(route, new HashSet<String>());
11931208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen            entries.add(aid);
12031208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen            aidRoutingTable.put(route, entries);
12131208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen            routeForAid.put(aid, route);
12231208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen        }
12331208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen
1244358172f18871d58d5bc2050e4d9d0bf9bc2d5e5Martijn Coenen        synchronized (mLock) {
12531208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen            if (routeForAid.equals(mRouteForAid)) {
12631208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen                if (DBG) Log.d(TAG, "Routing table unchanged, not updating");
12731208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen                return false;
1284358172f18871d58d5bc2050e4d9d0bf9bc2d5e5Martijn Coenen            }
12931208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen
13031208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen            // Otherwise, update internal structures and commit new routing
13131208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen            clearNfcRoutingTableLocked();
13231208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen            mRouteForAid = routeForAid;
13331208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen            mAidRoutingTable = aidRoutingTable;
13431208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen            if (mAidMatchingSupport == AID_MATCHING_PREFIX_ONLY) {
13531208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen                /* If a non-default route registers an exact AID which is shorter
13631208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen                 * than this exact AID, this will create a problem with controllers
13731208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen                 * that treat every AID in the routing table as a prefix.
13831208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen                 * For example, if App A registers F0000000041010 as an exact AID,
13931208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen                 * and App B registers F000000004 as an exact AID, and App B is not
14031208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen                 * the default route, the following would be added to the routing table:
14131208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen                 * F000000004 -> non-default destination
14231208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen                 * However, because in this mode, the controller treats every routing table
14331208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen                 * entry as a prefix, it means F0000000041010 would suddenly go to the non-default
14431208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen                 * destination too, whereas it should have gone to the default.
14531208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen                 *
14631208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen                 * The only way to prevent this is to add the longer AIDs of the
14731208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen                 * default route at the top of the table, so they will be matched first.
14831208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen                 */
14931208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen                Set<String> defaultRouteAids = mAidRoutingTable.get(mDefaultRoute);
15031208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen                if (defaultRouteAids != null) {
15131208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen                    for (String defaultRouteAid : defaultRouteAids) {
15231208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen                        // Check whether there are any shorted AIDs routed to non-default
15331208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen                        // TODO this is O(N^2) run-time complexity...
15431208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen                        for (Map.Entry<String, Integer> aidEntry : mRouteForAid.entrySet()) {
15531208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen                            String aid = aidEntry.getKey();
15631208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen                            int route = aidEntry.getValue();
15731208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen                            if (defaultRouteAid.startsWith(aid) && route != mDefaultRoute) {
15831208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen                                if (DBG)
15931208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen                                    Log.d(TAG, "Adding AID " + defaultRouteAid + " for default " +
16031208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen                                            "route, because a conflicting shorter AID will be " +
16131208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen                                            "added to the routing table");
16231208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen                                NfcService.getInstance().routeAids(defaultRouteAid, mDefaultRoute);
16331208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen                            }
16431208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen                        }
16531208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen                    }
16631208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen                }
1674358172f18871d58d5bc2050e4d9d0bf9bc2d5e5Martijn Coenen            }
16831208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen
16931208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen            // Add AID entries for all non-default routes
17031208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen            for (int i = 0; i < mAidRoutingTable.size(); i++) {
17131208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen                int route = mAidRoutingTable.keyAt(i);
17231208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen                if (route != mDefaultRoute) {
17331208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen                    Set<String> aidsForRoute = mAidRoutingTable.get(route);
17431208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen                    for (String aid : aidsForRoute) {
17531208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen                        if (aid.endsWith("*")) {
17631208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen                            if (mAidMatchingSupport == AID_MATCHING_EXACT_ONLY) {
17731208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen                                Log.e(TAG, "This device does not support prefix AIDs.");
17831208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen                            } else if (mAidMatchingSupport == AID_MATCHING_PREFIX_ONLY) {
17931208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen                                if (DBG) Log.d(TAG, "Routing prefix AID " + aid + " to route "
18031208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen                                        + Integer.toString(route));
18131208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen                                // Cut off '*' since controller anyway treats all AIDs as a prefix
18231208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen                                NfcService.getInstance().routeAids(aid.substring(0,
18331208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen                                                aid.length() - 1), route);
18431208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen                            } else if (mAidMatchingSupport == AID_MATCHING_EXACT_OR_PREFIX) {
18531208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen                                if (DBG) Log.d(TAG, "Routing prefix AID " + aid + " to route "
18631208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen                                        + Integer.toString(route));
18731208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen                                NfcService.getInstance().routeAids(aid, route);
18831208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen                            }
18931208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen                        } else {
19031208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen                            if (DBG) Log.d(TAG, "Routing exact AID " + aid + " to route "
19131208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen                                    + Integer.toString(route));
19231208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen                            NfcService.getInstance().routeAids(aid, route);
19331208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen                        }
19431208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen                    }
19531208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen                }
1966a707e75739696dde62201047158913411e8cd81Martijn Coenen            }
197d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen        }
19831208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen
19931208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen        // And finally commit the routing
20031208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen        NfcService.getInstance().commitRouting();
20131208d3ee36f583fd998c89508a3e93bb550cb29Martijn Coenen
202d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen        return true;
203d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen    }
204d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen
205d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen    /**
206d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen     * This notifies that the AID routing table in the controller
207d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen     * has been cleared (usually due to NFC being turned off).
208d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen     */
209d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen    public void onNfccRoutingTableCleared() {
210d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen        // The routing table in the controller was cleared
211d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen        // To stay in sync, clear our own tables.
2124358172f18871d58d5bc2050e4d9d0bf9bc2d5e5Martijn Coenen        synchronized (mLock) {
2134358172f18871d58d5bc2050e4d9d0bf9bc2d5e5Martijn Coenen            mAidRoutingTable.clear();
2144358172f18871d58d5bc2050e4d9d0bf9bc2d5e5Martijn Coenen            mRouteForAid.clear();
2154358172f18871d58d5bc2050e4d9d0bf9bc2d5e5Martijn Coenen        }
216d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen    }
217d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen
218af3e301d7820bc0a2447db8af16ab5335e6bd520Martijn Coenen    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
219af3e301d7820bc0a2447db8af16ab5335e6bd520Martijn Coenen        pw.println("Routing table:");
220ea8f37ee5376e296c3b67f57946b73e48ad88c5cEvan Chu        pw.println("    Default route: " + ((mDefaultRoute == 0x00) ? "host" : "secure element"));
221af3e301d7820bc0a2447db8af16ab5335e6bd520Martijn Coenen        synchronized (mLock) {
222af3e301d7820bc0a2447db8af16ab5335e6bd520Martijn Coenen            for (int i = 0; i < mAidRoutingTable.size(); i++) {
223af3e301d7820bc0a2447db8af16ab5335e6bd520Martijn Coenen                Set<String> aids = mAidRoutingTable.valueAt(i);
224af3e301d7820bc0a2447db8af16ab5335e6bd520Martijn Coenen                pw.println("    Routed to 0x" + Integer.toHexString(mAidRoutingTable.keyAt(i)) + ":");
225af3e301d7820bc0a2447db8af16ab5335e6bd520Martijn Coenen                for (String aid : aids) {
226af3e301d7820bc0a2447db8af16ab5335e6bd520Martijn Coenen                    pw.println("        \"" + aid + "\"");
227af3e301d7820bc0a2447db8af16ab5335e6bd520Martijn Coenen                }
228af3e301d7820bc0a2447db8af16ab5335e6bd520Martijn Coenen            }
229af3e301d7820bc0a2447db8af16ab5335e6bd520Martijn Coenen        }
230af3e301d7820bc0a2447db8af16ab5335e6bd520Martijn Coenen    }
231d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen}
232