1 package com.android.cts.verifier.nfc.hce; 2 3 import android.annotation.TargetApi; 4 import android.app.AlertDialog; 5 import android.content.Intent; 6 import android.content.SharedPreferences; 7 import android.nfc.NfcAdapter; 8 import android.nfc.NfcAdapter.ReaderCallback; 9 import android.nfc.tech.IsoDep; 10 import android.nfc.Tag; 11 import android.os.Bundle; 12 import android.os.Parcelable; 13 import android.util.Log; 14 import android.view.View; 15 import android.widget.AdapterView; 16 import android.widget.AdapterView.OnItemSelectedListener; 17 import android.widget.ArrayAdapter; 18 import android.widget.Spinner; 19 import android.widget.TextView; 20 21 import com.android.cts.verifier.PassFailButtons; 22 import com.android.cts.verifier.R; 23 24 import java.io.IOException; 25 import java.util.Arrays; 26 27 @TargetApi(19) 28 public class SimpleReaderActivity extends PassFailButtons.Activity implements ReaderCallback, 29 OnItemSelectedListener { 30 public static final String PREFS_NAME = "HceTypePrefs"; 31 32 public static final String TAG = "SimpleReaderActivity"; 33 public static final String EXTRA_APDUS = "apdus"; 34 public static final String EXTRA_RESPONSES = "responses"; 35 public static final String EXTRA_LABEL = "label"; 36 37 NfcAdapter mAdapter; 38 CommandApdu[] mApdus; 39 String[] mResponses; 40 41 TextView mTextView; 42 Spinner mSpinner; 43 SharedPreferences mPrefs; 44 45 @Override 46 protected void onCreate(Bundle savedInstanceState) { 47 super.onCreate(savedInstanceState); 48 setContentView(R.layout.nfc_hce_reader); 49 setPassFailButtonClickListeners(); 50 getPassButton().setEnabled(false); 51 52 String label = getIntent().getStringExtra(EXTRA_LABEL); 53 setTitle(label); 54 55 mAdapter = NfcAdapter.getDefaultAdapter(this); 56 mTextView = (TextView) findViewById(R.id.text); 57 mTextView.setTextSize(12.0f); 58 mTextView.setText(R.string.nfc_hce_type_selection); 59 60 Spinner spinner = (Spinner) findViewById(R.id.type_ab_selection); 61 ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this, 62 R.array.nfc_types_array, android.R.layout.simple_spinner_item); 63 adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); 64 spinner.setAdapter(adapter); 65 spinner.setOnItemSelectedListener(this); 66 67 mPrefs = getSharedPreferences(PREFS_NAME, 0); 68 boolean isTypeB = mPrefs.getBoolean("typeB", false); 69 if (isTypeB) { 70 spinner.setSelection(1); 71 } 72 } 73 74 @Override 75 protected void onResume() { 76 super.onResume(); 77 mAdapter.enableReaderMode(this, this, NfcAdapter.FLAG_READER_NFC_A | 78 NfcAdapter.FLAG_READER_NFC_BARCODE | NfcAdapter.FLAG_READER_SKIP_NDEF_CHECK, null); 79 Intent intent = getIntent(); 80 Parcelable[] apdus = intent.getParcelableArrayExtra(EXTRA_APDUS); 81 if (apdus != null) { 82 mApdus = new CommandApdu[apdus.length]; 83 for (int i = 0; i < apdus.length; i++) { 84 mApdus[i] = (CommandApdu) apdus[i]; 85 } 86 } else { 87 mApdus = null; 88 } 89 mResponses = intent.getStringArrayExtra(EXTRA_RESPONSES); 90 } 91 92 @Override 93 public void onTagDiscovered(Tag tag) { 94 final StringBuilder sb = new StringBuilder(); 95 IsoDep isoDep = IsoDep.get(tag); 96 if (isoDep == null) { 97 // TODO dialog box 98 return; 99 } 100 101 try { 102 isoDep.connect(); 103 isoDep.setTimeout(5000); 104 int count = 0; 105 boolean success = true; 106 long startTime = System.currentTimeMillis(); 107 for (CommandApdu apdu: mApdus) { 108 sb.append("Request APDU:\n"); 109 sb.append(apdu.getApdu() + "\n\n"); 110 long apduStartTime = System.currentTimeMillis(); 111 byte[] response = isoDep.transceive(HceUtils.hexStringToBytes(apdu.getApdu())); 112 long apduEndTime = System.currentTimeMillis(); 113 sb.append("Response APDU (in " + Long.toString(apduEndTime - apduStartTime) + 114 " ms):\n"); 115 sb.append(HceUtils.getHexBytes(null, response)); 116 117 sb.append("\n\n\n"); 118 boolean wildCard = "*".equals(mResponses[count]); 119 byte[] expectedResponse = HceUtils.hexStringToBytes(mResponses[count]); 120 Log.d(TAG, HceUtils.getHexBytes("APDU response: ", response)); 121 if (!wildCard && !Arrays.equals(response, expectedResponse)) { 122 Log.d(TAG, "Unexpected APDU response: " + HceUtils.getHexBytes("", response)); 123 success = false; 124 break; 125 } 126 count++; 127 } 128 if (success) { 129 sb.insert(0, "Total APDU exchange time: " + 130 Long.toString(System.currentTimeMillis() - startTime) + " ms.\n\n"); 131 runOnUiThread(new Runnable() { 132 @Override 133 public void run() { 134 mTextView.setText(sb.toString()); 135 getPassButton().setEnabled(true); 136 } 137 }); 138 } else { 139 sb.insert(0, "FAIL. Total APDU exchange time: " + 140 Long.toString(System.currentTimeMillis() - startTime) + " ms.\n\n"); 141 runOnUiThread(new Runnable() { 142 @Override 143 public void run() { 144 mTextView.setText(sb.toString()); 145 AlertDialog.Builder builder = new AlertDialog.Builder(SimpleReaderActivity.this); 146 builder.setTitle("Test failed"); 147 builder.setMessage("An unexpected response APDU was received, or no APDUs were received at all."); 148 builder.setPositiveButton("OK", null); 149 builder.show(); 150 } 151 }); 152 } 153 } catch (IOException e) { 154 sb.insert(0, "Test failed. IOException (did you keep the devices in range?)\n\n."); 155 runOnUiThread(new Runnable() { 156 @Override 157 public void run() { 158 mTextView.setText(sb.toString()); 159 } 160 }); 161 } finally { 162 } 163 } 164 165 @Override 166 public void onItemSelected(AdapterView<?> parent, View view, int position, 167 long id) { 168 if (position == 0) { 169 // Type-A 170 mAdapter.disableReaderMode(this); 171 mAdapter.enableReaderMode(this, this, NfcAdapter.FLAG_READER_NFC_A | 172 NfcAdapter.FLAG_READER_NFC_BARCODE | NfcAdapter.FLAG_READER_SKIP_NDEF_CHECK, null); 173 SharedPreferences.Editor editor = mPrefs.edit(); 174 editor.putBoolean("typeB", false); 175 editor.commit(); 176 } else { 177 // Type-B 178 mAdapter.disableReaderMode(this); 179 mAdapter.enableReaderMode(this, this, NfcAdapter.FLAG_READER_NFC_B | 180 NfcAdapter.FLAG_READER_SKIP_NDEF_CHECK, null); 181 SharedPreferences.Editor editor = mPrefs.edit(); 182 editor.putBoolean("typeB", true); 183 editor.commit(); 184 } 185 } 186 187 @Override 188 public void onNothingSelected(AdapterView<?> parent) { 189 } 190 } 191