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