1 /*
2  * Copyright (C) 2016 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.cts.verifier.nfc.hcef;
17 
18 import android.annotation.TargetApi;
19 import android.nfc.NfcAdapter;
20 import android.nfc.NfcAdapter.ReaderCallback;
21 import android.nfc.Tag;
22 import android.nfc.tech.NfcF;
23 import android.os.Bundle;
24 import android.util.Log;
25 import android.view.View;
26 import android.widget.AdapterView;
27 import android.widget.AdapterView.OnItemSelectedListener;
28 
29 import com.android.cts.verifier.PassFailButtons;
30 import com.android.cts.verifier.R;
31 
32 import java.io.IOException;
33 
34 @TargetApi(24)
35 public class HceFReaderActivity extends PassFailButtons.Activity implements ReaderCallback,
36         OnItemSelectedListener {
37     public static final String TAG = "HceFReaderActivity";
38 
39     NfcAdapter mAdapter;
40 
41     @Override
onCreate(Bundle savedInstanceState)42     protected void onCreate(Bundle savedInstanceState) {
43         super.onCreate(savedInstanceState);
44         setContentView(R.layout.pass_fail_text);
45         setPassFailButtonClickListeners();
46         getPassButton().setEnabled(false);
47 
48         mAdapter = NfcAdapter.getDefaultAdapter(this);
49     }
50 
51     @Override
onResume()52     protected void onResume() {
53         super.onResume();
54         mAdapter.enableReaderMode(this, this, NfcAdapter.FLAG_READER_NFC_F |
55                 NfcAdapter.FLAG_READER_SKIP_NDEF_CHECK, null);
56     }
57 
createEchoCommand(byte[] nfcid2, byte[] payload)58     static byte[] createEchoCommand(byte[] nfcid2, byte[] payload) {
59         byte length = (byte) (2 + nfcid2.length + payload.length);
60 
61         byte[] echo_cmd = new byte[length];
62         echo_cmd[0] = length;
63         echo_cmd[1] = MyHostFelicaService.CMD_ECHO;
64         System.arraycopy(nfcid2, 0, echo_cmd, 2, nfcid2.length);
65         System.arraycopy(payload, 0, echo_cmd, 2 + nfcid2.length, payload.length);
66         return echo_cmd;
67     }
68 
createSuccessCommand(byte[] nfcid2)69     static byte[] createSuccessCommand(byte[] nfcid2) {
70         byte[] cmd = new byte[2 + nfcid2.length];
71         cmd[0] = (byte) (2 + nfcid2.length);
72         cmd[1] = MyHostFelicaService.CMD_SUCCESS;
73         System.arraycopy(nfcid2, 0, cmd, 2, nfcid2.length);
74         return cmd;
75     }
76 
verifyResponse(byte[] cmd, byte[] resp)77     static boolean verifyResponse(byte[] cmd, byte[] resp) {
78         if (resp == null) return false;
79 
80         // Verify length
81         if (resp[0] != resp.length) return false;
82         if (resp.length != cmd.length) return false;
83         // Verify cmd
84         if (resp[1] != MyHostFelicaService.RESPONSE_ECHO) return false;
85 
86         // Verify rest of data
87         for (int i = 2; i < resp.length; i++) {
88             if (resp[i] != cmd[i]) return false;
89         }
90 
91         return true;
92     }
93 
94     @Override
onTagDiscovered(Tag tag)95     public void onTagDiscovered(Tag tag) {
96         NfcF felica = NfcF.get(tag);
97         if (felica == null) return;
98 
99         try {
100             felica.connect();
101 	    byte[] command =
102 		    new byte[]{6, 0x00, (byte)0x40, (byte)0x01, 0x00, 0x00}; // in this case, SC of HCE-F is 4001h
103 	    felica.transceive(command);
104             for (int i = 0; i < 32; i++) {
105                 byte[] payload = new byte[] {0x14, (byte)i};
106                 byte[] echo_cmd = createEchoCommand(MyHostFelicaService.NFCID2, payload);
107                 byte[] resp = felica.transceive(echo_cmd);
108                 if (!verifyResponse(echo_cmd, resp)) {
109                     Log.e(TAG, "Echo response not correct.");
110                     return;
111                 }
112             }
113             // All successful, send success cmd
114             byte[] success_cmd = createSuccessCommand(MyHostFelicaService.NFCID2);
115             felica.transceive(success_cmd);
116 
117             runOnUiThread(new Runnable() {
118                 @Override
119                 public void run() {
120                     getPassButton().setEnabled(true);
121                 }
122             });
123         } catch (IOException e) {
124             Log.e(TAG, "IOException, try again.");
125         }
126     }
127 
128     @Override
onItemSelected(AdapterView<?> parent, View view, int position, long id)129     public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
130 
131     }
132 
133     @Override
onNothingSelected(AdapterView<?> parent)134     public void onNothingSelected(AdapterView<?> parent) {
135 
136     }
137 }
138