public void process(APDU apdu) {

    byte[] buffer = apdu.getBuffer();

    if (apdu.isISOInterindustryCLA()) {
      if (buffer[ISO7816.OFFSET_INS] == (byte) (0xA4)) {
        return;
      } else {
        ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED);
      }
    }

    switch (buffer[ISO7816.OFFSET_INS]) {
      case VALIDATEKEY:
        validateKey(apdu);
        return;
      case TIMETICK:
        timeTick(apdu);
        return;
      case SETCONNECTION:
        setConnection();
        return;
      case RESETCONNECTION:
        resetConnection();
        return;
      default:
        ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
    }
  }
  // Connection management methods
  private void timeTick(APDU apdu) {
    // Updates the area code according to the passed parameter.
    byte[] buffer = apdu.getBuffer();
    byte numBytes = (byte) (buffer[ISO7816.OFFSET_LC]);
    byte byteRead = (byte) (apdu.setIncomingAndReceive());

    if ((numBytes != 2) || (byteRead != 2)) ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);

    // get area code
    short newAreaCode =
        (short)
            ((short) (buffer[ISO7816.OFFSET_CDATA] << (short) 8)
                | (short) (buffer[ISO7816.OFFSET_CDATA + 1] & 0x00FF));

    if (newAreaCode != INACTIVE_AREA) {
      activeAreaCode[0] = newAreaCode;
    } else {
      resetConnection();
      ISOException.throwIt(SW_NO_NETWORK);
    }

    short connectionType = apdu.getProtocol();
    byte b = apdu.getCLAChannel();
    boolean contactless = false;
    if ((connectionType & 0xf0) == 0x80 // APDU.PROTOCOL_MEDIA_CONTACTLESS_TYPE_A
        || (connectionType & 0xf0) == 0x90) { // APDU.PROTOCOL_MEDIA_CONTACTLESS_TYPE_B ){
      contactless = true;
    }

    // If a connection is active, the user account is debited.
    // If user runs out of credits, the connection is terminated.
    if (connectionStatus[0] == CONNECTION_INUSE) {

      if (AccountAccessor.getAccount() == null) {
        ISOException.throwIt(SW_NO_ACCOUNT);
      }

      if (AccountAccessor.getAccount().debit(activeAreaCode[0], contactless) == false) {
        resetConnection();
        ISOException.throwIt(SW_NEGATIVE_BALANCE);
      }
    }
  }
  private void setConnection() {

    if (AccountAccessor.getAccount() == null) {
      ISOException.throwIt(SW_NO_ACCOUNT);
    }

    if (connectionStatus[0] == CONNECTION_INUSE) {
      ISOException.throwIt(SW_CONNECTION_BUSY);
    }

    if (activeAreaCode[0] == INACTIVE_AREA) {
      ISOException.throwIt(SW_NO_NETWORK);
    }

    // The first time unit is charged at connection setup
    if (AccountAccessor.getAccount().debit(activeAreaCode[0], false)) {
      connectionStatus[0] = CONNECTION_INUSE;
    } else {
      ISOException.throwIt(SW_NEGATIVE_BALANCE);
    }
  }
 // Check that the key sent is valid
 private void validateKey(APDU apdu) {
   // fake key test
   byte[] buffer = apdu.getBuffer();
   // process extended length apdu
   short testKey =
       (short)
           ((short) (buffer[ISO7816.OFFSET_EXT_CDATA] << (short) 8)
               | (short) (buffer[ISO7816.OFFSET_EXT_CDATA + 3] & 0x00FF));
   if (testKey != (short) 3) ISOException.throwIt(SW_INVALID_KEY);
   return;
   // System.out.println("here here");
 }