• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.app.ActivityManager;
20 import android.content.ComponentName;
21 import android.content.Context;
22 import android.nfc.cardemulation.NfcFServiceInfo;
23 import android.util.Log;
24 
25 import java.io.FileDescriptor;
26 import java.io.PrintWriter;
27 import java.util.ArrayList;
28 import java.util.Iterator;
29 import java.util.List;
30 import java.util.Map;
31 import java.util.HashMap;
32 
33 public class RegisteredT3tIdentifiersCache {
34     static final String TAG = "RegisteredT3tIdentifiersCache";
35 
36     static final boolean DBG = false;
37 
38     // All NFC-F services that have registered
39     List<NfcFServiceInfo> mServices = new ArrayList<NfcFServiceInfo>();
40 
41     final HashMap<String, NfcFServiceInfo> mForegroundT3tIdentifiersCache =
42             new HashMap<String, NfcFServiceInfo>();
43 
44     ComponentName mEnabledForegroundService;
45 
46     final class T3tIdentifier {
47         public final String systemCode;
48         public final String nfcid2;
49         public final String t3tPmm;
50 
T3tIdentifier(String systemCode, String nfcid2, String t3tPmm)51         T3tIdentifier(String systemCode, String nfcid2, String t3tPmm) {
52             this.systemCode = systemCode;
53             this.nfcid2 = nfcid2;
54             this.t3tPmm = t3tPmm;
55         }
56 
57         @Override
equals(Object o)58         public boolean equals(Object o) {
59             if (this == o) return true;
60             if (o == null || getClass() != o.getClass()) return false;
61 
62             T3tIdentifier that = (T3tIdentifier) o;
63             if (!systemCode.equalsIgnoreCase(that.systemCode)) return false;
64             if (!nfcid2.equalsIgnoreCase(that.nfcid2)) return false;
65 
66             return true;
67         }
68 
69         @Override
hashCode()70         public int hashCode() {
71             int result = systemCode.hashCode();
72             result = 31 * result + nfcid2.hashCode();
73             return result;
74         }
75     }
76 
77     final Context mContext;
78     final SystemCodeRoutingManager mRoutingManager;
79 
80     final Object mLock = new Object();
81 
82     boolean mNfcEnabled = false;
83 
RegisteredT3tIdentifiersCache(Context context)84     public RegisteredT3tIdentifiersCache(Context context) {
85         Log.d(TAG, "RegisteredT3tIdentifiersCache");
86         mContext = context;
87         mRoutingManager = new SystemCodeRoutingManager();
88     }
89 
resolveNfcid2(String nfcid2)90     public NfcFServiceInfo resolveNfcid2(String nfcid2) {
91         synchronized (mLock) {
92             if (DBG) Log.d(TAG, "resolveNfcid2: resolving NFCID " + nfcid2);
93             NfcFServiceInfo resolveInfo;
94             resolveInfo = mForegroundT3tIdentifiersCache.get(nfcid2);
95             Log.d(TAG,
96                     "Resolved to: " + (resolveInfo == null ? "null" : resolveInfo.toString()));
97             return resolveInfo;
98         }
99     }
100 
generateForegroundT3tIdentifiersCacheLocked()101     void generateForegroundT3tIdentifiersCacheLocked() {
102         if (DBG) Log.d(TAG, "generateForegroundT3tIdentifiersCacheLocked");
103         mForegroundT3tIdentifiersCache.clear();
104         if (mEnabledForegroundService != null) {
105             for (NfcFServiceInfo service : mServices) {
106                 if (mEnabledForegroundService.equals(service.getComponent())) {
107                     if (!service.getSystemCode().equalsIgnoreCase("NULL") &&
108                             !service.getNfcid2().equalsIgnoreCase("NULL")) {
109                         mForegroundT3tIdentifiersCache.put(service.getNfcid2(), service);
110                     }
111                     break;
112                 }
113             }
114         }
115 
116         if (DBG) {
117             Log.d(TAG, "mForegroundT3tIdentifiersCache: size=" +
118                     mForegroundT3tIdentifiersCache.size());
119             for (Map.Entry<String, NfcFServiceInfo> entry :
120                     mForegroundT3tIdentifiersCache.entrySet()) {
121                 Log.d(TAG, "    " + entry.getKey() +
122                         "/" + entry.getValue().getComponent().toString());
123             }
124         }
125 
126         updateRoutingLocked();
127     }
128 
updateRoutingLocked()129     void updateRoutingLocked() {
130         if (DBG) Log.d(TAG, "updateRoutingLocked");
131         if (!mNfcEnabled) {
132             Log.d(TAG, "Not updating routing table because NFC is off.");
133             return;
134         }
135         List<T3tIdentifier> t3tIdentifiers = new ArrayList<T3tIdentifier>();
136         Iterator<Map.Entry<String, NfcFServiceInfo>> it;
137         // Register foreground service
138         it = mForegroundT3tIdentifiersCache.entrySet().iterator();
139         while (it.hasNext()) {
140             Map.Entry<String, NfcFServiceInfo> entry =
141                     (Map.Entry<String, NfcFServiceInfo>) it.next();
142             t3tIdentifiers.add(new T3tIdentifier(
143                     entry.getValue().getSystemCode(), entry.getValue().getNfcid2(), entry.getValue().getT3tPmm()));
144         }
145         mRoutingManager.configureRouting(t3tIdentifiers);
146     }
147 
onServicesUpdated(int userId, List<NfcFServiceInfo> services)148     public void onServicesUpdated(int userId, List<NfcFServiceInfo> services) {
149         if (DBG) Log.d(TAG, "onServicesUpdated");
150         synchronized (mLock) {
151             if (ActivityManager.getCurrentUser() == userId) {
152                 // Rebuild our internal data-structures
153                 mServices = services;
154             } else {
155                 Log.d(TAG, "Ignoring update because it's not for the current user.");
156             }
157         }
158     }
159 
onEnabledForegroundNfcFServiceChanged(ComponentName component)160     public void onEnabledForegroundNfcFServiceChanged(ComponentName component) {
161         if (DBG) Log.d(TAG, "Enabled foreground service changed.");
162         synchronized (mLock) {
163             if (component != null) {
164                 if (mEnabledForegroundService != null) {
165                     return;
166                 }
167                 mEnabledForegroundService = component;
168             } else {
169                 if (mEnabledForegroundService == null) {
170                     return;
171                 }
172                 mEnabledForegroundService = null;
173             }
174             generateForegroundT3tIdentifiersCacheLocked();
175         }
176     }
177 
onNfcEnabled()178     public void onNfcEnabled() {
179         synchronized (mLock) {
180             mNfcEnabled = true;
181         }
182     }
183 
onNfcDisabled()184     public void onNfcDisabled() {
185         synchronized (mLock) {
186             mNfcEnabled = false;
187             mForegroundT3tIdentifiersCache.clear();
188             mEnabledForegroundService = null;
189         }
190         mRoutingManager.onNfccRoutingTableCleared();
191     }
192 
onUserSwitched()193     public void onUserSwitched() {
194         synchronized (mLock) {
195             mForegroundT3tIdentifiersCache.clear();
196             updateRoutingLocked();
197             mEnabledForegroundService = null;
198         }
199     }
200 
dump(FileDescriptor fd, PrintWriter pw, String[] args)201     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
202         pw.println("T3T Identifier cache entries: ");
203         for (Map.Entry<String, NfcFServiceInfo> entry : mForegroundT3tIdentifiersCache.entrySet()) {
204             pw.println("    NFCID2: " + entry.getKey());
205             pw.println("    NfcFServiceInfo: ");
206             entry.getValue().dump(fd, pw, args);
207         }
208         pw.println("");
209         mRoutingManager.dump(fd, pw, args);
210         pw.println("");
211     }
212 }
213