• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 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.emulator;
17 
18 import android.app.Instrumentation;
19 import android.content.ComponentName;
20 import android.content.Intent;
21 import android.nfc.NfcAdapter;
22 import android.nfc.cardemulation.CardEmulation;
23 import android.nfc.cardemulation.PollingFrame;
24 import android.util.Log;
25 
26 import androidx.test.platform.app.InstrumentationRegistry;
27 import androidx.test.uiautomator.UiObject;
28 import androidx.test.uiautomator.UiObjectNotFoundException;
29 import androidx.test.uiautomator.UiScrollable;
30 import androidx.test.uiautomator.UiSelector;
31 
32 import com.android.compatibility.common.util.CommonTestUtils;
33 import com.android.nfc.service.AccessServiceTurnObserveModeOnProcessApdu;
34 import com.android.nfc.utils.CommandApdu;
35 import com.android.nfc.utils.HceUtils;
36 import com.android.nfc.utils.NfcSnippet;
37 
38 import com.google.android.mobly.snippet.rpc.AsyncRpc;
39 import com.google.android.mobly.snippet.rpc.Rpc;
40 
41 import java.util.ArrayList;
42 import java.util.Arrays;
43 import java.util.List;
44 
45 public class NfcEmulatorDeviceSnippet extends NfcSnippet {
46 
47     static String sRfOnAction = "com.android.nfc_extras.action.RF_FIELD_ON_DETECTED";
48     private BaseEmulatorActivity mActivity;
49 
50     private static final long TIMEOUT_MS = 10_000L;
51 
52     /**
53      * Starts emulator activity for simple multidevice tests
54      *
55      * @param serviceClassNames - service class names to enable
56      * @param testPassClassName - class name of service that should handle the APDUs
57      * @param isPaymentActivity - whether or not it is a payment activity
58      * @param shouldDisableServicesOnDestroy - whether or not to disable services on destroy
59      */
60     @Rpc(description = "Start simple emulator activity")
startSimpleEmulatorActivity( String[] serviceClassNames, String testPassClassName, boolean isPaymentActivity, boolean shouldDisableServicesOnDestroy)61     public void startSimpleEmulatorActivity(
62             String[] serviceClassNames, String testPassClassName,
63             boolean isPaymentActivity, boolean shouldDisableServicesOnDestroy) {
64         Intent intent =
65                 buildSimpleEmulatorActivityIntent(
66                         serviceClassNames, testPassClassName, null, isPaymentActivity,
67                         shouldDisableServicesOnDestroy);
68         mActivity =
69                 (SimpleEmulatorActivity)
70                         InstrumentationRegistry.getInstrumentation().startActivitySync(intent);
71     }
72 
73     /**
74      * Starts emulator activity for simple multidevice tests
75      *
76      * @param serviceClassNames - services to enable
77      * @param testPassClassName - service that should handle the APDU
78      * @param preferredServiceClassName - preferred service to set
79      * @param isPaymentActivity - whether or not this is a payment activity
80      */
81     @Rpc(description = "Start simple emulator activity with preferred service")
startSimpleEmulatorActivityWithPreferredService( String[] serviceClassNames, String testPassClassName, String preferredServiceClassName, boolean isPaymentActivity)82     public void startSimpleEmulatorActivityWithPreferredService(
83             String[] serviceClassNames,
84             String testPassClassName,
85             String preferredServiceClassName,
86             boolean isPaymentActivity) {
87         Intent intent =
88                 buildSimpleEmulatorActivityIntent(
89                         serviceClassNames,
90                         testPassClassName,
91                         preferredServiceClassName,
92                         isPaymentActivity,
93                         true);
94         mActivity =
95                 (SimpleEmulatorActivity)
96                         InstrumentationRegistry.getInstrumentation().startActivitySync(intent);
97     }
98 
99     @Rpc(description = "Opens emulator activity with Access Service that turns on observe mode")
startAccessServiceObserveModeEmulatorActivity()100     public void startAccessServiceObserveModeEmulatorActivity() {
101         Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
102 
103         Intent intent = new Intent(Intent.ACTION_MAIN);
104         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
105         intent.setClassName(
106                 instrumentation.getTargetContext(),
107                 AccessServiceTurnObserveModeOnProcessApduEmulatorActivity.class.getName());
108 
109         mActivity =
110                 (AccessServiceTurnObserveModeOnProcessApduEmulatorActivity)
111                         instrumentation.startActivitySync(intent);
112     }
113 
114     /** Opens dynamic AID emulator activity */
115     @Rpc(description = "Opens dynamic AID emulator activity")
startDynamicAidEmulatorActivity()116     public void startDynamicAidEmulatorActivity() {
117         Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
118 
119         Intent intent = new Intent(Intent.ACTION_MAIN);
120         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
121         intent.setClassName(
122                 instrumentation.getTargetContext(), DynamicAidEmulatorActivity.class.getName());
123 
124         mActivity = (DynamicAidEmulatorActivity) instrumentation.startActivitySync(intent);
125     }
126 
127     /** Opens prefix payment emulator activity */
128     @Rpc(description = "Opens prefix payment emulator activity")
startPrefixPaymentEmulatorActivity()129     public void startPrefixPaymentEmulatorActivity() {
130         Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
131 
132         Intent intent = new Intent(Intent.ACTION_MAIN);
133         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
134         intent.setClassName(
135                 instrumentation.getTargetContext(), PrefixPaymentEmulatorActivity.class.getName());
136 
137         mActivity = (PrefixPaymentEmulatorActivity) instrumentation.startActivitySync(intent);
138     }
139 
140     /** Opens prefix payment emulator 2 activity */
141     @Rpc(description = "Opens prefix payment emulator 2 activity")
startPrefixPaymentEmulator2Activity()142     public void startPrefixPaymentEmulator2Activity() {
143         Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
144 
145         Intent intent = new Intent(Intent.ACTION_MAIN);
146         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
147         intent.setClassName(
148                 instrumentation.getTargetContext(), PrefixPaymentEmulator2Activity.class.getName());
149 
150         mActivity = (PrefixPaymentEmulator2Activity) instrumentation.startActivitySync(intent);
151     }
152 
153     /** Opens dual non payment activity */
154     @Rpc(description = "Opens dual non-payment prefix emulator activity")
startDualNonPaymentPrefixEmulatorActivity()155     public void startDualNonPaymentPrefixEmulatorActivity() {
156         Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
157 
158         Intent intent = new Intent(Intent.ACTION_MAIN);
159         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
160         intent.setClassName(
161                 instrumentation.getTargetContext(),
162                 DualNonPaymentPrefixEmulatorActivity.class.getName());
163 
164         mActivity =
165                 (DualNonPaymentPrefixEmulatorActivity) instrumentation.startActivitySync(intent);
166     }
167 
168     /** Opens off host emulator activity */
169     @Rpc(description = "Open off host emulator activity")
startOffHostEmulatorActivity(boolean enableObserveMode)170     public void startOffHostEmulatorActivity(boolean enableObserveMode) {
171         Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
172 
173         Intent intent = new Intent(Intent.ACTION_MAIN);
174         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
175         intent.setClassName(
176                 instrumentation.getTargetContext(), OffHostEmulatorActivity.class.getName());
177         intent.putExtra(OffHostEmulatorActivity.EXTRA_ENABLE_OBSERVE_MODE, enableObserveMode);
178 
179         mActivity = (OffHostEmulatorActivity) instrumentation.startActivitySync(intent);
180     }
181 
182     /** Opens screen on only off host emulator activity */
183     @Rpc(description = "Open screen-on only off host emulator activity")
startScreenOnOnlyOffHostEmulatorActivity()184     public void startScreenOnOnlyOffHostEmulatorActivity() {
185         Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
186 
187         Intent intent = new Intent(Intent.ACTION_MAIN);
188         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
189         intent.setClassName(
190                 instrumentation.getTargetContext(),
191                 ScreenOnOnlyOffHostEmulatorActivity.class.getName());
192 
193         mActivity = (ScreenOnOnlyOffHostEmulatorActivity) instrumentation.startActivitySync(intent);
194     }
195 
196     /** Opens on and off host emulator activity */
197     @Rpc(description = "Open on and off host emulator activity")
startOnAndOffHostEmulatorActivity()198     public void startOnAndOffHostEmulatorActivity() {
199         Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
200 
201         Intent intent = new Intent(Intent.ACTION_MAIN);
202         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
203         intent.setClassName(
204                 instrumentation.getTargetContext(), OnAndOffHostEmulatorActivity.class.getName());
205 
206         mActivity = (OnAndOffHostEmulatorActivity) instrumentation.startActivitySync(intent);
207     }
208 
209     /** Opens throughput emulator activity */
210     @Rpc(description = "Opens throughput emulator activity")
startThroughputEmulatorActivity()211     public void startThroughputEmulatorActivity() {
212         Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
213 
214         Intent intent = new Intent(Intent.ACTION_MAIN);
215         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
216         intent.setClassName(
217                 instrumentation.getTargetContext(), ThroughputEmulatorActivity.class.getName());
218 
219         mActivity = (ThroughputEmulatorActivity) instrumentation.startActivitySync(intent);
220     }
221 
222     /** Opens polling frame emulator activity */
223     @Rpc(description = "Opens polling frame emulator activity")
startPollingFrameEmulatorActivity()224     public void startPollingFrameEmulatorActivity() {
225         Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
226 
227         Intent intent = new Intent(Intent.ACTION_MAIN);
228         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
229         intent.setClassName(
230                 instrumentation.getTargetContext(), PollingFrameEmulatorActivity.class.getName());
231 
232         mActivity = (PollingFrameEmulatorActivity) instrumentation.startActivitySync(intent);
233     }
234 
235     /** Opens large num AIDs emulator activity */
236     @Rpc(description = "Opens large num AIDs emulator activity")
startLargeNumAidsEmulatorActivity()237     public void startLargeNumAidsEmulatorActivity() {
238         Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
239 
240         Intent intent = new Intent(Intent.ACTION_MAIN);
241         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
242         intent.setClassName(
243                 instrumentation.getTargetContext(), LargeNumAidsEmulatorActivity.class.getName());
244 
245         mActivity = (LargeNumAidsEmulatorActivity) instrumentation.startActivitySync(intent);
246     }
247 
248     /** Opens screen off emulator activity */
249     @Rpc(description = "Opens screen off emulator activity")
startScreenOffPaymentEmulatorActivity()250     public void startScreenOffPaymentEmulatorActivity() {
251         Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
252 
253         Intent intent = new Intent(Intent.ACTION_MAIN);
254         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
255         intent.setClassName(
256                 instrumentation.getTargetContext(),
257                 ScreenOffPaymentEmulatorActivity.class.getName());
258 
259         mActivity = (ScreenOffPaymentEmulatorActivity) instrumentation.startActivitySync(intent);
260     }
261 
262     /** Opens conflicting non-payment prefix emulator activity */
263     @Rpc(description = "Opens conflicting non-payment prefix emulator activity")
startConflictingNonPaymentPrefixEmulatorActivity()264     public void startConflictingNonPaymentPrefixEmulatorActivity() {
265         Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
266 
267         Intent intent = new Intent(Intent.ACTION_MAIN);
268         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
269         intent.setClassName(
270                 instrumentation.getTargetContext(),
271                 ConflictingNonPaymentPrefixEmulatorActivity.class.getName());
272         mActivity =
273                 (ConflictingNonPaymentPrefixEmulatorActivity)
274                         instrumentation.startActivitySync(intent);
275     }
276 
277     /** Opens protocol params emulator activity */
278     @Rpc(description = "Opens protocol params emulator activity")
startProtocolParamsEmulatorActivity()279     public void startProtocolParamsEmulatorActivity() {
280         Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
281 
282         Intent intent = new Intent(Intent.ACTION_MAIN);
283         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
284         intent.setClassName(
285                 instrumentation.getTargetContext(), ProtocolParamsEmulatorActivity.class.getName());
286 
287         mActivity = (ProtocolParamsEmulatorActivity) instrumentation.startActivitySync(intent);
288     }
289 
290     /** Checks if AID prefix registration is supported */
291     @Rpc(description = "Checks if AID prefix registration is supported")
isAidPrefixRegistrationSupported()292     public boolean isAidPrefixRegistrationSupported() {
293         NfcAdapter adapter = NfcAdapter.getDefaultAdapter(mContext);
294         if (adapter == null) {
295             return false;
296         }
297         CardEmulation cardEmulation = CardEmulation.getInstance(adapter);
298         if (cardEmulation == null) {
299             return false;
300         }
301         return cardEmulation.supportsAidPrefixRegistration();
302     }
303 
304     @Rpc(description = "Returns if observe mode is supported.")
isObserveModeSupported()305     public boolean isObserveModeSupported() {
306         NfcAdapter adapter = NfcAdapter.getDefaultAdapter(mContext);
307         if (adapter == null) {
308             return false;
309         }
310         return adapter.isObserveModeSupported();
311     }
312 
313     @Rpc(description = "Returns if observe mode is enabled.")
isObserveModeEnabled()314     public boolean isObserveModeEnabled() {
315         return mActivity.isObserveModeEnabled();
316     }
317 
318     @Rpc(description = "Set observe mode.")
setObserveModeEnabled(boolean enable)319     public boolean setObserveModeEnabled(boolean enable) {
320         if (mActivity != null && isObserveModeSupported()) {
321             return mActivity.setObserveModeEnabled(enable);
322         }
323         return false;
324     }
325 
326     /** Open polling and off host emulator activity */
327     @Rpc(description = "Open polling and off host emulator activity")
startPollingAndOffHostEmulatorActivity()328     public void startPollingAndOffHostEmulatorActivity() {
329         Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
330         Intent intent = new Intent(Intent.ACTION_MAIN);
331         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
332         intent.setClassName(
333                 instrumentation.getTargetContext(),
334                 PollingAndOffHostEmulatorActivity.class.getName());
335         intent.putExtra(PollingLoopEmulatorActivity.NFC_TECH_KEY, NfcAdapter.FLAG_READER_NFC_A);
336         mActivity = (PollingAndOffHostEmulatorActivity) instrumentation.startActivitySync(intent);
337     }
338 
339     /** Open polling loop emulator activity for Type A */
340     @Rpc(description = "Open polling loop emulator activity for polling loop A test")
startPollingLoopAEmulatorActivity()341     public void startPollingLoopAEmulatorActivity() {
342         Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
343         Intent intent =
344                 buildPollingLoopEmulatorIntent(instrumentation, NfcAdapter.FLAG_READER_NFC_A);
345         mActivity = (PollingLoopEmulatorActivity) instrumentation.startActivitySync(intent);
346     }
347 
348     /** Open polling loop emulator activity for Type B */
349     @Rpc(description = "Open polling loop emulator activity for polling loop B test")
startPollingLoopBEmulatorActivity()350     public void startPollingLoopBEmulatorActivity() {
351         Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
352         Intent intent =
353                 buildPollingLoopEmulatorIntent(instrumentation, NfcAdapter.FLAG_READER_NFC_B);
354         mActivity = (PollingLoopEmulatorActivity) instrumentation.startActivitySync(intent);
355     }
356 
357     /** Open polling loop emulator activity for Type A and B */
358     @Rpc(description = "Open polling loop emulator activity for polling loop A/B test")
startPollingLoopABEmulatorActivity()359     public void startPollingLoopABEmulatorActivity() {
360         Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
361         Intent intent =
362                 buildPollingLoopEmulatorIntent(
363                         instrumentation,
364                         NfcAdapter.FLAG_READER_NFC_A | NfcAdapter.FLAG_READER_NFC_B);
365         mActivity = (PollingLoopEmulatorActivity) instrumentation.startActivitySync(intent);
366     }
367 
368     /** Open polling loop emulator activity for Type A and B */
369     @Rpc(description = "Open polling loop emulator activity for custom polling frame test")
startCustomPollingFrameEmulatorActivity(String customFrame)370     public void startCustomPollingFrameEmulatorActivity(String customFrame) {
371         Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
372         Intent intent =
373                 buildPollingLoopEmulatorIntent(
374                         instrumentation,
375                         NfcAdapter.FLAG_READER_NFC_A | NfcAdapter.FLAG_READER_NFC_B);
376         intent.putExtra(PollingLoopEmulatorActivity.NFC_CUSTOM_FRAME_KEY, customFrame);
377         mActivity = (PollingLoopEmulatorActivity) instrumentation.startActivitySync(intent);
378     }
379 
380     @Rpc(description = "Open two polling frame emulator activity for two readers test")
startTwoPollingFrameEmulatorActivity()381     public void startTwoPollingFrameEmulatorActivity() {
382         Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
383 
384         Intent intent = new Intent(Intent.ACTION_MAIN);
385         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
386         intent.setClassName(
387                 instrumentation.getTargetContext(),
388                 TwoPollingFrameEmulatorActivity.class.getName());
389 
390         mActivity = (TwoPollingFrameEmulatorActivity) instrumentation.startActivitySync(intent);
391     }
392 
393     @Rpc(description = "Opens PN532 Activity")
startPN532Activity()394     public void startPN532Activity() {
395         Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
396 
397         Intent intent = new Intent(Intent.ACTION_MAIN);
398         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
399         intent.setClassName(instrumentation.getTargetContext(), PN532Activity.class.getName());
400 
401         mActivity = (PN532Activity) instrumentation.startActivitySync(intent);
402     }
403 
404     @Rpc(description = "Opens the Event Listener Activity")
startEventListenerActivity()405     public void startEventListenerActivity() {
406         Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
407 
408         Intent intent = new Intent(Intent.ACTION_MAIN);
409         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
410         intent.setClassName(instrumentation.getTargetContext(),
411             EventListenerEmulatorActivity.class.getName());
412 
413         mActivity = (EventListenerEmulatorActivity) instrumentation.startActivitySync(intent);
414     }
415 
416     @Rpc(description = "Opens the Exit Frame Activity")
startExitFrameActivity(String intendedExitFrame, String[] plpfs, boolean waitForTransaction)417     public void startExitFrameActivity(String intendedExitFrame, String[] plpfs,
418             boolean waitForTransaction) {
419         Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
420 
421         Intent intent = new Intent(Intent.ACTION_MAIN);
422         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
423         intent.setClassName(instrumentation.getTargetContext(),
424                 ExitFrameEmulatorActivity.class.getName());
425         intent.putExtra(ExitFrameEmulatorActivity.EXIT_FRAME_KEY, intendedExitFrame);
426         intent.putStringArrayListExtra(ExitFrameEmulatorActivity.REGISTER_PATTERNS_KEY,
427                 new ArrayList<>(Arrays.asList(plpfs)));
428         intent.putExtra(ExitFrameEmulatorActivity.WAIT_FOR_TRANSACTION_KEY, waitForTransaction);
429 
430         mActivity = (ExitFrameEmulatorActivity) instrumentation.startActivitySync(intent);
431     }
432 
433     /** Registers receiver that waits for RF field broadcast */
434     @AsyncRpc(description = "Waits for RF field detected broadcast")
asyncWaitForRfOnBroadcast(String callbackId, String eventName)435     public void asyncWaitForRfOnBroadcast(String callbackId, String eventName) {
436         registerSnippetBroadcastReceiver(callbackId, eventName, sRfOnAction);
437     }
438 
439     /** Registers receiver that waits for RF field broadcast */
440     @AsyncRpc(description = "Waits for RF field detected broadcast")
asyncWaitsForTagDiscovered(String callbackId, String eventName)441     public void asyncWaitsForTagDiscovered(String callbackId, String eventName) {
442         registerSnippetBroadcastReceiver(
443                 callbackId, eventName, PN532Activity.ACTION_TAG_DISCOVERED);
444     }
445 
446     @Rpc(description = "Enable reader mode with given flags")
enableReaderMode(int flags)447     public void enableReaderMode(int flags) {
448         if (mActivity == null || !(mActivity instanceof PN532Activity)) {
449             return;
450         }
451         ((PN532Activity) mActivity).enableReaderMode(flags);
452     }
453 
454     /** Returns a list of collected polling frames */
455     @Rpc(description = "Get polling frames")
getPollingFrames()456     public PollingFrame[] getPollingFrames() {
457         if (mActivity == null || !(mActivity instanceof PollingFrameEmulatorActivity)) {
458             Log.e(TAG, "Activity is null.");
459             return new PollingFrame[] {};
460         }
461         Log.e(TAG, "Activity is not null.");
462         return ((PollingFrameEmulatorActivity) mActivity).getPollingFrames();
463     }
464 
465     /** Registers receiver that waits for OFF polling frame */
466     @AsyncRpc(description = "Waits for OFF polling frame")
asyncWaitForPollingFrameOff(String callbackId, String eventName)467     public void asyncWaitForPollingFrameOff(String callbackId, String eventName) {
468         registerSnippetBroadcastReceiver(
469                 callbackId, eventName, PollingFrameEmulatorActivity.POLLING_FRAME_OFF_DETECTED);
470         Log.i("PollingFrameEmulatorActivity", "register for polling frame off");
471     }
472 
473     /** Registers receiver for polling loop action */
474     @AsyncRpc(description = "Waits for seen correct polling loop")
asyncWaitsForSeenCorrectPollingLoop(String callbackId, String eventName)475     public void asyncWaitsForSeenCorrectPollingLoop(String callbackId, String eventName) {
476         registerSnippetBroadcastReceiver(
477                 callbackId,
478                 eventName,
479                 PollingLoopEmulatorActivity.SEEN_CORRECT_POLLING_LOOP_ACTION);
480     }
481 
482     /** Registers receiver for Test Pass event */
483     @AsyncRpc(description = "Waits for Test Pass event")
asyncWaitForTestPass(String callbackId, String eventName)484     public void asyncWaitForTestPass(String callbackId, String eventName) {
485         registerSnippetBroadcastReceiver(
486                 callbackId, eventName, BaseEmulatorActivity.ACTION_TEST_PASSED);
487     }
488 
489     /** Registers receiver for Role Held event */
490     @AsyncRpc(description = "Waits for Role Held event")
asyncWaitForRoleHeld(String callbackId, String eventName)491     public void asyncWaitForRoleHeld(String callbackId, String eventName) {
492         registerSnippetBroadcastReceiver(
493                 callbackId, eventName, BaseEmulatorActivity.ACTION_ROLE_HELD);
494     }
495 
496     /** Registers receiver for Screen Off event */
497     @AsyncRpc(description = "Waits for Screen Off event")
asyncWaitForScreenOff(String callbackId, String eventName)498     public void asyncWaitForScreenOff(String callbackId, String eventName) {
499         registerSnippetBroadcastReceiver(callbackId, eventName, Intent.ACTION_SCREEN_OFF);
500     }
501 
502     /** Registers receiver for Screen On event */
503     @AsyncRpc(description = "Waits for Screen On event")
asyncWaitForScreenOn(String callbackId, String eventName)504     public void asyncWaitForScreenOn(String callbackId, String eventName) {
505         registerSnippetBroadcastReceiver(callbackId, eventName, Intent.ACTION_SCREEN_ON);
506     }
507 
508     @AsyncRpc(description = "Waits for Observe Mode False")
asyncWaitForObserveModeFalse(String callbackId, String eventName)509     public void asyncWaitForObserveModeFalse(String callbackId, String eventName) {
510         registerSnippetBroadcastReceiver(
511                 callbackId,
512                 eventName,
513                 AccessServiceTurnObserveModeOnProcessApdu.OBSERVE_MODE_FALSE);
514     }
515 
516     /** Sets the listen tech for the active emulator activity */
517     @Rpc(description = "Set the listen tech for the emulator")
setListenTech(Integer listenTech)518     public void setListenTech(Integer listenTech) {
519         if (mActivity == null) {
520             Log.e(TAG, "Activity is null.");
521             return;
522         }
523         mActivity.setListenTech(listenTech);
524     }
525 
526     /** Resets the listen tech for the active emulator activity */
527     @Rpc(description = "Reset the listen tech for the emulator")
resetListenTech()528     public void resetListenTech() {
529         if (mActivity == null) {
530             Log.e(TAG, "Activity is null.");
531             return;
532         }
533         mActivity.resetListenTech();
534     }
535 
536     /** Automatically selects TransportService2 from list of services. */
537     @Rpc(description = "Automatically selects TransportService2 from list of services.")
selectItem()538     public void selectItem() {
539         Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
540 
541         String text = instrumentation.getTargetContext().getString(R.string.transportService2);
542         Log.d(TAG, text);
543         try {
544             UiScrollable listView = new UiScrollable(new UiSelector());
545             listView.waitForExists(TIMEOUT_MS);
546             listView.scrollTextIntoView(text);
547             UiObject listViewItem =
548                     listView.getChildByText(
549                             new UiSelector().className(android.widget.TextView.class.getName()),
550                             "" + text + "");
551             if (listViewItem.exists()) {
552                 listViewItem.clickAndWaitForNewWindow();
553                 Log.d(TAG, text + " ListView item was clicked.");
554                 // Wait for NFC to update services.
555                 Thread.currentThread().sleep(1_000);
556             } else {
557                 Log.e(TAG, "UI Object does not exist.");
558             }
559         } catch (UiObjectNotFoundException|InterruptedException e) {
560             Log.e(TAG, "Ui Object not found.", e);
561         }
562     }
563 
564     /** Closes emulator activity */
565     @Rpc(description = "Close activity if one was opened.")
closeActivity()566     public void closeActivity() {
567         if (mActivity != null) {
568             mActivity.finish();
569             try {
570                 CommonTestUtils.waitUntil(
571                         "Activity didn't finish in 5 seconds",
572                         5,
573                         () -> mActivity.isDestroyed()
574                 );
575             } catch (InterruptedException | AssertionError e) {
576             }
577         }
578     }
579 
580     /** Wait for preferred service to be set */
581     @Rpc(description = "Waits for preferred service to be set")
waitForPreferredService()582     public void waitForPreferredService() {
583         if (mActivity != null) {
584             mActivity.waitForPreferredService();
585         }
586     }
587 
588     /** Wait for preferred service to be set */
589     @Rpc(description = "Waits for preferred service to be set")
waitForService(String serviceName)590     public void waitForService(String serviceName) {
591         if (mActivity != null) {
592             mActivity.waitForService(
593                     new ComponentName(HceUtils.EMULATOR_PACKAGE_NAME, serviceName));
594         }
595     }
596 
597     @Rpc(description = "Gets command apdus")
getCommandApdus(String serviceClassName)598     public String[] getCommandApdus(String serviceClassName) {
599         CommandApdu[] commandApdus = HceUtils.COMMAND_APDUS_BY_SERVICE.get(serviceClassName);
600         return Arrays.stream(commandApdus)
601                 .map(commandApdu -> new String(commandApdu.getApdu()))
602                 .toArray(String[]::new);
603     }
604 
605     @Rpc(description = "Gets response apdus")
getResponseApdus(String serviceClassName)606     public String[] getResponseApdus(String serviceClassName) {
607         return HceUtils.RESPONSE_APDUS_BY_SERVICE.get(serviceClassName);
608     }
609 
610     /** Builds intent to launch polling loop emulators */
buildPollingLoopEmulatorIntent(Instrumentation instrumentation, int nfcTech)611     private Intent buildPollingLoopEmulatorIntent(Instrumentation instrumentation, int nfcTech) {
612         Intent intent = new Intent(Intent.ACTION_MAIN);
613         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
614         intent.setClassName(
615                 instrumentation.getTargetContext(), PollingLoopEmulatorActivity.class.getName());
616         intent.putExtra(PollingLoopEmulatorActivity.NFC_TECH_KEY, nfcTech);
617         return intent;
618     }
619 
620     /** Builds intent to launch simple emulator activity */
buildSimpleEmulatorActivityIntent( String[] serviceClassNames, String expectedServiceClassName, String preferredServiceClassName, boolean isPaymentActivity, boolean shouldDisableServicesOnDestroy)621     private Intent buildSimpleEmulatorActivityIntent(
622             String[] serviceClassNames,
623             String expectedServiceClassName,
624             String preferredServiceClassName,
625             boolean isPaymentActivity,
626             boolean shouldDisableServicesOnDestroy) {
627         Intent intent = new Intent(Intent.ACTION_MAIN);
628         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
629         intent.setClassName(
630                 InstrumentationRegistry.getInstrumentation().getTargetContext(),
631                 SimpleEmulatorActivity.class.getName());
632 
633         if (serviceClassNames != null && serviceClassNames.length > 0) {
634             List<ComponentName> services =
635                     Arrays.stream(serviceClassNames)
636                             .map(cls -> new ComponentName(HceUtils.EMULATOR_PACKAGE_NAME, cls))
637                             .toList();
638             intent.putExtra(SimpleEmulatorActivity.EXTRA_SERVICES, new ArrayList<>(services));
639         }
640 
641         if (expectedServiceClassName != null) {
642             intent.putExtra(
643                     SimpleEmulatorActivity.EXTRA_EXPECTED_SERVICE,
644                     new ComponentName(HceUtils.EMULATOR_PACKAGE_NAME, expectedServiceClassName));
645         }
646 
647         if (preferredServiceClassName != null) {
648             intent.putExtra(
649                     SimpleEmulatorActivity.EXTRA_PREFERRED_SERVICE,
650                     new ComponentName(HceUtils.EMULATOR_PACKAGE_NAME, preferredServiceClassName));
651         }
652 
653         intent.putExtra(SimpleEmulatorActivity.EXTRA_IS_PAYMENT_ACTIVITY, isPaymentActivity);
654         intent.putExtra(
655                 SimpleEmulatorActivity.EXTRA_SHOULD_DISABLE_SERVICES_ON_DESTROY,
656                 shouldDisableServicesOnDestroy);
657         return intent;
658     }
659 }
660