SapMessage.java revision 549c5a7e95c7934d8d3ab10a8653564e42b0c937
1package com.android.bluetooth.sap;
2
3import android.hardware.radio.V1_0.ISap;
4import android.hardware.radio.V1_0.SapApduType;
5import android.hardware.radio.V1_0.SapTransferProtocol;
6import java.io.IOException;
7import java.io.InputStream;
8import java.io.OutputStream;
9import java.util.ArrayList;
10import java.util.Hashtable;
11import java.util.Map;
12import java.util.concurrent.atomic.AtomicInteger;
13
14import org.android.btsap.SapApi;
15import org.android.btsap.SapApi.*;
16import com.google.protobuf.micro.*;
17
18import android.util.Log;
19
20/**
21 * SapMessage is used for incoming and outgoing messages.
22 *
23 * For incoming messages
24 *
25 */
26public 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 = false;
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    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            Log.e(TAG, "Unknown request type");
408            return null;
409        }
410        return newMessage;
411    }
412
413    /**
414     * Blocking read of an entire array of data.
415     * @param is the input stream to read from
416     * @param buffer the buffer to read into - the length of the buffer will
417     *        determine how many bytes will be read.
418     */
419    private static void read(InputStream is, byte[] buffer) throws IOException {
420        int bytesToRead = buffer.length;
421        int bytesRead = 0;
422        int tmpBytesRead;
423        while (bytesRead < bytesToRead) {
424            tmpBytesRead = is.read(buffer, bytesRead, bytesToRead-bytesRead);
425            if(tmpBytesRead == -1)
426                throw new IOException("EOS reached while reading a byte array.");
427            else
428                bytesRead += tmpBytesRead;
429        }
430    }
431
432    /**
433     * Skip a number of bytes in an InputStream.
434     * @param is the input stream
435     * @param count the number of bytes to skip
436     * @throws IOException In case of reaching EOF or a stream error
437     */
438    private static void skip(InputStream is, int count) throws IOException {
439        for(int i = 0; i < count; i++) {
440            is.read(); // Do not use the InputStream.skip as it fails for some stream types
441        }
442    }
443
444    /**
445     * Read the parameters from the stream and update the relevant members.
446     * This function will ensure that all parameters are read from the stream, even
447     * if an error is detected.
448     * @param count the number of parameters to read
449     * @param is the input stream
450     * @return True if all parameters were successfully parsed, False if an error were detected.
451     * @throws IOException
452     */
453    private boolean parseParameters(int count, InputStream is) throws IOException {
454        int paramId;
455        int paramLength;
456        boolean success = true;
457        int skipLen = 0;
458
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
465            // As per SAP spec padding should be 0-3 bytes
466            if ((paramLength % 4) != 0)
467                skipLen = 4 - (paramLength % 4);
468
469            if(VERBOSE) Log.i(TAG, "parsing paramId: " + paramId + " with length: " + paramLength);
470            switch(paramId) {
471            case PARAM_MAX_MSG_SIZE_ID:
472                if(paramLength != PARAM_MAX_MSG_SIZE_LENGTH) {
473                    Log.e(TAG, "Received PARAM_MAX_MSG_SIZE with wrong length: " +
474                            paramLength + " skipping this parameter.");
475                    skip(is, paramLength + skipLen);
476                    success = false;
477                } else {
478                    mMaxMsgSize = is.read();
479                    mMaxMsgSize = mMaxMsgSize << 8 | is.read();
480                    skip(is, 4 - PARAM_MAX_MSG_SIZE_LENGTH);
481                }
482                break;
483            case PARAM_COMMAND_APDU_ID:
484                mApdu = new byte[paramLength];
485                read(is, mApdu);
486                skip(is, skipLen);
487                break;
488            case PARAM_COMMAND_APDU7816_ID:
489                mApdu7816 = new byte[paramLength];
490                read(is, mApdu7816);
491                skip(is, skipLen);
492                break;
493            case PARAM_TRANSPORT_PROTOCOL_ID:
494                if(paramLength != PARAM_TRANSPORT_PROTOCOL_LENGTH) {
495                    Log.e(TAG, "Received PARAM_TRANSPORT_PROTOCOL with wrong length: " +
496                            paramLength + " skipping this parameter.");
497                    skip(is, paramLength + skipLen);
498                    success = false;
499                } else {
500                    mTransportProtocol = is.read();
501                    skip(is, 4 - PARAM_TRANSPORT_PROTOCOL_LENGTH);
502                }
503                break;
504            case PARAM_CONNECTION_STATUS_ID:
505                // not needed for server role, but used for module test
506                if(paramLength != PARAM_CONNECTION_STATUS_LENGTH) {
507                    Log.e(TAG, "Received PARAM_CONNECTION_STATUS with wrong length: " +
508                            paramLength + " skipping this parameter.");
509                    skip(is, paramLength + skipLen);
510                    success = false;
511                } else {
512                    mConnectionStatus = is.read();
513                    skip(is, 4 - PARAM_CONNECTION_STATUS_LENGTH);
514                }
515                break;
516            case PARAM_CARD_READER_STATUS_ID:
517                // not needed for server role, but used for module test
518                if(paramLength != PARAM_CARD_READER_STATUS_LENGTH) {
519                    Log.e(TAG, "Received PARAM_CARD_READER_STATUS with wrong length: " +
520                            paramLength + " skipping this parameter.");
521                    skip(is, paramLength + skipLen);
522                    success = false;
523                } else {
524                    mCardReaderStatus = is.read();
525                    skip(is, 4 - PARAM_CARD_READER_STATUS_LENGTH);
526                }
527                break;
528            case PARAM_STATUS_CHANGE_ID:
529                // not needed for server role, but used for module 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 + skipLen);
534                    success = false;
535                } else {
536                    mStatusChange = is.read();
537                    skip(is, 4 - PARAM_STATUS_CHANGE_LENGTH);
538                }
539                break;
540            case PARAM_RESULT_CODE_ID:
541                // not needed for server role, but used for module test
542                if(paramLength != PARAM_RESULT_CODE_LENGTH) {
543                    Log.e(TAG, "Received PARAM_RESULT_CODE with wrong length: " +
544                            paramLength + " skipping this parameter.");
545                    skip(is, paramLength + skipLen);
546                    success = false;
547                } else {
548                    mResultCode = is.read();
549                    skip(is, 4 - PARAM_RESULT_CODE_LENGTH);
550                }
551                break;
552            case PARAM_DISCONNECT_TYPE_ID:
553                // not needed for server role, but used for module test
554                if(paramLength != PARAM_DISCONNECT_TYPE_LENGTH) {
555                    Log.e(TAG, "Received PARAM_DISCONNECT_TYPE_ID with wrong length: " +
556                            paramLength + " skipping this parameter.");
557                    skip(is, paramLength + skipLen);
558                    success = false;
559                } else {
560                    mDisconnectionType = is.read();
561                    skip(is, 4 - PARAM_DISCONNECT_TYPE_LENGTH);
562                }
563                break;
564            case PARAM_RESPONSE_APDU_ID:
565                // not needed for server role, but used for module test
566                mApduResp = new byte[paramLength];
567                read(is, mApduResp);
568                skip(is, skipLen);
569                break;
570            case PARAM_ATR_ID:
571                // not needed for server role, but used for module test
572                mAtr = new byte[paramLength];
573                read(is, mAtr);
574                skip(is, skipLen);
575                break;
576            default:
577                Log.e(TAG, "Received unknown parameter ID: " + paramId + " length: " +
578                        paramLength + " skipping this parameter.");
579                skip(is, paramLength + skipLen);
580            }
581        }
582        return success;
583    }
584
585    /**
586     * Writes a single value parameter of 1 or 2 bytes in length.
587     * @param os The BufferedOutputStream to write to.
588     * @param id The Parameter ID
589     * @param value The parameter value
590     * @param length The length of the parameter value
591     * @throws IOException if the write to os fails
592     */
593    private static void writeParameter(OutputStream os, int id, int value, int length)
594                throws IOException {
595
596        /* Parameter Header*/
597        os.write(id);
598        os.write(0);
599        os.write(0);
600        os.write(length);
601
602        switch(length) {
603        case 1:
604            os.write(value & 0xff);
605            os.write(0); // Padding
606            os.write(0); // Padding
607            os.write(0); // padding
608            break;
609        case 2:
610            os.write((value >> 8) & 0xff);
611            os.write(value & 0xff);
612            os.write(0); // Padding
613            os.write(0); // padding
614            break;
615        default:
616            throw new IOException("Unable to write value of length: " + length);
617        }
618    }
619
620    /**
621     * Writes a byte[] parameter of any length.
622     * @param os The BufferedOutputStream to write to.
623     * @param id The Parameter ID
624     * @param value The byte array to write, the length will be extracted from the array.
625     * @throws IOException if the write to os fails
626     */
627    private static void writeParameter(OutputStream os, int id, byte[] value) throws IOException {
628
629        /* Parameter Header*/
630        os.write(id);
631        os.write(0); // reserved
632        os.write((value.length >> 8) & 0xff);
633        os.write(value.length & 0xff);
634
635        /* Payload */
636        os.write(value);
637        if (value.length % 4 != 0) {
638            for (int i = 0; i < (4 - (value.length % 4)); ++i) {
639                os.write(0); // Padding
640            }
641        }
642    }
643
644    public void write(OutputStream os) throws IOException {
645        /* Write the header */
646        os.write(mMsgType);
647        os.write(getParamCount());
648        os.write(0); // padding
649        os.write(0); // padding
650
651        /* write the parameters */
652        if(mConnectionStatus != INVALID_VALUE) {
653            writeParameter(os,PARAM_CONNECTION_STATUS_ID, mConnectionStatus,
654                            PARAM_CONNECTION_STATUS_LENGTH);
655        }
656        if(mMaxMsgSize != INVALID_VALUE) {
657            writeParameter(os, PARAM_MAX_MSG_SIZE_ID, mMaxMsgSize,
658                            PARAM_MAX_MSG_SIZE_LENGTH);
659        }
660        if(mResultCode != INVALID_VALUE) {
661            writeParameter(os, PARAM_RESULT_CODE_ID, mResultCode,
662                            PARAM_RESULT_CODE_LENGTH);
663        }
664        if(mDisconnectionType != INVALID_VALUE) {
665            writeParameter(os, PARAM_DISCONNECT_TYPE_ID, mDisconnectionType,
666                            PARAM_DISCONNECT_TYPE_LENGTH);
667        }
668        if(mCardReaderStatus != INVALID_VALUE) {
669            writeParameter(os, PARAM_CARD_READER_STATUS_ID, mCardReaderStatus,
670                            PARAM_CARD_READER_STATUS_LENGTH);
671        }
672        if(mStatusChange != INVALID_VALUE) {
673            writeParameter(os, PARAM_STATUS_CHANGE_ID, mStatusChange,
674                            PARAM_STATUS_CHANGE_LENGTH);
675        }
676        if(mTransportProtocol != INVALID_VALUE) {
677            writeParameter(os, PARAM_TRANSPORT_PROTOCOL_ID, mTransportProtocol,
678                            PARAM_TRANSPORT_PROTOCOL_LENGTH);
679        }
680        if(mApdu != null) {
681            writeParameter(os, PARAM_COMMAND_APDU_ID, mApdu);
682        }
683        if(mApdu7816 != null) {
684            writeParameter(os, PARAM_COMMAND_APDU7816_ID, mApdu7816);
685        }
686        if(mApduResp != null) {
687            writeParameter(os, PARAM_RESPONSE_APDU_ID, mApduResp);
688        }
689        if(mAtr != null) {
690            writeParameter(os, PARAM_ATR_ID, mAtr);
691        }
692    }
693
694    /***************************************************************************
695     * RILD Interface message conversion functions.
696     ***************************************************************************/
697
698    /**
699     * We use this function to
700     * @param length
701     * @param rawOut
702     * @throws IOException
703     */
704    private void writeLength(int length, CodedOutputStreamMicro out) throws IOException {
705        byte[] dataLength = new byte[4];
706        dataLength[0] = dataLength[1] = 0;
707        dataLength[2] = (byte)((length >> 8) & 0xff);
708        dataLength[3] = (byte)((length) & 0xff);
709        out.writeRawBytes(dataLength);
710    }
711
712    private ArrayList<Byte> primitiveArrayToContainerArrayList(byte[] arr) {
713        ArrayList<Byte> arrayList = new ArrayList<>(arr.length);
714        for (byte b : arr) {
715            arrayList.add(b);
716        }
717        return arrayList;
718    }
719
720    /**
721     * Send the message by calling corresponding ISap api.
722     */
723    public void send(ISap sapProxy) throws Exception {
724        int rilSerial = sNextSerial.getAndIncrement();
725
726        Log.e(TAG, "callISapReq: called for mMsgType " + mMsgType + " rilSerial " + rilSerial);
727
728        /* Update the ongoing requests queue */
729        if (mClearRilQueue == true) {
730            resetPendingRilMessages();
731        }
732        // No need to synchronize this, as the HashList is already doing this.
733        sOngoingRequests.put(rilSerial, mMsgType);
734
735        switch(mMsgType) {
736        case ID_CONNECT_REQ:
737        {
738            sapProxy.connectReq(rilSerial, mMaxMsgSize);
739            break;
740        }
741        case ID_DISCONNECT_REQ:
742        {
743            sapProxy.disconnectReq(rilSerial);
744            break;
745        }
746        case ID_TRANSFER_APDU_REQ:
747        {
748            int type;
749            ArrayList<Byte> command;
750            if(mApdu != null) {
751                type = SapApduType.APDU;
752                command = primitiveArrayToContainerArrayList(mApdu);
753            } else if (mApdu7816 != null) {
754                type = SapApduType.APDU7816;
755                command = primitiveArrayToContainerArrayList(mApdu7816);
756            } else {
757                Log.e(TAG, "Missing Apdu parameter in TRANSFER_APDU_REQ");
758                throw new IllegalArgumentException();
759            }
760            sapProxy.apduReq(rilSerial, type, command);
761            break;
762        }
763        case ID_SET_TRANSPORT_PROTOCOL_REQ:
764        {
765            int transportProtocol;
766            if(mTransportProtocol == TRANS_PROTO_T0) {
767                transportProtocol = SapTransferProtocol.T0;
768            } else if(mTransportProtocol == TRANS_PROTO_T1) {
769                transportProtocol = SapTransferProtocol.T1;
770            } else {
771                Log.e(TAG, "Missing or invalid TransportProtocol parameter in"
772                                + " SET_TRANSPORT_PROTOCOL_REQ: " + mTransportProtocol);
773                throw new IllegalArgumentException();
774            }
775            sapProxy.setTransferProtocolReq(rilSerial, transportProtocol);
776            break;
777        }
778        case ID_TRANSFER_ATR_REQ:
779        {
780            sapProxy.transferAtrReq(rilSerial);
781            break;
782        }
783        case ID_POWER_SIM_OFF_REQ:
784        {
785            sapProxy.powerReq(rilSerial, false);
786            break;
787        }
788        case ID_POWER_SIM_ON_REQ:
789        {
790            sapProxy.powerReq(rilSerial, true);
791            break;
792        }
793        case ID_RESET_SIM_REQ:
794        {
795            sapProxy.resetSimReq(rilSerial);
796            break;
797        }
798        case ID_TRANSFER_CARD_READER_STATUS_REQ:
799        {
800            sapProxy.transferCardReaderStatusReq(rilSerial);
801            break;
802        }
803        default:
804            Log.e(TAG, "Unknown request type");
805            throw new IllegalArgumentException();
806        }
807        if (VERBOSE) Log.e(TAG, "callISapReq: done without exceptions");
808    }
809
810    public static SapMessage newInstance(MsgHeader msg) throws IOException {
811        return new SapMessage(msg);
812    }
813
814    private SapMessage(MsgHeader msg) throws IOException {
815        // All header members are "required" hence the hasXxxx() is not needed for those
816        try{
817            switch(msg.getType()){
818            case SapApi.UNSOL_RESPONSE:
819                createUnsolicited(msg);
820                break;
821            case SapApi.RESPONSE:
822                createSolicited(msg);
823                break;
824            default:
825                throw new IOException("Wrong msg header received: Type: " + msg.getType());
826            }
827        } catch (InvalidProtocolBufferMicroException e) {
828            Log.w(TAG, "Error occured parsing a RIL message", e);
829            throw new IOException("Error occured parsing a RIL message");
830        }
831    }
832
833    private void createUnsolicited(MsgHeader msg)
834                    throws IOException, InvalidProtocolBufferMicroException {
835        switch(msg.getId()) {
836// TODO:
837//        Not sure when we use these?        case RIL_UNSOL_RIL_CONNECTED:
838//            if(VERBOSE) Log.i(TAG, "RIL_UNSOL_RIL_CONNECTED received, ignoring");
839//            msgType = ID_RIL_UNSOL_CONNECTED;
840//            break;
841        case SapApi.RIL_SIM_SAP_STATUS:
842        {
843            if(VERBOSE) Log.i(TAG, "RIL_SIM_SAP_STATUS_IND received");
844            RIL_SIM_SAP_STATUS_IND indMsg =
845                    RIL_SIM_SAP_STATUS_IND.parseFrom(msg.getPayload().toByteArray());
846            mMsgType = ID_STATUS_IND;
847            if(indMsg.hasStatusChange()) {
848                setStatusChange(indMsg.getStatusChange());
849                if(VERBOSE) Log.i(TAG, "RIL_UNSOL_SIM_SAP_STATUS_IND received value = "
850                        + mStatusChange);
851            } else {
852                if(VERBOSE) Log.i(TAG, "Wrong number of parameters in SAP_STATUS_IND, ignoring...");
853                mMsgType = ID_RIL_UNKNOWN;
854            }
855            break;
856        }
857        case SapApi.RIL_SIM_SAP_DISCONNECT:
858        {
859            if(VERBOSE) Log.i(TAG, "RIL_SIM_SAP_DISCONNECT_IND received");
860
861            RIL_SIM_SAP_DISCONNECT_IND indMsg =
862                    RIL_SIM_SAP_DISCONNECT_IND.parseFrom(msg.getPayload().toByteArray());
863            mMsgType = ID_RIL_UNSOL_DISCONNECT_IND; // don't use ID_DISCONNECT_IND;
864            if(indMsg.hasDisconnectType()) {
865                setDisconnectionType(indMsg.getDisconnectType());
866                if(VERBOSE) Log.i(TAG, "RIL_UNSOL_SIM_SAP_STATUS_IND received value = "
867                                                                + mDisconnectionType);
868            } else {
869                if(VERBOSE) Log.i(TAG, "Wrong number of parameters in SAP_STATUS_IND, ignoring...");
870                mMsgType = ID_RIL_UNKNOWN;
871            }
872            break;
873        }
874        default:
875            if(VERBOSE) Log.i(TAG, "Unused unsolicited message received, ignoring: " + msg.getId());
876            mMsgType = ID_RIL_UNKNOWN;
877        }
878    }
879
880    private void createSolicited(MsgHeader msg) throws IOException,
881                                                       InvalidProtocolBufferMicroException{
882        /* re-evaluate if we should just ignore these - we could simply catch the exception? */
883        if(msg.hasToken() == false) throw new IOException("Token is missing");
884        if(msg.hasError() == false) throw new IOException("Error code is missing");
885        int serial = msg.getToken();
886        int error = msg.getError();
887        Integer reqType = null;
888        reqType = sOngoingRequests.remove(serial);
889        if(VERBOSE) Log.i(TAG, "RIL SOLICITED serial: " + serial + ", error: " + error
890                + " SapReqType: " + ((reqType== null)?"null":getMsgTypeName(reqType)));
891
892        if(reqType == null) {
893            /* This can happen if we get a resp. for a canceled request caused by a power off,
894             *  reset or disconnect
895             */
896            Log.w(TAG, "Solicited response received on a command not initiated - ignoring.");
897            return;
898        }
899        mResultCode = mapRilErrorCode(error);
900
901        switch(reqType) {
902        case ID_CONNECT_REQ:
903        {
904            RIL_SIM_SAP_CONNECT_RSP resMsg =
905                    RIL_SIM_SAP_CONNECT_RSP.parseFrom(msg.getPayload().toByteArray());
906            mMsgType = ID_CONNECT_RESP;
907            if(resMsg.hasMaxMessageSize()) {
908                mMaxMsgSize = resMsg.getMaxMessageSize();
909
910            }
911            switch(resMsg.getResponse()) {
912            case RIL_SIM_SAP_CONNECT_RSP.RIL_E_SUCCESS:
913                mConnectionStatus = CON_STATUS_OK;
914                break;
915            case RIL_SIM_SAP_CONNECT_RSP.RIL_E_SAP_CONNECT_OK_CALL_ONGOING:
916                mConnectionStatus = CON_STATUS_OK_ONGOING_CALL;
917                break;
918            case RIL_SIM_SAP_CONNECT_RSP.RIL_E_SAP_CONNECT_FAILURE:
919                mConnectionStatus = CON_STATUS_ERROR_CONNECTION;
920                break;
921            case RIL_SIM_SAP_CONNECT_RSP.RIL_E_SAP_MSG_SIZE_TOO_LARGE:
922                mConnectionStatus = CON_STATUS_ERROR_MAX_MSG_SIZE_UNSUPPORTED;
923                break;
924            case RIL_SIM_SAP_CONNECT_RSP.RIL_E_SAP_MSG_SIZE_TOO_SMALL:
925                mConnectionStatus = CON_STATUS_ERROR_MAX_MSG_SIZE_TOO_SMALL;
926                break;
927            default:
928                mConnectionStatus = CON_STATUS_ERROR_CONNECTION; // Cannot happen!
929                break;
930            }
931            mResultCode = INVALID_VALUE;
932            if(VERBOSE) Log.v(TAG, "  ID_CONNECT_REQ: mMaxMsgSize: " + mMaxMsgSize
933                    + "  mConnectionStatus: " + mConnectionStatus);
934            break;
935        }
936        case ID_DISCONNECT_REQ:
937            mMsgType = ID_DISCONNECT_RESP;
938            mResultCode = INVALID_VALUE;
939            break;
940        case ID_TRANSFER_APDU_REQ:
941        {
942            RIL_SIM_SAP_APDU_RSP resMsg =
943                    RIL_SIM_SAP_APDU_RSP.parseFrom(msg.getPayload().toByteArray());
944            mMsgType = ID_TRANSFER_APDU_RESP;
945            switch(resMsg.getResponse()) {
946            case RIL_SIM_SAP_APDU_RSP.RIL_E_SUCCESS:
947                mResultCode = RESULT_OK;
948                /* resMsg.getType is unused as the client knows the type of request used. */
949                if(resMsg.hasApduResponse()){
950                    mApduResp = resMsg.getApduResponse().toByteArray();
951                }
952                break;
953            case RIL_SIM_SAP_APDU_RSP.RIL_E_GENERIC_FAILURE:
954                mResultCode = RESULT_ERROR_NO_REASON;
955                break;
956            case RIL_SIM_SAP_APDU_RSP.RIL_E_SIM_ABSENT:
957                mResultCode = RESULT_ERROR_CARD_NOT_ACCESSIBLE;
958                break;
959            case RIL_SIM_SAP_APDU_RSP.RIL_E_SIM_ALREADY_POWERED_OFF:
960                mResultCode = RESULT_ERROR_CARD_POWERED_OFF;
961                break;
962            case RIL_SIM_SAP_APDU_RSP.RIL_E_SIM_NOT_READY:
963                mResultCode = RESULT_ERROR_CARD_REMOVED;
964                break;
965            default:
966                mResultCode = RESULT_ERROR_NO_REASON;
967                break;
968            }
969            break;
970        }
971        case ID_SET_TRANSPORT_PROTOCOL_REQ:
972        {
973            RIL_SIM_SAP_SET_TRANSFER_PROTOCOL_RSP resMsg =
974                        RIL_SIM_SAP_SET_TRANSFER_PROTOCOL_RSP.parseFrom(
975                                msg.getPayload().toByteArray());
976            mMsgType = ID_SET_TRANSPORT_PROTOCOL_RESP;
977            switch(resMsg.getResponse()) {
978            case RIL_SIM_SAP_SET_TRANSFER_PROTOCOL_RSP.RIL_E_SUCCESS:
979                mResultCode = RESULT_OK;
980                break;
981            case RIL_SIM_SAP_SET_TRANSFER_PROTOCOL_RSP.RIL_E_GENERIC_FAILURE:
982                mResultCode = RESULT_ERROR_NOT_SUPPORTED;
983                break;
984            case RIL_SIM_SAP_SET_TRANSFER_PROTOCOL_RSP.RIL_E_SIM_ABSENT:
985                mResultCode = RESULT_ERROR_CARD_NOT_ACCESSIBLE;
986                break;
987            case RIL_SIM_SAP_SET_TRANSFER_PROTOCOL_RSP.RIL_E_SIM_ALREADY_POWERED_OFF:
988                mResultCode = RESULT_ERROR_CARD_POWERED_OFF;
989                break;
990            case RIL_SIM_SAP_SET_TRANSFER_PROTOCOL_RSP.RIL_E_SIM_NOT_READY:
991                mResultCode = RESULT_ERROR_CARD_REMOVED;
992                break;
993            default:
994                mResultCode = RESULT_ERROR_NOT_SUPPORTED;
995                break;
996            }
997            break;
998        }
999        case ID_TRANSFER_ATR_REQ:
1000        {
1001            RIL_SIM_SAP_TRANSFER_ATR_RSP resMsg =
1002                    RIL_SIM_SAP_TRANSFER_ATR_RSP.parseFrom(msg.getPayload().toByteArray());
1003            mMsgType =ID_TRANSFER_ATR_RESP;
1004            if(resMsg.hasAtr()) {
1005                mAtr = resMsg.getAtr().toByteArray();
1006            }
1007            switch(resMsg.getResponse()) {
1008            case RIL_SIM_SAP_TRANSFER_ATR_RSP.RIL_E_SUCCESS:
1009                mResultCode = RESULT_OK;
1010                break;
1011            case RIL_SIM_SAP_TRANSFER_ATR_RSP.RIL_E_GENERIC_FAILURE:
1012                mResultCode = RESULT_ERROR_NO_REASON;
1013                break;
1014            case RIL_SIM_SAP_TRANSFER_ATR_RSP.RIL_E_SIM_ABSENT:
1015                mResultCode = RESULT_ERROR_CARD_NOT_ACCESSIBLE;
1016                break;
1017            case RIL_SIM_SAP_TRANSFER_ATR_RSP.RIL_E_SIM_ALREADY_POWERED_OFF:
1018                mResultCode = RESULT_ERROR_CARD_POWERED_OFF;
1019                break;
1020            case RIL_SIM_SAP_TRANSFER_ATR_RSP.RIL_E_SIM_ALREADY_POWERED_ON:
1021                mResultCode = RESULT_ERROR_CARD_POWERED_ON;
1022                break;
1023            case RIL_SIM_SAP_TRANSFER_ATR_RSP.RIL_E_SIM_DATA_NOT_AVAILABLE:
1024                mResultCode = RESULT_ERROR_DATA_NOT_AVAILABLE;
1025                break;
1026            default:
1027                mResultCode = RESULT_ERROR_NO_REASON;
1028                break;
1029            }
1030            break;
1031        }
1032        case ID_POWER_SIM_OFF_REQ:
1033        {
1034            RIL_SIM_SAP_POWER_RSP resMsg =
1035                    RIL_SIM_SAP_POWER_RSP.parseFrom(msg.getPayload().toByteArray());
1036            mMsgType = ID_POWER_SIM_OFF_RESP;
1037            switch(resMsg.getResponse()) {
1038            case RIL_SIM_SAP_POWER_RSP.RIL_E_SUCCESS:
1039                mResultCode = RESULT_OK;
1040                break;
1041            case RIL_SIM_SAP_POWER_RSP.RIL_E_GENERIC_FAILURE:
1042                mResultCode = RESULT_ERROR_NO_REASON;
1043                break;
1044            case RIL_SIM_SAP_POWER_RSP.RIL_E_SIM_ABSENT:
1045                mResultCode = RESULT_ERROR_CARD_NOT_ACCESSIBLE;
1046                break;
1047            case RIL_SIM_SAP_POWER_RSP.RIL_E_SIM_ALREADY_POWERED_OFF:
1048                mResultCode = RESULT_ERROR_CARD_POWERED_OFF;
1049                break;
1050            case RIL_SIM_SAP_POWER_RSP.RIL_E_SIM_ALREADY_POWERED_ON:
1051                mResultCode = RESULT_ERROR_CARD_POWERED_ON;
1052                break;
1053            default:
1054                mResultCode = RESULT_ERROR_NO_REASON;
1055                break;
1056            }
1057            break;
1058        }
1059        case ID_POWER_SIM_ON_REQ:
1060        {
1061            RIL_SIM_SAP_POWER_RSP resMsg =
1062                    RIL_SIM_SAP_POWER_RSP.parseFrom(msg.getPayload().toByteArray());
1063            mMsgType = ID_POWER_SIM_ON_RESP;
1064            switch(resMsg.getResponse()) {
1065            case RIL_SIM_SAP_POWER_RSP.RIL_E_SUCCESS:
1066                mResultCode = RESULT_OK;
1067                break;
1068            case RIL_SIM_SAP_POWER_RSP.RIL_E_GENERIC_FAILURE:
1069                mResultCode = RESULT_ERROR_NO_REASON;
1070                break;
1071            case RIL_SIM_SAP_POWER_RSP.RIL_E_SIM_ABSENT:
1072                mResultCode = RESULT_ERROR_CARD_NOT_ACCESSIBLE;
1073                break;
1074            case RIL_SIM_SAP_POWER_RSP.RIL_E_SIM_ALREADY_POWERED_OFF:
1075                mResultCode = RESULT_ERROR_CARD_POWERED_OFF;
1076                break;
1077            case RIL_SIM_SAP_POWER_RSP.RIL_E_SIM_ALREADY_POWERED_ON:
1078                mResultCode = RESULT_ERROR_CARD_POWERED_ON;
1079                break;
1080            default:
1081                mResultCode = RESULT_ERROR_NO_REASON;
1082                break;
1083            }
1084            break;
1085        }
1086        case ID_RESET_SIM_REQ:
1087        {
1088            RIL_SIM_SAP_RESET_SIM_RSP resMsg =
1089                    RIL_SIM_SAP_RESET_SIM_RSP.parseFrom(msg.getPayload().toByteArray());
1090            mMsgType = ID_RESET_SIM_RESP;
1091            switch(resMsg.getResponse()) {
1092            case RIL_SIM_SAP_RESET_SIM_RSP.RIL_E_SUCCESS:
1093                mResultCode = RESULT_OK;
1094                break;
1095            case RIL_SIM_SAP_RESET_SIM_RSP.RIL_E_GENERIC_FAILURE:
1096                mResultCode = RESULT_ERROR_NO_REASON;
1097                break;
1098            case RIL_SIM_SAP_RESET_SIM_RSP.RIL_E_SIM_ABSENT:
1099                mResultCode = RESULT_ERROR_CARD_NOT_ACCESSIBLE;
1100                break;
1101            case RIL_SIM_SAP_RESET_SIM_RSP.RIL_E_SIM_ALREADY_POWERED_OFF:
1102                mResultCode = RESULT_ERROR_CARD_POWERED_OFF;
1103                break;
1104            default:
1105                mResultCode = RESULT_ERROR_NO_REASON;
1106                break;
1107            }
1108            break;
1109        }
1110        case ID_TRANSFER_CARD_READER_STATUS_REQ:
1111        {
1112            RIL_SIM_SAP_TRANSFER_CARD_READER_STATUS_RSP resMsg =
1113                    RIL_SIM_SAP_TRANSFER_CARD_READER_STATUS_RSP.parseFrom(
1114                            msg.getPayload().toByteArray());
1115            mMsgType = ID_TRANSFER_CARD_READER_STATUS_RESP;
1116            switch(resMsg.getResponse()) {
1117            case RIL_SIM_SAP_TRANSFER_CARD_READER_STATUS_RSP.RIL_E_SUCCESS:
1118                mResultCode = RESULT_OK;
1119                if(resMsg.hasCardReaderStatus()) {
1120                    mCardReaderStatus = resMsg.getCardReaderStatus();
1121                } else {
1122                    mResultCode = RESULT_ERROR_DATA_NOT_AVAILABLE;
1123                }
1124                break;
1125            case RIL_SIM_SAP_TRANSFER_CARD_READER_STATUS_RSP.RIL_E_GENERIC_FAILURE:
1126                mResultCode = RESULT_ERROR_NO_REASON;
1127                break;
1128            case RIL_SIM_SAP_TRANSFER_CARD_READER_STATUS_RSP.RIL_E_SIM_DATA_NOT_AVAILABLE:
1129                mResultCode = RESULT_ERROR_DATA_NOT_AVAILABLE;
1130                break;
1131            default:
1132                mResultCode = RESULT_ERROR_NO_REASON;
1133                break;
1134            }
1135            break;
1136        }
1137
1138        case ID_RIL_SIM_ACCESS_TEST_REQ: // TODO: implement in RILD
1139            mMsgType = ID_RIL_SIM_ACCESS_TEST_RESP;
1140            break;
1141        default:
1142            Log.e(TAG, "Unknown request type: " + reqType);
1143
1144        }
1145    }
1146
1147
1148
1149    /* Map from RIL header error codes to SAP error codes */
1150    private static int mapRilErrorCode(int rilErrorCode) {
1151        switch(rilErrorCode) {
1152        case SapApi.RIL_E_SUCCESS:
1153            return RESULT_OK;
1154        case SapApi.RIL_E_CANCELLED:
1155            return RESULT_ERROR_NO_REASON;
1156        case SapApi.RIL_E_GENERIC_FAILURE:
1157            return RESULT_ERROR_NO_REASON;
1158        case SapApi.RIL_E_RADIO_NOT_AVAILABLE:
1159            return RESULT_ERROR_CARD_NOT_ACCESSIBLE;
1160        case SapApi.RIL_E_INVALID_PARAMETER:
1161            return RESULT_ERROR_NO_REASON;
1162        case SapApi.RIL_E_REQUEST_NOT_SUPPORTED:
1163            return RESULT_ERROR_NOT_SUPPORTED;
1164        default:
1165            return RESULT_ERROR_NO_REASON;
1166        }
1167    }
1168
1169
1170
1171    public static String getMsgTypeName(int msgType) {
1172        if(DEBUG || VERBOSE) {
1173            switch (msgType)
1174            {
1175                case ID_CONNECT_REQ: return "ID_CONNECT_REQ";
1176                case ID_CONNECT_RESP: return "ID_CONNECT_RESP";
1177                case ID_DISCONNECT_REQ: return "ID_DISCONNECT_REQ";
1178                case ID_DISCONNECT_RESP: return "ID_DISCONNECT_RESP";
1179                case ID_DISCONNECT_IND: return "ID_DISCONNECT_IND";
1180                case ID_TRANSFER_APDU_REQ: return "ID_TRANSFER_APDU_REQ";
1181                case ID_TRANSFER_APDU_RESP: return "ID_TRANSFER_APDU_RESP";
1182                case ID_TRANSFER_ATR_REQ: return "ID_TRANSFER_ATR_REQ";
1183                case ID_TRANSFER_ATR_RESP: return "ID_TRANSFER_ATR_RESP";
1184                case ID_POWER_SIM_OFF_REQ: return "ID_POWER_SIM_OFF_REQ";
1185                case ID_POWER_SIM_OFF_RESP: return "ID_POWER_SIM_OFF_RESP";
1186                case ID_POWER_SIM_ON_REQ: return "ID_POWER_SIM_ON_REQ";
1187                case ID_POWER_SIM_ON_RESP: return "ID_POWER_SIM_ON_RESP";
1188                case ID_RESET_SIM_REQ: return "ID_RESET_SIM_REQ";
1189                case ID_RESET_SIM_RESP: return "ID_RESET_SIM_RESP";
1190                case ID_TRANSFER_CARD_READER_STATUS_REQ:
1191                    return "ID_TRANSFER_CARD_READER_STATUS_REQ";
1192                case ID_TRANSFER_CARD_READER_STATUS_RESP:
1193                    return "ID_TRANSFER_CARD_READER_STATUS_RESP";
1194                case ID_STATUS_IND: return "ID_STATUS_IND";
1195                case ID_ERROR_RESP: return "ID_ERROR_RESP";
1196                case ID_SET_TRANSPORT_PROTOCOL_REQ: return "ID_SET_TRANSPORT_PROTOCOL_REQ";
1197                case ID_SET_TRANSPORT_PROTOCOL_RESP: return "ID_SET_TRANSPORT_PROTOCOL_RESP";
1198                case ID_RIL_UNSOL_CONNECTED: return "ID_RIL_UNSOL_CONNECTED";
1199                case ID_RIL_UNKNOWN: return "ID_RIL_UNKNOWN";
1200                case ID_RIL_GET_SIM_STATUS_REQ: return "ID_RIL_GET_SIM_STATUS_REQ";
1201                case ID_RIL_SIM_ACCESS_TEST_REQ: return "ID_RIL_SIM_ACCESS_TEST_REQ";
1202                case ID_RIL_SIM_ACCESS_TEST_RESP: return "ID_RIL_SIM_ACCESS_TEST_RESP";
1203                default: return "Unknown Message Type (" + msgType + ")";
1204            }
1205        } else {
1206            return null;
1207        }
1208    }
1209}
1210