• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
CardEmulationManager(Context context)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 
getNfcCardEmulationInterface()100     public INfcCardEmulation getNfcCardEmulationInterface() {
101         return mCardEmulationInterface;
102     }
103 
getNfcFCardEmulationInterface()104     public INfcFCardEmulation getNfcFCardEmulationInterface() {
105         return mNfcFCardEmulationInterface;
106     }
107 
108 
onHostCardEmulationActivated(int technology)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 
onHostCardEmulationData(int technology, byte[] data)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 
onHostCardEmulationDeactivated(int technology)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 
onOffHostAidSelected()145     public void onOffHostAidSelected() {
146         mHostEmulationManager.onOffHostAidSelected();
147     }
148 
onUserSwitched(int userId)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 
onNfcEnabled()160     public void onNfcEnabled() {
161         // for HCE
162         mAidCache.onNfcEnabled();
163         // for HCE-F
164         mT3tIdentifiersCache.onNfcEnabled();
165     }
166 
onNfcDisabled()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 
dump(FileDescriptor fd, PrintWriter pw, String[] args)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
onServicesUpdated(int userId, List<ApduServiceInfo> services)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
onNfcFServicesUpdated(int userId, List<NfcFServiceInfo> services)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 
verifyDefaults(int userId, List<ApduServiceInfo> services)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 
getDefaultServiceForCategory(int userId, String category, boolean validateInstalled)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 
setDefaultServiceForCategoryChecked(int userId, ComponentName service, String category)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 
isServiceRegistered(int userId, ComponentName service)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 
isNfcFServiceInstalled(int userId, ComponentName service)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      */
packageHasPreferredService(String packageName)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
isDefaultServiceForCategory(int userId, ComponentName service, String category)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
isDefaultServiceForAid(int userId, ComponentName service, String aid)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
setDefaultServiceForCategory(int userId, ComponentName service, String category)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
setDefaultForNextTap(int userId, ComponentName service)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
registerAidGroupForService(int userId, ComponentName service, AidGroup aidGroup)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
getAidGroupForService(int userId, ComponentName service, String category)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
removeAidGroupForService(int userId, ComponentName service, String category)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
getServices(int userId, String category)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
setPreferredService(ComponentName service)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
unsetPreferredService()464         public boolean unsetPreferredService() throws RemoteException {
465             NfcPermissions.enforceUserPermissions(mContext);
466             return mPreferredServices.unregisteredPreferredForegroundService(
467                     Binder.getCallingUid());
468         }
469 
470         @Override
supportsAidPrefixRegistration()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
getSystemCodeForService(int userId, ComponentName service)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
registerSystemCodeForService(int userId, ComponentName service, String systemCode)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
removeSystemCodeForService(int userId, ComponentName service)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
getNfcid2ForService(int userId, ComponentName service)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
setNfcid2ForService(int userId, ComponentName service, String nfcid2)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
enableNfcFForegroundService(ComponentName service)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
disableNfcFForegroundService()554         public boolean disableNfcFForegroundService() throws RemoteException {
555             NfcPermissions.enforceUserPermissions(mContext);
556             return mEnabledNfcFServices.unregisteredEnabledForegroundService(
557                     Binder.getCallingUid());
558         }
559 
560         @Override
getNfcFServices(int userId)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
getMaxNumOfRegisterableSystemCodes()569         public int getMaxNumOfRegisterableSystemCodes()
570                 throws RemoteException {
571             NfcPermissions.enforceUserPermissions(mContext);
572             return NfcService.getInstance().getLfT3tMax();
573         }
574     }
575 
576     @Override
onPreferredPaymentServiceChanged(ComponentName service)577     public void onPreferredPaymentServiceChanged(ComponentName service) {
578         mAidCache.onPreferredPaymentServiceChanged(service);
579         mHostEmulationManager.onPreferredPaymentServiceChanged(service);
580     }
581 
582     @Override
onPreferredForegroundServiceChanged(ComponentName service)583     public void onPreferredForegroundServiceChanged(ComponentName service) {
584         mAidCache.onPreferredForegroundServiceChanged(service);
585         mHostEmulationManager.onPreferredForegroundServiceChanged(service);
586     }
587 
588     @Override
onEnabledForegroundNfcFServiceChanged(ComponentName service)589     public void onEnabledForegroundNfcFServiceChanged(ComponentName service) {
590         mT3tIdentifiersCache.onEnabledForegroundNfcFServiceChanged(service);
591         mHostNfcFEmulationManager.onEnabledForegroundNfcFServiceChanged(service);
592     }
593 }
594