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