Merge "Do not treat NULL response as error for getAllowedCarriers" am: e1bdb3ff16 am: 2579380c88
am: cbfb65f7cc

Change-Id: Ic1fe6f3c559b26f26f3aa9335a04836be969abff
diff --git a/include/telephony/ril.h b/include/telephony/ril.h
index 2012403..ad10627 100644
--- a/include/telephony/ril.h
+++ b/include/telephony/ril.h
@@ -73,6 +73,7 @@
  *                    RIL_REQUEST_SET_CARRIER_RESTRICTIONS and RIL_UNSOL_PCO_DATA.
  *
  * RIL_VERSION = 15 : New commands added:
+ *                    RIL_UNSOL_MODEM_RESTART,
  *                    RIL_REQUEST_SEND_DEVICE_STATE,
  *                    RIL_REQUEST_SET_UNSOLICITED_RESPONSE_FILTER,
  *                    RIL_REQUEST_SET_SIM_CARD_POWER,
@@ -350,7 +351,17 @@
     PREF_NET_TYPE_LTE_GSM_WCDMA            = 9, /* LTE, GSM/WCDMA */
     PREF_NET_TYPE_LTE_CMDA_EVDO_GSM_WCDMA  = 10, /* LTE, CDMA, EvDo, GSM/WCDMA */
     PREF_NET_TYPE_LTE_ONLY                 = 11, /* LTE only */
-    PREF_NET_TYPE_LTE_WCDMA                = 12  /* LTE/WCDMA */
+    PREF_NET_TYPE_LTE_WCDMA                = 12,  /* LTE/WCDMA */
+    PREF_NET_TYPE_TD_SCDMA_ONLY            = 13, /* TD-SCDMA only */
+    PREF_NET_TYPE_TD_SCDMA_WCDMA           = 14, /* TD-SCDMA and WCDMA */
+    PREF_NET_TYPE_TD_SCDMA_LTE             = 15, /* TD-SCDMA and LTE */
+    PREF_NET_TYPE_TD_SCDMA_GSM             = 16, /* TD-SCDMA and GSM */
+    PREF_NET_TYPE_TD_SCDMA_GSM_LTE         = 17, /* TD-SCDMA,GSM and LTE */
+    PREF_NET_TYPE_TD_SCDMA_GSM_WCDMA       = 18, /* TD-SCDMA, GSM/WCDMA */
+    PREF_NET_TYPE_TD_SCDMA_WCDMA_LTE       = 19, /* TD-SCDMA, WCDMA and LTE */
+    PREF_NET_TYPE_TD_SCDMA_GSM_WCDMA_LTE   = 20, /* TD-SCDMA, GSM/WCDMA and LTE */
+    PREF_NET_TYPE_TD_SCDMA_GSM_WCDMA_CDMA_EVDO_AUTO  = 21, /* TD-SCDMA, GSM/WCDMA, CDMA and EvDo */
+    PREF_NET_TYPE_TD_SCDMA_LTE_CDMA_EVDO_GSM_WCDMA   = 22  /* TD-SCDMA, LTE, CDMA, EvDo GSM/WCDMA */
 } RIL_PreferredNetworkType;
 
 /* Source for cdma subscription */
@@ -1981,11 +1992,11 @@
 
 typedef enum {
     RIL_DST_POWER_SAVE_MODE,        // Device power save mode (provided by PowerManager)
-                                    // Non-zero value indicates the device is in power save mode.
+                                    // True indicates the device is in power save mode.
     RIL_DST_CHARGING_STATE,         // Device charging state (provided by BatteryManager)
-                                    // Non-zero value indicates the device is charging.
-    RIL_DST_LOW_DATA_EXPECTED       // Low data expected mode. Non-zero value indicates low data
-                                    // traffic is expected, for example, when the device is idle
+                                    // True indicates the device is charging.
+    RIL_DST_LOW_DATA_EXPECTED       // Low data expected mode. True indicates low data traffic
+                                    // is expected, for example, when the device is idle
                                     // (e.g. not doing tethering in the background). Note
                                     // this doesn't mean no data is expected.
 } RIL_DeviceStateType;
@@ -2057,7 +2068,6 @@
  *
  * SUCCESS
  * RADIO_NOT_AVAILABLE (radio resetting)
