1 package com.android.bluetooth.sap;
2 
3 import java.io.IOException;
4 import java.io.InputStream;
5 import java.io.OutputStream;
6 import java.security.InvalidParameterException;
7 import java.util.Arrays;
8 import java.util.Hashtable;
9 import java.util.Map;
10 import java.util.concurrent.atomic.AtomicInteger;
11 
12 import org.android.btsap.SapApi;
13 import org.android.btsap.SapApi.*;
14 import com.google.protobuf.micro.*;
15 
16 import android.os.Parcel;
17 import android.os.Parcelable;
18 import android.util.Log;
19 
20 /**
21  * SapMessage is used for incoming and outgoing messages.
22  *
23  * For incoming messages
24  *
25  */
26 public class SapMessage {
27 
28     public static final String TAG = "SapMessage";
29     public static final boolean DEBUG = SapService.DEBUG;
30     public static final boolean VERBOSE = SapService.VERBOSE;
31     public static final boolean TEST = 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     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      */
SapMessage(int msgType)185     public SapMessage(int msgType){
186         this.mMsgType = msgType;
187     }
188 
resetPendingRilMessages()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 
getNumPendingRilMessages()197     public static int getNumPendingRilMessages() {
198         return sOngoingRequests.size();
199     }
200 
getMsgType()201     public int getMsgType() {
202         return mMsgType;
203     }
204 
setMsgType(int msgType)205     public void setMsgType(int msgType) {
206         this.mMsgType = msgType;
207     }
208 
getMaxMsgSize()209     public int getMaxMsgSize() {
210         return mMaxMsgSize;
211     }
212 
setMaxMsgSize(int maxMsgSize)213     public void setMaxMsgSize(int maxMsgSize) {
214         this.mMaxMsgSize = maxMsgSize;
215     }
216 
getConnectionStatus()217     public int getConnectionStatus() {
218         return mConnectionStatus;
219     }
220 
setConnectionStatus(int connectionStatus)221     public void setConnectionStatus(int connectionStatus) {
222         this.mConnectionStatus = connectionStatus;
223     }
224 
getResultCode()225     public int getResultCode() {
226         return mResultCode;
227     }
228 
setResultCode(int resultCode)229     public void setResultCode(int resultCode) {
230         this.mResultCode = resultCode;
231     }
232 
getDisconnectionType()233     public int getDisconnectionType() {
234         return mDisconnectionType;
235     }
236 
setDisconnectionType(int disconnectionType)237     public void setDisconnectionType(int disconnectionType) {
238         this.mDisconnectionType = disconnectionType;
239     }
240 
getCardReaderStatus()241     public int getCardReaderStatus() {
242         return mCardReaderStatus;
243     }
244 
setCardReaderStatus(int cardReaderStatus)245     public void setCardReaderStatus(int cardReaderStatus) {
246         this.mCardReaderStatus = cardReaderStatus;
247     }
248 
getStatusChange()249     public int getStatusChange() {
250         return mStatusChange;
251     }
252 
setStatusChange(int statusChange)253     public void setStatusChange(int statusChange) {
254         this.mStatusChange = statusChange;
255     }
256 
getTransportProtocol()257     public int getTransportProtocol() {
258         return mTransportProtocol;
259     }
260 
setTransportProtocol(int transportProtocol)261     public void setTransportProtocol(int transportProtocol) {
262         this.mTransportProtocol = transportProtocol;
263     }
264 
getApdu()265     public byte[] getApdu() {
266         return mApdu;
267     }
268 
setApdu(byte[] apdu)269     public void setApdu(byte[] apdu) {
270         this.mApdu = apdu;
271     }
272 
getApdu7816()273     public byte[] getApdu7816() {
274         return mApdu7816;
275     }
276 
setApdu7816(byte[] apdu)277     public void setApdu7816(byte[] apdu) {
278         this.mApdu7816 = apdu;
279     }
280 
getApduResp()281     public byte[] getApduResp() {
282         return mApduResp;
283     }
284 
setApduResp(byte[] apduResp)285     public void setApduResp(byte[] apduResp) {
286         this.mApduResp = apduResp;
287     }
288 
getAtr()289     public byte[] getAtr() {
290         return mAtr;
291     }
292 
setAtr(byte[] atr)293     public void setAtr(byte[] atr) {
294         this.mAtr = atr;
295     }
296 
getSendToRil()297     public boolean getSendToRil() {
298         return mSendToRil;
299     }
300 
setSendToRil(boolean sendToRil)301     public void setSendToRil(boolean sendToRil) {
302         this.mSendToRil = sendToRil;
303     }
304 
getClearRilQueue()305     public boolean getClearRilQueue() {
306         return mClearRilQueue;
307     }
308 
setClearRilQueue(boolean clearRilQueue)309     public void setClearRilQueue(boolean clearRilQueue) {
310         this.mClearRilQueue = clearRilQueue;
311     }
312 
getTestMode()313     public int getTestMode() {
314         return mTestMode;
315     }
316 
setTestMode(int testMode)317     public void setTestMode(int testMode) {
318         this.mTestMode = testMode;
319     }
320 
getParamCount()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")
readMessage(int requestType, InputStream is)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      */
read(InputStream is, byte[] buffer)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      */
skip(InputStream is, int count)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      */
parseParameters(int count, InputStream is)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      */
writeParameter(OutputStream os, int id, int value, int length)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      */
writeParameter(OutputStream os, int id, byte[] value)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 
write(OutputStream os)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      */
writeLength(int length, CodedOutputStreamMicro out)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      * Write this SAP message as a rild compatible protobuf message.
713      * Solicited Requests are formed as follows:
714      *  int type - the rild-bt type
715      *  int serial - an number incrementing for each message.
716      */
writeReqToStream(CodedOutputStreamMicro out)717     public void writeReqToStream(CodedOutputStreamMicro out) throws IOException {
718 
719         int rilSerial = sNextSerial.getAndIncrement();
720         SapApi.MsgHeader msg = new MsgHeader();
721         /* Common variables for all requests */
722         msg.setToken(rilSerial);
723         msg.setType(SapApi.REQUEST);
724         msg.setError(SapApi.RIL_E_UNUSED);
725 
726         switch(mMsgType) {
727         case ID_CONNECT_REQ:
728         {
729             SapApi.RIL_SIM_SAP_CONNECT_REQ reqMsg = new RIL_SIM_SAP_CONNECT_REQ();
730             reqMsg.setMaxMessageSize(mMaxMsgSize);
731             msg.setId(SapApi.RIL_SIM_SAP_CONNECT);
732             msg.setPayload(ByteStringMicro.copyFrom(reqMsg.toByteArray()));
733             writeLength(msg.getSerializedSize(), out);
734             msg.writeTo(out);
735             break;
736         }
737         case ID_DISCONNECT_REQ:
738         {
739             SapApi.RIL_SIM_SAP_DISCONNECT_REQ reqMsg = new RIL_SIM_SAP_DISCONNECT_REQ();
740             msg.setId(SapApi.RIL_SIM_SAP_DISCONNECT);
741             msg.setPayload(ByteStringMicro.copyFrom(reqMsg.toByteArray()));
742             writeLength(msg.getSerializedSize(), out);
743             msg.writeTo(out);
744             break;
745         }
746         case ID_TRANSFER_APDU_REQ:
747         {
748             SapApi.RIL_SIM_SAP_APDU_REQ reqMsg = new RIL_SIM_SAP_APDU_REQ();
749             msg.setId(SapApi.RIL_SIM_SAP_APDU);
750             if(mApdu != null) {
751                 reqMsg.setType(SapApi.RIL_SIM_SAP_APDU_REQ.RIL_TYPE_APDU);
752                 reqMsg.setCommand(ByteStringMicro.copyFrom(mApdu));
753             } else if (mApdu7816 != null) {
754                 reqMsg.setType(SapApi.RIL_SIM_SAP_APDU_REQ.RIL_TYPE_APDU7816);
755                 reqMsg.setCommand(ByteStringMicro.copyFrom(mApdu7816));
756             } else {
757                 Log.e(TAG, "Missing Apdu parameter in TRANSFER_APDU_REQ");
758                 throw new IllegalArgumentException();
759             }
760             msg.setPayload(ByteStringMicro.copyFrom(reqMsg.toByteArray()));
761             writeLength(msg.getSerializedSize(), out);
762             msg.writeTo(out);
763             break;
764         }
765         case ID_SET_TRANSPORT_PROTOCOL_REQ:
766         {
767             SapApi.RIL_SIM_SAP_SET_TRANSFER_PROTOCOL_REQ reqMsg =
768                                             new RIL_SIM_SAP_SET_TRANSFER_PROTOCOL_REQ();
769             msg.setId(SapApi.RIL_SIM_SAP_SET_TRANSFER_PROTOCOL);
770 
771             if(mTransportProtocol == TRANS_PROTO_T0) {
772                 reqMsg.setProtocol(SapApi.RIL_SIM_SAP_SET_TRANSFER_PROTOCOL_REQ.t0);
773             } else if(mTransportProtocol == TRANS_PROTO_T1) {
774                 reqMsg.setProtocol(SapApi.RIL_SIM_SAP_SET_TRANSFER_PROTOCOL_REQ.t1);
775             } else {
776                 Log.e(TAG, "Missing or invalid TransportProtocol parameter in"+
777                            " SET_TRANSPORT_PROTOCOL_REQ: "+ mTransportProtocol );
778                 throw new IllegalArgumentException();
779             }
780             msg.setPayload(ByteStringMicro.copyFrom(reqMsg.toByteArray()));
781             writeLength(msg.getSerializedSize(), out);
782             msg.writeTo(out);
783             break;
784         }
785         case ID_TRANSFER_ATR_REQ:
786         {
787             SapApi.RIL_SIM_SAP_TRANSFER_ATR_REQ reqMsg = new RIL_SIM_SAP_TRANSFER_ATR_REQ();
788             msg.setId(SapApi.RIL_SIM_SAP_TRANSFER_ATR);
789             msg.setPayload(ByteStringMicro.copyFrom(reqMsg.toByteArray()));
790             writeLength(msg.getSerializedSize(), out);
791             msg.writeTo(out);
792             break;
793         }
794         case ID_POWER_SIM_OFF_REQ:
795         {
796             SapApi.RIL_SIM_SAP_POWER_REQ reqMsg = new RIL_SIM_SAP_POWER_REQ();
797             msg.setId(SapApi.RIL_SIM_SAP_POWER);
798             reqMsg.setState(false);
799             msg.setPayload(ByteStringMicro.copyFrom(reqMsg.toByteArray()));
800             writeLength(msg.getSerializedSize(), out);
801             msg.writeTo(out);
802             break;
803         }
804         case ID_POWER_SIM_ON_REQ:
805         {
806             SapApi.RIL_SIM_SAP_POWER_REQ reqMsg = new RIL_SIM_SAP_POWER_REQ();
807             msg.setId(SapApi.RIL_SIM_SAP_POWER);
808             reqMsg.setState(true);
809             msg.setPayload(ByteStringMicro.copyFrom(reqMsg.toByteArray()));
810             writeLength(msg.getSerializedSize(), out);
811             msg.writeTo(out);
812             break;
813         }
814         case ID_RESET_SIM_REQ:
815         {
816             SapApi.RIL_SIM_SAP_RESET_SIM_REQ reqMsg = new RIL_SIM_SAP_RESET_SIM_REQ();
817             msg.setId(SapApi.RIL_SIM_SAP_RESET_SIM);
818             msg.setPayload(ByteStringMicro.copyFrom(reqMsg.toByteArray()));
819             writeLength(msg.getSerializedSize(), out);
820             msg.writeTo(out);
821             break;
822         }
823         case ID_TRANSFER_CARD_READER_STATUS_REQ:
824         {
825             SapApi.RIL_SIM_SAP_TRANSFER_CARD_READER_STATUS_REQ reqMsg =
826                                     new RIL_SIM_SAP_TRANSFER_CARD_READER_STATUS_REQ();
827             msg.setId(SapApi.RIL_SIM_SAP_TRANSFER_CARD_READER_STATUS);
828             msg.setPayload(ByteStringMicro.copyFrom(reqMsg.toByteArray()));
829             writeLength(msg.getSerializedSize(), out);
830             msg.writeTo(out);
831             break;
832         }
833         default:
834             Log.e(TAG, "Unknown request type");
835             throw new IllegalArgumentException();
836         }
837         /* Update the ongoing requests queue */
838         if(mClearRilQueue == true) {
839             resetPendingRilMessages();
840         }
841         // No need to synchronize this, as the HashList is already doing this.
842         sOngoingRequests.put(rilSerial, mMsgType);
843         out.flush();
844     }
845 
newInstance(MsgHeader msg)846     public static SapMessage newInstance(MsgHeader msg) throws IOException {
847         return new SapMessage(msg);
848     }
849 
SapMessage(MsgHeader msg)850     private SapMessage(MsgHeader msg) throws IOException {
851         // All header members are "required" hence the hasXxxx() is not needed for those
852         try{
853             switch(msg.getType()){
854             case SapApi.UNSOL_RESPONSE:
855                 createUnsolicited(msg);
856                 break;
857             case SapApi.RESPONSE:
858                 createSolicited(msg);
859                 break;
860             default:
861                 throw new IOException("Wrong msg header received: Type: " + msg.getType());
862             }
863         } catch (InvalidProtocolBufferMicroException e) {
864             Log.w(TAG, "Error occured parsing a RIL message", e);
865             throw new IOException("Error occured parsing a RIL message");
866         }
867     }
868 
createUnsolicited(MsgHeader msg)869     private void createUnsolicited(MsgHeader msg)
870                     throws IOException, InvalidProtocolBufferMicroException {
871         switch(msg.getId()) {
872 // TODO:
873 //        Not sure when we use these?        case RIL_UNSOL_RIL_CONNECTED:
874 //            if(VERBOSE) Log.i(TAG, "RIL_UNSOL_RIL_CONNECTED received, ignoring");
875 //            msgType = ID_RIL_UNSOL_CONNECTED;
876 //            break;
877         case SapApi.RIL_SIM_SAP_STATUS:
878         {
879             if(VERBOSE) Log.i(TAG, "RIL_SIM_SAP_STATUS_IND received");
880             RIL_SIM_SAP_STATUS_IND indMsg =
881                     RIL_SIM_SAP_STATUS_IND.parseFrom(msg.getPayload().toByteArray());
882             mMsgType = ID_STATUS_IND;
883             if(indMsg.hasStatusChange()) {
884                 setStatusChange(indMsg.getStatusChange());
885                 if(VERBOSE) Log.i(TAG, "RIL_UNSOL_SIM_SAP_STATUS_IND received value = "
886                         + mStatusChange);
887             } else {
888                 if(VERBOSE) Log.i(TAG, "Wrong number of parameters in SAP_STATUS_IND, ignoring...");
889                 mMsgType = ID_RIL_UNKNOWN;
890             }
891             break;
892         }
893         case SapApi.RIL_SIM_SAP_DISCONNECT:
894         {
895             if(VERBOSE) Log.i(TAG, "RIL_SIM_SAP_DISCONNECT_IND received");
896 
897             RIL_SIM_SAP_DISCONNECT_IND indMsg =
898                     RIL_SIM_SAP_DISCONNECT_IND.parseFrom(msg.getPayload().toByteArray());
899             mMsgType = ID_RIL_UNSOL_DISCONNECT_IND; // don't use ID_DISCONNECT_IND;
900             if(indMsg.hasDisconnectType()) {
901                 setDisconnectionType(indMsg.getDisconnectType());
902                 if(VERBOSE) Log.i(TAG, "RIL_UNSOL_SIM_SAP_STATUS_IND received value = "
903                                                                 + mDisconnectionType);
904             } else {
905                 if(VERBOSE) Log.i(TAG, "Wrong number of parameters in SAP_STATUS_IND, ignoring...");
906                 mMsgType = ID_RIL_UNKNOWN;
907             }
908             break;
909         }
910         default:
911             if(VERBOSE) Log.i(TAG, "Unused unsolicited message received, ignoring: " + msg.getId());
912             mMsgType = ID_RIL_UNKNOWN;
913         }
914     }
915 
createSolicited(MsgHeader msg)916     private void createSolicited(MsgHeader msg) throws IOException,
917                                                        InvalidProtocolBufferMicroException{
918         /* re-evaluate if we should just ignore these - we could simply catch the exception? */
919         if(msg.hasToken() == false) throw new IOException("Token is missing");
920         if(msg.hasError() == false) throw new IOException("Error code is missing");
921         int serial = msg.getToken();
922         int error = msg.getError();
923         Integer reqType = null;
924         reqType = sOngoingRequests.remove(serial);
925         if(VERBOSE) Log.i(TAG, "RIL SOLICITED serial: " + serial + ", error: " + error
926                 + " SapReqType: " + ((reqType== null)?"null":getMsgTypeName(reqType)));
927 
928         if(reqType == null) {
929             /* This can happen if we get a resp. for a canceled request caused by a power off,
930              *  reset or disconnect
931              */
932             Log.w(TAG, "Solicited response received on a command not initiated - ignoring.");
933             return;
934         }
935         mResultCode = mapRilErrorCode(error);
936 
937         switch(reqType) {
938         case ID_CONNECT_REQ:
939         {
940             RIL_SIM_SAP_CONNECT_RSP resMsg =
941                     RIL_SIM_SAP_CONNECT_RSP.parseFrom(msg.getPayload().toByteArray());
942             mMsgType = ID_CONNECT_RESP;
943             if(resMsg.hasMaxMessageSize()) {
944                 mMaxMsgSize = resMsg.getMaxMessageSize();
945 
946             }
947             switch(resMsg.getResponse()) {
948             case RIL_SIM_SAP_CONNECT_RSP.RIL_E_SUCCESS:
949                 mConnectionStatus = CON_STATUS_OK;
950                 break;
951             case RIL_SIM_SAP_CONNECT_RSP.RIL_E_SAP_CONNECT_OK_CALL_ONGOING:
952                 mConnectionStatus = CON_STATUS_OK_ONGOING_CALL;
953                 break;
954             case RIL_SIM_SAP_CONNECT_RSP.RIL_E_SAP_CONNECT_FAILURE:
955                 mConnectionStatus = CON_STATUS_ERROR_CONNECTION;
956                 break;
957             case RIL_SIM_SAP_CONNECT_RSP.RIL_E_SAP_MSG_SIZE_TOO_LARGE:
958                 mConnectionStatus = CON_STATUS_ERROR_MAX_MSG_SIZE_UNSUPPORTED;
959                 break;
960             case RIL_SIM_SAP_CONNECT_RSP.RIL_E_SAP_MSG_SIZE_TOO_SMALL:
961                 mConnectionStatus = CON_STATUS_ERROR_MAX_MSG_SIZE_TOO_SMALL;
962                 break;
963             default:
964                 mConnectionStatus = CON_STATUS_ERROR_CONNECTION; // Cannot happen!
965                 break;
966             }
967             mResultCode = INVALID_VALUE;
968             if(VERBOSE) Log.v(TAG, "  ID_CONNECT_REQ: mMaxMsgSize: " + mMaxMsgSize
969                     + "  mConnectionStatus: " + mConnectionStatus);
970             break;
971         }
972         case ID_DISCONNECT_REQ:
973             mMsgType = ID_DISCONNECT_RESP;
974             mResultCode = INVALID_VALUE;
975             break;
976         case ID_TRANSFER_APDU_REQ:
977         {
978             RIL_SIM_SAP_APDU_RSP resMsg =
979                     RIL_SIM_SAP_APDU_RSP.parseFrom(msg.getPayload().toByteArray());
980             mMsgType = ID_TRANSFER_APDU_RESP;
981             switch(resMsg.getResponse()) {
982             case RIL_SIM_SAP_APDU_RSP.RIL_E_SUCCESS:
983                 mResultCode = RESULT_OK;
984                 /* resMsg.getType is unused as the client knows the type of request used. */
985                 if(resMsg.hasApduResponse()){
986                     mApduResp = resMsg.getApduResponse().toByteArray();
987                 }
988                 break;
989             case RIL_SIM_SAP_APDU_RSP.RIL_E_GENERIC_FAILURE:
990                 mResultCode = RESULT_ERROR_NO_REASON;
991                 break;
992             case RIL_SIM_SAP_APDU_RSP.RIL_E_SIM_ABSENT:
993                 mResultCode = RESULT_ERROR_CARD_NOT_ACCESSIBLE;
994                 break;
995             case RIL_SIM_SAP_APDU_RSP.RIL_E_SIM_ALREADY_POWERED_OFF:
996                 mResultCode = RESULT_ERROR_CARD_POWERED_OFF;
997                 break;
998             case RIL_SIM_SAP_APDU_RSP.RIL_E_SIM_NOT_READY:
999                 mResultCode = RESULT_ERROR_CARD_REMOVED;
1000                 break;
1001             default:
1002                 mResultCode = RESULT_ERROR_NO_REASON;
1003                 break;
1004             }
1005             break;
1006         }
1007         case ID_SET_TRANSPORT_PROTOCOL_REQ:
1008         {
1009             RIL_SIM_SAP_SET_TRANSFER_PROTOCOL_RSP resMsg =
1010                         RIL_SIM_SAP_SET_TRANSFER_PROTOCOL_RSP.parseFrom(
1011                                 msg.getPayload().toByteArray());
1012             mMsgType = ID_SET_TRANSPORT_PROTOCOL_RESP;
1013             switch(resMsg.getResponse()) {
1014             case RIL_SIM_SAP_SET_TRANSFER_PROTOCOL_RSP.RIL_E_SUCCESS:
1015                 mResultCode = RESULT_OK;
1016                 break;
1017             case RIL_SIM_SAP_SET_TRANSFER_PROTOCOL_RSP.RIL_E_GENERIC_FAILURE:
1018                 mResultCode = RESULT_ERROR_NOT_SUPPORTED;
1019                 break;
1020             case RIL_SIM_SAP_SET_TRANSFER_PROTOCOL_RSP.RIL_E_SIM_ABSENT:
1021                 mResultCode = RESULT_ERROR_CARD_NOT_ACCESSIBLE;
1022                 break;
1023             case RIL_SIM_SAP_SET_TRANSFER_PROTOCOL_RSP.RIL_E_SIM_ALREADY_POWERED_OFF:
1024                 mResultCode = RESULT_ERROR_CARD_POWERED_OFF;
1025                 break;
1026             case RIL_SIM_SAP_SET_TRANSFER_PROTOCOL_RSP.RIL_E_SIM_NOT_READY:
1027                 mResultCode = RESULT_ERROR_CARD_REMOVED;
1028                 break;
1029             default:
1030                 mResultCode = RESULT_ERROR_NOT_SUPPORTED;
1031                 break;
1032             }
1033             break;
1034         }
1035         case ID_TRANSFER_ATR_REQ:
1036         {
1037             RIL_SIM_SAP_TRANSFER_ATR_RSP resMsg =
1038                     RIL_SIM_SAP_TRANSFER_ATR_RSP.parseFrom(msg.getPayload().toByteArray());
1039             mMsgType =ID_TRANSFER_ATR_RESP;
1040             if(resMsg.hasAtr()) {
1041                 mAtr = resMsg.getAtr().toByteArray();
1042             }
1043             switch(resMsg.getResponse()) {
1044             case RIL_SIM_SAP_TRANSFER_ATR_RSP.RIL_E_SUCCESS:
1045                 mResultCode = RESULT_OK;
1046                 break;
1047             case RIL_SIM_SAP_TRANSFER_ATR_RSP.RIL_E_GENERIC_FAILURE:
1048                 mResultCode = RESULT_ERROR_NO_REASON;
1049                 break;
1050             case RIL_SIM_SAP_TRANSFER_ATR_RSP.RIL_E_SIM_ABSENT:
1051                 mResultCode = RESULT_ERROR_CARD_NOT_ACCESSIBLE;
1052                 break;
1053             case RIL_SIM_SAP_TRANSFER_ATR_RSP.RIL_E_SIM_ALREADY_POWERED_OFF:
1054                 mResultCode = RESULT_ERROR_CARD_POWERED_OFF;
1055                 break;
1056             case RIL_SIM_SAP_TRANSFER_ATR_RSP.RIL_E_SIM_ALREADY_POWERED_ON:
1057                 mResultCode = RESULT_ERROR_CARD_POWERED_ON;
1058                 break;
1059             case RIL_SIM_SAP_TRANSFER_ATR_RSP.RIL_E_SIM_DATA_NOT_AVAILABLE:
1060                 mResultCode = RESULT_ERROR_DATA_NOT_AVAILABLE;
1061                 break;
1062             default:
1063                 mResultCode = RESULT_ERROR_NO_REASON;
1064                 break;
1065             }
1066             break;
1067         }
1068         case ID_POWER_SIM_OFF_REQ:
1069         {
1070             RIL_SIM_SAP_POWER_RSP resMsg =
1071                     RIL_SIM_SAP_POWER_RSP.parseFrom(msg.getPayload().toByteArray());
1072             mMsgType = ID_POWER_SIM_OFF_RESP;
1073             switch(resMsg.getResponse()) {
1074             case RIL_SIM_SAP_POWER_RSP.RIL_E_SUCCESS:
1075                 mResultCode = RESULT_OK;
1076                 break;
1077             case RIL_SIM_SAP_POWER_RSP.RIL_E_GENERIC_FAILURE:
1078                 mResultCode = RESULT_ERROR_NO_REASON;
1079                 break;
1080             case RIL_SIM_SAP_POWER_RSP.RIL_E_SIM_ABSENT:
1081                 mResultCode = RESULT_ERROR_CARD_NOT_ACCESSIBLE;
1082                 break;
1083             case RIL_SIM_SAP_POWER_RSP.RIL_E_SIM_ALREADY_POWERED_OFF:
1084                 mResultCode = RESULT_ERROR_CARD_POWERED_OFF;
1085                 break;
1086             case RIL_SIM_SAP_POWER_RSP.RIL_E_SIM_ALREADY_POWERED_ON:
1087                 mResultCode = RESULT_ERROR_CARD_POWERED_ON;
1088                 break;
1089             default:
1090                 mResultCode = RESULT_ERROR_NO_REASON;
1091                 break;
1092             }
1093             break;
1094         }
1095         case ID_POWER_SIM_ON_REQ:
1096         {
1097             RIL_SIM_SAP_POWER_RSP resMsg =
1098                     RIL_SIM_SAP_POWER_RSP.parseFrom(msg.getPayload().toByteArray());
1099             mMsgType = ID_POWER_SIM_ON_RESP;
1100             switch(resMsg.getResponse()) {
1101             case RIL_SIM_SAP_POWER_RSP.RIL_E_SUCCESS:
1102                 mResultCode = RESULT_OK;
1103                 break;
1104             case RIL_SIM_SAP_POWER_RSP.RIL_E_GENERIC_FAILURE:
1105                 mResultCode = RESULT_ERROR_NO_REASON;
1106                 break;
1107             case RIL_SIM_SAP_POWER_RSP.RIL_E_SIM_ABSENT:
1108                 mResultCode = RESULT_ERROR_CARD_NOT_ACCESSIBLE;
1109                 break;
1110             case RIL_SIM_SAP_POWER_RSP.RIL_E_SIM_ALREADY_POWERED_OFF:
1111                 mResultCode = RESULT_ERROR_CARD_POWERED_OFF;
1112                 break;
1113             case RIL_SIM_SAP_POWER_RSP.RIL_E_SIM_ALREADY_POWERED_ON:
1114                 mResultCode = RESULT_ERROR_CARD_POWERED_ON;
1115                 break;
1116             default:
1117                 mResultCode = RESULT_ERROR_NO_REASON;
1118                 break;
1119             }
1120             break;
1121         }
1122         case ID_RESET_SIM_REQ:
1123         {
1124             RIL_SIM_SAP_RESET_SIM_RSP resMsg =
1125                     RIL_SIM_SAP_RESET_SIM_RSP.parseFrom(msg.getPayload().toByteArray());
1126             mMsgType = ID_RESET_SIM_RESP;
1127             switch(resMsg.getResponse()) {
1128             case RIL_SIM_SAP_RESET_SIM_RSP.RIL_E_SUCCESS:
1129                 mResultCode = RESULT_OK;
1130                 break;
1131             case RIL_SIM_SAP_RESET_SIM_RSP.RIL_E_GENERIC_FAILURE:
1132                 mResultCode = RESULT_ERROR_NO_REASON;
1133                 break;
1134             case RIL_SIM_SAP_RESET_SIM_RSP.RIL_E_SIM_ABSENT:
1135                 mResultCode = RESULT_ERROR_CARD_NOT_ACCESSIBLE;
1136                 break;
1137             case RIL_SIM_SAP_RESET_SIM_RSP.RIL_E_SIM_ALREADY_POWERED_OFF:
1138                 mResultCode = RESULT_ERROR_CARD_POWERED_OFF;
1139                 break;
1140             default:
1141                 mResultCode = RESULT_ERROR_NO_REASON;
1142                 break;
1143             }
1144             break;
1145         }
1146         case ID_TRANSFER_CARD_READER_STATUS_REQ:
1147         {
1148             RIL_SIM_SAP_TRANSFER_CARD_READER_STATUS_RSP resMsg =
1149                     RIL_SIM_SAP_TRANSFER_CARD_READER_STATUS_RSP.parseFrom(
1150                             msg.getPayload().toByteArray());
1151             mMsgType = ID_TRANSFER_CARD_READER_STATUS_RESP;
1152             switch(resMsg.getResponse()) {
1153             case RIL_SIM_SAP_TRANSFER_CARD_READER_STATUS_RSP.RIL_E_SUCCESS:
1154                 mResultCode = RESULT_OK;
1155                 if(resMsg.hasCardReaderStatus()) {
1156                     mCardReaderStatus = resMsg.getCardReaderStatus();
1157                 } else {
1158                     mResultCode = RESULT_ERROR_DATA_NOT_AVAILABLE;
1159                 }
1160                 break;
1161             case RIL_SIM_SAP_TRANSFER_CARD_READER_STATUS_RSP.RIL_E_GENERIC_FAILURE:
1162                 mResultCode = RESULT_ERROR_NO_REASON;
1163                 break;
1164             case RIL_SIM_SAP_TRANSFER_CARD_READER_STATUS_RSP.RIL_E_SIM_DATA_NOT_AVAILABLE:
1165                 mResultCode = RESULT_ERROR_DATA_NOT_AVAILABLE;
1166                 break;
1167             default:
1168                 mResultCode = RESULT_ERROR_NO_REASON;
1169                 break;
1170             }
1171             break;
1172         }
1173 
1174         case ID_RIL_SIM_ACCESS_TEST_REQ: // TODO: implement in RILD
1175             mMsgType = ID_RIL_SIM_ACCESS_TEST_RESP;
1176             break;
1177         default:
1178             Log.e(TAG, "Unknown request type: " + reqType);
1179 
1180         }
1181     }
1182 
1183 
1184 
1185     /* Map from RIL header error codes to SAP error codes */
mapRilErrorCode(int rilErrorCode)1186     private static int mapRilErrorCode(int rilErrorCode) {
1187         switch(rilErrorCode) {
1188         case SapApi.RIL_E_SUCCESS:
1189             return RESULT_OK;
1190         case SapApi.RIL_E_CANCELLED:
1191             return RESULT_ERROR_NO_REASON;
1192         case SapApi.RIL_E_GENERIC_FAILURE:
1193             return RESULT_ERROR_NO_REASON;
1194         case SapApi.RIL_E_RADIO_NOT_AVAILABLE:
1195             return RESULT_ERROR_CARD_NOT_ACCESSIBLE;
1196         case SapApi.RIL_E_INVALID_PARAMETER:
1197             return RESULT_ERROR_NO_REASON;
1198         case SapApi.RIL_E_REQUEST_NOT_SUPPORTED:
1199             return RESULT_ERROR_NOT_SUPPORTED;
1200         default:
1201             return RESULT_ERROR_NO_REASON;
1202         }
1203     }
1204 
1205 
1206 
getMsgTypeName(int msgType)1207     public static String getMsgTypeName(int msgType) {
1208         if(DEBUG || VERBOSE) {
1209             switch (msgType)
1210             {
1211                 case ID_CONNECT_REQ: return "ID_CONNECT_REQ";
1212                 case ID_CONNECT_RESP: return "ID_CONNECT_RESP";
1213                 case ID_DISCONNECT_REQ: return "ID_DISCONNECT_REQ";
1214                 case ID_DISCONNECT_RESP: return "ID_DISCONNECT_RESP";
1215                 case ID_DISCONNECT_IND: return "ID_DISCONNECT_IND";
1216                 case ID_TRANSFER_APDU_REQ: return "ID_TRANSFER_APDU_REQ";
1217                 case ID_TRANSFER_APDU_RESP: return "ID_TRANSFER_APDU_RESP";
1218                 case ID_TRANSFER_ATR_REQ: return "ID_TRANSFER_ATR_REQ";
1219                 case ID_TRANSFER_ATR_RESP: return "ID_TRANSFER_ATR_RESP";
1220                 case ID_POWER_SIM_OFF_REQ: return "ID_POWER_SIM_OFF_REQ";
1221                 case ID_POWER_SIM_OFF_RESP: return "ID_POWER_SIM_OFF_RESP";
1222                 case ID_POWER_SIM_ON_REQ: return "ID_POWER_SIM_ON_REQ";
1223                 case ID_POWER_SIM_ON_RESP: return "ID_POWER_SIM_ON_RESP";
1224                 case ID_RESET_SIM_REQ: return "ID_RESET_SIM_REQ";
1225                 case ID_RESET_SIM_RESP: return "ID_RESET_SIM_RESP";
1226                 case ID_TRANSFER_CARD_READER_STATUS_REQ:
1227                     return "ID_TRANSFER_CARD_READER_STATUS_REQ";
1228                 case ID_TRANSFER_CARD_READER_STATUS_RESP:
1229                     return "ID_TRANSFER_CARD_READER_STATUS_RESP";
1230                 case ID_STATUS_IND: return "ID_STATUS_IND";
1231                 case ID_ERROR_RESP: return "ID_ERROR_RESP";
1232                 case ID_SET_TRANSPORT_PROTOCOL_REQ: return "ID_SET_TRANSPORT_PROTOCOL_REQ";
1233                 case ID_SET_TRANSPORT_PROTOCOL_RESP: return "ID_SET_TRANSPORT_PROTOCOL_RESP";
1234                 case ID_RIL_UNSOL_CONNECTED: return "ID_RIL_UNSOL_CONNECTED";
1235                 case ID_RIL_UNKNOWN: return "ID_RIL_UNKNOWN";
1236                 case ID_RIL_GET_SIM_STATUS_REQ: return "ID_RIL_GET_SIM_STATUS_REQ";
1237                 case ID_RIL_SIM_ACCESS_TEST_REQ: return "ID_RIL_SIM_ACCESS_TEST_REQ";
1238                 case ID_RIL_SIM_ACCESS_TEST_RESP: return "ID_RIL_SIM_ACCESS_TEST_RESP";
1239                 default: return "Unknown Message Type (" + msgType + ")";
1240             }
1241         } else {
1242             return null;
1243         }
1244     }
1245 }
1246