Merge "RIL changes for IPv6 / IPv4v6 data calls."
diff --git a/mock-ril/src/cpp/requests.cpp b/mock-ril/src/cpp/requests.cpp
index 65f59aa..990d138 100644
--- a/mock-ril/src/cpp/requests.cpp
+++ b/mock-ril/src/cpp/requests.cpp
@@ -283,7 +283,7 @@
  */
 void RilRequestWorkerQueue::AddRequest (const int request,
         const void *data, const size_t datalen, const RIL_Token token) {
-    DBG("RilRequestWorkerQueue:AddRequest E: Before adding the request");
+    DBG("RilRequestWorkerQueue:AddRequest: %d E", request);
 
     v8::Locker locker;
     v8::HandleScope handle_scope;
diff --git a/mock-ril/src/cpp/responses.cpp b/mock-ril/src/cpp/responses.cpp
index 4c6aa0b..8f60c4f 100644
--- a/mock-ril/src/cpp/responses.cpp
+++ b/mock-ril/src/cpp/responses.cpp
@@ -348,9 +348,9 @@
     DBG("evdo_signalstrength = %d", curSignalStrength.EVDO_SignalStrength.signalNoiseRatio);
 
     s_rilenv->OnUnsolicitedResponse(cmd, &curSignalStrength, sizeof(curSignalStrength));
+    DBG("UnsolRspSignalStrength X");
 }
 
