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