• 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