| /** |
| * Copyright (C) 2010 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include <stdio.h> |
| #include <assert.h> |
| #include <string.h> |
| #include <errno.h> |
| #include <unistd.h> |
| #include <sys/types.h> |
| #include <sys/stat.h> |
| #include <fcntl.h> |
| #include <pthread.h> |
| #include <alloca.h> |
| #include <getopt.h> |
| #include <sys/socket.h> |
| #include <cutils/sockets.h> |
| #include <termios.h> |
| |
| #include <v8.h> |
| #include "ril.h" |
| |
| #include "hardware/ril/mock-ril/src/proto/ril.pb.h" |
| |
| #include "ctrl_server.h" |
| #include "logging.h" |
| #include "experiments.h" |
| #include "js_support.h" |
| #include "node_buffer.h" |
| #include "node_object_wrap.h" |
| #include "node_util.h" |
| #include "protobuf_v8.h" |
| #include "requests.h" |
| #include "responses.h" |
| #include "status.h" |
| #include "util.h" |
| #include "worker.h" |
| #include "worker_v8.h" |
| |
| #include "mock_ril.h" |
| |
| extern "C" { |
| // Needed so we can call it prior to calling startMockRil |
| extern void RIL_register(const RIL_RadioFunctions *callbacks); |
| } |
| |
| //#define MOCK_RIL_DEBUG |
| #ifdef MOCK_RIL_DEBUG |
| |
| #define DBG(...) ALOGD(__VA_ARGS__) |
| |
| #else |
| |
| #define DBG(...) |
| |
| #endif |
| |
| |
| #define MOCK_RIL_VER_STRING "Android Mock-ril 0.1" |
| |
| /** |
| * Forward declarations |
| */ |
| static void onRequest (int request, void *data, size_t datalen, RIL_Token t); |
| static RIL_RadioState currentState(); |
| static int onSupports (int requestCode); |
| static void onCancel (RIL_Token t); |
| static const char *getVersion(); |
| |
| static void testOnRequestComplete(RIL_Token t, RIL_Errno e, |
| void *response, size_t responselen); |
| static void testRequestTimedCallback(RIL_TimedCallback callback, |
| void *param, const struct timeval *relativeTime); |
| static void testOnUnsolicitedResponse(int unsolResponse, const void *data, |
| size_t datalen); |
| |
| /** |
| * The environment from rild with the completion routine |
| */ |
| const struct RIL_Env *s_rilenv; |
| |
| /** |
| * Expose our routines to rild |
| */ |
| static const RIL_RadioFunctions s_callbacks = { |
| RIL_VERSION, |
| onRequest, |
| currentState, |
| onSupports, |
| onCancel, |
| getVersion |
| }; |
| |
| /** |
| * A test environment |
| */ |
| static const RIL_Env testEnv = { |
| testOnRequestComplete, |
| testOnUnsolicitedResponse, |
| testRequestTimedCallback |
| }; |
| |
| /** |
| * The request worker queue to handle requests |
| */ |
| static RilRequestWorkerQueue *s_requestWorkerQueue; |
| |
| /** |
| * Call from RIL to us to make a RIL_REQUEST |
| * |
| * Must be completed with a call to RIL_onRequestComplete() |
| * |
| * RIL_onRequestComplete() may be called from any thread, before or after |
| * this function returns. |
| * |
| * Will always be called from the same thread, so returning here implies |
| * that the radio is ready to process another command (whether or not |
| * the previous command has c1mpleted). |
| */ |
| static void onRequest (int request, void *data, size_t datalen, RIL_Token t) |
| { |
| DBG("onRequest: request=%d data=%p datalen=%d token=%p", |
| request, data, datalen, t); |
| s_requestWorkerQueue->AddRequest(request, data, datalen, t); |
| } |
| |
| /** |
| * Synchronous call from the RIL to us to return current radio state. |
| * RADIO_STATE_UNAVAILABLE should be the initial state. |
| */ |
| static RIL_RadioState currentState() |
| { |
| DBG("currentState: gRadioState=%d", gRadioState); |
| return gRadioState; |
| } |
| |
| /** |
| * Call from RIL to us to find out whether a specific request code |
| * is supported by this implementation. |
| * |
| * Return 1 for "supported" and 0 for "unsupported" |
| */ |
| |
| static int |
| onSupports (int requestCode) |
| { |
| DBG("onSupports: nothing supported at the moment, return 0"); |
| return 0; |
| } |
| |
| static void onCancel (RIL_Token t) |
| { |
| DBG("onCancel: ignorning"); |
| } |
| |
| static const char * getVersion(void) |
| { |
| DBG("getVersion: return '%s'", MOCK_RIL_VER_STRING); |
| return MOCK_RIL_VER_STRING; |
| } |
| |
| /** |
| * "t" is parameter passed in on previous call to RIL_Notification |
| * routine. |
| * |
| * If "e" != SUCCESS, then response can be null/is ignored |
| * |
| * "response" is owned by caller, and should not be modified or |
| * freed by callee |
| * |
| * RIL_onRequestComplete will return as soon as possible |
| */ |
| void testOnRequestComplete(RIL_Token t, RIL_Errno e, |
| void *response, size_t responselen) { |
| DBG("testOnRequestComplete E: token=%p rilErrCode=%d data=%p datalen=%d", |
| t, e, response, responselen); |
| DBG("testOnRequestComplete X:"); |
| } |
| |
| /** |
| * "unsolResponse" is one of RIL_UNSOL_RESPONSE_* |
| * "data" is pointer to data defined for that RIL_UNSOL_RESPONSE_* |
| * |
| * "data" is owned by caller, and should not be modified or freed by callee |
| */ |
| void testOnUnsolicitedResponse(int unsolResponse, const void *data, |
| size_t datalen) { |
| DBG("testOnUnsolicitedResponse ignoring"); |
| } |
| |
| /** |
| * Call user-specifed "callback" function on on the same thread that |
| * RIL_RequestFunc is called. If "relativeTime" is specified, then it specifies |
| * a relative time value at which the callback is invoked. If relativeTime is |
| * NULL or points to a 0-filled structure, the callback will be invoked as |
| * soon as possible |
| */ |
| void testRequestTimedCallback(RIL_TimedCallback callback, |
| void *param, const struct timeval *relativeTime) { |
| DBG("testRequestTimedCallback ignoring"); |
| } |
| |
| #if 0 |
| class UnsolicitedThread : public WorkerThread { |
| private: |
| v8::Handle<v8::Context> context_; |
| |
| public: |
| UnsolicitedThread(v8::Handle<v8::Context> context) : |
| context_(context) { |
| } |
| |
| int OnUnsolicitedTick(int tick) { |
| v8::HandleScope handle_scope; |
| |
| // Get handle to onUnslicitedTick. |
| v8::Handle<v8::String> name = v8::String::New("onUnsolicitedTick"); |
| v8::Handle<v8::Value> functionValue = context_->Global()->Get(name); |
| v8::Handle<v8::Function> onUnsolicitedTick = |
| v8::Handle<v8::Function>::Cast(functionValue); |
| |
| // Create the argument array |
| v8::Handle<v8::Value> v8TickValue = v8::Number::New(tick); |
| v8::Handle<v8::Value> argv[1] = { v8TickValue }; |
| |
| v8::Handle<v8::Value> resultValue = |
| onUnsolicitedTick->Call(context_->Global(), 1, argv); |
| int result = int(resultValue->NumberValue()); |
| return result; |
| } |
| |
| void * Worker(void *param) |
| { |
| ALOGD("UnsolicitedThread::Worker E param=%p", param); |
| |
| v8::Locker locker; |
| |
| for (int i = 0; isRunning(); i++) { |
| // Get access and setup scope |
| v8::HandleScope handle_scope; |
| v8::Context::Scope context_scope(context_); |
| |
| // Do it |
| int sleepTime = OnUnsolicitedTick(i); |
| |
| // Wait |
| v8::Unlocker unlocker; |
| sleep(sleepTime); |
| v8::Locker locker; |
| } |
| |
| ALOGD("UnsolicitedThread::Worker X param=%p", param); |
| |
| return NULL; |
| } |
| }; |
| #endif |
| |
| void startMockRil(v8::Handle<v8::Context> context) { |
| v8::HandleScope handle_scope; |
| v8::TryCatch try_catch; |
| |
| // Get handle to startMockRil and call it. |
| v8::Handle<v8::String> name = v8::String::New("startMockRil"); |
| v8::Handle<v8::Value> functionValue = context->Global()->Get(name); |
| v8::Handle<v8::Function> start = |
| v8::Handle<v8::Function>::Cast(functionValue); |
| |
| v8::Handle<v8::Value> result = start->Call(context->Global(), 0, NULL); |
| if (try_catch.HasCaught()) { |
| LOGE("startMockRil error"); |
| ReportException(&try_catch); |
| LOGE("FATAL ERROR: Unsable to startMockRil."); |
| } else { |
| v8::String::Utf8Value result_string(result); |
| LOGE("startMockRil result=%s", ToCString(result_string)); |
| } |
| |
| } |
| |
| |
| const RIL_RadioFunctions *RIL_Init(const struct RIL_Env *env, int argc, |
| char **argv) { |
| int ret; |
| pthread_attr_t attr; |
| |
| ALOGD("RIL_Init E: ----------------"); |
| |
| // Initialize V8 |
| v8::V8::Initialize(); |
| |
| // We're going to use multiple threads need to start locked |
| v8::Locker locker; |
| |
| // Initialize modules |
| protobuf_v8::Init(); |
| WorkerV8Init(); |
| |
| // Make a context and setup a scope |
| v8::Persistent<v8::Context> context = makeJsContext(); |
| v8::Context::Scope context_scope(context); |
| v8::TryCatch try_catch; |
| try_catch.SetVerbose(true); |
| |
| // Initialize modules needing context |
| ctrlServerInit(context); |
| |
| s_rilenv = &testEnv; |
| |
| // load/run mock_ril.js |
| char *buffer; |
| int status = ReadFile("/sdcard/data/mock_ril.js", &buffer); |
| if (status == 0) { |
| runJs(context, &try_catch, "mock_ril.js", buffer); |
| if (try_catch.HasCaught()) { |
| // TODO: Change to event this is fatal |
| LOGE("FATAL ERROR: Unable to run mock_ril.js"); |
| } |
| } |
| |
| s_rilenv = env; |
| requestsInit(context, &s_requestWorkerQueue); |
| responsesInit(context); |
| |
| #if 0 |
| ALOGD("RIL_Init run tests #####################"); |
| testJsSupport(context); |
| testRequests(context); |
| experiments(context); |
| testWorker(); |
| testWorkerV8(context); |
| ALOGD("RIL_Init tests completed ###############"); |
| #endif |
| |
| // Register our call backs so when we startMockRil |
| // and it wants to send unsolicited messages the |
| // mock ril is registered |
| RIL_register(&s_callbacks); |
| |
| // Start the mock ril |
| startMockRil(context); |
| |
| #if 0 |
| UnsolicitedThread *ut = new UnsolicitedThread(context); |
| ut->Run(NULL); |
| #endif |
| |
| ALOGD("RIL_Init X: ----------------"); |
| return &s_callbacks; |
| } |