• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     if (response && response_len > 0) {
304         MsgHeader rsp;
305         rsp.token = request->curr->token;
306         rsp.type = MsgType_RESPONSE;
307         rsp.id = request->curr->id;
308         rsp.error = (Error)e;
309         rsp.payload = (pb_bytes_array_t *)calloc(1,
310                 sizeof(pb_bytes_array_t) + response_len);
311         if (!rsp.payload) {
312             RLOGE("onRequestComplete: OOM");
313         } else {
314             memcpy(rsp.payload->bytes, response, response_len);
315             rsp.payload->size = response_len;
316 
317             RLOGE("Token:%d, MessageId:%d", hdr->token, hdr->id);
318 
319             sendResponse(&rsp);
320             free(rsp.payload);
321         }
322     }
323 
324     // Deallocate SapSocketRequest
325     if(!pendingResponseQueue.checkAndDequeue(hdr->id, hdr->token)) {
326         RLOGE("Token:%d, MessageId:%d", hdr->token, hdr->id);
327         RLOGE ("RilSapSocket::onRequestComplete: invalid Token or Message Id");
328     }
329 
330     // Deallocate MsgHeader
331     free(hdr);
332 }
333 
sendResponse(MsgHeader * hdr)334 void RilSapSocket::sendResponse(MsgHeader* hdr) {
335     size_t encoded_size = 0;
336     uint32_t written_size;
337     size_t buffer_size = 0;
338     pb_ostream_t ostream;
339     bool success = false;
340 
341     pthread_mutex_lock(&write_lock);
342 
343     if ((success = pb_get_encoded_size(&encoded_size, MsgHeader_fields,
344         hdr)) && encoded_size <= INT32_MAX && commandFd != -1) {
345         buffer_size = encoded_size + sizeof(uint32_t);
346         uint8_t buffer[buffer_size];
347         written_size = htonl((uint32_t) encoded_size);
348         ostream = pb_ostream_from_buffer(buffer, buffer_size);
349         pb_write(&ostream, (uint8_t *)&written_size, sizeof(written_size));
350         success = pb_encode(&ostream, MsgHeader_fields, hdr);
351 
352         if (success) {
353             RLOGD("Size: %d (0x%x) Size as written: 0x%x", encoded_size, encoded_size,
354         written_size);
355             log_hex("onRequestComplete", &buffer[sizeof(written_size)], encoded_size);
356             RLOGI("[%d] < SAP RESPONSE type: %d. id: %d. error: %d",
357         hdr->token, hdr->type, hdr->id,hdr->error );
358 
359             if ( 0 != blockingWrite_helper(commandFd, buffer, buffer_size)) {
360                 RLOGE("Error %d while writing to fd", errno);
361             } else {
362                 RLOGD("Write successful");
363             }
364         } else {
365             RLOGE("Error while encoding response of type %d id %d buffer_size: %d: %s.",
366             hdr->type, hdr->id, buffer_size, PB_GET_ERROR(&ostream));
367         }
368     } else {
369     RLOGE("Not sending response type %d: encoded_size: %u. commandFd: %d. encoded size result: %d",
370         hdr->type, encoded_size, commandFd, success);
371     }
372 
373     pthread_mutex_unlock(&write_lock);
374 }
375 
onUnsolicitedResponse(int unsolResponse,void * data,size_t datalen)376 void RilSapSocket::onUnsolicitedResponse(int unsolResponse, void *data, size_t datalen) {
377     if (data && datalen > 0) {
378         pb_bytes_array_t *payload = (pb_bytes_array_t *)calloc(1,
379                 sizeof(pb_bytes_array_t) + datalen);
380         if (!payload) {
381             RLOGE("onUnsolicitedResponse: OOM");
382             return;
383         }
384         memcpy(payload->bytes, data, datalen);
385         payload->size = datalen;
386         MsgHeader rsp;
387         rsp.payload = payload;
388         rsp.type = MsgType_UNSOL_RESPONSE;
389         rsp.id = (MsgId)unsolResponse;
390         rsp.error = Error_RIL_E_SUCCESS;
391         sendResponse(&rsp);
392         free(payload);
393     }
394 }
395 
pushRecord(void * p_record,size_t recordlen)396 void RilSapSocket::pushRecord(void *p_record, size_t recordlen) {
397     pb_istream_t stream = pb_istream_from_buffer((uint8_t *)p_record, recordlen);
398     // MsgHeader will be deallocated in onRequestComplete()
399     MsgHeader *reqHeader = (MsgHeader *)malloc(sizeof (MsgHeader));
400     if (!reqHeader) {
401         RLOGE("pushRecord: OOM");
402         return;
403     }
404     memset(reqHeader, 0, sizeof(MsgHeader));
405 
406     log_hex("BtSapTest-Payload", (const uint8_t*)p_record, recordlen);
407 
408     if (!pb_decode(&stream, MsgHeader_fields, reqHeader) ) {
409         RLOGE("Error decoding protobuf buffer : %s", PB_GET_ERROR(&stream));
410         free(reqHeader);
411     } else {
412         // SapSocketRequest will be deallocated in processRequestsLoop()
413         SapSocketRequest *recv = (SapSocketRequest*)malloc(sizeof(SapSocketRequest));
414         if (!recv) {
415             RLOGE("pushRecord: OOM");
416             free(reqHeader);
417             return;
418         }
419         recv->token = reqHeader->token;
420         recv->curr = reqHeader;
421         recv->socketId = id;
422 
423         dispatchQueue.enqueue(recv);
424     }
425 }
426 
sendDisconnect()427 void RilSapSocket::sendDisconnect() {
428     size_t encoded_size = 0;
429     uint32_t written_size;
430     size_t buffer_size = 0;
431     pb_ostream_t ostream;
432     bool success = false;
433 
434     RIL_SIM_SAP_DISCONNECT_REQ disconnectReq;
435 
436    if ((success = pb_get_encoded_size(&encoded_size, RIL_SIM_SAP_DISCONNECT_REQ_fields,
437         &disconnectReq)) && encoded_size <= INT32_MAX) {
438         buffer_size = encoded_size + sizeof(uint32_t);
439         uint8_t buffer[buffer_size];
440         written_size = htonl((uint32_t) encoded_size);
441         ostream = pb_ostream_from_buffer(buffer, buffer_size);
442         pb_write(&ostream, (uint8_t *)&written_size, sizeof(written_size));
443         success = pb_encode(&ostream, RIL_SIM_SAP_DISCONNECT_REQ_fields, buffer);
444 
445         if(success) {
446             // Buffer will be deallocated in sOnRequestComplete()
447             pb_bytes_array_t *payload = (pb_bytes_array_t *)calloc(1,
448                     sizeof(pb_bytes_array_t) + written_size);
449             if (!payload) {
450                 RLOGE("sendDisconnect: OOM");
451                 return;
452             }
453             memcpy(payload->bytes, buffer, written_size);
454             payload->size = written_size;
455             // MsgHeader will be deallocated in sOnRequestComplete()
456             MsgHeader *hdr = (MsgHeader *)malloc(sizeof(MsgHeader));
457             if (!hdr) {
458                 RLOGE("sendDisconnect: OOM");
459                 free(payload);
460                 return;
461             }
462             hdr->payload = payload;
463             hdr->type = MsgType_REQUEST;
464             hdr->id = MsgId_RIL_SIM_SAP_DISCONNECT;
465             hdr->error = Error_RIL_E_SUCCESS;
466             dispatchDisconnect(hdr);
467         }
468         else {
469             RLOGE("Encode failed in send disconnect!");
470         }
471     }
472 }
473 
dispatchDisconnect(MsgHeader * req)474 void RilSapSocket::dispatchDisconnect(MsgHeader *req) {
475     // SapSocketRequest will be deallocated in sOnRequestComplete()
476     SapSocketRequest* currRequest=(SapSocketRequest*)malloc(sizeof(SapSocketRequest));
477     if (!currRequest) {
478         RLOGE("dispatchDisconnect: OOM");
479         // Free memory allocated in sendDisconnect
480         free(req->payload);
481         free(req);
482         return;
483     }
484     currRequest->token = -1;
485     currRequest->curr = req;
486     currRequest->p_next = NULL;
487     currRequest->socketId = (RIL_SOCKET_ID)99;
488 
489     RLOGD("Sending disconnect on command close!");
490 
491 #if defined(ANDROID_MULTI_SIM)
492     uimFuncs->onRequest(req->id, req->payload->bytes, req->payload->size, currRequest, id);
493 #else
494     uimFuncs->onRequest(req->id, req->payload->bytes, req->payload->size, currRequest);
495 #endif
496 }
497 
onCommandsSocketClosed()498 void RilSapSocket::onCommandsSocketClosed() {
499     sendDisconnect();
500     RLOGE("Socket command closed");
501 }
502