diff options
author | Vinit Deshpande <vinitd@google.com> | 2015-04-14 16:27:44 -0700 |
---|---|---|
committer | Vinit Deshpande <vinitd@google.com> | 2015-04-14 16:27:44 -0700 |
commit | fd08733077d63c6e50e913cdf33714ba08940cbc (patch) | |
tree | eac6ca7b5c9e74d0ce3621d5bf71fc08731f64c4 | |
parent | b5a6e5059bdca5c59ab800c369331042b82b5243 (diff) | |
parent | 27976c479473bb772703fe4caa100e535e635e84 (diff) | |
download | android_hardware_ril-fd08733077d63c6e50e913cdf33714ba08940cbc.tar.gz android_hardware_ril-fd08733077d63c6e50e913cdf33714ba08940cbc.tar.bz2 android_hardware_ril-fd08733077d63c6e50e913cdf33714ba08940cbc.zip |
am 27976c4..27976c4 from mirror-m-wireless-internal-release
27976c4 Introduction of the new SAP-UIM socket
Change-Id: I9ab9d65f230edd83037e2d1779b3bdd3b32a0aa7
-rw-r--r-- | libril/Android.mk | 37 | ||||
-rw-r--r-- | libril/RilSapSocket.cpp | 457 | ||||
-rw-r--r-- | libril/RilSapSocket.h | 262 | ||||
-rw-r--r-- | libril/RilSocket.cpp | 177 | ||||
-rw-r--r-- | libril/RilSocket.h | 270 | ||||
-rw-r--r-- | libril/ril.cpp | 142 | ||||
-rw-r--r-- | libril/rilSocketQueue.h | 167 | ||||
-rw-r--r-- | libril/ril_ex.h | 48 | ||||
-rw-r--r-- | librilutils/Android.mk | 25 | ||||
-rw-r--r-- | librilutils/proto/sap-api.options | 23 | ||||
-rw-r--r-- | rild/Android.mk | 2 | ||||
-rw-r--r-- | rild/rild.c | 46 |
12 files changed, 1602 insertions, 54 deletions
diff --git a/libril/Android.mk b/libril/Android.mk index e8b815e..5ac5fb3 100644 --- a/libril/Android.mk +++ b/libril/Android.mk @@ -5,7 +5,9 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES:= \ ril.cpp \ - ril_event.cpp + ril_event.cpp\ + RilSocket.cpp \ + RilSapSocket.cpp \ LOCAL_SHARED_LIBRARIES := \ liblog \ @@ -13,7 +15,10 @@ LOCAL_SHARED_LIBRARIES := \ libbinder \ libcutils \ libhardware_legacy \ - librilutils + librilutils \ + +LOCAL_STATIC_LIBRARIES := \ + libnanopb-c-2.8.0-enable_malloc \ #LOCAL_CFLAGS := -DANDROID_MULTI_SIM -DDSDA_RILD1 @@ -21,6 +26,34 @@ ifeq ($(SIM_COUNT), 2) LOCAL_CFLAGS += -DANDROID_SIM_COUNT_2 endif +LOCAL_C_INCLUDES += $(TARGET_OUT_HEADER)/librilutils +LOCAL_C_INCLUDES += external/nanopb-c + LOCAL_MODULE:= libril +LOCAL_COPY_HEADERS_TO := libril +LOCAL_COPY_HEADERS := ril_ex.h + include $(BUILD_SHARED_LIBRARY) + + +# For RdoServD which needs a static library +# ========================================= +ifneq ($(ANDROID_BIONIC_TRANSITION),) +include $(CLEAR_VARS) + +LOCAL_SRC_FILES:= \ + ril.cpp + +LOCAL_STATIC_LIBRARIES := \ + libutils_static \ + libcutils \ + librilutils_static \ + libnanopb-c-2.8.0-enable_malloc \ + +LOCAL_CFLAGS := + +LOCAL_MODULE:= libril_static + +include $(BUILD_STATIC_LIBRARY) +endif # ANDROID_BIONIC_TRANSITION diff --git a/libril/RilSapSocket.cpp b/libril/RilSapSocket.cpp new file mode 100644 index 0000000..92cc98c --- /dev/null +++ b/libril/RilSapSocket.cpp @@ -0,0 +1,457 @@ +/* +* Copyright (C) 2014 The Android Open Source Project +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#define __STDC_LIMIT_MACROS +#include <stdint.h> +#define RIL_SHLIB +#include "telephony/ril.h" +#include "RilSapSocket.h" +#include "pb_decode.h" +#include "pb_encode.h" +#define LOG_TAG "RIL_UIM_SOCKET" +#include <utils/Log.h> +#include <arpa/inet.h> + +RilSapSocket::RilSapSocketList *head; + +void ril_sap_on_request_complete ( + RIL_Token t, RIL_Errno e, + void *response, size_t responselen +); + +void ril_sap_on_unsolicited_response ( + int unsolResponse, const void *data, + size_t datalen +); +extern "C" void +RIL_requestTimedCallback (RIL_TimedCallback callback, void *param, + const struct timeval *relativeTime); + +struct RIL_Env RilSapSocket::uimRilEnv = { + .OnRequestComplete = RilSapSocket::sOnRequestComplete, + .OnUnsolicitedResponse = RilSapSocket::sOnUnsolicitedResponse, + .RequestTimedCallback = RIL_requestTimedCallback +}; + +void RilSapSocket::sOnRequestComplete (RIL_Token t, + RIL_Errno e, + void *response, + size_t responselen) { + RilSapSocket *sap_socket; + SapSocketRequest *request = (SapSocketRequest*) t; + + RLOGD("Socket id:%d", request->socketId); + + sap_socket = getSocketById(request->socketId); + + if (sap_socket) { + sap_socket->onRequestComplete(t,e,response,responselen); + } else { + RLOGE("Invalid socket id"); + free(request->curr); + free(request); + } +} + +#if defined(ANDROID_MULTI_SIM) +void RilSapSocket::sOnUnsolicitedResponse(int unsolResponse, + const void *data, + size_t datalen, + RIL_SOCKET_ID socketId) { + RilSapSocket *sap_socket = getSocketById(socketId); + if (sap_socket) { + sap_socket->onUnsolicitedResponse(unsolResponse, (void *)data, datalen); + } +} +#else +void RilSapSocket::sOnUnsolicitedResponse(int unsolResponse, + const void *data, + size_t datalen) { + RilSapSocket *sap_socket = getSocketById(RIL_SOCKET_1); + sap_socket->onUnsolicitedResponse(unsolResponse, (void *)data, datalen); +} +#endif + +void RilSapSocket::printList() { + RilSapSocketList *current = head; + RLOGD("Printing socket list"); + while(NULL != current) { + RLOGD("SocketName:%s",current->socket->name); + RLOGD("Socket id:%d",current->socket->id); + current = current->next; + } +} + +RilSapSocket *RilSapSocket::getSocketById(RIL_SOCKET_ID socketId) { + RilSapSocket *sap_socket; + RilSapSocketList *current = head; + + RLOGD("Entered getSocketById"); + printList(); + + while(NULL != current) { + if(socketId == current->socket->id) { + sap_socket = current->socket; + return sap_socket; + } + current = current->next; + } + return NULL; +} + +void RilSapSocket::initSapSocket(const char *socketName, + RIL_RadioFunctions *uimFuncs) { + + if (strcmp(socketName, "sap_uim_socket1") == 0) { + if(!SocketExists(socketName)) { + addSocketToList(socketName, RIL_SOCKET_1, uimFuncs); + } + } + +#if (SIM_COUNT >= 2) + if (strcmp(socketName, "sap_uim_socket2") == 0) { + if(!SocketExists(socketName)) { + addSocketToList(socketName, RIL_SOCKET_2, uimFuncs); + } + } +#endif + +#if (SIM_COUNT >= 3) + if (strcmp(socketName, "sap_uim_socket3") == 0) { + if(!SocketExists(socketName)) { + addSocketToList(socketName, RIL_SOCKET_3, uimFuncs); + } + } +#endif + +#if (SIM_COUNT >= 4) + if (strcmp(socketName, "sap_uim_socket4") == 0) { + if(!SocketExists(socketName)) { + addSocketToList(socketName, RIL_SOCKET_4, uimFuncs); + } + } +#endif +} + +void RilSapSocket::addSocketToList(const char *socketName, RIL_SOCKET_ID socketid, + RIL_RadioFunctions *uimFuncs) { + RilSapSocket* socket = NULL; + RilSapSocketList* listItem = (RilSapSocketList*)malloc(sizeof(RilSapSocketList)); + RilSapSocketList *current; + + if(!SocketExists(socketName)) { + socket = new RilSapSocket(socketName, socketid, uimFuncs); + listItem->socket = socket; + listItem->next = NULL; + + RLOGD("Adding socket with id: %d", socket->id); + + if(NULL == head) { + head = listItem; + head->next = NULL; + } + else { + current = head; + while(NULL != current->next) { + current = current->next; + } + current->next = listItem; + } + socket->socketInit(); + } +} + +bool RilSapSocket::SocketExists(const char *socketName) { + RilSapSocketList* current = head; + + while(NULL != current) { + if(strcmp(current->socket->name, socketName) == 0) { + return true; + } + current = current->next; + } + return false; +} + +void* RilSapSocket::processRequestsLoop(void) { + SapSocketRequest *req = (SapSocketRequest*)malloc(sizeof(SapSocketRequest)); + RLOGI("UIM_SOCKET:Request loop started"); + + while(true) { + req = dispatchQueue.dequeue(); + + RLOGI("New request from the dispatch Queue"); + + if (req != NULL) { + processRequest(req->curr); + free(req); + } else { + RLOGE("Fetched null buffer from queue!"); + } + } + return NULL; +} + +RilSapSocket::RilSapSocket(const char *socketName, + RIL_SOCKET_ID socketId, + RIL_RadioFunctions *inputUimFuncs): + RilSocket(socketName, socketId) { + if (inputUimFuncs) { + uimFuncs = inputUimFuncs; + } +} + +int RilSapSocket::processRequest(MsgHeader *request) { + dispatchRequest(request); + return 0; +} + +#define BYTES_PER_LINE 16 + +#define NIBBLE_TO_HEX(n) ({ \ + uint8_t __n = (uint8_t) n & 0x0f; \ + __nibble >= 10 ? 'A' + __n - 10: '0' + __n; \ +}) + +#define HEX_HIGH(b) ({ \ + uint8_t __b = (uint8_t) b; \ + uint8_t __nibble = (__b >> 4) & 0x0f; \ + NIBBLE_TO_HEX(__nibble); \ +}) + +#define HEX_LOW(b) ({ \ + uint8_t __b = (uint8_t) b; \ + uint8_t __nibble = __b & 0x0f; \ + NIBBLE_TO_HEX(__nibble); \ +}) + +void log_hex(const char *who, const uint8_t *buffer, int length) { + char out[80]; + int source = 0; + int dest = 0; + int dest_len = sizeof(out); + int per_line = 0; + + do { + dest += sprintf(out, "%8.8s [%8.8x] ", who, source); + for(; source < length && dest_len - dest > 3 && per_line < BYTES_PER_LINE; source++, + per_line ++) { + out[dest++] = HEX_HIGH(buffer[source]); + out[dest++] = HEX_LOW(buffer[source]); + out[dest++] = ' '; + } + if (dest < dest_len && (per_line == BYTES_PER_LINE || source >= length)) { + out[dest++] = 0; + per_line = 0; + dest = 0; + RLOGD("%s\n", out); + } + } while(source < length && dest < dest_len); +} + +void RilSapSocket::dispatchRequest(MsgHeader *req) { + SapSocketRequest* currRequest=(SapSocketRequest*)malloc(sizeof(SapSocketRequest)); + currRequest->token = req->token; + currRequest->curr = req; + currRequest->p_next = NULL; + currRequest->socketId = id; + + pendingResponseQueue.enqueue(currRequest); + + if (uimFuncs) { + RLOGI("[%d] > SAP REQUEST type: %d. id: %d. error: %d", + req->token, + req->type, + req->id, + req->error ); + +#if defined(ANDROID_MULTI_SIM) + uimFuncs->onRequest(req->id, req->payload->bytes, req->payload->size, currRequest, id); +#else + uimFuncs->onRequest(req->id, req->payload->bytes, req->payload->size, currRequest); +#endif + } +} + +void RilSapSocket::onRequestComplete(RIL_Token t, RIL_Errno e, void *response, + size_t response_len) { + SapSocketRequest* request= (SapSocketRequest*)t; + MsgHeader *hdr = request->curr; + pb_bytes_array_t *payload = (pb_bytes_array_t *) + calloc(1,sizeof(pb_bytes_array_t) + response_len); + + if (hdr && payload) { + memcpy(payload->bytes, response, response_len); + payload->size = response_len; + hdr->payload = payload; + hdr->type = MsgType_RESPONSE; + hdr->error = (Error) e; + + RLOGE("Token:%d, MessageId:%d", hdr->token, hdr->id); + + if(!pendingResponseQueue.checkAndDequeue(hdr->id, hdr->token)) { + RLOGE("Token:%d, MessageId:%d", hdr->token, hdr->id); + RLOGE ("RilSapSocket::onRequestComplete: invalid Token or Message Id"); + return; + } + + sendResponse(hdr); + free(hdr); + } +} + +void RilSapSocket::sendResponse(MsgHeader* hdr) { + size_t encoded_size = 0; + uint32_t written_size; + size_t buffer_size = 0; + pb_ostream_t ostream; + bool success = false; + + pthread_mutex_lock(&write_lock); + + if ((success = pb_get_encoded_size(&encoded_size, MsgHeader_fields, + hdr)) && encoded_size <= INT32_MAX && commandFd != -1) { + buffer_size = encoded_size + sizeof(uint32_t); + uint8_t buffer[buffer_size]; + written_size = htonl((uint32_t) encoded_size); + ostream = pb_ostream_from_buffer(buffer, buffer_size); + pb_write(&ostream, (uint8_t *)&written_size, sizeof(written_size)); + success = pb_encode(&ostream, MsgHeader_fields, hdr); + + if (success) { + RLOGD("Size: %d (0x%x) Size as written: 0x%x", encoded_size, encoded_size, + written_size); + log_hex("onRequestComplete", &buffer[sizeof(written_size)], encoded_size); + RLOGI("[%d] < SAP RESPONSE type: %d. id: %d. error: %d", + hdr->token, hdr->type, hdr->id,hdr->error ); + + if ( 0 != blockingWrite_helper(commandFd, buffer, buffer_size)) { + RLOGE("Error %d while writing to fd", errno); + } else { + RLOGD("Write successful"); + } + } else { + RLOGE("Error while encoding response of type %d id %d buffer_size: %d: %s.", + hdr->type, hdr->id, buffer_size, PB_GET_ERROR(&ostream)); + } + } else { + RLOGE("Not sending response type %d: encoded_size: %u. commandFd: %d. encoded size result: %d", + hdr->type, encoded_size, commandFd, success); + } + + pthread_mutex_unlock(&write_lock); +} + +void RilSapSocket::onUnsolicitedResponse(int unsolResponse, void *data, size_t datalen) { + MsgHeader *hdr = new MsgHeader; + pb_bytes_array_t *payload = (pb_bytes_array_t *) + calloc(1, sizeof(pb_bytes_array_t) + datalen); + if (hdr && payload) { + memcpy(payload->bytes, data, datalen); + payload->size = datalen; + hdr->payload = payload; + hdr->type = MsgType_UNSOL_RESPONSE; + hdr->id = (MsgId)unsolResponse; + hdr->error = Error_RIL_E_SUCCESS; + sendResponse(hdr); + delete hdr; + } +} + +void RilSapSocket::pushRecord(void *p_record, size_t recordlen) { + int ret; + SapSocketRequest *recv = (SapSocketRequest*)malloc(sizeof(SapSocketRequest)); + MsgHeader *reqHeader; + pb_istream_t stream; + + stream = pb_istream_from_buffer((uint8_t *)p_record, recordlen); + reqHeader = (MsgHeader *)malloc(sizeof (MsgHeader)); + memset(reqHeader, 0, sizeof(MsgHeader)); + + log_hex("BtSapTest-Payload", (const uint8_t*)p_record, recordlen); + + if (!pb_decode(&stream, MsgHeader_fields, reqHeader) ) { + RLOGE("Error decoding protobuf buffer : %s", PB_GET_ERROR(&stream)); + } else { + recv->token = reqHeader->token; + recv->curr = reqHeader; + recv->socketId = id; + + dispatchQueue.enqueue(recv); + } +} + +void RilSapSocket::sendDisconnect() { + MsgHeader *hdr = new MsgHeader; + pb_bytes_array_t *payload ; + size_t encoded_size = 0; + uint32_t written_size; + size_t buffer_size = 0; + pb_ostream_t ostream; + bool success = false; + ssize_t written_bytes; + + RIL_SIM_SAP_DISCONNECT_REQ disconnectReq; + + if ((success = pb_get_encoded_size(&encoded_size, RIL_SIM_SAP_DISCONNECT_REQ_fields, + &disconnectReq)) && encoded_size <= INT32_MAX) { + buffer_size = encoded_size + sizeof(uint32_t); + uint8_t buffer[buffer_size]; + written_size = htonl((uint32_t) encoded_size); + ostream = pb_ostream_from_buffer(buffer, buffer_size); + pb_write(&ostream, (uint8_t *)&written_size, sizeof(written_size)); + success = pb_encode(&ostream, RIL_SIM_SAP_DISCONNECT_REQ_fields, buffer); + + if(success) { + pb_bytes_array_t *payload = (pb_bytes_array_t *) + calloc(1,sizeof(pb_bytes_array_t) + written_size); + + memcpy(payload->bytes, buffer, written_size); + payload->size = written_size; + hdr->payload = payload; + hdr->type = MsgType_REQUEST; + hdr->id = MsgId_RIL_SIM_SAP_DISCONNECT; + hdr->error = Error_RIL_E_SUCCESS; + dispatchDisconnect(hdr); + } + else { + RLOGE("Encode failed in send disconnect!"); + delete hdr; + free(payload); + } + } +} + +void RilSapSocket::dispatchDisconnect(MsgHeader *req) { + SapSocketRequest* currRequest=(SapSocketRequest*)malloc(sizeof(SapSocketRequest)); + currRequest->token = -1; + currRequest->curr = req; + currRequest->p_next = NULL; + currRequest->socketId = (RIL_SOCKET_ID)99; + + RLOGD("Sending disconnect on command close!"); + +#if defined(ANDROID_MULTI_SIM) + uimFuncs->onRequest(req->id, req->payload->bytes, req->payload->size, currRequest, id); +#else + uimFuncs->onRequest(req->id, req->payload->bytes, req->payload->size, currRequest); +#endif +} + +void RilSapSocket::onCommandsSocketClosed() { + sendDisconnect(); + RLOGE("Socket command closed"); +} diff --git a/libril/RilSapSocket.h b/libril/RilSapSocket.h new file mode 100644 index 0000000..4261f93 --- /dev/null +++ b/libril/RilSapSocket.h @@ -0,0 +1,262 @@ +/* +* Copyright (C) 2014 The Android Open Source Project +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef RIL_UIM_SOCKET_H_INCLUDED +#define RIL_UIM_SOCKET_H_INCLUDED +#define RIL_SHLIB +#include "telephony/ril.h" +#include "RilSocket.h" +#include <hardware/ril/librilutils/proto/sap-api.pb.h> + +/** + * RilSapSocket is a derived class, derived from the RilSocket abstract + * class, representing sockets for communication between bluetooth SAP module and + * the ril daemon. + * <p> + * This class performs the following functions : + * <ul> + * <li>Initialize the socket. + * <li>Process the requests coming on the socket. + * <li>Provide handlers for Unsolicited and request responses. + * <li>Request and pending response queue handling. + * </ul> + */ +class RilSapSocket : public RilSocket { + /** + * Function pointer to the ril initialization funtion. + * + * @param Ril environment variable with place request and + * response handlers and timeout handler. + * + * @param Number of arguements for the initialization function. + * + * @param Arguements to the initialization function used to + * generate instance id of the ril daemon. + * + * @return Radio functions with handlers for onRequest, onStateRequest, + * supports, onCancel and getVersion. + */ + RIL_RadioFunctions *(*UimInit)(const struct RIL_Env *, int argc, char **argv); + + /** + * Place holder for the radio functions returned by the initialization + * function. Currenty only onRequest handler is being used. + */ + RIL_RadioFunctions* uimFuncs; + + /** + * Wrapper struct for handling the requests in the queue. + */ + typedef struct SapSocketRequest { + int token; + MsgHeader* curr; + struct SapSocketRequest* p_next; + RIL_SOCKET_ID socketId; + } SapSocketRequest; + + /** + * Queue for requests that are pending dispatch. + */ + Ril_queue<SapSocketRequest> dispatchQueue; + + /** + * Queue for requests that are dispatched but are pending response + */ + Ril_queue<SapSocketRequest> pendingResponseQueue; + + public: + /** + * Initialize the socket and add the socket to the list. + * + * @param Name of the socket. + * @param Radio functions to be used by the socket. + */ + static void initSapSocket(const char *socketName, + RIL_RadioFunctions *uimFuncs); + + /** + * Process requests from the dispatch request queue. + * @param Request to be dispatched. + */ + int processRequest(MsgHeader *request); + + /** + * Ril envoronment variable that holds the request and + * unsol response handlers. + */ + static struct RIL_Env uimRilEnv; + + /** + * Function to print the socket list. + */ + static void printList(); + + /** + * Clean up method to be called on command close. + */ + void onCommandsSocketClosed(void); + + /** + * Datatype to handle the socket list. + */ + typedef struct RilSapSocketList { + RilSapSocket* socket; + RilSapSocketList *next; + } RilSapSocketList; + + protected: + /** + * Process each record read from the socket and + * push a new request created from that record to + * the dispatch request queue. + * + * @param The record data. + * @param The record length. + */ + void pushRecord(void *record, size_t recordlen); + + /** + * Socket handler to be called when a request has + * been completed. + * + * @param Token associated with the request. + * @param Error, if any, while processing the request. + * @param The response payload. + * @param Response payload length. + */ + void onRequestComplete(RIL_Token t,RIL_Errno e, + void *response, size_t response_len); + + /** + * Socket handler to be called when there is an + * unsolicited response. + * + * @param Message id. + * @param Response data. + * @param Response data length. + */ + void onUnsolicitedResponse(int unsolResponse, + void *data, size_t datalen); + + /** + * Class method to get the socket from the socket list. + * + * @param Socket id. + * @return the sap socket. + */ + static RilSapSocket* getSocketById(RIL_SOCKET_ID socketId); + + /** + * Method to send response to SAP. It does an atomic write operation on the + * socket. + * + * @param the response header with the payload. + */ + void sendResponse(MsgHeader *hdr); + + /** + * A loop for processing the requests in the request dispatch queue. + */ + void *processRequestsLoop(void); + + /** + * Class method to add the sap socket to the list of sockets. + * Does nothing if the socket is already present in the list. + * Otherwise, calls the constructor of the parent class(To startlistening) + * and add socket to the socket list. + */ + static void addSocketToList(const char *socketName, RIL_SOCKET_ID socketid, + RIL_RadioFunctions *uimFuncs); + + /** + * Check if a socket of the given name exists in the socket list. + * + * @param Socket name. + * @return true if exists, false otherwise. + */ + static bool SocketExists(const char *socketName); + + /** + * Send a clean up SAP DISCONNECT if the socket disconnects before doing a SAP + * disconnect. + */ + void sendDisconnect(void); + + /** + * Dispatch the clean up disconnect request. + */ + void dispatchDisconnect(MsgHeader *req); + + + private: + /** + * Constructor. + * + * @param Socket name. + * @param Socket id. + * @param Radio functions. + */ + RilSapSocket(const char *socketName, + RIL_SOCKET_ID socketId, + RIL_RadioFunctions *inputUimFuncs); + + /** + * Called by the processRequest method to dispatch the request to + * the lower layers. It calls the on request function. + * + * @param The request message. + */ + void dispatchRequest(MsgHeader *request); + + /** + * Class method that selects the socket on which the onRequestComplete + * is called. + * + * @param Token associated with the request. + * @param Error, if any, while processing the request. + * @param The response payload. + * @param Response payload length. + */ + static void sOnRequestComplete(RIL_Token t, + RIL_Errno e, void *response, size_t responselen); + +#if defined(ANDROID_MULTI_SIM) + /** + * Class method that selects the socket on which the onUnsolicitedResponse + * is called. + * + * @param Message id. + * @param Response data. + * @param Response data length. + * @param Socket id. + */ + static void sOnUnsolicitedResponse(int unsolResponse, const void *data, + size_t datalen, RIL_SOCKET_ID socket_id); +#else + /** + * Class method that selects the socket on which the onUnsolicitedResponse + * is called. + * + * @param Message id. + * @param Response data. + * @param Response data length. + */ + static void sOnUnsolicitedResponse(int unsolResponse, const void *data, + size_t datalen); +#endif +}; + +#endif /*RIL_UIM_SOCKET_H_INCLUDED*/ diff --git a/libril/RilSocket.cpp b/libril/RilSocket.cpp new file mode 100644 index 0000000..a002d94 --- /dev/null +++ b/libril/RilSocket.cpp @@ -0,0 +1,177 @@ +/* +* Copyright (C) 2014 The Android Open Source Project +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +extern "C" +void *ril_socket_process_requests_loop(void *arg); + +#include "RilSocket.h" +#include <cutils/sockets.h> +#include <utils/Log.h> +#include <assert.h> +#define SOCKET_LISTEN_BACKLOG 0 + +int RilSocket::socketInit(void) { + int ret; + + listenCb = &RilSocket::sSocketListener; + commandCb = &RilSocket::sSocketRequestsHandler; + listenFd = android_get_control_socket(name); + + //Start listening + ret = listen(listenFd, SOCKET_LISTEN_BACKLOG); + + if (ret < 0) { + RLOGE("Failed to listen on %s socket '%d': %s", + name, listenFd, strerror(errno)); + return ret; + } + //Add listen event to the event loop + ril_event_set(&listenEvent, listenFd, false, listenCb, this); + rilEventAddWakeup_helper(&listenEvent); + return ret; +} + +void RilSocket::sSocketListener(int fd, short flags, void *param) { + RilSocket *theSocket = (RilSocket *) param; + MySocketListenParam listenParam; + listenParam.socket = theSocket; + listenParam.sListenParam.type = RIL_SAP_SOCKET; + + listenCallback_helper(fd, flags, (void*)&listenParam); +} + +void RilSocket::onNewCommandConnect() { + pthread_attr_t attr; + PthreadPtr pptr = ril_socket_process_requests_loop; + int result; + + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + + //Start socket request processing loop thread + result = pthread_create(&socketThreadId, &attr, pptr, this); + if(result < 0) { + RLOGE("pthread_create failed with result:%d",result); + } + + RLOGE("New socket command connected and socket request thread started"); +} + +void RilSocket::sSocketRequestsHandler(int fd, short flags, void *param) { + socketClient *sc = (socketClient *) param; + RilSocket *theSocket = sc->socketPtr; + RecordStream *rs = sc->rs; + + theSocket->socketRequestsHandler(fd, flags, rs); +} + +void RilSocket::socketRequestsHandler(int fd, short flags, RecordStream *p_rs) { + int ret; + assert(fd == commandFd); + void *p_record; + size_t recordlen; + + for (;;) { + /* loop until EAGAIN/EINTR, end of stream, or other error */ + ret = record_stream_get_next(p_rs, &p_record, &recordlen); + + if (ret == 0 && p_record == NULL) { + /* end-of-stream */ + break; + } else if (ret < 0) { + break; + } else if (ret == 0) { + pushRecord(p_record, recordlen); + } + } + + if (ret == 0 || !(errno == EAGAIN || errno == EINTR)) { + /* fatal error or end-of-stream */ + if (ret != 0) { + RLOGE("error on reading command socket errno:%d\n", errno); + } else { + RLOGW("EOS. Closing command socket."); + } + + close(commandFd); + commandFd = -1; + + ril_event_del(&callbackEvent); + + record_stream_free(p_rs); + + /* start listening for new connections again */ + + rilEventAddWakeup_helper(&listenEvent); + + onCommandsSocketClosed(); + } +} + +void RilSocket::setListenFd(int fd) { + listenFd = fd; +} + +void RilSocket::setCommandFd(int fd) { + commandFd = fd; +} + +int RilSocket::getListenFd(void) { + return listenFd; +} + +int RilSocket::getCommandFd(void) { + return commandFd; +} + +void RilSocket::setListenCb(ril_event_cb cb) { + listenCb = cb; +} + +void RilSocket::setCommandCb(ril_event_cb cb) { + commandCb = cb; +} + +ril_event_cb RilSocket::getListenCb(void) { + return listenCb; +} + +ril_event_cb RilSocket::getCommandCb(void) { + return commandCb; +} + +void RilSocket::setListenEvent(ril_event event) { + listenEvent = event; +} + +void RilSocket::setCallbackEvent(ril_event event) { + callbackEvent = event; +} + +ril_event* RilSocket::getListenEvent(void) { + return &listenEvent; +} + +ril_event* RilSocket::getCallbackEvent(void) { + return &callbackEvent; +} + +extern "C" +void *ril_socket_process_requests_loop(void *arg) { + RilSocket *socket = (RilSocket *)arg; + socket->processRequestsLoop(); + return NULL; +} diff --git a/libril/RilSocket.h b/libril/RilSocket.h new file mode 100644 index 0000000..053df3e --- /dev/null +++ b/libril/RilSocket.h @@ -0,0 +1,270 @@ +/* +* Copyright (C) 2014 The Android Open Source Project +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef RIL_SOCKET_H_INCLUDED +#define RIL_SOCKET_H_INCLUDED +#include "ril_ex.h" +#include "rilSocketQueue.h" +#include <ril_event.h> + +using namespace std; + +/** + * Abstract socket class representing sockets in rild. + * <p> + * This class performs the following functions : + * <ul> + * <li> Start socket listen. + * <li> Handle socket listen and command callbacks. + * </ul> + */ +class RilSocket { + protected: + + /** + * Socket name. + */ + const char* name; + + /** + * Socket id. + */ + RIL_SOCKET_ID id; + + /** + * Listen socket file descriptor. + */ + int listenFd = -1; + + /** + * Commands socket file descriptor. + */ + int commandFd = -1; + + /** + * Socket request loop thread id. + */ + pthread_t socketThreadId; + + /** + * Listen event callack. Callback called when the other ends does accept. + */ + ril_event_cb listenCb; + + /** + * Commands event callack.Callback called when there are requests from the other side. + */ + ril_event_cb commandCb; + + /** + * Listen event to be added to eventloop after socket listen. + */ + struct ril_event listenEvent; + + /** + * Commands event to be added to eventloop after accept. + */ + struct ril_event callbackEvent; + + /** + * Static socket listen handler. Chooses the socket to call the listen callback + * from ril.cpp. + * + * @param Listen fd. + * @param flags. + * @param Parameter for the listen handler. + */ + static void sSocketListener(int fd, short flags, void *param); + + /** + * Static socket request handler. Chooses the socket to call the request handler on. + * + * @param Commands fd. + * @param flags. + * @param Parameter for the request handler. + */ + static void sSocketRequestsHandler(int fd, short flags, void *param); + + /** + * Process record from the record stream and push the requests onto the queue. + * + * @param record data. + * @param record length. + */ + virtual void pushRecord(void *record, size_t recordlen) = 0; + + /** + * Socket lock for writing data on the socket. + */ + pthread_mutex_t write_lock = PTHREAD_MUTEX_INITIALIZER; + + /** + * The loop to process the incoming requests. + */ + virtual void *processRequestsLoop(void) = 0; + + private: + friend void *::ril_socket_process_requests_loop(void *arg); + + public: + + /** + * Constructor. + * + * @param Socket name. + * @param Socket id. + */ + RilSocket(const char* socketName, RIL_SOCKET_ID socketId) { + name = socketName; + id = socketId; + } + + /** + * Clean up function on commands socket close. + */ + virtual void onCommandsSocketClosed(void) = 0; + + /** + * Function called on new commands socket connect. Request loop thread is started here. + */ + void onNewCommandConnect(void); + + /** + * Set listen socket fd. + * + * @param Input fd. + */ + void setListenFd(int listenFd); + + /** + * Set commands socket fd. + * + * @param Input fd. + */ + void setCommandFd(int commandFd); + + /** + * Get listen socket fd. + * + * @return Listen fd. + */ + int getListenFd(void); + + /** + * Get commands socket fd. + * + * @return Commands fd. + */ + int getCommandFd(void); + + /** + * Set listen event callback. + * + * @param Input event callback. + */ + void setListenCb(ril_event_cb listenCb); + + /** + * Set command event callback. + * + * @param Input event callback. + */ + void setCommandCb(ril_event_cb commandCb); + + /** + * Get listen event callback. + * + * @return Listen event callback. + */ + ril_event_cb getListenCb(void); + + /** + * Gey command event callback. + * + * @return Command event callback. + */ + ril_event_cb getCommandCb(void); + + /** + * Set listen event. + * + * @param Input event. + */ + void setListenEvent(ril_event listenEvent); + + /** + * Set command callback event. + * + * @param Input event. + */ + void setCallbackEvent(ril_event commandEvent); + + /** + * Get listen event. + * + * @return Listen event. + */ + ril_event* getListenEvent(void); + + /** + * Get commands callback event. + * + * @return Commands callback event. + */ + ril_event* getCallbackEvent(void); + + virtual ~RilSocket(){} + + protected: + + /** + * Start listening on the socket and add the socket listen callback event. + * + * @return Result of the socket listen. + */ + int socketInit(void); + + /** + * Socket request handler + * + * @param Commands fd. + * @param flags. + * @param Record stream. + */ + void socketRequestsHandler(int fd, short flags, RecordStream *rs); +}; + +class socketClient { + public: + RilSocket *socketPtr; + RecordStream *rs; + + socketClient(RilSocket *socketPtr, RecordStream *rs) { + this->socketPtr = socketPtr; + this->rs = rs; + } +}; + +typedef struct MySocketListenParam { + SocketListenParam sListenParam; + RilSocket *socket; +} MySocketListenParam; + +typedef void* (RilSocket::*RilSocketFuncPtr)(void); +typedef void (RilSocket::*RilSocketEventPtr)(int fd,short flags, void *param); +typedef void* (*PthreadPtr)(void*); + +#endif diff --git a/libril/ril.cpp b/libril/ril.cpp index 382a526..4aea484 100644 --- a/libril/ril.cpp +++ b/libril/ril.cpp @@ -18,7 +18,6 @@ #define LOG_TAG "RILC" #include <hardware_legacy/power.h> - #include <telephony/ril.h> #include <telephony/ril_cdma_sms.h> #include <cutils/sockets.h> @@ -29,11 +28,9 @@ #include <pthread.h> #include <binder/Parcel.h> #include <cutils/jstring.h> - #include <sys/types.h> #include <sys/limits.h> #include <pwd.h> - #include <stdio.h> #include <stdlib.h> #include <stdarg.h> @@ -49,12 +46,14 @@ #include <assert.h> #include <netinet/in.h> #include <cutils/properties.h> +#include <RilSapSocket.h> -#include <ril_event.h> - +extern "C" void +RIL_onRequestComplete(RIL_Token t, RIL_Errno e, void *response, size_t responselen); namespace android { #define PHONE_PROCESS "radio" +#define BLUETOOTH_PROCESS "bluetooth" #define SOCKET_NAME_RIL "rild" #define SOCKET2_NAME_RIL "rild2" @@ -148,17 +147,6 @@ typedef struct UserCallbackInfo { struct UserCallbackInfo *p_next; } UserCallbackInfo; -typedef struct SocketListenParam { - RIL_SOCKET_ID socket_id; - int fdListen; - int fdCommand; - char* processName; - struct ril_event* commands_event; - struct ril_event* listen_event; - void (*processCommandsCallback)(int fd, short flags, void *param); - RecordStream *p_rs; -} SocketListenParam; - extern "C" const char * requestToString(int request); extern "C" const char * failCauseToString(RIL_Errno); extern "C" const char * callStateToString(RIL_CallState); @@ -371,7 +359,7 @@ static char * RIL_getRilSocketName() { } extern "C" -void RIL_setRilSocketName(char * s) { +void RIL_setRilSocketName(const char * s) { strncpy(rild, s, MAX_SOCKET_NAME_LENGTH); } @@ -2064,7 +2052,7 @@ blockingWrite(int fd, const void *buffer, size_t len) { return -1; } } - + RLOGE("RIL Response bytes written:%d", writeOffset); return 0; } @@ -3729,9 +3717,19 @@ static void listenCallback (int fd, short flags, void *param) { int err; int is_phone_socket; int fdCommand = -1; + char* processName; RecordStream *p_rs; + MySocketListenParam* listenParam; + RilSocket *sapSocket = NULL; + socketClient *sClient = NULL; + SocketListenParam *p_info = (SocketListenParam *)param; + if(RIL_SAP_SOCKET == p_info->type) { + listenParam = (MySocketListenParam *)param; + sapSocket = listenParam->socket; + } + struct sockaddr_un peeraddr; socklen_t socklen = sizeof (peeraddr); @@ -3740,15 +3738,27 @@ static void listenCallback (int fd, short flags, void *param) { struct passwd *pwd = NULL; - assert (*p_info->fdCommand < 0); - assert (fd == *p_info->fdListen); + if(NULL == sapSocket) { + assert (*p_info->fdCommand < 0); + assert (fd == *p_info->fdListen); + processName = PHONE_PROCESS; + } else { + assert (sapSocket->commandFd < 0); + assert (fd == sapSocket->listenFd); + processName = BLUETOOTH_PROCESS; + } + fdCommand = accept(fd, (sockaddr *) &peeraddr, &socklen); if (fdCommand < 0 ) { RLOGE("Error on accept() errno:%d", errno); /* start listening for new connections again */ - rilEventAddWakeup(p_info->listen_event); + if(NULL == sapSocket) { + rilEventAddWakeup(p_info->listen_event); + } else { + rilEventAddWakeup(sapSocket->getListenEvent()); + } return; } @@ -3764,7 +3774,7 @@ static void listenCallback (int fd, short flags, void *param) { errno = 0; pwd = getpwuid(creds.uid); if (pwd != NULL) { - if (strcmp(pwd->pw_name, p_info->processName) == 0) { + if (strcmp(pwd->pw_name, processName) == 0) { is_phone_socket = 1; } else { RLOGE("RILD can't accept socket from process %s", pwd->pw_name); @@ -3777,17 +3787,24 @@ static void listenCallback (int fd, short flags, void *param) { } if (!is_phone_socket) { - RLOGE("RILD must accept socket from %s", p_info->processName); + RLOGE("RILD must accept socket from %s", processName); - close(fdCommand); - fdCommand = -1; + close(fdCommand); + fdCommand = -1; - onCommandsSocketClosed(p_info->socket_id); + if(NULL == sapSocket) { + onCommandsSocketClosed(p_info->socket_id); - /* start listening for new connections again */ - rilEventAddWakeup(p_info->listen_event); + /* start listening for new connections again */ + rilEventAddWakeup(p_info->listen_event); + } else { + sapSocket->onCommandsSocketClosed(); - return; + /* start listening for new connections again */ + rilEventAddWakeup(sapSocket->getListenEvent()); + } + + return; } ret = fcntl(fdCommand, F_SETFL, O_NONBLOCK); @@ -3796,20 +3813,30 @@ static void listenCallback (int fd, short flags, void *param) { RLOGE ("Error setting O_NONBLOCK errno:%d", errno); } - RLOGI("libril: new connection to %s", rilSocketIdToString(p_info->socket_id)); + if(NULL == sapSocket) { + RLOGI("libril: new connection to %s", rilSocketIdToString(p_info->socket_id)); - p_info->fdCommand = fdCommand; + p_info->fdCommand = fdCommand; + p_rs = record_stream_new(p_info->fdCommand, MAX_COMMAND_BYTES); + p_info->p_rs = p_rs; - p_rs = record_stream_new(p_info->fdCommand, MAX_COMMAND_BYTES); - - p_info->p_rs = p_rs; - - ril_event_set (p_info->commands_event, p_info->fdCommand, 1, + ril_event_set (p_info->commands_event, p_info->fdCommand, 1, p_info->processCommandsCallback, p_info); + rilEventAddWakeup (p_info->commands_event); - rilEventAddWakeup (p_info->commands_event); + onNewCommandConnect(p_info->socket_id); + } else { + RLOGI("libril: new connection"); - onNewCommandConnect(p_info->socket_id); + sapSocket->setCommandFd(fdCommand); + p_rs = record_stream_new(sapSocket->getCommandFd(), MAX_COMMAND_BYTES); + sClient = new socketClient(sapSocket,p_rs); + ril_event_set (sapSocket->getCallbackEvent(), sapSocket->getCommandFd(), 1, + sapSocket->getCommandCb(), sClient); + + rilEventAddWakeup(sapSocket->getCallbackEvent()); + sapSocket->onNewCommandConnect(); + } } static void freeDebugCallbackArgs(int number, char **args) { @@ -4286,6 +4313,33 @@ RIL_register (const RIL_RadioFunctions *callbacks) { } +extern "C" void +RIL_register_socket (RIL_RadioFunctions *(*Init)(const struct RIL_Env *, int, char **),RIL_SOCKET_TYPE socketType, int argc, char **argv) { + + RIL_RadioFunctions* UimFuncs = NULL; + + if(Init) { + UimFuncs = Init(&RilSapSocket::uimRilEnv, argc, argv); + + switch(socketType) { + case RIL_SAP_SOCKET: + RilSapSocket::initSapSocket("sap_uim_socket1", UimFuncs); + +#if (SIM_COUNT >= 2) + RilSapSocket::initSapSocket("sap_uim_socket2", UimFuncs); +#endif + +#if (SIM_COUNT >= 3) + RilSapSocket::initSapSocket("sap_uim_socket3", UimFuncs); +#endif + +#if (SIM_COUNT >= 4) + RilSapSocket::initSapSocket("sap_uim_socket4", UimFuncs); +#endif + } + } +} + static int checkAndDequeueRequestInfo(struct RequestInfo *pRI) { int ret = 0; @@ -4992,3 +5046,15 @@ rilSocketIdToString(RIL_SOCKET_ID socket_id) } } /* namespace android */ + +void rilEventAddWakeup_helper(struct ril_event *ev) { + android::rilEventAddWakeup(ev); +} + +void listenCallback_helper(int fd, short flags, void *param) { + android::listenCallback(fd, flags, param); +} + +int blockingWrite_helper(int fd, void *buffer, size_t len) { + return android::blockingWrite(fd, buffer, len); +} diff --git a/libril/rilSocketQueue.h b/libril/rilSocketQueue.h new file mode 100644 index 0000000..eaa5155 --- /dev/null +++ b/libril/rilSocketQueue.h @@ -0,0 +1,167 @@ +/* +* Copyright (C) 2014 The Android Open Source Project +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "pb_decode.h" +#include <pthread.h> +#include <hardware/ril/librilutils/proto/sap-api.pb.h> +#include <utils/Log.h> + +using namespace std; + +/** + * Template queue class to handling requests for a rild socket. + * <p> + * This class performs the following functions : + * <ul> + * <li>Enqueue. + * <li>Dequeue. + * <li>Check and dequeue. + * </ul> + */ + +template <typename T> +class Ril_queue { + + /** + * Mutex attribute used in queue mutex initialization. + */ + pthread_mutexattr_t attr; + + /** + * Queue mutex variable for synchronized queue access. + */ + pthread_mutex_t mutex_instance; + + /** + * Condition to be waited on for dequeuing. + */ + pthread_cond_t cond; + + /** + * Front of the queue. + */ + T *front; + + public: + + /** + * Remove the first element of the queue. + * + * @return first element of the queue. + */ + T* dequeue(void); + + /** + * Add a request to the front of the queue. + * + * @param Request to be added. + */ + void enqueue(T* request); + + /** + * Check if the queue is empty. + */ + int empty(void); + + /** + * Check and remove an element with a particular message id and token. + * + * @param Request message id. + * @param Request token. + */ + int checkAndDequeue( MsgId id, int token); + + /** + * Queue constructor. + */ + Ril_queue(void); +}; + +template <typename T> +Ril_queue<T>::Ril_queue(void) { + pthread_mutexattr_init(&attr); + pthread_mutex_init(&mutex_instance, &attr); + cond = PTHREAD_COND_INITIALIZER; + front = NULL; +} + +template <typename T> +T* Ril_queue<T>::dequeue(void) { + T* temp = NULL; + + pthread_mutex_lock(&mutex_instance); + while(empty()) { + pthread_cond_wait(&cond, &mutex_instance); + } + temp = this->front; + if(NULL != this->front->p_next) { + this->front = this->front->p_next; + } else { + this->front = NULL; + } + pthread_mutex_unlock(&mutex_instance); + + return temp; +} + +template <typename T> +void Ril_queue<T>::enqueue(T* request) { + + pthread_mutex_lock(&mutex_instance); + + if(NULL == this->front) { + this->front = request; + request->p_next = NULL; + } else { + request->p_next = this->front; + this->front = request; + } + pthread_cond_broadcast(&cond); + pthread_mutex_unlock(&mutex_instance); +} + +template <typename T> +int Ril_queue<T>::checkAndDequeue(MsgId id, int token) { + int ret = 0; + T* temp; + + pthread_mutex_lock(&mutex_instance); + + for(T **ppCur = &(this->front); *ppCur != NULL; ppCur = &((*ppCur)->p_next)) { + if (token == (*ppCur)->token && id == (*ppCur)->curr->id) { + ret = 1; + temp = *ppCur; + *ppCur = (*ppCur)->p_next; + free(temp); + break; + } + } + + pthread_mutex_unlock(&mutex_instance); + + return ret; +} + + +template <typename T> +int Ril_queue<T>::empty(void) { + + if(this->front == NULL) { + return 1; + } else { + return 0; + } +} diff --git a/libril/ril_ex.h b/libril/ril_ex.h new file mode 100644 index 0000000..8e15d65 --- /dev/null +++ b/libril/ril_ex.h @@ -0,0 +1,48 @@ +/* +* Copyright (C) 2014 The Android Open Source Project +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef RIL_EX_H_INCLUDED +#define RIL_EX_H_INCLUDED + +#include <telephony/ril.h> +#include <telephony/record_stream.h> + +#define NUM_ELEMS_SOCKET(a) (sizeof (a) / sizeof (a)[0]) + +void rilEventAddWakeup_helper(struct ril_event *ev); +void listenCallback_helper(int fd, short flags, void *param); +int blockingWrite_helper(int fd, void* data, size_t len); + +enum SocketWakeType {DONT_WAKE, WAKE_PARTIAL}; + +typedef enum { + RIL_TELEPHONY_SOCKET, + RIL_SAP_SOCKET +} RIL_SOCKET_TYPE; + +typedef struct SocketListenParam { + RIL_SOCKET_ID socket_id; + int fdListen; + int fdCommand; + char* processName; + struct ril_event* commands_event; + struct ril_event* listen_event; + void (*processCommandsCallback)(int fd, short flags, void *param); + RecordStream *p_rs; + RIL_SOCKET_TYPE type; +} SocketListenParam; + +#endif diff --git a/librilutils/Android.mk b/librilutils/Android.mk index 033a4dc..1ac00e0 100644 --- a/librilutils/Android.mk +++ b/librilutils/Android.mk @@ -5,7 +5,12 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES:= \ librilutils.c \ - record_stream.c + record_stream.c \ + proto/sap-api.proto \ + +LOCAL_C_INCLUDES += external/nanopb-c/ \ + +LOCAL_PROTOC_OPTIMIZE_TYPE := nanopb-c-enable_malloc LOCAL_CFLAGS := @@ -20,12 +25,26 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES:= \ librilutils.c \ - record_stream.c + record_stream.c \ + proto/sap-api.proto \ -LOCAL_STATIC_LIBRARIES := +LOCAL_C_INCLUDES += external/nanopb-c/ \ + +LOCAL_PROTOC_OPTIMIZE_TYPE := nanopb-c-enable_malloc LOCAL_CFLAGS := LOCAL_MODULE:= librilutils_static include $(BUILD_STATIC_LIBRARY) + +# Create java protobuf code + +include $(CLEAR_VARS) + +src_proto := $(LOCAL_PATH) +LOCAL_MODULE := sap-api-java-static +LOCAL_SRC_FILES := proto/sap-api.proto +LOCAL_PROTOC_OPTIMIZE_TYPE := micro + +include $(BUILD_STATIC_JAVA_LIBRARY) diff --git a/librilutils/proto/sap-api.options b/librilutils/proto/sap-api.options new file mode 100644 index 0000000..f76ba93 --- /dev/null +++ b/librilutils/proto/sap-api.options @@ -0,0 +1,23 @@ +# +# Copyright (C) 2014 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +MsgHeader.payload type:FT_POINTER +RIL_SIM_SAP_APDU_REQ.command type:FT_POINTER +RIL_SIM_SAP_APDU_RSP.apduResponse type:FT_POINTER +RIL_SIM_SAP_TRANSFER_ATR_RSP.atr type:FT_POINTER + +#RIL_SIM_SAP_REQUEST.apdu type:FT_POINTER +#RIL_SIM_SAP_RESPONSE.apdu type:FT_POINTER diff --git a/rild/Android.mk b/rild/Android.mk index 151cda6..8aae88d 100644 --- a/rild/Android.mk +++ b/rild/Android.mk @@ -27,6 +27,8 @@ endif LOCAL_MODULE:= rild LOCAL_MODULE_TAGS := optional +LOCAL_C_INCLUDES += $(TARGET_OUT_HEADERS)/libril + include $(BUILD_EXECUTABLE) # For radiooptions binary diff --git a/rild/rild.c b/rild/rild.c index 0747717..6324253 100644 --- a/rild/rild.c +++ b/rild/rild.c @@ -33,6 +33,7 @@ #include <sys/prctl.h> #include <sys/stat.h> #include <sys/types.h> +#include <libril/ril_ex.h> #include <private/android_filesystem_config.h> #include "hardware/qemu_pipe.h" @@ -41,8 +42,7 @@ #define LIB_ARGS_PROPERTY "rild.libargs" #define MAX_LIB_ARGS 16 -static void usage(const char *argv0) -{ +static void usage(const char *argv0) { fprintf(stderr, "Usage: %s -l <ril impl library> [-- <args for impl library>]\n", argv0); exit(EXIT_FAILURE); } @@ -51,21 +51,24 @@ extern char rild[MAX_SOCKET_NAME_LENGTH]; extern void RIL_register (const RIL_RadioFunctions *callbacks); +extern void RIL_register_socket (RIL_RadioFunctions *(*rilUimInit) + (const struct RIL_Env *, int, char **), RIL_SOCKET_TYPE socketType, int argc, char **argv); + extern void RIL_onRequestComplete(RIL_Token t, RIL_Errno e, - void *response, size_t responselen); + void *response, size_t responselen); extern void RIL_setRilSocketName(char *); #if defined(ANDROID_MULTI_SIM) extern void RIL_onUnsolicitedResponse(int unsolResponse, const void *data, - size_t datalen, RIL_SOCKET_ID socket_id); + size_t datalen, RIL_SOCKET_ID socket_id); #else extern void RIL_onUnsolicitedResponse(int unsolResponse, const void *data, - size_t datalen); + size_t datalen); #endif extern void RIL_requestTimedCallback (RIL_TimedCallback callback, - void *param, const struct timeval *relativeTime); + void *param, const struct timeval *relativeTime); static struct RIL_Env s_rilEnv = { @@ -76,8 +79,7 @@ static struct RIL_Env s_rilEnv = { extern void RIL_startEventLoop(); -static int make_argv(char * args, char ** argv) -{ +static int make_argv(char * args, char ** argv) { // Note: reserve argv[0] int count = 1; char * tok; @@ -130,12 +132,14 @@ void switchUser() { } } -int main(int argc, char **argv) -{ +int main(int argc, char **argv) { const char * rilLibPath = NULL; char **rilArgv; void *dlHandle; const RIL_RadioFunctions *(*rilInit)(const struct RIL_Env *, int, char **); + const RIL_RadioFunctions *(*rilUimInit)(const struct RIL_Env *, int, char **); + char *err_str = NULL; + const RIL_RadioFunctions *funcs; char libPath[PROPERTY_VALUE_MAX]; unsigned char hasLibArgs = 0; @@ -300,13 +304,26 @@ OpenLib: RIL_startEventLoop(); - rilInit = (const RIL_RadioFunctions *(*)(const struct RIL_Env *, int, char **))dlsym(dlHandle, "RIL_Init"); + rilInit = + (const RIL_RadioFunctions *(*)(const struct RIL_Env *, int, char **)) + dlsym(dlHandle, "RIL_Init"); if (rilInit == NULL) { RLOGE("RIL_Init not defined or exported in %s\n", rilLibPath); exit(EXIT_FAILURE); } + dlerror(); // Clear any previous dlerror + rilUimInit = + (const RIL_RadioFunctions *(*)(const struct RIL_Env *, int, char **)) + dlsym(dlHandle, "RIL_SAP_Init"); + err_str = dlerror(); + if (err_str) { + RLOGW("RIL_SAP_Init not defined or exported in %s: %s\n", rilLibPath, err_str); + } else if (!rilUimInit) { + RLOGW("RIL_SAP_Init defined as null in %s. SAP Not usable\n", rilLibPath); + } + if (hasLibArgs) { rilArgv = argv + i - 1; argc = argc -i + 1; @@ -332,6 +349,13 @@ OpenLib: RLOGD("RIL_Init RIL_register completed"); + if (rilUimInit) { + RLOGD("RIL_register_socket started"); + RIL_register_socket(rilUimInit, RIL_SAP_SOCKET, argc, rilArgv); + } + + RLOGD("RIL_register_socket completed"); + done: RLOGD("RIL_Init starting sleep loop"); |