- * GENERIC_FAILURE
  * PASSWORD_INCORRECT
  */
 
@@ -2620,7 +2630,6 @@
  *
  * Based on the return error, caller decides to resend if sending sms
  * fails. SMS_SEND_FAIL_RETRY means retry (i.e. error cause is 332)
- * and GENERIC_FAILURE means no retry (i.e. error cause is 500)
  *
  * Valid errors:
  *  SUCCESS
@@ -2663,7 +2672,6 @@
  *
  * Based on the return error, caller decides to resend if sending sms
  * fails. SMS_SEND_FAIL_RETRY means retry (i.e. error cause is 332)
- * and GENERIC_FAILURE means no retry (i.e. error cause is 500)
  *
  * Valid errors:
  *  SUCCESS
@@ -2756,7 +2764,7 @@
  *  For all other errors the RIL_Data_Call_Resonse_v6 is ignored.
  *
  *  Other errors could include:
- *    RADIO_NOT_AVAILABLE, GENERIC_FAILURE, OP_NOT_ALLOWED_BEFORE_REG_TO_NW,
+ *    RADIO_NOT_AVAILABLE, OP_NOT_ALLOWED_BEFORE_REG_TO_NW,
  *    OP_NOT_ALLOWED_DURING_VOICE_CALL and REQUEST_NOT_SUPPORTED.
  *
  * See also: RIL_REQUEST_DEACTIVATE_DATA_CALL
@@ -3269,8 +3277,6 @@
  *
  * Note: Returns ILLEGAL_SIM_OR_ME when the failure is permanent and
  *       no retries needed, such as illegal SIM or ME.
- *       Returns GENERIC_FAILURE for all other causes that might be
- *       fixed by retries.
  *
  */
 #define RIL_REQUEST_SET_NETWORK_SELECTION_AUTOMATIC 46
@@ -3294,8 +3300,6 @@
  *
  * Note: Returns ILLEGAL_SIM_OR_ME when the failure is permanent and
  *       no retries needed, such as illegal SIM or ME.
- *       Returns GENERIC_FAILURE for all other causes that might be
- *       fixed by retries.
  *
  */
 #define RIL_REQUEST_SET_NETWORK_SELECTION_MANUAL 47
@@ -3786,7 +3790,6 @@
  * Valid errors:
  *  RIL_E_SUCCESS
  *  RIL_E_RADIO_NOT_AVAILABLE (radio resetting)
- *  RIL_E_GENERIC_FAILURE
  */
 #define RIL_REQUEST_STK_GET_PROFILE 67
 
@@ -3804,7 +3807,6 @@
  * Valid errors:
  *  RIL_E_SUCCESS
  *  RIL_E_RADIO_NOT_AVAILABLE (radio resetting)
- *  RIL_E_GENERIC_FAILURE
  */
 #define RIL_REQUEST_STK_SET_PROFILE 68
 
@@ -3826,7 +3828,6 @@
  *  RIL_E_RADIO_NOT_AVAILABLE (radio resetting)
  *  SIM_BUSY
  *  OPERATION_NOT_ALLOWED
- *  RIL_E_GENERIC_FAILURE
  */
 #define RIL_REQUEST_STK_SEND_ENVELOPE_COMMAND 69
 
@@ -3845,7 +3846,6 @@
  *  RIL_E_SUCCESS
  *  RIL_E_RADIO_NOT_AVAILABLE (radio resetting)
  *  RIL_E_OPERATION_NOT_ALLOWED
- *  RIL_E_GENERIC_FAILURE
  */
 #define RIL_REQUEST_STK_SEND_TERMINAL_RESPONSE 70
 
@@ -3867,7 +3867,6 @@
  *  RIL_E_SUCCESS
  *  RIL_E_RADIO_NOT_AVAILABLE (radio resetting)
  *  RIL_E_OPERATION_NOT_ALLOWED
- *  RIL_E_GENERIC_FAILURE
  */
 #define RIL_REQUEST_STK_HANDLE_CALL_SETUP_REQUESTED_FROM_SIM 71
 
@@ -4215,7 +4214,6 @@
  * fails. The CDMA error class is derived as follows,
  * SUCCESS is error class 0 (no error)
  * SMS_SEND_FAIL_RETRY is error class 2 (temporary failure)
- * and GENERIC_FAILURE is error class 3 (permanent and no retry)
  *
  * Valid errors:
  *  SUCCESS
