Snap for 8426163 from 2d9d13e7a03633a46a6d830c127813e8dfa60e29 to mainline-tzdata2-release

Change-Id: I497fc3ed24f0b3f8a4f770e6188e3a11bdd6c827
diff --git a/Android.bp b/Android.bp
index b710333..cffa338 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1,18 +1,3 @@
-package {
-    default_applicable_licenses: ["hardware_ril_license"],
-}
-
-// Added automatically by a large-scale-change
-// See: http://go/android-license-faq
-license {
-    name: "hardware_ril_license",
-    visibility: [":__subpackages__"],
-    license_kinds: [
-        "SPDX-license-identifier-Apache-2.0",
-    ],
-    // large-scale-change unable to identify any license_text files
-}
-
 cc_library_headers {
     name: "ril_headers",
     vendor: true,
diff --git a/METADATA b/METADATA
deleted file mode 100644
index d97975c..0000000
--- a/METADATA
+++ /dev/null
@@ -1,3 +0,0 @@
-third_party {
-  license_type: NOTICE
-}
diff --git a/include/telephony/ril.h b/include/telephony/ril.h
index c879873..7530146 100644
--- a/include/telephony/ril.h
+++ b/include/telephony/ril.h
@@ -743,8 +743,8 @@
 typedef struct {
   int32_t len_allowed_carriers;         /* length of array allowed_carriers */
   int32_t len_excluded_carriers;        /* length of array excluded_carriers */
-  RIL_Carrier * allowed_carriers;       /* list of allowed carriers */
-  RIL_Carrier * excluded_carriers;      /* list of explicitly excluded carriers
+  RIL_Carrier * allowed_carriers;       /* whitelist for allowed carriers */
+  RIL_Carrier * excluded_carriers;      /* blacklist for explicitly excluded carriers
                                          * which match allowed_carriers. Eg. allowed_carriers match
                                          * mcc/mnc, excluded_carriers has same mcc/mnc and gid1
                                          * is ABCD. It means except the carrier whose gid1 is ABCD,
diff --git a/libril/Android.mk b/libril/Android.mk
index 12b58cf..87319bf 100644
--- a/libril/Android.mk
+++ b/libril/Android.mk
@@ -20,6 +20,7 @@
     librilutils \
     android.hardware.radio@1.0 \
     android.hardware.radio@1.1 \
+    android.hardware.radio.deprecated@1.0 \
     libhidlbase \
 
 LOCAL_STATIC_LIBRARIES := \
@@ -42,9 +43,7 @@
 LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/../include
 
 LOCAL_MODULE:= libril
-LOCAL_LICENSE_KINDS:= SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS:= notice
-LOCAL_NOTICE_FILE:= $(LOCAL_PATH)/NOTICE
 LOCAL_SANITIZE := integer
 
 include $(BUILD_SHARED_LIBRARY)
+
diff --git a/libril/ril.cpp b/libril/ril.cpp
index 074a858..214fa10 100644
--- a/libril/ril.cpp
+++ b/libril/ril.cpp
@@ -1081,6 +1081,8 @@
         case RIL_REQUEST_LAST_DATA_CALL_FAIL_CAUSE: return "LAST_DATA_CALL_FAIL_CAUSE";
         case RIL_REQUEST_DATA_CALL_LIST: return "DATA_CALL_LIST";
         case RIL_REQUEST_RESET_RADIO: return "RESET_RADIO";
+        case RIL_REQUEST_OEM_HOOK_RAW: return "OEM_HOOK_RAW";
+        case RIL_REQUEST_OEM_HOOK_STRINGS: return "OEM_HOOK_STRINGS";
         case RIL_REQUEST_SCREEN_STATE: return "SCREEN_STATE";
         case RIL_REQUEST_SET_SUPP_SVC_NOTIFICATION: return "SET_SUPP_SVC_NOTIFICATION";
         case RIL_REQUEST_WRITE_SMS_TO_SIM: return "WRITE_SMS_TO_SIM";
diff --git a/libril/ril_commands.h b/libril/ril_commands.h
index bd0f6f7..94c2a26 100644
--- a/libril/ril_commands.h
+++ b/libril/ril_commands.h
@@ -73,8 +73,8 @@
     {RIL_REQUEST_LAST_DATA_CALL_FAIL_CAUSE, NULL},
     {RIL_REQUEST_DATA_CALL_LIST, radio::getDataCallListResponse},
     {RIL_REQUEST_RESET_RADIO, NULL},
-    {RIL_REQUEST_OEM_HOOK_RAW, NULL},
-    {RIL_REQUEST_OEM_HOOK_STRINGS, NULL},
+    {RIL_REQUEST_OEM_HOOK_RAW, radio::sendRequestRawResponse},
+    {RIL_REQUEST_OEM_HOOK_STRINGS, radio::sendRequestStringsResponse},
     {RIL_REQUEST_SCREEN_STATE, radio::sendDeviceStateResponse},   // Note the response function is different.
     {RIL_REQUEST_SET_SUPP_SVC_NOTIFICATION, radio::setSuppServiceNotificationsResponse},
     {RIL_REQUEST_WRITE_SMS_TO_SIM, radio::writeSmsToSimResponse},
diff --git a/libril/ril_service.cpp b/libril/ril_service.cpp
index 8009d47..c97b607 100755
--- a/libril/ril_service.cpp
+++ b/libril/ril_service.cpp
@@ -21,6 +21,8 @@
 #include <android/hardware/radio/1.1/IRadioIndication.h>
 #include <android/hardware/radio/1.1/types.h>
 
+#include <android/hardware/radio/deprecated/1.0/IOemHook.h>
+
 #include <hwbinder/IPCThreadState.h>
 #include <hwbinder/ProcessState.h>
 #include <telephony/ril.h>
@@ -35,6 +37,7 @@
 
 using namespace android::hardware::radio;
 using namespace android::hardware::radio::V1_0;
+using namespace android::hardware::radio::deprecated::V1_0;
 using ::android::hardware::configureRpcThreadpool;
 using ::android::hardware::joinRpcThreadpool;
 using ::android::hardware::Return;
@@ -60,21 +63,32 @@
 #define CALL_ONSTATEREQUEST(a) s_vendorFunctions->onStateRequest()
 #endif
 
+#ifdef OEM_HOOK_DISABLED
+constexpr bool kOemHookEnabled = false;
+#else
+constexpr bool kOemHookEnabled = true;
+#endif
+
 RIL_RadioFunctions *s_vendorFunctions = NULL;
 static CommandInfo *s_commands;
 
 struct RadioImpl;
+struct OemHookImpl;
 
 #if (SIM_COUNT >= 2)
 sp<RadioImpl> radioService[SIM_COUNT];
+sp<OemHookImpl> oemHookService[SIM_COUNT];
 int64_t nitzTimeReceived[SIM_COUNT];
 // counter used for synchronization. It is incremented every time response callbacks are updated.
 volatile int32_t mCounterRadio[SIM_COUNT];
+volatile int32_t mCounterOemHook[SIM_COUNT];
 #else
 sp<RadioImpl> radioService[1];
+sp<OemHookImpl> oemHookService[1];
 int64_t nitzTimeReceived[1];
 // counter used for synchronization. It is incremented every time response callbacks are updated.
 volatile int32_t mCounterRadio[1];
+volatile int32_t mCounterOemHook[1];
 #endif
 
 static pthread_rwlock_t radioServiceRwlock = PTHREAD_RWLOCK_INITIALIZER;
@@ -451,6 +465,22 @@
     void checkReturnStatus(Return<void>& ret);
 };
 
+struct OemHookImpl : public IOemHook {
+    int32_t mSlotId;
+    sp<IOemHookResponse> mOemHookResponse;
+    sp<IOemHookIndication> mOemHookIndication;
+
+    Return<void> setResponseFunctions(
+            const ::android::sp<IOemHookResponse>& oemHookResponse,
+            const ::android::sp<IOemHookIndication>& oemHookIndication);
+
+    Return<void> sendRequestRaw(int32_t serial,
+            const ::android::hardware::hidl_vec<uint8_t>& data);
+
+    Return<void> sendRequestStrings(int32_t serial,
+            const ::android::hardware::hidl_vec<::android::hardware::hidl_string>& data);
+};
+
 void memsetAndFreeStrings(int numPointers, ...) {
     va_list ap;
     va_start(ap, numPointers);
@@ -732,7 +762,7 @@
         // Caller should already hold rdlock, release that first
         // note the current counter to avoid overwriting updates made by another thread before
         // write lock is acquired.
-        int counter = mCounterRadio[slotId];
+        int counter = isRadioService ? mCounterRadio[slotId] : mCounterOemHook[slotId];
         pthread_rwlock_t *radioServiceRwlockPtr = radio::getRadioServiceRwlock(slotId);
         int ret = pthread_rwlock_unlock(radioServiceRwlockPtr);
         assert(ret == 0);
@@ -742,12 +772,17 @@
         assert(ret == 0);
 
         // make sure the counter value has not changed
-        if (counter == mCounterRadio[slotId]) {
-            radioService[slotId]->mRadioResponse = NULL;
-            radioService[slotId]->mRadioIndication = NULL;
-            radioService[slotId]->mRadioResponseV1_1 = NULL;
-            radioService[slotId]->mRadioIndicationV1_1 = NULL;
-            mCounterRadio[slotId]++;
+        if (counter == (isRadioService ? mCounterRadio[slotId] : mCounterOemHook[slotId])) {
+            if (isRadioService) {
+                radioService[slotId]->mRadioResponse = NULL;
+                radioService[slotId]->mRadioIndication = NULL;
+                radioService[slotId]->mRadioResponseV1_1 = NULL;
+                radioService[slotId]->mRadioIndicationV1_1 = NULL;
+            } else {
+                oemHookService[slotId]->mOemHookResponse = NULL;
+                oemHookService[slotId]->mOemHookIndication = NULL;
+            }
+            isRadioService ? mCounterRadio[slotId]++ : mCounterOemHook[slotId]++;
         } else {
             RLOGE("checkReturnStatus: not resetting responseFunctions as they likely "
                     "got updated on another thread");
@@ -1763,21 +1798,17 @@
         return Void();
     }
 
-    uint32_t num = configInfo.size();
+    int num = configInfo.size();
     if (num > MAX_BROADCAST_SMS_CONFIG_INFO) {
         RLOGE("setGsmBroadcastConfig: Invalid configInfo length %s",
                 requestToString(pRI->pCI->requestNumber));
         sendErrorResponse(pRI, RIL_E_INVALID_ARGUMENTS);
         return Void();
     }
-    auto gsmBci = new RIL_GSM_BroadcastSmsConfigInfo[num];
-    if (gsmBci == nullptr) {
-        sendErrorResponse(pRI, RIL_E_NO_MEMORY);
-        return Void();
-    }
-    std::vector<RIL_GSM_BroadcastSmsConfigInfo*> gsmBciPtrs(num);
+    RIL_GSM_BroadcastSmsConfigInfo gsmBci[num];
+    RIL_GSM_BroadcastSmsConfigInfo *gsmBciPtrs[num];
 
-    for (uint32_t i = 0 ; i < num ; i++ ) {
+    for (int i = 0 ; i < num ; i++ ) {
         gsmBciPtrs[i] = &gsmBci[i];
         gsmBci[i].fromServiceId = configInfo[i].fromServiceId;
         gsmBci[i].toServiceId = configInfo[i].toServiceId;
@@ -1786,10 +1817,8 @@
         gsmBci[i].selected = BOOL_TO_INT(configInfo[i].selected);
     }
 
-    CALL_ONREQUEST(pRI->pCI->requestNumber, gsmBciPtrs.data(),
+    CALL_ONREQUEST(pRI->pCI->requestNumber, gsmBciPtrs,
             num * sizeof(RIL_GSM_BroadcastSmsConfigInfo *), pRI, mSlotId);
-
-    delete []gsmBci;
     return Void();
 }
 
@@ -1822,30 +1851,25 @@
         return Void();
     }
 
-    uint32_t num = configInfo.size();
+    int num = configInfo.size();
     if (num > MAX_BROADCAST_SMS_CONFIG_INFO) {
         RLOGE("setCdmaBroadcastConfig: Invalid configInfo length %s",
                 requestToString(pRI->pCI->requestNumber));
         sendErrorResponse(pRI, RIL_E_INVALID_ARGUMENTS);
         return Void();
     }
-    auto cdmaBci = new RIL_CDMA_BroadcastSmsConfigInfo[num];
-    if (cdmaBci == nullptr) {
-        sendErrorResponse(pRI, RIL_E_NO_MEMORY);
-        return Void();
-    }
-    std::vector<RIL_CDMA_BroadcastSmsConfigInfo*> cdmaBciPtrs(num);
-    for (uint32_t i = 0 ; i < num ; i++ ) {
+    RIL_CDMA_BroadcastSmsConfigInfo cdmaBci[num];
+    RIL_CDMA_BroadcastSmsConfigInfo *cdmaBciPtrs[num];
+
+    for (int i = 0 ; i < num ; i++ ) {
         cdmaBciPtrs[i] = &cdmaBci[i];
         cdmaBci[i].service_category = configInfo[i].serviceCategory;
         cdmaBci[i].language = configInfo[i].language;
         cdmaBci[i].selected = BOOL_TO_INT(configInfo[i].selected);
     }
 
-    CALL_ONREQUEST(pRI->pCI->requestNumber, cdmaBciPtrs.data(),
+    CALL_ONREQUEST(pRI->pCI->requestNumber, cdmaBciPtrs,
             num * sizeof(RIL_CDMA_BroadcastSmsConfigInfo *), pRI, mSlotId);
-
-    delete []cdmaBci;
     return Void();
 }
 
@@ -2197,9 +2221,11 @@
         return Void();
     }
 
-    if (RadioTechnologyFamily::THREE_GPP == message.tech) {
+    RIL_RadioTechnologyFamily format = (RIL_RadioTechnologyFamily) message.tech;
+
+    if (RADIO_TECH_3GPP == format) {
         dispatchImsGsmSms(message, pRI);
-    } else if (RadioTechnologyFamily::THREE_GPP2 == message.tech) {
+    } else if (RADIO_TECH_3GPP2 == format) {
         dispatchImsCdmaSms(message, pRI);
     } else {
         RLOGE("sendImsSms: Invalid radio tech %s",
@@ -2892,6 +2918,44 @@
     return Void();
 }
 
+Return<void> OemHookImpl::setResponseFunctions(
+        const ::android::sp<IOemHookResponse>& oemHookResponseParam,
+        const ::android::sp<IOemHookIndication>& oemHookIndicationParam) {
+#if VDBG
+    RLOGD("OemHookImpl::setResponseFunctions");
+#endif
+
+    pthread_rwlock_t *radioServiceRwlockPtr = radio::getRadioServiceRwlock(mSlotId);
+    int ret = pthread_rwlock_wrlock(radioServiceRwlockPtr);
+    assert(ret == 0);
+
+    mOemHookResponse = oemHookResponseParam;
+    mOemHookIndication = oemHookIndicationParam;
+    mCounterOemHook[mSlotId]++;
+
+    ret = pthread_rwlock_unlock(radioServiceRwlockPtr);
+    assert(ret == 0);
+
+    return Void();
+}
+
+Return<void> OemHookImpl::sendRequestRaw(int32_t serial, const hidl_vec<uint8_t>& data) {
+#if VDBG
+    RLOGD("OemHookImpl::sendRequestRaw: serial %d", serial);
+#endif
+    dispatchRaw(serial, mSlotId, RIL_REQUEST_OEM_HOOK_RAW, data);
+    return Void();
+}
+
+Return<void> OemHookImpl::sendRequestStrings(int32_t serial,
+        const hidl_vec<hidl_string>& data) {
+#if VDBG
+    RLOGD("OemHookImpl::sendRequestStrings: serial %d", serial);
+#endif
+    dispatchStrings(serial, mSlotId, RIL_REQUEST_OEM_HOOK_STRINGS, data);
+    return Void();
+}
+
 /***************************************************************************************************
  * RESPONSE FUNCTIONS
  * Functions above are used for requests going from framework to vendor code. The ones below are
@@ -5909,7 +5973,7 @@
         RadioResponseInfo responseInfo = {};
         populateResponseInfo(responseInfo, serial, responseType, e);
         bool isRegistered = false;
-        RadioTechnologyFamily ratFamily = RadioTechnologyFamily::THREE_GPP;
+        int ratFamily = 0;
         int numInts = responseLen / sizeof(int);
         if (response == NULL || numInts != 2) {
             RLOGE("getImsRegistrationStateResponse Invalid response: NULL");
@@ -5917,16 +5981,11 @@
         } else {
             int *pInt = (int *) response;
             isRegistered = pInt[0] == 1 ? true : false;
-            // Map RIL_RadioTechnologyFamily to RadioTechnologyFamily
-            if (pInt[1] == RADIO_TECH_3GPP) {
-                ratFamily = RadioTechnologyFamily::THREE_GPP;
-            } else {
-                ratFamily = RadioTechnologyFamily::THREE_GPP2;
-            }
+            ratFamily = pInt[1];
         }
         Return<void> retStatus
                 = radioService[slotId]->mRadioResponse->getImsRegistrationStateResponse(
-                responseInfo, isRegistered, ratFamily);
+                responseInfo, isRegistered, (RadioTechnologyFamily) ratFamily);
         radioService[slotId]->checkReturnStatus(retStatus);
     } else {
         RLOGE("getImsRegistrationStateResponse: radioService[%d]->mRadioResponse == NULL",
@@ -6727,6 +6786,74 @@
     return 0;
 }
 
+int radio::sendRequestRawResponse(int slotId,
+                                  int responseType, int serial, RIL_Errno e,
+                                  void *response, size_t responseLen) {
+#if VDBG
+   RLOGD("sendRequestRawResponse: serial %d", serial);
+#endif
+
+    if (!kOemHookEnabled) return 0;
+
+    if (oemHookService[slotId]->mOemHookResponse != NULL) {
+        RadioResponseInfo responseInfo = {};
+        populateResponseInfo(responseInfo, serial, responseType, e);
+        hidl_vec<uint8_t> data;
+
+        if (response == NULL) {
+            RLOGE("sendRequestRawResponse: Invalid response");
+            if (e == RIL_E_SUCCESS) responseInfo.error = RadioError::INVALID_RESPONSE;
+        } else {
+            data.setToExternal((uint8_t *) response, responseLen);
+        }
+        Return<void> retStatus = oemHookService[slotId]->mOemHookResponse->
+                sendRequestRawResponse(responseInfo, data);
+        checkReturnStatus(slotId, retStatus, false);
+    } else {
+        RLOGE("sendRequestRawResponse: oemHookService[%d]->mOemHookResponse == NULL",
+                slotId);
+    }
+
+    return 0;
+}
+
+int radio::sendRequestStringsResponse(int slotId,
+                                      int responseType, int serial, RIL_Errno e,
+                                      void *response, size_t responseLen) {
+#if VDBG
+    RLOGD("sendRequestStringsResponse: serial %d", serial);
+#endif
+
+    if (!kOemHookEnabled) return 0;
+
+    if (oemHookService[slotId]->mOemHookResponse != NULL) {
+        RadioResponseInfo responseInfo = {};
+        populateResponseInfo(responseInfo, serial, responseType, e);
+        hidl_vec<hidl_string> data;
+
+        if ((response == NULL && responseLen != 0) || responseLen % sizeof(char *) != 0) {
+            RLOGE("sendRequestStringsResponse Invalid response: NULL");
+            if (e == RIL_E_SUCCESS) responseInfo.error = RadioError::INVALID_RESPONSE;
+        } else {
+            char **resp = (char **) response;
+            int numStrings = responseLen / sizeof(char *);
+            data.resize(numStrings);
+            for (int i = 0; i < numStrings; i++) {
+                data[i] = convertCharPtrToHidlString(resp[i]);
+            }
+        }
+        Return<void> retStatus
+                = oemHookService[slotId]->mOemHookResponse->sendRequestStringsResponse(
+                responseInfo, data);
+        checkReturnStatus(slotId, retStatus, false);
+    } else {
+        RLOGE("sendRequestStringsResponse: oemHookService[%d]->mOemHookResponse == "
+                "NULL", slotId);
+    }
+
+    return 0;
+}
+
 /***************************************************************************************************
  * INDICATION FUNCTIONS
  * The below function handle unsolicited messages coming from the Radio
@@ -8412,6 +8539,32 @@
     return 0;
 }
 
+int radio::oemHookRawInd(int slotId,
+                         int indicationType, int token, RIL_Errno e, void *response,
+                         size_t responseLen) {
+    if (!kOemHookEnabled) return 0;
+
+    if (oemHookService[slotId] != NULL && oemHookService[slotId]->mOemHookIndication != NULL) {
+        if (response == NULL || responseLen == 0) {
+            RLOGE("oemHookRawInd: invalid response");
+            return 0;
+        }
+
+        hidl_vec<uint8_t> data;
+        data.setToExternal((uint8_t *) response, responseLen);
+#if VDBG
+        RLOGD("oemHookRawInd");
+#endif
+        Return<void> retStatus = oemHookService[slotId]->mOemHookIndication->oemHookRaw(
+                convertIntToRadioIndicationType(indicationType), data);
+        checkReturnStatus(slotId, retStatus, false);
+    } else {
+        RLOGE("oemHookRawInd: oemHookService[%d]->mOemHookIndication == NULL", slotId);
+    }
+
+    return 0;
+}
+
 void radio::registerService(RIL_RadioFunctions *callbacks, CommandInfo *commands) {
     using namespace android::hardware;
     int simCount = 1;
@@ -8445,7 +8598,13 @@
         radioService[i]->mSlotId = i;
         RLOGD("registerService: starting android::hardware::radio::V1_1::IRadio %s",
                 serviceNames[i]);
-        (void) radioService[i]->registerAsService(serviceNames[i]);
+        android::status_t status = radioService[i]->registerAsService(serviceNames[i]);
+
+        if (kOemHookEnabled) {
+            oemHookService[i] = new OemHookImpl;
+            oemHookService[i]->mSlotId = i;
+            status = oemHookService[i]->registerAsService(serviceNames[i]);
+        }
 
         ret = pthread_rwlock_unlock(radioServiceRwlockPtr);
         assert(ret == 0);
@@ -8473,6 +8632,6 @@
 }
 
 // should acquire write lock for the corresponding service before calling this
-void radio::setNitzTimeReceived(int slotId, int64_t timeReceived) {
+void radio::setNitzTimeReceived(int slotId, long timeReceived) {
     nitzTimeReceived[slotId] = timeReceived;
 }
diff --git a/libril/ril_service.h b/libril/ril_service.h
index b98dd3e..870b644 100644
--- a/libril/ril_service.h
+++ b/libril/ril_service.h
@@ -641,6 +641,10 @@
                    int indicationType, int token, RIL_Errno e, void *response,
                    size_t responselen);
 
+int oemHookRawInd(int slotId,
+                  int indicationType, int token, RIL_Errno e, void *response,
+                  size_t responselen);
+
 int indicateRingbackToneInd(int slotId,
                             int indicationType, int token, RIL_Errno e, void *response,
                             size_t responselen);
@@ -721,6 +725,14 @@
                        int indicationType, int token, RIL_Errno e, void *response,
                        size_t responselen);
 
+int sendRequestRawResponse(int slotId,
+                           int responseType, int serial, RIL_Errno e,
+                           void *response, size_t responseLen);
+
+int sendRequestStringsResponse(int slotId,
+                               int responseType, int serial, RIL_Errno e,
+                               void *response, size_t responseLen);
+
 int setCarrierInfoForImsiEncryptionResponse(int slotId,
                                             int responseType, int serial, RIL_Errno e,
                                             void *response, size_t responseLen);
@@ -731,7 +743,7 @@
 
 pthread_rwlock_t * getRadioServiceRwlock(int slotId);
 
-void setNitzTimeReceived(int slotId, int64_t timeReceived);
+void setNitzTimeReceived(int slotId, long timeReceived);
 
 }   // namespace radio
 
diff --git a/libril/ril_unsol_commands.h b/libril/ril_unsol_commands.h
index dab15ee..831f5fb 100644
--- a/libril/ril_unsol_commands.h
+++ b/libril/ril_unsol_commands.h
@@ -42,7 +42,7 @@
     {RIL_UNSOL_CDMA_CALL_WAITING, radio::cdmaCallWaitingInd, WAKE_PARTIAL},
     {RIL_UNSOL_CDMA_OTA_PROVISION_STATUS, radio::cdmaOtaProvisionStatusInd, WAKE_PARTIAL},
     {RIL_UNSOL_CDMA_INFO_REC, radio::cdmaInfoRecInd, WAKE_PARTIAL},
-    {RIL_UNSOL_OEM_HOOK_RAW, NULL, WAKE_PARTIAL},
+    {RIL_UNSOL_OEM_HOOK_RAW, radio::oemHookRawInd, WAKE_PARTIAL},
     {RIL_UNSOL_RINGBACK_TONE, radio::indicateRingbackToneInd, WAKE_PARTIAL},
     {RIL_UNSOL_RESEND_INCALL_MUTE, radio::resendIncallMuteInd, WAKE_PARTIAL},
     {RIL_UNSOL_CDMA_SUBSCRIPTION_SOURCE_CHANGED, radio::cdmaSubscriptionSourceChangedInd, WAKE_PARTIAL},
diff --git a/librilutils/Android.bp b/librilutils/Android.bp
index da50a87..c5207f8 100644
--- a/librilutils/Android.bp
+++ b/librilutils/Android.bp
@@ -1,14 +1,5 @@
 // Copyright 2013 The Android Open Source Project
 
-package {
-    // See: http://go/android-license-faq
-    // A large-scale-change added 'default_applicable_licenses' to import
-    // all of the 'license_kinds' from "hardware_ril_license"
-    // to get the below license kinds:
-    //   SPDX-license-identifier-Apache-2.0
-    default_applicable_licenses: ["hardware_ril_license"],
-}
-
 cc_library {
     name: "librilutils",
 
diff --git a/reference-ril/Android.mk b/reference-ril/Android.mk
index 8aeba23..6afdbd3 100644
--- a/reference-ril/Android.mk
+++ b/reference-ril/Android.mk
@@ -14,7 +14,7 @@
 LOCAL_SHARED_LIBRARIES := \
     liblog libcutils libutils libril librilutils
 
-LOCAL_STATIC_LIBRARIES := libbase
+LOCAL_STATIC_LIBRARIES := libqemu_pipe libbase
 
 # for asprinf
 LOCAL_CFLAGS := -D_GNU_SOURCE
@@ -42,17 +42,11 @@
       libcutils libutils
   LOCAL_CFLAGS += -DRIL_SHLIB
   LOCAL_MODULE:= libreference-ril
-  LOCAL_LICENSE_KINDS:= SPDX-license-identifier-Apache-2.0
-  LOCAL_LICENSE_CONDITIONS:= notice
-  LOCAL_NOTICE_FILE:= $(LOCAL_PATH)/NOTICE
   include $(BUILD_SHARED_LIBRARY)
 else
   #build executable
   LOCAL_SHARED_LIBRARIES += \
       libril
   LOCAL_MODULE:= reference-ril
-  LOCAL_LICENSE_KINDS:= SPDX-license-identifier-Apache-2.0
-  LOCAL_LICENSE_CONDITIONS:= notice
-  LOCAL_NOTICE_FILE:= $(LOCAL_PATH)/NOTICE
   include $(BUILD_EXECUTABLE)
 endif
diff --git a/reference-ril/atchannel.c b/reference-ril/atchannel.c
index 104ec36..0041836 100644
--- a/reference-ril/atchannel.c
+++ b/reference-ril/atchannel.c
@@ -741,11 +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,
@@ -753,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();
@@ -892,11 +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++) {
@@ -917,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 4b7cc82..c0e9b6e 100644
--- a/reference-ril/misc.c
+++ b/reference-ril/misc.c
@@ -28,3 +28,13 @@
 
     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 5918db4..9e65ab3 100644
--- a/reference-ril/misc.h
+++ b/reference-ril/misc.h
@@ -18,3 +18,5 @@
 
 /** 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 689e01d..084c4ad 100644
--- a/reference-ril/reference-ril.c
+++ b/reference-ril/reference-ril.c
@@ -37,6 +37,7 @@
 #include <cutils/properties.h>
 #include <cutils/sockets.h>
 #include <termios.h>
+#include <qemu_pipe.h>
 #include <sys/wait.h>
 #include <stdbool.h>
 #include <net/if.h>
@@ -566,7 +567,7 @@
 static bool hasWifiCapability()
 {
     char propValue[PROP_VALUE_MAX];
-    return property_get("ro.boot.qemu.wifi", propValue, "") > 0 &&
+    return property_get("ro.kernel.qemu.wifi", propValue, "") > 0 &&
            strcmp("1", propValue) == 0;
 }
 
@@ -702,11 +703,59 @@
         responses[i].addresses = alloca(addresses_size);
         strlcpy(responses[i].addresses, out, addresses_size);
 
-        /* I don't know where we are, so use the public Google DNS
-            * servers by default and no gateway.
-            */
-        responses[i].dnses = "8.8.8.8 8.8.4.4";
-        responses[i].gateways = "";
+        if (isInEmulator()) {
+            /* We are in the emulator - the dns servers are listed
+                * by the following system properties, setup in
+                * /system/etc/init.goldfish.sh:
+                *  - net.eth0.dns1
+                *  - net.eth0.dns2
+                *  - net.eth0.dns3
+                *  - net.eth0.dns4
+                */
+            const int   dnslist_sz = 128;
+            char*       dnslist = alloca(dnslist_sz);
+            const char* separator = "";
+            int         nn;
+
+            dnslist[0] = 0;
+            for (nn = 1; nn <= 4; nn++) {
+                /* Probe net.eth0.dns<n> */
+                char  propName[PROP_NAME_MAX];
+                char  propValue[PROP_VALUE_MAX];
+
+                snprintf(propName, sizeof propName, "net.eth0.dns%d", nn);
+
+                /* Ignore if undefined */
+                if (property_get(propName, propValue, "") <= 0) {
+                    continue;
+                }
+
+                /* Append the DNS IP address */
+                strlcat(dnslist, separator, dnslist_sz);
+                strlcat(dnslist, propValue, dnslist_sz);
+                separator = " ";
+            }
+            responses[i].dnses = dnslist;
+
+            /* There is only one gateway in the emulator. If WiFi is
+             * configured the interface visible to RIL will be behind a NAT
+             * where the gateway is different. */
+            if (hasWifi) {
+                responses[i].gateways = "192.168.200.1";
+            } else if (property_get("net.eth0.gw", propValue, "") > 0) {
+                responses[i].gateways = propValue;
+            } else {
+                responses[i].gateways = "";
+            }
+            responses[i].mtu = DEFAULT_MTU;
+        }
+        else {
+            /* I don't know where we are, so use the public Google DNS
+                * servers by default and no gateway.
+                */
+            responses[i].dnses = "8.8.8.8 8.8.4.4";
+            responses[i].gateways = "";
+        }
     }
 
     at_response_free(p_response);
@@ -1789,7 +1838,7 @@
         return;
     }
 
