1/*
2* Copyright (C) 2014 The Android Open Source Project
3*
4* Licensed under the Apache License, Version 2.0 (the "License");
5* you may not use this file except in compliance with the License.
6* You may obtain a copy of the License at
7*
8*     http://www.apache.org/licenses/LICENSE-2.0
9*
10* Unless required by applicable law or agreed to in writing, software
11* distributed under the License is distributed on an "AS IS" BASIS,
12* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13* See the License for the specific language governing permissions and
14* limitations under the License.
15*/
16
17#define __STDC_LIMIT_MACROS
18#include <stdint.h>
19#define RIL_SHLIB
20#include "telephony/ril.h"
21#include "RilSapSocket.h"
22#include "pb_decode.h"
23#include "pb_encode.h"
24#undef LOG_TAG
25#define LOG_TAG "RIL_UIM_SOCKET"
26#include <utils/Log.h>
27#include <arpa/inet.h>
28#include <errno.h>
29#include <sap_service.h>
30
31static RilSapSocket::RilSapSocketList *head = NULL;
32
33extern "C" void
34RIL_requestTimedCallback (RIL_TimedCallback callback, void *param,
35        const struct timeval *relativeTime);
36
37struct RIL_Env RilSapSocket::uimRilEnv = {
38        .OnRequestComplete = RilSapSocket::sOnRequestComplete,
39        .OnUnsolicitedResponse = RilSapSocket::sOnUnsolicitedResponse,
40        .RequestTimedCallback = RIL_requestTimedCallback
41};
42
43void RilSapSocket::sOnRequestComplete (RIL_Token t,
44        RIL_Errno e,
45        void *response,
46        size_t responselen) {
47    RilSapSocket *sap_socket;
48    SapSocketRequest *request = (SapSocketRequest*) t;
49
50    RLOGD("Socket id:%d", request->socketId);
51
52    sap_socket = getSocketById(request->socketId);
53
54    if (sap_socket) {
55        sap_socket->onRequestComplete(t,e,response,responselen);
56    } else {
57        RLOGE("Invalid socket id");
58        if (request->curr) {
59            free(request->curr);
60        }
61        free(request);
62    }
63}
64
65#if defined(ANDROID_MULTI_SIM)
66void RilSapSocket::sOnUnsolicitedResponse(int unsolResponse,
67        const void *data,
68        size_t datalen,
69        RIL_SOCKET_ID socketId) {
70    RilSapSocket *sap_socket = getSocketById(socketId);
71    if (sap_socket) {
72        sap_socket->onUnsolicitedResponse(unsolResponse, (void *)data, datalen);
73    }
74}
75#else
76void RilSapSocket::sOnUnsolicitedResponse(int unsolResponse,
77       const void *data,
78       size_t datalen) {
79    RilSapSocket *sap_socket = getSocketById(RIL_SOCKET_1);
80    if(sap_socket){
81        sap_socket->onUnsolicitedResponse(unsolResponse, (void *)data, datalen);
82    }
83}
84#endif
85
86void RilSapSocket::printList() {
87    RilSapSocketList *current = head;
88    RLOGD("Printing socket list");
89    while(NULL != current) {
90        RLOGD("SocketName:%s",current->socket->name);
91        RLOGD("Socket id:%d",current->socket->id);
92        current = current->next;
93    }
94}
95
96RilSapSocket *RilSapSocket::getSocketById(RIL_SOCKET_ID socketId) {
97    RilSapSocket *sap_socket;
98    RilSapSocketList *current = head;
99
100    RLOGD("Entered getSocketById");
101    printList();
102
103    while(NULL != current) {
104        if(socketId == current->socket->id) {
105            sap_socket = current->socket;
106            return sap_socket;
107        }
108        current = current->next;
109    }
110    return NULL;
111}
112
113void RilSapSocket::initSapSocket(const char *socketName,
114        const RIL_RadioFunctions *uimFuncs) {
115
116    if (strcmp(socketName, RIL1_SERVICE_NAME) == 0) {
117        if(!SocketExists(socketName)) {
118            addSocketToList(socketName, RIL_SOCKET_1, uimFuncs);
119        }
120    }
121
122#if (SIM_COUNT >= 2)
123    if (strcmp(socketName, RIL2_SERVICE_NAME) == 0) {
124        if(!SocketExists(socketName)) {
125            addSocketToList(socketName, RIL_SOCKET_2, uimFuncs);
126        }
127    }
128#endif
129
130#if (SIM_COUNT >= 3)
131    if (strcmp(socketName, RIL3_SERVICE_NAME) == 0) {
132        if(!SocketExists(socketName)) {
133            addSocketToList(socketName, RIL_SOCKET_3, uimFuncs);
134        }
135    }
136#endif
137
138#if (SIM_COUNT >= 4)
139    if (strcmp(socketName, RIL4_SERVICE_NAME) == 0) {
140        if(!SocketExists(socketName)) {
141            addSocketToList(socketName, RIL_SOCKET_4, uimFuncs);
142        }
143    }
144#endif
145}
146
147void RilSapSocket::addSocketToList(const char *socketName, RIL_SOCKET_ID socketid,
148        const RIL_RadioFunctions *uimFuncs) {
149    RilSapSocket* socket = NULL;
150    RilSapSocketList *current;
151
152    if(!SocketExists(socketName)) {
153        socket = new RilSapSocket(socketName, socketid, uimFuncs);
154        RilSapSocketList* listItem = (RilSapSocketList*)malloc(sizeof(RilSapSocketList));
155        if (!listItem) {
156            RLOGE("addSocketToList: OOM");
157            delete socket;
158            return;
159        }
160        listItem->socket = socket;
161        listItem->next = NULL;
162
163        RLOGD("Adding socket with id: %d", socket->id);
164
165        if(NULL == head) {
166            head = listItem;
167            head->next = NULL;
168        }
169        else {
170            current = head;
171            while(NULL != current->next) {
172                current = current->next;
173            }
174            current->next = listItem;
175        }
176    }
177}
178
179bool RilSapSocket::SocketExists(const char *socketName) {
180    RilSapSocketList* current = head;
181
182    while(NULL != current) {
183        if(strcmp(current->socket->name, socketName) == 0) {
184            return true;
185        }
186        current = current->next;
187    }
188    return false;
189}
190
191RilSapSocket::RilSapSocket(const char *socketName,
192        RIL_SOCKET_ID socketId,
193        const RIL_RadioFunctions *inputUimFuncs):
194        RilSocket(socketName, socketId) {
195    if (inputUimFuncs) {
196        uimFuncs = inputUimFuncs;
197    }
198}
199
200void RilSapSocket::dispatchRequest(MsgHeader *req) {
201    // SapSocketRequest will be deallocated in onRequestComplete()
202    SapSocketRequest* currRequest=(SapSocketRequest*)malloc(sizeof(SapSocketRequest));
203    if (!currRequest) {
204        RLOGE("dispatchRequest: OOM");
205        // Free MsgHeader allocated in pushRecord()
206        free(req);
207        return;
208    }
209    currRequest->token = req->token;
210    currRequest->curr = req;
211    currRequest->p_next = NULL;
212    currRequest->socketId = id;
213
214    pendingResponseQueue.enqueue(currRequest);
215
216    if (uimFuncs) {
217        RLOGI("RilSapSocket::dispatchRequest [%d] > SAP REQUEST type: %d. id: %d. error: %d, \
218                token 0x%p",
219                req->token,
220                req->type,
221                req->id,
222                req->error,
223                currRequest );
224
225#if defined(ANDROID_MULTI_SIM)
226        uimFuncs->onRequest(req->id, req->payload->bytes, req->payload->size, currRequest, id);
227#else
228        uimFuncs->onRequest(req->id, req->payload->bytes, req->payload->size, currRequest);
229#endif
230    }
231}
232
233void RilSapSocket::onRequestComplete(RIL_Token t, RIL_Errno e, void *response,
234        size_t response_len) {
235    SapSocketRequest* request= (SapSocketRequest*)t;
236
237    if (!request || !request->curr) {
238        RLOGE("RilSapSocket::onRequestComplete: request/request->curr is NULL");
239        return;
240    }
241
242    MsgHeader *hdr = request->curr;
243
244    MsgHeader rsp;
245    rsp.token = request->curr->token;
246    rsp.type = MsgType_RESPONSE;
247    rsp.id = request->curr->id;
248    rsp.error = (Error)e;
249    rsp.payload = (pb_bytes_array_t *)calloc(1, sizeof(pb_bytes_array_t) + response_len);
250    if (!rsp.payload) {
251        RLOGE("onRequestComplete: OOM");
252    } else {
253        if (response && response_len > 0) {
254            memcpy(rsp.payload->bytes, response, response_len);
255            rsp.payload->size = response_len;
256        } else {
257            rsp.payload->size = 0;
258        }
259
260        RLOGE("RilSapSocket::onRequestComplete: Token:%d, MessageId:%d ril token 0x%p",
261                hdr->token, hdr->id, t);
262
263        sap::processResponse(&rsp, this);
264        free(rsp.payload);
265    }
266
267    // Deallocate SapSocketRequest
268    if(!pendingResponseQueue.checkAndDequeue(hdr->id, hdr->token)) {
269        RLOGE("Token:%d, MessageId:%d", hdr->token, hdr->id);
270        RLOGE ("RilSapSocket::onRequestComplete: invalid Token or Message Id");
271    }
272
273    // Deallocate MsgHeader
274    free(hdr);
275}
276
277void RilSapSocket::onUnsolicitedResponse(int unsolResponse, void *data, size_t datalen) {
278    if (data && datalen > 0) {
279        pb_bytes_array_t *payload = (pb_bytes_array_t *)calloc(1,
280                sizeof(pb_bytes_array_t) + datalen);
281        if (!payload) {
282            RLOGE("onUnsolicitedResponse: OOM");
283            return;
284        }
285        memcpy(payload->bytes, data, datalen);
286        payload->size = datalen;
287        MsgHeader rsp;
288        rsp.payload = payload;
289        rsp.type = MsgType_UNSOL_RESPONSE;
290        rsp.id = (MsgId)unsolResponse;
291        rsp.error = Error_RIL_E_SUCCESS;
292        sap::processUnsolResponse(&rsp, this);
293        free(payload);
294    }
295}
296