• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
71include("ril_vars.js");
72
73var NULL_RESPONSE_STRING = '*magic-null*';
74
75// The state of the radio, needed by currentState()
76var gRadioState = RADIOSTATE_UNAVAILABLE;
77
78// The state of the screen
79var gScreenState = 0;
80
81// The base band version
82var gBaseBandVersion = 'mock-ril 0.1';
83
84// define a global variable to access the global object
85var globals = this;
86
87// Empty Protobuf, defined here so we don't have
88// to recreate an empty Buffer frequently
89var emptyProtobuf = new Buffer();
90
91// Get the ril description file and create a schema
92var packageNameAndSeperator = 'ril_proto.';
93var rilSchema = new Schema(readFileToBuffer('ril.desc'));
94var ctrlSchema = new Schema(readFileToBuffer('ctrl.desc'));
95
96/**
97 * Print properties of an object
98 */
99function 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
125if (false) {
126    var myObject = { 'field1' : '1', 'field2' : '2', 'hello' : [ 'hi', 'there' ] };
127    printProperties(myObject, 3);
128}
129
130/**
131 * Include the components
132 */
133
134include("simulated_radio.js");
135include("simulated_icc.js");
136include("ctrl_server.js");
137
138/**
139 * Construct a new request which is passed to the
140 * Worker handler method.
141 */
142function 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 */
156function 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
204function 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 */
221var dispatchTable = new Array();
222
223dispatchTable[RIL_REQUEST_GET_SIM_STATUS] = { // 1
224    'components' : [simulatedIccWorker],
225    'schemaName' : 'ReqGetSimStatus',
226};
227dispatchTable[RIL_REQUEST_ENTER_SIM_PIN] = { // 2
228    'components' : [simulatedIccWorker],
229    'schemaName' : 'ReqEnterSimPin',
230};
231dispatchTable[RIL_REQUEST_GET_CURRENT_CALLS] = { // 9
232    'components' : [simulatedRadioWorker],
233};
234dispatchTable[RIL_REQUEST_DIAL] = { // 10
235    'components' : [simulatedRadioWorker],
236    'schemaName' : 'ReqDial',
237};
238dispatchTable[RIL_REQUEST_GET_IMSI] = { // 11
239    'components' : [simulatedIccWorker],
240};
241dispatchTable[RIL_REQUEST_HANGUP] = { // 12
242    'components' : [simulatedRadioWorker],
243    'schemaName' : 'ReqHangUp',
244};
245dispatchTable[RIL_REQUEST_HANGUP_WAITING_OR_BACKGROUND] =  { // 13
246    'components' : [simulatedRadioWorker],
247};
248dispatchTable[RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND] = { // 14
249    'components' : [simulatedRadioWorker],
250};
251dispatchTable[RIL_REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE] = { // 15
252    'components' : [simulatedRadioWorker],
253};
254dispatchTable[RIL_REQUEST_CONFERENCE] = { // 16
255    'components' : [simulatedRadioWorker],
256};
257dispatchTable[RIL_REQUEST_LAST_CALL_FAIL_CAUSE] = { // 18
258    'components' : [simulatedRadioWorker],
259};
260dispatchTable[RIL_REQUEST_SIGNAL_STRENGTH]  = { // 19
261    'components' : [simulatedRadioWorker],
262};
263dispatchTable[RIL_REQUEST_REGISTRATION_STATE] = { // 20
264    'components' : [simulatedRadioWorker],
265};
266dispatchTable[RIL_REQUEST_GPRS_REGISTRATION_STATE] = { // 21
267    'components' : [simulatedRadioWorker],
268};
269dispatchTable[RIL_REQUEST_OPERATOR] = { // 22
270    'components' : [simulatedIccWorker],
271};
272dispatchTable[RIL_REQUEST_GET_IMEI] = { // 38
273    'components' : [simulatedIccWorker],
274};
275dispatchTable[RIL_REQUEST_GET_IMEISV] = { // 39
276    'components' : [simulatedIccWorker],
277};
278dispatchTable[RIL_REQUEST_ANSWER] = { // 40
279    'components' : [simulatedRadioWorker],
280};
281dispatchTable[RIL_REQUEST_QUERY_NETWORK_SELECTION_MODE] = { // 45
282    'components' : [simulatedRadioWorker],
283};
284dispatchTable[RIL_REQUEST_SET_NETWORK_SELECTION_AUTOMATIC] = { // 46
285    'components' : [simulatedRadioWorker],
286};
287dispatchTable[RIL_REQUEST_BASEBAND_VERSION] = { // 51
288    'components' : [simulatedRadioWorker],
289};
290dispatchTable[RIL_REQUEST_SEPARATE_CONNECTION] = { // 52
291    'components' : [simulatedRadioWorker],
292    'schemaName' : 'ReqSeparateConnection',
293};
294dispatchTable[RIL_REQUEST_SET_MUTE ] = { // 53
295    'components' : [simulatedRadioWorker],
296    'schemaName' : 'ReqSetMute',
297};
298dispatchTable[RIL_REQUEST_SCREEN_STATE] = { // 61
299    'components' : [simulatedRadioWorker],
300    'schemaName' : 'ReqScreenState',
301};
302
303/**
304 * Start the mock rill after loading
305 */
306function 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 */
318if (false) {
319    include("mock_ril_tests.js");
320}
321