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