OSDN Git Service

Add LTE location information to DATA_REGISTRATION_STATE
[android-x86/hardware-ril.git] / mock-ril / src / cpp / js_support.cpp
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 #include <v8.h>
18 #include "ril.h"
19
20 #include "ctrl_server.h"
21 #include "logging.h"
22 #include "node_buffer.h"
23 #include "node_object_wrap.h"
24 #include "node_util.h"
25 #include "protobuf_v8.h"
26 #include "responses.h"
27 #include "status.h"
28 #include "util.h"
29 #include "worker.h"
30 #include "worker_v8.h"
31
32 #include "js_support.h"
33
34 //#define JS_SUPPORT_DEBUG
35 #ifdef  JS_SUPPORT_DEBUG
36
37 #define DBG(...) ALOGD(__VA_ARGS__)
38
39 #else
40
41 #define DBG(...)
42
43 #endif
44
45 /**
46  * Current Radio state
47  */
48 RIL_RadioState gRadioState = RADIO_STATE_UNAVAILABLE;
49
50 v8::Handle<v8::Value> RadioStateGetter(v8::Local<v8::String> property,
51         const v8::AccessorInfo& info) {
52     return v8::Integer::New((int)gRadioState);
53 }
54
55 void RadioStateSetter(v8::Local<v8::String> property,
56         v8::Local<v8::Value> value, const v8::AccessorInfo& info) {
57     gRadioState = RIL_RadioState(value->Int32Value());
58 }
59
60 // A javascript sleep for a number of milli-seconds
61 v8::Handle<v8::Value> MsSleep(const v8::Arguments& args) {
62     if (args.Length() != 1) {
63         DBG("MsSleep: expecting milli-seconds to sleep");
64     } else {
65         v8::Handle<v8::Value> v8MsValue(args[0]->ToObject());
66         int ms = int(v8MsValue->NumberValue());
67         v8::Unlocker unlocker;
68         usleep(ms * 1000);
69         v8::Locker locker;
70     }
71     return v8::Undefined();
72 }
73
74 // A javascript print function
75 v8::Handle<v8::Value> Print(const v8::Arguments& args) {
76     bool first = true;
77     const int str_size = 1000;
78     char* str = new char[str_size];
79     int offset = 0;
80     for (int i = 0; i < args.Length(); i++) {
81         v8::HandleScope handle_scope;
82         if (first) {
83             first = false;
84         } else {
85             offset += snprintf(&str[offset], str_size, " ");
86         }
87         v8::String::Utf8Value strUtf8(args[i]);
88         const char* cstr = ToCString(strUtf8);
89         offset += snprintf(&str[offset], str_size, "%s", cstr);
90     }
91     ALOGD("%s", str);
92     delete [] str;
93     return v8::Undefined();
94 }
95
96 int ReadFile(const char *fileName, char** data, size_t *length) {
97     int status;
98     char* buffer = NULL;
99     size_t fileLength = 0;
100     FILE *f;
101
102     DBG("ReadFile E fileName=%s", fileName);
103
104     f = fopen(fileName, "rb");
105     if (f == NULL) {
106         DBG("Could not fopen '%s'", fileName);
107         status = STATUS_COULD_NOT_OPEN_FILE;
108     } else {
109         // Determine the length of the file
110         fseek(f, 0, SEEK_END);
111         fileLength = ftell(f);
112         DBG("fileLength=%d", fileLength);
113         rewind(f);
114
115         // Read file into a buffer
116         buffer = new char[fileLength+1];
117         size_t readLength = fread(buffer, 1, fileLength, f);
118         if (readLength != fileLength) {
119             DBG("Couldn't read entire file");
120             delete [] buffer;
121             buffer = NULL;
122             status = STATUS_COULD_NOT_READ_FILE;
123         } else {
124             DBG("File read");
125             buffer[fileLength] = 0;
126             status = STATUS_OK;
127         }
128         fclose(f);
129     }
130
131     if (length != NULL) {
132         *length = fileLength;
133     }
134     *data = buffer;
135     DBG("ReadFile X status=%d", status);
136     return status;
137 }
138
139 char *CreateFileName(const v8::Arguments& args) {
140     v8::String::Utf8Value fileNameUtf8Value(args[0]);
141     const char* fileName = ToCString(fileNameUtf8Value);
142     const char* directory = "/sdcard/data/";
143
144     int fullPathLength = strlen(directory) + strlen(fileName) + 1;
145     char * fullPath = new char[fullPathLength];
146     strncpy(fullPath, directory, fullPathLength);
147     strncat(fullPath, fileName, fullPathLength);
148     return fullPath;
149 }
150
151 // A javascript read file function arg[0] = filename
152 v8::Handle<v8::Value> ReadFileToString(const v8::Arguments& args) {
153     DBG("ReadFileToString E");
154     v8::HandleScope handle_scope;
155     v8::Handle<v8::Value> retValue;
156
157     if (args.Length() < 1) {
158         // No file name return Undefined
159         DBG("ReadFile X no argumens");
160         return v8::Undefined();
161     } else {
162         char *fileName = CreateFileName(args);
163
164         char *buffer;
165         int status = ReadFile(fileName, &buffer);
166         if (status == 0) {
167             retValue = v8::String::New(buffer);
168         } else {
169             retValue = v8::Undefined();
170         }
171     }
172     DBG("ReadFileToString X");
173     return retValue;
174 }
175
176 // A javascript read file function arg[0] = filename
177 v8::Handle<v8::Value> ReadFileToBuffer(const v8::Arguments& args) {
178     DBG("ReadFileToBuffer E");
179     v8::HandleScope handle_scope;
180     v8::Handle<v8::Value> retValue;
181
182     if (args.Length() < 1) {
183         // No file name return Undefined
184         DBG("ReadFileToBuffer X no argumens");
185         return v8::Undefined();
186     } else {
187         char *fileName = CreateFileName(args);
188
189         char *buffer;
190         size_t length;
191         int status = ReadFile(fileName, &buffer, &length);
192         if (status == 0) {
193             Buffer *buf = Buffer::New(length);
194             memmove(buf->data(), buffer, length);
195             retValue = buf->handle_;
196         } else {
197             retValue = v8::Undefined();
198         }
199     }
200     DBG("ReadFileToBuffer X");
201     return retValue;
202 }
203
204 void ErrorCallback(v8::Handle<v8::Message> message,
205         v8::Handle<v8::Value> data) {
206     LogErrorMessage(message, "");
207 }
208
209 // Read, compile and run a javascript file
210 v8::Handle<v8::Value> Include(const v8::Arguments& args) {
211     DBG("Include E");
212     v8::HandleScope handle_scope;
213     v8::Handle<v8::Value> retValue;
214     v8::TryCatch try_catch;
215     try_catch.SetVerbose(true);
216
217     if (args.Length() < 1) {
218         // No file name return Undefined
219         DBG("Include X no argumens");
220         return v8::Undefined();
221     } else {
222         char *fileName = CreateFileName(args);
223
224         char *buffer;
225         int status = ReadFile(fileName, &buffer);
226         if (status == 0) {
227             runJs(v8::Context::GetCurrent(), &try_catch, fileName, buffer);
228         } else {
229             retValue = v8::Undefined();
230         }
231     }
232     DBG("Include X");
233     return retValue;
234 }
235
236
237 /**
238  * Create a JsContext, must be called within a HandleScope?
239  */
240 v8::Persistent<v8::Context> makeJsContext() {
241     v8::HandleScope handle_scope;
242     v8::TryCatch try_catch;
243
244     // Add a Message listner to Catch errors as they occur
245     v8::V8::AddMessageListener(ErrorCallback);
246
247     // Create a template for the global object and
248     // add the function template for print to it.
249     v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New();
250     global->SetAccessor(v8::String::New("gRadioState"),
251             RadioStateGetter, RadioStateSetter);
252     global->Set(v8::String::New("msSleep"), v8::FunctionTemplate::New(MsSleep));
253     global->Set(v8::String::New("print"), v8::FunctionTemplate::New(Print));
254     global->Set(v8::String::New("readFileToBuffer"),
255             v8::FunctionTemplate::New(ReadFileToBuffer));
256     global->Set(v8::String::New("readFileToString"),
257             v8::FunctionTemplate::New(ReadFileToString));
258     global->Set(v8::String::New("sendRilRequestComplete"),
259             v8::FunctionTemplate::New(SendRilRequestComplete));
260     global->Set(v8::String::New("sendRilUnsolicitedResponse"),
261             v8::FunctionTemplate::New(SendRilUnsolicitedResponse));
262     global->Set(v8::String::New("sendCtrlRequestComplete"),
263             v8::FunctionTemplate::New(SendCtrlRequestComplete));
264     global->Set(v8::String::New("include"), v8::FunctionTemplate::New(Include));
265     WorkerV8ObjectTemplateInit(global);
266     SchemaObjectTemplateInit(global);
267     Buffer::InitializeObjectTemplate(global);
268
269     // Create context with our globals and make it the current scope
270     v8::Persistent<v8::Context> context = v8::Context::New(NULL, global);
271
272
273     if (try_catch.HasCaught()) {
274         DBG("makeJsContext: Exception making the context");
275         ReportException(&try_catch);
276         try_catch.ReThrow();
277     }
278
279     return context;
280 }
281
282 /**
283  * Run some javascript code.
284  */
285 void runJs(v8::Handle<v8::Context> context, v8::TryCatch *try_catch,
286         const char *fileName, const char *code) {
287     v8::HandleScope handle_scope;
288
289     // Compile the source
290     v8::Handle<v8::Script> script = v8::Script::Compile(
291                 v8::String::New(code), v8::String::New(fileName));
292     if (try_catch->HasCaught()) {
293         ALOGE("-- Compiling the source failed");
294     } else {
295         // Run the resulting script
296         v8::Handle<v8::Value> result = script->Run();
297         if (try_catch->HasCaught()) {
298             ALOGE("-- Running the script failed");
299         }
300     }
301 }
302
303 void testRadioState(v8::Handle<v8::Context> context) {
304     ALOGD("testRadioState E:");
305     v8::HandleScope handle_scope;
306
307     v8::TryCatch try_catch;
308     try_catch.SetVerbose(true);
309
310     runJs(context, &try_catch, "local-string",
311         "for(i = 0; i < 10; i++) {\n"
312         "  gRadioState = i;\n"
313         "  print('gRadioState=' + gRadioState);\n"
314         "}\n"
315         "gRadioState = 1;\n"
316         "print('last gRadioState=' + gRadioState);\n");
317     ALOGD("testRadioState X:");
318 }
319
320 void testMsSleep(v8::Handle<v8::Context> context) {
321     ALOGD("testMsSleep E:");
322     v8::HandleScope handle_scope;
323
324     v8::TryCatch try_catch;
325     try_catch.SetVerbose(true);
326
327     runJs(context, &try_catch, "local-string",
328         "for(i = 0; i < 10; i++) {\n"
329         "  sleeptime = i * 200\n"
330         "  print('msSleep ' + sleeptime);\n"
331         "  msSleep(sleeptime);\n"
332         "}\n");
333     ALOGD("testMsSleep X:");
334 }
335
336 void testPrint(v8::Handle<v8::Context> context) {
337     ALOGD("testPrint E:");
338     v8::HandleScope handle_scope;
339
340     v8::TryCatch try_catch;
341     try_catch.SetVerbose(true);
342
343     runJs(context, &try_catch, "local-string", "print(\"Hello\")");
344     ALOGD("testPrint X:");
345 }
346
347 void testCompileError(v8::Handle<v8::Context> context) {
348     ALOGD("testCompileError E:");
349     v8::HandleScope handle_scope;
350
351     v8::TryCatch try_catch;
352     try_catch.SetVerbose(true);
353
354     // +++ generate a compile time error
355     runJs(context, &try_catch, "local-string", "+++");
356     ALOGD("testCompileError X:");
357 }
358
359 void testRuntimeError(v8::Handle<v8::Context> context) {
360     ALOGD("testRuntimeError E:");
361     v8::HandleScope handle_scope;
362
363     v8::TryCatch try_catch;
364     try_catch.SetVerbose(true);
365
366     // Runtime error
367     runJs(context, &try_catch, "local-string",
368         "function hello() {\n"
369         "  print(\"Hi there\");\n"
370         "}\n"
371         "helloo()");
372     ALOGD("testRuntimeError X:");
373 }
374
375 void testReadFile() {
376     char *buffer;
377     size_t length;
378     int status;
379
380     ALOGD("testReadFile E:");
381
382     status = ReadFile("/sdcard/data/no-file", &buffer, &length);
383     ALOGD("testReadFile expect status != 0, status=%d, buffer=%p, length=%d",
384             status, buffer, length);
385
386     ALOGD("testReadFile X:");
387 }
388
389
390 void testReadFileToStringBuffer(v8::Handle<v8::Context> context) {
391     ALOGD("testReadFileToStringBuffer E:");
392     v8::HandleScope handle_scope;
393
394     v8::TryCatch try_catch;
395     try_catch.SetVerbose(true);
396
397     runJs(context, &try_catch, "local-string",
398         "fileContents = readFileToString(\"mock_ril.js\");\n"
399         "print(\"fileContents:\\n\" + fileContents);\n"
400         "buffer = readFileToBuffer(\"ril.desc\");\n"
401         "print(\"buffer.length=\" + buffer.length);\n");
402     ALOGD("testReadFileToStringBuffer X:");
403 }
404
405 void testJsSupport(v8::Handle<v8::Context> context) {
406     ALOGD("testJsSupport E: ********");
407     testRadioState(context);
408     testMsSleep(context);
409     testPrint(context);
410     testCompileError(context);
411     testRuntimeError(context);
412     testReadFile();
413     testReadFileToStringBuffer(context);
414     ALOGD("testJsSupport X: ********\n");
415 }