1 /*
2 * Copyright (C) 2014 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 #define __STDC_LIMIT_MACROS
18 #include <stdint.h>
19 #define RIL_SHLIB
20 #include "telephony/ril.h"
21 #include "RilSapSocket.h"
22 #include "pb_decode.h"
23 #include "pb_encode.h"
24 #define LOG_TAG "RIL_UIM_SOCKET"
25 #include <utils/Log.h>
26 #include <arpa/inet.h>
27 #include <errno.h>
28
29 static RilSapSocket::RilSapSocketList *head = NULL;
30
31 void ril_sap_on_request_complete (
32 RIL_Token t, RIL_Errno e,
33 void *response, size_t responselen
34 );
35
36 void ril_sap_on_unsolicited_response (
37 int unsolResponse, const void *data,
38 size_t datalen
39 );
40 extern "C" void
41 RIL_requestTimedCallback (RIL_TimedCallback callback, void *param,
42 const struct timeval *relativeTime);
43
44 struct RIL_Env RilSapSocket::uimRilEnv = {
45 .OnRequestComplete = RilSapSocket::sOnRequestComplete,
46 .OnUnsolicitedResponse = RilSapSocket::sOnUnsolicitedResponse,
47 .RequestTimedCallback = RIL_requestTimedCallback
48 };
49
sOnRequestComplete(RIL_Token t,RIL_Errno e,void * response,size_t responselen)50 void RilSapSocket::sOnRequestComplete (RIL_Token t,
51 RIL_Errno e,
52 void *response,
53 size_t responselen) {
54 RilSapSocket *sap_socket;
55 SapSocketRequest *request = (SapSocketRequest*) t;
56
57 RLOGD("Socket id:%d", request->socketId);
58
59 sap_socket = getSocketById(request->socketId);
60
61 if (sap_socket) {
62 sap_socket->onRequestComplete(t,e,response,responselen);
63 } else {
64 RLOGE("Invalid socket id");
65 if (request->curr->payload) {
66 free(request->curr->payload);
67 }
68 free(request->curr);
69 free(request);
70 }
71 }
72
73 #if defined(ANDROID_MULTI_SIM)
sOnUnsolicitedResponse(int unsolResponse,const void * data,size_t datalen,RIL_SOCKET_ID socketId)74 void RilSapSocket::sOnUnsolicitedResponse(int unsolResponse,
75 const void *data,
76 size_t datalen,
77 RIL_SOCKET_ID socketId) {
78 RilSapSocket *sap_socket = getSocketById(socketId);
79 if (sap_socket) {
80 sap_socket->onUnsolicitedResponse(unsolResponse, (void *)data, datalen);
81 }
82 }
83 #else
sOnUnsolicitedResponse(int unsolResponse,const void * data,size_t datalen)84 void RilSapSocket::sOnUnsolicitedResponse(int unsolResponse,
85 const void *data,
86 size_t datalen) {
87 RilSapSocket *sap_socket = getSocketById(RIL_SOCKET_1);
88 sap_socket->onUnsolicitedResponse(unsolResponse, (void *)data, datalen);
89 }
90 #endif
91
printList()92 void RilSapSocket::printList() {
93 RilSapSocketList *current = head;
94 RLOGD("Printing socket list");
95 while(NULL != current) {
96 RLOGD("SocketName:%s",current->socket->name);
97 RLOGD("Socket id:%d",current->socket->id);
98 current = current->next;
99 }
100 }
101
getSocketById(RIL_SOCKET_ID socketId)102 RilSapSocket *RilSapSocket::getSocketById(RIL_SOCKET_ID socketId) {
103 RilSapSocket *sap_socket;
104 RilSapSocketList *current = head;
105
106 RLOGD("Entered getSocketById");
107 printList();
108
109 while(NULL != current) {
110 if(socketId == current->socket->id) {
111 sap_socket = current->socket;
112 return sap_socket;
113 }
114 current = current->next;
115 }
116 return NULL;
117 }
118
initSapSocket(const char * socketName,RIL_RadioFunctions * uimFuncs)119 void RilSapSocket::initSapSocket(const char *socketName,
120 RIL_RadioFunctions *uimFuncs) {
121
122 if (strcmp(socketName, "sap_uim_socket1") == 0) {
123 if(!SocketExists(socketName)) {
124 addSocketToList(socketName, RIL_SOCKET_1, uimFuncs);
125 }
126 }
127
128 #if (SIM_COUNT >= 2)
129 if (strcmp(socketName, "sap_uim_socket2") == 0) {
130 if(!SocketExists(socketName)) {
131 addSocketToList(socketName, RIL_SOCKET_2, uimFuncs);
132 }
133 }
134 #endif
135
136 #if (SIM_COUNT >= 3)
137 if (strcmp(socketName, "sap_uim_socket3") == 0) {
138 if(!SocketExists(socketName)) {
139 addSocketToList(socketName, RIL_SOCKET_3, uimFuncs);
140 }
141 }
142 #endif
143
144 #if (SIM_COUNT >= 4)
145 if (strcmp(socketName, "sap_uim_socket4") == 0) {
146 if(!SocketExists(socketName)) {
147 addSocketToList(socketName, RIL_SOCKET_4, uimFuncs);
148 }
149 }
150 #endif
151 }
152
addSocketToList(const char * socketName,RIL_SOCKET_ID socketid,RIL_RadioFunctions * uimFuncs)153 void RilSapSocket::addSocketToList(const char *socketName, RIL_SOCKET_ID socketid,
154 RIL_RadioFunctions *uimFuncs) {
155 RilSapSocket* socket = NULL;
156 RilSapSocketList *current;
157
158 if(!SocketExists(socketName)) {
159 socket = new RilSapSocket(socketName, socketid, uimFuncs);
160 RilSapSocketList* listItem = (RilSapSocketList*)malloc(sizeof(RilSapSocketList));
161 if (!listItem) {
162 RLOGE("addSocketToList: OOM");
163 return;
164 }
165 listItem->socket = socket;
166 listItem->next = NULL;
167
168 RLOGD("Adding socket with id: %d", socket->id);
169
170 if(NULL == head) {
171 head = listItem;
172 head->next = NULL;
173 }
174 else {
175 current = head;
176 while(NULL != current->next) {
177 current = current->next;
178 }
179 current->next = listItem;
180 }
181 socket->socketInit();
182 }
183 }
184
SocketExists(const char * socketName)185 bool RilSapSocket::SocketExists(const char *socketName) {
186 RilSapSocketList* current = head;
187
188 while(NULL != current) {
189 if(strcmp(current->socket->name, socketName) == 0) {
190 return true;
191 }
192 current = current->next;
193 }
194 return false;
195 }
196
processRequestsLoop(void)197 void* RilSapSocket::processRequestsLoop(void) {
198 RLOGI("UIM_SOCKET:Request loop started");
199
200 while(true) {
201 SapSocketRequest *req = dispatchQueue.dequeue();
202
203 RLOGI("New request from the dispatch Queue");
204
205 if (req != NULL) {
206 dispatchRequest(req->curr);
207 free(req);
208 } else {
209 RLOGE("Fetched null buffer from queue!");
210 }
211 }
212 return NULL;
213 }
214
RilSapSocket(const char * socketName,RIL_SOCKET_ID socketId,RIL_RadioFunctions * inputUimFuncs)215 RilSapSocket::RilSapSocket(const char *socketName,
216 RIL_SOCKET_ID socketId,
217 RIL_RadioFunctions *inputUimFuncs):
218 RilSocket(socketName, socketId) {
219 if (inputUimFuncs) {
220 uimFuncs = inputUimFuncs;
221 }
222 }
223
224 #define BYTES_PER_LINE 16
225
226 #define NIBBLE_TO_HEX(n) ({ \
227 uint8_t __n = (uint8_t) n & 0x0f; \
228 __nibble >= 10 ? 'A' + __n - 10: '0' + __n; \
229 })
230
231 #define HEX_HIGH(b) ({ \
232 uint8_t __b = (uint8_t) b; \
233 uint8_t __nibble = (__b >> 4) & 0x0f; \
234 NIBBLE_TO_HEX(__nibble); \
235 })
236
237 #define HEX_LOW(b) ({ \
238 uint8_t __b = (uint8_t) b; \
239 uint8_t __nibble = __b & 0x0f; \
240 NIBBLE_TO_HEX(__nibble); \
241 })
242
log_hex(const char * who,const uint8_t * buffer,int length)243 void log_hex(const char *who, const uint8_t *buffer, int length) {
244 char out[80];
245 int source = 0;
246 int dest = 0;
247 int dest_len = sizeof(out);
248 int per_line = 0;
249
250 do {
251 dest += sprintf(out, "%8.8s [%8.8x] ", who, source);
252 for(; source < length && dest_len - dest > 3 && per_line < BYTES_PER_LINE; source++,
253 per_line ++) {
254 out[dest++] = HEX_HIGH(buffer[source]);
255 out[dest++] = HEX_LOW(buffer[source]);
256 out[dest++] = ' ';
257 }
258 if (dest < dest_len && (per_line == BYTES_PER_LINE || source >= length)) {
259 out[dest++] = 0;
260 per_line = 0;
261 dest = 0;
262 RLOGD("%s\n", out);
263 }
264 } while(source < length && dest < dest_len);
265 }
266
dispatchRequest(MsgHeader * req)267 void RilSapSocket::dispatchRequest(MsgHeader *req) {
268 // SapSocketRequest will be deallocated in onRequestComplete()
269 SapSocketRequest* currRequest=(SapSocketRequest*)malloc(sizeof(SapSocketRequest));
270 if (!currRequest) {
271 RLOGE("dispatchRequest: OOM");
272 // Free MsgHeader allocated in pushRecord()
273 free(req);
274 return;
275 }
276 currRequest->token = req->token;
277 currRequest->curr = req;
278 currRequest->p_next = NULL;
279 currRequest->socketId = id;
280
281 pendingResponseQueue.enqueue(currRequest);
282
283 if (uimFuncs) {
284 RLOGI("[%d] > SAP REQUEST type: %d. id: %d. error: %d",
285 req->token,
286 req->type,
287 req->id,
288 req->error );
289
290 #if defined(ANDROID_MULTI_SIM)
291 uimFuncs->onRequest(req->id, req->payload->bytes, req->payload->size, currRequest, id);
292 #else
293 uimFuncs->onRequest(req->id, req->payload->bytes, req->payload->size, currRequest);
294 #endif
295 }
296 }
297
onRequestComplete(RIL_Token t,RIL_Errno e,void * response,size_t response_len)298 void RilSapSocket::onRequestComplete(RIL_Token t, RIL_Errno e, void *response,
299 size_t response_len) {
300 SapSocketRequest* request= (SapSocketRequest*)t;
301 MsgHeader *hdr = request->curr;
302
303 MsgHeader rsp;
304 rsp.token = request->curr->token;
305 rsp.type = MsgType_RESPONSE;
306 rsp.id = request->curr->id;
307 rsp.error = (Error)e;
308 rsp.payload = (pb_bytes_array_t *)calloc(1, sizeof(pb_bytes_array_t) + response_len);
309 if (!rsp.payload) {
310 RLOGE("onRequestComplete: OOM");
311 } else {
312 if (response && response_len > 0) {
313 memcpy(rsp.payload->bytes, response, response_len);
314 rsp.payload->size = response_len;
315 } else {
316 rsp.payload->size = 0;
317 }
318
319 RLOGE("Token:%d, MessageId:%d", hdr->token, hdr->id);
320
321 sendResponse(&rsp);
322 free(rsp.payload);
323 }
324
325 // Deallocate SapSocketRequest
326 if(!pendingResponseQueue.checkAndDequeue(hdr->id, hdr->token)) {
327 RLOGE("Token:%d, MessageId:%d", hdr->token, hdr->id);
328 RLOGE ("RilSapSocket::onRequestComplete: invalid Token or Message Id");
329 }
330
331 // Deallocate MsgHeader
332 free(hdr);
333 }
334
sendResponse(MsgHeader * hdr)335 void RilSapSocket::sendResponse(MsgHeader* hdr) {
336 size_t encoded_size = 0;
337 uint32_t written_size;
338 size_t buffer_size = 0;
339 pb_ostream_t ostream;
340 bool success = false;
341
342 pthread_mutex_lock(&write_lock);
343
344 if ((success = pb_get_encoded_size(&encoded_size, MsgHeader_fields,
345 hdr)) && encoded_size <= INT32_MAX && commandFd != -1) {
346 buffer_size = encoded_size + sizeof(uint32_t);
347 uint8_t buffer[buffer_size];
348 written_size = htonl((uint32_t) encoded_size);
349 ostream = pb_ostream_from_buffer(buffer, buffer_size);
350 pb_write(&ostream, (uint8_t *)&written_size, sizeof(written_size));
351 success = pb_encode(&ostream, MsgHeader_fields, hdr);
352
353 if (success) {
354 RLOGD("Size: %d (0x%x) Size as written: 0x%x", encoded_size, encoded_size,
355 written_size);
356 log_hex("onRequestComplete", &buffer[sizeof(written_size)], encoded_size);
357 RLOGI("[%d] < SAP RESPONSE type: %d. id: %d. error: %d",
358 hdr->token, hdr->type, hdr->id,hdr->error );
359
360 if ( 0 != blockingWrite_helper(commandFd, buffer, buffer_size)) {
361 RLOGE("Error %d while writing to fd", errno);
362 } else {
363 RLOGD("Write successful");
364 }
365 } else {
366 RLOGE("Error while encoding response of type %d id %d buffer_size: %d: %s.",
367 hdr->type, hdr->id, buffer_size, PB_GET_ERROR(&ostream));
368 }
369 } else {
370 RLOGE("Not sending response type %d: encoded_size: %u. commandFd: %d. encoded size result: %d",
371 hdr->type, encoded_size, commandFd, success);
372 }
373
374 pthread_mutex_unlock(&write_lock);
375 }
376
onUnsolicitedResponse(int unsolResponse,void * data,size_t datalen)377 void RilSapSocket::onUnsolicitedResponse(int unsolResponse, void *data, size_t datalen) {
378 if (data && datalen > 0) {
379 pb_bytes_array_t *payload = (pb_bytes_array_t *)calloc(1,
380 sizeof(pb_bytes_array_t) + datalen);
381 if (!payload) {
382 RLOGE("onUnsolicitedResponse: OOM");
383 return;
384 }
385 memcpy(payload->bytes, data, datalen);
386 payload->size = datalen;
387 MsgHeader rsp;
388 rsp.payload = payload;
389 rsp.type = MsgType_UNSOL_RESPONSE;
390 rsp.id = (MsgId)unsolResponse;
391 rsp.error = Error_RIL_E_SUCCESS;
392 sendResponse(&rsp);
393 free(payload);
394 }
395 }
396
pushRecord(void * p_record,size_t recordlen)397 void RilSapSocket::pushRecord(void *p_record, size_t recordlen) {
398 pb_istream_t stream = pb_istream_from_buffer((uint8_t *)p_record, recordlen);
399 // MsgHeader will be deallocated in onRequestComplete()
400 MsgHeader *reqHeader = (MsgHeader *)malloc(sizeof (MsgHeader));
401 if (!reqHeader) {
402 RLOGE("pushRecord: OOM");
403 return;
404 }
405 memset(reqHeader, 0, sizeof(MsgHeader));
406
407 log_hex("BtSapTest-Payload", (const uint8_t*)p_record, recordlen);
408
409 if (!pb_decode(&stream, MsgHeader_fields, reqHeader) ) {
410 RLOGE("Error decoding protobuf buffer : %s", PB_GET_ERROR(&stream));
411 free(reqHeader);
412 } else {
413 // SapSocketRequest will be deallocated in processRequestsLoop()
414 SapSocketRequest *recv = (SapSocketRequest*)malloc(sizeof(SapSocketRequest));
415 if (!recv) {
416 RLOGE("pushRecord: OOM");
417 free(reqHeader);
418 return;
419 }
420 recv->token = reqHeader->token;
421 recv->curr = reqHeader;
422 recv->socketId = id;
423
424 dispatchQueue.enqueue(recv);
425 }
426 }
427
sendDisconnect()428 void RilSapSocket::sendDisconnect() {
429 size_t encoded_size = 0;
430 uint32_t written_size;
431 size_t buffer_size = 0;
432 pb_ostream_t ostream;
433 bool success = false;
434
435 RIL_SIM_SAP_DISCONNECT_REQ disconnectReq;
436
437 if ((success = pb_get_encoded_size(&encoded_size, RIL_SIM_SAP_DISCONNECT_REQ_fields,
438 &disconnectReq)) && encoded_size <= INT32_MAX) {
439 buffer_size = encoded_size + sizeof(uint32_t);
440 uint8_t buffer[buffer_size];
441 written_size = htonl((uint32_t) encoded_size);
442 ostream = pb_ostream_from_buffer(buffer, buffer_size);
443 pb_write(&ostream, (uint8_t *)&written_size, sizeof(written_size));
444 success = pb_encode(&ostream, RIL_SIM_SAP_DISCONNECT_REQ_fields, buffer);
445
446 if(success) {
447 // Buffer will be deallocated in sOnRequestComplete()
448 pb_bytes_array_t *payload = (pb_bytes_array_t *)calloc(1,
449 sizeof(pb_bytes_array_t) + written_size);
450 if (!payload) {
451 RLOGE("sendDisconnect: OOM");
452 return;
453 }
454 memcpy(payload->bytes, buffer, written_size);
455 payload->size = written_size;
456 // MsgHeader will be deallocated in sOnRequestComplete()
457 MsgHeader *hdr = (MsgHeader *)malloc(sizeof(MsgHeader));
458 if (!hdr) {
459 RLOGE("sendDisconnect: OOM");
460 free(payload);
461 return;
462 }
463 hdr->payload = payload;
464 hdr->type = MsgType_REQUEST;
465 hdr->id = MsgId_RIL_SIM_SAP_DISCONNECT;
466 hdr->error = Error_RIL_E_SUCCESS;
467 dispatchDisconnect(hdr);
468 }
469 else {
470 RLOGE("Encode failed in send disconnect!");
471 }
472 }
473 }
474
dispatchDisconnect(MsgHeader * req)475 void RilSapSocket::dispatchDisconnect(MsgHeader *req) {
476 // SapSocketRequest will be deallocated in sOnRequestComplete()
477 SapSocketRequest* currRequest=(SapSocketRequest*)malloc(sizeof(SapSocketRequest));
478 if (!currRequest) {
479 RLOGE("dispatchDisconnect: OOM");
480 // Free memory allocated in sendDisconnect
481 free(req->payload);
482 free(req);
483 return;
484 }
485 currRequest->token = -1;
486 currRequest->curr = req;
487 currRequest->p_next = NULL;
488 currRequest->socketId = (RIL_SOCKET_ID)99;
489
490 RLOGD("Sending disconnect on command close!");
491
492 #if defined(ANDROID_MULTI_SIM)
493 uimFuncs->onRequest(req->id, req->payload->bytes, req->payload->size, currRequest, id);
494 #else
495 uimFuncs->onRequest(req->id, req->payload->bytes, req->payload->size, currRequest);
496 #endif
497 }
498
onCommandsSocketClosed()499 void RilSapSocket::onCommandsSocketClosed() {
500 sendDisconnect();
501 RLOGE("Socket command closed");
502 }
503