@@ -4703,7 +4701,6 @@
  *  RIL_E_RADIO_NOT_AVAILABLE (radio resetting)
  *  SIM_BUSY
  *  OPERATION_NOT_ALLOWED
- *  RIL_E_GENERIC_FAILURE
  */
 #define RIL_REQUEST_STK_SEND_ENVELOPE_WITH_STATUS 107
 
@@ -4711,7 +4708,7 @@
  * RIL_REQUEST_VOICE_RADIO_TECH
  *
  * Query the radio technology type (3GPP/3GPP2) used for voice. Query is valid only
- * when radio state is RADIO_STATE_ON
+ * when radio state is not RADIO_STATE_UNAVAILABLE
  *
  * "data" is NULL
  * "response" is int *
@@ -5220,7 +5217,6 @@
  *
  * SUCCESS
  * RADIO_NOT_AVAILABLE (radio resetting)
- * GENERIC_FAILURE
  */
 #define RIL_REQUEST_GET_ACTIVITY_INFO 135
 
@@ -5994,6 +5990,29 @@
   */
 #define RIL_UNSOL_PCO_DATA 1046
 
+ /**
+  * RIL_UNSOL_MODEM_RESTART
+  *
+  * Called when there is a modem reset.
+  *
+  * "reason" is "const char *" containing the reason for the reset. It
+  * could be a crash signature if the restart was due to a crash or some
+  * string such as "user-initiated restart" or "AT command initiated
+  * restart" that explains the cause of the modem restart.
+  *
+  * When modem restarts, one of the following radio state transitions will happen
+  * 1) RADIO_STATE_ON->RADIO_STATE_UNAVAILABLE->RADIO_STATE_ON or
+  * 2) RADIO_STATE_OFF->RADIO_STATE_UNAVAILABLE->RADIO_STATE_OFF
+  * This message can be sent either just before the RADIO_STATE changes to RADIO_STATE_UNAVAILABLE
+  * or just after but should never be sent after the RADIO_STATE changes from UNAVAILABLE to
+  * AVAILABLE(RADIO_STATE_ON/RADIO_STATE_OFF) again.
+  *
+  * It should NOT be sent after the RADIO_STATE changes to AVAILABLE after the
+  * modem restart as that could be interpreted as a second modem reset by the
+  * framework.
+  */
+#define RIL_UNSOL_MODEM_RESTART 1047
+
 /**
  * RIL_UNSOL_CARRIER_INFO_IMSI_ENCRYPTION
  *
@@ -6003,7 +6022,7 @@
  * "data" is NULL
  *
  */
-#define RIL_UNSOL_CARRIER_INFO_IMSI_ENCRYPTION 1047
+#define RIL_UNSOL_CARRIER_INFO_IMSI_ENCRYPTION 1048
 
 /***********************************************************************/
 
diff --git a/libril/Android.mk b/libril/Android.mk
index 27083ef..705a1a0 100644
--- a/libril/Android.mk
+++ b/libril/Android.mk
@@ -45,24 +45,3 @@
 
 include $(BUILD_SHARED_LIBRARY)
 
-
-# For RdoServD which needs a static library
-# =========================================
-ifneq ($(ANDROID_BIONIC_TRANSITION),)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
-    ril.cpp
-
-LOCAL_STATIC_LIBRARIES := \
-    libutils_static \
-    libcutils \
-    librilutils_static \
-    libprotobuf-c-nano-enable_malloc
-
-LOCAL_CFLAGS += -Wno-unused-parameter
-
-LOCAL_MODULE:= libril_static
-
-include $(BUILD_STATIC_LIBRARY)
-endif # ANDROID_BIONIC_TRANSITION
diff --git a/libril/RilSapSocket.cpp b/libril/RilSapSocket.cpp
index 02db4ad..cf99773 100644
--- a/libril/RilSapSocket.cpp
+++ b/libril/RilSapSocket.cpp
@@ -78,7 +78,9 @@
        const void *data,
        size_t datalen) {
     RilSapSocket *sap_socket = getSocketById(RIL_SOCKET_1);
-    sap_socket->onUnsolicitedResponse(unsolResponse, (void *)data, datalen);
+    if(sap_socket){
+        sap_socket->onUnsolicitedResponse(unsolResponse, (void *)data, datalen);
+    }
 }
 #endif
 
