1 /*
2  * Copyright (C) 2013 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 
17 package com.android.nfc.cardemulation;
18 
19 import android.annotation.TargetApi;
20 import android.annotation.FlaggedApi;
21 import android.app.ActivityManager;
22 import android.app.KeyguardManager;
23 import android.content.ComponentName;
24 import android.content.Context;
25 import android.content.Intent;
26 import android.content.ServiceConnection;
27 import android.content.pm.ApplicationInfo;
28 import android.content.pm.PackageManager;
29 import android.content.pm.PackageManager.NameNotFoundException;
30 import android.nfc.NfcAdapter;
31 import android.nfc.cardemulation.ApduServiceInfo;
32 import android.nfc.cardemulation.CardEmulation;
33 import android.nfc.cardemulation.HostApduService;
34 import android.nfc.cardemulation.PollingFrame;
35 import android.nfc.cardemulation.Utils;
36 import android.os.Bundle;
37 import android.os.Handler;
38 import android.os.IBinder;
39 import android.os.Looper;
40 import android.os.Message;
41 import android.os.Messenger;
42 import android.os.PowerManager;
43 import android.os.RemoteException;
44 import android.os.UserHandle;
45 import android.sysprop.NfcProperties;
46 import android.util.ArraySet;
47 import android.util.Log;
48 import android.util.Pair;
49 import android.util.proto.ProtoOutputStream;
50 
51 import androidx.annotation.VisibleForTesting;
52 
53 import com.android.nfc.ForegroundUtils;
54 import com.android.nfc.NfcInjector;
55 import com.android.nfc.NfcService;
56 import com.android.nfc.NfcStatsLog;
57 import com.android.nfc.cardemulation.RegisteredAidCache.AidResolveInfo;
58 import com.android.nfc.cardemulation.util.StatsdUtils;
59 import com.android.nfc.flags.Flags;
60 import com.android.nfc.proto.NfcEventProto;
61 
62 import java.io.FileDescriptor;
63 import java.io.PrintWriter;
64 import java.util.ArrayList;
65 import java.util.Arrays;
66 import java.util.HashMap;
67 import java.util.HexFormat;
68 import java.util.List;
69 import java.util.Locale;
70 import java.util.Map;
71 import java.util.Objects;
72 import java.util.Set;
73 import java.util.regex.Pattern;
74 
75 
76 public class HostEmulationManager {
77     static final String TAG = "HostEmulationManager";
78     static final boolean DBG = NfcProperties.debug_enabled().orElse(true);
79 
80     static final int STATE_IDLE = 0;
81     static final int STATE_W4_SELECT = 1;
82     static final int STATE_W4_SERVICE = 2;
83     static final int STATE_W4_DEACTIVATE = 3;
84     static final int STATE_XFER = 4;
85     static final int STATE_POLLING_LOOP = 5;
86 
87     /** Minimum AID length as per ISO7816 */
88     static final int MINIMUM_AID_LENGTH = 5;
89 
90     /** Length of Select APDU header including length byte */
91     static final int SELECT_APDU_HDR_LENGTH = 5;
92 
93     static final byte INSTR_SELECT = (byte)0xA4;
94 
95     static final String ANDROID_HCE_AID = "A000000476416E64726F6964484345";
96     static final String NDEF_V1_AID = "D2760000850100";
97     static final String NDEF_V2_AID = "D2760000850101";
98     static final byte[] ANDROID_HCE_RESPONSE = {0x14, (byte)0x81, 0x00, 0x00, (byte)0x90, 0x00};
99 
100     static final byte[] AID_NOT_FOUND = {0x6A, (byte)0x82};
101     static final byte[] UNKNOWN_ERROR = {0x6F, 0x00};
102 
103     static final int CE_HCE_PAYMENT =
104             NfcStatsLog.NFC_CARDEMULATION_OCCURRED__CATEGORY__HCE_PAYMENT;
105     static final int CE_HCE_OTHER =
106             NfcStatsLog.NFC_CARDEMULATION_OCCURRED__CATEGORY__HCE_OTHER;
107     static final String NFC_PACKAGE = "com.android.nfc";
108     static final String DATA_KEY = "data";
109     static final int FIELD_OFF_IDLE_DELAY_MS = 2000;
110     static final int RE_ENABLE_OBSERVE_MODE_DELAY_MS = 2000;
111 
112     final Context mContext;
113     final RegisteredAidCache mAidCache;
114     final Messenger mMessenger = new Messenger (new MessageHandler());
115     final KeyguardManager mKeyguard;
116     final Object mLock;
117     final PowerManager mPowerManager;
118     private final Looper mLooper;
119 
120     private final StatsdUtils mStatsdUtils;
121 
122     // All variables below protected by mLock
123 
124     // Variables below are for a non-payment service,
125     // that is typically only bound in the STATE_XFER state.
126     Messenger mService;
127     boolean mServiceBound = false;
128     ComponentName mServiceName = null;
129     int mServiceUserId; // The UserId of the non-payment service
130     ArrayList<PollingFrame> mPendingPollingLoopFrames = null;
131     ArrayList<PollingFrame> mUnprocessedPollingFrames = null;
132     Map<ComponentName, ArrayList<PollingFrame>> mPollingFramesToSend = null;
133     private Map<Integer, Map<String, List<ApduServiceInfo>>> mPollingLoopFilters;
134     private Map<Integer, Map<Pattern, List<ApduServiceInfo>>> mPollingLoopPatternFilters;
135     AutoDisableObserveModeRunnable mAutoDisableObserveModeRunnable = null;
136 
137     // Variables below are for a payment service,
138     // which is typically bound persistently to improve on
139     // latency.
140     Messenger mPaymentService;
141     boolean mPaymentServiceBound = false;
142 
143     boolean mEnableObserveModeAfterTransaction = false;
144     boolean mEnableObserveModeOnFieldOff = false;
145     ComponentName mPaymentServiceName = null;
146     int mPaymentServiceUserId; // The userId of the payment service
147     ComponentName mLastBoundPaymentServiceName;
148 
149     // mActiveService denotes the service interface
150     // that is the current active one, until a new SELECT AID
151     // comes in that may be resolved to a different service.
152     // On deactivation, mActiveService stops being valid.
153     Messenger mActiveService;
154     ComponentName mActiveServiceName;
155     int mActiveServiceUserId; // The UserId of the current active one
156 
157     String mLastSelectedAid;
158     int mState;
159     byte[] mSelectApdu;
160     Handler mHandler;
161 
162 
163     enum PollingLoopState {
164         EVALUATING_POLLING_LOOP,
165         FILTER_MATCHED,
166         DELIVERING_TO_PREFERRED
167     };
168 
169     PollingLoopState mPollingLoopState = PollingLoopState.EVALUATING_POLLING_LOOP;
170 
171     // Runnable to return to an IDLE_STATE and reset preferred service. This should be run after we
172     // have left a field and gone a period of time without any HCE or polling frame data.
173     Runnable mReturnToIdleStateRunnable = new Runnable() {
174         @Override
175         public void run() {
176             synchronized (mLock) {
177                 Log.d(TAG, "Have been outside field, returning to idle state");
178                 mPendingPollingLoopFrames = null;
179                 mPollingFramesToSend = null;
180                 mPollingLoopState = PollingLoopState.EVALUATING_POLLING_LOOP;
181                 resetActiveService();
182                 mState = STATE_IDLE;
183             }
184         }
185     };
186 
187     // Runnable to re-enable observe mode after a transaction. This should be delayed after
188     // HCE is deactivated to ensure we don't receive another select AID.
189     Runnable mEnableObserveModeAfterTransactionRunnable = new Runnable() {
190         @Override
191         public void run() {
192             synchronized (mLock) {
193               Log.d(TAG, "re-enabling observe mode after transaction.");
194               mEnableObserveModeAfterTransaction = false;
195               mEnableObserveModeOnFieldOff = false;
196               NfcAdapter adapter = NfcAdapter.getDefaultAdapter(mContext);
197               adapter.setObserveModeEnabled(true);
198             }
199         }
200     };
201 
HostEmulationManager(Context context, Looper looper, RegisteredAidCache aidCache)202     public HostEmulationManager(Context context, Looper looper, RegisteredAidCache aidCache) {
203         this(context, looper, aidCache, new StatsdUtils(StatsdUtils.SE_NAME_HCE));
204     }
205 
206     @VisibleForTesting
HostEmulationManager(Context context, Looper looper, RegisteredAidCache aidCache, StatsdUtils statsdUtils)207     HostEmulationManager(Context context, Looper looper, RegisteredAidCache aidCache,
208                          StatsdUtils statsdUtils) {
209         mContext = context;
210         mLooper = looper;
211         mHandler = new Handler(looper);
212         mLock = new Object();
213         mAidCache = aidCache;
214         mState = STATE_IDLE;
215         mPollingLoopState = PollingLoopState.EVALUATING_POLLING_LOOP;
216         mKeyguard = context.getSystemService(KeyguardManager.class);
217         mPowerManager = context.getSystemService(PowerManager.class);
218         mStatsdUtils = Flags.statsdCeEventsFlag() ? statsdUtils : null;
219         mPollingLoopFilters = new HashMap<Integer, Map<String, List<ApduServiceInfo>>>();
220         mPollingLoopPatternFilters = new HashMap<Integer, Map<Pattern, List<ApduServiceInfo>>>();
221     }
222 
223     /**
224      *  Preferred payment service changed
225      */
onPreferredPaymentServiceChanged(int userId, final ComponentName service)226     public void onPreferredPaymentServiceChanged(int userId, final ComponentName service) {
227         mHandler.post(() -> {
228             synchronized (mLock) {
229                 if (!isHostCardEmulationActivated()) {
230                     Log.d(TAG, "onPreferredPaymentServiceChanged, resetting active service");
231                     resetActiveService();
232                 }
233                 if (service != null) {
234                     bindPaymentServiceLocked(userId, service);
235                 } else {
236                     unbindPaymentServiceLocked();
237                 }
238             }
239         });
240     }
241 
getForegroundServiceOrDefault()242     private Messenger getForegroundServiceOrDefault() {
243         Pair<Messenger, ComponentName> pair = getForegroundServiceAndNameOrDefault();
244         if (pair == null) {
245             return null;
246         }
247         return pair.first;
248     }
249 
getForegroundServiceAndNameOrDefault()250     private Pair<Messenger, ComponentName> getForegroundServiceAndNameOrDefault() {
251         Pair<Integer, ComponentName> preferredService = mAidCache.getPreferredService();
252         int preferredServiceUserId = preferredService.first != null ?
253                 preferredService.first : -1;
254         ComponentName preferredServiceName = preferredService.second;
255 
256         if (preferredServiceName == null || preferredServiceUserId < 0) {
257             return null;
258         }
259 
260         return new Pair<>(bindServiceIfNeededLocked(preferredServiceUserId, preferredServiceName),
261             preferredServiceName);
262     }
263 
264 
265     @TargetApi(35)
266     @FlaggedApi(android.nfc.Flags.FLAG_NFC_OBSERVE_MODE)
updateForShouldDefaultToObserveMode(boolean enabled)267     public void updateForShouldDefaultToObserveMode(boolean enabled) {
268         synchronized (mLock) {
269             if (!isHostCardEmulationActivated()) {
270                 NfcAdapter adapter = NfcAdapter.getDefaultAdapter(mContext);
271                 adapter.setObserveModeEnabled(enabled);
272             } else {
273                 mEnableObserveModeAfterTransaction = enabled;
274             }
275         }
276     }
277 
278 
279     @TargetApi(35)
280     @FlaggedApi(android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP)
updatePollingLoopFilters(int userId, List<ApduServiceInfo> services)281     public void updatePollingLoopFilters(int userId, List<ApduServiceInfo> services) {
282         HashMap<String, List<ApduServiceInfo>> pollingLoopFilters =
283                 new HashMap<String, List<ApduServiceInfo>>();
284         HashMap<Pattern, List<ApduServiceInfo>> pollingLoopPatternFilters =
285                 new HashMap<Pattern, List<ApduServiceInfo>>();
286         for (ApduServiceInfo serviceInfo : services) {
287             for (String plf : serviceInfo.getPollingLoopFilters()) {
288                 List<ApduServiceInfo> list =
289                         pollingLoopFilters.getOrDefault(plf, new ArrayList<ApduServiceInfo>());
290                 list.add(serviceInfo);
291                 pollingLoopFilters.putIfAbsent(plf, list);
292 
293             }
294             for (Pattern plpf : serviceInfo.getPollingLoopPatternFilters()) {
295                 List<ApduServiceInfo> list =
296                         pollingLoopPatternFilters.getOrDefault(plpf,
297                         new ArrayList<ApduServiceInfo>());
298                 list.add(serviceInfo);
299                 pollingLoopPatternFilters.putIfAbsent(plpf, list);
300 
301             }
302         }
303         mPollingLoopFilters.put(Integer.valueOf(userId), pollingLoopFilters);
304         mPollingLoopPatternFilters.put(Integer.valueOf(userId), pollingLoopPatternFilters);
305     }
306 
onObserveModeStateChange(boolean enabled)307     public void onObserveModeStateChange(boolean enabled) {
308         synchronized(mLock) {
309             if (!enabled && mAutoDisableObserveModeRunnable != null) {
310                 mHandler.removeCallbacks(mAutoDisableObserveModeRunnable);
311                 mAutoDisableObserveModeRunnable = null;
312             }
313         }
314     }
315 
316 
317     class AutoDisableObserveModeRunnable implements Runnable {
318         Set<String> mServicePackageNames;
AutoDisableObserveModeRunnable(ComponentName componentName)319         AutoDisableObserveModeRunnable(ComponentName componentName) {
320             mServicePackageNames = new ArraySet<>(1);
321             addServiceToList(componentName);
322         }
323 
324         @Override
run()325         public void run() {
326             synchronized(mLock) {
327                 NfcAdapter adapter = NfcAdapter.getDefaultAdapter(mContext);
328                 if (!adapter.isObserveModeEnabled()) {
329                     return;
330                 }
331                 if (arePackagesInForeground()) {
332                     return;
333                 }
334                 Log.w(TAG, "Observe mode not disabled and no application from the following " +
335                     "packages are in the foreground: " + String.join(", ", mServicePackageNames));
336                 allowOneTransaction();
337             }
338         }
339 
340 
addServiceToList(ComponentName service)341         void addServiceToList(ComponentName service) {
342             mServicePackageNames.add(service.getPackageName());
343         }
344 
arePackagesInForeground()345         boolean arePackagesInForeground() {
346             ActivityManager am = mContext.getSystemService(ActivityManager.class);
347             if (am == null) {
348                 return false;
349             }
350             ForegroundUtils foregroundUtils = ForegroundUtils.getInstance(am);
351             if (foregroundUtils == null) {
352                 return false;
353             }
354             PackageManager packageManager = mContext.getPackageManager();
355             if (packageManager == null) {
356                 return false;
357             }
358             for (Integer uid : foregroundUtils.getForegroundUids()) {
359                 for (String packageName :  packageManager.getPackagesForUid(uid)) {
360                     if (packageName != null) {
361                         for (String servicePackageName : mServicePackageNames) {
362                             if (Objects.equals(servicePackageName, packageName)) {
363                                 return true;
364                             }
365                         }
366                     }
367                 }
368             }
369             return false;
370         }
371     }
372 
sendFrameToServiceLocked(Messenger service, ComponentName name, PollingFrame frame)373     private void sendFrameToServiceLocked(Messenger service, ComponentName name,
374         PollingFrame frame) {
375         sendFramesToServiceLocked(service, name, Arrays.asList(frame));
376     }
377 
sendFramesToServiceLocked(Messenger service, ComponentName name, List<PollingFrame> frames)378     private void sendFramesToServiceLocked(Messenger service, ComponentName name,
379             List<PollingFrame> frames) {
380         if (service != null) {
381             sendPollingFramesToServiceLocked(service, new ArrayList<>(frames));
382         } else {
383             mUnprocessedPollingFrames = new ArrayList<PollingFrame>();
384             if (mPollingFramesToSend == null) {
385                 mPollingFramesToSend = new HashMap<ComponentName, ArrayList<PollingFrame>>();
386             }
387             if (mPollingFramesToSend.containsKey(name)) {
388                 mPollingFramesToSend.get(name).addAll(frames);
389             } else {
390                 mPollingFramesToSend.put(name, new ArrayList<>(frames));
391             }
392         }
393         if (Flags.autoDisableObserveMode()) {
394             if (mAutoDisableObserveModeRunnable == null) {
395                 mAutoDisableObserveModeRunnable = new AutoDisableObserveModeRunnable(name);
396                 mHandler.postDelayed(mAutoDisableObserveModeRunnable, 3000);
397             } else {
398                 mAutoDisableObserveModeRunnable.addServiceToList(name);
399             }
400         }
401     }
402 
403     @TargetApi(35)
404     @FlaggedApi(android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP)
onPollingLoopDetected(List<PollingFrame> pollingFrames)405     public void onPollingLoopDetected(List<PollingFrame> pollingFrames) {
406         Log.d(TAG, "onPollingLoopDetected, size: " + pollingFrames.size());
407         synchronized (mLock) {
408             mHandler.removeCallbacks(mReturnToIdleStateRunnable);
409             // We need to have this check here in addition to the one in onFieldChangeDetected,
410             // because we can receive an OFF frame after the field change is detected.
411             if (!pollingFrames.isEmpty()
412                     && pollingFrames.getLast().getType() == PollingFrame.POLLING_LOOP_TYPE_OFF) {
413                 mHandler.postDelayed(mReturnToIdleStateRunnable, FIELD_OFF_IDLE_DELAY_MS);
414             }
415 
416             if (mState == STATE_IDLE) {
417                 mState = STATE_POLLING_LOOP;
418             }
419             int onCount = 0;
420             int offCount = 0;
421             int aCount = 0;
422             int bCount = 0;
423             if (mPendingPollingLoopFrames == null) {
424                 mPendingPollingLoopFrames = new ArrayList<PollingFrame>(1);
425             }
426             for (PollingFrame pollingFrame : pollingFrames) {
427                 if (mUnprocessedPollingFrames != null) {
428                     mUnprocessedPollingFrames.add(pollingFrame);
429                 } else if (pollingFrame.getType()
430                         == PollingFrame.POLLING_LOOP_TYPE_F) {
431                     Pair<Messenger, ComponentName> serviceAndName =
432                         getForegroundServiceAndNameOrDefault();
433                     if (serviceAndName != null) {
434                         sendFrameToServiceLocked(serviceAndName.first, serviceAndName.second,
435                             pollingFrame);
436                     }
437                 } else if (pollingFrame.getType()
438                         == PollingFrame.POLLING_LOOP_TYPE_UNKNOWN) {
439                     byte[] data = pollingFrame.getData();
440                     String dataStr = HexFormat.of().formatHex(data).toUpperCase(Locale.ROOT);
441                     List<ApduServiceInfo> serviceInfos =
442                             mPollingLoopFilters.get(ActivityManager.getCurrentUser()).get(dataStr);
443                     Map<Pattern, List<ApduServiceInfo>> patternMappingForUser =
444                             mPollingLoopPatternFilters.get(ActivityManager.getCurrentUser());
445                     Set<Pattern> patternSet = patternMappingForUser.keySet();
446                     List<Pattern> matchedPatterns = patternSet.stream()
447                             .filter(p -> p.matcher(dataStr).matches()).toList();
448                     if (!matchedPatterns.isEmpty()) {
449                         if (serviceInfos == null) {
450                             serviceInfos = new ArrayList<ApduServiceInfo>();
451                         }
452                         for (Pattern matchedPattern : matchedPatterns) {
453                             serviceInfos.addAll(patternMappingForUser.get(matchedPattern));
454                         }
455                     }
456                     if (serviceInfos != null && serviceInfos.size() > 0) {
457                         ApduServiceInfo serviceInfo;
458                         if (serviceInfos.size() == 1) {
459                             serviceInfo = serviceInfos.get(0);
460                         } else {
461                             serviceInfo = mAidCache.resolvePollingLoopFilterConflict(serviceInfos);
462                             if (serviceInfo == null) {
463                                 /*  If neither the foreground or payments service can handle the plf,
464                                 *  pick the first in the list. */
465                                 serviceInfo = serviceInfos.get(0);
466                             }
467                         }
468                         if (serviceInfo.getShouldAutoTransact(dataStr)) {
469                             allowOneTransaction();
470                             pollingFrame.setTriggeredAutoTransact(true);
471                         }
472                         UserHandle user = UserHandle.getUserHandleForUid(serviceInfo.getUid());
473                         if (serviceInfo.isOnHost()) {
474                             Messenger service = bindServiceIfNeededLocked(user.getIdentifier(),
475                                     serviceInfo.getComponent());
476                             mPollingLoopState = PollingLoopState.FILTER_MATCHED;
477                             sendFrameToServiceLocked(service, serviceInfo.getComponent(),
478                                 pollingFrame);
479                         }
480                     } else {
481                         Pair<Messenger, ComponentName> serviceAndName =
482                                 getForegroundServiceAndNameOrDefault();
483                         if (serviceAndName != null) {
484                             sendFrameToServiceLocked(serviceAndName.first, serviceAndName.second,
485                                 pollingFrame);
486                         }
487                     }
488 
489                     if (mStatsdUtils != null) {
490                         mStatsdUtils.tallyPollingFrame(dataStr, pollingFrame);
491                     }
492                 } else {
493                     mPendingPollingLoopFrames.add(pollingFrame);
494                 }
495                 if (mStatsdUtils != null) {
496                     mStatsdUtils.logPollingFrames();
497                 }
498             }
499 
500             if (mPollingLoopState == PollingLoopState.EVALUATING_POLLING_LOOP) {
501                 if (mPendingPollingLoopFrames.size() >= 3) {
502                     for (PollingFrame frame : mPendingPollingLoopFrames) {
503                         int type = frame.getType();
504                         switch (type) {
505                             case PollingFrame.POLLING_LOOP_TYPE_A:
506                                 aCount++;
507                                 if (aCount > 3) {
508                                     mPollingLoopState = PollingLoopState.DELIVERING_TO_PREFERRED;
509                                 }
510                                 break;
511                             case PollingFrame.POLLING_LOOP_TYPE_B:
512                                 bCount++;
513                                 if (bCount > 3) {
514                                     mPollingLoopState = PollingLoopState.DELIVERING_TO_PREFERRED;
515                                 }
516                                 break;
517                             case PollingFrame.POLLING_LOOP_TYPE_ON:
518                                 onCount++;
519                                 break;
520                             case PollingFrame.POLLING_LOOP_TYPE_OFF:
521                                 // Send the loop data if we've seen at least one on before an off.
522                                 offCount++;
523                                 if (onCount >= 2 && offCount >=2) {
524                                     mPollingLoopState = PollingLoopState.DELIVERING_TO_PREFERRED;
525                                 }
526                                 break;
527                             default:
528                         }
529                         if (mPollingLoopState != PollingLoopState.EVALUATING_POLLING_LOOP) {
530                             break;
531                         }
532                     }
533                 }
534             }
535 
536             if (mPollingLoopState == PollingLoopState.DELIVERING_TO_PREFERRED) {
537                 Pair<Messenger, ComponentName> serviceAndName =
538                         getForegroundServiceAndNameOrDefault();
539                 if (serviceAndName != null) {
540                     sendFramesToServiceLocked(serviceAndName.first, serviceAndName.second,
541                         mPendingPollingLoopFrames);
542                     mPendingPollingLoopFrames = null;
543                 } else {
544                     Log.i(TAG, "No preferred service to deliver polling frames to,"
545                     + " allowing transaction.");
546                     allowOneTransaction();
547                 }
548             }
549         }
550     }
551 
allowOneTransaction()552     private void allowOneTransaction() {
553         Log.d(TAG, "disabling observe mode for one transaction.");
554         mEnableObserveModeAfterTransaction = true;
555         NfcAdapter adapter = NfcAdapter.getDefaultAdapter(mContext);
556         mHandler.post(() -> adapter.setObserveModeEnabled(false));
557     }
558 
559     /**
560      *  Preferred foreground service changed
561      */
onPreferredForegroundServiceChanged(int userId, ComponentName service)562     public void onPreferredForegroundServiceChanged(int userId, ComponentName service) {
563         synchronized (mLock) {
564             if (!isHostCardEmulationActivated()) {
565                 Log.d(TAG, "onPreferredForegroundServiceChanged, resetting active service");
566                 resetActiveService();
567             }
568             if (service != null) {
569                 bindServiceIfNeededLocked(userId, service);
570             } else {
571                 unbindServiceIfNeededLocked();
572             }
573          }
574      }
575 
onFieldChangeDetected(boolean fieldOn)576     public void onFieldChangeDetected(boolean fieldOn) {
577         mHandler.removeCallbacks(mReturnToIdleStateRunnable);
578         if (!fieldOn) {
579             mHandler.postDelayed(mReturnToIdleStateRunnable, FIELD_OFF_IDLE_DELAY_MS);
580         }
581         if (!fieldOn && mEnableObserveModeOnFieldOff && mEnableObserveModeAfterTransaction) {
582             Log.d(TAG, "Field off detected, will re-enable observe mode.");
583             mHandler.postDelayed(mEnableObserveModeAfterTransactionRunnable,
584                 RE_ENABLE_OBSERVE_MODE_DELAY_MS);
585         }
586     }
587 
onHostEmulationActivated()588     public void onHostEmulationActivated() {
589         Log.d(TAG, "notifyHostEmulationActivated");
590         synchronized (mLock) {
591             mHandler.removeCallbacks(mReturnToIdleStateRunnable);
592             // Regardless of what happens, if we're having a tap again
593             // activity up, close it
594             Intent intent = new Intent(TapAgainDialog.ACTION_CLOSE);
595             intent.setPackage(NFC_PACKAGE);
596             mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
597             if (mState != STATE_IDLE && mState != STATE_POLLING_LOOP) {
598                 Log.e(TAG, "Got activation event in non-idle state");
599             }
600             mState = STATE_W4_SELECT;
601         }
602     }
603 
604     static private class UnroutableAidBugReportRunnable implements Runnable {
605         List<String> mUnroutedAids;
606 
UnroutableAidBugReportRunnable(String aid)607         UnroutableAidBugReportRunnable(String aid) {
608             mUnroutedAids = new ArrayList<String>(1);
609             mUnroutedAids.add(aid);
610         }
611 
addAid(String aid)612         void addAid(String aid) {
613             mUnroutedAids.add(aid);
614         }
615         @Override
run()616         public void run() {
617             NfcService.getInstance().mNfcDiagnostics.takeBugReport(
618                     "NFC tap failed."
619                         + " (If you weren't using NFC, "
620                         + "no need to submit this report.)",
621                     "Couldn't route " + String.join(", ", mUnroutedAids));
622         }
623     }
624 
625     UnroutableAidBugReportRunnable mUnroutableAidBugReportRunnable = null;
626 
onHostEmulationData(byte[] data)627     public void onHostEmulationData(byte[] data) {
628         Log.d(TAG, "notifyHostEmulationData");
629         mHandler.removeCallbacks(mReturnToIdleStateRunnable);
630         mHandler.removeCallbacks(mEnableObserveModeAfterTransactionRunnable);
631         String selectAid = findSelectAid(data);
632         ComponentName resolvedService = null;
633         ApduServiceInfo resolvedServiceInfo = null;
634         AidResolveInfo resolveInfo = null;
635         synchronized (mLock) {
636             if (mState == STATE_IDLE) {
637                 Log.e(TAG, "Got data in idle state.");
638                 return;
639             } else if (mState == STATE_W4_DEACTIVATE) {
640                 Log.e(TAG, "Dropping APDU in STATE_W4_DECTIVATE");
641                 return;
642             }
643             if (selectAid != null) {
644                 if (selectAid.equals(ANDROID_HCE_AID)) {
645                     NfcService.getInstance().sendData(ANDROID_HCE_RESPONSE);
646                     return;
647                 }
648                 resolveInfo = mAidCache.resolveAid(selectAid);
649                 if (resolveInfo == null || resolveInfo.services.size() == 0) {
650                     if (selectAid.equals(NDEF_V1_AID) || selectAid.equals(NDEF_V2_AID)) {
651                         Log.w(TAG, "Can't route NDEF AID, sending AID_NOT_FOUND");
652                     } else if (!mPowerManager.isScreenOn()) {
653                       Log.i(TAG,
654                           "Screen is off, sending AID_NOT_FOUND, but not triggering bug report");
655                     } else {
656                         Log.w(TAG, "Can't handle AID " + selectAid + " sending AID_NOT_FOUND");
657                         if (mUnroutableAidBugReportRunnable != null) {
658                             mUnroutableAidBugReportRunnable.addAid(selectAid);
659                         } else {
660                             mUnroutableAidBugReportRunnable =
661                                     new UnroutableAidBugReportRunnable(selectAid);
662                             /* Wait 1s to see if there is an alternate AID we can route before
663                              * taking a bug report */
664                             mHandler.postDelayed(mUnroutableAidBugReportRunnable, 1000);
665                         }
666                     }
667                     NfcInjector.getInstance().getNfcEventLog().logEvent(
668                             NfcEventProto.EventType.newBuilder()
669                                     .setCeUnroutableAid(
670                                         NfcEventProto.NfcCeUnroutableAid.newBuilder()
671                                             .setAid(selectAid)
672                                             .build())
673                                     .build());
674                     // Tell the remote we don't handle this AID
675                     NfcService.getInstance().sendData(AID_NOT_FOUND);
676                     return;
677                 } else if (mUnroutableAidBugReportRunnable != null) {
678                     /* If there is a pending bug report runnable, cancel it. */
679                     mHandler.removeCallbacks(mUnroutableAidBugReportRunnable);
680                     mUnroutableAidBugReportRunnable = null;
681                 }
682                 mLastSelectedAid = selectAid;
683                 if (resolveInfo.defaultService != null) {
684                     // Resolve to default
685                     // Check if resolvedService requires unlock
686                     ApduServiceInfo defaultServiceInfo = resolveInfo.defaultService;
687                     if (mStatsdUtils != null) {
688                         mStatsdUtils.setCardEmulationEventCategory(resolveInfo.category);
689                         mStatsdUtils.setCardEmulationEventUid(defaultServiceInfo.getUid());
690                     }
691 
692                     if ((defaultServiceInfo.requiresUnlock()
693                             || NfcService.getInstance().isSecureNfcEnabled())
694                           && mKeyguard.isKeyguardLocked()) {
695                         NfcService.getInstance().sendRequireUnlockIntent();
696                         NfcService.getInstance().sendData(AID_NOT_FOUND);
697                         if (DBG) Log.d(TAG, "requiresUnlock()! show toast");
698                         if (mStatsdUtils != null) {
699                             mStatsdUtils.logCardEmulationWrongSettingEvent();
700                         }
701                         launchTapAgain(resolveInfo.defaultService, resolveInfo.category);
702                         return;
703                     }
704                     if (defaultServiceInfo.requiresScreenOn() && !mPowerManager.isScreenOn()) {
705                         NfcService.getInstance().sendData(AID_NOT_FOUND);
706                         if (DBG) Log.d(TAG, "requiresScreenOn()!");
707                         if (mStatsdUtils != null) {
708                             mStatsdUtils.logCardEmulationWrongSettingEvent();
709                         }
710                         return;
711                     }
712                     // In no circumstance should this be an OffHostService -
713                     // we should never get this AID on the host in the first place
714                     if (!defaultServiceInfo.isOnHost()) {
715                         Log.e(TAG, "AID that was meant to go off-host was routed to host." +
716                                 " Check routing table configuration.");
717                         NfcService.getInstance().sendData(AID_NOT_FOUND);
718                         if (mStatsdUtils != null) {
719                             mStatsdUtils.logCardEmulationNoRoutingEvent();
720                         }
721                         return;
722                     }
723                     resolvedService = defaultServiceInfo.getComponent();
724                     resolvedServiceInfo = defaultServiceInfo;
725                 } else if (mActiveServiceName != null) {
726                     for (ApduServiceInfo serviceInfo : resolveInfo.services) {
727                         if (mActiveServiceName.equals(serviceInfo.getComponent())) {
728                             resolvedService = mActiveServiceName;
729                             resolvedServiceInfo = serviceInfo;
730                             break;
731                         }
732                     }
733                 }
734                 if (resolvedService == null) {
735                     // We have no default, and either one or more services.
736                     // Ask the user to confirm.
737                     // Just ignore all future APDUs until we resolve to only one
738                     mState = STATE_W4_DEACTIVATE;
739                     NfcStatsLog.write(NfcStatsLog.NFC_AID_CONFLICT_OCCURRED, selectAid);
740                     if (mStatsdUtils != null) {
741                         mStatsdUtils.setCardEmulationEventCategory(CardEmulation.CATEGORY_OTHER);
742                         mStatsdUtils.logCardEmulationWrongSettingEvent();
743                     }
744                     launchResolver((ArrayList<ApduServiceInfo>)resolveInfo.services, null,
745                             resolveInfo.category);
746                     return;
747                 }
748             }
749             switch (mState) {
750                 case STATE_W4_SELECT:
751                     if (selectAid != null) {
752                         int uid = resolvedServiceInfo.getUid();
753                         if (mStatsdUtils != null) {
754                             mStatsdUtils.setCardEmulationEventUid(uid);
755                             mStatsdUtils.setCardEmulationEventCategory(resolveInfo.category);
756                         }
757                         UserHandle user =
758                                 UserHandle.getUserHandleForUid(uid);
759                         Messenger existingService =
760                                 bindServiceIfNeededLocked(user.getIdentifier(), resolvedService);
761                         if (existingService != null) {
762                             Log.d(TAG, "Binding to existing service");
763                             sendDataToServiceLocked(existingService, data);
764                         } else {
765                             // Waiting for service to be bound
766                             Log.d(TAG, "Waiting for new service.");
767                             // Queue SELECT APDU to be used
768                             mSelectApdu = data;
769                             mState = STATE_W4_SERVICE;
770                         }
771                         if (mStatsdUtils != null) {
772                             mStatsdUtils.notifyCardEmulationEventWaitingForResponse();
773                         } else {
774                             int statsdCategory =
775                                     resolveInfo.category.equals(CardEmulation.CATEGORY_PAYMENT)
776                                             ? CE_HCE_PAYMENT
777                                             : CE_HCE_OTHER;
778                             NfcStatsLog.write(
779                                     NfcStatsLog.NFC_CARDEMULATION_OCCURRED,
780                                     statsdCategory,
781                                     "HCE",
782                                     uid);
783                         }
784                     } else {
785                         Log.d(TAG, "Dropping non-select APDU in STATE_W4_SELECT");
786                         NfcService.getInstance().sendData(UNKNOWN_ERROR);
787                     }
788                     break;
789                 case STATE_W4_SERVICE:
790                     Log.d(TAG, "Unexpected APDU in STATE_W4_SERVICE");
791                     break;
792                 case STATE_XFER:
793                     if (selectAid != null) {
794                         UserHandle user =
795                                 UserHandle.getUserHandleForUid(resolvedServiceInfo.getUid());
796                         Messenger existingService =
797                                 bindServiceIfNeededLocked(user.getIdentifier(), resolvedService);
798                         if (existingService != null) {
799                             sendDataToServiceLocked(existingService, data);
800                         } else {
801                             // Waiting for service to be bound
802                             mSelectApdu = data;
803                             mState = STATE_W4_SERVICE;
804                         }
805                     } else if (mActiveService != null) {
806                         // Regular APDU data
807                         sendDataToServiceLocked(mActiveService, data);
808                     } else {
809                         // No SELECT AID and no active service.
810                         Log.d(TAG, "Service no longer bound, dropping APDU");
811                     }
812                     break;
813             }
814         }
815     }
816 
onHostEmulationDeactivated()817     public void onHostEmulationDeactivated() {
818         Log.d(TAG, "notifyHostEmulationDeactivated");
819         synchronized (mLock) {
820             if (mState == STATE_IDLE) {
821                 Log.e(TAG, "Got deactivation event while in idle state");
822             }
823             sendDeactivateToActiveServiceLocked(HostApduService.DEACTIVATION_LINK_LOSS);
824             resetActiveService();
825             mPendingPollingLoopFrames = null;
826             mPollingFramesToSend = null;
827             unbindServiceIfNeededLocked();
828             mState = STATE_IDLE;
829             mPollingLoopState = PollingLoopState.EVALUATING_POLLING_LOOP;
830 
831             if (mAutoDisableObserveModeRunnable != null) {
832                 mHandler.removeCallbacks(mAutoDisableObserveModeRunnable);
833                 mAutoDisableObserveModeRunnable = null;
834             }
835 
836             if (mEnableObserveModeAfterTransaction) {
837                 Log.d(TAG, "HCE deactivated, will re-enable observe mode.");
838                 mHandler.postDelayed(mEnableObserveModeAfterTransactionRunnable,
839                     RE_ENABLE_OBSERVE_MODE_DELAY_MS);
840             }
841 
842             if (mStatsdUtils != null) {
843                 mStatsdUtils.logCardEmulationDeactivatedEvent();
844             }
845         }
846     }
847 
isHostCardEmulationActivated()848     public boolean isHostCardEmulationActivated() {
849         synchronized (mLock) {
850             return mState != STATE_IDLE && mState != STATE_POLLING_LOOP;
851         }
852     }
853 
onOffHostAidSelected()854     public void onOffHostAidSelected() {
855         Log.d(TAG, "notifyOffHostAidSelected");
856         synchronized (mLock) {
857             mHandler.removeCallbacks(mReturnToIdleStateRunnable);
858             mHandler.removeCallbacks(mEnableObserveModeAfterTransactionRunnable);
859             if (mState != STATE_XFER || mActiveService == null) {
860                 // Don't bother telling, we're not bound to any service yet
861             } else {
862                 sendDeactivateToActiveServiceLocked(HostApduService.DEACTIVATION_DESELECTED);
863             }
864             if (mEnableObserveModeAfterTransaction) {
865                 Log.i(TAG, "OffHost AID selected, waiting for Field off to reenable observe mode");
866                 mEnableObserveModeOnFieldOff = true;
867             }
868             resetActiveService();
869             unbindServiceIfNeededLocked();
870             mState = STATE_W4_SELECT;
871 
872             //close the TapAgainDialog
873             Intent intent = new Intent(TapAgainDialog.ACTION_CLOSE);
874             intent.setPackage(NFC_PACKAGE);
875             mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
876         }
877     }
878 
bindServiceIfNeededLocked(int userId, ComponentName service)879     Messenger bindServiceIfNeededLocked(int userId, ComponentName service) {
880         if (service == null) {
881             Log.e(TAG, "service ComponentName is null");
882             return null;
883         }
884 
885         Pair<Integer, ComponentName> preferredPaymentService =
886                 mAidCache.getPreferredPaymentService();
887         int preferredPaymentUserId = preferredPaymentService.first  != null ?
888                 preferredPaymentService.first : -1;
889         ComponentName preferredPaymentServiceName = preferredPaymentService.second;
890 
891         if (mPaymentServiceName != null && mPaymentServiceName.equals(service)
892                 && mPaymentServiceUserId == userId) {
893             Log.d(TAG, "Service already bound as payment service.");
894             return mPaymentService;
895         } else if (!mPaymentServiceBound && preferredPaymentServiceName != null
896                 && preferredPaymentServiceName.equals(service)
897                 && preferredPaymentUserId == userId) {
898             Log.d(TAG, "Service should be bound as payment service but is not, binding now");
899             bindPaymentServiceLocked(userId, preferredPaymentServiceName);
900             return null;
901         } else if (mServiceName != null && mServiceName.equals(service)
902                 && mServiceUserId == userId) {
903             Log.d(TAG, "Service already bound as regular service.");
904             return mService;
905         } else {
906             Log.d(TAG, "Binding to service " + service + " for userid:" + userId);
907             if (mStatsdUtils != null) {
908                 mStatsdUtils.notifyCardEmulationEventWaitingForService();
909             }
910             unbindServiceIfNeededLocked();
911             Intent aidIntent = new Intent(HostApduService.SERVICE_INTERFACE);
912             aidIntent.setComponent(service);
913             try {
914                 mServiceBound = mContext.bindServiceAsUser(aidIntent, mConnection,
915                         Context.BIND_AUTO_CREATE | Context.BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS,
916                         UserHandle.of(userId));
917                 if (!mServiceBound) {
918                     Log.e(TAG, "Could not bind service.");
919                 } else {
920                     mServiceUserId = userId;
921                 }
922             } catch (SecurityException e) {
923                 Log.e(TAG, "Could not bind service due to security exception.");
924             }
925             return null;
926         }
927     }
928 
sendDataToServiceLocked(Messenger service, byte[] data)929     void sendDataToServiceLocked(Messenger service, byte[] data) {
930         mState = STATE_XFER;
931         if (service != mActiveService) {
932             sendDeactivateToActiveServiceLocked(HostApduService.DEACTIVATION_DESELECTED);
933             mActiveService = service;
934             if (service.equals(mPaymentService)) {
935                 mActiveServiceName = mPaymentServiceName;
936                 mActiveServiceUserId = mPaymentServiceUserId;
937             } else {
938                 mActiveServiceName = mServiceName;
939                 mActiveServiceUserId = mServiceUserId;
940             }
941         }
942         Message msg = Message.obtain(null, HostApduService.MSG_COMMAND_APDU);
943         Bundle dataBundle = new Bundle();
944         dataBundle.putByteArray(DATA_KEY, data);
945         msg.setData(dataBundle);
946         msg.replyTo = mMessenger;
947         try {
948             mActiveService.send(msg);
949         } catch (RemoteException e) {
950             Log.e(TAG, "Remote service " + mActiveServiceName + " has died, dropping APDU", e);
951         }
952     }
953 
sendPollingFramesToServiceLocked(Messenger service, ArrayList<PollingFrame> pollingFrames)954     void sendPollingFramesToServiceLocked(Messenger service,
955             ArrayList<PollingFrame> pollingFrames) {
956         if (!Objects.equals(service, mActiveService)) {
957             sendDeactivateToActiveServiceLocked(HostApduService.DEACTIVATION_DESELECTED);
958             mActiveService = service;
959             if (service.equals(mPaymentService)) {
960                 mActiveServiceName = mPaymentServiceName;
961                 mActiveServiceUserId = mPaymentServiceUserId;
962             } else {
963                 mActiveServiceName = mServiceName;
964                 mActiveServiceUserId = mServiceUserId;
965             }
966         }
967         Message msg = Message.obtain(null, HostApduService.MSG_POLLING_LOOP);
968         Bundle msgData = new Bundle();
969         msgData.putParcelableArrayList(HostApduService.KEY_POLLING_LOOP_FRAMES_BUNDLE,
970                 pollingFrames);
971         msg.setData(msgData);
972         msg.replyTo = mMessenger;
973         if (mState == STATE_IDLE) {
974             mState = STATE_POLLING_LOOP;
975         }
976         try {
977             mActiveService.send(msg);
978         } catch (RemoteException e) {
979             Log.e(TAG, "Remote service " + mActiveServiceName + " has died, dropping frames", e);
980             allowOneTransaction();
981         }
982     }
983 
sendDeactivateToActiveServiceLocked(int reason)984     void sendDeactivateToActiveServiceLocked(int reason) {
985         if (mActiveService == null) return;
986         Message msg = Message.obtain(null, HostApduService.MSG_DEACTIVATED);
987         msg.arg1 = reason;
988         try {
989             mActiveService.send(msg);
990         } catch (RemoteException e) {
991             // Don't care
992         }
993     }
994 
unbindPaymentServiceLocked()995     void unbindPaymentServiceLocked() {
996         Log.d(TAG, "Unbinding payment service");
997         if (mPaymentServiceBound) {
998             try {
999                 mContext.unbindService(mPaymentConnection);
1000             } catch (Exception e) {
1001                 Log.w(TAG, "Failed to unbind payment service: " + mPaymentServiceName, e);
1002             }
1003             mPaymentServiceBound = false;
1004         }
1005 
1006         mPaymentService = null;
1007         mPaymentServiceName = null;
1008         mPaymentServiceUserId = -1;
1009     }
1010 
bindPaymentServiceLocked(int userId, ComponentName service)1011     void bindPaymentServiceLocked(int userId, ComponentName service) {
1012         unbindPaymentServiceLocked();
1013 
1014         Log.d(TAG, "Binding to payment service " + service + " for userid:" + userId);
1015         Intent intent = new Intent(HostApduService.SERVICE_INTERFACE);
1016         intent.setComponent(service);
1017         try {
1018             if (mContext.bindServiceAsUser(intent, mPaymentConnection,
1019                     Context.BIND_AUTO_CREATE | Context.BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS,
1020                     UserHandle.of(userId))) {
1021                 mPaymentServiceBound = true;
1022                 mPaymentServiceUserId = userId;
1023                 mLastBoundPaymentServiceName = service;
1024             } else {
1025                 Log.e(TAG, "Could not bind (persistent) payment service.");
1026             }
1027         } catch (SecurityException e) {
1028             Log.e(TAG, "Could not bind service due to security exception.");
1029         }
1030     }
1031 
unbindServiceIfNeededLocked()1032     void unbindServiceIfNeededLocked() {
1033         if (mServiceBound) {
1034             Log.d(TAG, "Unbinding from service " + mServiceName);
1035             try {
1036                 mContext.unbindService(mConnection);
1037             } catch (Exception e) {
1038                 Log.w(TAG, "Failed to unbind service " + mServiceName, e);
1039             }
1040             mServiceBound = false;
1041         }
1042 
1043         mService = null;
1044         mServiceName = null;
1045         mServiceUserId = -1;
1046     }
1047 
launchTapAgain(ApduServiceInfo service, String category)1048     void launchTapAgain(ApduServiceInfo service, String category) {
1049         Intent dialogIntent = new Intent(mContext, TapAgainDialog.class);
1050         dialogIntent.putExtra(TapAgainDialog.EXTRA_CATEGORY, category);
1051         dialogIntent.putExtra(TapAgainDialog.EXTRA_APDU_SERVICE, service);
1052         dialogIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
1053         mContext.startActivityAsUser(dialogIntent,
1054                 UserHandle.getUserHandleForUid(service.getUid()));
1055     }
1056 
launchResolver(ArrayList<ApduServiceInfo> services, ComponentName failedComponent, String category)1057     void launchResolver(ArrayList<ApduServiceInfo> services, ComponentName failedComponent,
1058             String category) {
1059         Intent intent = new Intent(mContext, AppChooserActivity.class);
1060         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
1061         intent.putParcelableArrayListExtra(AppChooserActivity.EXTRA_APDU_SERVICES, services);
1062         intent.putExtra(AppChooserActivity.EXTRA_CATEGORY, category);
1063         if (failedComponent != null) {
1064             intent.putExtra(AppChooserActivity.EXTRA_FAILED_COMPONENT, failedComponent);
1065         }
1066         mContext.startActivityAsUser(intent, UserHandle.CURRENT);
1067     }
1068 
findSelectAid(byte[] data)1069     String findSelectAid(byte[] data) {
1070         if (data == null || data.length < SELECT_APDU_HDR_LENGTH + MINIMUM_AID_LENGTH) {
1071             if (DBG) Log.d(TAG, "Data size too small for SELECT APDU");
1072             return null;
1073         }
1074         // To accept a SELECT AID for dispatch, we require the following:
1075         // Class byte must be 0x00: logical channel set to zero, no secure messaging, no chaining
1076         // Instruction byte must be 0xA4: SELECT instruction
1077         // P1: must be 0x04: select by application identifier
1078         // P2: File control information is only relevant for higher-level application,
1079         //     and we only support "first or only occurrence".
1080         if (data[0] == 0x00 && data[1] == INSTR_SELECT && data[2] == 0x04) {
1081             if (data[3] != 0x00) {
1082                 Log.d(TAG, "Selecting next, last or previous AID occurrence is not supported");
1083             }
1084             int aidLength = Byte.toUnsignedInt(data[4]);
1085             if (data.length < SELECT_APDU_HDR_LENGTH + aidLength) {
1086                 return null;
1087             }
1088             return bytesToString(data, SELECT_APDU_HDR_LENGTH, aidLength);
1089         }
1090         return null;
1091     }
1092 
resetActiveService()1093     private void resetActiveService() {
1094         mActiveService = null;
1095         mActiveServiceName = null;
1096         mActiveServiceUserId = -1;
1097     }
1098 
1099     private ServiceConnection mPaymentConnection = new ServiceConnection() {
1100         @Override
1101         public void onServiceConnected(ComponentName name, IBinder service) {
1102             synchronized (mLock) {
1103                 /* Preferred Payment Service has been changed. */
1104                 if (!mLastBoundPaymentServiceName.equals(name)) {
1105                     Log.i(TAG, "Ignoring bound payment service, " + name + " != "
1106                             + mLastBoundPaymentServiceName);
1107                     return;
1108                 }
1109                 mPaymentServiceName = name;
1110                 mPaymentService = new Messenger(service);
1111                 Log.i(TAG, "Payment service bound: " + name);
1112             }
1113         }
1114 
1115         @Override
1116         public void onServiceDisconnected(ComponentName name) {
1117             Log.i(TAG, "Payment service disconnected: " + name);
1118             synchronized (mLock) {
1119                 mPaymentService = null;
1120                 mPaymentServiceName = null;
1121             }
1122         }
1123 
1124         @Override
1125         public void onBindingDied(ComponentName name) {
1126             Log.i(TAG, "Payment service died: " + name);
1127             synchronized (mLock) {
1128                 bindPaymentServiceLocked(mPaymentServiceUserId, mLastBoundPaymentServiceName);
1129             }
1130         }
1131     };
1132 
1133     private ServiceConnection mConnection = new ServiceConnection() {
1134         @Override
1135         public void onServiceConnected(ComponentName name, IBinder service) {
1136             synchronized (mLock) {
1137                 /* Service is already deactivated, don't bind */
1138                 if (mState == STATE_IDLE) {
1139                   return;
1140                 }
1141                 mService = new Messenger(service);
1142                 mServiceName = name;
1143                 mServiceBound = true;
1144                 Log.d(TAG, "Service bound: " + name);
1145                 // Send pending select APDU
1146                 if (mSelectApdu != null) {
1147                     if (mStatsdUtils != null) {
1148                         mStatsdUtils.notifyCardEmulationEventServiceBound();
1149                     }
1150                     sendDataToServiceLocked(mService, mSelectApdu);
1151                     mSelectApdu = null;
1152                 } else if (mPollingFramesToSend != null && mPollingFramesToSend.containsKey(name)) {
1153                     sendPollingFramesToServiceLocked(mService, mPollingFramesToSend.get(name));
1154                     mPollingFramesToSend.remove(name);
1155                     if (android.nfc.Flags.nfcReadPollingLoop()
1156                         && mUnprocessedPollingFrames != null) {
1157                         ArrayList unprocessedPollingFrames = mUnprocessedPollingFrames;
1158                         mUnprocessedPollingFrames = null;
1159                         onPollingLoopDetected(unprocessedPollingFrames);
1160                     }
1161                 } else {
1162                     Log.d(TAG, "bound with nothing to send");
1163                 }
1164             }
1165         }
1166 
1167         @Override
1168         public void onServiceDisconnected(ComponentName name) {
1169             synchronized (mLock) {
1170                 Log.d(TAG, "Service unbound: " + name);
1171                 mService = null;
1172                 mServiceName = null;
1173                 mServiceBound = false;
1174             }
1175         }
1176     };
1177 
1178     class MessageHandler extends Handler {
1179         @Override
handleMessage(Message msg)1180         public void handleMessage(Message msg) {
1181             synchronized(mLock) {
1182                 if (mActiveService == null) {
1183                     Log.d(TAG, "Dropping service response message; service no longer active.");
1184                     return;
1185                 } else if (!msg.replyTo.getBinder().equals(mActiveService.getBinder())) {
1186                     Log.d(TAG, "Dropping service response message; service no longer bound.");
1187                     return;
1188                 }
1189             }
1190             if (msg.what == HostApduService.MSG_RESPONSE_APDU) {
1191                 Bundle dataBundle = msg.getData();
1192                 if (dataBundle == null) {
1193                     return;
1194                 }
1195                 byte[] data = dataBundle.getByteArray(DATA_KEY);
1196                 if (data == null || data.length == 0) {
1197                     Log.e(TAG, "Dropping empty R-APDU");
1198                     return;
1199                 }
1200                 int state;
1201                 synchronized(mLock) {
1202                     state = mState;
1203                 }
1204                 if (state == STATE_XFER) {
1205                     Log.d(TAG, "Sending data");
1206                     NfcService.getInstance().sendData(data);
1207                     if (mStatsdUtils != null) {
1208                         mStatsdUtils.notifyCardEmulationEventResponseReceived();
1209                     }
1210                 } else {
1211                     Log.d(TAG, "Dropping data, wrong state " + Integer.toString(state));
1212                 }
1213             } else if (msg.what == HostApduService.MSG_UNHANDLED) {
1214                 synchronized (mLock) {
1215                     Log.d(TAG, "Received MSG_UNHANDLED");
1216                     AidResolveInfo resolveInfo = mAidCache.resolveAid(mLastSelectedAid);
1217                     boolean isPayment = false;
1218                     if (resolveInfo.services.size() > 0) {
1219                         NfcStatsLog.write(NfcStatsLog.NFC_AID_CONFLICT_OCCURRED, mLastSelectedAid);
1220                         launchResolver((ArrayList<ApduServiceInfo>)resolveInfo.services,
1221                                 mActiveServiceName, resolveInfo.category);
1222                     }
1223                 }
1224             }
1225         }
1226     }
1227 
bytesToString(byte[] bytes, int offset, int length)1228     static String bytesToString(byte[] bytes, int offset, int length) {
1229         final char[] hexChars = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
1230         char[] chars = new char[length * 2];
1231         int byteValue;
1232         for (int j = 0; j < length; j++) {
1233             byteValue = bytes[offset + j] & 0xFF;
1234             chars[j * 2] = hexChars[byteValue >>> 4];
1235             chars[j * 2 + 1] = hexChars[byteValue & 0x0F];
1236         }
1237         return new String(chars);
1238     }
1239 
dump(FileDescriptor fd, PrintWriter pw, String[] args)1240     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1241         pw.println("Bound HCE-A/HCE-B services: ");
1242         if (mPaymentServiceBound) {
1243             pw.println("    payment: " + mPaymentServiceName);
1244         }
1245         if (mServiceBound) {
1246             pw.println("    other: " + mServiceName);
1247         }
1248     }
1249 
1250     /**
1251      * Dump debugging information as a HostEmulationManagerProto
1252      *
1253      * Note:
1254      * See proto definition in frameworks/base/core/proto/android/nfc/card_emulation.proto
1255      * When writing a nested message, must call {@link ProtoOutputStream#start(long)} before and
1256      * {@link ProtoOutputStream#end(long)} after.
1257      * Never reuse a proto field number. When removing a field, mark it as reserved.
1258      */
dumpDebug(ProtoOutputStream proto)1259     void dumpDebug(ProtoOutputStream proto) {
1260         if (mPaymentServiceBound) {
1261             Utils.dumpDebugComponentName(
1262                     mPaymentServiceName, proto, HostEmulationManagerProto.PAYMENT_SERVICE_NAME);
1263         }
1264         if (mServiceBound) {
1265             Utils.dumpDebugComponentName(
1266                     mServiceName, proto, HostEmulationManagerProto.SERVICE_NAME);
1267         }
1268     }
1269 
1270     @VisibleForTesting
getState()1271     public int getState(){
1272         return mState;
1273     }
1274 
1275     @VisibleForTesting
getServiceConnection()1276     public ServiceConnection getServiceConnection(){
1277         return mConnection;
1278     }
1279 
1280     @VisibleForTesting
getPaymentConnection()1281     public ServiceConnection getPaymentConnection(){
1282         return mPaymentConnection;
1283     }
1284 
1285     @VisibleForTesting
getMessenger()1286     public IBinder getMessenger(){
1287         if (mActiveService != null) {
1288             return mActiveService.getBinder();
1289         }
1290         return null;
1291     }
1292 
1293     @VisibleForTesting
getLocalMessenger()1294     public Messenger getLocalMessenger() {
1295         return mMessenger;
1296     }
1297 
1298     @VisibleForTesting
getServiceName()1299     public ComponentName getServiceName(){
1300         return mLastBoundPaymentServiceName;
1301     }
1302 
1303     @VisibleForTesting
isServiceBounded()1304     public Boolean isServiceBounded(){
1305         return mServiceBound;
1306     }
1307 
1308     @VisibleForTesting
getPollingLoopFilters()1309     public Map<Integer, Map<String, List<ApduServiceInfo>>> getPollingLoopFilters() {
1310         return mPollingLoopFilters;
1311     }
1312 
1313     @VisibleForTesting
getPollingLoopPatternFilters()1314     public Map<Integer, Map<Pattern, List<ApduServiceInfo>>> getPollingLoopPatternFilters() {
1315         return mPollingLoopPatternFilters;
1316     }
1317 }
1318