1 /*
2  * Copyright (C) 2015 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  */
16 
17 package com.android.nfc.cardemulation;
18 
19 import android.util.Log;
20 import android.util.proto.ProtoOutputStream;
21 
22 import com.android.nfc.NfcService;
23 import com.android.nfc.cardemulation.RegisteredT3tIdentifiersCache.T3tIdentifier;
24 
25 import java.io.FileDescriptor;
26 import java.io.PrintWriter;
27 import java.util.ArrayList;
28 import java.util.List;
29 
30 public class SystemCodeRoutingManager {
31     static final String TAG = "SystemCodeRoutingManager";
32 
33     static final boolean DBG = false;
34 
35     final Object mLock = new Object();
36 
37     List<T3tIdentifier> mConfiguredT3tIdentifiers =
38             new ArrayList<T3tIdentifier>();
39 
configureRouting(List<T3tIdentifier> t3tIdentifiers)40     public boolean configureRouting(List<T3tIdentifier> t3tIdentifiers) {
41         if (DBG) Log.d(TAG, "configureRouting");
42         List<T3tIdentifier> toBeAdded = new ArrayList<T3tIdentifier>();
43         List<T3tIdentifier> toBeRemoved = new ArrayList<T3tIdentifier>();
44         synchronized (mLock) {
45             for (T3tIdentifier t3tIdentifier : t3tIdentifiers) {
46                 if (!mConfiguredT3tIdentifiers.contains(t3tIdentifier)) {
47                     toBeAdded.add(t3tIdentifier);
48                 }
49             }
50             for (T3tIdentifier t3tIdentifier : mConfiguredT3tIdentifiers) {
51                 if (!t3tIdentifiers.contains(t3tIdentifier)) {
52                     toBeRemoved.add(t3tIdentifier);
53                 }
54             }
55             if (toBeAdded.size() <= 0 && toBeRemoved.size() <= 0) {
56                 Log.d(TAG, "Routing table unchanged, not updating");
57                 return false;
58             }
59             // Update internal structures
60             for (T3tIdentifier t3tIdentifier : toBeRemoved) {
61                 if (DBG) Log.d(TAG, "deregisterNfcFSystemCodeonDh:");
62                 NfcService.getInstance().deregisterT3tIdentifier(
63                         t3tIdentifier.systemCode, t3tIdentifier.nfcid2, t3tIdentifier.t3tPmm);
64             }
65             for (T3tIdentifier t3tIdentifier : toBeAdded) {
66                 if (DBG) Log.d(TAG, "registerNfcFSystemCodeonDh:");
67                 NfcService.getInstance().registerT3tIdentifier(
68                         t3tIdentifier.systemCode, t3tIdentifier.nfcid2 , t3tIdentifier.t3tPmm);
69             }
70             if (DBG) {
71                 Log.d(TAG, "(Before) mConfiguredT3tIdentifiers: size=" +
72                         mConfiguredT3tIdentifiers.size());
73                 for (T3tIdentifier t3tIdentifier : mConfiguredT3tIdentifiers) {
74                     Log.d(TAG, "    " + t3tIdentifier.systemCode +
75                             "/" + t3tIdentifier.t3tPmm);
76                 }
77                 Log.d(TAG, "(After) mConfiguredT3tIdentifiers: size=" +
78                         t3tIdentifiers.size());
79                 for (T3tIdentifier t3tIdentifier : t3tIdentifiers) {
80                     Log.d(TAG, "    " + t3tIdentifier.systemCode +
81                             "/" + t3tIdentifier.nfcid2 +
82                             "/" + t3tIdentifier.t3tPmm);
83                 }
84             }
85             mConfiguredT3tIdentifiers = t3tIdentifiers;
86         }
87 
88         // And finally commit the routing
89         NfcService.getInstance().commitRouting();
90 
91         return true;
92     }
93 
94     /**
95      * This notifies that the SystemCode routing table in the controller
96      * has been cleared (usually due to NFC being turned off).
97      */
onNfccRoutingTableCleared()98     public void onNfccRoutingTableCleared() {
99         // The routing table in the controller was cleared
100         // To stay in sync, clear our own tables.
101         synchronized (mLock) {
102             if (DBG) Log.d(TAG, "onNfccRoutingTableCleared");
103             NfcService.getInstance().clearT3tIdentifiersCache();
104             mConfiguredT3tIdentifiers.clear();
105         }
106     }
107 
dump(FileDescriptor fd, PrintWriter pw, String[] args)108     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
109         pw.println("HCE-F routing table:");
110         synchronized (mLock) {
111             for (T3tIdentifier t3tIdentifier : mConfiguredT3tIdentifiers) {
112                 pw.println("    " + t3tIdentifier.systemCode +
113                         "/" + t3tIdentifier.nfcid2);
114             }
115         }
116     }
117 
118     /**
119      * Dump debugging information as a SystemCodeRoutingManagerProto
120      *
121      * Note:
122      * See proto definition in frameworks/base/core/proto/android/nfc/card_emulation.proto
123      * When writing a nested message, must call {@link ProtoOutputStream#start(long)} before and
124      * {@link ProtoOutputStream#end(long)} after.
125      * Never reuse a proto field number. When removing a field, mark it as reserved.
126      */
dumpDebug(ProtoOutputStream proto)127     void dumpDebug(ProtoOutputStream proto) {
128         synchronized (mLock) {
129             for (T3tIdentifier t3tIdentifier : mConfiguredT3tIdentifiers) {
130                 long token = proto.start(SystemCodeRoutingManagerProto.T3T_IDENTIFIERS);
131                 proto.write(SystemCodeRoutingManagerProto.T3tIdentifier.SYSTEM_CODE,
132                         t3tIdentifier.systemCode);
133                 proto.write(SystemCodeRoutingManagerProto.T3tIdentifier.NFCID2,
134                         t3tIdentifier.nfcid2);
135                 proto.end(token);
136             }
137         }
138     }
139 }
140