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.invalidateCache(userId); 158 } 159 160 public void onNfcEnabled() { 161 // for HCE 162 mAidCache.onNfcEnabled(); 163 // for HCE-F 164 mT3tIdentifiersCache.onNfcEnabled(); 165 } 166 167 public void onNfcDisabled() { 168 // for HCE 169 mAidCache.onNfcDisabled(); 170 // for HCE-F 171 mHostNfcFEmulationManager.onNfcDisabled(); 172 mNfcFServicesCache.onNfcDisabled(); 173 mT3tIdentifiersCache.onNfcDisabled(); 174 mEnabledNfcFServices.onNfcDisabled(); 175 } 176 177 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 178 mServiceCache.dump(fd, pw, args); 179 mNfcFServicesCache.dump(fd, pw ,args); 180 mPreferredServices.dump(fd, pw, args); 181 mEnabledNfcFServices.dump(fd, pw, args); 182 mAidCache.dump(fd, pw, args); 183 mT3tIdentifiersCache.dump(fd, pw, args); 184 mHostEmulationManager.dump(fd, pw, args); 185 mHostNfcFEmulationManager.dump(fd, pw, args); 186 } 187 188 @Override 189 public void onServicesUpdated(int userId, List<ApduServiceInfo> services) { 190 // Verify defaults are still sane 191 verifyDefaults(userId, services); 192 // Update the AID cache 193 mAidCache.onServicesUpdated(userId, services); 194 // Update the preferred services list 195 mPreferredServices.onServicesUpdated(); 196 } 197 198 @Override 199 public void onNfcFServicesUpdated(int userId, List<NfcFServiceInfo> services) { 200 // Update the T3T identifier cache 201 mT3tIdentifiersCache.onServicesUpdated(userId, services); 202 // Update the enabled services list 203 mEnabledNfcFServices.onServicesUpdated(); 204 } 205 206 void verifyDefaults(int userId, List<ApduServiceInfo> services) { 207 ComponentName defaultPaymentService = 208 getDefaultServiceForCategory(userId, CardEmulation.CATEGORY_PAYMENT, false); 209 if (DBG) Log.d(TAG, "Current default: " + defaultPaymentService); 210 if (defaultPaymentService != null) { 211 // Validate the default is still installed and handling payment 212 ApduServiceInfo serviceInfo = mServiceCache.getService(userId, defaultPaymentService); 213 if (serviceInfo == null || !serviceInfo.hasCategory(CardEmulation.CATEGORY_PAYMENT)) { 214 if (serviceInfo == null) { 215 Log.e(TAG, "Default payment service unexpectedly removed."); 216 } else if (!serviceInfo.hasCategory(CardEmulation.CATEGORY_PAYMENT)) { 217 if (DBG) Log.d(TAG, "Default payment service had payment category removed"); 218 } 219 int numPaymentServices = 0; 220 ComponentName lastFoundPaymentService = null; 221 for (ApduServiceInfo service : services) { 222 if (service.hasCategory(CardEmulation.CATEGORY_PAYMENT)) { 223 numPaymentServices++; 224 lastFoundPaymentService = service.getComponent(); 225 } 226 } 227 if (DBG) Log.d(TAG, "Number of payment services is " + 228 Integer.toString(numPaymentServices)); 229 if (numPaymentServices == 0) { 230 if (DBG) Log.d(TAG, "Default removed, no services left."); 231 // No payment services left, unset default and don't ask the user 232 setDefaultServiceForCategoryChecked(userId, null, CardEmulation.CATEGORY_PAYMENT); 233 } else if (numPaymentServices == 1) { 234 // Only one left, automatically make it the default 235 if (DBG) Log.d(TAG, "Default removed, making remaining service default."); 236 setDefaultServiceForCategoryChecked(userId, lastFoundPaymentService, 237 CardEmulation.CATEGORY_PAYMENT); 238 } else if (numPaymentServices > 1) { 239 // More than one left, unset default and ask the user if he wants 240 // to set a new one 241 if (DBG) Log.d(TAG, "Default removed, asking user to pick."); 242 setDefaultServiceForCategoryChecked(userId, null, 243 CardEmulation.CATEGORY_PAYMENT); 244 Intent intent = new Intent(mContext, DefaultRemovedActivity.class); 245 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); 246 mContext.startActivityAsUser(intent, UserHandle.CURRENT); 247 } 248 } else { 249 // Default still exists and handles the category, nothing do 250 if (DBG) Log.d(TAG, "Default payment service still ok."); 251 } 252 } else { 253 // A payment service may have been removed, leaving only one; 254 // in that case, automatically set that app as default. 255 int numPaymentServices = 0; 256 ComponentName lastFoundPaymentService = null; 257 for (ApduServiceInfo service : services) { 258 if (service.hasCategory(CardEmulation.CATEGORY_PAYMENT)) { 259 numPaymentServices++; 260 lastFoundPaymentService = service.getComponent(); 261 } 262 } 263 if (numPaymentServices > 1) { 264 // More than one service left, leave default unset 265 if (DBG) Log.d(TAG, "No default set, more than one service left."); 266 } else if (numPaymentServices == 1) { 267 // Make single found payment service the default 268 if (DBG) Log.d(TAG, "No default set, making single service default."); 269 setDefaultServiceForCategoryChecked(userId, lastFoundPaymentService, 270 CardEmulation.CATEGORY_PAYMENT); 271 } else { 272 // No payment services left, leave default at null 273 if (DBG) Log.d(TAG, "No default set, last payment service removed."); 274 } 275 } 276 } 277 278 ComponentName getDefaultServiceForCategory(int userId, String category, 279 boolean validateInstalled) { 280 if (!CardEmulation.CATEGORY_PAYMENT.equals(category)) { 281 Log.e(TAG, "Not allowing defaults for category " + category); 282 return null; 283 } 284 // Load current payment default from settings 285 String name = Settings.Secure.getStringForUser( 286 mContext.getContentResolver(), Settings.Secure.NFC_PAYMENT_DEFAULT_COMPONENT, 287 userId); 288 if (name != null) { 289 ComponentName service = ComponentName.unflattenFromString(name); 290 if (!validateInstalled || service == null) { 291 return service; 292 } else { 293 return mServiceCache.hasService(userId, service) ? service : null; 294 } 295 } else { 296 return null; 297 } 298 } 299 300 boolean setDefaultServiceForCategoryChecked(int userId, ComponentName service, 301 String category) { 302 if (!CardEmulation.CATEGORY_PAYMENT.equals(category)) { 303 Log.e(TAG, "Not allowing defaults for category " + category); 304 return false; 305 } 306 // TODO Not really nice to be writing to Settings.Secure here... 307 // ideally we overlay our local changes over whatever is in 308 // Settings.Secure 309 if (service == null || mServiceCache.hasService(userId, service)) { 310 Settings.Secure.putStringForUser(mContext.getContentResolver(), 311 Settings.Secure.NFC_PAYMENT_DEFAULT_COMPONENT, 312 service != null ? service.flattenToString() : null, userId); 313 } else { 314 Log.e(TAG, "Could not find default service to make default: " + service); 315 } 316 return true; 317 } 318 319 boolean isServiceRegistered(int userId, ComponentName service) { 320 boolean serviceFound = mServiceCache.hasService(userId, service); 321 if (!serviceFound) { 322 // If we don't know about this service yet, it may have just been enabled 323 // using PackageManager.setComponentEnabledSetting(). The PackageManager 324 // broadcasts are delayed by 10 seconds in that scenario, which causes 325 // calls to our APIs referencing that service to fail. 326 // Hence, update the cache in case we don't know about the service. 327 if (DBG) Log.d(TAG, "Didn't find passed in service, invalidating cache."); 328 mServiceCache.invalidateCache(userId); 329 } 330 return mServiceCache.hasService(userId, service); 331 } 332 333 boolean isNfcFServiceInstalled(int userId, ComponentName service) { 334 boolean serviceFound = mNfcFServicesCache.hasService(userId, service); 335 if (!serviceFound) { 336 // If we don't know about this service yet, it may have just been enabled 337 // using PackageManager.setComponentEnabledSetting(). The PackageManager 338 // broadcasts are delayed by 10 seconds in that scenario, which causes 339 // calls to our APIs referencing that service to fail. 340 // Hence, update the cache in case we don't know about the service. 341 if (DBG) Log.d(TAG, "Didn't find passed in service, invalidating cache."); 342 mNfcFServicesCache.invalidateCache(userId); 343 } 344 return mNfcFServicesCache.hasService(userId, service); 345 } 346 347 /** 348 * Returns whether a service in this package is preferred, 349 * either because it's the default payment app or it's running 350 * in the foreground. 351 */ 352 public boolean packageHasPreferredService(String packageName) { 353 return mPreferredServices.packageHasPreferredService(packageName); 354 } 355 356 /** 357 * This class implements the application-facing APIs and are called 358 * from binder. All calls must be permission-checked. 359 */ 360 final class CardEmulationInterface extends INfcCardEmulation.Stub { 361 @Override 362 public boolean isDefaultServiceForCategory(int userId, ComponentName service, 363 String category) { 364 NfcPermissions.enforceUserPermissions(mContext); 365 NfcPermissions.validateUserId(userId); 366 if (!isServiceRegistered(userId, service)) { 367 return false; 368 } 369 ComponentName defaultService = 370 getDefaultServiceForCategory(userId, category, true); 371 return (defaultService != null && defaultService.equals(service)); 372 } 373 374 @Override 375 public boolean isDefaultServiceForAid(int userId, 376 ComponentName service, String aid) throws RemoteException { 377 NfcPermissions.validateUserId(userId); 378 NfcPermissions.enforceUserPermissions(mContext); 379 if (!isServiceRegistered(userId, service)) { 380 return false; 381 } 382 return mAidCache.isDefaultServiceForAid(userId, service, aid); 383 } 384 385 @Override 386 public boolean setDefaultServiceForCategory(int userId, 387 ComponentName service, String category) throws RemoteException { 388 NfcPermissions.validateUserId(userId); 389 NfcPermissions.enforceAdminPermissions(mContext); 390 if (!isServiceRegistered(userId, service)) { 391 return false; 392 } 393 return setDefaultServiceForCategoryChecked(userId, service, category); 394 } 395 396 @Override 397 public boolean setDefaultForNextTap(int userId, ComponentName service) 398 throws RemoteException { 399 NfcPermissions.validateUserId(userId); 400 NfcPermissions.enforceAdminPermissions(mContext); 401 if (!isServiceRegistered(userId, service)) { 402 return false; 403 } 404 return mPreferredServices.setDefaultForNextTap(service); 405 } 406 407 @Override 408 public boolean registerAidGroupForService(int userId, 409 ComponentName service, AidGroup aidGroup) throws RemoteException { 410 NfcPermissions.validateUserId(userId); 411 NfcPermissions.enforceUserPermissions(mContext); 412 if (!isServiceRegistered(userId, service)) { 413 return false; 414 } 415 return mServiceCache.registerAidGroupForService(userId, Binder.getCallingUid(), service, 416 aidGroup); 417 } 418 419 @Override 420 public AidGroup getAidGroupForService(int userId, 421 ComponentName service, String category) throws RemoteException { 422 NfcPermissions.validateUserId(userId); 423 NfcPermissions.enforceUserPermissions(mContext); 424 if (!isServiceRegistered(userId, service)) { 425 return null; 426 } 427 return mServiceCache.getAidGroupForService(userId, Binder.getCallingUid(), service, 428 category); 429 } 430 431 @Override 432 public boolean removeAidGroupForService(int userId, 433 ComponentName service, String category) throws RemoteException { 434 NfcPermissions.validateUserId(userId); 435 NfcPermissions.enforceUserPermissions(mContext); 436 if (!isServiceRegistered(userId, service)) { 437 return false; 438 } 439 return mServiceCache.removeAidGroupForService(userId, Binder.getCallingUid(), service, 440 category); 441 } 442 443 @Override 444 public List<ApduServiceInfo> getServices(int userId, String category) 445 throws RemoteException { 446 NfcPermissions.validateUserId(userId); 447 NfcPermissions.enforceAdminPermissions(mContext); 448 return mServiceCache.getServicesForCategory(userId, category); 449 } 450 451 @Override 452 public boolean setPreferredService(ComponentName service) 453 throws RemoteException { 454 NfcPermissions.enforceUserPermissions(mContext); 455 if (!isServiceRegistered(UserHandle.getCallingUserId(), service)) { 456 Log.e(TAG, "setPreferredService: unknown component."); 457 return false; 458 } 459 return mPreferredServices.registerPreferredForegroundService(service, 460 Binder.getCallingUid()); 461 } 462 463 @Override 464 public boolean unsetPreferredService() throws RemoteException { 465 NfcPermissions.enforceUserPermissions(mContext); 466 return mPreferredServices.unregisteredPreferredForegroundService( 467 Binder.getCallingUid()); 468 } 469 470 @Override 471 public boolean supportsAidPrefixRegistration() throws RemoteException { 472 return mAidCache.supportsAidPrefixRegistration(); 473 } 474 } 475 476 /** 477 * This class implements the application-facing APIs and are called 478 * from binder. All calls must be permission-checked. 479 */ 480 final class NfcFCardEmulationInterface extends INfcFCardEmulation.Stub { 481 @Override 482 public String getSystemCodeForService(int userId, ComponentName service) 483 throws RemoteException { 484 NfcPermissions.validateUserId(userId); 485 NfcPermissions.enforceUserPermissions(mContext); 486 if (!isNfcFServiceInstalled(userId, service)) { 487 return null; 488 } 489 return mNfcFServicesCache.getSystemCodeForService( 490 userId, Binder.getCallingUid(), service); 491 } 492 493 @Override 494 public boolean registerSystemCodeForService(int userId, ComponentName service, 495 String systemCode) 496 throws RemoteException { 497 NfcPermissions.validateUserId(userId); 498 NfcPermissions.enforceUserPermissions(mContext); 499 if (!isNfcFServiceInstalled(userId, service)) { 500 return false; 501 } 502 return mNfcFServicesCache.registerSystemCodeForService( 503 userId, Binder.getCallingUid(), service, systemCode); 504 } 505 506 @Override 507 public boolean removeSystemCodeForService(int userId, ComponentName service) 508 throws RemoteException { 509 NfcPermissions.validateUserId(userId); 510 NfcPermissions.enforceUserPermissions(mContext); 511 if (!isNfcFServiceInstalled(userId, service)) { 512 return false; 513 } 514 return mNfcFServicesCache.removeSystemCodeForService( 515 userId, Binder.getCallingUid(), service); 516 } 517 518 @Override 519 public String getNfcid2ForService(int userId, ComponentName service) 520 throws RemoteException { 521 NfcPermissions.validateUserId(userId); 522 NfcPermissions.enforceUserPermissions(mContext); 523 if (!isNfcFServiceInstalled(userId, service)) { 524 return null; 525 } 526 return mNfcFServicesCache.getNfcid2ForService( 527 userId, Binder.getCallingUid(), service); 528 } 529 530 @Override 531 public boolean setNfcid2ForService(int userId, 532 ComponentName service, String nfcid2) throws RemoteException { 533 NfcPermissions.validateUserId(userId); 534 NfcPermissions.enforceUserPermissions(mContext); 535 if (!isNfcFServiceInstalled(userId, service)) { 536 return false; 537 } 538 return mNfcFServicesCache.setNfcid2ForService( 539 userId, Binder.getCallingUid(), service, nfcid2); 540 } 541 542 @Override 543 public boolean enableNfcFForegroundService(ComponentName service) 544 throws RemoteException { 545 NfcPermissions.enforceUserPermissions(mContext); 546 if (isNfcFServiceInstalled(UserHandle.getCallingUserId(), service)) { 547 return mEnabledNfcFServices.registerEnabledForegroundService(service, 548 Binder.getCallingUid()); 549 } 550 return false; 551 } 552 553 @Override 554 public boolean disableNfcFForegroundService() throws RemoteException { 555 NfcPermissions.enforceUserPermissions(mContext); 556 return mEnabledNfcFServices.unregisteredEnabledForegroundService( 557 Binder.getCallingUid()); 558 } 559 560 @Override 561 public List<NfcFServiceInfo> getNfcFServices(int userId) 562 throws RemoteException { 563 NfcPermissions.validateUserId(userId); 564 NfcPermissions.enforceUserPermissions(mContext); 565 return mNfcFServicesCache.getServices(userId); 566 } 567 568 @Override 569 public int getMaxNumOfRegisterableSystemCodes() 570 throws RemoteException { 571 NfcPermissions.enforceUserPermissions(mContext); 572 return NfcService.getInstance().getLfT3tMax(); 573 } 574 } 575 576 @Override 577 public void onPreferredPaymentServiceChanged(ComponentName service) { 578 mAidCache.onPreferredPaymentServiceChanged(service); 579 mHostEmulationManager.onPreferredPaymentServiceChanged(service); 580 } 581 582 @Override 583 public void onPreferredForegroundServiceChanged(ComponentName service) { 584 mAidCache.onPreferredForegroundServiceChanged(service); 585 mHostEmulationManager.onPreferredForegroundServiceChanged(service); 586 } 587 588 @Override 589 public void onEnabledForegroundNfcFServiceChanged(ComponentName service) { 590 mT3tIdentifiersCache.onEnabledForegroundNfcFServiceChanged(service); 591 mHostNfcFEmulationManager.onEnabledForegroundNfcFServiceChanged(service); 592 } 593 } 594