diff --git a/libril/ril.cpp b/libril/ril.cpp
index bd5e02e..b791e0d 100644
--- a/libril/ril.cpp
+++ b/libril/ril.cpp
@@ -1219,6 +1219,7 @@
         case RIL_UNSOL_HARDWARE_CONFIG_CHANGED: return "UNSOL_HARDWARE_CONFIG_CHANGED";
         case RIL_UNSOL_DC_RT_INFO_CHANGED: return "UNSOL_DC_RT_INFO_CHANGED";
         case RIL_UNSOL_RADIO_CAPABILITY: return "UNSOL_RADIO_CAPABILITY";
+        case RIL_UNSOL_MODEM_RESTART: return "UNSOL_MODEM_RESTART";
         case RIL_UNSOL_CARRIER_INFO_IMSI_ENCRYPTION: return "UNSOL_CARRIER_INFO_IMSI_ENCRYPTION";
         case RIL_UNSOL_ON_SS: return "UNSOL_ON_SS";
         case RIL_UNSOL_STK_CC_ALPHA_NOTIFY: return "UNSOL_STK_CC_ALPHA_NOTIFY";
@@ -1251,4 +1252,4 @@
     }
 }
 
-} /* namespace android */
\ No newline at end of file
+} /* namespace android */
diff --git a/libril/ril_unsol_commands.h b/libril/ril_unsol_commands.h
index 03a1c14..a551da7 100644
--- a/libril/ril_unsol_commands.h
+++ b/libril/ril_unsol_commands.h
@@ -61,4 +61,5 @@
     {RIL_UNSOL_STK_CC_ALPHA_NOTIFY, radio::stkCallControlAlphaNotifyInd, WAKE_PARTIAL},
     {RIL_UNSOL_LCEDATA_RECV, radio::lceDataInd, WAKE_PARTIAL},
     {RIL_UNSOL_PCO_DATA, radio::pcoDataInd, WAKE_PARTIAL},
+    {RIL_UNSOL_MODEM_RESTART, radio::modemResetInd, WAKE_PARTIAL},
     {RIL_UNSOL_CARRIER_INFO_IMSI_ENCRYPTION, radio::carrierInfoForImsiEncryption, WAKE_PARTIAL},
diff --git a/reference-ril/atchannel.c b/reference-ril/atchannel.c
index 5dc3e3c..0041836 100644
--- a/reference-ril/atchannel.c
+++ b/reference-ril/atchannel.c
@@ -61,12 +61,17 @@
 #endif
 
 /*
- * for current pending command
- * these are protected by s_commandmutex
+ * There is one reader thread |s_tid_reader| and potentially multiple writer
+ * threads. |s_commandmutex| and |s_commandcond| are used to maintain the
+ * condition that the writer thread will not read from |sp_response| until the
+ * reader thread has signaled itself is finished, etc. |s_writeMutex| is used to
+ * prevent multiple writer threads from calling at_send_command_full_nolock
+ * function at the same time.
  */
 
 static pthread_mutex_t s_commandmutex = PTHREAD_MUTEX_INITIALIZER;
 static pthread_cond_t s_commandcond = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t s_writeMutex = PTHREAD_MUTEX_INITIALIZER;
 
 static ATCommandType s_type;
 static const char *s_responsePrefix = NULL;
