Added new socket connection for communication between the SAP module in Telephony and User Identity Module with DSDA support. New classes added are: RilSocket --------- Base class(virtual) for any type of socket. Has listen and commands callbacks similar to that of the existing telephony->rild socket. RilSapSocket ------------ Derived class for socket for communication between BT SAP and the sim module in the modem. It initialises socket, calls Sap_Uim_Init to get the handles and starts the socket thread. rilSocketQueue -------------- Queue for managing socket requests. Change-Id: I8828173941d6ae76f1f9cc0d567efaf41a77d175tirimbino
parent
6187ef8378
commit
cc231015f2
@ -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"); |
||||||
|
} |
@ -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*/ |
@ -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; |
||||||
|
} |
@ -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 |
@ -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; |
||||||
|
} |
||||||
|
} |
@ -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 |
Loading…
Reference in new issue