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