-
 /**
  * Maps for converting request complete and unsoliciated response
  * protobufs to ril data arrays.
@@ -511,6 +511,7 @@
 
     unsolRilRspConversionMap[RIL_UNSOL_SIGNAL_STRENGTH] = UnsolRspSignalStrength;  // 1009
 
+
     LOGD("responsesInit X: status=%d", status);
     return STATUS_OK;
 }
diff --git a/mock-ril/src/js/simulated_icc.js b/mock-ril/src/js/simulated_icc.js
index 6d50ce4..e1d6aa4 100644
--- a/mock-ril/src/js/simulated_icc.js
+++ b/mock-ril/src/js/simulated_icc.js
@@ -51,7 +51,7 @@
     this.rilRequestEnterSimPin = function(req) { // 2
         print('Icc: rilRequestEnterSimPin req.data.pin=' + req.data.pin);
 
-        var rsp = Object();
+        var rsp = new Object();
         rsp.retriesRemaining = 3;
         result.responseProtobuf = rilSchema[packageNameAndSeperator +
                                  'RspEnterSimPin'].serialize(rsp);
@@ -61,8 +61,8 @@
     this.rilRequestGetImsi = function(req) { // 11
         print('Icc: rilRequestGetImsi');
 
-        var rsp = Object();
-        rsp.strings = Array();
+        var rsp = new Object();
+        rsp.strings = new Array();
         rsp.strings[0] = MCC + MNC + MSN;
         result.responseProtobuf = rilSchema[packageNameAndSeperator +
                                  'RspStrings'].serialize(rsp);
@@ -72,7 +72,7 @@
     this.rilRequestOperator = function(req) { // 22
         print('Icc: rilRequestOperator');
 
-        var rsp = Object();
+        var rsp = new Object();
         rsp.longAlphaOns = 'Mock-Ril long Alpha Ons';
         rsp.shortAlphaOns = 'Mock-Ril';
         rsp.mccMnc = MCC + MNC;
@@ -84,8 +84,8 @@
     this.rilRequestGetImei = function(req) { // 38
         print('Icc: rilRequestGetImei');
 
-        var rsp = Object();
-        rsp.strings = Array();
+        var rsp = new Object();
+        rsp.strings = new Array();
         rsp.strings[0] = IMEI;
         result.responseProtobuf = rilSchema[packageNameAndSeperator +
                                  'RspStrings'].serialize(rsp);
@@ -95,8 +95,8 @@
     this.rilRequestGetImeisv = function(req) { // 39
         print('Icc: rilRequestGetImeisv');
 
-        var rsp = Object();
-        rsp.strings = Array();
+        var rsp = new Object();
+        rsp.strings = new Array();
         rsp.strings[0] = IMEISV;
         result.responseProtobuf = rilSchema[packageNameAndSeperator +
                                  'RspStrings'].serialize(rsp);
@@ -116,7 +116,7 @@
             result.responseProtobuf = emptyProtobuf;
 
             try {
-                result = this.simDispatchTable[req.reqNum](req);
+                result = simDispatchTable[req.reqNum](req);
             } catch (err) {
                 print('Icc: Unknown reqNum=' + req.reqNum);
                 result.rilErrCode = RIL_E_REQUEST_NOT_SUPPORTED;
@@ -146,7 +146,7 @@
 }
 
 // The simulated sim instance and its associated Worker
-var simulatedIcc = new Icc()
+var simulatedIcc = new Icc();
 var simulatedIccWorker = new Worker(function (req) {
     simulatedIcc.process(req);
 });
diff --git a/mock-ril/src/js/simulated_radio.js b/mock-ril/src/js/simulated_radio.js
index ea569d5..9dfe3cd 100644
--- a/mock-ril/src/js/simulated_radio.js
+++ b/mock-ril/src/js/simulated_radio.js
@@ -15,6 +15,26 @@
  */
 
 /**
+ * The Radio object contains a set of methods and objects to handle ril request
+ * which is passed from simulatedRadioWorker queue. The global object initialize
+ * an instance of Radio object by calling "new Radio". For each ril request,
+ * rilDispatchTable gets searched and the corresponding method is called.
+ * Extra requests are also defined to process unsolicited rerequests.
+ *
+ * The rilDispatchTable is an array indexed by RIL_REQUEST_* or REQUEST_UNSOL_*,
+ * in which each request corresponds to a functions defined in the Radio object.
+ * We need to pay attention when using "this" within those functions. When they are
+ * called in "this.process" using
+ *               result = this.radioDispatchTable[req.reqNum])(req);
+ * this scope of "this" within those functions are the radioDispatchTable, not the
+ * object that "this.process" belongs to. Using "this." to access other
+ * functions in the object may cause trouble.
+ * To avoid that, the object is passed in when those functions are called as
+ * shown in the following:
+ *                 result = (this.radioDispatchTable[req.reqNum]).call(this, req);
+ */
+
+/**
  * Set radio state
  */
 function setRadioState(newState) {
@@ -113,14 +133,14 @@
      *
      * @return Array of RilCall's
      */
-    this.getCalls = function() {
+    this.getCalls =  function() {
         return calls;
     }
 
     /**
      * @return the RilCall at calls[index] or null if undefined.
      */
-    this.getCall = function(index) {
+    this.getCall = function (index) {
         var c = null;
         try {
             c = calls[index];
@@ -137,7 +157,7 @@
      *
      * @return a RilCall or null if too many active calls.
      */
-    this.addCall = function(state, phoneNumber, callerName) {
+    this.addCall = function (state, phoneNumber, callerName) {
         print('Radio: addCall');
         var c = null;
         if (numberActiveCalls < maxNumberActiveCalls) {
@@ -155,7 +175,7 @@
      * @param index into calls to remove.
      * @return the call removed or null if did not exist
      */
-    this.removeCall = function(index) {
+    this.removeCall =  function (index) {
         var c = null;
         if ((numberActiveCalls > 0)
                  && (index < calls.length)
@@ -177,7 +197,7 @@
      *
      * @param c is the RilCall to print
      */
-    this.printCall = function(c) {
+    this.printCall = function (c) {
         if ((c == null) || (typeof c == 'undefined')) {
             print('c[' + i + ']: undefined');
         } else {
@@ -192,7 +212,7 @@
      *
      * @param callArray is an Array of RilCall's
      */
-    this.printCalls = function(callArray) {
+    this.printCalls = function (callArray) {
         if (typeof callArray == 'undefined') {
             callArray = calls;
         }
@@ -221,7 +241,7 @@
      * @param rssi and bitErrorRate are signal strength parameters for GSM
      *        cdmaDbm, cdmaEcio, evdoRssi, evdoEcio, evdoSnr are parameters for CDMA & EVDO
      */
-    this.setSignalStrength = function(rssi, bitErrorRate, cdmaDbm, cdmaEcio, evdoRssi,
+    this.setSignalStrength = function (rssi, bitErrorRate, cdmaDbm, cdmaEcio, evdoRssi,
                                       evdoEcio, evdoSnr) {
         print('setSignalStrength E');
 
@@ -246,7 +266,7 @@
         rsp.cdmSignalstrength = cdmaSignalStrength;
         rsp.evdoSignalstrength = evdoSignalStrength;
 
-        response = rilSchema[packageNameAndSeperator +
+        var response = rilSchema[packageNameAndSeperator +
                              'RspSignalStrength'].serialize(rsp);
 
         sendRilUnsolicitedResponse(RIL_UNSOL_SIGNAL_STRENGTH, response);
@@ -279,6 +299,35 @@
     }
 
     /**
+     * Handle RIL_REQUEST_DIAL
+     *
+     * @param req is the Request
+     */
+    this.rilRequestDial = function(req) { // 10
+        print('Radio: rilRequestDial E');
+        var newCall = new Object();
+        newCall = this.addCall(CALLSTATE_DIALING, req.data.address, '');
+        if (newCall == null) {
+            result.rilErrCode = RIL_E_GENERIC_FAILURE;
+            return result;
+        }
+        this.printCalls(calls);
+
+        // Update call state change in 2 seconds
+        simulatedRadioWorker.addDelayed(
+                        {'reqNum' : REQUEST_UNSOL_CALL_STATE_CHANGED,
+                         'callType' : OUTGOING,
+                         'callIndex' : newCall.index,
+                         'nextState' : CALLSTATE_ALERTING}, 2000);
+        simulatedRadioWorker.addDelayed(
+                        {'reqNum' : REQUEST_UNSOL_CALL_STATE_CHANGED,
+                         'callType' : OUTGOING,
+                         'callIndex': newCall.index,
+                         'nextState' : CALLSTATE_ACTIVE}, 5000);
+        return result;
+    }
+
+    /**
      * Handle RIL_REQUEST_HANG_UP
      *
      * @param req is the Request
@@ -287,6 +336,7 @@
         print('Radio: rilRequestHangUp data.connection_index=' + req.data.connectionIndex);
         if (this.removeCall(req.data.connectionIndex) == null) {
             result.rilErrCode = RIL_E_GENERIC_FAILURE;
+            print('no connection to hangup');
         }
         return result;
     }
@@ -454,6 +504,34 @@
          simulatedRadioWorker.addDelayed(
              {'reqNum' : REQUEST_UNSOL_SIGNAL_STRENGTH}, 60000);
 
+         // this is not a request, no response is needed
+         result.sendResponse = false;
+         return result;
+     }
+
+     /**
+      * Send RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED
+      */
+     this.rilUnsolCallStateChanged = function(req) { // 2002
+         print('rilUnsolCallStateChanged: req.reqNum=' + req.reqNum);
+         print('rilUnsolCallStateChanged: req.callType=' + req.callType);
+         print('rilUnsolCallStateChanged: req.callIndex=' + req.callIndex);
+         print('rilUnsolCallStateChanged: req.nextState=' + req.nextState);
+
+         // if it is an outgoing call, update the call state of the call
+         // Send out call state changed flag
+         var curCall = this.getCall(req.callIndex);
+         this.printCall(curCall);
+
+         if (curCall != null) {
+             curCall.state = req.nextState;
+         } else {
+             this.removeCall(req.callIndex);
+         }
+         // TODO: if it is an incoming call, update the call state of the call
+         // Send out call state change flag
+         // Send out RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED
+         sendRilUnsolicitedResponse(RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED);
          result.sendResponse = false;
          return result;
      }
@@ -471,7 +549,9 @@
             result.responseProtobuf = emptyProtobuf;
 
             try {
-                result = this.radioDispatchTable[req.reqNum](req);
+                // Pass "this" object to each ril request call such that
+                // they have the same scope
+                result = (this.radioDispatchTable[req.reqNum]).call(this, req);
             } catch (err) {
                 print('err = ' + err);
                 print('Radio: Unknown reqNum=' + req.reqNum);
@@ -497,7 +577,9 @@
     this.radioDispatchTable = new Array();
     this.radioDispatchTable[RIL_REQUEST_GET_CURRENT_CALLS] = // 9
                 this.rilRequestGetCurrentCalls;
-    this.radioDispatchTable[RIL_REQUEST_HANGUP] = // 12
+    this.radioDispatchTable[RIL_REQUEST_DIAL] = // 10
+                this.rilRequestDial;
+    this.radioDispatchTable[RIL_REQUEST_HANGUP] =  // 12
                 this.rilRequestHangUp;
     this.radioDispatchTable[RIL_REQUEST_SIGNAL_STRENGTH] = // 19
                 this.rilRequestSignalStrength;
@@ -518,11 +600,13 @@
                 this.delayTestRequestHandler;
     this.radioDispatchTable[REQUEST_UNSOL_SIGNAL_STRENGTH] =  // 2001
                 this.rilUnsolSignalStrength;
+    this.radioDispatchTable[REQUEST_UNSOL_CALL_STATE_CHANGED] =  // 2002
+                this.rilUnsolCallStateChanged;
     print('Radio: constructor X');
 }
 
 // The simulated radio instance and its associated Worker
-var simulatedRadio = new Radio()
+var simulatedRadio = new Radio();
 var simulatedRadioWorker = new Worker(function (req) {
     simulatedRadio.process(req);
 });