Home | History | Annotate | Download | only in hce
      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