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 <stdio.h>
18 #include <assert.h>
19 #include <string.h>
20 #include <errno.h>
21 #include <unistd.h>
22 #include <sys/types.h>
23 #include <sys/stat.h>
24 #include <fcntl.h>
25 #include <pthread.h>
26 #include <alloca.h>
27 #include <getopt.h>
28 #include <sys/socket.h>
29 #include <cutils/sockets.h>
30 #include <termios.h>
31
32 #include <v8.h>
33 #include "ril.h"
34
35 #include "hardware/ril/mock-ril/src/proto/ril.pb.h"
36
37 #include "ctrl_server.h"
38 #include "logging.h"
39 #include "experiments.h"
40 #include "js_support.h"
41 #include "node_buffer.h"
42 #include "node_object_wrap.h"
43 #include "node_util.h"
44 #include "protobuf_v8.h"
45 #include "requests.h"
46 #include "responses.h"
47 #include "status.h"
48 #include "util.h"
49 #include "worker.h"
50 #include "worker_v8.h"
51
52 #include "mock_ril.h"
53
54 extern "C" {
55 // Needed so we can call it prior to calling startMockRil
56 extern void RIL_register(const RIL_RadioFunctions *callbacks);
57 }
58
59 //#define MOCK_RIL_DEBUG
60 #ifdef MOCK_RIL_DEBUG
61
62 #define DBG(...) ALOGD(__VA_ARGS__)
63
64 #else
65
66 #define DBG(...)
67
68 #endif
69
70
71 #define MOCK_RIL_VER_STRING "Android Mock-ril 0.1"
72
73 /**
74 * Forward declarations
75 */
76 static void onRequest (int request, void *data, size_t datalen, RIL_Token t);
77 static RIL_RadioState currentState();
78 static int onSupports (int requestCode);
79 static void onCancel (RIL_Token t);
80 static const char *getVersion();
81
82 static void testOnRequestComplete(RIL_Token t, RIL_Errno e,
83 void *response, size_t responselen);
84 static void testRequestTimedCallback(RIL_TimedCallback callback,
85 void *param, const struct timeval *relativeTime);
86 static void testOnUnsolicitedResponse(int unsolResponse, const void *data,
87 size_t datalen);
88
89 /**
90 * The environment from rild with the completion routine
91 */
92 const struct RIL_Env *s_rilenv;
93
94 /**
95 * Expose our routines to rild
96 */
97 static const RIL_RadioFunctions s_callbacks = {
98 RIL_VERSION,
99 onRequest,
100 currentState,
101 onSupports,
102 onCancel,
103 getVersion
104 };
105
106 /**
107 * A test environment
108 */
109 static const RIL_Env testEnv = {
110 testOnRequestComplete,
111 testOnUnsolicitedResponse,
112 testRequestTimedCallback
113 };
114
115 /**
116 * The request worker queue to handle requests
117 */
118 static RilRequestWorkerQueue *s_requestWorkerQueue;
119
120 /**
121 * Call from RIL to us to make a RIL_REQUEST
122 *
123 * Must be completed with a call to RIL_onRequestComplete()
124 *
125 * RIL_onRequestComplete() may be called from any thread, before or after
126 * this function returns.
127 *
128 * Will always be called from the same thread, so returning here implies
129 * that the radio is ready to process another command (whether or not
130 * the previous command has c1mpleted).
131 */
onRequest(int request,void * data,size_t datalen,RIL_Token t)132 static void onRequest (int request, void *data, size_t datalen, RIL_Token t)
133 {
134 DBG("onRequest: request=%d data=%p datalen=%d token=%p",
135 request, data, datalen, t);
136 s_requestWorkerQueue->AddRequest(request, data, datalen, t);
137 }
138
139 /**
140 * Synchronous call from the RIL to us to return current radio state.
141 * RADIO_STATE_UNAVAILABLE should be the initial state.
142 */
currentState()143 static RIL_RadioState currentState()
144 {
145 DBG("currentState: gRadioState=%d", gRadioState);
146 return gRadioState;
147 }
148
149 /**
150 * Call from RIL to us to find out whether a specific request code
151 * is supported by this implementation.
152 *
153 * Return 1 for "supported" and 0 for "unsupported"
154 */
155
156 static int
onSupports(int requestCode)157 onSupports (int requestCode)
158 {
159 DBG("onSupports: nothing supported at the moment, return 0");
160 return 0;
161 }
162
onCancel(RIL_Token t)163 static void onCancel (RIL_Token t)
164 {
165 DBG("onCancel: ignorning");
166 }
167
getVersion(void)168 static const char * getVersion(void)
169 {
170 DBG("getVersion: return '%s'", MOCK_RIL_VER_STRING);
171 return MOCK_RIL_VER_STRING;
172 }
173
174 /**
175 * "t" is parameter passed in on previous call to RIL_Notification
176 * routine.
177 *
178 * If "e" != SUCCESS, then response can be null/is ignored
179 *
180 * "response" is owned by caller, and should not be modified or
181 * freed by callee
182 *
183 * RIL_onRequestComplete will return as soon as possible
184 */
testOnRequestComplete(RIL_Token t,RIL_Errno e,void * response,size_t responselen)185 void testOnRequestComplete(RIL_Token t, RIL_Errno e,
186 void *response, size_t responselen) {
187 DBG("testOnRequestComplete E: token=%p rilErrCode=%d data=%p datalen=%d",
188 t, e, response, responselen);
189 DBG("testOnRequestComplete X:");
190 }
191
192 /**
193 * "unsolResponse" is one of RIL_UNSOL_RESPONSE_*
194 * "data" is pointer to data defined for that RIL_UNSOL_RESPONSE_*
195 *
196 * "data" is owned by caller, and should not be modified or freed by callee
197 */
testOnUnsolicitedResponse(int unsolResponse,const void * data,size_t datalen)198 void testOnUnsolicitedResponse(int unsolResponse, const void *data,
199 size_t datalen) {
200 DBG("testOnUnsolicitedResponse ignoring");
201 }
202
203 /**
204 * Call user-specifed "callback" function on on the same thread that
205 * RIL_RequestFunc is called. If "relativeTime" is specified, then it specifies
206 * a relative time value at which the callback is invoked. If relativeTime is
207 * NULL or points to a 0-filled structure, the callback will be invoked as
208 * soon as possible
209 */
testRequestTimedCallback(RIL_TimedCallback callback,void * param,const struct timeval * relativeTime)210 void testRequestTimedCallback(RIL_TimedCallback callback,
211 void *param, const struct timeval *relativeTime) {
212 DBG("testRequestTimedCallback ignoring");
213 }
214
215 #if 0
216 class UnsolicitedThread : public WorkerThread {
217 private:
218 v8::Handle<v8::Context> context_;
219
220 public:
221 UnsolicitedThread(v8::Handle<v8::Context> context) :
222 context_(context) {
223 }
224
225 int OnUnsolicitedTick(int tick) {
226 v8::HandleScope handle_scope;
227
228 // Get handle to onUnslicitedTick.
229 v8::Handle<v8::String> name = v8::String::New("onUnsolicitedTick");
230 v8::Handle<v8::Value> functionValue = context_->Global()->Get(name);
231 v8::Handle<v8::Function> onUnsolicitedTick =
232 v8::Handle<v8::Function>::Cast(functionValue);
233
234 // Create the argument array
235 v8::Handle<v8::Value> v8TickValue = v8::Number::New(tick);
236 v8::Handle<v8::Value> argv[1] = { v8TickValue };
237
238 v8::Handle<v8::Value> resultValue =
239 onUnsolicitedTick->Call(context_->Global(), 1, argv);
240 int result = int(resultValue->NumberValue());
241 return result;
242 }
243
244 void * Worker(void *param)
245 {
246 ALOGD("UnsolicitedThread::Worker E param=%p", param);
247
248 v8::Locker locker;
249
250 for (int i = 0; isRunning(); i++) {
251 // Get access and setup scope
252 v8::HandleScope handle_scope;
253 v8::Context::Scope context_scope(context_);
254
255 // Do it
256 int sleepTime = OnUnsolicitedTick(i);
257
258 // Wait
259 v8::Unlocker unlocker;
260 sleep(sleepTime);
261 v8::Locker locker;
262 }
263
264 ALOGD("UnsolicitedThread::Worker X param=%p", param);
265
266 return NULL;
267 }
268 };
269 #endif
270
startMockRil(v8::Handle<v8::Context> context)271 void startMockRil(v8::Handle<v8::Context> context) {
272 v8::HandleScope handle_scope;
273 v8::TryCatch try_catch;
274
275 // Get handle to startMockRil and call it.
276 v8::Handle<v8::String> name = v8::String::New("startMockRil");
277 v8::Handle<v8::Value> functionValue = context->Global()->Get(name);
278 v8::Handle<v8::Function> start =
279 v8::Handle<v8::Function>::Cast(functionValue);
280
281 v8::Handle<v8::Value> result = start->Call(context->Global(), 0, NULL);
282 if (try_catch.HasCaught()) {
283 ALOGE("startMockRil error");
284 ReportException(&try_catch);
285 ALOGE("FATAL ERROR: Unsable to startMockRil.");
286 } else {
287 v8::String::Utf8Value result_string(result);
288 ALOGE("startMockRil result=%s", ToCString(result_string));
289 }
290
291 }
292
293
RIL_Init(const struct RIL_Env * env,int argc,char ** argv)294 const RIL_RadioFunctions *RIL_Init(const struct RIL_Env *env, int argc,
295 char **argv) {
296 int ret;
297 pthread_attr_t attr;
298
299 ALOGD("RIL_Init E: ----------------");
300
301 // Initialize V8
302 v8::V8::Initialize();
303
304 // We're going to use multiple threads need to start locked
305 v8::Locker locker;
306
307 // Initialize modules
308 protobuf_v8::Init();
309 WorkerV8Init();
310
311 // Make a context and setup a scope
312 v8::Persistent<v8::Context> context = makeJsContext();
313 v8::Context::Scope context_scope(context);
314 v8::TryCatch try_catch;
315 try_catch.SetVerbose(true);
316
317 // Initialize modules needing context
318 ctrlServerInit(context);
319
320 s_rilenv = &testEnv;
321
322 // load/run mock_ril.js
323 char *buffer;
324 int status = ReadFile("/sdcard/data/mock_ril.js", &buffer);
325 if (status == 0) {
326 runJs(context, &try_catch, "mock_ril.js", buffer);
327 if (try_catch.HasCaught()) {
328 // TODO: Change to event this is fatal
329 ALOGE("FATAL ERROR: Unable to run mock_ril.js");
330 }
331 }
332
333 s_rilenv = env;
334 requestsInit(context, &s_requestWorkerQueue);
335 responsesInit(context);
336
337 #if 0
338 ALOGD("RIL_Init run tests #####################");
339 testJsSupport(context);
340 testRequests(context);
341 experiments(context);
342 testWorker();
343 testWorkerV8(context);
344 ALOGD("RIL_Init tests completed ###############");
345 #endif
346
347 // Register our call backs so when we startMockRil
348 // and it wants to send unsolicited messages the
349 // mock ril is registered
350 RIL_register(&s_callbacks);
351
352 // Start the mock ril
353 startMockRil(context);
354
355 #if 0
356 UnsolicitedThread *ut = new UnsolicitedThread(context);
357 ut->Run(NULL);
358 #endif
359
360 ALOGD("RIL_Init X: ----------------");
361 return &s_callbacks;
362 }
363