Home | History | Annotate | Download | only in sap
      1 package com.android.bluetooth.sap;
      2 
      3 import android.hardware.radio.V1_0.ISap;
      4 import android.hardware.radio.V1_0.SapApduType;
      5 import android.hardware.radio.V1_0.SapTransferProtocol;
      6 import android.os.RemoteException;
      7 import android.util.Log;
      8 
      9 import com.google.protobuf.micro.CodedOutputStreamMicro;
     10 import com.google.protobuf.micro.InvalidProtocolBufferMicroException;
     11 
     12 import org.android.btsap.SapApi;
     13 import org.android.btsap.SapApi.MsgHeader;
     14 import org.android.btsap.SapApi.RIL_SIM_SAP_APDU_RSP;
     15 import org.android.btsap.SapApi.RIL_SIM_SAP_CONNECT_RSP;
     16 import org.android.btsap.SapApi.RIL_SIM_SAP_DISCONNECT_IND;
     17 import org.android.btsap.SapApi.RIL_SIM_SAP_POWER_RSP;
     18 import org.android.btsap.SapApi.RIL_SIM_SAP_RESET_SIM_RSP;
     19 import org.android.btsap.SapApi.RIL_SIM_SAP_SET_TRANSFER_PROTOCOL_RSP;
     20 import org.android.btsap.SapApi.RIL_SIM_SAP_STATUS_IND;
     21 import org.android.btsap.SapApi.RIL_SIM_SAP_TRANSFER_ATR_RSP;
     22 import org.android.btsap.SapApi.RIL_SIM_SAP_TRANSFER_CARD_READER_STATUS_RSP;
     23 
     24 import java.io.IOException;
     25 import java.io.InputStream;
     26 import java.io.OutputStream;
     27 import java.util.ArrayList;
     28 import java.util.Hashtable;
     29 import java.util.Map;
     30 import java.util.concurrent.atomic.AtomicInteger;
     31 
     32 /**
     33  * SapMessage is used for incoming and outgoing messages.
     34  *
     35  * For incoming messages
     36  *
     37  */
     38 public class SapMessage {
     39 
     40     public static final String TAG = "SapMessage";
     41     public static final boolean DEBUG = SapService.DEBUG;
     42     public static final boolean VERBOSE = SapService.VERBOSE;
     43     public static final boolean TEST = false;
     44 
     45     /* Message IDs - SAP specification */
     46     public static final int ID_CONNECT_REQ = 0x00;
     47     public static final int ID_CONNECT_RESP = 0x01;
     48 
     49     public static final int ID_DISCONNECT_REQ = 0x02;
     50     public static final int ID_DISCONNECT_RESP = 0x03;
     51     public static final int ID_DISCONNECT_IND = 0x04;
     52 
     53     public static final int ID_TRANSFER_APDU_REQ = 0x05;
     54     public static final int ID_TRANSFER_APDU_RESP = 0x06;
     55 
     56     public static final int ID_TRANSFER_ATR_REQ = 0x07;
     57     public static final int ID_TRANSFER_ATR_RESP = 0x08;
     58 
     59     public static final int ID_POWER_SIM_OFF_REQ = 0x09;
     60     public static final int ID_POWER_SIM_OFF_RESP = 0x0A;
     61 
     62     public static final int ID_POWER_SIM_ON_REQ = 0x0B;
     63     public static final int ID_POWER_SIM_ON_RESP = 0x0C;
     64 
     65     public static final int ID_RESET_SIM_REQ = 0x0D;
     66     public static final int ID_RESET_SIM_RESP = 0x0E;
     67 
     68     public static final int ID_TRANSFER_CARD_READER_STATUS_REQ = 0x0F;
     69     public static final int ID_TRANSFER_CARD_READER_STATUS_RESP = 0x10;
     70 
     71     public static final int ID_STATUS_IND = 0x11;
     72     public static final int ID_ERROR_RESP = 0x12;
     73 
     74     public static final int ID_SET_TRANSPORT_PROTOCOL_REQ = 0x13;
     75     public static final int ID_SET_TRANSPORT_PROTOCOL_RESP = 0x14;
     76 
     77     /* Message IDs - RIL specific unsolicited */
     78     // First RIL message id
     79     public static final int ID_RIL_BASE = 0x100;
     80     // RIL_UNSOL_RIL_CONNECTED
     81     public static final int ID_RIL_UNSOL_CONNECTED = 0x100;
     82     // A disconnect ind from RIL will be converted after handled locally
     83     public static final int ID_RIL_UNSOL_DISCONNECT_IND = 0x102;
     84     // All others
     85     public static final int ID_RIL_UNKNOWN = 0x1ff;
     86 
     87     /* Message IDs - RIL specific solicited */
     88     public static final int ID_RIL_GET_SIM_STATUS_REQ = 0x200; // RIL_REQUEST_GET_SIM_STATUS
     89     /* Test signals used to set the reference ril in test mode */
     90     public static final int ID_RIL_SIM_ACCESS_TEST_REQ = 0x201; // RIL_REQUEST_SIM_ACCESS_TEST
     91     public static final int ID_RIL_SIM_ACCESS_TEST_RESP = 0x202; /* response for
     92                                                                     RIL_REQUEST_SIM_ACCESS_TEST */
     93 
     94     /* Parameter IDs and lengths */
     95     public static final int PARAM_MAX_MSG_SIZE_ID = 0x00;
     96     public static final int PARAM_MAX_MSG_SIZE_LENGTH = 2;
     97 
     98     public static final int PARAM_CONNECTION_STATUS_ID = 0x01;
     99     public static final int PARAM_CONNECTION_STATUS_LENGTH = 1;
    100 
    101     public static final int PARAM_RESULT_CODE_ID = 0x02;
    102     public static final int PARAM_RESULT_CODE_LENGTH = 1;
    103 
    104     public static final int PARAM_DISCONNECT_TYPE_ID = 0x03;
    105     public static final int PARAM_DISCONNECT_TYPE_LENGTH = 1;
    106 
    107     public static final int PARAM_COMMAND_APDU_ID = 0x04;
    108 
    109     public static final int PARAM_COMMAND_APDU7816_ID = 0x10;
    110 
    111     public static final int PARAM_RESPONSE_APDU_ID = 0x05;
    112 
    113     public static final int PARAM_ATR_ID = 0x06;
    114 
    115     public static final int PARAM_CARD_READER_STATUS_ID = 0x07;
    116     public static final int PARAM_CARD_READER_STATUS_LENGTH = 1;
    117 
    118     public static final int PARAM_STATUS_CHANGE_ID = 0x08;
    119     public static final int PARAM_STATUS_CHANGE_LENGTH = 1;
    120 
    121     public static final int PARAM_TRANSPORT_PROTOCOL_ID = 0x09;
    122     public static final int PARAM_TRANSPORT_PROTOCOL_LENGTH = 1;
    123 
    124     /* Result codes */
    125     public static final int RESULT_OK = 0x00;
    126     public static final int RESULT_ERROR_NO_REASON = 0x01;
    127     public static final int RESULT_ERROR_CARD_NOT_ACCESSIBLE = 0x02;
    128     public static final int RESULT_ERROR_CARD_POWERED_OFF = 0x03;
    129     public static final int RESULT_ERROR_CARD_REMOVED = 0x04;
    130     public static final int RESULT_ERROR_CARD_POWERED_ON = 0x05;
    131     public static final int RESULT_ERROR_DATA_NOT_AVAILABLE = 0x06;
    132     public static final int RESULT_ERROR_NOT_SUPPORTED = 0x07;
    133 
    134     /* Connection Status codes */
    135     public static final int CON_STATUS_OK = 0x00;
    136     public static final int CON_STATUS_ERROR_CONNECTION = 0x01;
    137     public static final int CON_STATUS_ERROR_MAX_MSG_SIZE_UNSUPPORTED = 0x02;
    138     public static final int CON_STATUS_ERROR_MAX_MSG_SIZE_TOO_SMALL = 0x03;
    139     public static final int CON_STATUS_OK_ONGOING_CALL = 0x04;
    140 
    141     /* Disconnection type */
    142     public static final int DISC_GRACEFULL = 0x00;
    143     public static final int DISC_IMMEDIATE = 0x01;
    144     public static final int DISC_FORCED = 0x100; // Used internal only
    145     public static final int DISC_RFCOMM = 0x101; // Used internal only
    146 
    147     /* Status Change */
    148     public static final int STATUS_UNKNOWN_ERROR = 0x00;
    149     public static final int STATUS_CARD_RESET = 0x01;
    150     public static final int STATUS_CARD_NOT_ACCESSIBLE = 0x02;
    151     public static final int STATUS_CARD_REMOVED = 0x03;
    152     public static final int STATUS_CARD_INSERTED = 0x04;
    153     public static final int STATUS_RECOVERED = 0x05;
    154 
    155     /* Transport Protocol */
    156     public static final int TRANS_PROTO_T0 = 0x00;
    157     public static final int TRANS_PROTO_T1 = 0x01;
    158 
    159     /* Test Mode */
    160     public static final int TEST_MODE_DISABLE = 0x00;
    161     public static final int TEST_MODE_ENABLE = 0x01;
    162 
    163     /* Used to detect uninitialized values */
    164     public static final int INVALID_VALUE = -1;
    165 
    166     /* Stuff related to communicating with rild-bt */
    167     static final int RESPONSE_SOLICITED = 0;
    168     static final int RESPONSE_UNSOLICITED = 1;
    169     static AtomicInteger sNextSerial = new AtomicInteger(1);
    170 
    171     // Map<rilSerial, RequestType> - HashTable is synchronized
    172     static Map<Integer, Integer> sOngoingRequests = new Hashtable<Integer, Integer>();
    173     private boolean mSendToRil = false; // set to true for messages that needs to go to the RIL
    174     private boolean mClearRilQueue = false; /* set to true for messages that needs to cause the
    175                                               sOngoingRequests to be cleared. */
    176 
    177     /* Instance members */
    178     private int mMsgType = INVALID_VALUE; // The SAP message ID
    179 
    180     private int mMaxMsgSize = INVALID_VALUE;
    181     private int mConnectionStatus = INVALID_VALUE;
    182     private int mResultCode = INVALID_VALUE;
    183     private int mDisconnectionType = INVALID_VALUE;
    184     private int mCardReaderStatus = INVALID_VALUE;
    185     private int mStatusChange = INVALID_VALUE;
    186     private int mTransportProtocol = INVALID_VALUE;
    187     private int mTestMode = INVALID_VALUE;
    188     private byte[] mApdu = null;
    189     private byte[] mApdu7816 = null;
    190     private byte[] mApduResp = null;
    191     private byte[] mAtr = null;
    192 
    193     /**
    194      * Create a SapMessage
    195      * @param msgType the SAP message type
    196      */
    197     public SapMessage(int msgType) {
    198         this.mMsgType = msgType;
    199     }
    200 
    201     private static void resetPendingRilMessages() {
    202         int numMessages = sOngoingRequests.size();
    203         if (numMessages != 0) {
    204             Log.w(TAG, "Clearing message queue with size: " + numMessages);
    205             sOngoingRequests.clear();
    206         }
    207     }
    208 
    209     public static int getNumPendingRilMessages() {
    210         return sOngoingRequests.size();
    211     }
    212 
    213     public int getMsgType() {
    214         return mMsgType;
    215     }
    216 
    217     public void setMsgType(int msgType) {
    218         this.mMsgType = msgType;
    219     }
    220 
    221     public int getMaxMsgSize() {
    222         return mMaxMsgSize;
    223     }
    224 
    225     public void setMaxMsgSize(int maxMsgSize) {
    226         this.mMaxMsgSize = maxMsgSize;
    227     }
    228 
    229     public int getConnectionStatus() {
    230         return mConnectionStatus;
    231     }
    232 
    233     public void setConnectionStatus(int connectionStatus) {
    234         this.mConnectionStatus = connectionStatus;
    235     }
    236 
    237     public int getResultCode() {
    238         return mResultCode;
    239     }
    240 
    241     public void setResultCode(int resultCode) {
    242         this.mResultCode = resultCode;
    243     }
    244 
    245     public int getDisconnectionType() {
    246         return mDisconnectionType;
    247     }
    248 
    249     public void setDisconnectionType(int disconnectionType) {
    250         this.mDisconnectionType = disconnectionType;
    251     }
    252 
    253     public int getCardReaderStatus() {
    254         return mCardReaderStatus;
    255     }
    256 
    257     public void setCardReaderStatus(int cardReaderStatus) {
    258         this.mCardReaderStatus = cardReaderStatus;
    259     }
    260 
    261     public int getStatusChange() {
    262         return mStatusChange;
    263     }
    264 
    265     public void setStatusChange(int statusChange) {
    266         this.mStatusChange = statusChange;
    267     }
    268 
    269     public int getTransportProtocol() {
    270         return mTransportProtocol;
    271     }
    272 
    273     public void setTransportProtocol(int transportProtocol) {
    274         this.mTransportProtocol = transportProtocol;
    275     }
    276 
    277     public byte[] getApdu() {
    278         return mApdu;
    279     }
    280 
    281     public void setApdu(byte[] apdu) {
    282         this.mApdu = apdu;
    283     }
    284 
    285     public byte[] getApdu7816() {
    286         return mApdu7816;
    287     }
    288 
    289     public void setApdu7816(byte[] apdu) {
    290         this.mApdu7816 = apdu;
    291     }
    292 
    293     public byte[] getApduResp() {
    294         return mApduResp;
    295     }
    296 
    297     public void setApduResp(byte[] apduResp) {
    298         this.mApduResp = apduResp;
    299     }
    300 
    301     public byte[] getAtr() {
    302         return mAtr;
    303     }
    304 
    305     public void setAtr(byte[] atr) {
    306         this.mAtr = atr;
    307     }
    308 
    309     public boolean getSendToRil() {
    310         return mSendToRil;
    311     }
    312 
    313     public void setSendToRil(boolean sendToRil) {
    314         this.mSendToRil = sendToRil;
    315     }
    316 
    317     public boolean getClearRilQueue() {
    318         return mClearRilQueue;
    319     }
    320 
    321     public void setClearRilQueue(boolean clearRilQueue) {
    322         this.mClearRilQueue = clearRilQueue;
    323     }
    324 
    325     public int getTestMode() {
    326         return mTestMode;
    327     }
    328 
    329     public void setTestMode(int testMode) {
    330         this.mTestMode = testMode;
    331     }
    332 
    333     private int getParamCount() {
    334         int paramCount = 0;
    335         if (mMaxMsgSize != INVALID_VALUE) {
    336             paramCount++;
    337         }
    338         if (mConnectionStatus != INVALID_VALUE) {
    339             paramCount++;
    340         }
    341         if (mResultCode != INVALID_VALUE) {
    342             paramCount++;
    343         }
    344         if (mDisconnectionType != INVALID_VALUE) {
    345             paramCount++;
    346         }
    347         if (mCardReaderStatus != INVALID_VALUE) {
    348             paramCount++;
    349         }
    350         if (mStatusChange != INVALID_VALUE) {
    351             paramCount++;
    352         }
    353         if (mTransportProtocol != INVALID_VALUE) {
    354             paramCount++;
    355         }
    356         if (mApdu != null) {
    357             paramCount++;
    358         }
    359         if (mApdu7816 != null) {
    360             paramCount++;
    361         }
    362         if (mApduResp != null) {
    363             paramCount++;
    364         }
    365         if (mAtr != null) {
    366             paramCount++;
    367         }
    368         return paramCount;
    369     }
    370 
    371     /**
    372      * Construct a SapMessage based on the incoming rfcomm request.
    373      * @param requestType The type of the request
    374      * @param is the input stream to read the data from
    375      * @return the resulting message, or null if an error occurs
    376      */
    377     @SuppressWarnings("unused")
    378     public static SapMessage readMessage(int requestType, InputStream is) {
    379         SapMessage newMessage = new SapMessage(requestType);
    380 
    381         /* Read in all the parameters (if any) */
    382         int paramCount;
    383         try {
    384             paramCount = is.read();
    385             skip(is, 2); // Skip the 2 padding bytes
    386             if (paramCount > 0) {
    387                 if (VERBOSE) {
    388                     Log.i(TAG, "Parsing message with paramCount: " + paramCount);
    389                 }
    390                 if (!newMessage.parseParameters(paramCount, is)) {
    391                     return null;
    392                 }
    393             }
    394         } catch (IOException e) {
    395             Log.w(TAG, e);
    396             return null;
    397         }
    398         if (DEBUG) {
    399             Log.i(TAG, "readMessage() Read message: " + getMsgTypeName(requestType));
    400         }
    401 
    402         /* Validate parameters */
    403         switch (requestType) {
    404             case ID_CONNECT_REQ:
    405                 if (newMessage.getMaxMsgSize() == INVALID_VALUE) {
    406                     Log.e(TAG, "Missing MaxMsgSize parameter in CONNECT_REQ");
    407                     return null;
    408                 }
    409                 break;
    410             case ID_TRANSFER_APDU_REQ:
    411                 if (newMessage.getApdu() == null && newMessage.getApdu7816() == null) {
    412                     Log.e(TAG, "Missing Apdu parameter in TRANSFER_APDU_REQ");
    413                     return null;
    414                 }
    415                 newMessage.setSendToRil(true);
    416                 break;
    417             case ID_SET_TRANSPORT_PROTOCOL_REQ:
    418                 if (newMessage.getTransportProtocol() == INVALID_VALUE) {
    419                     Log.e(TAG, "Missing TransportProtocol parameter in SET_TRANSPORT_PROTOCOL_REQ");
    420                     return null;
    421                 }
    422                 newMessage.setSendToRil(true);
    423                 break;
    424             case ID_TRANSFER_ATR_REQ:  /* No params */
    425             case ID_POWER_SIM_OFF_REQ: /* No params */
    426             case ID_POWER_SIM_ON_REQ:  /* No params */
    427             case ID_RESET_SIM_REQ:     /* No params */
    428             case ID_TRANSFER_CARD_READER_STATUS_REQ: /* No params */
    429                 newMessage.setSendToRil(true);
    430                 break;
    431             case ID_DISCONNECT_REQ:    /* No params */
    432                 break;
    433             default:
    434                 Log.e(TAG, "Unknown request type");
    435                 return null;
    436         }
    437         return newMessage;
    438     }
    439 
    440     /**
    441      * Blocking read of an entire array of data.
    442      * @param is the input stream to read from
    443      * @param buffer the buffer to read into - the length of the buffer will
    444      *        determine how many bytes will be read.
    445      */
    446     private static void read(InputStream is, byte[] buffer) throws IOException {
    447         int bytesToRead = buffer.length;
    448         int bytesRead = 0;
    449         int tmpBytesRead;
    450         while (bytesRead < bytesToRead) {
    451             tmpBytesRead = is.read(buffer, bytesRead, bytesToRead - bytesRead);
    452             if (tmpBytesRead == -1) {
    453                 throw new IOException("EOS reached while reading a byte array.");
    454             } else {
    455                 bytesRead += tmpBytesRead;
    456             }
    457         }
    458     }
    459 
    460     /**
    461      * Skip a number of bytes in an InputStream.
    462      * @param is the input stream
    463      * @param count the number of bytes to skip
    464      * @throws IOException In case of reaching EOF or a stream error
    465      */
    466     private static void skip(InputStream is, int count) throws IOException {
    467         for (int i = 0; i < count; i++) {
    468             is.read(); // Do not use the InputStream.skip as it fails for some stream types
    469         }
    470     }
    471 
    472     /**
    473      * Read the parameters from the stream and update the relevant members.
    474      * This function will ensure that all parameters are read from the stream, even
    475      * if an error is detected.
    476      * @param count the number of parameters to read
    477      * @param is the input stream
    478      * @return True if all parameters were successfully parsed, False if an error were detected.
    479      * @throws IOException
    480      */
    481     private boolean parseParameters(int count, InputStream is) throws IOException {
    482         int paramId;
    483         int paramLength;
    484         boolean success = true;
    485         int skipLen = 0;
    486 
    487         for (int i = 0; i < count; i++) {
    488             paramId = is.read();
    489             is.read(); // Skip the reserved byte
    490             paramLength = is.read();
    491             paramLength = paramLength << 8 | is.read();
    492 
    493             // As per SAP spec padding should be 0-3 bytes
    494             if ((paramLength % 4) != 0) {
    495                 skipLen = 4 - (paramLength % 4);
    496             }
    497 
    498             if (VERBOSE) {
    499                 Log.i(TAG, "parsing paramId: " + paramId + " with length: " + paramLength);
    500             }
    501             switch (paramId) {
    502                 case PARAM_MAX_MSG_SIZE_ID:
    503                     if (paramLength != PARAM_MAX_MSG_SIZE_LENGTH) {
    504                         Log.e(TAG, "Received PARAM_MAX_MSG_SIZE with wrong length: " + paramLength
    505                                 + " skipping this parameter.");
    506                         skip(is, paramLength + skipLen);
    507                         success = false;
    508                     } else {
    509                         mMaxMsgSize = is.read();
    510                         mMaxMsgSize = mMaxMsgSize << 8 | is.read();
    511                         skip(is, 4 - PARAM_MAX_MSG_SIZE_LENGTH);
    512                     }
    513                     break;
    514                 case PARAM_COMMAND_APDU_ID:
    515                     mApdu = new byte[paramLength];
    516                     read(is, mApdu);
    517                     skip(is, skipLen);
    518                     break;
    519                 case PARAM_COMMAND_APDU7816_ID:
    520                     mApdu7816 = new byte[paramLength];
    521                     read(is, mApdu7816);
    522                     skip(is, skipLen);
    523                     break;
    524                 case PARAM_TRANSPORT_PROTOCOL_ID:
    525                     if (paramLength != PARAM_TRANSPORT_PROTOCOL_LENGTH) {
    526                         Log.e(TAG, "Received PARAM_TRANSPORT_PROTOCOL with wrong length: "
    527                                 + paramLength + " skipping this parameter.");
    528                         skip(is, paramLength + skipLen);
    529                         success = false;
    530                     } else {
    531                         mTransportProtocol = is.read();
    532                         skip(is, 4 - PARAM_TRANSPORT_PROTOCOL_LENGTH);
    533                     }
    534                     break;
    535                 case PARAM_CONNECTION_STATUS_ID:
    536                     // not needed for server role, but used for module test
    537                     if (paramLength != PARAM_CONNECTION_STATUS_LENGTH) {
    538                         Log.e(TAG,
    539                                 "Received PARAM_CONNECTION_STATUS with wrong length: " + paramLength
    540                                         + " skipping this parameter.");
    541                         skip(is, paramLength + skipLen);
    542                         success = false;
    543                     } else {
    544                         mConnectionStatus = is.read();
    545                         skip(is, 4 - PARAM_CONNECTION_STATUS_LENGTH);
    546                     }
    547                     break;
    548                 case PARAM_CARD_READER_STATUS_ID:
    549                     // not needed for server role, but used for module test
    550                     if (paramLength != PARAM_CARD_READER_STATUS_LENGTH) {
    551                         Log.e(TAG, "Received PARAM_CARD_READER_STATUS with wrong length: "
    552                                 + paramLength + " skipping this parameter.");
    553                         skip(is, paramLength + skipLen);
    554                         success = false;
    555                     } else {
    556                         mCardReaderStatus = is.read();
    557                         skip(is, 4 - PARAM_CARD_READER_STATUS_LENGTH);
    558                     }
    559                     break;
    560                 case PARAM_STATUS_CHANGE_ID:
    561                     // not needed for server role, but used for module test
    562                     if (paramLength != PARAM_STATUS_CHANGE_LENGTH) {
    563                         Log.e(TAG, "Received PARAM_STATUS_CHANGE with wrong length: " + paramLength
    564                                 + " skipping this parameter.");
    565                         skip(is, paramLength + skipLen);
    566                         success = false;
    567                     } else {
    568                         mStatusChange = is.read();
    569                         skip(is, 4 - PARAM_STATUS_CHANGE_LENGTH);
    570                     }
    571                     break;
    572                 case PARAM_RESULT_CODE_ID:
    573                     // not needed for server role, but used for module test
    574                     if (paramLength != PARAM_RESULT_CODE_LENGTH) {
    575                         Log.e(TAG, "Received PARAM_RESULT_CODE with wrong length: " + paramLength
    576                                 + " skipping this parameter.");
    577                         skip(is, paramLength + skipLen);
    578                         success = false;
    579                     } else {
    580                         mResultCode = is.read();
    581                         skip(is, 4 - PARAM_RESULT_CODE_LENGTH);
    582                     }
    583                     break;
    584                 case PARAM_DISCONNECT_TYPE_ID:
    585                     // not needed for server role, but used for module test
    586                     if (paramLength != PARAM_DISCONNECT_TYPE_LENGTH) {
    587                         Log.e(TAG, "Received PARAM_DISCONNECT_TYPE_ID with wrong length: "
    588                                 + paramLength + " skipping this parameter.");
    589                         skip(is, paramLength + skipLen);
    590                         success = false;
    591                     } else {
    592                         mDisconnectionType = is.read();
    593                         skip(is, 4 - PARAM_DISCONNECT_TYPE_LENGTH);
    594                     }
    595                     break;
    596                 case PARAM_RESPONSE_APDU_ID:
    597                     // not needed for server role, but used for module test
    598                     mApduResp = new byte[paramLength];
    599                     read(is, mApduResp);
    600                     skip(is, skipLen);
    601                     break;
    602                 case PARAM_ATR_ID:
    603                     // not needed for server role, but used for module test
    604                     mAtr = new byte[paramLength];
    605                     read(is, mAtr);
    606                     skip(is, skipLen);
    607                     break;
    608                 default:
    609                     Log.e(TAG,
    610                             "Received unknown parameter ID: " + paramId + " length: " + paramLength
    611                                     + " skipping this parameter.");
    612                     skip(is, paramLength + skipLen);
    613             }
    614         }
    615         return success;
    616     }
    617 
    618     /**
    619      * Writes a single value parameter of 1 or 2 bytes in length.
    620      * @param os The BufferedOutputStream to write to.
    621      * @param id The Parameter ID
    622      * @param value The parameter value
    623      * @param length The length of the parameter value
    624      * @throws IOException if the write to os fails
    625      */
    626     private static void writeParameter(OutputStream os, int id, int value, int length)
    627             throws IOException {
    628 
    629         /* Parameter Header*/
    630         os.write(id);
    631         os.write(0);
    632         os.write(0);
    633         os.write(length);
    634 
    635         switch (length) {
    636             case 1:
    637                 os.write(value & 0xff);
    638                 os.write(0); // Padding
    639                 os.write(0); // Padding
    640                 os.write(0); // padding
    641                 break;
    642             case 2:
    643                 os.write((value >> 8) & 0xff);
    644                 os.write(value & 0xff);
    645                 os.write(0); // Padding
    646                 os.write(0); // padding
    647                 break;
    648             default:
    649                 throw new IOException("Unable to write value of length: " + length);
    650         }
    651     }
    652 
    653     /**
    654      * Writes a byte[] parameter of any length.
    655      * @param os The BufferedOutputStream to write to.
    656      * @param id The Parameter ID
    657      * @param value The byte array to write, the length will be extracted from the array.
    658      * @throws IOException if the write to os fails
    659      */
    660     private static void writeParameter(OutputStream os, int id, byte[] value) throws IOException {
    661 
    662         /* Parameter Header*/
    663         os.write(id);
    664         os.write(0); // reserved
    665         os.write((value.length >> 8) & 0xff);
    666         os.write(value.length & 0xff);
    667 
    668         /* Payload */
    669         os.write(value);
    670         if (value.length % 4 != 0) {
    671             for (int i = 0; i < (4 - (value.length % 4)); ++i) {
    672                 os.write(0); // Padding
    673             }
    674         }
    675     }
    676 
    677     public void write(OutputStream os) throws IOException {
    678         /* Write the header */
    679         os.write(mMsgType);
    680         os.write(getParamCount());
    681         os.write(0); // padding
    682         os.write(0); // padding
    683 
    684         /* write the parameters */
    685         if (mConnectionStatus != INVALID_VALUE) {
    686             writeParameter(os, PARAM_CONNECTION_STATUS_ID, mConnectionStatus,
    687                     PARAM_CONNECTION_STATUS_LENGTH);
    688         }
    689         if (mMaxMsgSize != INVALID_VALUE) {
    690             writeParameter(os, PARAM_MAX_MSG_SIZE_ID, mMaxMsgSize, PARAM_MAX_MSG_SIZE_LENGTH);
    691         }
    692         if (mResultCode != INVALID_VALUE) {
    693             writeParameter(os, PARAM_RESULT_CODE_ID, mResultCode, PARAM_RESULT_CODE_LENGTH);
    694         }
    695         if (mDisconnectionType != INVALID_VALUE) {
    696             writeParameter(os, PARAM_DISCONNECT_TYPE_ID, mDisconnectionType,
    697                     PARAM_DISCONNECT_TYPE_LENGTH);
    698         }
    699         if (mCardReaderStatus != INVALID_VALUE) {
    700             writeParameter(os, PARAM_CARD_READER_STATUS_ID, mCardReaderStatus,
    701                     PARAM_CARD_READER_STATUS_LENGTH);
    702         }
    703         if (mStatusChange != INVALID_VALUE) {
    704             writeParameter(os, PARAM_STATUS_CHANGE_ID, mStatusChange, PARAM_STATUS_CHANGE_LENGTH);
    705         }
    706         if (mTransportProtocol != INVALID_VALUE) {
    707             writeParameter(os, PARAM_TRANSPORT_PROTOCOL_ID, mTransportProtocol,
    708                     PARAM_TRANSPORT_PROTOCOL_LENGTH);
    709         }
    710         if (mApdu != null) {
    711             writeParameter(os, PARAM_COMMAND_APDU_ID, mApdu);
    712         }
    713         if (mApdu7816 != null) {
    714             writeParameter(os, PARAM_COMMAND_APDU7816_ID, mApdu7816);
    715         }
    716         if (mApduResp != null) {
    717             writeParameter(os, PARAM_RESPONSE_APDU_ID, mApduResp);
    718         }
    719         if (mAtr != null) {
    720             writeParameter(os, PARAM_ATR_ID, mAtr);
    721         }
    722     }
    723 
    724     /***************************************************************************
    725      * RILD Interface message conversion functions.
    726      ***************************************************************************/
    727 
    728     /**
    729      * We use this function to
    730      * @param length
    731      * @param rawOut
    732      * @throws IOException
    733      */
    734     private void writeLength(int length, CodedOutputStreamMicro out) throws IOException {
    735         byte[] dataLength = new byte[4];
    736         dataLength[0] = dataLength[1] = 0;
    737         dataLength[2] = (byte) ((length >> 8) & 0xff);
    738         dataLength[3] = (byte) ((length) & 0xff);
    739         out.writeRawBytes(dataLength);
    740     }
    741 
    742     private ArrayList<Byte> primitiveArrayToContainerArrayList(byte[] arr) {
    743         ArrayList<Byte> arrayList = new ArrayList<>(arr.length);
    744         for (byte b : arr) {
    745             arrayList.add(b);
    746         }
    747         return arrayList;
    748     }
    749 
    750     /**
    751      * Send the message by calling corresponding ISap api.
    752      */
    753     public void send(ISap sapProxy) throws RemoteException, RuntimeException {
    754         int rilSerial = sNextSerial.getAndIncrement();
    755 
    756         Log.e(TAG, "callISapReq: called for mMsgType " + mMsgType + " rilSerial " + rilSerial);
    757 
    758         /* Update the ongoing requests queue */
    759         if (mClearRilQueue) {
    760             resetPendingRilMessages();
    761         }
    762         // No need to synchronize this, as the HashList is already doing this.
    763         sOngoingRequests.put(rilSerial, mMsgType);
    764 
    765         switch (mMsgType) {
    766             case ID_CONNECT_REQ: {
    767                 sapProxy.connectReq(rilSerial, mMaxMsgSize);
    768                 break;
    769             }
    770             case ID_DISCONNECT_REQ: {
    771                 sapProxy.disconnectReq(rilSerial);
    772                 break;
    773             }
    774             case ID_TRANSFER_APDU_REQ: {
    775                 int type;
    776                 ArrayList<Byte> command;
    777                 if (mApdu != null) {
    778                     type = SapApduType.APDU;
    779                     command = primitiveArrayToContainerArrayList(mApdu);
    780                 } else if (mApdu7816 != null) {
    781                     type = SapApduType.APDU7816;
    782                     command = primitiveArrayToContainerArrayList(mApdu7816);
    783                 } else {
    784                     Log.e(TAG, "Missing Apdu parameter in TRANSFER_APDU_REQ");
    785                     throw new IllegalArgumentException();
    786                 }
    787                 sapProxy.apduReq(rilSerial, type, command);
    788                 break;
    789             }
    790             case ID_SET_TRANSPORT_PROTOCOL_REQ: {
    791                 int transportProtocol;
    792                 if (mTransportProtocol == TRANS_PROTO_T0) {
    793                     transportProtocol = SapTransferProtocol.T0;
    794                 } else if (mTransportProtocol == TRANS_PROTO_T1) {
    795                     transportProtocol = SapTransferProtocol.T1;
    796                 } else {
    797                     Log.e(TAG, "Missing or invalid TransportProtocol parameter in"
    798                             + " SET_TRANSPORT_PROTOCOL_REQ: " + mTransportProtocol);
    799                     throw new IllegalArgumentException();
    800                 }
    801                 sapProxy.setTransferProtocolReq(rilSerial, transportProtocol);
    802                 break;
    803             }
    804             case ID_TRANSFER_ATR_REQ: {
    805                 sapProxy.transferAtrReq(rilSerial);
    806                 break;
    807             }
    808             case ID_POWER_SIM_OFF_REQ: {
    809                 sapProxy.powerReq(rilSerial, false);
    810                 break;
    811             }
    812             case ID_POWER_SIM_ON_REQ: {
    813                 sapProxy.powerReq(rilSerial, true);
    814                 break;
    815             }
    816             case ID_RESET_SIM_REQ: {
    817                 sapProxy.resetSimReq(rilSerial);
    818                 break;
    819             }
    820             case ID_TRANSFER_CARD_READER_STATUS_REQ: {
    821                 sapProxy.transferCardReaderStatusReq(rilSerial);
    822                 break;
    823             }
    824             default:
    825                 Log.e(TAG, "Unknown request type");
    826                 throw new IllegalArgumentException();
    827         }
    828         if (VERBOSE) {
    829             Log.e(TAG, "callISapReq: done without exceptions");
    830         }
    831     }
    832 
    833     public static SapMessage newInstance(MsgHeader msg) throws IOException {
    834         return new SapMessage(msg);
    835     }
    836 
    837     private SapMessage(MsgHeader msg) throws IOException {
    838         // All header members are "required" hence the hasXxxx() is not needed for those
    839         try {
    840             switch (msg.getType()) {
    841                 case SapApi.UNSOL_RESPONSE:
    842                     createUnsolicited(msg);
    843                     break;
    844                 case SapApi.RESPONSE:
    845                     createSolicited(msg);
    846                     break;
    847                 default:
    848                     throw new IOException("Wrong msg header received: Type: " + msg.getType());
    849             }
    850         } catch (InvalidProtocolBufferMicroException e) {
    851             Log.w(TAG, "Error occured parsing a RIL message", e);
    852             throw new IOException("Error occured parsing a RIL message");
    853         }
    854     }
    855 
    856     private void createUnsolicited(MsgHeader msg)
    857             throws IOException, InvalidProtocolBufferMicroException {
    858         switch (msg.getId()) {
    859 // TODO:
    860 //        Not sure when we use these?        case RIL_UNSOL_RIL_CONNECTED:
    861 //            if(VERBOSE) Log.i(TAG, "RIL_UNSOL_RIL_CONNECTED received, ignoring");
    862 //            msgType = ID_RIL_UNSOL_CONNECTED;
    863 //            break;
    864             case SapApi.RIL_SIM_SAP_STATUS: {
    865                 if (VERBOSE) {
    866                     Log.i(TAG, "RIL_SIM_SAP_STATUS_IND received");
    867                 }
    868                 RIL_SIM_SAP_STATUS_IND indMsg =
    869                         RIL_SIM_SAP_STATUS_IND.parseFrom(msg.getPayload().toByteArray());
    870                 mMsgType = ID_STATUS_IND;
    871                 if (indMsg.hasStatusChange()) {
    872                     setStatusChange(indMsg.getStatusChange());
    873                     if (VERBOSE) {
    874                         Log.i(TAG,
    875                                 "RIL_UNSOL_SIM_SAP_STATUS_IND received value = " + mStatusChange);
    876                     }
    877                 } else {
    878                     if (VERBOSE) {
    879                         Log.i(TAG, "Wrong number of parameters in SAP_STATUS_IND, ignoring...");
    880                     }
    881                     mMsgType = ID_RIL_UNKNOWN;
    882                 }
    883                 break;
    884             }
    885             case SapApi.RIL_SIM_SAP_DISCONNECT: {
    886                 if (VERBOSE) {
    887                     Log.i(TAG, "RIL_SIM_SAP_DISCONNECT_IND received");
    888                 }
    889 
    890                 RIL_SIM_SAP_DISCONNECT_IND indMsg =
    891                         RIL_SIM_SAP_DISCONNECT_IND.parseFrom(msg.getPayload().toByteArray());
    892                 mMsgType = ID_RIL_UNSOL_DISCONNECT_IND; // don't use ID_DISCONNECT_IND;
    893                 if (indMsg.hasDisconnectType()) {
    894                     setDisconnectionType(indMsg.getDisconnectType());
    895                     if (VERBOSE) {
    896                         Log.i(TAG, "RIL_UNSOL_SIM_SAP_STATUS_IND received value = "
    897                                 + mDisconnectionType);
    898                     }
    899                 } else {
    900                     if (VERBOSE) {
    901                         Log.i(TAG, "Wrong number of parameters in SAP_STATUS_IND, ignoring...");
    902                     }
    903                     mMsgType = ID_RIL_UNKNOWN;
    904                 }
    905                 break;
    906             }
    907             default:
    908                 if (VERBOSE) {
    909                     Log.i(TAG, "Unused unsolicited message received, ignoring: " + msg.getId());
    910                 }
    911                 mMsgType = ID_RIL_UNKNOWN;
    912         }
    913     }
    914 
    915     private void createSolicited(MsgHeader msg)
    916             throws IOException, InvalidProtocolBufferMicroException {
    917         /* re-evaluate if we should just ignore these - we could simply catch the exception? */
    918         if (!msg.hasToken()) {
    919             throw new IOException("Token is missing");
    920         }
    921         if (!msg.hasError()) {
    922             throw new IOException("Error code is missing");
    923         }
    924         int serial = msg.getToken();
    925         int error = msg.getError();
    926         Integer reqType = null;
    927         reqType = sOngoingRequests.remove(serial);
    928         if (VERBOSE) {
    929             Log.i(TAG, "RIL SOLICITED serial: " + serial + ", error: " + error + " SapReqType: " + (
    930                     (reqType == null) ? "null" : getMsgTypeName(reqType)));
    931         }
    932 
    933         if (reqType == null) {
    934             /* This can happen if we get a resp. for a canceled request caused by a power off,
    935              *  reset or disconnect
    936              */
    937             Log.w(TAG, "Solicited response received on a command not initiated - ignoring.");
    938             return;
    939         }
    940         mResultCode = mapRilErrorCode(error);
    941 
    942         switch (reqType) {
    943             case ID_CONNECT_REQ: {
    944                 RIL_SIM_SAP_CONNECT_RSP resMsg =
    945                         RIL_SIM_SAP_CONNECT_RSP.parseFrom(msg.getPayload().toByteArray());
    946                 mMsgType = ID_CONNECT_RESP;
    947                 if (resMsg.hasMaxMessageSize()) {
    948                     mMaxMsgSize = resMsg.getMaxMessageSize();
    949 
    950                 }
    951                 switch (resMsg.getResponse()) {
    952                     case RIL_SIM_SAP_CONNECT_RSP.RIL_E_SUCCESS:
    953                         mConnectionStatus = CON_STATUS_OK;
    954                         break;
    955                     case RIL_SIM_SAP_CONNECT_RSP.RIL_E_SAP_CONNECT_OK_CALL_ONGOING:
    956                         mConnectionStatus = CON_STATUS_OK_ONGOING_CALL;
    957                         break;
    958                     case RIL_SIM_SAP_CONNECT_RSP.RIL_E_SAP_CONNECT_FAILURE:
    959                         mConnectionStatus = CON_STATUS_ERROR_CONNECTION;
    960                         break;
    961                     case RIL_SIM_SAP_CONNECT_RSP.RIL_E_SAP_MSG_SIZE_TOO_LARGE:
    962                         mConnectionStatus = CON_STATUS_ERROR_MAX_MSG_SIZE_UNSUPPORTED;
    963                         break;
    964                     case RIL_SIM_SAP_CONNECT_RSP.RIL_E_SAP_MSG_SIZE_TOO_SMALL:
    965                         mConnectionStatus = CON_STATUS_ERROR_MAX_MSG_SIZE_TOO_SMALL;
    966                         break;
    967                     default:
    968                         mConnectionStatus = CON_STATUS_ERROR_CONNECTION; // Cannot happen!
    969                         break;
    970                 }
    971                 mResultCode = INVALID_VALUE;
    972                 if (VERBOSE) {
    973                     Log.v(TAG, "  ID_CONNECT_REQ: mMaxMsgSize: " + mMaxMsgSize
    974                             + "  mConnectionStatus: " + mConnectionStatus);
    975                 }
    976                 break;
    977             }
    978             case ID_DISCONNECT_REQ:
    979                 mMsgType = ID_DISCONNECT_RESP;
    980                 mResultCode = INVALID_VALUE;
    981                 break;
    982             case ID_TRANSFER_APDU_REQ: {
    983                 RIL_SIM_SAP_APDU_RSP resMsg =
    984                         RIL_SIM_SAP_APDU_RSP.parseFrom(msg.getPayload().toByteArray());
    985                 mMsgType = ID_TRANSFER_APDU_RESP;
    986                 switch (resMsg.getResponse()) {
    987                     case RIL_SIM_SAP_APDU_RSP.RIL_E_SUCCESS:
    988                         mResultCode = RESULT_OK;
    989                 /* resMsg.getType is unused as the client knows the type of request used. */
    990                         if (resMsg.hasApduResponse()) {
    991                             mApduResp = resMsg.getApduResponse().toByteArray();
    992                         }
    993                         break;
    994                     case RIL_SIM_SAP_APDU_RSP.RIL_E_GENERIC_FAILURE:
    995                         mResultCode = RESULT_ERROR_NO_REASON;
    996                         break;
    997                     case RIL_SIM_SAP_APDU_RSP.RIL_E_SIM_ABSENT:
    998                         mResultCode = RESULT_ERROR_CARD_NOT_ACCESSIBLE;
    999                         break;
   1000                     case RIL_SIM_SAP_APDU_RSP.RIL_E_SIM_ALREADY_POWERED_OFF:
   1001                         mResultCode = RESULT_ERROR_CARD_POWERED_OFF;
   1002                         break;
   1003                     case RIL_SIM_SAP_APDU_RSP.RIL_E_SIM_NOT_READY:
   1004                         mResultCode = RESULT_ERROR_CARD_REMOVED;
   1005                         break;
   1006                     default:
   1007                         mResultCode = RESULT_ERROR_NO_REASON;
   1008                         break;
   1009                 }
   1010                 break;
   1011             }
   1012             case ID_SET_TRANSPORT_PROTOCOL_REQ: {
   1013                 RIL_SIM_SAP_SET_TRANSFER_PROTOCOL_RSP resMsg =
   1014                         RIL_SIM_SAP_SET_TRANSFER_PROTOCOL_RSP.parseFrom(
   1015                                 msg.getPayload().toByteArray());
   1016                 mMsgType = ID_SET_TRANSPORT_PROTOCOL_RESP;
   1017                 switch (resMsg.getResponse()) {
   1018                     case RIL_SIM_SAP_SET_TRANSFER_PROTOCOL_RSP.RIL_E_SUCCESS:
   1019                         mResultCode = RESULT_OK;
   1020                         break;
   1021                     case RIL_SIM_SAP_SET_TRANSFER_PROTOCOL_RSP.RIL_E_GENERIC_FAILURE:
   1022                         mResultCode = RESULT_ERROR_NOT_SUPPORTED;
   1023                         break;
   1024                     case RIL_SIM_SAP_SET_TRANSFER_PROTOCOL_RSP.RIL_E_SIM_ABSENT:
   1025                         mResultCode = RESULT_ERROR_CARD_NOT_ACCESSIBLE;
   1026                         break;
   1027                     case RIL_SIM_SAP_SET_TRANSFER_PROTOCOL_RSP.RIL_E_SIM_ALREADY_POWERED_OFF:
   1028                         mResultCode = RESULT_ERROR_CARD_POWERED_OFF;
   1029                         break;
   1030                     case RIL_SIM_SAP_SET_TRANSFER_PROTOCOL_RSP.RIL_E_SIM_NOT_READY:
   1031                         mResultCode = RESULT_ERROR_CARD_REMOVED;
   1032                         break;
   1033                     default:
   1034                         mResultCode = RESULT_ERROR_NOT_SUPPORTED;
   1035                         break;
   1036                 }
   1037                 break;
   1038             }
   1039             case ID_TRANSFER_ATR_REQ: {
   1040                 RIL_SIM_SAP_TRANSFER_ATR_RSP resMsg =
   1041                         RIL_SIM_SAP_TRANSFER_ATR_RSP.parseFrom(msg.getPayload().toByteArray());
   1042                 mMsgType = ID_TRANSFER_ATR_RESP;
   1043                 if (resMsg.hasAtr()) {
   1044                     mAtr = resMsg.getAtr().toByteArray();
   1045                 }
   1046                 switch (resMsg.getResponse()) {
   1047                     case RIL_SIM_SAP_TRANSFER_ATR_RSP.RIL_E_SUCCESS:
   1048                         mResultCode = RESULT_OK;
   1049                         break;
   1050                     case RIL_SIM_SAP_TRANSFER_ATR_RSP.RIL_E_GENERIC_FAILURE:
   1051                         mResultCode = RESULT_ERROR_NO_REASON;
   1052                         break;
   1053                     case RIL_SIM_SAP_TRANSFER_ATR_RSP.RIL_E_SIM_ABSENT:
   1054                         mResultCode = RESULT_ERROR_CARD_NOT_ACCESSIBLE;
   1055                         break;
   1056                     case RIL_SIM_SAP_TRANSFER_ATR_RSP.RIL_E_SIM_ALREADY_POWERED_OFF:
   1057                         mResultCode = RESULT_ERROR_CARD_POWERED_OFF;
   1058                         break;
   1059                     case RIL_SIM_SAP_TRANSFER_ATR_RSP.RIL_E_SIM_ALREADY_POWERED_ON:
   1060                         mResultCode = RESULT_ERROR_CARD_POWERED_ON;
   1061                         break;
   1062                     case RIL_SIM_SAP_TRANSFER_ATR_RSP.RIL_E_SIM_DATA_NOT_AVAILABLE:
   1063                         mResultCode = RESULT_ERROR_DATA_NOT_AVAILABLE;
   1064                         break;
   1065                     default:
   1066                         mResultCode = RESULT_ERROR_NO_REASON;
   1067                         break;
   1068                 }
   1069                 break;
   1070             }
   1071             case ID_POWER_SIM_OFF_REQ: {
   1072                 RIL_SIM_SAP_POWER_RSP resMsg =
   1073                         RIL_SIM_SAP_POWER_RSP.parseFrom(msg.getPayload().toByteArray());
   1074                 mMsgType = ID_POWER_SIM_OFF_RESP;
   1075                 switch (resMsg.getResponse()) {
   1076                     case RIL_SIM_SAP_POWER_RSP.RIL_E_SUCCESS:
   1077                         mResultCode = RESULT_OK;
   1078                         break;
   1079                     case RIL_SIM_SAP_POWER_RSP.RIL_E_GENERIC_FAILURE:
   1080                         mResultCode = RESULT_ERROR_NO_REASON;
   1081                         break;
   1082                     case RIL_SIM_SAP_POWER_RSP.RIL_E_SIM_ABSENT:
   1083                         mResultCode = RESULT_ERROR_CARD_NOT_ACCESSIBLE;
   1084                         break;
   1085                     case RIL_SIM_SAP_POWER_RSP.RIL_E_SIM_ALREADY_POWERED_OFF:
   1086                         mResultCode = RESULT_ERROR_CARD_POWERED_OFF;
   1087                         break;
   1088                     case RIL_SIM_SAP_POWER_RSP.RIL_E_SIM_ALREADY_POWERED_ON:
   1089                         mResultCode = RESULT_ERROR_CARD_POWERED_ON;
   1090                         break;
   1091                     default:
   1092                         mResultCode = RESULT_ERROR_NO_REASON;
   1093                         break;
   1094                 }
   1095                 break;
   1096             }
   1097             case ID_POWER_SIM_ON_REQ: {
   1098                 RIL_SIM_SAP_POWER_RSP resMsg =
   1099                         RIL_SIM_SAP_POWER_RSP.parseFrom(msg.getPayload().toByteArray());
   1100                 mMsgType = ID_POWER_SIM_ON_RESP;
   1101                 switch (resMsg.getResponse()) {
   1102                     case RIL_SIM_SAP_POWER_RSP.RIL_E_SUCCESS:
   1103                         mResultCode = RESULT_OK;
   1104                         break;
   1105                     case RIL_SIM_SAP_POWER_RSP.RIL_E_GENERIC_FAILURE:
   1106                         mResultCode = RESULT_ERROR_NO_REASON;
   1107                         break;
   1108                     case RIL_SIM_SAP_POWER_RSP.RIL_E_SIM_ABSENT:
   1109                         mResultCode = RESULT_ERROR_CARD_NOT_ACCESSIBLE;
   1110                         break;
   1111                     case RIL_SIM_SAP_POWER_RSP.RIL_E_SIM_ALREADY_POWERED_OFF:
   1112                         mResultCode = RESULT_ERROR_CARD_POWERED_OFF;
   1113                         break;
   1114                     case RIL_SIM_SAP_POWER_RSP.RIL_E_SIM_ALREADY_POWERED_ON:
   1115                         mResultCode = RESULT_ERROR_CARD_POWERED_ON;
   1116                         break;
   1117                     default:
   1118                         mResultCode = RESULT_ERROR_NO_REASON;
   1119                         break;
   1120                 }
   1121                 break;
   1122             }
   1123             case ID_RESET_SIM_REQ: {
   1124                 RIL_SIM_SAP_RESET_SIM_RSP resMsg =
   1125                         RIL_SIM_SAP_RESET_SIM_RSP.parseFrom(msg.getPayload().toByteArray());
   1126                 mMsgType = ID_RESET_SIM_RESP;
   1127                 switch (resMsg.getResponse()) {
   1128                     case RIL_SIM_SAP_RESET_SIM_RSP.RIL_E_SUCCESS:
   1129                         mResultCode = RESULT_OK;
   1130                         break;
   1131                     case RIL_SIM_SAP_RESET_SIM_RSP.RIL_E_GENERIC_FAILURE:
   1132                         mResultCode = RESULT_ERROR_NO_REASON;
   1133                         break;
   1134                     case RIL_SIM_SAP_RESET_SIM_RSP.RIL_E_SIM_ABSENT:
   1135                         mResultCode = RESULT_ERROR_CARD_NOT_ACCESSIBLE;
   1136                         break;
   1137                     case RIL_SIM_SAP_RESET_SIM_RSP.RIL_E_SIM_ALREADY_POWERED_OFF:
   1138                         mResultCode = RESULT_ERROR_CARD_POWERED_OFF;
   1139                         break;
   1140                     default:
   1141                         mResultCode = RESULT_ERROR_NO_REASON;
   1142                         break;
   1143                 }
   1144                 break;
   1145             }
   1146             case ID_TRANSFER_CARD_READER_STATUS_REQ: {
   1147                 RIL_SIM_SAP_TRANSFER_CARD_READER_STATUS_RSP resMsg =
   1148                         RIL_SIM_SAP_TRANSFER_CARD_READER_STATUS_RSP.parseFrom(
   1149                                 msg.getPayload().toByteArray());
   1150                 mMsgType = ID_TRANSFER_CARD_READER_STATUS_RESP;
   1151                 switch (resMsg.getResponse()) {
   1152                     case RIL_SIM_SAP_TRANSFER_CARD_READER_STATUS_RSP.RIL_E_SUCCESS:
   1153                         mResultCode = RESULT_OK;
   1154                         if (resMsg.hasCardReaderStatus()) {
   1155                             mCardReaderStatus = resMsg.getCardReaderStatus();
   1156                         } else {
   1157                             mResultCode = RESULT_ERROR_DATA_NOT_AVAILABLE;
   1158                         }
   1159                         break;
   1160                     case RIL_SIM_SAP_TRANSFER_CARD_READER_STATUS_RSP.RIL_E_GENERIC_FAILURE:
   1161                         mResultCode = RESULT_ERROR_NO_REASON;
   1162                         break;
   1163                     case RIL_SIM_SAP_TRANSFER_CARD_READER_STATUS_RSP.RIL_E_SIM_DATA_NOT_AVAILABLE:
   1164                         mResultCode = RESULT_ERROR_DATA_NOT_AVAILABLE;
   1165                         break;
   1166                     default:
   1167                         mResultCode = RESULT_ERROR_NO_REASON;
   1168                         break;
   1169                 }
   1170                 break;
   1171             }
   1172 
   1173             case ID_RIL_SIM_ACCESS_TEST_REQ: // TODO: implement in RILD
   1174                 mMsgType = ID_RIL_SIM_ACCESS_TEST_RESP;
   1175                 break;
   1176             default:
   1177                 Log.e(TAG, "Unknown request type: " + reqType);
   1178 
   1179         }
   1180     }
   1181 
   1182 
   1183     /* Map from RIL header error codes to SAP error codes */
   1184     private static int mapRilErrorCode(int rilErrorCode) {
   1185         switch (rilErrorCode) {
   1186             case SapApi.RIL_E_SUCCESS:
   1187                 return RESULT_OK;
   1188             case SapApi.RIL_E_CANCELLED:
   1189                 return RESULT_ERROR_NO_REASON;
   1190             case SapApi.RIL_E_GENERIC_FAILURE:
   1191                 return RESULT_ERROR_NO_REASON;
   1192             case SapApi.RIL_E_RADIO_NOT_AVAILABLE:
   1193                 return RESULT_ERROR_CARD_NOT_ACCESSIBLE;
   1194             case SapApi.RIL_E_INVALID_PARAMETER:
   1195                 return RESULT_ERROR_NO_REASON;
   1196             case SapApi.RIL_E_REQUEST_NOT_SUPPORTED:
   1197                 return RESULT_ERROR_NOT_SUPPORTED;
   1198             default:
   1199                 return RESULT_ERROR_NO_REASON;
   1200         }
   1201     }
   1202 
   1203 
   1204     public static String getMsgTypeName(int msgType) {
   1205         if (DEBUG || VERBOSE) {
   1206             switch (msgType) {
   1207                 case ID_CONNECT_REQ:
   1208                     return "ID_CONNECT_REQ";
   1209                 case ID_CONNECT_RESP:
   1210                     return "ID_CONNECT_RESP";
   1211                 case ID_DISCONNECT_REQ:
   1212                     return "ID_DISCONNECT_REQ";
   1213                 case ID_DISCONNECT_RESP:
   1214                     return "ID_DISCONNECT_RESP";
   1215                 case ID_DISCONNECT_IND:
   1216                     return "ID_DISCONNECT_IND";
   1217                 case ID_TRANSFER_APDU_REQ:
   1218                     return "ID_TRANSFER_APDU_REQ";
   1219                 case ID_TRANSFER_APDU_RESP:
   1220                     return "ID_TRANSFER_APDU_RESP";
   1221                 case ID_TRANSFER_ATR_REQ:
   1222                     return "ID_TRANSFER_ATR_REQ";
   1223                 case ID_TRANSFER_ATR_RESP:
   1224                     return "ID_TRANSFER_ATR_RESP";
   1225                 case ID_POWER_SIM_OFF_REQ:
   1226                     return "ID_POWER_SIM_OFF_REQ";
   1227                 case ID_POWER_SIM_OFF_RESP:
   1228                     return "ID_POWER_SIM_OFF_RESP";
   1229                 case ID_POWER_SIM_ON_REQ:
   1230                     return "ID_POWER_SIM_ON_REQ";
   1231                 case ID_POWER_SIM_ON_RESP:
   1232                     return "ID_POWER_SIM_ON_RESP";
   1233                 case ID_RESET_SIM_REQ:
   1234                     return "ID_RESET_SIM_REQ";
   1235                 case ID_RESET_SIM_RESP:
   1236                     return "ID_RESET_SIM_RESP";
   1237                 case ID_TRANSFER_CARD_READER_STATUS_REQ:
   1238                     return "ID_TRANSFER_CARD_READER_STATUS_REQ";
   1239                 case ID_TRANSFER_CARD_READER_STATUS_RESP:
   1240                     return "ID_TRANSFER_CARD_READER_STATUS_RESP";
   1241                 case ID_STATUS_IND:
   1242                     return "ID_STATUS_IND";
   1243                 case ID_ERROR_RESP:
   1244                     return "ID_ERROR_RESP";
   1245                 case ID_SET_TRANSPORT_PROTOCOL_REQ:
   1246                     return "ID_SET_TRANSPORT_PROTOCOL_REQ";
   1247                 case ID_SET_TRANSPORT_PROTOCOL_RESP:
   1248                     return "ID_SET_TRANSPORT_PROTOCOL_RESP";
   1249                 case ID_RIL_UNSOL_CONNECTED:
   1250                     return "ID_RIL_UNSOL_CONNECTED";
   1251                 case ID_RIL_UNSOL_DISCONNECT_IND:
   1252                     return "ID_RIL_UNSOL_DISCONNECT_IND";
   1253                 case ID_RIL_UNKNOWN:
   1254                     return "ID_RIL_UNKNOWN";
   1255                 case ID_RIL_GET_SIM_STATUS_REQ:
   1256                     return "ID_RIL_GET_SIM_STATUS_REQ";
   1257                 case ID_RIL_SIM_ACCESS_TEST_REQ:
   1258                     return "ID_RIL_SIM_ACCESS_TEST_REQ";
   1259                 case ID_RIL_SIM_ACCESS_TEST_RESP:
   1260                     return "ID_RIL_SIM_ACCESS_TEST_RESP";
   1261                 default:
   1262                     return "Unknown Message Type (" + msgType + ")";
   1263             }
   1264         } else {
   1265             return null;
   1266         }
   1267     }
   1268 }
   1269