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