1 /* 2 * Copyright (C) 2014 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 package com.android.nfc.cardemulation; 17 18 import java.io.FileDescriptor; 19 import java.io.PrintWriter; 20 import java.util.List; 21 22 import android.content.ComponentName; 23 import android.content.Context; 24 import android.content.Intent; 25 import android.nfc.INfcCardEmulation; 26 import android.nfc.INfcFCardEmulation; 27 import android.nfc.cardemulation.AidGroup; 28 import android.nfc.cardemulation.ApduServiceInfo; 29 import android.nfc.cardemulation.NfcFServiceInfo; 30 import android.nfc.cardemulation.CardEmulation; 31 import android.nfc.cardemulation.NfcFCardEmulation; 32 import android.os.Binder; 33 import android.os.RemoteException; 34 import android.os.UserHandle; 35 import android.os.PowerManager; 36 import android.os.SystemClock; 37 import android.provider.Settings; 38 import android.util.Log; 39 40 import com.android.nfc.NfcPermissions; 41 import com.android.nfc.NfcService; 42 import com.android.nfc.cardemulation.RegisteredServicesCache; 43 import com.android.nfc.cardemulation.RegisteredNfcFServicesCache; 44 45 /** 46 * CardEmulationManager is the central entity 47 * responsible for delegating to individual components 48 * implementing card emulation: 49 * - RegisteredServicesCache keeping track of HCE and SE services on the device 50 * - RegisteredNfcFServicesCache keeping track of HCE-F services on the device 51 * - RegisteredAidCache keeping track of AIDs registered by those services and manages 52 * the routing table in the NFCC. 53 * - RegisteredT3tIdentifiersCache keeping track of T3T Identifier registered by 54 * those services and manages the routing table in the NFCC. 55 * - HostEmulationManager handles incoming APDUs for the host and forwards to HCE 56 * services as necessary. 57 * - HostNfcFEmulationManager handles incoming NFC-F packets for the host and 58 * forwards to HCE-F services as necessary. 59 */ 60 public class CardEmulationManager implements RegisteredServicesCache.Callback, 61 RegisteredNfcFServicesCache.Callback, PreferredServices.Callback, 62 EnabledNfcFServices.Callback { 63 static final String TAG = "CardEmulationManager"; 64 static final boolean DBG = false; 65 66 static final int NFC_HCE_APDU = 0x01; 67 static final int NFC_HCE_NFCF = 0x04; 68 69 final RegisteredAidCache mAidCache; 70 final RegisteredT3tIdentifiersCache mT3tIdentifiersCache; 71 final RegisteredServicesCache mServiceCache; 72 final RegisteredNfcFServicesCache mNfcFServicesCache; 73 final HostEmulationManager mHostEmulationManager; 74 final HostNfcFEmulationManager mHostNfcFEmulationManager; 75 final PreferredServices mPreferredServices; 76 final EnabledNfcFServices mEnabledNfcFServices; 77 final Context mContext; 78 final CardEmulationInterface mCardEmulationInterface; 79 final NfcFCardEmulationInterface mNfcFCardEmulationInterface; 80 final PowerManager mPowerManager; 81 82 public CardEmulationManager(Context context) { 83 mContext = context; 84 mCardEmulationInterface = new CardEmulationInterface(); 85 mNfcFCardEmulationInterface = new NfcFCardEmulationInterface(); 86 mAidCache = new RegisteredAidCache(context); 87 mT3tIdentifiersCache = new RegisteredT3tIdentifiersCache(context); 88 mHostEmulationManager = new HostEmulationManager(context, mAidCache); 89 mHostNfcFEmulationManager = new HostNfcFEmulationManager(context, mT3tIdentifiersCache); 90 mServiceCache = new RegisteredServicesCache(context, this); 91 mNfcFServicesCache = new RegisteredNfcFServicesCache(context, this); 92 mPreferredServices = new PreferredServices(context, mServiceCache, mAidCache, this); 93 mEnabledNfcFServices = new EnabledNfcFServices( 94 context, mNfcFServicesCache, mT3tIdentifiersCache, this); 95 mServiceCache.initialize(); 96 mNfcFServicesCache.initialize(); 97 mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE); 98 } 99 100 public INfcCardEmulation getNfcCardEmulationInterface() { 101 return mCardEmulationInterface; 102 } 103 104 public INfcFCardEmulation getNfcFCardEmulationInterface() { 105 return mNfcFCardEmulationInterface; 106 } 107 108 109 public void onHostCardEmulationActivated(int technology) { 110 if (mPowerManager != null) { 111 mPowerManager.userActivity(SystemClock.uptimeMillis(), PowerManager.USER_ACTIVITY_EVENT_TOUCH, 0); 112 } 113 if (technology == NFC_HCE_APDU) { 114 mHostEmulationManager.onHostEmulationActivated(); 115 mPreferredServices.onHostEmulationActivated(); 116 } else if (technology == NFC_HCE_NFCF) { 117 mHostNfcFEmulationManager.onHostEmulationActivated(); 118 mNfcFServicesCache.onHostEmulationActivated(); 119 mEnabledNfcFServices.onHostEmulationActivated(); 120 } 121 } 122 123 public void onHostCardEmulationData(int technology, byte[] data) { 124 if (mPowerManager != null) { 125 mPowerManager.userActivity(SystemClock.uptimeMillis(), PowerManager.USER_ACTIVITY_EVENT_TOUCH, 0); 126 } 127 if (technology == NFC_HCE_APDU) { 128 mHostEmulationManager.onHostEmulationData(data); 129 } else if (technology == NFC_HCE_NFCF) { 130 mHostNfcFEmulationManager.onHostEmulationData(data); 131 } 132 } 133 134 public void onHostCardEmulationDeactivated(int technology) { 135 if (technology == NFC_HCE_APDU) { 136 mHostEmulationManager.onHostEmulationDeactivated(); 137 mPreferredServices.onHostEmulationDeactivated(); 138 } else if (technology == NFC_HCE_NFCF) { 139 mHostNfcFEmulationManager.onHostEmulationDeactivated(); 140 mNfcFServicesCache.onHostEmulationDeactivated(); 141 mEnabledNfcFServices.onHostEmulationDeactivated(); 142 } 143 } 144 145 public void onOffHostAidSelected() { 146 mHostEmulationManager.onOffHostAidSelected(); 147 } 148 149 public void onUserSwitched(int userId) { 150 // for HCE 151 mServiceCache.invalidateCache(userId); 152 mPreferredServices.onUserSwitched(userId); 153 // for HCE-F 154 mHostNfcFEmulationManager.onUserSwitched(); 155 mT3tIdentifiersCache.onUserSwitched(); 156 mEnabledNfcFServices.onUserSwitched(userId); 157 mNfcFServicesCache.onUserSwitched(); 158 mNfcFServicesCache.invalidateCache(userId); 159 } 160 161 public void onNfcEnabled() { 162 // for HCE 163 mAidCache.onNfcEnabled(); 164 // for HCE-F 165 mT3tIdentifiersCache.onNfcEnabled(); 166 } 167 168 public void onNfcDisabled() { 169 // for HCE 170 mAidCache.onNfcDisabled(); 171 // for HCE-F 172 mHostNfcFEmulationManager.onNfcDisabled(); 173 mNfcFServicesCache.onNfcDisabled(); 174 mT3tIdentifiersCache.onNfcDisabled(); 175 mEnabledNfcFServices.onNfcDisabled(); 176 } 177 178 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 179 mServiceCache.dump(fd, pw, args); 180 mNfcFServicesCache.dump(fd, pw ,args); 181 mPreferredServices.dump(fd, pw, args); 182 mEnabledNfcFServices.dump(fd, pw, args); 183 mAidCache.dump(fd, pw, args); 184 mT3tIdentifiersCache.dump(fd, pw, args); 185 mHostEmulationManager.dump(fd, pw, args); 186 mHostNfcFEmulationManager.dump(fd, pw, args); 187 } 188 189 @Override 190 public void onServicesUpdated(int userId, List<ApduServiceInfo> services) { 191 // Verify defaults are still sane 192 verifyDefaults(userId, services); 193 // Update the AID cache 194 mAidCache.onServicesUpdated(userId, services); 195 // Update the preferred services list 196 mPreferredServices.onServicesUpdated(); 197 } 198 199 @Override 200 public void onNfcFServicesUpdated(int userId, List<NfcFServiceInfo> services) { 201 // Update the T3T identifier cache 202 mT3tIdentifiersCache.onServicesUpdated(userId, services); 203 // Update the enabled services list 204 mEnabledNfcFServices.onServicesUpdated(); 205 } 206 207 void verifyDefaults(int userId, List<ApduServiceInfo> services) { 208 ComponentName defaultPaymentService = 209 getDefaultServiceForCategory(userId, CardEmulation.CATEGORY_PAYMENT, false); 210 if (DBG) Log.d(TAG, "Current default: " + defaultPaymentService); 211 if (defaultPaymentService == null) { 212 // A payment service may have been removed, leaving only one; 213 // in that case, automatically set that app as default. 214 int numPaymentServices = 0; 215 ComponentName lastFoundPaymentService = null; 216 for (ApduServiceInfo service : services) { 217 if (service.hasCategory(CardEmulation.CATEGORY_PAYMENT)) { 218 numPaymentServices++; 219 lastFoundPaymentService = service.getComponent(); 220 } 221 } 222 if (numPaymentServices > 1) { 223 // More than one service left, leave default unset 224 if (DBG) Log.d(TAG, "No default set, more than one service left."); 225 } else if (numPaymentServices == 1) { 226 // Make single found payment service the default 227 if (DBG) Log.d(TAG, "No default set, making single service default."); 228 setDefaultServiceForCategoryChecked(userId, lastFoundPaymentService, 229 CardEmulation.CATEGORY_PAYMENT); 230 } else { 231 // No payment services left, leave default at null 232 if (DBG) Log.d(TAG, "No default set, last payment service removed."); 233 } 234 } 235 } 236 237 ComponentName getDefaultServiceForCategory(int userId, String category, 238 boolean validateInstalled) { 239 if (!CardEmulation.CATEGORY_PAYMENT.equals(category)) { 240 Log.e(TAG, "Not allowing defaults for category " + category); 241 return null; 242 } 243 // Load current payment default from settings 244 String name = Settings.Secure.getStringForUser( 245 mContext.getContentResolver(), Settings.Secure.NFC_PAYMENT_DEFAULT_COMPONENT, 246 userId); 247 if (name != null) { 248 ComponentName service = ComponentName.unflattenFromString(name); 249 if (!validateInstalled || service == null) { 250 return service; 251 } else { 252 return mServiceCache.hasService(userId, service) ? service : null; 253 } 254 } else { 255 return null; 256 } 257 } 258 259 boolean setDefaultServiceForCategoryChecked(int userId, ComponentName service, 260 String category) { 261 if (!CardEmulation.CATEGORY_PAYMENT.equals(category)) { 262 Log.e(TAG, "Not allowing defaults for category " + category); 263 return false; 264 } 265 // TODO Not really nice to be writing to Settings.Secure here... 266 // ideally we overlay our local changes over whatever is in 267 // Settings.Secure 268 if (service == null || mServiceCache.hasService(userId, service)) { 269 Settings.Secure.putStringForUser(mContext.getContentResolver(), 270 Settings.Secure.NFC_PAYMENT_DEFAULT_COMPONENT, 271 service != null ? service.flattenToString() : null, userId); 272 } else { 273 Log.e(TAG, "Could not find default service to make default: " + service); 274 } 275 return true; 276 } 277 278 boolean isServiceRegistered(int userId, ComponentName service) { 279 boolean serviceFound = mServiceCache.hasService(userId, service); 280 if (!serviceFound) { 281 // If we don't know about this service yet, it may have just been enabled 282 // using PackageManager.setComponentEnabledSetting(). The PackageManager 283 // broadcasts are delayed by 10 seconds in that scenario, which causes 284 // calls to our APIs referencing that service to fail. 285 // Hence, update the cache in case we don't know about the service. 286 if (DBG) Log.d(TAG, "Didn't find passed in service, invalidating cache."); 287 mServiceCache.invalidateCache(userId); 288 } 289 return mServiceCache.hasService(userId, service); 290 } 291 292 boolean isNfcFServiceInstalled(int userId, ComponentName service) { 293 boolean serviceFound = mNfcFServicesCache.hasService(userId, service); 294 if (!serviceFound) { 295 // If we don't know about this service yet, it may have just been enabled 296 // using PackageManager.setComponentEnabledSetting(). The PackageManager 297 // broadcasts are delayed by 10 seconds in that scenario, which causes 298 // calls to our APIs referencing that service to fail. 299 // Hence, update the cache in case we don't know about the service. 300 if (DBG) Log.d(TAG, "Didn't find passed in service, invalidating cache."); 301 mNfcFServicesCache.invalidateCache(userId); 302 } 303 return mNfcFServicesCache.hasService(userId, service); 304 } 305 306 /** 307 * Returns whether a service in this package is preferred, 308 * either because it's the default payment app or it's running 309 * in the foreground. 310 */ 311 public boolean packageHasPreferredService(String packageName) { 312 return mPreferredServices.packageHasPreferredService(packageName); 313 } 314 315 /** 316 * This class implements the application-facing APIs and are called 317 * from binder. All calls must be permission-checked. 318 */ 319 final class CardEmulationInterface extends INfcCardEmulation.Stub { 320 @Override 321 public boolean isDefaultServiceForCategory(int userId, ComponentName service, 322 String category) { 323 NfcPermissions.enforceUserPermissions(mContext); 324 NfcPermissions.validateUserId(userId); 325 if (!isServiceRegistered(userId, service)) { 326 return false; 327 } 328 ComponentName defaultService = 329 getDefaultServiceForCategory(userId, category, true); 330 return (defaultService != null && defaultService.equals(service)); 331 } 332 333 @Override 334 public boolean isDefaultServiceForAid(int userId, 335 ComponentName service, String aid) throws RemoteException { 336 NfcPermissions.validateUserId(userId); 337 NfcPermissions.enforceUserPermissions(mContext); 338 if (!isServiceRegistered(userId, service)) { 339 return false; 340 } 341 return mAidCache.isDefaultServiceForAid(userId, service, aid); 342 } 343 344 @Override 345 public boolean setDefaultServiceForCategory(int userId, 346 ComponentName service, String category) throws RemoteException { 347 NfcPermissions.validateUserId(userId); 348 NfcPermissions.enforceAdminPermissions(mContext); 349 if (!isServiceRegistered(userId, service)) { 350 return false; 351 } 352 return setDefaultServiceForCategoryChecked(userId, service, category); 353 } 354 355 @Override 356 public boolean setDefaultForNextTap(int userId, ComponentName service) 357 throws RemoteException { 358 NfcPermissions.validateUserId(userId); 359 NfcPermissions.enforceAdminPermissions(mContext); 360 if (service != null && !isServiceRegistered(userId, service)) { 361 return false; 362 } 363 return mPreferredServices.setDefaultForNextTap(service); 364 } 365 366 @Override 367 public boolean registerAidGroupForService(int userId, 368 ComponentName service, AidGroup aidGroup) throws RemoteException { 369 NfcPermissions.validateUserId(userId); 370 NfcPermissions.enforceUserPermissions(mContext); 371 if (!isServiceRegistered(userId, service)) { 372 return false; 373 } 374 return mServiceCache.registerAidGroupForService(userId, Binder.getCallingUid(), service, 375 aidGroup); 376 } 377 378 @Override 379 public AidGroup getAidGroupForService(int userId, 380 ComponentName service, String category) throws RemoteException { 381 NfcPermissions.validateUserId(userId); 382 NfcPermissions.enforceUserPermissions(mContext); 383 if (!isServiceRegistered(userId, service)) { 384 return null; 385 } 386 return mServiceCache.getAidGroupForService(userId, Binder.getCallingUid(), service, 387 category); 388 } 389 390 @Override 391 public boolean removeAidGroupForService(int userId, 392 ComponentName service, String category) throws RemoteException { 393 NfcPermissions.validateUserId(userId); 394 NfcPermissions.enforceUserPermissions(mContext); 395 if (!isServiceRegistered(userId, service)) { 396 return false; 397 } 398 return mServiceCache.removeAidGroupForService(userId, Binder.getCallingUid(), service, 399 category); 400 } 401 402 @Override 403 public List<ApduServiceInfo> getServices(int userId, String category) 404 throws RemoteException { 405 NfcPermissions.validateUserId(userId); 406 NfcPermissions.enforceAdminPermissions(mContext); 407 return mServiceCache.getServicesForCategory(userId, category); 408 } 409 410 @Override 411 public boolean setPreferredService(ComponentName service) 412 throws RemoteException { 413 NfcPermissions.enforceUserPermissions(mContext); 414 if (!isServiceRegistered(UserHandle.getCallingUserId(), service)) { 415 Log.e(TAG, "setPreferredService: unknown component."); 416 return false; 417 } 418 return mPreferredServices.registerPreferredForegroundService(service, 419 Binder.getCallingUid()); 420 } 421 422 @Override 423 public boolean unsetPreferredService() throws RemoteException { 424 NfcPermissions.enforceUserPermissions(mContext); 425 return mPreferredServices.unregisteredPreferredForegroundService( 426 Binder.getCallingUid()); 427 } 428 429 @Override 430 public boolean supportsAidPrefixRegistration() throws RemoteException { 431 return mAidCache.supportsAidPrefixRegistration(); 432 } 433 } 434 435 /** 436 * This class implements the application-facing APIs and are called 437 * from binder. All calls must be permission-checked. 438 */ 439 final class NfcFCardEmulationInterface extends INfcFCardEmulation.Stub { 440 @Override 441 public String getSystemCodeForService(int userId, ComponentName service) 442 throws RemoteException { 443 NfcPermissions.validateUserId(userId); 444 NfcPermissions.enforceUserPermissions(mContext); 445 if (!isNfcFServiceInstalled(userId, service)) { 446 return null; 447 } 448 return mNfcFServicesCache.getSystemCodeForService( 449 userId, Binder.getCallingUid(), service); 450 } 451 452 @Override 453 public boolean registerSystemCodeForService(int userId, ComponentName service, 454 String systemCode) 455 throws RemoteException { 456 NfcPermissions.validateUserId(userId); 457 NfcPermissions.enforceUserPermissions(mContext); 458 if (!isNfcFServiceInstalled(userId, service)) { 459 return false; 460 } 461 return mNfcFServicesCache.registerSystemCodeForService( 462 userId, Binder.getCallingUid(), service, systemCode); 463 } 464 465 @Override 466 public boolean removeSystemCodeForService(int userId, ComponentName service) 467 throws RemoteException { 468 NfcPermissions.validateUserId(userId); 469 NfcPermissions.enforceUserPermissions(mContext); 470 if (!isNfcFServiceInstalled(userId, service)) { 471 return false; 472 } 473 return mNfcFServicesCache.removeSystemCodeForService( 474 userId, Binder.getCallingUid(), service); 475 } 476 477 @Override 478 public String getNfcid2ForService(int userId, ComponentName service) 479 throws RemoteException { 480 NfcPermissions.validateUserId(userId); 481 NfcPermissions.enforceUserPermissions(mContext); 482 if (!isNfcFServiceInstalled(userId, service)) { 483 return null; 484 } 485 return mNfcFServicesCache.getNfcid2ForService( 486 userId, Binder.getCallingUid(), service); 487 } 488 489 @Override 490 public boolean setNfcid2ForService(int userId, 491 ComponentName service, String nfcid2) throws RemoteException { 492 NfcPermissions.validateUserId(userId); 493 NfcPermissions.enforceUserPermissions(mContext); 494 if (!isNfcFServiceInstalled(userId, service)) { 495 return false; 496 } 497 return mNfcFServicesCache.setNfcid2ForService( 498 userId, Binder.getCallingUid(), service, nfcid2); 499 } 500 501 @Override 502 public boolean enableNfcFForegroundService(ComponentName service) 503 throws RemoteException { 504 NfcPermissions.enforceUserPermissions(mContext); 505 if (isNfcFServiceInstalled(UserHandle.getCallingUserId(), service)) { 506 return mEnabledNfcFServices.registerEnabledForegroundService(service, 507 Binder.getCallingUid()); 508 } 509 return false; 510 } 511 512 @Override 513 public boolean disableNfcFForegroundService() throws RemoteException { 514 NfcPermissions.enforceUserPermissions(mContext); 515 return mEnabledNfcFServices.unregisteredEnabledForegroundService( 516 Binder.getCallingUid()); 517 } 518 519 @Override 520 public List<NfcFServiceInfo> getNfcFServices(int userId) 521 throws RemoteException { 522 NfcPermissions.validateUserId(userId); 523 NfcPermissions.enforceUserPermissions(mContext); 524 return mNfcFServicesCache.getServices(userId); 525 } 526 527 @Override 528 public int getMaxNumOfRegisterableSystemCodes() 529 throws RemoteException { 530 NfcPermissions.enforceUserPermissions(mContext); 531 return NfcService.getInstance().getLfT3tMax(); 532 } 533 } 534 535 @Override 536 public void onPreferredPaymentServiceChanged(ComponentName service) { 537 mAidCache.onPreferredPaymentServiceChanged(service); 538 mHostEmulationManager.onPreferredPaymentServiceChanged(service); 539 } 540 541 @Override 542 public void onPreferredForegroundServiceChanged(ComponentName service) { 543 mAidCache.onPreferredForegroundServiceChanged(service); 544 mHostEmulationManager.onPreferredForegroundServiceChanged(service); 545 } 546 547 @Override 548 public void onEnabledForegroundNfcFServiceChanged(ComponentName service) { 549 mT3tIdentifiersCache.onEnabledForegroundNfcFServiceChanged(service); 550 mHostNfcFEmulationManager.onEnabledForegroundNfcFServiceChanged(service); 551 } 552 } 553