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 #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 
     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)
     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
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    499 void RilSapSocket::onCommandsSocketClosed() {
    500     sendDisconnect();
    501     RLOGE("Socket command closed");
    502 }
    503