2 * Copyright (C) 2010 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include <telephony/ril.h>
23 #include <sys/types.h>
29 #include <sys/socket.h>
30 #include <cutils/sockets.h>
37 #include "ctrl_server.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"
46 #include "responses.h"
50 #include "worker_v8.h"
55 // Needed so we can call it prior to calling startMockRil
56 extern void RIL_register(const RIL_RadioFunctions *callbacks);
59 //#define MOCK_RIL_DEBUG
62 #define DBG(...) LOGD(__VA_ARGS__)
71 #define MOCK_RIL_VER_STRING "Android Mock-ril 0.1"
74 * Forward declarations
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();
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,
90 * The environment from rild with the completion routine
92 const struct RIL_Env *s_rilenv;
95 * Expose our routines to rild
97 static const RIL_RadioFunctions s_callbacks = {
109 static const RIL_Env testEnv = {
110 testOnRequestComplete,
111 testOnUnsolicitedResponse,
112 testRequestTimedCallback
116 * The request worker queue to handle requests
118 static RilRequestWorkerQueue *s_requestWorkerQueue;
121 * Call from RIL to us to make a RIL_REQUEST
123 * Must be completed with a call to RIL_onRequestComplete()
125 * RIL_onRequestComplete() may be called from any thread, before or after
126 * this function returns.
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).
132 static void onRequest (int request, void *data, size_t datalen, RIL_Token t)
134 DBG("onRequest: request=%d data=%p datalen=%d token=%p",
135 request, data, datalen, t);
136 s_requestWorkerQueue->AddRequest(request, data, datalen, t);
140 * Synchronous call from the RIL to us to return current radio state.
141 * RADIO_STATE_UNAVAILABLE should be the initial state.
143 static RIL_RadioState currentState()
145 DBG("currentState: gRadioState=%d", gRadioState);
150 * Call from RIL to us to find out whether a specific request code
151 * is supported by this implementation.
153 * Return 1 for "supported" and 0 for "unsupported"
157 onSupports (int requestCode)
159 DBG("onSupports: nothing supported at the moment, return 0");
163 static void onCancel (RIL_Token t)
165 DBG("onCancel: ignorning");
168 static const char * getVersion(void)
170 DBG("getVersion: return '%s'", MOCK_RIL_VER_STRING);
171 return MOCK_RIL_VER_STRING;
175 * "t" is parameter passed in on previous call to RIL_Notification
178 * If "e" != SUCCESS, then response can be null/is ignored
180 * "response" is owned by caller, and should not be modified or
183 * RIL_onRequestComplete will return as soon as possible
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:");
193 * "unsolResponse" is one of RIL_UNSOL_RESPONSE_*
194 * "data" is pointer to data defined for that RIL_UNSOL_RESPONSE_*
196 * "data" is owned by caller, and should not be modified or freed by callee
198 void testOnUnsolicitedResponse(int unsolResponse, const void *data,
200 DBG("testOnUnsolicitedResponse ignoring");
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
210 void testRequestTimedCallback(RIL_TimedCallback callback,
211 void *param, const struct timeval *relativeTime) {
212 DBG("testRequestTimedCallback ignoring");
216 class UnsolicitedThread : public WorkerThread {
218 v8::Handle<v8::Context> context_;
221 UnsolicitedThread(v8::Handle<v8::Context> context) :
225 int OnUnsolicitedTick(int tick) {
226 v8::HandleScope handle_scope;
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);
234 // Create the argument array
235 v8::Handle<v8::Value> v8TickValue = v8::Number::New(tick);
236 v8::Handle<v8::Value> argv[1] = { v8TickValue };
238 v8::Handle<v8::Value> resultValue =
239 onUnsolicitedTick->Call(context_->Global(), 1, argv);
240 int result = int(resultValue->NumberValue());
244 void * Worker(void *param)
246 LOGD("UnsolicitedThread::Worker E param=%p", param);
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_);
256 int sleepTime = OnUnsolicitedTick(i);
259 v8::Unlocker unlocker;
264 LOGD("UnsolicitedThread::Worker X param=%p", param);
271 void startMockRil(v8::Handle<v8::Context> context) {
272 v8::HandleScope handle_scope;
273 v8::TryCatch try_catch;
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);
281 v8::Handle<v8::Value> result = start->Call(context->Global(), 0, NULL);
282 if (try_catch.HasCaught()) {
283 LOGE("startMockRil error");
284 ReportException(&try_catch);
285 LOGE("FATAL ERROR: Unsable to startMockRil.");
287 v8::String::Utf8Value result_string(result);
288 LOGE("startMockRil result=%s", ToCString(result_string));
294 const RIL_RadioFunctions *RIL_Init(const struct RIL_Env *env, int argc,
299 LOGD("RIL_Init E: ----------------");
302 v8::V8::Initialize();
304 // We're going to use multiple threads need to start locked
307 // Initialize modules
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);
317 // Initialize modules needing context
318 ctrlServerInit(context);
322 // load/run mock_ril.js
324 int status = ReadFile("/sdcard/data/mock_ril.js", &buffer);
326 runJs(context, &try_catch, "mock_ril.js", buffer);
327 if (try_catch.HasCaught()) {
328 // TODO: Change to event this is fatal
329 LOGE("FATAL ERROR: Unable to run mock_ril.js");
334 requestsInit(context, &s_requestWorkerQueue);
335 responsesInit(context);
338 LOGD("RIL_Init run tests #####################");
339 testJsSupport(context);
340 testRequests(context);
341 experiments(context);
343 testWorkerV8(context);
344 LOGD("RIL_Init tests completed ###############");
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);
352 // Start the mock ril
353 startMockRil(context);
356 UnsolicitedThread *ut = new UnsolicitedThread(context);
360 LOGD("RIL_Init X: ----------------");