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