@@ -736,12 +741,16 @@
                     long long timeoutMsec, ATResponse **pp_outResponse)
 {
     int err;
+    bool inEmulator;
 
     if (0 != pthread_equal(s_tid_reader, pthread_self())) {
         /* cannot be called from reader thread */
         return AT_ERROR_INVALID_THREAD;
     }
-
+    inEmulator = isInEmulator();
+    if (inEmulator) {
+        pthread_mutex_lock(&s_writeMutex);
+    }
     pthread_mutex_lock(&s_commandmutex);
 
     err = at_send_command_full_nolock(command, type,
@@ -749,6 +758,9 @@
                     timeoutMsec, pp_outResponse);
 
     pthread_mutex_unlock(&s_commandmutex);
+    if (inEmulator) {
+        pthread_mutex_unlock(&s_writeMutex);
+    }
 
     if (err == AT_ERROR_TIMEOUT && s_onTimeout != NULL) {
         s_onTimeout();
@@ -888,12 +900,16 @@
 {
     int i;
     int err = 0;
+    bool inEmulator;
 
     if (0 != pthread_equal(s_tid_reader, pthread_self())) {
         /* cannot be called from reader thread */
         return AT_ERROR_INVALID_THREAD;
     }
-
+    inEmulator = isInEmulator();
+    if (inEmulator) {
+        pthread_mutex_lock(&s_writeMutex);
+    }
     pthread_mutex_lock(&s_commandmutex);
 
     for (i = 0 ; i < HANDSHAKE_RETRY_COUNT ; i++) {
@@ -914,6 +930,9 @@
     }
 
     pthread_mutex_unlock(&s_commandmutex);
+    if (inEmulator) {
+        pthread_mutex_unlock(&s_writeMutex);
+    }
 
     return err;
 }
diff --git a/reference-ril/misc.c b/reference-ril/misc.c
index e4b8d72..c0e9b6e 100644
--- a/reference-ril/misc.c
+++ b/reference-ril/misc.c
@@ -14,7 +14,9 @@
 ** See the License for the specific language governing permissions and
 ** limitations under the License.
 */
+#include <sys/system_properties.h>
 
+#include "misc.h"
 /** returns 1 if line starts with prefix, 0 if it does not */
 int strStartsWith(const char *line, const char *prefix)
 {
@@ -27,3 +29,12 @@
     return *prefix == '\0';
 }
 
+// Returns true iff running this process in an emulator VM
+bool isInEmulator(void) {
+  static int inQemu = -1;
+  if (inQemu < 0) {
+      char propValue[PROP_VALUE_MAX];
+      inQemu = (__system_property_get("ro.kernel.qemu", propValue) != 0);
+  }
+  return inQemu == 1;
+}
diff --git a/reference-ril/misc.h b/reference-ril/misc.h
index 7044a07..9e65ab3 100644
--- a/reference-ril/misc.h
+++ b/reference-ril/misc.h
@@ -14,6 +14,9 @@
 ** See the License for the specific language governing permissions and
 ** limitations under the License.
 */
+#include <stdbool.h>
 
 /** returns 1 if line starts with prefix, 0 if it does not */
 int strStartsWith(const char *line, const char *prefix);
+/** Returns true iff running this process in an emulator VM */
+bool isInEmulator(void);
\ No newline at end of file
diff --git a/reference-ril/reference-ril.c b/reference-ril/reference-ril.c
index 16a279c..9b9c624 100644
--- a/reference-ril/reference-ril.c
+++ b/reference-ril/reference-ril.c
@@ -17,7 +17,6 @@
 
 #include <telephony/ril_cdma_sms.h>
 #include <telephony/librilutils.h>
-#include <stdbool.h>
 #include <stdio.h>
 #include <assert.h>
 #include <string.h>
@@ -26,6 +25,7 @@
 #include <sys/cdefs.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <inttypes.h>
 #include <fcntl.h>
 #include <pthread.h>
 #include <alloca.h>
@@ -35,8 +35,8 @@
 #include <getopt.h>
 #include <sys/socket.h>
 #include <cutils/sockets.h>
-#include <termios.h>
 #include <sys/system_properties.h>
+#include <termios.h>
 #include <system/qemu_pipe.h>
 
 #include "ril.h"
@@ -240,15 +240,6 @@
 static int s_expectAnswer = 0;
 #endif /* WORKAROUND_ERRONEOUS_ANSWER */
 
-// Returns true iff running this process in an emulator VM
-static bool isInEmulator(void) {
-    static int inQemu = -1;
-    if (inQemu < 0) {
-        char propValue[PROP_VALUE_MAX];
-        inQemu = (__system_property_get("ro.kernel.qemu", propValue) != 0);
-    }
-    return inQemu == 1;
-}
 
 static int s_cell_info_rate_ms = INT_MAX;
 static int s_mcc = 0;
@@ -340,6 +331,22 @@
     return -1;
 }
 
+static int parseSimResponseLine(char* line, RIL_SIM_IO_Response* response) {
+    int err;
+
+    err = at_tok_start(&line);
+    if (err < 0) return err;
+    err = at_tok_nextint(&line, &response->sw1);
+    if (err < 0) return err;
+    err = at_tok_nextint(&line, &response->sw2);
+    if (err < 0) return err;
+
+    if (at_tok_hasmore(&line)) {
+        err = at_tok_nextstr(&line, &response->simResponse);
+        if (err < 0) return err;
+    }
+    return 0;
+}
 
 /** do post-AT+CFUN=1 initialization */
 static void onRadioPowerOn()
@@ -543,23 +550,27 @@
         err = at_tok_nextstr(&line, &out);
         if (err < 0)
             goto error;
-        responses[i].type = alloca(strlen(out) + 1);
-        strcpy(responses[i].type, out);
+
+        int type_size = strlen(out) + 1;
+        responses[i].type = alloca(type_size);
+        strlcpy(responses[i].type, out, type_size);
 
         // APN ignored for v5
         err = at_tok_nextstr(&line, &out);
         if (err < 0)
             goto error;
 
-        responses[i].ifname = alloca(strlen(PPP_TTY_PATH) + 1);
-        strcpy(responses[i].ifname, PPP_TTY_PATH);
+        int ifname_size = strlen(PPP_TTY_PATH) + 1;
+        responses[i].ifname = alloca(ifname_size);
+        strlcpy(responses[i].ifname, PPP_TTY_PATH, ifname_size);
 
         err = at_tok_nextstr(&line, &out);
         if (err < 0)
             goto error;
 
-        responses[i].addresses = alloca(strlen(out) + 1);
-        strcpy(responses[i].addresses, out);
+        int addresses_size = strlen(out) + 1;
+        responses[i].addresses = alloca(addresses_size);
+        strlcpy(responses[i].addresses, out, addresses_size);
 
         if (isInEmulator()) {
             /* We are in the emulator - the dns servers are listed
@@ -1653,6 +1664,119 @@
     RIL_onRequestComplete(t, RIL_E_SMS_SEND_FAIL_RETRY, &response, sizeof(response));
 }
 
+static void requestSimOpenChannel(void *data, size_t datalen, RIL_Token t)
+{
+    ATResponse *p_response = NULL;
+    int32_t session_id;
+    int err;
+    char cmd[32];
+    char dummy;
+    char *line;
+
+    // Max length is 16 bytes according to 3GPP spec 27.007 section 8.45
+    if (data == NULL || datalen == 0 || datalen > 16) {
+        ALOGE("Invalid data passed to requestSimOpenChannel");
+        RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
+        return;
+    }
+
+    snprintf(cmd, sizeof(cmd), "AT+CCHO=%s", data);
+
+    err = at_send_command_numeric(cmd, &p_response);
+    if (err < 0 || p_response == NULL || p_response->success == 0) {
+        ALOGE("Error %d opening logical channel: %d",
+              err, p_response ? p_response->success : 0);
+        RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
+        at_response_free(p_response);
+        return;
+    }
+
+    // Ensure integer only by scanning for an extra char but expect one result
+    line = p_response->p_intermediates->line;
+    if (sscanf(line, "%" SCNd32 "%c", &session_id, &dummy) != 1) {
+        ALOGE("Invalid AT response, expected integer, was '%s'", line);
+        RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
+        return;
+    }
+
+    RIL_onRequestComplete(t, RIL_E_SUCCESS, &session_id, sizeof(&session_id));
+    at_response_free(p_response);
+}
+
+static void requestSimCloseChannel(void *data, size_t datalen, RIL_Token t)
+{
+    ATResponse *p_response = NULL;
+    int32_t session_id;
+    int err;
+    char cmd[32];
+
+    if (data == NULL || datalen != sizeof(session_id)) {
+        ALOGE("Invalid data passed to requestSimCloseChannel");
+        RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
+        return;
+    }
+    session_id = ((int32_t *)data)[0];
+    snprintf(cmd, sizeof(cmd), "AT+CCHC=%" PRId32, session_id);
+    err = at_send_command_singleline(cmd, "+CCHC", &p_response);
+
+    if (err < 0 || p_response == NULL || p_response->success == 0) {
+        ALOGE("Error %d closing logical channel %d: %d",
+              err, session_id, p_response ? p_response->success : 0);
+        RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
+        at_response_free(p_response);
+        return;
+    }
+
+    RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
+
+    at_response_free(p_response);
+}
+
+static void requestSimTransmitApduChannel(void *data,
+                                          size_t datalen,
+                                          RIL_Token t)
+{
+    ATResponse *p_response = NULL;
+    int err;
+    char *cmd;
+    char *line;
+    size_t cmd_size;
+    RIL_SIM_IO_Response sim_response;
+    RIL_SIM_APDU *apdu = (RIL_SIM_APDU *)data;
+
+    if (apdu == NULL || datalen != sizeof(RIL_SIM_APDU)) {
+        RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
+        return;
+    }
+
+    cmd_size = 10 + (apdu->data ? strlen(apdu->data) : 0);
+    asprintf(&cmd, "AT+CGLA=%d,%zu,%02x%02x%02x%02x%02x%s",
+             apdu->sessionid, cmd_size, apdu->cla, apdu->instruction,
+             apdu->p1, apdu->p2, apdu->p3, apdu->data ? apdu->data : "");
+
+    err = at_send_command_singleline(cmd, "+CGLA", &p_response);
+    free(cmd);
+    if (err < 0 || p_response == NULL || p_response->success == 0) {
+        ALOGE("Error %d transmitting APDU: %d",
+              err, p_response ? p_response->success : 0);
+        RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
+        at_response_free(p_response);
+        return;
+    }
+
+    line = p_response->p_intermediates->line;
+    err = parseSimResponseLine(line, &sim_response);
+
+    if (err == 0) {
+        RIL_onRequestComplete(t, RIL_E_SUCCESS,
+                              &sim_response, sizeof(sim_response));
+    } else {
+        ALOGE("Error %d parsing SIM response line: %s", err, line);
+        RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
+    }
+    at_response_free(p_response);
+}
+
 static void requestSetupDataCall(void *data, size_t datalen, RIL_Token t)
 {
     const char *apn;
@@ -1831,18 +1955,9 @@
 
     line = p_response->p_intermediates->line;
 
-    err = at_tok_start(&line);
-    if (err < 0) goto error;
-
-    err = at_tok_nextint(&line, &(sr.sw1));
-    if (err < 0) goto error;
-
-    err = at_tok_nextint(&line, &(sr.sw2));
-    if (err < 0) goto error;
-
-    if (at_tok_hasmore(&line)) {
-        err = at_tok_nextstr(&line, &(sr.simResponse));
-        if (err < 0) goto error;
+    err = parseSimResponseLine(line, &sr);
+    if (err < 0) {
+        goto error;
     }
 
     RIL_onRequestComplete(t, RIL_E_SUCCESS, &sr, sizeof(sr));
@@ -2002,9 +2117,9 @@
  * RIL_onRequestComplete() may be called from any thread, before or after
  * this function returns.
  *
- * Will always be called from the same thread, so returning here implies
- * that the radio is ready to process another command (whether or not
- * the previous command has completed).
+ * Because onRequest function could be called from multiple different thread,
+ * we must ensure that the underlying at_send_command_* function
+ * is atomic.
  */
 static void
 onRequest (int request, void *data, size_t datalen, RIL_Token t)
@@ -2176,6 +2291,15 @@
         case RIL_REQUEST_IMS_SEND_SMS:
             requestImsSendSMS(data, datalen, t);
             break;
+        case RIL_REQUEST_SIM_OPEN_CHANNEL:
+            requestSimOpenChannel(data, datalen, t);
+            break;
+        case RIL_REQUEST_SIM_CLOSE_CHANNEL:
+            requestSimCloseChannel(data, datalen, t);
+            break;
+        case RIL_REQUEST_SIM_TRANSMIT_APDU_CHANNEL:
+            requestSimTransmitApduChannel(data, datalen, t);
+            break;
         case RIL_REQUEST_SETUP_DATA_CALL:
             requestSetupDataCall(data, datalen, t);
             break;
diff --git a/rild/Android.mk b/rild/Android.mk
index fe81d22..abcc522 100644
--- a/rild/Android.mk
+++ b/rild/Android.mk
@@ -6,14 +6,13 @@
 LOCAL_SRC_FILES:= \
 	rild.c
 
-
 LOCAL_SHARED_LIBRARIES := \
-	liblog \
 	libcutils \
-	libril \
-	libdl
+	libdl \
+	liblog \
+	libril
 
-# temporary hack for broken vendor rils
+# Temporary hack for broken vendor RILs.
 LOCAL_WHOLE_STATIC_LIBRARIES := \
 	librilutils_static
 
diff --git a/rild/rild.c b/rild/rild.c
index ce04040..fb4955a 100644
--- a/rild/rild.c
+++ b/rild/rild.c
@@ -40,7 +40,6 @@
 #define LIB_PATH_PROPERTY   "rild.libpath"
 #define LIB_ARGS_PROPERTY   "rild.libargs"
 #define MAX_LIB_ARGS        16
-#define MAX_CAP_NUM         (CAP_TO_INDEX(CAP_LAST_CAP) + 1)
 
 static void usage(const char *argv0) {
     fprintf(stderr, "Usage: %s -l <ril impl library> [-- <args for impl library>]\n", argv0);
@@ -98,54 +97,9 @@
     return count;
 }
 
-/*
- * switchUser - Switches UID to radio, preserving CAP_NET_ADMIN capabilities.
- * Our group, cache, was set by init.
- */
-void switchUser() {
-    char debuggable[PROP_VALUE_MAX];
-
-    prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
-    if (setresuid(AID_RADIO, AID_RADIO, AID_RADIO) == -1) {
-        RLOGE("setresuid failed: %s", strerror(errno));
-        exit(EXIT_FAILURE);
-    }
-
-    struct __user_cap_header_struct header;
-    memset(&header, 0, sizeof(header));
-    header.version = _LINUX_CAPABILITY_VERSION_3;
-    header.pid = 0;
-
-    struct __user_cap_data_struct data[MAX_CAP_NUM];
-    memset(&data, 0, sizeof(data));
-
-    data[CAP_TO_INDEX(CAP_NET_ADMIN)].effective |= CAP_TO_MASK(CAP_NET_ADMIN);
-    data[CAP_TO_INDEX(CAP_NET_ADMIN)].permitted |= CAP_TO_MASK(CAP_NET_ADMIN);
-
-    data[CAP_TO_INDEX(CAP_NET_RAW)].effective |= CAP_TO_MASK(CAP_NET_RAW);
-    data[CAP_TO_INDEX(CAP_NET_RAW)].permitted |= CAP_TO_MASK(CAP_NET_RAW);
-
-    data[CAP_TO_INDEX(CAP_BLOCK_SUSPEND)].effective |= CAP_TO_MASK(CAP_BLOCK_SUSPEND);
-    data[CAP_TO_INDEX(CAP_BLOCK_SUSPEND)].permitted |= CAP_TO_MASK(CAP_BLOCK_SUSPEND);
-
-    if (capset(&header, &data[0]) == -1) {
-        RLOGE("capset failed: %s", strerror(errno));
-        exit(EXIT_FAILURE);
-    }
-
-    /*
-     * Debuggable build only:
-     * Set DUMPABLE that was cleared by setuid() to have tombstone on RIL crash
-     */
-    property_get("ro.debuggable", debuggable, "0");
-    if (strcmp(debuggable, "1") == 0) {
-        prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
-    }
-}
-
 int main(int argc, char **argv) {
     // vendor ril lib path either passed in as -l parameter, or read from rild.libpath property
-    const char * rilLibPath = NULL;
+    const char *rilLibPath = NULL;
     // ril arguments either passed in as -- parameter, or read from rild.libargs property
     char **rilArgv;
     // handle for vendor ril lib
@@ -209,8 +163,6 @@
         }
     }
 
-    switchUser();
-
     dlHandle = dlopen(rilLibPath, RTLD_NOW);
 
     if (dlHandle == NULL) {
@@ -252,7 +204,7 @@
     }
 
     rilArgv[argc++] = "-c";
-    rilArgv[argc++] = clientId;
+    rilArgv[argc++] = (char*)clientId;
     RLOGD("RIL_Init argc = %d clientId = %s", argc, rilArgv[argc-1]);
 
     // Make sure there's a reasonable argv[0]
diff --git a/rild/rild.rc b/rild/rild.rc
index 2aa8c63..b27e1da 100644
--- a/rild/rild.rc
+++ b/rild/rild.rc
@@ -1,4 +1,5 @@
 service ril-daemon /vendor/bin/hw/rild
     class main
-    user root
+    user radio
     group radio cache inet misc audio log readproc wakelock
+    capabilities BLOCK_SUSPEND NET_ADMIN NET_RAW