-    snprintf(cmd, sizeof(cmd), "AT+CCHO=%s", (char*) data);
+    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) {
@@ -3665,7 +3714,9 @@
     for (;;) {
         fd = -1;
         while  (fd < 0) {
-            if (s_port > 0) {
+            if (isInEmulator()) {
+                fd = qemu_pipe_open("pipe:qemud:gsm");
+            } else if (s_port > 0) {
                 fd = socket_network_client("localhost", s_port, SOCK_STREAM);
             } else if (s_device_socket) {
                 fd = socket_local_client(s_device_path,
@@ -3753,7 +3804,7 @@
         }
     }
 
-    if (s_port < 0 && s_device_path == NULL) {
+    if (s_port < 0 && s_device_path == NULL && !isInEmulator()) {
         usage(argv[0]);
         return NULL;
     }
@@ -3802,7 +3853,7 @@
         }
     }
 
-    if (s_port < 0 && s_device_path == NULL) {
+    if (s_port < 0 && s_device_path == NULL && !isInEmulator()) {
         usage(argv[0]);
     }
 
diff --git a/rild/Android.mk b/rild/Android.mk
index d1c1b95..55f2a18 100644
--- a/rild/Android.mk
+++ b/rild/Android.mk
@@ -29,9 +29,6 @@
 LOCAL_MODULE_RELATIVE_PATH := hw
 LOCAL_PROPRIETARY_MODULE := true
 LOCAL_MODULE:= rild
-LOCAL_LICENSE_KINDS:= SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS:= notice
-LOCAL_NOTICE_FILE:= $(LOCAL_PATH)/NOTICE
 ifeq ($(PRODUCT_COMPATIBLE_PROPERTY),true)
 LOCAL_INIT_RC := rild.rc
 LOCAL_CFLAGS += -DPRODUCT_COMPATIBLE_PROPERTY