Home | History | Annotate | Download | only in cardemulation
      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