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     String[] mCommandApdus = null;
     22     String[] mResponseApdus = null;
     23     int mApduIndex = 0;
     24     int mState = STATE_IDLE;
     25     long mStartTime;
     26 
     27     public void initialize(String[] 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         if (mApduIndex >= mCommandApdus.length) {
     66             Log.d(TAG, "Ignoring command APDU; protocol complete.");
     67             // Ignore new APDUs after completion
     68             return null;
     69         } else {
     70             if (!Arrays.equals(HceUtils.hexStringToBytes(mCommandApdus[mApduIndex]), arg0)) {
     71                 Log.d(TAG, "Unexpected command APDU: " + HceUtils.getHexBytes("", arg0));
     72                 onApduSequenceError();
     73                 return null;
     74             } else {
     75                 // Send corresponding response APDU
     76                 byte[] responseApdu = HceUtils.hexStringToBytes(mResponseApdus[mApduIndex]);
     77                 mApduIndex++;
     78                 if (mApduIndex == mCommandApdus.length) {
     79                     // Test passed
     80                     onApduSequenceComplete();
     81                 }
     82                 return responseApdu;
     83             }
     84         }
     85     }
     86 }
     87