• Home
  • History
  • Annotate
  • 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.reader;
17 
18 
19 import android.app.Instrumentation;
20 import android.content.Intent;
21 import android.os.RemoteException;
22 import android.util.Log;
23 
24 import androidx.test.platform.app.InstrumentationRegistry;
25 import androidx.test.uiautomator.UiDevice;
26 
27 import com.android.nfc.utils.CommandApdu;
28 import com.android.nfc.utils.HceUtils;
29 import com.android.nfc.utils.NfcSnippet;
30 import com.android.nfc.service.AccessService;
31 import com.android.nfc.service.LargeNumAidsService;
32 import com.android.nfc.service.OffHostService;
33 import com.android.nfc.service.PaymentService1;
34 import com.android.nfc.service.PaymentService2;
35 import com.android.nfc.service.PaymentServiceDynamicAids;
36 import com.android.nfc.service.PrefixAccessService;
37 import com.android.nfc.service.PrefixPaymentService1;
38 import com.android.nfc.service.PrefixTransportService1;
39 import com.android.nfc.service.PrefixTransportService2;
40 import com.android.nfc.service.ScreenOffPaymentService;
41 import com.android.nfc.service.ScreenOnOnlyOffHostService;
42 import com.android.nfc.service.ThroughputService;
43 import com.android.nfc.service.TransportService1;
44 import com.android.nfc.service.TransportService2;
45 
46 import com.google.android.mobly.snippet.rpc.AsyncRpc;
47 import com.google.android.mobly.snippet.rpc.Rpc;
48 
49 public class NfcReaderDeviceSnippet extends NfcSnippet {
50     protected static final String TAG = "NfcSnippet";
51 
52     private BaseReaderActivity mActivity;
53 
54     /** Opens NFC reader for single non-payment test */
55     @Rpc(description = "Open simple reader activity for single non-payment test")
startSingleNonPaymentReaderActivity()56     public void startSingleNonPaymentReaderActivity() {
57         Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
58         Intent intent =
59                 buildReaderIntentWithApduSequence(
60                         instrumentation,
61                         HceUtils.COMMAND_APDUS_BY_SERVICE.get(TransportService1.class.getName()),
62                         HceUtils.RESPONSE_APDUS_BY_SERVICE.get(TransportService1.class.getName()));
63         mActivity = (SimpleReaderActivity) instrumentation.startActivitySync(intent);
64     }
65 
66     /** Open simple reader activity for single non-payment test */
67     @Rpc(description = "Open simple reader activity for single non-payment test")
startSinglePaymentReaderActivity()68     public void startSinglePaymentReaderActivity() {
69         Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
70         Intent intent =
71                 buildReaderIntentWithApduSequence(
72                         instrumentation,
73                         HceUtils.COMMAND_APDUS_BY_SERVICE.get(PaymentService1.class.getName()),
74                         HceUtils.RESPONSE_APDUS_BY_SERVICE.get(PaymentService1.class.getName()));
75         mActivity = (SimpleReaderActivity) instrumentation.startActivitySync(intent);
76     }
77 
78     /** Opens simple reader activity for dual payment services test */
79     @Rpc(description = "Opens simple reader activity for dual payment services test")
startDualPaymentReaderActivity()80     public void startDualPaymentReaderActivity() {
81         Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
82         Intent intent =
83                 buildReaderIntentWithApduSequence(
84                         instrumentation,
85                         HceUtils.COMMAND_APDUS_BY_SERVICE.get(PaymentService1.class.getName()),
86                         HceUtils.RESPONSE_APDUS_BY_SERVICE.get(PaymentService1.class.getName()));
87         mActivity = (SimpleReaderActivity) instrumentation.startActivitySync(intent);
88     }
89 
90     /** Opens simple reader activity for foreground payment test */
91     @Rpc(description = "Opens simple reader activity for foreground payment test")
startForegroundPaymentReaderActivity()92     public void startForegroundPaymentReaderActivity() {
93         Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
94         Intent intent =
95                 buildReaderIntentWithApduSequence(
96                         instrumentation,
97                         HceUtils.COMMAND_APDUS_BY_SERVICE.get(PaymentService2.class.getName()),
98                         HceUtils.RESPONSE_APDUS_BY_SERVICE.get(PaymentService2.class.getName()));
99         mActivity = (SimpleReaderActivity) instrumentation.startActivitySync(intent);
100     }
101 
102     /** Opens simple reader activity for dynamic AID test */
103     @Rpc(description = "Opens simple reader activity for dynamic AID test")
startDynamicAidReaderActivity()104     public void startDynamicAidReaderActivity() {
105         Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
106         Intent intent =
107                 buildReaderIntentWithApduSequence(
108                         instrumentation,
109                         HceUtils.COMMAND_APDUS_BY_SERVICE.get(
110                                 PaymentServiceDynamicAids.class.getName()),
111                         HceUtils.RESPONSE_APDUS_BY_SERVICE.get(
112                                 PaymentServiceDynamicAids.class.getName()));
113         mActivity = (SimpleReaderActivity) instrumentation.startActivitySync(intent);
114     }
115 
116     /** Opens simple reader activity for prefix payment test */
117     @Rpc(description = "Opens simple reader activity for prefix payment test")
startPrefixPaymentReaderActivity()118     public void startPrefixPaymentReaderActivity() {
119         Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
120         Intent intent =
121                 buildReaderIntentWithApduSequence(
122                         instrumentation,
123                         HceUtils.COMMAND_APDUS_BY_SERVICE.get(
124                                 PrefixPaymentService1.class.getName()),
125                         HceUtils.RESPONSE_APDUS_BY_SERVICE.get(
126                                 PrefixPaymentService1.class.getName()));
127         mActivity = (SimpleReaderActivity) instrumentation.startActivitySync(intent);
128     }
129 
130     /** Opens simple reader activity for prefix payment 2 test */
131     @Rpc(description = "Opens simple reader activity for prefix payment 2 test")
startPrefixPaymentReader2Activity()132     public void startPrefixPaymentReader2Activity() {
133         Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
134         Intent intent =
135                 buildReaderIntentWithApduSequence(
136                         instrumentation,
137                         HceUtils.COMMAND_APDUS_BY_SERVICE.get(
138                                 PrefixPaymentService1.class.getName()),
139                         HceUtils.RESPONSE_APDUS_BY_SERVICE.get(
140                                 PrefixPaymentService1.class.getName()));
141         mActivity = (SimpleReaderActivity) instrumentation.startActivitySync(intent);
142     }
143 
144     /** Opens simple reader activity for non-payment prefix test */
145     @Rpc(description = "Opens simple reader activity for non-payment prefix test.")
startDualNonPaymentPrefixReaderActivity()146     public void startDualNonPaymentPrefixReaderActivity() {
147         Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
148         CommandApdu[] prefixTransportService1Commands =
149                 HceUtils.COMMAND_APDUS_BY_SERVICE.get(PrefixTransportService1.class.getName());
150         CommandApdu[] prefixAccessServiceCommands =
151                 HceUtils.COMMAND_APDUS_BY_SERVICE.get(PrefixAccessService.class.getName());
152 
153         // Combine command/response APDU arrays
154         CommandApdu[] combinedCommands =
155                 new CommandApdu
156                         [prefixTransportService1Commands.length
157                                 + prefixAccessServiceCommands.length];
158         System.arraycopy(
159                 prefixTransportService1Commands,
160                 0,
161                 combinedCommands,
162                 0,
163                 prefixTransportService1Commands.length);
164         System.arraycopy(
165                 prefixAccessServiceCommands,
166                 0,
167                 combinedCommands,
168                 prefixTransportService1Commands.length,
169                 prefixAccessServiceCommands.length);
170 
171         String[] prefixTransportService1Responses =
172                 HceUtils.RESPONSE_APDUS_BY_SERVICE.get(PrefixTransportService1.class.getName());
173         String[] prefixAccessServiceResponses =
174                 HceUtils.RESPONSE_APDUS_BY_SERVICE.get(PrefixAccessService.class.getName());
175 
176         String[] combinedResponses =
177                 new String
178                         [prefixTransportService1Responses.length
179                                 + prefixAccessServiceResponses.length];
180         System.arraycopy(
181                 prefixTransportService1Responses,
182                 0,
183                 combinedResponses,
184                 0,
185                 prefixTransportService1Responses.length);
186         System.arraycopy(
187                 prefixAccessServiceResponses,
188                 0,
189                 combinedResponses,
190                 prefixTransportService1Responses.length,
191                 prefixAccessServiceResponses.length);
192         Intent intent =
193                 buildReaderIntentWithApduSequence(
194                         instrumentation, combinedCommands, combinedResponses);
195         mActivity = (SimpleReaderActivity) instrumentation.startActivitySync(intent);
196     }
197 
198     /** Open simple reader activity for off host test. */
199     @Rpc(description = "Open simple reader activity for off host test")
startOffHostReaderActivity()200     public void startOffHostReaderActivity() {
201         Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
202         Intent intent =
203                 buildReaderIntentWithApduSequence(
204                         instrumentation,
205                         HceUtils.COMMAND_APDUS_BY_SERVICE.get(OffHostService.class.getName()),
206                         HceUtils.RESPONSE_APDUS_BY_SERVICE.get(OffHostService.class.getName()));
207         mActivity = (SimpleReaderActivity) instrumentation.startActivitySync(intent);
208     }
209 
210     /** Open simple reader activity for on and off host test. */
211     @Rpc(description = "Open simple reader activity for off host test")
startOnAndOffHostReaderActivity()212     public void startOnAndOffHostReaderActivity() {
213         Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
214         // Merge command/response APDU sequences.
215         CommandApdu[] offHostCommands = HceUtils.COMMAND_APDUS_BY_SERVICE.get(
216                 OffHostService.class.getName());
217         CommandApdu[] onHostCommands = HceUtils.COMMAND_APDUS_BY_SERVICE.get(
218                 TransportService1.class.getName());
219         CommandApdu[] combinedCommands =
220                 new CommandApdu[offHostCommands.length + onHostCommands.length];
221         System.arraycopy(offHostCommands, 0, combinedCommands, 0, offHostCommands.length);
222         System.arraycopy(onHostCommands, 0, combinedCommands, offHostCommands.length,
223                 onHostCommands.length);
224 
225         String[] offHostResponses = HceUtils.RESPONSE_APDUS_BY_SERVICE.get(
226                 OffHostService.class.getName());
227         String[] onHostResponses = HceUtils.RESPONSE_APDUS_BY_SERVICE.get(
228                 TransportService1.class.getName());
229         String[] combinedResponses = new String[offHostResponses.length + onHostResponses.length];
230 
231         System.arraycopy(offHostResponses, 0, combinedResponses, 0, offHostResponses.length);
232         System.arraycopy(onHostResponses, 0, combinedResponses, offHostResponses.length,
233                 onHostResponses.length);
234 
235         Intent intent =
236                 buildReaderIntentWithApduSequence(
237                         instrumentation,
238                         combinedCommands,
239                         combinedResponses);
240         mActivity = (SimpleReaderActivity) instrumentation.startActivitySync(intent);
241     }
242 
243     /** Open simple reader activity for dual non-payment test */
244     @Rpc(description = "Open simple reader activity for dual non-payment test")
startDualNonPaymentReaderActivity()245     public void startDualNonPaymentReaderActivity() {
246         Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
247         CommandApdu[] transportService2CommandApdus =
248                 HceUtils.COMMAND_APDUS_BY_SERVICE.get(TransportService2.class.getName());
249         String[] transportService2ResponseApdus =
250                 HceUtils.RESPONSE_APDUS_BY_SERVICE.get(TransportService2.class.getName());
251 
252         CommandApdu[] accessServiceCommandApdus =
253                 HceUtils.COMMAND_APDUS_BY_SERVICE.get(AccessService.class.getName());
254         String[] accessServiceResponseApdus =
255                 HceUtils.RESPONSE_APDUS_BY_SERVICE.get(AccessService.class.getName());
256         // Combine command/response APDU arrays
257         CommandApdu[] commandSequences =
258                 new CommandApdu
259                         [transportService2CommandApdus.length + accessServiceCommandApdus.length];
260         System.arraycopy(
261                 transportService2CommandApdus,
262                 0,
263                 commandSequences,
264                 0,
265                 transportService2CommandApdus.length);
266         System.arraycopy(
267                 accessServiceCommandApdus,
268                 0,
269                 commandSequences,
270                 transportService2CommandApdus.length,
271                 accessServiceCommandApdus.length);
272         String[] responseSequences =
273                 new String
274                         [transportService2ResponseApdus.length + accessServiceResponseApdus.length];
275         System.arraycopy(
276                 transportService2ResponseApdus,
277                 0,
278                 responseSequences,
279                 0,
280                 transportService2ResponseApdus.length);
281         System.arraycopy(
282                 accessServiceResponseApdus,
283                 0,
284                 responseSequences,
285                 transportService2ResponseApdus.length,
286                 accessServiceResponseApdus.length);
287 
288         Intent intent =
289                 buildReaderIntentWithApduSequence(
290                         instrumentation, commandSequences, responseSequences);
291         mActivity = (SimpleReaderActivity) instrumentation.startActivitySync(intent);
292     }
293 
294     /** Open simple reader activity for foreground non-payment test */
295     @Rpc(description = "Open simple reader activity for foreground non-payment test")
startForegroundNonPaymentReaderActivity()296     public void startForegroundNonPaymentReaderActivity() {
297         Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
298         Intent intent =
299                 buildReaderIntentWithApduSequence(
300                         instrumentation,
301                         HceUtils.COMMAND_APDUS_BY_SERVICE.get(TransportService2.class.getName()),
302                         HceUtils.RESPONSE_APDUS_BY_SERVICE.get(TransportService2.class.getName()));
303         mActivity = (SimpleReaderActivity) instrumentation.startActivitySync(intent);
304     }
305 
306     /** Open simple reader activity for throughput test */
307     @Rpc(description = "Open simple reader activity for throughput test")
startThroughputReaderActivity()308     public void startThroughputReaderActivity() {
309         Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
310         Intent intent =
311                 buildReaderIntentWithApduSequence(
312                         instrumentation,
313                         HceUtils.COMMAND_APDUS_BY_SERVICE.get(ThroughputService.class.getName()),
314                         HceUtils.RESPONSE_APDUS_BY_SERVICE.get(ThroughputService.class.getName()));
315         mActivity = (SimpleReaderActivity) instrumentation.startActivitySync(intent);
316     }
317 
318     /** Open simple reader activity for tap test */
319     @Rpc(description = "Open simple reader activity for tap test")
startTapTestReaderActivity()320     public void startTapTestReaderActivity() {
321         Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
322         Intent intent =
323                 buildReaderIntentWithApduSequence(
324                         instrumentation,
325                         HceUtils.COMMAND_APDUS_BY_SERVICE.get(TransportService1.class.getName()),
326                         HceUtils.RESPONSE_APDUS_BY_SERVICE.get(TransportService1.class.getName()));
327         mActivity = (SimpleReaderActivity) instrumentation.startActivitySync(intent);
328     }
329 
330     /** Open simple reader activity for large num AIDs test */
331     @Rpc(description = "Open simple reader activity for large num AIDs Test")
startLargeNumAidsReaderActivity()332     public void startLargeNumAidsReaderActivity() {
333         Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
334         Intent intent =
335                 buildReaderIntentWithApduSequence(
336                         instrumentation,
337                         HceUtils.COMMAND_APDUS_BY_SERVICE.get(LargeNumAidsService.class.getName()),
338                         HceUtils.RESPONSE_APDUS_BY_SERVICE.get(
339                                 LargeNumAidsService.class.getName()));
340         mActivity = (SimpleReaderActivity) instrumentation.startActivitySync(intent);
341     }
342 
343     /** Open simple reader activity for screen off payment test */
344     @Rpc(description = "Open simple reader activity for screen off payment Test")
startScreenOffPaymentReaderActivity()345     public void startScreenOffPaymentReaderActivity() {
346         Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
347         Intent intent =
348                 buildReaderIntentWithApduSequence(
349                         instrumentation,
350                         HceUtils.COMMAND_APDUS_BY_SERVICE.get(
351                                 ScreenOffPaymentService.class.getName()),
352                         HceUtils.RESPONSE_APDUS_BY_SERVICE.get(
353                                 ScreenOffPaymentService.class.getName()));
354         mActivity = (SimpleReaderActivity) instrumentation.startActivitySync(intent);
355     }
356 
357     /** Open protocol params reader activity */
358     @Rpc(description = "Open protocol params reader activity")
startProtocolParamsReaderActivity()359     public void startProtocolParamsReaderActivity() {
360         Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
361         Intent intent = new Intent(Intent.ACTION_MAIN);
362         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
363         intent.setClassName(
364                 instrumentation.getTargetContext(), ProtocolParamsReaderActivity.class.getName());
365         mActivity = (ProtocolParamsReaderActivity) instrumentation.startActivitySync(intent);
366     }
367 
368     /** Open simple reader activity for conflicting non-payment test */
369     @Rpc(description = "Open simple reader activity for conflicting non-payment Test")
startConflictingNonPaymentReaderActivity()370     public void startConflictingNonPaymentReaderActivity() {
371         Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
372         Intent intent =
373                 buildReaderIntentWithApduSequence(
374                         instrumentation,
375                         HceUtils.COMMAND_APDUS_BY_SERVICE.get(TransportService2.class.getName()),
376                         HceUtils.RESPONSE_APDUS_BY_SERVICE.get(TransportService2.class.getName()));
377         mActivity = (SimpleReaderActivity) instrumentation.startActivitySync(intent);
378     }
379 
380     /** Open simple reader activity for conflicting non-payment prefix test */
381     @Rpc(description = "Open simple reader activity for conflicting non-payment prefix Test")
startConflictingNonPaymentPrefixReaderActivity()382     public void startConflictingNonPaymentPrefixReaderActivity() {
383         Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
384         Intent intent =
385                 buildReaderIntentWithApduSequence(
386                         instrumentation,
387                         HceUtils.COMMAND_APDUS_BY_SERVICE.get(
388                                 PrefixTransportService2.class.getName()),
389                         HceUtils.RESPONSE_APDUS_BY_SERVICE.get(
390                                 PrefixTransportService2.class.getName()));
391         mActivity = (SimpleReaderActivity) instrumentation.startActivitySync(intent);
392     }
393 
394     /** Open simple reader activity for screen on only off-host service test */
395     @Rpc(description = "Open simple reader activity for screen on only off-host service Test")
startScreenOnOnlyOffHostReaderActivity()396     public void startScreenOnOnlyOffHostReaderActivity() {
397         Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
398         Intent intent =
399                 buildReaderIntentWithApduSequence(
400                         instrumentation,
401                         HceUtils.COMMAND_APDUS_BY_SERVICE.get(
402                                 ScreenOnOnlyOffHostService.class.getName()),
403                         HceUtils.RESPONSE_APDUS_BY_SERVICE.get(
404                                 ScreenOnOnlyOffHostService.class.getName()
405                         ));
406         mActivity = (SimpleReaderActivity) instrumentation.startActivitySync(intent);
407     }
408 
409     /** Registers receiver for Test Pass event */
410     @AsyncRpc(description = "Waits for Test Pass event")
asyncWaitForTestPass(String callbackId, String eventName)411     public void asyncWaitForTestPass(String callbackId, String eventName) {
412         registerSnippetBroadcastReceiver(
413                 callbackId, eventName, BaseReaderActivity.ACTION_TEST_PASSED);
414     }
415 
416     /** Sets the poll tech for the active reader activity */
417     @Rpc(description = "Set the listen tech for the emulator")
setPollTech(Integer pollTech)418     public void setPollTech(Integer pollTech) {
419         if (mActivity == null) {
420             Log.e(TAG, "Activity is null.");
421             return;
422         }
423         mActivity.setPollTech(pollTech);
424     }
425 
426     /** Resets the poll tech for the active reader activity */
427     @Rpc(description = "Reset the listen tech for the emulator")
resetPollTech()428     public void resetPollTech() {
429         if (mActivity == null) {
430             Log.e(TAG, "Activity is null.");
431             return;
432         }
433         mActivity.resetPollTech();
434     }
435 
436     /** Closes reader activity between tests */
437     @Rpc(description = "Close activity if one was opened.")
closeActivity()438     public void closeActivity() {
439         if (mActivity != null) {
440             mActivity.finish();
441         }
442     }
443 
buildReaderIntentWithApduSequence( Instrumentation instrumentation, CommandApdu[] commandApdus, String[] responseApdus)444     private Intent buildReaderIntentWithApduSequence(
445             Instrumentation instrumentation, CommandApdu[] commandApdus, String[] responseApdus) {
446         Intent intent = new Intent(Intent.ACTION_MAIN);
447         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
448         intent.setClassName(
449                 instrumentation.getTargetContext(), SimpleReaderActivity.class.getName());
450         intent.putExtra(SimpleReaderActivity.EXTRA_APDUS, commandApdus);
451         intent.putExtra(SimpleReaderActivity.EXTRA_RESPONSES, responseApdus);
452         return intent;
453     }
454 }
455