• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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