OSDN Git Service

am 2e977068: (-s ours) am 060f053e: DO NOT MERGE
[android-x86/hardware-ril.git] / mock-ril / src / cpp / mock_ril.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 <telephony/ril.h>
18 #include <stdio.h>
19 #include <assert.h>
20 #include <string.h>
21 #include <errno.h>
22 #include <unistd.h>
23 #include <sys/types.h>
24 #include <sys/stat.h>
25 #include <fcntl.h>
26 #include <pthread.h>
27 #include <alloca.h>
28 #include <getopt.h>
29 #include <sys/socket.h>
30 #include <cutils/sockets.h>
31 #include <termios.h>
32
33 #include <v8.h>
34
35 #include "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(...) LOGD(__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  */
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  */
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
157 onSupports (int requestCode)
158 {
159     DBG("onSupports: nothing supported at the moment, return 0");
160     return 0;
161 }
162
163 static void onCancel (RIL_Token t)
164 {
165     DBG("onCancel: ignorning");
166 }
167
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  */
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  */
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  */
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         LOGD("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         LOGD("UnsolicitedThread::Worker X param=%p", param);
265
266         return NULL;
267     }
268 };
269 #endif
270
271 void startMockRil(v8::Handle<v8::Context> context) {
272     v8::HandleScope handle_scope;
273
274     // Get handle to startMockRil and call it.
275     v8::Handle<v8::String> name = v8::String::New("startMockRil");
276     v8::Handle<v8::Value> functionValue = context->Global()->Get(name);
277     v8::Handle<v8::Function> start =
278             v8::Handle<v8::Function>::Cast(functionValue);
279
280     start->Call(context->Global(), 0, NULL);
281 }
282
283
284 const RIL_RadioFunctions *RIL_Init(const struct RIL_Env *env, int argc,
285         char **argv) {
286     int ret;
287     pthread_attr_t attr;
288
289     LOGD("RIL_Init E: ----------------");
290
291     // Initialize V8
292     v8::V8::Initialize();
293
294     // We're going to use multiple threads need to start locked
295     v8::Locker locker;
296
297     // Initialize modules
298     protobuf_v8::Init();
299     WorkerV8Init();
300
301     // Make a context and setup a scope
302     v8::Persistent<v8::Context> context = makeJsContext();
303     v8::Context::Scope context_scope(context);
304     v8::TryCatch try_catch;
305     try_catch.SetVerbose(true);
306
307     // Initialize modules needing context
308     ctrlServerInit(context);
309
310     s_rilenv = &testEnv;
311
312 #if 0
313     LOGD("RIL_Init run tests #####################");
314     testJsSupport(context);
315     testRequests(context);
316     experiments(context);
317     testWorker();
318     testWorkerV8(context);
319     testJs(context);
320     LOGD("RIL_Init tests completed ###############");
321 #endif
322
323     // load/run mock_ril.js
324     char *buffer;
325     int status = ReadFile("/sdcard/data/mock_ril.js", &buffer);
326     if (status == 0) {
327         runJs(context, &try_catch, "mock_ril.js", buffer);
328         if (try_catch.HasCaught()) {
329             // TODO: Change to event this is fatal
330             LOGE("FATAL ERROR: Unable to run mock_ril.js");
331         }
332     }
333
334     s_rilenv = env;
335     requestsInit(context, &s_requestWorkerQueue);
336     responsesInit(context);
337
338     // Register our call backs so when we startMockRil
339     // and it wants to send unsolicited messages the
340     // mock ril is registered
341     RIL_register(&s_callbacks);
342
343     // Start the mock ril
344     startMockRil(context);
345
346 #if 0
347     UnsolicitedThread *ut = new UnsolicitedThread(context);
348     ut->Run(NULL);
349 #endif
350
351     LOGD("RIL_Init X: ----------------");
352     return &s_callbacks;
353 }