1 package com.android.cts.verifier.nfc.hce; 2 3 import android.annotation.TargetApi; 4 import android.content.ComponentName; 5 import android.content.Intent; 6 import android.nfc.cardemulation.HostApduService; 7 import android.os.Bundle; 8 import android.util.Log; 9 10 import java.util.Arrays; 11 12 @TargetApi(19) 13 public abstract class HceService extends HostApduService { 14 final static String TAG = "HceService"; 15 16 final static int STATE_IDLE = 0; 17 final static int STATE_IN_PROGRESS = 1; 18 final static int STATE_FAILED = 2; 19 20 // Variables below only used on main thread 21 CommandApdu[] mCommandApdus = null; 22 String[] mResponseApdus = null; 23 int mApduIndex = 0; 24 int mState = STATE_IDLE; 25 long mStartTime; 26 27 public void initialize(CommandApdu[] commandApdus, String[] responseApdus) { 28 mCommandApdus = commandApdus; 29 mResponseApdus = responseApdus; 30 } 31 32 @Override 33 public void onDeactivated(int arg0) { 34 mApduIndex = 0; 35 mState = STATE_IDLE; 36 } 37 38 public abstract ComponentName getComponent(); 39 40 public void onApduSequenceComplete() { 41 Intent completionIntent = new Intent(HceUtils.ACTION_APDU_SEQUENCE_COMPLETE); 42 completionIntent.putExtra(HceUtils.EXTRA_COMPONENT, getComponent()); 43 completionIntent.putExtra(HceUtils.EXTRA_DURATION, 44 System.currentTimeMillis() - mStartTime); 45 sendBroadcast(completionIntent); 46 } 47 48 public void onApduSequenceError() { 49 Intent errorIntent = new Intent(HceUtils.ACTION_APDU_SEQUENCE_ERROR); 50 sendBroadcast(errorIntent); 51 } 52 53 @Override 54 public byte[] processCommandApdu(byte[] arg0, Bundle arg1) { 55 if (mState == STATE_FAILED) { 56 // Don't accept any more APDUs until deactivated 57 return null; 58 } 59 60 if (mState == STATE_IDLE) { 61 mState = STATE_IN_PROGRESS; 62 mStartTime = System.currentTimeMillis(); 63 } 64 65 66 if (mApduIndex >= mCommandApdus.length) { 67 // Skip all APDUs which aren't supposed to reach us 68 return null; 69 } 70 71 do { 72 if (!mCommandApdus[mApduIndex].isReachable()) { 73 mApduIndex++; 74 } else { 75 break; 76 } 77 } while (mApduIndex < mCommandApdus.length); 78 79 if (mApduIndex >= mCommandApdus.length) { 80 Log.d(TAG, "Ignoring command APDU; protocol complete."); 81 // Ignore new APDUs after completion 82 return null; 83 } else { 84 85 if (!Arrays.equals(HceUtils.hexStringToBytes(mCommandApdus[mApduIndex].getApdu()), arg0)) { 86 Log.d(TAG, "Unexpected command APDU: " + HceUtils.getHexBytes("", arg0)); 87 onApduSequenceError(); 88 return null; 89 } else { 90 // Send corresponding response APDU 91 byte[] responseApdu = HceUtils.hexStringToBytes(mResponseApdus[mApduIndex]); 92 mApduIndex++; 93 if (mApduIndex == mCommandApdus.length) { 94 // Test passed 95 onApduSequenceComplete(); 96 } 97 return responseApdu; 98 } 99 } 100 } 101 } 102