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 <map> 18 19 #include <v8.h> 20 #include <telephony/ril.h> 21 22 23 #include "ril.pb.h" 24 25 #include "logging.h" 26 #include "js_support.h" 27 #include "mock_ril.h" 28 #include "node_buffer.h" 29 #include "node_object_wrap.h" 30 #include "node_util.h" 31 #include "protobuf_v8.h" 32 #include "status.h" 33 #include "util.h" 34 #include "worker.h" 35 36 #include "requests.h" 37 38 //#define REQUESTS_DEBUG 39 #ifdef REQUESTS_DEBUG 40 41 #define DBG(...) LOGD(__VA_ARGS__) 42 43 #else 44 45 #define DBG(...) 46 47 #endif 48 49 50 /** 51 * Request has no data so create an empty Buffer 52 */ 53 int ReqWithNoData(Buffer **pBuffer, 54 const void *data, const size_t datalen, const RIL_Token t) { 55 int status; 56 static Buffer *emptyBuffer = Buffer::New(0L); 57 58 DBG("ReqWithNoData E"); 59 *pBuffer = emptyBuffer; 60 status = STATUS_OK; 61 62 DBG("ReqWithNoData X status=%d", status); 63 return status; 64 } 65 66 /** 67 * request for RIL_REQUEST_ENTER_SIM_PIN // 2 68 */ 69 int ReqEnterSimPin(Buffer **pBuffer, 70 const void *data, const size_t datalen, const RIL_Token t) { 71 int status; 72 Buffer *buffer; 73 74 DBG("ReqEnterSimPin E"); 75 if (datalen < sizeof(int)) { 76 LOGE("ReqEnterSimPin: data to small err size < sizeof int"); 77 status = STATUS_BAD_DATA; 78 } else { 79 ril_proto::ReqEnterSimPin *req = new ril_proto::ReqEnterSimPin(); 80 DBG("ReqEnterSimPin: pin = %s", ((const char **)data)[0]); 81 req->set_pin((((char **)data)[0])); 82 buffer = Buffer::New(req->ByteSize()); 83 req->SerializeToArray(buffer->data(), buffer->length()); 84 delete req; 85 *pBuffer = buffer; 86 status = STATUS_OK; 87 } 88 DBG("ReqEnterSimPin X status=%d", status); 89 return status; 90 } 91 92 /** 93 * request for RIL_REQUEST_DIAL // 10 94 */ 95 int ReqDial(Buffer **pBuffer, 96 const void *data, const size_t datalen, const RIL_Token t) { 97 int status; 98 Buffer *buffer; 99 100 DBG("ReqDial E"); 101 DBG("data=%p datalen=%d t=%p", data, datalen, t); 102 103 if (datalen < sizeof(int)) { 104 LOGE("ReqDial: data to small err size < sizeof int"); 105 status = STATUS_BAD_DATA; 106 } else { 107 ril_proto::ReqDial *req = new ril_proto::ReqDial(); 108 109 // cast the data to RIL_Dial 110 RIL_Dial *rilDial = (RIL_Dial *)data; 111 DBG("ReqDial: rilDial->address =%s, rilDial->clir=%d", rilDial->address, rilDial->clir); 112 113 req->set_address(rilDial->address); 114 req->set_clir(rilDial->clir); 115 ril_proto::RilUusInfo *uusInfo = (ril_proto::RilUusInfo *)(&(req->uus_info())); 116 117 if (rilDial->uusInfo != NULL) { 118 DBG("ReqDial: print uusInfo:"); 119 DBG("rilDial->uusInfo->uusType = %d, " 120 "rilDial->uusInfo->uusDcs =%d, " 121 "rilDial->uusInfo->uusLength=%d, " 122 "rilDial->uusInfo->uusData = %s", 123 rilDial->uusInfo->uusType, 124 rilDial->uusInfo->uusDcs, 125 rilDial->uusInfo->uusLength, 126 rilDial->uusInfo->uusData); 127 128 uusInfo->set_uus_type((ril_proto::RilUusType)rilDial->uusInfo->uusType); 129 uusInfo->set_uus_dcs((ril_proto::RilUusDcs)rilDial->uusInfo->uusDcs); 130 uusInfo->set_uus_length(rilDial->uusInfo->uusLength); 131 uusInfo->set_uus_data(rilDial->uusInfo->uusData); 132 } else { 133 DBG("uusInfo is NULL"); 134 } 135 136 DBG("ReqDial: after set the request"); 137 DBG("req->ByetSize=%d", req->ByteSize()); 138 buffer = Buffer::New(req->ByteSize()); 139 DBG("buffer size=%d", buffer->length()); 140 141 req->SerializeToArray(buffer->data(), buffer->length()); 142 delete req; 143 *pBuffer = buffer; 144 status = STATUS_OK; 145 DBG("ReqDial X, buffer->length()=%d", buffer->length()); 146 } 147 DBG("ReqDial X status = %d", status); 148 return status; 149 } 150 151 /** 152 * request for RIL_REQUEST_HANGUP // 12 153 */ 154 int ReqHangUp(Buffer **pBuffer, 155 const void *data, const size_t datalen, const RIL_Token t) { 156 int status; 157 Buffer *buffer; 158 159 DBG("ReqHangUp E"); 160 if (datalen < sizeof(int)) { 161 LOGE("ReqHangUp: data to small err size < sizeof int"); 162 status = STATUS_BAD_DATA; 163 } else { 164 ril_proto::ReqHangUp *req = new ril_proto::ReqHangUp(); 165 DBG("ReqHangUp: connection_index=%d", ((int *)data)[0]); 166 req->set_connection_index(((int *)data)[0]); 167 buffer = Buffer::New(req->ByteSize()); 168 req->SerializeToArray(buffer->data(), buffer->length()); 169 delete req; 170 *pBuffer = buffer; 171 status = STATUS_OK; 172 } 173 DBG("ReqHangUp X status=%d", status); 174 return status; 175 } 176 177 /** 178 * request for RIL_REQUEST_SEPARATE_CONNECTION // 52 179 */ 180 int ReqSeparateConnection (Buffer **pBuffer, 181 const void *data, const size_t datalen, const RIL_Token t) { 182 int status; 183 Buffer *buffer; 184 v8::HandleScope handle_scope; 185 186 DBG("ReqSeparateConnection E"); 187 if (datalen < sizeof(int)) { 188 LOGE("ReqSetMute: data to small err size < sizeof int"); 189 status = STATUS_BAD_DATA; 190 } else { 191 ril_proto::ReqSeparateConnection *req = new ril_proto::ReqSeparateConnection(); 192 DBG("ReqSeparateConnection: index=%d", ((int *)data)[0]); 193 req->set_index(((int *)data)[0]); 194 DBG("ReqSeparateConnection: req->ByetSize=%d", req->ByteSize()); 195 buffer = Buffer::New(req->ByteSize()); 196 req->SerializeToArray(buffer->data(), buffer->length()); 197 delete req; 198 *pBuffer = buffer; 199 status = STATUS_OK; 200 } 201 DBG("ReqSeparateConnection X status=%d", status); 202 return status; 203 } 204 205 /** 206 * request for RIL_REQUEST_SET_MUTE // 53 207 */ 208 int ReqSetMute(Buffer **pBuffer, 209 const void *data, const size_t datalen, const RIL_Token t) { 210 int status; 211 Buffer *buffer; 212 v8::HandleScope handle_scope; 213 214 DBG("ReqSetMute E"); 215 if (datalen < sizeof(int)) { 216 LOGE("ReqSetMute: data to small err size < sizeof int"); 217 status = STATUS_BAD_DATA; 218 } else { 219 ril_proto::ReqSetMute *req = new ril_proto::ReqSetMute(); 220 DBG("ReqSetMute: state=%d", ((int *)data)[0]); 221 req->set_state(((int *)data)[0]); 222 DBG("ReqSetMute: req->ByetSize=%d", req->ByteSize()); 223 buffer = Buffer::New(req->ByteSize()); 224 req->SerializeToArray(buffer->data(), buffer->length()); 225 delete req; 226 *pBuffer = buffer; 227 status = STATUS_OK; 228 } 229 DBG("ReqSetMute X status=%d", status); 230 return status; 231 } 232 233 /** 234 * request for RIL_REQUEST_SCREEN_STATE // 61 235 */ 236 int ReqScreenState(Buffer **pBuffer, 237 const void *data, const size_t datalen, const RIL_Token t) { 238 int status; 239 Buffer *buffer; 240 v8::HandleScope handle_scope; 241 242 DBG("ReqScreenState E data=%p datalen=%d t=%p", 243 data, datalen, t); 244 if (datalen < sizeof(int)) { 245 LOGE("ReqScreenState: data to small err size < sizeof int"); 246 status = STATUS_BAD_DATA; 247 } else { 248 ril_proto::ReqScreenState *req = new ril_proto::ReqScreenState(); 249 DBG("ReqScreenState: state=%d", ((int *)data)[0]); 250 req->set_state(((int *)data)[0]); 251 DBG("ReqScreenState: req->ByteSize()=%d", req->ByteSize()); 252 buffer = Buffer::New(req->ByteSize()); 253 DBG("ReqScreenState: serialize"); 254 req->SerializeToArray(buffer->data(), buffer->length()); 255 delete req; 256 *pBuffer = buffer; 257 status = STATUS_OK; 258 } 259 DBG("ReqScreenState X status=%d", status); 260 return status; 261 } 262 263 /** 264 * Map from indexed by cmd and used to convert Data to Protobuf. 265 */ 266 typedef int (*ReqConversion)(Buffer** pBuffer, const void *data, 267 const size_t datalen, const RIL_Token t); 268 typedef std::map<int, ReqConversion> ReqConversionMap; 269 ReqConversionMap rilReqConversionMap; 270 271 int callOnRilRequest(v8::Handle<v8::Context> context, int cmd, 272 const void *buffer, RIL_Token t) { 273 DBG("callOnRilRequest E: cmd=%d", cmd); 274 275 int status; 276 v8::HandleScope handle_scope; 277 v8::TryCatch try_catch; 278 279 // Get the onRilRequest Function 280 v8::Handle<v8::String> name = v8::String::New("onRilRequest"); 281 v8::Handle<v8::Value> onRilRequestFunctionValue = context->Global()->Get(name); 282 v8::Handle<v8::Function> onRilRequestFunction = 283 v8::Handle<v8::Function>::Cast(onRilRequestFunctionValue); 284 285 // Create the cmd and token 286 v8::Handle<v8::Value> v8RequestValue = v8::Number::New(cmd); 287 v8::Handle<v8::Value> v8TokenValue = v8::Number::New(int64_t(t)); 288 289 // Invoke onRilRequest 290 const int argc = 3; 291 v8::Handle<v8::Value> argv[argc] = { 292 v8RequestValue, v8TokenValue, ((Buffer *)buffer)->handle_ }; 293 v8::Handle<v8::Value> result = 294 onRilRequestFunction->Call(context->Global(), argc, argv); 295 if (try_catch.HasCaught()) { 296 LOGE("callOnRilRequest error"); 297 ReportException(&try_catch); 298 status = STATUS_ERR; 299 } else { 300 v8::String::Utf8Value result_string(result); 301 DBG("callOnRilRequest result=%s", ToCString(result_string)); 302 status = STATUS_OK; 303 } 304 305 DBG("callOnRilRequest X: status=%d", status); 306 return status; 307 } 308 309 RilRequestWorkerQueue::RilRequestWorkerQueue(v8::Handle<v8::Context> context) { 310 DBG("RilRequestWorkerQueue E:"); 311 312 context_ = context; 313 pthread_mutex_init(&free_list_mutex_, NULL); 314 315 DBG("RilRequestWorkerQueue X:"); 316 } 317 318 RilRequestWorkerQueue::~RilRequestWorkerQueue() { 319 DBG("~RilRequestWorkerQueue E:"); 320 Request *req; 321 pthread_mutex_lock(&free_list_mutex_); 322 while(free_list_.size() != 0) { 323 req = free_list_.front(); 324 delete req; 325 free_list_.pop(); 326 } 327 pthread_mutex_unlock(&free_list_mutex_); 328 pthread_mutex_destroy(&free_list_mutex_); 329 DBG("~RilRequestWorkerQueue X:"); 330 } 331 332 /** 333 * Add a request to the processing queue. 334 * Data is serialized to a protobuf before adding to the queue. 335 */ 336 void RilRequestWorkerQueue::AddRequest (const int request, 337 const void *data, const size_t datalen, const RIL_Token token) { 338 DBG("RilRequestWorkerQueue:AddRequest: %d E", request); 339 340 v8::Locker locker; 341 v8::HandleScope handle_scope; 342 v8::Context::Scope context_scope(context_); 343 344 int status; 345 346 // Convert the data to a protobuf before inserting it into the request queue (serialize data) 347 Buffer *buffer = NULL; 348 ReqConversionMap::iterator itr; 349 itr = rilReqConversionMap.find(request); 350 if (itr != rilReqConversionMap.end()) { 351 status = itr->second(&buffer, data, datalen, token); 352 } else { 353 LOGE("RilRequestWorkerQueue:AddRequest: X unknown request %d", request); 354 status = STATUS_UNSUPPORTED_REQUEST; 355 } 356 357 if (status == STATUS_OK) { 358 // Add serialized request to the queue 359 Request *req; 360 pthread_mutex_lock(&free_list_mutex_); 361 DBG("RilRequestWorkerQueue:AddRequest: return ok, buffer = %p, buffer->length()=%d", 362 buffer, buffer->length()); 363 if (free_list_.size() == 0) { 364 req = new Request(request, buffer, token); 365 pthread_mutex_unlock(&free_list_mutex_); 366 } else { 367 req = free_list_.front(); 368 free_list_.pop(); 369 pthread_mutex_unlock(&free_list_mutex_); 370 req->Set(request, buffer, token); 371 } 372 // add the request 373 Add(req); 374 } else { 375 DBG("RilRequestWorkerQueue:AddRequest: return from the serialization, status is not OK"); 376 // An error report complete now 377 RIL_Errno rilErrCode = (status == STATUS_UNSUPPORTED_REQUEST) ? 378 RIL_E_REQUEST_NOT_SUPPORTED : RIL_E_GENERIC_FAILURE; 379 s_rilenv->OnRequestComplete(token, rilErrCode, NULL, 0); 380 } 381 382 DBG("RilRequestWorkerQueue::AddRequest: X" 383 " request=%d data=%p datalen=%d token=%p", 384 request, data, datalen, token); 385 } 386 387 void RilRequestWorkerQueue::Process(void *p) { 388 389 Request *req = (Request *)p; 390 DBG("RilRequestWorkerQueue::Process: E" 391 " request=%d buffer=%p, bufferlen=%d t=%p", 392 req->request_, req->buffer_, req->buffer_->length(), req->token_); 393 394 v8::Locker locker; 395 v8::HandleScope handle_scope; 396 v8::Context::Scope context_scope(context_); 397 callOnRilRequest(context_, req->request_, 398 req->buffer_, req->token_); 399 400 pthread_mutex_lock(&free_list_mutex_); 401 free_list_.push(req); 402 pthread_mutex_unlock(&free_list_mutex_); 403 } 404 405 int requestsInit(v8::Handle<v8::Context> context, RilRequestWorkerQueue **rwq) { 406 LOGD("requestsInit E"); 407 408 rilReqConversionMap[RIL_REQUEST_GET_SIM_STATUS] = ReqWithNoData; // 1 409 rilReqConversionMap[RIL_REQUEST_ENTER_SIM_PIN] = ReqEnterSimPin; // 2 410 rilReqConversionMap[RIL_REQUEST_GET_CURRENT_CALLS] = ReqWithNoData; // 9 411 rilReqConversionMap[RIL_REQUEST_DIAL] = ReqDial; // 10 412 rilReqConversionMap[RIL_REQUEST_GET_IMSI] = ReqWithNoData; // 11 413 rilReqConversionMap[RIL_REQUEST_HANGUP] = ReqHangUp; // 12 414 rilReqConversionMap[RIL_REQUEST_HANGUP_WAITING_OR_BACKGROUND] = ReqWithNoData; // 13 415 rilReqConversionMap[RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND] = ReqWithNoData; // 14 416 rilReqConversionMap[RIL_REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE] = ReqWithNoData; // 15 417 rilReqConversionMap[RIL_REQUEST_CONFERENCE] = ReqWithNoData; // 16 418 rilReqConversionMap[RIL_REQUEST_LAST_CALL_FAIL_CAUSE] = ReqWithNoData; // 18 419 rilReqConversionMap[RIL_REQUEST_SIGNAL_STRENGTH] = ReqWithNoData; // 19 420 rilReqConversionMap[RIL_REQUEST_REGISTRATION_STATE] = ReqWithNoData; // 20 421 rilReqConversionMap[RIL_REQUEST_GPRS_REGISTRATION_STATE] = ReqWithNoData; // 21 422 rilReqConversionMap[RIL_REQUEST_OPERATOR] = ReqWithNoData; // 22 423 rilReqConversionMap[RIL_REQUEST_GET_IMEI] = ReqWithNoData; // 38 424 rilReqConversionMap[RIL_REQUEST_GET_IMEISV] = ReqWithNoData; // 39 425 rilReqConversionMap[RIL_REQUEST_ANSWER] = ReqWithNoData; // 40 426 rilReqConversionMap[RIL_REQUEST_QUERY_NETWORK_SELECTION_MODE] = ReqWithNoData; // 45 427 rilReqConversionMap[RIL_REQUEST_SET_NETWORK_SELECTION_AUTOMATIC] = ReqWithNoData; // 46 428 rilReqConversionMap[RIL_REQUEST_BASEBAND_VERSION] = ReqWithNoData; // 51 429 rilReqConversionMap[RIL_REQUEST_SEPARATE_CONNECTION] = ReqSeparateConnection; // 52 430 rilReqConversionMap[RIL_REQUEST_SET_MUTE] = ReqSetMute; // 53 431 rilReqConversionMap[RIL_REQUEST_SCREEN_STATE] = ReqScreenState; // 61 432 433 *rwq = new RilRequestWorkerQueue(context); 434 int status = (*rwq)->Run(); 435 436 LOGD("requestsInit X: status=%d", status); 437 return status; 438 } 439 440 /** 441 * Subroutine to test a single RIL request 442 */ 443 void testRilRequest(v8::Handle<v8::Context> context, int request, const void *data, 444 const size_t datalen, const RIL_Token t) { 445 Buffer *buffer = NULL; 446 ReqConversionMap::iterator itr; 447 int status; 448 449 LOGD("testRilRequest: request=%d", request); 450 451 itr = rilReqConversionMap.find(request); 452 if (itr != rilReqConversionMap.end()) { 453 status = itr->second(&buffer, data, sizeof(data), (void *)0x12345677); 454 } else { 455 LOGE("testRequests X unknown request %d", request); 456 status = STATUS_UNSUPPORTED_REQUEST; 457 } 458 if (status == STATUS_OK) { 459 callOnRilRequest(context, request, buffer, (void *)0x12345677); 460 } else { 461 LOGE("testRilRequest X, serialize error"); 462 } 463 } 464 465 void testRequests(v8::Handle<v8::Context> context) { 466 LOGD("testRequests E: ********"); 467 468 v8::TryCatch try_catch; 469 470 char *buffer; 471 const char *fileName= "/sdcard/data/mock_ril.js"; 472 int status = ReadFile(fileName, &buffer); 473 if (status == 0) { 474 runJs(context, &try_catch, fileName, buffer); 475 Buffer *buffer = NULL; 476 ReqConversionMap::iterator itr; 477 int status; 478 int request; 479 480 if (!try_catch.HasCaught()) { 481 { 482 const int data[1] = { 1 }; 483 testRilRequest(context, RIL_REQUEST_SIGNAL_STRENGTH, data, sizeof(data), 484 (void *)0x12345677); 485 } 486 { 487 const char *data[1] = { "winks-pin" }; 488 testRilRequest(context, RIL_REQUEST_ENTER_SIM_PIN, data, sizeof(data), 489 (void *)0x12345677); 490 } 491 { 492 const int data[1] = { 1 }; 493 testRilRequest(context, RIL_REQUEST_HANGUP, data, sizeof(data), 494 (void *)0x12345677); 495 } 496 { 497 const int data[1] = { 1 }; 498 testRilRequest(context, RIL_REQUEST_SCREEN_STATE, data, sizeof(data), 499 (void *)0x12345677); 500 } 501 { 502 const int data[1] = { 1 }; 503 testRilRequest(context, RIL_REQUEST_GET_SIM_STATUS, data, sizeof(data), 504 (void *)0x12345677); 505 } 506 { 507 RilRequestWorkerQueue *rwq = new RilRequestWorkerQueue(context); 508 if (rwq->Run() == STATUS_OK) { 509 const int data[1] = { 1 }; 510 rwq->AddRequest(RIL_REQUEST_SCREEN_STATE, 511 data, sizeof(data), (void *)0x1234567A); 512 rwq->AddRequest(RIL_REQUEST_SIGNAL_STRENGTH, 513 data, sizeof(data), (void *)0x1234567A); 514 // Sleep to let it be processed 515 v8::Unlocker unlocker; 516 sleep(3); 517 v8::Locker locker; 518 } 519 delete rwq; 520 } 521 } 522 } 523 524 LOGD("testRequests X: ********\n"); 525 } 526