Home | History | Annotate | Download | only in js
      1 /**
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 /**
     18  * The Radio object contains a set of methods and objects to handle ril request
     19  * which is passed from simulatedRadioWorker queue. The global object initialize
     20  * an instance of Radio object by calling "new Radio". For each ril request,
     21  * rilDispatchTable gets searched and the corresponding method is called.
     22  * Extra requests are also defined to process unsolicited rerequests.
     23  *
     24  * The rilDispatchTable is an array indexed by RIL_REQUEST_* or REQUEST_UNSOL_*,
     25  * in which each request corresponds to a functions defined in the Radio object.
     26  * We need to pay attention when using "this" within those functions. When they are
     27  * called in "this.process" using
     28  *               result = this.radioDispatchTable[req.reqNum])(req);
     29  * this scope of "this" within those functions are the radioDispatchTable, not the
     30  * object that "this.process" belongs to. Using "this." to access other
     31  * functions in the object may cause trouble.
     32  * To avoid that, the object is passed in when those functions are called as
     33  * shown in the following:
     34  *                 result = (this.radioDispatchTable[req.reqNum]).call(this, req);
     35  */
     36 
     37 /**
     38  * Set radio state
     39  */
     40 function setRadioState(newState) {
     41     newRadioState = newState;
     42     if (typeof newState == 'string') {
     43         newRadioState = globals[newState];
     44         if (typeof newRadioState == 'undefined') {
     45             throw('setRadioState: Unknow string: ' + newState);
     46         }
     47     }
     48     if ((newRadioState < RADIOSTATE_OFF) || (newRadioState > RADIOSTATE_NV_READY)) {
     49         throw('setRadioState: newRadioState: ' + newRadioState + ' is invalid');
     50     }
     51     gRadioState = newRadioState;
     52     sendRilUnsolicitedResponse(RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED);
     53 }
     54 
     55 /**
     56  * Create a call.
     57  *
     58  * @return a RilCall
     59  */
     60 function RilCall(state, phoneNumber, callerName) {
     61     this.state = state;
     62     this.index = 0;
     63     this.toa = 0;
     64     this.isMpty = false;
     65     this.isMt = false;
     66     this.als = 0;
     67     this.isVoice = true;
     68     this.isVoicePrivacy = false;
     69     this.number = phoneNumber;
     70     this.numberPresentation = 0;
     71     this.name = callerName;
     72 }
     73 
     74 /**
     75  * Simulated Radio
     76  */
     77 function Radio() {
     78     var registrationState = '1';
     79     var lac = '0';
     80     var cid = '0';
     81     var radioTechnology = '3';
     82     var baseStationId = NULL_RESPONSE_STRING;
     83     var baseStationLatitude = NULL_RESPONSE_STRING;
     84     var baseStationLongitude = NULL_RESPONSE_STRING;
     85     var concurrentServices = NULL_RESPONSE_STRING;
     86     var systemId  = NULL_RESPONSE_STRING;
     87     var networkId = NULL_RESPONSE_STRING;
     88     var roamingIndicator = NULL_RESPONSE_STRING;
     89     var prlActive = NULL_RESPONSE_STRING;
     90     var defaultRoamingIndicator = NULL_RESPONSE_STRING;
     91     var registrationDeniedReason = NULL_RESPONSE_STRING;
     92     var primaryScrambingCode = NULL_RESPONSE_STRING;
     93 
     94     var NETWORK_SELECTION_MODE_AUTOMATIC = 0;
     95     var NETWORK_SELECTION_MODE_MANUAL = 1;
     96     var networkSelectionMode = NETWORK_SELECTION_MODE_AUTOMATIC;
     97 
     98     var muteState = 0;   // disable mute
     99 
    100     // Number of active calls in calls
    101     var numberActiveCalls = 0;
    102 
    103     // Maximum number of active calls
    104     var maxNumberActiveCalls = 7;
    105     var maxConnectionsPerCall = 5; // only 5 connections allowed per call
    106 
    107     // Flag to denote whether an incoming/waiting call is answered
    108     var incomingCallIsProcessed = false;
    109 
    110     // Call transition flag
    111     var callTransitionFlag = false;  // default to auto-transition
    112 
    113     var lastCallFailCause = 0;
    114 
    115     // Array of "active" calls
    116     var calls = Array(maxNumberActiveCalls + 1);
    117 
    118     // The result returned by the request handlers
    119     var result = new Object();
    120 
    121     function GWSignalStrength() {
    122         this.signalStrength = 10;  // 10 * 2 + (-113) = -93dBm, make it three bars
    123         this.bitErrorRate = 0;
    124     }
    125 
    126     function CDMASignalStrength() {
    127         this.dbm = -1;
    128         this.ecio = -1;
    129     }
    130 
    131     function EVDOSignalStrength() {
    132         this.dbm = -1;
    133         this.ecio = -1;
    134         this.signalNoiseRatio = 0;
    135     }
    136 
    137     var gwSignalStrength = new GWSignalStrength;
    138     var cdmaSignalStrength = new CDMASignalStrength();
    139     var evdoSignalStrength = new EVDOSignalStrength();
    140 
    141     /**
    142      * The the array of calls, this is a sparse
    143      * array and some elements maybe 'undefined'.
    144      *
    145      * @return Array of RilCall's
    146      */
    147     this.getCalls =  function() {
    148         return calls;
    149     }
    150 
    151     /**
    152      * @return the RilCall at calls[index] or null if undefined.
    153      */
    154     this.getCall = function(index) {
    155         var c = null;
    156         try {
    157             c = calls[index];
    158             if (typeof c == 'undefined') {
    159                 c = null;
    160             }
    161         } catch (err) {
    162             c = null;
    163         }
    164         return c;
    165     }
    166 
    167     /**
    168      * @return the first call that is in the given state
    169      */
    170     this.getCallIdByState = function(callState) {
    171         if ((callState < CALLSTATE_ACTIVE) || (callState > CALLSTATE_WAITING)) {
    172             return null;
    173         }
    174         for (var i = 0; i < calls.length; i++) {
    175             if (typeof calls[i] != 'undefined') {
    176                 if (calls[i].state == callState) {
    177                     return i;
    178                 }
    179             }
    180         }
    181         return null;
    182     }
    183 
    184     /** Add an active call
    185      *
    186      * @return a RilCall or null if too many active calls.
    187      */
    188     this.addCall = function(state, phoneNumber, callerName) {
    189         print('Radio: addCall');
    190         var c = null;
    191         if (numberActiveCalls < maxNumberActiveCalls) {
    192             numberActiveCalls += 1;
    193             c = new RilCall(state, phoneNumber, callerName);
    194             // call index should fall in the closure of [1, 7]
    195             // Search for an "undefined" element in the array and insert the call
    196             for (var i = 1; i < (maxNumberActiveCalls + 1); i++) {
    197                 print('Radio: addCall, i=' + i);
    198                 if (typeof calls[i] == 'undefined') {
    199                     print('Radio: addCall, calls[' + i + '] is undefined');
    200                     c.index = i;
    201                     calls[i] = c;
    202                     break;
    203                 }
    204             }
    205             this.printCalls(calls);
    206         }
    207         return c;
    208     }
    209 
    210     /**
    211      * Remove the call, does nothing if the call is undefined.
    212      *
    213      * @param index into calls to remove.
    214      * @return the call removed or null if did not exist
    215      */
    216     this.removeCall =  function(index) {
    217         var c = null;
    218         if ((numberActiveCalls > 0)
    219                  && (index < calls.length)
    220                  && (typeof calls[index] != 'undefined')) {
    221             c = calls[index];
    222             delete calls[index];
    223             numberActiveCalls -= 1;
    224             if (numberActiveCalls == 0) {
    225                 calls = new Array();
    226             }
    227         } else {
    228             c = null;
    229         }
    230         return c;
    231     }
    232 
    233     /**
    234      * Print the call
    235      *
    236      * @param c is the RilCall to print
    237      */
    238     this.printCall = function(c) {
    239         if ((c != null) && (typeof c != 'undefined')) {
    240             print('c[' + c.index + ']: index=' + c.index + ' state=' + c.state +
    241                   ' number=' + c.number + ' name=' + c.name);
    242         }
    243     }
    244 
    245     /**
    246      * Print all the calls.
    247      *
    248      * @param callArray is an Array of RilCall's
    249      */
    250     this.printCalls = function(callArray) {
    251         if (typeof callArray == 'undefined') {
    252             callArray = calls;
    253         }
    254         print('callArray.length=' + callArray.length);
    255         for (var i = 0; i < callArray.length; i++) {
    256             if ((callArray[i] == null) || (typeof callArray[i] == 'undefined')) {
    257                 print('c[' + i + ']: undefined');
    258             } else {
    259                 this.printCall(callArray[i]);
    260             }
    261         }
    262     }
    263 
    264     /**
    265      * Count number of calls in the given state
    266      *
    267      * @param callState is the give state
    268      */
    269     this.countCallsInState = function(callState) {
    270         var count = 0;
    271         if ((callState < CALLSTATE_ACTIVE) || (callState > CALLSTATE_WAITING)) {
    272             // not a valid call state
    273             return null;
    274         }
    275         for (var i = 0; i < calls.length; i++) {
    276             if (typeof calls[i] != 'undefined') {
    277                 if (calls[i].state == callState) {
    278                     count++;
    279                 }
    280             }
    281         }
    282         return count;
    283     }
    284 
    285     /**
    286      * Print signal strength
    287      */
    288     this.printSignalStrength = function() {
    289         print('rssi: '         + gwSignalStrength.signalStrength);
    290         print('bitErrorRate: ' + gwSignalStrength.bitErrorRate);
    291         print('cdmaDbm: '  +  cdmaSignalStrength.dbm);
    292         print('cdmaEcio: ' + cdmaSignalStrength.ecio);
    293         print('evdoRssi: ' + evdoSignalStrength.dbm);
    294         print('evdoEcio: ' + evdoSignalStrength.ecio);
    295         print('evdoSnr: '  + evdoSignalStrength.signalNoiseRatio);
    296     }
    297 
    298     /**
    299      * set signal strength
    300      *
    301      * @param rssi and bitErrorRate are signal strength parameters for GSM
    302      *        cdmaDbm, cdmaEcio, evdoRssi, evdoEcio, evdoSnr are parameters for CDMA & EVDO
    303      */
    304     this.setSignalStrength = function(rssi, bitErrorRate, cdmaDbm, cdmaEcio, evdoRssi,
    305                                       evdoEcio, evdoSnr) {
    306         print('setSignalStrength E');
    307 
    308         if (rssi != 99) {
    309             if ((rssi < 0) || (rssi > 31)) {
    310                 throw ('not a valid signal strength');
    311             }
    312         }
    313         // update signal strength
    314         gwSignalStrength.signalStrength = rssi;
    315         gwSignalStrength.bitErrorRate = bitErrorRate;
    316         cdmaSignalStrength.dbm = cdmaDbm;
    317         cdmaSignalStrength.ecio = cdmaEcio;
    318         evdoSignalStrength.dbm = evdoRssi;
    319         evdoSignalStrength.ecio = evdoEcio;
    320         evdoSignalStrength.signalNoiseRatio = evdoSnr;
    321 
    322         // pack the signal strength into RspSignalStrength and send a unsolicited response
    323         var rsp = new Object();
    324 
    325         rsp.gwSignalstrength = gwSignalStrength;
    326         rsp.cdmSignalstrength = cdmaSignalStrength;
    327         rsp.evdoSignalstrength = evdoSignalStrength;
    328 
    329         var response = rilSchema[packageNameAndSeperator +
    330                              'RspSignalStrength'].serialize(rsp);
    331 
    332         sendRilUnsolicitedResponse(RIL_UNSOL_SIGNAL_STRENGTH, response);
    333 
    334         // send the unsolicited signal strength every 1 minute.
    335         simulatedRadioWorker.addDelayed(
    336             {'reqNum' : CMD_UNSOL_SIGNAL_STRENGTH}, 60000);
    337         print('setSignalStrength X');
    338     }
    339 
    340     /**
    341      * Handle RIL_REQUEST_GET_CURRENT_CALL
    342      *
    343      * @param req is the Request
    344      */
    345     this.rilRequestGetCurrentCalls = function(req) { // 9
    346         print('Radio: rilRequestGetCurrentCalls E');
    347         var rsp = new Object();
    348 
    349         // pack calls into rsp.calls
    350         rsp.calls = new Array();
    351         var i;
    352         var j;
    353         for (i = 0, j = 0; i < calls.length; i++) {
    354             if (typeof calls[i] != 'undefined') {
    355                 rsp.calls[j++] = calls[i];
    356             }
    357         }
    358         result.responseProtobuf = rilSchema[packageNameAndSeperator +
    359                                             'RspGetCurrentCalls'].serialize(rsp);
    360         return result;
    361     }
    362 
    363     /**
    364      * Handle RIL_REQUEST_DIAL
    365      *
    366      * @param req is the Request
    367      */
    368     this.rilRequestDial = function(req) { // 10
    369         print('Radio: rilRequestDial E');
    370         var newCall = new Object();
    371         newCall = this.addCall(CALLSTATE_DIALING, req.data.address, '');
    372         if (newCall == null) {
    373             result.rilErrCode = RIL_E_GENERIC_FAILURE;
    374             return result;
    375         }
    376         this.printCalls(calls);
    377 
    378         print('after add the call');
    379         // Set call state to dialing
    380         simulatedRadioWorker.add(
    381                         {'reqNum' : CMD_CALL_STATE_CHANGE,
    382                          'callType' : OUTGOING,
    383                          'callIndex' : newCall.index,
    384                          'nextState' : CALLSTATE_DIALING});
    385         if (!callTransitionFlag) {
    386             // for auto transition
    387             // Update call state to alerting after 1 second
    388             simulatedRadioWorker.addDelayed(
    389                 {'reqNum' : CMD_CALL_STATE_CHANGE,
    390                  'callType' : OUTGOING,
    391                  'callIndex' : newCall.index,
    392                  'nextState' : CALLSTATE_ALERTING}, 1000);
    393             // Update call state to active after 2 seconds
    394             simulatedRadioWorker.addDelayed(
    395                 {'reqNum' : CMD_CALL_STATE_CHANGE,
    396                  'callType' : OUTGOING,
    397                  'callIndex': newCall.index,
    398                  'nextState' : CALLSTATE_ACTIVE}, 2000);
    399         }
    400         return result;
    401     }
    402 
    403     /**
    404      * Handle RIL_REQUEST_HANG_UP
    405      *
    406      * @param req is the Request
    407      */
    408     this.rilRequestHangUp = function(req) { // 12
    409         print('Radio: rilRequestHangUp data.connection_index=' + req.data.connectionIndex);
    410         if (this.removeCall(req.data.connectionIndex) == null) {
    411             result.rilErrCode = RIL_E_GENERIC_FAILURE;
    412             print('no connection to hangup');
    413         }
    414         return result;
    415     }
    416 
    417     /**
    418      * Handle RIL_REQUEST_HANGUP_WAITING_OR_BACKGROUND
    419      *        Hang up waiting or held
    420      *
    421      * @param req is the Request
    422      */
    423     this.rilRequestHangupWaitingOrBackground = function(req) { // 13
    424         print('Radio: rilRequestHangupWaitingOrBackground');
    425         if (numberActiveCalls <= 0) {
    426           result.rilErrCode = RIL_E_GENERIC_FAILURE;
    427         } else {
    428             for (var i = 0; i < calls.length; i++) {
    429                 if (typeof calls[i] != 'undefined') {
    430                     switch (calls[i].state) {
    431                         case CALLSTATE_HOLDING:
    432                         case CALLSTATE_WAITING:
    433                         case CALLSTATE_INCOMING:
    434                             this.removeCall(i);
    435                             incomingCallIsProcessed = true;
    436                             break;
    437                         default:
    438                             result.rilErrCode = RIL_E_GENERIC_FAILURE;
    439                             break;
    440                     }
    441                     this.printCalls(calls);
    442                     if(result.rilErrCode == RIL_E_GENERIC_FAILURE) {
    443                         return result;
    444                     }
    445                 } // end of processing call[i]
    446             } // end of for
    447         }
    448         // Send out RIL_UNSOL_CALL_STATE_CHANGED after the request is returned
    449         simulatedRadioWorker.add(
    450           {'reqNum' : CMD_UNSOL_CALL_STATE_CHANGED});
    451         return result;
    452     }
    453 
    454     /**
    455      * Handle RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND
    456      *   release all active calls (if any exist) and resume held or waiting calls.
    457      * @param req is the Request
    458      */
    459     this.rilRequestHangUpForegroundResumeBackground = function(req) { //14
    460         print('Radio: rilRequestHangUpForegroundResumeBackground');
    461         if (numberActiveCalls <= 0) {
    462             result.rilErrCode = RIL_E_GENERIC_FAILURE;
    463         } else {
    464             for (var i = 0; i < calls.length; i++) {
    465                 if (typeof calls[i] != 'undefined') {
    466                     switch (calls[i].state) {
    467                         case CALLSTATE_ACTIVE:
    468                             this.removeCall(i);
    469                             break;
    470                         case CALLSTATE_HOLDING:
    471                         case CALLSTATE_WAITING:
    472                           calls[i].state = CALLSTATE_ACTIVE;
    473                             break;
    474                         default:
    475                             result.rilErrCode = RIL_E_GENERIC_FAILURE;
    476                             break;
    477                     }
    478                     this.printCalls(calls);
    479                     if(result.rilErrCode == RIL_E_GENERIC_FAILURE) {
    480                         return result;
    481                     }
    482                 } // end of processing call[i]
    483             }
    484         }
    485         // Send out RIL_UNSOL_CALL_STATE_CHANGED after the request is returned
    486         simulatedRadioWorker.add(
    487           {'reqNum' : CMD_UNSOL_CALL_STATE_CHANGED});
    488         return result;
    489     }
    490 
    491     /**
    492      * Handle RIL_REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE
    493      *
    494      *     BEFORE                               AFTER
    495      * Call 1   Call 2                 Call 1       Call 2
    496      * ACTIVE   HOLDING                HOLDING     ACTIVE
    497      * ACTIVE   WAITING                HOLDING     ACTIVE
    498      * HOLDING  WAITING                HOLDING     ACTIVE
    499      * ACTIVE   IDLE                   HOLDING     IDLE
    500      * IDLE     IDLE                   IDLE        IDLE
    501      *
    502      * @param req is the Request
    503      */
    504     this.rilRequestSwitchWaitingOrHoldingAndActive = function(req) {  // 15
    505         print('Radio: rilRequestSwitchWaitingOrHoldingAndActive');
    506         print('Radio: lastReq = ' + lastReq);
    507         print('Radio: req.reqNum = ' + req.reqNum);
    508         if (lastReq == req.reqNum) {
    509             print('Radio: called twice');
    510             return result;
    511         }
    512 
    513         if (numberActiveCalls <= 0) {
    514             result.rilErrCode = RIL_E_GENERIC_FAILURE;
    515         } else {
    516             for (var i = 0; i < calls.length; i++) {
    517                 if (typeof calls[i] != 'undefined') {
    518                     switch (calls[i].state) {
    519                         case CALLSTATE_ACTIVE:
    520                             calls[i].state = CALLSTATE_HOLDING;
    521                             break;
    522                         case CALLSTATE_HOLDING:
    523                         case CALLSTATE_WAITING:
    524                             calls[i].state = CALLSTATE_ACTIVE;
    525                             break;
    526                         default:
    527                             result.rilErrCode = RIL_E_GENERIC_FAILURE;
    528                             break;
    529                     }
    530                     this.printCalls(calls);
    531                     if(result.rilErrCode == RIL_E_GENERIC_FAILURE) {
    532                         return result;
    533                     }
    534                 } // end of processing call[i]
    535             } // end of for
    536         }
    537         // Send out RIL_UNSOL_CALL_STATE_CHANGED after the request is returned
    538         simulatedRadioWorker.add(
    539           {'reqNum' : CMD_UNSOL_CALL_STATE_CHANGED});
    540         return result;
    541     }
    542 
    543     /**
    544      * Handle RIL_REQUEST_CONFERENCE
    545      * Conference holding and active
    546      *
    547      * @param req is the Request
    548      */
    549     this.rilRequestConference = function(req) {  // 16
    550         print('Radio: rilRequestConference E');
    551         if ((numberActiveCalls <= 0) || (numberActiveCalls > maxConnectionsPerCall)) {
    552             // The maximum number of connections within a call is 5
    553             result.rilErrCode = RIL_E_GENERIC_FAILURE;
    554             return result;
    555         } else {
    556             var numCallsInBadState = 0;
    557             for (var i = 0; i < calls.length; i++) {
    558                 if (typeof calls[i] != 'undefined') {
    559                     if ((calls[i].state != CALLSTATE_ACTIVE) &&
    560                             (calls[i].state != CALLSTATE_HOLDING)) {
    561                         numCallsInBadState++;
    562                     }
    563                 }
    564             }
    565 
    566             // if there are calls not in ACITVE or HOLDING state, return error
    567             if (numCallsInBadState > 0) {
    568                 result.rilErrCode = RIL_E_GENERIC_FAILURE;
    569                 return result;
    570             } else { // conference ACTIVE and HOLDING calls
    571                 for (var i = 0; i < calls.length; i++) {
    572                     if (typeof calls[i] != 'undefined') {
    573                         switch (calls[i].state) {
    574                             case CALLSTATE_ACTIVE:
    575                                 break;
    576                             case CALLSTATE_HOLDING:
    577                                 calls[i].state = CALLSTATE_ACTIVE;
    578                                 break;
    579                             default:
    580                                 result.rilErrCode = RIL_E_GENERIC_FAILURE;
    581                                 break;
    582                         }
    583                     }
    584                     this.printCalls(calls);
    585                     if(result.rilErrCode == RIL_E_GENERIC_FAILURE) {
    586                         return result;
    587                     }
    588                 }
    589             }
    590         }
    591 
    592         // Only if conferencing is successful,
    593         // Send out RIL_UNSOL_CALL_STATE_CHANGED after the request is returned
    594         simulatedRadioWorker.add(
    595           {'reqNum' : CMD_UNSOL_CALL_STATE_CHANGED});
    596         return result;
    597     }
    598 
    599     /**
    600      * Handle RIL_REQUEST_LAST_CALL_FAIL_CAUSE
    601      *
    602      * @param req is the request
    603      */
    604     this.rilRequestLastCallFailCause = function(req) {
    605         print('Radio: rilRequestLastCallFailCause E');
    606 
    607         var rsp = new Object();
    608         rsp.integers = new Array();
    609         rsp.integers[0] = lastCallFailCause;
    610 
    611         result.responseProtobuf = rilSchema[packageNameAndSeperator +
    612                                             'RspIntegers'].serialize(rsp);
    613         return result;
    614     }
    615 
    616     /**
    617      * Handle RIL_REQUEST_SIGNAL_STRENGTH
    618      *
    619      * @param req is the Request
    620      */
    621     this.rilRequestSignalStrength = function(req) { // 19
    622         print('Radio: rilRequestSignalStrength E');
    623         var rsp = new Object();
    624 
    625         // pack the signal strength into RspSignalStrength
    626         rsp.gwSignalstrength = gwSignalStrength;
    627         rsp.cdmaSignalstrength = cdmaSignalStrength;
    628         rsp.evdoSignalstrength = evdoSignalStrength;
    629 
    630         result.responseProtobuf = rilSchema[packageNameAndSeperator +
    631                                             'RspSignalStrength'].serialize(rsp);
    632         return result;
    633     }
    634 
    635     /**
    636      * Handle RIL_REQUEST_REGISTRATION_STATE
    637      *
    638      * @param req is the Request
    639      */
    640     this.rilRequestRegistrationState = function(req) { // 20
    641         print('Radio: rilRequestRegistrationState');
    642 
    643         var rsp = new Object();
    644         rsp.strings = Array();
    645         rsp.strings[0] = registrationState;
    646         rsp.strings[1] = lac;
    647         rsp.strings[2] = cid;
    648         rsp.strings[3] = radioTechnology;
    649         rsp.strings[4] = baseStationId;
    650         rsp.strings[5] = baseStationLatitude;
    651         rsp.strings[6] = baseStationLongitude;
    652         rsp.strings[7] = concurrentServices;
    653         rsp.strings[8] = systemId;
    654         rsp.strings[9] = networkId;
    655         rsp.strings[10] = roamingIndicator;
    656         rsp.strings[11] = prlActive;
    657         rsp.strings[12] = defaultRoamingIndicator;
    658         rsp.strings[13] = registrationDeniedReason;
    659         rsp.strings[14] = primaryScrambingCode;
    660 
    661         result.responseProtobuf = rilSchema[packageNameAndSeperator +
    662                                  'RspStrings'].serialize(rsp);
    663         return result;
    664     }
    665 
    666     /**
    667      * Handle RIL_REQUEST_GPRS_REGISTRATION_STATE
    668      *
    669      * @param req is the Request
    670      */
    671     this.rilRequestGprsRegistrationState = function(req) { // 21
    672         print('Radio: rilRequestGprsRegistrationState');
    673 
    674         var rsp = new Object();
    675         rsp.strings = Array();
    676         rsp.strings[0] = registrationState;
    677         rsp.strings[1] = lac;
    678         rsp.strings[2] = cid;
    679         rsp.strings[3] = radioTechnology;
    680 
    681         result.responseProtobuf = rilSchema[packageNameAndSeperator +
    682                                  'RspStrings'].serialize(rsp);
    683         return result;
    684     }
    685 
    686     /**
    687      * Handle RIL_REQUEST_ANSWER
    688      *
    689      * @param req is the Request
    690      */
    691     this.rilRequestAnswer = function(req) { // 40
    692         print('Radio: rilRequestAnswer');
    693 
    694         if (numberActiveCalls != 1) {
    695             result.rilErrCode = RIL_E_GENERIC_FAILURE;
    696             return result;
    697         } else {
    698             for (var i = 0; i < calls.length; i++) {
    699                 if (typeof calls[i] != 'undefined') {
    700                     if (calls[i].state == CALLSTATE_INCOMING) {
    701                         calls[i].state = CALLSTATE_ACTIVE;
    702                         break;
    703                     } else {
    704                         result.rilErrCode = RIL_E_GENERIC_FAILURE;
    705                         this.removeCall(i);
    706                         return result;
    707                     }
    708                 } // end of processing call[i]
    709             } // end of for
    710         }
    711         incomingCallIsProcessed = true;
    712         return result;
    713     }
    714 
    715     /**
    716      * Handle RIL_REQUEST_QUERY_NETWORK_SELECTION_MODE
    717      *
    718      * @param req is the Request
    719      */
    720     this.rilRequestQueryNeworkSelectionMode = function(req) { // 45
    721         print('Radio: rilRequestQueryNeworkSelectionMode');
    722 
    723         var rsp = new Object();
    724         rsp.integers = Array();
    725         rsp.integers[0] = networkSelectionMode;
    726 
    727         result.responseProtobuf = rilSchema[packageNameAndSeperator +
    728                                  'RspIntegers'].serialize(rsp);
    729         return result;
    730     }
    731 
    732     /**
    733      * Handle RIL_REQUEST_SET_NETWORK_SELECTION_AUTOMATIC
    734      *
    735      * @param req is the Request
    736      */
    737     this.rilRequestSetNeworkSelectionAutomatic = function(req) { // 46
    738         print('Radio: rilRequestSetNeworkSelectionAutomatic');
    739 
    740         networkSelectionMode = NETWORK_SELECTION_MODE_AUTOMATIC;
    741 
    742         return result;
    743     }
    744 
    745     /**
    746      * Handle RIL_REQUEST_BASE_BAND_VERSION
    747      *
    748      * @param req is the Request
    749      */
    750     this.rilRequestBaseBandVersion = function(req) { // 51
    751         print('Radio: rilRequestBaseBandVersion');
    752         var rsp = new Object();
    753         rsp.strings = Array();
    754         rsp.strings[0] = gBaseBandVersion;
    755 
    756         result.responseProtobuf = rilSchema[packageNameAndSeperator +
    757                                  'RspStrings'].serialize(rsp);
    758         return result;
    759     }
    760 
    761     /**
    762      * Handle RIL_REQUEST_SEPRATE_CONNECTION
    763      * Separate a party from a multiparty call placing the multiparty call
    764      * (less the specified party) on hold and leaving the specified party
    765      * as the only other member of the current (active) call
    766      *
    767      * See TS 22.084 1.3.8.2 (iii)
    768      *
    769      * @param req is the Request
    770      */
    771     this.rilReqestSeparateConnection = function(req) {  // 52
    772         print('Radio: rilReqestSeparateConnection');
    773         var index = req.data.index;
    774 
    775         if (numberActiveCalls <= 0) {
    776             result.rilErrCode = RIL_E_GENERIC_FAILURE;
    777             return result;
    778         } else {
    779             // get the connection to separate
    780             var separateConn = this.getCall(req.data.index);
    781             if (separateConn == null) {
    782                 result.rilErrCode = RIL_E_GENERIC_FAILURE;
    783                 return result;
    784             } else {
    785                 if (separateConn.state != CALLSTATE_ACTIVE) {
    786                     result.rilErrCode = RIL_E_GENERIC_FAILURE;
    787                     return result;
    788                 }
    789                 // Put all other connections in hold.
    790                 for (var i = 0; i < calls.length; i++) {
    791                     if (index != i) {
    792                         // put all the active call to hold
    793                         if (typeof calls[i] != 'undefined') {
    794                             switch (calls[i].state) {
    795                                 case CALLSTATE_ACTIVE:
    796                                     calls[i].state = CALLSTATE_HOLDING;
    797                                     break;
    798                                 default:
    799                                     result.rilErrCode = RIL_E_GENERIC_FAILURE;
    800                                     break;
    801                             }
    802                             this.printCalls(calls);
    803                             if(result.rilErrCode == RIL_E_GENERIC_FAILURE) {
    804                                 return result;
    805                             }
    806                         }  // end of processing call[i]
    807                     }
    808                 }  // end of for
    809             }
    810         }
    811 
    812         // Send out RIL_UNSOL_CALL_STATE_CHANGED after the request is returned
    813         simulatedRadioWorker.add(
    814           {'reqNum' : CMD_UNSOL_CALL_STATE_CHANGED});
    815         return result;
    816     }
    817 
    818     /**
    819      * Handle RIL_REQUEST_SET_MUTE
    820      */
    821     this.rilRequestSetMute = function(req) { // 53
    822         print('Radio: rilRequestSetMute: req.data.state=' + req.data.state);
    823         muteState = req.data.state;
    824         if (gRadioState == RADIOSTATE_UNAVAILABLE) {
    825             result.rilErrCode = RIL_E_RADIO_NOT_AVAILABLE;
    826         }
    827         return result;
    828     }
    829 
    830     /**
    831      * Handle RIL_REQUEST_SCREEN_STATE
    832      *
    833      * @param req is the Request
    834      */
    835     this.rilRequestScreenState = function(req) { // 61
    836         print('Radio: rilRequestScreenState: req.data.state=' + req.data.state);
    837         screenState = req.data.state;
    838         return result;
    839     }
    840 
    841     /**
    842      * Delay test
    843      */
    844      this.cmdDelayTest = function(req) { // 2000
    845          print('cmdDelayTest: req.hello=' + req.hello);
    846          result.sendResponse = false;
    847          return result;
    848      }
    849 
    850      /**
    851       * Delay for RIL_UNSOL_SIGNAL_STRENGTH
    852       * TODO: Simulate signal strength changes:
    853       * Method 1: provide an array for signal strength, and send the unsolicited
    854       *           reponse periodically (the period can also be simulated)
    855       * Method 2: Simulate signal strength randomly (within a certain range) and
    856       *           send the response periodically.
    857       */
    858      this.cmdUnsolSignalStrength = function(req) { // 2001
    859          print('cmdUnsolSignalStrength: req.reqNum=' + req.reqNum);
    860          var rsp = new Object();
    861 
    862          // pack the signal strength into RspSignalStrength
    863          rsp.gwSignalstrength = gwSignalStrength;
    864          rsp.cdmaSignalstrength = cdmaSignalStrength;
    865          rsp.evdoSignalstrength = evdoSignalStrength;
    866 
    867          response = rilSchema[packageNameAndSeperator +
    868                               'RspSignalStrength'].serialize(rsp);
    869 
    870          // upldate signal strength
    871          sendRilUnsolicitedResponse(RIL_UNSOL_SIGNAL_STRENGTH, response);
    872 
    873          // Send the unsolicited signal strength every 1 minute.
    874          simulatedRadioWorker.addDelayed(
    875              {'reqNum' : CMD_UNSOL_SIGNAL_STRENGTH}, 60000);
    876 
    877          // this is not a request, no response is needed
    878          result.sendResponse = false;
    879          return result;
    880      }
    881 
    882      /**
    883       * Send RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED
    884       */
    885      this.cmdUnsolCallStateChanged = function(req) { // 2002
    886          print('cmdUnsolCallStateChanged: req.reqNum=' + req.reqNum);
    887          sendRilUnsolicitedResponse(RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED);
    888          result.sendResponse = false;
    889          return result;
    890      }
    891 
    892      /**
    893       * Simulate call state change
    894       */
    895      this.cmdCallStateChange = function(req) { // 2003
    896          print('cmdCallStateChange: req.reqNum=' + req.reqNum);
    897          print('cmdCallStateChange: req.callType=' + req.callType);
    898          print('cmdCallStateChange: req.callIndex=' + req.callIndex);
    899          print('cmdCallStateChange: req.nextState=' + req.nextState);
    900 
    901          // if it is an outgoing call, update the call state of the call
    902          // Send out call state changed flag
    903          var curCall = this.getCall(req.callIndex);
    904          this.printCall(curCall);
    905 
    906          if (curCall != null) {
    907              curCall.state = req.nextState;
    908          } else {
    909              this.removeCall(req.callIndex);
    910          }
    911 
    912          // TODO: if it is an incoming call, update the call state of the call
    913          // Send out call state change flag
    914          // Send out RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED
    915          simulatedRadioWorker.add(
    916            {'reqNum' : CMD_UNSOL_CALL_STATE_CHANGED});
    917          result.sendResponse = false;
    918          return result;
    919      }
    920 
    921      /**
    922       * send UNSOL_CALL_STATE_CHANGED and UNSOL_CALL_RING
    923       */
    924      this.cmdUnsolCallRing = function(req) { // 2004
    925          print('cmdUnsolCallRing: req.reqNum=' + req.reqNum);
    926          if(!incomingCallIsProcessed) {
    927              sendRilUnsolicitedResponse(RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED);
    928              sendRilUnsolicitedResponse(RIL_UNSOL_CALL_RING);
    929 
    930              // Send the next alert in 3 seconds. [refer to ril.h definition]
    931              simulatedRadioWorker.addDelayed(
    932                  {'reqNum' : CMD_UNSOL_CALL_RING}, 3000);
    933          }
    934          result.sendResponse = false;
    935          return result;
    936      }
    937 
    938      /**
    939       * Create an incoming call for the giving number
    940       * return CTRL_STATUS_ERR if there is already a call in any of the states of
    941       * dialing, alerting, incoming, waiting [TS 22 030 6.5] , else
    942       * return CTRL_STATUS_OK and update the call state
    943       */
    944      this.ctrlServerCmdStartInComingCall = function(req) {  // 1001
    945          print('ctrlServerCmdStartInComingCall: req.reqNum:' + req.reqNum);
    946          print('ctrlServerCmdStartInComingCall: req.data.phonenumber:' + req.data.phoneNumber);
    947 
    948          var phoneNumber = req.data.phoneNumber;
    949          var state;
    950 
    951          if (numberActiveCalls <= 0) {
    952              // If there is no connection in use, the call state is INCOMING
    953              state = CALLSTATE_INCOMING;
    954          } else {
    955              // If there is call in any of the states of dialing, alerting, incoming
    956              // waiting, this MT call can not be set
    957              for (var i  = 0; i < calls.length; i++) {
    958                  if (typeof calls[i] != 'undefined') {
    959                      if ( (calls[i].state == CALLSTATE_DIALING) ||
    960                           (calls[i].state == CALLSTATE_ALERTING) ||
    961                           (calls[i].state == CALLSTATE_INCOMING) ||
    962                           (calls[i].state == CALLSTATE_WAITING))
    963                      {
    964                          result.rilErrCode = CTRL_STATUS_ERR;
    965                          return result;
    966                      }
    967                  }
    968              }
    969              // If the incoming call is a second call, the state is WAITING
    970              state = CALLSTATE_WAITING;
    971          }
    972 
    973          // Add call to the call array
    974          this.addCall(state, phoneNumber, '');
    975 
    976          // set the incomingCallIsProcessed flag to be false
    977          incomingCallIsProcessed = false;
    978 
    979          simulatedRadioWorker.add(
    980            {'reqNum' : CMD_UNSOL_CALL_RING});
    981 
    982          result.rilErrCode = CTRL_STATUS_OK;
    983          return result;
    984     }
    985 
    986     /**
    987      * Handle control command CTRL_CMD_HANGUP_CONN_REMOTE
    988      *   hangup the connection for the given failure cause
    989      *
    990      *@param req is the control request
    991      */
    992     this.ctrlServerCmdHangupConnRemote = function(req) {    // 1002
    993         print('ctrlServerCmdHangupConnRemote: req.data.connectionId=' + req.data.connectionId +
    994               ' req.data.callFailCause' + req.data.callFailCause);
    995 
    996         var connection = req.data.connectionId;
    997         var failureCause = req.data.callFailCause;
    998 
    999         this.printCalls(calls);
   1000         var hangupCall = this.removeCall(connection);
   1001         if (hangupCall == null) {
   1002             print('ctrlServerCmdHangupConnRemote: connection id is required.');
   1003             result.rilErrCode = CTRL_STATUS_ERR;
   1004             return result;
   1005         } else {
   1006             // for incoming call, stop sending call ring
   1007             if ((hangupCall.state == CALLSTATE_INCOMING) ||
   1008                 (hangupCall.state == CALLSTATE_WAITING)) {
   1009                 incomingCallIsProcessed = true;
   1010             }
   1011         }
   1012         this.printCalls(calls);
   1013         lastCallFailCause = failureCause;
   1014 
   1015         // send out call state changed response
   1016         simulatedRadioWorker.add(
   1017             {'reqNum' : CMD_UNSOL_CALL_STATE_CHANGED});
   1018 
   1019         result.rilErrCode = CTRL_STATUS_OK;
   1020         return result;
   1021     }
   1022 
   1023     /**
   1024      * Set call transition flag
   1025      */
   1026     this.ctrlServerCmdSetCallTransitionFlag = function(req) {  // 1003
   1027         print('ctrlServerCmdSetCallTransitionFlag: flag=' + req.data.flag);
   1028 
   1029         callTransitionFlag = req.data.flag;
   1030         result.rilErrCode = CTRL_STATUS_OK;
   1031         return result;
   1032     }
   1033 
   1034     /**
   1035      * Set the dialing call to alert
   1036      */
   1037     this.ctrlServerCmdSetCallAlert = function(req) {    // 1004
   1038         print('ctrlServerCmdSetCallAlert: E');
   1039 
   1040         if (callTransitionFlag == false) {
   1041             print('ctrlServerCmdSetCallAlert: need to set the flag first');
   1042             result.rilErrCode = CTRL_STATUS_ERR;
   1043             return result;
   1044         }
   1045         if (numberActiveCalls <= 0) {
   1046             print('ctrlServerCmdSetCallAlert: no active calls');
   1047             result.rilErrCode = CTRL_STATUS_ERR;
   1048             return result;
   1049         }
   1050         var dialingCalls = this.countCallsInState(CALLSTATE_DIALING);
   1051         var index = this.getCallIdByState(CALLSTATE_DIALING);
   1052         if ((dialingCalls == 1) && (index != null)) {
   1053             calls[index].state = CALLSTATE_ALERTING;
   1054         } else {
   1055             // if there 0 or more than one call in dialing state, return error
   1056             print('ctrlServerCmdSetCallAlert: no valid calls in dialing state');
   1057             result.rilErrCode = CTRL_STATUS_ERR;
   1058             return result;
   1059         }
   1060         // send unsolicited call state change response
   1061         simulatedRadioWorker.add(
   1062             {'reqNum' : CMD_UNSOL_CALL_STATE_CHANGED});
   1063 
   1064         result.rilErrCode = CTRL_STATUS_OK;
   1065         return result;
   1066     }
   1067 
   1068     /**
   1069      * Set the alserting call to active
   1070      */
   1071     this.ctrlServerCmdSetCallActive = function(req) {   // 1005
   1072         print('ctrlServerCmdSetCallActive: E');
   1073 
   1074         if (callTransitionFlag == false) {
   1075             print('ctrlServerCmdSetCallActive: need to set the flag firt');
   1076             result.rilErrCode = CTRL_STATUS_ERR;
   1077             return result;
   1078         }
   1079         if (numberActiveCalls <= 0) {
   1080             print('ctrlServerCmdSetCallActive: no active calls');
   1081             result.rilErrCode = CTRL_STATUS_ERR;
   1082             return result;
   1083         }
   1084         var alertingCalls = this.countCallsInState(CALLSTATE_ALERTING);
   1085         var index = this.getCallIdByState(CALLSTATE_ALERTING);
   1086         if ((alertingCalls == 1) && (index != null)) {
   1087             calls[index].state = CALLSTATE_ACTIVE;
   1088         } else {
   1089             print('ctrlServerCmdSetCallActive: no valid calls in alert state');
   1090             result.rilErrCode = CTRL_STATUS_ERR;
   1091             return result;
   1092         }
   1093         // send out unsolicited call state change response
   1094         simulatedRadioWorker.add(
   1095             {'reqNum' : CMD_UNSOL_CALL_STATE_CHANGED});
   1096 
   1097         result.rilErrCode = CTRL_STATUS_OK;
   1098         return result;
   1099     }
   1100 
   1101     /**
   1102      * Add a dialing call
   1103      */
   1104     this.ctrlServerCmdAddDialingCall = function(req) {   // 1006
   1105         print('ctrlServerCmdAddDialingCall: E');
   1106 
   1107         var phoneNumber = req.data.phoneNumber;
   1108         var dialingCalls = this.countCallsInState(CALLSTATE_DIALING);
   1109         if (dialingCalls == 0) {
   1110             this.addCall(CALLSTATE_DIALING, phoneNumber, '');
   1111             result.rilErrCode = CTRL_STATUS_OK;
   1112         } else {
   1113             print('ctrlServerCmdAddDialingCall: add dialing call failed');
   1114             result.rilErrCode = CTRL_STATUS_ERR;
   1115         }
   1116         return result;
   1117     }
   1118 
   1119     /**
   1120      * Process the request by dispatching to the request handlers
   1121      */
   1122     this.process = function(req) {
   1123         try {
   1124             print('Radio E: req.reqNum=' + req.reqNum + ' req.token=' + req.token);
   1125 
   1126             // Assume the result will be true, successful and nothing to return
   1127             result.sendResponse = true;
   1128             result.rilErrCode = RIL_E_SUCCESS;
   1129             result.responseProtobuf = emptyProtobuf;
   1130 
   1131             try {
   1132                 // Pass "this" object to each ril request call such that
   1133                 // they have the same scope
   1134                 result = (this.radioDispatchTable[req.reqNum]).call(this, req);
   1135             } catch (err) {
   1136                 print('Radio:process err = ' + err);
   1137                 print('Radio: Unknown reqNum=' + req.reqNum);
   1138                 result.rilErrCode = RIL_E_REQUEST_NOT_SUPPORTED;
   1139             }
   1140 
   1141             if (req.reqNum < 200) {
   1142                 lastReq = req.reqNum;
   1143             }
   1144             if (result.sendResponse) {
   1145                 if (isCtrlServerDispatchCommand(req.reqNum)) {
   1146                     //print('Command ' + req.reqNum + ' is a control server command');
   1147                     sendCtrlRequestComplete(result.rilErrCode, req.reqNum,
   1148                       req.token, result.responseProtobuf);
   1149                 } else {
   1150                     //print('Request ' + req.reqNum + ' is a ril request');
   1151                     sendRilRequestComplete(result.rilErrCode, req.reqNum,
   1152                       req.token, result.responseProtobuf);
   1153                 }
   1154             }
   1155             //print('Radio X: req.reqNum=' + req.reqNum + ' req.token=' + req.token);
   1156         } catch (err) {
   1157             print('Radio: Exception req.reqNum=' +
   1158                     req.reqNum + ' req.token=' + req.token + ' err=' + err);
   1159         }
   1160     }
   1161 
   1162     /**
   1163      * Construct the simulated radio
   1164      */
   1165     print('Radio: constructor E');
   1166     this.radioDispatchTable = new Array();
   1167     this.radioDispatchTable[RIL_REQUEST_GET_CURRENT_CALLS] = // 9
   1168                 this.rilRequestGetCurrentCalls;
   1169     this.radioDispatchTable[RIL_REQUEST_DIAL] = // 10
   1170                 this.rilRequestDial;
   1171     this.radioDispatchTable[RIL_REQUEST_HANGUP] =  // 12
   1172                 this.rilRequestHangUp;
   1173     this.radioDispatchTable[RIL_REQUEST_HANGUP_WAITING_OR_BACKGROUND] = // 13
   1174                 this.rilRequestHangupWaitingOrBackground;
   1175     this.radioDispatchTable[RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND] =  // 14
   1176                 this.rilRequestHangUpForegroundResumeBackground;
   1177     this.radioDispatchTable[RIL_REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE] =  // 15
   1178                 this.rilRequestSwitchWaitingOrHoldingAndActive;
   1179     this.radioDispatchTable[RIL_REQUEST_CONFERENCE] = // 16
   1180                 this.rilRequestConference;
   1181     this.radioDispatchTable[RIL_REQUEST_LAST_CALL_FAIL_CAUSE] = // 18
   1182                 this.rilRequestLastCallFailCause;
   1183     this.radioDispatchTable[RIL_REQUEST_SIGNAL_STRENGTH] = // 19
   1184                 this.rilRequestSignalStrength;
   1185     this.radioDispatchTable[RIL_REQUEST_REGISTRATION_STATE] = // 20
   1186                 this.rilRequestRegistrationState;
   1187     this.radioDispatchTable[RIL_REQUEST_GPRS_REGISTRATION_STATE] = // 21
   1188                 this.rilRequestGprsRegistrationState;
   1189     this.radioDispatchTable[RIL_REQUEST_ANSWER] = // 40
   1190                 this.rilRequestAnswer;
   1191     this.radioDispatchTable[RIL_REQUEST_QUERY_NETWORK_SELECTION_MODE] = // 45
   1192                 this.rilRequestQueryNeworkSelectionMode;
   1193     this.radioDispatchTable[RIL_REQUEST_SET_NETWORK_SELECTION_AUTOMATIC] = // 46
   1194                 this.rilRequestSetNeworkSelectionAutomatic;
   1195     this.radioDispatchTable[RIL_REQUEST_BASEBAND_VERSION] = // 51
   1196                 this.rilRequestBaseBandVersion;
   1197     this.radioDispatchTable[RIL_REQUEST_SEPARATE_CONNECTION] = // 52
   1198                 this.rilReqestSeparateConnection;
   1199     this.radioDispatchTable[RIL_REQUEST_SET_MUTE] = // 53
   1200                 this.rilRequestSetMute;
   1201     this.radioDispatchTable[RIL_REQUEST_SCREEN_STATE] = // 61
   1202                 this.rilRequestScreenState;
   1203 
   1204     this.radioDispatchTable[CTRL_CMD_SET_MT_CALL] = //1001
   1205                 this.ctrlServerCmdStartInComingCall;
   1206     this.radioDispatchTable[CTRL_CMD_HANGUP_CONN_REMOTE] = //1002
   1207                 this.ctrlServerCmdHangupConnRemote;
   1208     this.radioDispatchTable[CTRL_CMD_SET_CALL_TRANSITION_FLAG] = //1003
   1209                 this.ctrlServerCmdSetCallTransitionFlag;
   1210     this.radioDispatchTable[CTRL_CMD_SET_CALL_ALERT] =  // 1004
   1211                 this.ctrlServerCmdSetCallAlert;
   1212     this.radioDispatchTable[CTRL_CMD_SET_CALL_ACTIVE] =  // 1005
   1213                 this.ctrlServerCmdSetCallActive;
   1214     this.radioDispatchTable[CTRL_CMD_ADD_DIALING_CALL] =  // 1006
   1215                 this.ctrlServerCmdAddDialingCall;
   1216 
   1217     this.radioDispatchTable[CMD_DELAY_TEST] = // 2000
   1218                 this.cmdDelayTest;
   1219     this.radioDispatchTable[CMD_UNSOL_SIGNAL_STRENGTH] =  // 2001
   1220                 this.cmdUnsolSignalStrength;
   1221     this.radioDispatchTable[CMD_UNSOL_CALL_STATE_CHANGED] =  // 2002
   1222                 this.cmdUnsolCallStateChanged;
   1223     this.radioDispatchTable[CMD_CALL_STATE_CHANGE] = //2003
   1224                 this.cmdCallStateChange;
   1225     this.radioDispatchTable[CMD_UNSOL_CALL_RING] = //2004
   1226                 this.cmdUnsolCallRing;
   1227 
   1228     print('Radio: constructor X');
   1229 }
   1230 
   1231 // The simulated radio instance and its associated Worker
   1232 var simulatedRadio = new Radio();
   1233 var simulatedRadioWorker = new Worker(function (req) {
   1234     simulatedRadio.process(req);
   1235 });
   1236 simulatedRadioWorker.run();
   1237 
   1238 // TODO: this is a workaround for bug http://b/issue?id=3001613
   1239 // When adding a new all, two RIL_REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE
   1240 // will be sent from the framework.
   1241 var lastReq = 0;
   1242 
   1243 /**
   1244  * Optional tests
   1245  */
   1246 if (false) {
   1247     include("simulated_radio_tests.js");
   1248 }
   1249