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  * @fileoverview Mock Radio Interface Layer (RIL) used for testing
     19  *
     20  * The following routines are defined in c++:
     21  *
     22  * Print a string to android log
     23  *   print(string)
     24  *
     25  * Read a file to a string.
     26  *   String readFileToString(String fileName)
     27  *
     28  * Read a file to a Buffer.
     29  *   Buffer readFileToBuffer(String fileName)
     30  *
     31  * Send an response unsolicited response to the framework.
     32  *   sendRilUnsolicitedResponse(Number responseNum, Buffer responseProtobuf)
     33  *
     34  * Send a completion request to the framework.
     35  *   sendRilRequestComplete(Number rilErrCode, Number reqNum,
     36  *                              String token, Buffer responseProtobuf)
     37  *
     38  * Send a complete request to the controller.
     39  *   sendCtrlRequestComplete(Number ctrlStatus, Number reqNum,
     40  *                              String token, Buffer responseProtobuf)
     41  *
     42  * Include the javascript file.
     43  *   include(string)
     44  *
     45  * The following objects are defined in c++
     46  *
     47  * Buffer is defined in node_buffer and provides a wrapper
     48  * for a buffer that can be shared between c++ and js.
     49  *   Buffer(length)
     50  *     Buffer::length()
     51  *     Buffer::data()
     52  *
     53  * Schema is defined in protobuf_v8 and converts between
     54  * a buffer and an object. A protobuf descriptor, ril.desc
     55  * and ctrl.desc, is used to drive the conversation.
     56  *     Object Schema::parse(Buffer protobuf)
     57  *     Buffer Schema::serialize(object)
     58  *
     59  * Worker is a thread which receives messages to be handled.
     60  * It is passed a function which is called once for each
     61  * message as it arrives. Call the add method to queue up
     62  * requests for the worker function to process.
     63  *   Object Worker(function (req))
     64  *      Worker::add(req);
     65  */
     66 
     67 /**
     68  * Globals
     69  */
     70 
     71 include("ril_vars.js");
     72 
     73 var NULL_RESPONSE_STRING = '*magic-null*';
     74 
     75 // The state of the radio, needed by currentState()
     76 var gRadioState = RADIOSTATE_UNAVAILABLE;
     77 
     78 // The state of the screen
     79 var gScreenState = 0;
     80 
     81 // The base band version
     82 var gBaseBandVersion = 'mock-ril 0.1';
     83 
     84 // define a global variable to access the global object
     85 var globals = this;
     86 
     87 // Empty Protobuf, defined here so we don't have
     88 // to recreate an empty Buffer frequently
     89 var emptyProtobuf = new Buffer();
     90 
     91 // Get the ril description file and create a schema
     92 var packageNameAndSeperator = 'ril_proto.';
     93 var rilSchema = new Schema(readFileToBuffer('ril.desc'));
     94 var ctrlSchema = new Schema(readFileToBuffer('ctrl.desc'));
     95 
     96 /**
     97  * Print properties of an object
     98  */
     99 function printProperties(obj, maxDepth, depth) {
    100     if (typeof maxDepth == 'undefined') {
    101         maxDepth = 1;
    102     }
    103     if (typeof depth == 'undefined') {
    104         depth = 1;
    105     }
    106     if (depth == 1) {
    107         print('printProperties:');
    108     }
    109     for (var property in obj) {
    110         try {
    111             if ((typeof obj[property] == 'object')
    112                     && (depth < maxDepth)) {
    113                 printProperties(obj[property], maxDepth, depth+1);
    114             } else {
    115                 print(depth + ': ' + property + '=' + obj[property] +
    116                         ' type=' + typeof obj[property]);
    117             }
    118         } catch (err) {
    119             print('err=' + err)
    120         }
    121     }
    122 }
    123 
    124 // Test printProperties
    125 if (false) {
    126     var myObject = { 'field1' : '1', 'field2' : '2', 'hello' : [ 'hi', 'there' ] };
    127     printProperties(myObject, 3);
    128 }
    129 
    130 /**
    131  * Include the components
    132  */
    133 
    134 include("simulated_radio.js");
    135 include("simulated_icc.js");
    136 include("ctrl_server.js");
    137 
    138 /**
    139  * Construct a new request which is passed to the
    140  * Worker handler method.
    141  */
    142 function Request(reqNum, token, protobuf, schema, schemaName) {
    143     this.reqNum = reqNum;
    144     this.token = token;
    145     try {
    146         this.data = schema[packageNameAndSeperator + schemaName].parse(protobuf);
    147     } catch (err) {
    148         // not a valid protobuf in the request
    149         this.data = null;
    150     }
    151 }
    152 
    153 /**
    154  * Dispatch incoming requests from RIL to the appropriate component.
    155  */
    156 function onRilRequest(reqNum, token, requestProtobuf) {
    157     try {
    158         //print('onRilRequest E: reqNum=' + reqNum + ' token=' + token);
    159 
    160         /**
    161          * Validate parameters
    162          */
    163         rilErrCode = RIL_E_SUCCESS;
    164         if (typeof reqNum != 'number') {
    165             print('onRilRequest: reqNum is not a number');
    166             rilErrCode = RIL_E_GENERIC_FAILURE;
    167         }
    168         if (typeof token != 'number') {
    169             print('onRilRequest: token is not a number');
    170             rilErrCode = RIL_E_GENERIC_FAILURE;
    171         }
    172         if (typeof requestProtobuf != 'object') {
    173             print('onRilRequest: requestProtobuf is not an object');
    174             rilErrCode = RIL_E_GENERIC_FAILURE;
    175         }
    176         if (rilErrCode != RIL_E_SUCCESS) {
    177             sendRilRequestComplete(rilErrCode, reqNum, token);
    178             return 'onRilRequest X: invalid parameter';
    179         }
    180 
    181         try {
    182             //print('onRilRequest: get entry from dispatchTable reqNum=' + reqNum);
    183             entry = dispatchTable[reqNum];
    184             if (typeof entry == 'undefined') {
    185                 throw ('entry = dispatchTable[' + reqNum + '] was undefined');
    186             } else {
    187                 req = new Request(reqNum, token, requestProtobuf, rilSchema, entry.schemaName);
    188                 for(i = 0; i < entry.components.length; i++) {
    189                     entry.components[i].add(req);
    190                 }
    191             }
    192         } catch (err) {
    193             print('onRilRequest: Unknown reqNum=' + reqNum + ' err=' + err);
    194             sendRilRequestComplete(RIL_E_REQUEST_NOT_SUPPORTED, reqNum, token);
    195         }
    196         // print('onRilRequest X: reqNum=' + reqNum + ' token=' + token);
    197     } catch (err) {
    198         print('onRilRequest X: Exception err=' + err);
    199         return('onRilRequest X: Exception err=' + err);
    200     }
    201     return 'onRilRequest X';
    202 }
    203 
    204 function onUnsolicitedTick(tick) {
    205     print('onUnsolicitedTick EX tick=' + tick);
    206     return 3;
    207 }
    208 
    209 /**
    210  * Dispatch table for requests
    211  *
    212  * Each table entry is index by the RIL_REQUEST_xxxx
    213  * and contains an array of components this request
    214  * is to be sent to and the name of the schema
    215  * that converts the incoming protobuf to the
    216  * appropriate request data.
    217  *
    218  * DispatchTable[RIL_REQUEST_xxx].components = Array of components
    219  * DisptachTable[RIL_REQUEST_xxx].Entry.schemaName = 'Name-of-schema';
    220  */
    221 var dispatchTable = new Array();
    222 
    223 dispatchTable[RIL_REQUEST_GET_SIM_STATUS] = { // 1
    224     'components' : [simulatedIccWorker],
    225     'schemaName' : 'ReqGetSimStatus',
    226 };
    227 dispatchTable[RIL_REQUEST_ENTER_SIM_PIN] = { // 2
    228     'components' : [simulatedIccWorker],
    229     'schemaName' : 'ReqEnterSimPin',
    230 };
    231 dispatchTable[RIL_REQUEST_GET_CURRENT_CALLS] = { // 9
    232     'components' : [simulatedRadioWorker],
    233 };
    234 dispatchTable[RIL_REQUEST_DIAL] = { // 10
    235     'components' : [simulatedRadioWorker],
    236     'schemaName' : 'ReqDial',
    237 };
    238 dispatchTable[RIL_REQUEST_GET_IMSI] = { // 11
    239     'components' : [simulatedIccWorker],
    240 };
    241 dispatchTable[RIL_REQUEST_HANGUP] = { // 12
    242     'components' : [simulatedRadioWorker],
    243     'schemaName' : 'ReqHangUp',
    244 };
    245 dispatchTable[RIL_REQUEST_HANGUP_WAITING_OR_BACKGROUND] =  { // 13
    246     'components' : [simulatedRadioWorker],
    247 };
    248 dispatchTable[RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND] = { // 14
    249     'components' : [simulatedRadioWorker],
    250 };
    251 dispatchTable[RIL_REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE] = { // 15
    252     'components' : [simulatedRadioWorker],
    253 };
    254 dispatchTable[RIL_REQUEST_CONFERENCE] = { // 16
    255     'components' : [simulatedRadioWorker],
    256 };
    257 dispatchTable[RIL_REQUEST_LAST_CALL_FAIL_CAUSE] = { // 18
    258     'components' : [simulatedRadioWorker],
    259 };
    260 dispatchTable[RIL_REQUEST_SIGNAL_STRENGTH]  = { // 19
    261     'components' : [simulatedRadioWorker],
    262 };
    263 dispatchTable[RIL_REQUEST_VOICE_REGISTRATION_STATE] = { // 20
    264     'components' : [simulatedRadioWorker],
    265 };
    266 dispatchTable[RIL_REQUEST_DATA_REGISTRATION_STATE] = { // 21
    267     'components' : [simulatedRadioWorker],
    268 };
    269 dispatchTable[RIL_REQUEST_OPERATOR] = { // 22
    270     'components' : [simulatedIccWorker],
    271 };
    272 dispatchTable[RIL_REQUEST_GET_IMEI] = { // 38
    273     'components' : [simulatedIccWorker],
    274 };
    275 dispatchTable[RIL_REQUEST_GET_IMEISV] = { // 39
    276     'components' : [simulatedIccWorker],
    277 };
    278 dispatchTable[RIL_REQUEST_ANSWER] = { // 40
    279     'components' : [simulatedRadioWorker],
    280 };
    281 dispatchTable[RIL_REQUEST_QUERY_NETWORK_SELECTION_MODE] = { // 45
    282     'components' : [simulatedRadioWorker],
    283 };
    284 dispatchTable[RIL_REQUEST_SET_NETWORK_SELECTION_AUTOMATIC] = { // 46
    285     'components' : [simulatedRadioWorker],
    286 };
    287 dispatchTable[RIL_REQUEST_BASEBAND_VERSION] = { // 51
    288     'components' : [simulatedRadioWorker],
    289 };
    290 dispatchTable[RIL_REQUEST_SEPARATE_CONNECTION] = { // 52
    291     'components' : [simulatedRadioWorker],
    292     'schemaName' : 'ReqSeparateConnection',
    293 };
    294 dispatchTable[RIL_REQUEST_SET_MUTE ] = { // 53
    295     'components' : [simulatedRadioWorker],
    296     'schemaName' : 'ReqSetMute',
    297 };
    298 dispatchTable[RIL_REQUEST_SCREEN_STATE] = { // 61
    299     'components' : [simulatedRadioWorker],
    300     'schemaName' : 'ReqScreenState',
    301 };
    302 
    303 /**
    304  * Start the mock rill after loading
    305  */
    306 function startMockRil() {
    307     print("startMockRil E:");
    308     setRadioState(RADIOSTATE_SIM_READY);
    309     // send the signal strength after 5 seconds, wait until mock ril is started
    310     simulatedRadioWorker.addDelayed({
    311       'reqNum' : CMD_UNSOL_SIGNAL_STRENGTH}, 5000);
    312     print("startMockRil X:");
    313 }
    314 
    315 /**
    316  * Optional tests
    317  */
    318 if (false) {
    319     include("mock_ril_tests.js");
    320 }
    321