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