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 */ 16package com.android.nfc.cardemulation; 17 18import java.io.FileDescriptor; 19import java.io.PrintWriter; 20import java.util.List; 21 22import android.content.ComponentName; 23import android.content.Context; 24import android.content.Intent; 25import android.nfc.INfcCardEmulation; 26import android.nfc.INfcFCardEmulation; 27import android.nfc.cardemulation.AidGroup; 28import android.nfc.cardemulation.ApduServiceInfo; 29import android.nfc.cardemulation.NfcFServiceInfo; 30import android.nfc.cardemulation.CardEmulation; 31import android.nfc.cardemulation.NfcFCardEmulation; 32import android.os.Binder; 33import android.os.RemoteException; 34import android.os.UserHandle; 35import android.os.PowerManager; 36import android.os.SystemClock; 37import android.provider.Settings; 38import android.util.Log; 39 40import com.android.nfc.NfcPermissions; 41import com.android.nfc.NfcService; 42import com.android.nfc.cardemulation.RegisteredServicesCache; 43import 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 */ 60public 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 // A payment service may have been removed, leaving only one; 212 // in that case, automatically set that app as default. 213 int numPaymentServices = 0; 214 ComponentName lastFoundPaymentService = null; 215 for (ApduServiceInfo service : services) { 216 if (service.hasCategory(CardEmulation.CATEGORY_PAYMENT)) { 217 numPaymentServices++; 218 lastFoundPaymentService = service.getComponent(); 219 } 220 } 221 if (numPaymentServices > 1) { 222 // More than one service left, leave default unset 223 if (DBG) Log.d(TAG, "No default set, more than one service left."); 224 } else if (numPaymentServices == 1) { 225 // Make single found payment service the default 226 if (DBG) Log.d(TAG, "No default set, making single service default."); 227 setDefaultServiceForCategoryChecked(userId, lastFoundPaymentService, 228 CardEmulation.CATEGORY_PAYMENT); 229 } else { 230 // No payment services left, leave default at null 231 if (DBG) Log.d(TAG, "No default set, last payment service removed."); 232 } 233 } 234 } 235 236 ComponentName getDefaultServiceForCategory(int userId, String category, 237 boolean validateInstalled) { 238 if (!CardEmulation.CATEGORY_PAYMENT.equals(category)) { 239 Log.e(TAG, "Not allowing defaults for category " + category); 240 return null; 241 } 242 // Load current payment default from settings 243 String name = Settings.Secure.getStringForUser( 244 mContext.getContentResolver(), Settings.Secure.NFC_PAYMENT_DEFAULT_COMPONENT, 245 userId); 246 if (name != null) { 247 ComponentName service = ComponentName.unflattenFromString(name); 248 if (!validateInstalled || service == null) { 249 return service; 250 } else { 251 return mServiceCache.hasService(userId, service) ? service : null; 252 } 253 } else { 254 return null; 255 } 256 } 257 258 boolean setDefaultServiceForCategoryChecked(int userId, ComponentName service, 259 String category) { 260 if (!CardEmulation.CATEGORY_PAYMENT.equals(category)) { 261 Log.e(TAG, "Not allowing defaults for category " + category); 262 return false; 263 } 264 // TODO Not really nice to be writing to Settings.Secure here... 265 // ideally we overlay our local changes over whatever is in 266 // Settings.Secure 267 if (service == null || mServiceCache.hasService(userId, service)) { 268 Settings.Secure.putStringForUser(mContext.getContentResolver(), 269 Settings.Secure.NFC_PAYMENT_DEFAULT_COMPONENT, 270 service != null ? service.flattenToString() : null, userId); 271 } else { 272 Log.e(TAG, "Could not find default service to make default: " + service); 273 } 274 return true; 275 } 276 277 boolean isServiceRegistered(int userId, ComponentName service) { 278 boolean serviceFound = mServiceCache.hasService(userId, service); 279 if (!serviceFound) { 280 // If we don't know about this service yet, it may have just been enabled 281 // using PackageManager.setComponentEnabledSetting(). The PackageManager 282 // broadcasts are delayed by 10 seconds in that scenario, which causes 283 // calls to our APIs referencing that service to fail. 284 // Hence, update the cache in case we don't know about the service. 285 if (DBG) Log.d(TAG, "Didn't find passed in service, invalidating cache."); 286 mServiceCache.invalidateCache(userId); 287 } 288 return mServiceCache.hasService(userId, service); 289 } 290 291 boolean isNfcFServiceInstalled(int userId, ComponentName service) { 292 boolean serviceFound = mNfcFServicesCache.hasService(userId, service); 293 if (!serviceFound) { 294 // If we don't know about this service yet, it may have just been enabled 295 // using PackageManager.setComponentEnabledSetting(). The PackageManager 296 // broadcasts are delayed by 10 seconds in that scenario, which causes 297 // calls to our APIs referencing that service to fail. 298 // Hence, update the cache in case we don't know about the service. 299 if (DBG) Log.d(TAG, "Didn't find passed in service, invalidating cache."); 300 mNfcFServicesCache.invalidateCache(userId); 301 } 302 return mNfcFServicesCache.hasService(userId, service); 303 } 304 305 /** 306 * Returns whether a service in this package is preferred, 307 * either because it's the default payment app or it's running 308 * in the foreground. 309 */ 310 public boolean packageHasPreferredService(String packageName) { 311 return mPreferredServices.packageHasPreferredService(packageName); 312 } 313 314 /** 315 * This class implements the application-facing APIs and are called 316 * from binder. All calls must be permission-checked. 317 */ 318 final class CardEmulationInterface extends INfcCardEmulation.Stub { 319 @Override 320 public boolean isDefaultServiceForCategory(int userId, ComponentName service, 321 String category) { 322 NfcPermissions.enforceUserPermissions(mContext); 323 NfcPermissions.validateUserId(userId); 324 if (!isServiceRegistered(userId, service)) { 325 return false; 326 } 327 ComponentName defaultService = 328 getDefaultServiceForCategory(userId, category, true); 329 return (defaultService != null && defaultService.equals(service)); 330 } 331 332 @Override 333 public boolean isDefaultServiceForAid(int userId, 334 ComponentName service, String aid) throws RemoteException { 335 NfcPermissions.validateUserId(userId); 336 NfcPermissions.enforceUserPermissions(mContext); 337 if (!isServiceRegistered(userId, service)) { 338 return false; 339 } 340 return mAidCache.isDefaultServiceForAid(userId, service, aid); 341 } 342 343 @Override 344 public boolean setDefaultServiceForCategory(int userId, 345 ComponentName service, String category) throws RemoteException { 346 NfcPermissions.validateUserId(userId); 347 NfcPermissions.enforceAdminPermissions(mContext); 348 if (!isServiceRegistered(userId, service)) { 349 return false; 350 } 351 return setDefaultServiceForCategoryChecked(userId, service, category); 352 } 353 354 @Override 355 public boolean setDefaultForNextTap(int userId, ComponentName service) 356 throws RemoteException { 357 NfcPermissions.validateUserId(userId); 358 NfcPermissions.enforceAdminPermissions(mContext); 359 if (!isServiceRegistered(userId, service)) { 360 return false; 361 } 362 return mPreferredServices.setDefaultForNextTap(service); 363 } 364 365 @Override 366 public boolean registerAidGroupForService(int userId, 367 ComponentName service, AidGroup aidGroup) throws RemoteException { 368 NfcPermissions.validateUserId(userId); 369 NfcPermissions.enforceUserPermissions(mContext); 370 if (!isServiceRegistered(userId, service)) { 371 return false; 372 } 373 return mServiceCache.registerAidGroupForService(userId, Binder.getCallingUid(), service, 374 aidGroup); 375 } 376 377 @Override 378 public AidGroup getAidGroupForService(int userId, 379 ComponentName service, String category) throws RemoteException { 380 NfcPermissions.validateUserId(userId); 381 NfcPermissions.enforceUserPermissions(mContext); 382 if (!isServiceRegistered(userId, service)) { 383 return null; 384 } 385 return mServiceCache.getAidGroupForService(userId, Binder.getCallingUid(), service, 386 category); 387 } 388 389 @Override 390 public boolean removeAidGroupForService(int userId, 391 ComponentName service, String category) throws RemoteException { 392 NfcPermissions.validateUserId(userId); 393 NfcPermissions.enforceUserPermissions(mContext); 394 if (!isServiceRegistered(userId, service)) { 395 return false; 396 } 397 return mServiceCache.removeAidGroupForService(userId, Binder.getCallingUid(), service, 398 category); 399 } 400 401 @Override 402 public List<ApduServiceInfo> getServices(int userId, String category) 403 throws RemoteException { 404 NfcPermissions.validateUserId(userId); 405 NfcPermissions.enforceAdminPermissions(mContext); 406 return mServiceCache.getServicesForCategory(userId, category); 407 } 408 409 @Override 410 public boolean setPreferredService(ComponentName service) 411 throws RemoteException { 412 NfcPermissions.enforceUserPermissions(mContext); 413 if (!isServiceRegistered(UserHandle.getCallingUserId(), service)) { 414 Log.e(TAG, "setPreferredService: unknown component."); 415 return false; 416 } 417 return mPreferredServices.registerPreferredForegroundService(service, 418 Binder.getCallingUid()); 419 } 420 421 @Override 422 public boolean unsetPreferredService() throws RemoteException { 423 NfcPermissions.enforceUserPermissions(mContext); 424 return mPreferredServices.unregisteredPreferredForegroundService( 425 Binder.getCallingUid()); 426 } 427 428 @Override 429 public boolean supportsAidPrefixRegistration() throws RemoteException { 430 return mAidCache.supportsAidPrefixRegistration(); 431 } 432 } 433 434 /** 435 * This class implements the application-facing APIs and are called 436 * from binder. All calls must be permission-checked. 437 */ 438 final class NfcFCardEmulationInterface extends INfcFCardEmulation.Stub { 439 @Override 440 public String getSystemCodeForService(int userId, ComponentName service) 441 throws RemoteException { 442 NfcPermissions.validateUserId(userId); 443 NfcPermissions.enforceUserPermissions(mContext); 444 if (!isNfcFServiceInstalled(userId, service)) { 445 return null; 446 } 447 return mNfcFServicesCache.getSystemCodeForService( 448 userId, Binder.getCallingUid(), service); 449 } 450 451 @Override 452 public boolean registerSystemCodeForService(int userId, ComponentName service, 453 String systemCode) 454 throws RemoteException { 455 NfcPermissions.validateUserId(userId); 456 NfcPermissions.enforceUserPermissions(mContext); 457 if (!isNfcFServiceInstalled(userId, service)) { 458 return false; 459 } 460 return mNfcFServicesCache.registerSystemCodeForService( 461 userId, Binder.getCallingUid(), service, systemCode); 462 } 463 464 @Override 465 public boolean removeSystemCodeForService(int userId, ComponentName service) 466 throws RemoteException { 467 NfcPermissions.validateUserId(userId); 468 NfcPermissions.enforceUserPermissions(mContext); 469 if (!isNfcFServiceInstalled(userId, service)) { 470 return false; 471 } 472 return mNfcFServicesCache.removeSystemCodeForService( 473 userId, Binder.getCallingUid(), service); 474 } 475 476 @Override 477 public String getNfcid2ForService(int userId, ComponentName service) 478 throws RemoteException { 479 NfcPermissions.validateUserId(userId); 480 NfcPermissions.enforceUserPermissions(mContext); 481 if (!isNfcFServiceInstalled(userId, service)) { 482 return null; 483 } 484 return mNfcFServicesCache.getNfcid2ForService( 485 userId, Binder.getCallingUid(), service); 486 } 487 488 @Override 489 public boolean setNfcid2ForService(int userId, 490 ComponentName service, String nfcid2) throws RemoteException { 491 NfcPermissions.validateUserId(userId); 492 NfcPermissions.enforceUserPermissions(mContext); 493 if (!isNfcFServiceInstalled(userId, service)) { 494 return false; 495 } 496 return mNfcFServicesCache.setNfcid2ForService( 497 userId, Binder.getCallingUid(), service, nfcid2); 498 } 499 500 @Override 501 public boolean enableNfcFForegroundService(ComponentName service) 502 throws RemoteException { 503 NfcPermissions.enforceUserPermissions(mContext); 504 if (isNfcFServiceInstalled(UserHandle.getCallingUserId(), service)) { 505 return mEnabledNfcFServices.registerEnabledForegroundService(service, 506 Binder.getCallingUid()); 507 } 508 return false; 509 } 510 511 @Override 512 public boolean disableNfcFForegroundService() throws RemoteException { 513 NfcPermissions.enforceUserPermissions(mContext); 514 return mEnabledNfcFServices.unregisteredEnabledForegroundService( 515 Binder.getCallingUid()); 516 } 517 518 @Override 519 public List<NfcFServiceInfo> getNfcFServices(int userId) 520 throws RemoteException { 521 NfcPermissions.validateUserId(userId); 522 NfcPermissions.enforceUserPermissions(mContext); 523 return mNfcFServicesCache.getServices(userId); 524 } 525 526 @Override 527 public int getMaxNumOfRegisterableSystemCodes() 528 throws RemoteException { 529 NfcPermissions.enforceUserPermissions(mContext); 530 return NfcService.getInstance().getLfT3tMax(); 531 } 532 } 533 534 @Override 535 public void onPreferredPaymentServiceChanged(ComponentName service) { 536 mAidCache.onPreferredPaymentServiceChanged(service); 537 mHostEmulationManager.onPreferredPaymentServiceChanged(service); 538 } 539 540 @Override 541 public void onPreferredForegroundServiceChanged(ComponentName service) { 542 mAidCache.onPreferredForegroundServiceChanged(service); 543 mHostEmulationManager.onPreferredForegroundServiceChanged(service); 544 } 545 546 @Override 547 public void onEnabledForegroundNfcFServiceChanged(ComponentName service) { 548 mT3tIdentifiersCache.onEnabledForegroundNfcFServiceChanged(service); 549 mHostNfcFEmulationManager.onEnabledForegroundNfcFServiceChanged(service); 550 } 551} 552