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 "logging.h"
21#include "status.h"
22#include "worker.h"
23#include "util.h"
24
25#include "hardware/ril/mock-ril/src/proto/ril.pb.h"
26
27#include "logging.h"
28#include "js_support.h"
29#include "node_buffer.h"
30#include "node_util.h"
31#include "protobuf_v8.h"
32#include "requests.h"
33
34#include "experiments.h"
35
36void testStlPort() {
37    // Test using STLport
38    std::queue<int *> q;
39    int data[] = {1, 2, 3};
40
41    int *param = data;
42    ALOGD("before push q.size=%d", q.size());
43    q.push(param);
44    ALOGD("after push q.size=%d", q.size());
45    void *p = q.front();
46    if (p == param) {
47        ALOGD("q.push succeeded");
48    } else {
49        ALOGD("q.push failed");
50    }
51    q.pop();
52    ALOGD("after pop q.size=%d", q.size());
53}
54
55v8::Handle<v8::Value> GetReqScreenState(v8::Local<v8::String> property,
56                               const v8::AccessorInfo &info) {
57    v8::Local<v8::Object> self = info.Holder();
58    v8::Local<v8::External> wrap =
59            v8::Local<v8::External>::Cast(self->GetInternalField(0));
60    void *p = wrap->Value();
61    int state = static_cast<int *>(p)[0];
62    ALOGD("GetReqScreenState state=%d", state);
63    return v8::Integer::New(state);
64}
65
66bool callOnRilRequest(v8::Handle<v8::Context> context, int request,
67                   void *data, size_t datalen, RIL_Token t) {
68    v8::HandleScope handle_scope;
69    v8::TryCatch try_catch;
70
71    // Get the onRilRequestFunction, making sure its a function
72    v8::Handle<v8::String> name = v8::String::New("onRilRequest");
73    v8::Handle<v8::Value> onRilRequestFunctionValue = context->Global()->Get(name);
74    if(!onRilRequestFunctionValue->IsFunction()) {
75        // Wasn't a function
76        ALOGD("callOnRilRequest X wasn't a function");
77        return false;
78    }
79    v8::Handle<v8::Function> onRilRequestFunction =
80        v8::Handle<v8::Function>::Cast(onRilRequestFunctionValue);
81
82    // Create the request
83    v8::Handle<v8::Value> v8RequestValue = v8::Number::New(request);
84
85    // Create the parameter for the request
86    v8::Handle<v8::Object> params_obj =
87            v8::ObjectTemplate::New()->NewInstance();
88    switch(request) {
89        case(RIL_REQUEST_SCREEN_STATE): {
90            ALOGD("callOnRilRequest RIL_REQUEST_SCREEN_STATE");
91            if (datalen < sizeof(int)) {
92                ALOGD("callOnRilRequest err size < sizeof int");
93            } else {
94                v8::Handle<v8::ObjectTemplate> params_obj_template =
95                        v8::ObjectTemplate::New();
96                params_obj_template->SetInternalFieldCount(1);
97                params_obj_template->SetAccessor(v8::String::New(
98                            "ReqScreenState"), GetReqScreenState, NULL);
99                // How to not leak this pointer!!!
100                int *p = new int;
101                *p = ((int *)data)[0];
102                params_obj = params_obj_template->NewInstance();
103                params_obj->SetInternalField(0, v8::External::New(p));
104            }
105            break;
106        }
107        default: {
108            ALOGD("callOnRilRequest X unknown request");
109            break;
110        }
111    }
112
113    // Invoke onRilRequest
114    bool retValue;
115    const int argc = 2;
116    v8::Handle<v8::Value> argv[argc] = { v8RequestValue, params_obj };
117    v8::Handle<v8::Value> result =
118        onRilRequestFunction->Call(context->Global(), argc, argv);
119    if (try_catch.HasCaught()) {
120        ALOGD("callOnRilRequest error");
121        ReportException(&try_catch);
122        retValue = false;
123    } else {
124        v8::String::Utf8Value result_string(result);
125        ALOGD("callOnRilRequest result=%s", ToCString(result_string));
126        retValue = true;
127    }
128    return retValue;
129}
130
131void testOnRilRequestUsingCppRequestObjs(v8::Handle<v8::Context> context) {
132    ALOGD("testOnRilRequestUsingCppRequestObjs E:");
133    v8::HandleScope handle_scope;
134
135    v8::TryCatch try_catch;
136    try_catch.SetVerbose(true);
137
138    runJs(context, &try_catch, "local-string",
139        "function onRilRequest(reqNum, params) {\n"
140        "  print(\"reqNum=\" + reqNum);\n"
141        "  if (reqNum == 61) {\n"
142        "      print(\"params.ReqScreenState=\" + params.ReqScreenState);\n"
143        "  }\n"
144        "  return \"Hello World\";\n"
145        "}\n");
146    if (!try_catch.HasCaught()) {
147        // Call the onRilRequest function
148        int data[1] = { 0 };
149        callOnRilRequest(context, RIL_REQUEST_SCREEN_STATE, data,
150                sizeof(data), NULL);
151    }
152    ALOGD("testOnRilRequestUsingCppRequestObjs X:");
153}
154
155void testReqScreenStateProtobuf() {
156    v8::HandleScope handle_scope;
157    v8::TryCatch try_catch;
158
159    ALOGD("testReqScreenStateProtobuf E");
160
161    ALOGD("create ReqScreenState");
162    ril_proto::ReqScreenState* ss = new ril_proto::ReqScreenState();
163    ss->set_state(true);
164    bool state = ss->state();
165    ALOGD("state=%d", state);
166    ss->set_state(false);
167    state = ss->state();
168    ALOGD("state=%d", state);
169    int len = ss->ByteSize();
170    ALOGD("create buffer len=%d", len);
171    char *buffer = new char[len];
172    ALOGD("serialize");
173    bool ok = ss->SerializeToArray(buffer, len);
174    if (!ok) {
175        ALOGD("testReqScreenStateProtobuf X: Could not serialize ss");
176        return;
177    }
178    ALOGD("ReqScreenState serialized ok");
179    ril_proto::ReqScreenState *newSs = new ril_proto::ReqScreenState();
180    ok = newSs->ParseFromArray(buffer, len);
181    if (!ok) {
182        ALOGD("testReqScreenStateProtobuf X: Could not deserialize ss");
183        return;
184    }
185    ALOGD("newSs->state=%d", newSs->state());
186
187    delete [] buffer;
188    delete ss;
189    delete newSs;
190    ALOGD("testReqScreenStateProtobuf X");
191}
192
193void testReqHangUpProtobuf() {
194    v8::HandleScope handle_scope;
195    v8::TryCatch try_catch;
196
197    ALOGD("testReqHangUpProtobuf E");
198
199    ALOGD("create ReqHangUp");
200    ril_proto::ReqHangUp* hu = new ril_proto::ReqHangUp();
201    hu->set_connection_index(3);
202    bool connection_index = hu->connection_index();
203    ALOGD("connection_index=%d", connection_index);
204    hu->set_connection_index(2);
205    connection_index = hu->connection_index();
206    ALOGD("connection_index=%d", connection_index);
207    ALOGD("create buffer");
208    int len = hu->ByteSize();
209    char *buffer = new char[len];
210    ALOGD("serialize");
211    bool ok = hu->SerializeToArray(buffer, len);
212    if (!ok) {
213        ALOGD("testReqHangUpProtobuf X: Could not serialize hu");
214        return;
215    }
216    ALOGD("ReqHangUp serialized ok");
217    ril_proto::ReqHangUp *newHu = new ril_proto::ReqHangUp();
218    ok = newHu->ParseFromArray(buffer, len);
219    if (!ok) {
220        ALOGD("testReqHangUpProtobuf X: Could not deserialize hu");
221        return;
222    }
223    ALOGD("newHu->connection_index=%d", newHu->connection_index());
224
225    delete [] buffer;
226    delete hu;
227    delete newHu;
228    ALOGD("testReqHangUpProtobuf X");
229}
230
231void testProtobufV8(v8::Handle<v8::Context> context) {
232    ALOGD("testProtobufV8 E:");
233    v8::HandleScope handle_scope;
234
235    v8::TryCatch try_catch;
236    try_catch.SetVerbose(true);
237
238    if (try_catch.HasCaught()) {
239        ALOGD("TryCatch.hasCaught is true after protobuf_v8::init");
240        ReportException(&try_catch);
241    }
242    runJs(context, &try_catch, "local-string",
243        "fileContents = readFileToString('mock_ril.js');\n"
244        "print('fileContents:\\n' + fileContents);\n"
245        "\n"
246        "buffer = readFileToBuffer('ril.desc');\n"
247        "var schema = new Schema(buffer);\n"
248        "\n"
249        "var originalReqEnterSimPin = { pin : 'hello-the-pin' };\n"
250        "print('originalReqEnterSimPin: pin=' + originalReqEnterSimPin.pin);\n"
251        "var ReqEnterSimPinSchema = schema['ril_proto.ReqEnterSimPin'];\n"
252        "serializedOriginalReqEnterSimPin = ReqEnterSimPinSchema.serialize(originalReqEnterSimPin);\n"
253        "print('serializedOriginalReqEnterSimPin.length=' + serializedOriginalReqEnterSimPin.length);\n"
254        "newReqEnterSimPin = ReqEnterSimPinSchema.parse(serializedOriginalReqEnterSimPin);\n"
255        "print('newReqEnterSimPin: pin=' + newReqEnterSimPin.pin);\n"
256        "\n"
257        "var originalReqScreenState = { state : true };\n"
258        "print('originalReqScreenState: state=' + originalReqScreenState.state);\n"
259        "var ReqScreenStateSchema = schema['ril_proto.ReqScreenState'];\n"
260        "var serializedOriginalReqScreenState = ReqScreenStateSchema.serialize(originalReqScreenState);\n"
261        "print('serializedOriginalReqScreenState.length=' + serializedOriginalReqScreenState.length);\n"
262        "var newReqScreenState = ReqScreenStateSchema.parse(serializedOriginalReqScreenState);\n"
263        "print('newReqScreenState: state=' + newReqScreenState.state);\n"
264        "\n"
265        "originalReqScreenState.state = false;\n"
266        "print('originalReqScreenState: state=' + originalReqScreenState.state);\n"
267        "serializedOriginalReqScreenState = ReqScreenStateSchema.serialize(originalReqScreenState);\n"
268        "print('serializedOriginalReqScreenState.length=' + serializedOriginalReqScreenState.length);\n"
269        "newReqScreenState = ReqScreenStateSchema.parse(serializedOriginalReqScreenState);\n"
270        "print('newReqScreenState: state=' + newReqScreenState.state);\n");
271    ALOGD("testProtobufV8 X");
272}
273
274void experiments(v8::Handle<v8::Context> context) {
275    ALOGD("experiments E: ********");
276    testStlPort();
277    testReqScreenStateProtobuf();
278    testOnRilRequestUsingCppRequestObjs(context);
279    testProtobufV8(context);
280    ALOGD("experiments X: ********\n");
281}
282