Skip to content

Instantly share code, notes, and snippets.

@yhpark
Last active February 13, 2017 01:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yhpark/bb85db51b699120857cd to your computer and use it in GitHub Desktop.
Save yhpark/bb85db51b699120857cd to your computer and use it in GitHub Desktop.
RIL forwarding via tcp

Android RIL Forwarding via TCP

This is modified version of ril.cpp where one device (server) ignores its vendor RIL and use the other device's (client) RIL by sending the server's RIL data, originally transmitted to Android's Java layer, to client via TCP socket and vice versa. The result is that the client recognizes the server's RIL data (mobile network status, incoming call/SMS, ...) as if the server's USIM is inserted in the client device.

Demo Video

https://www.youtube.com/watch?v=EpkQaBxv_m4

Implementation

A single file (hardware/ril/libril/ril.cpp) is modified from the base code in AOSP 5.0.1_r1. The server listens for a client, and when connected, it sends all the data from domain socket (vendor RIL) to the connected socket, and forwards the data received from the socket to domain socket. The client connects to the server via predefined IP address and port defined with REMOTE_ADDR and REMOTE_PORT, and give the file descriptor of the socket to vendor RIL, instead of giving file descriptor of domain socket.

How to Build

You have to build the modified code and flash the devices. Server needs to be built with the following define header #define REMOTE_MODE REMOTE_MODE_SERVER, and the client with #define REMOTE_MODE REMOTE_MODE_CLIENT. For this to work properly, both devices should be visible to each other in a TCP/IP network.

Author: Yeong Hoon Park (me@yhpark.io) @ KAIST CPS Lab 2015

License: Apache 2.0

/* //device/libs/telephony/ril.cpp
**
** Copyright 2006, 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 LOG_TAG "RILC"
#define REMOTE_MODE_SERVER 0
#define REMOTE_MODE_CLIENT 1
#define REMOTE_MODE_ORIGINAL 2
#define REMOTE_MODE_SELF_TEST 3
#define REMOTE_MODE REMOTE_MODE_SERVER
#define REMOTE_ADDR "143.248.254.40"
#define REMOTE_PORT 1100
#include <hardware_legacy/power.h>
#include <telephony/ril.h>
#include <telephony/ril_cdma_sms.h>
#include <cutils/sockets.h>
#include <cutils/jstring.h>
#include <telephony/record_stream.h>
#include <utils/Log.h>
#include <utils/SystemClock.h>
#include <pthread.h>
#include <binder/Parcel.h>
#include <cutils/jstring.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/limits.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <time.h>
#include <errno.h>
#include <assert.h>
#include <ctype.h>
#include <alloca.h>
#include <sys/un.h>
#include <assert.h>
#include <netinet/in.h>
#include <cutils/properties.h>
#include <ril_event.h>
namespace android {
#define PHONE_PROCESS "radio"
#define SOCKET_NAME_RIL "rild"
#define SOCKET2_NAME_RIL "rild2"
#define SOCKET3_NAME_RIL "rild3"
#define SOCKET4_NAME_RIL "rild4"
#define SOCKET_NAME_RIL_DEBUG "rild-debug"
#define ANDROID_WAKE_LOCK_NAME "radio-interface"
#define PROPERTY_RIL_IMPL "gsm.version.ril-impl"
// match with constant in RIL.java
#define MAX_COMMAND_BYTES (8 * 1024)
// Basically: memset buffers that the client library
// shouldn't be using anymore in an attempt to find
// memory usage issues sooner.
#define MEMSET_FREED 1
#define NUM_ELEMS(a) (sizeof (a) / sizeof (a)[0])
#define MIN(a,b) ((a)<(b) ? (a) : (b))
/* Constants for response types */
#define RESPONSE_SOLICITED 0
#define RESPONSE_UNSOLICITED 1
/* Negative values for private RIL errno's */
#define RIL_ERRNO_INVALID_RESPONSE -1
// request, response, and unsolicited msg print macro
#define PRINTBUF_SIZE 8096
// Enable RILC log
#define RILC_LOG 1
#if RILC_LOG
#define startRequest sprintf(printBuf, "(")
#define closeRequest sprintf(printBuf, "%s)", printBuf)
#define printRequest(token, req) \
RLOGD("[%04d]> %s %s", token, requestToString(req), printBuf)
#define startResponse sprintf(printBuf, "%s {", printBuf)
#define closeResponse sprintf(printBuf, "%s}", printBuf)
#define printResponse RLOGD("%s", printBuf)
#define clearPrintBuf printBuf[0] = 0
#define removeLastChar printBuf[strlen(printBuf)-1] = 0
#define appendPrintBuf(x...) sprintf(printBuf, x)
#else
#define startRequest
#define closeRequest
#define printRequest(token, req)
#define startResponse
#define closeResponse
#define printResponse
#define clearPrintBuf
#define removeLastChar
#define appendPrintBuf(x...)
#endif
enum WakeType {DONT_WAKE, WAKE_PARTIAL};
typedef struct {
int requestNumber;
void (*dispatchFunction) (Parcel &p, struct RequestInfo *pRI);
int(*responseFunction) (Parcel &p, void *response, size_t responselen);
} CommandInfo;
typedef struct {
int requestNumber;
int (*responseFunction) (Parcel &p, void *response, size_t responselen);
WakeType wakeType;
} UnsolResponseInfo;
typedef struct RequestInfo {
int32_t token; //this is not RIL_Token
CommandInfo *pCI;
struct RequestInfo *p_next;
char cancelled;
char local; // responses to local commands do not go back to command process
RIL_SOCKET_ID socket_id;
} RequestInfo;
typedef struct UserCallbackInfo {
RIL_TimedCallback p_callback;
void *userParam;
struct ril_event event;
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);
extern "C" const char * radioStateToString(RIL_RadioState);
extern "C" const char * rilSocketIdToString(RIL_SOCKET_ID socket_id);
extern "C"
char rild[MAX_SOCKET_NAME_LENGTH] = SOCKET_NAME_RIL;
/*******************************************************************/
RIL_RadioFunctions s_callbacks = {0, NULL, NULL, NULL, NULL, NULL};
static int s_registerCalled = 0;
static pthread_t s_tid_dispatch;
static pthread_t s_tid_reader;
static int s_started = 0;
static int s_fdDebug = -1;
static int s_fdDebug_socket2 = -1;
static int s_fdWakeupRead;
static int s_fdWakeupWrite;
static struct ril_event s_commands_event;
static struct ril_event s_wakeupfd_event;
static struct ril_event s_listen_event;
static SocketListenParam s_ril_param_socket;
static pthread_mutex_t s_pendingRequestsMutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t s_writeMutex = PTHREAD_MUTEX_INITIALIZER;
static RequestInfo *s_pendingRequests = NULL;
#if (SIM_COUNT >= 2)
static struct ril_event s_commands_event_socket2;
static struct ril_event s_listen_event_socket2;
static SocketListenParam s_ril_param_socket2;
static pthread_mutex_t s_pendingRequestsMutex_socket2 = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t s_writeMutex_socket2 = PTHREAD_MUTEX_INITIALIZER;
static RequestInfo *s_pendingRequests_socket2 = NULL;
#endif
#if (SIM_COUNT >= 3)
static struct ril_event s_commands_event_socket3;
static struct ril_event s_listen_event_socket3;
static SocketListenParam s_ril_param_socket3;
static pthread_mutex_t s_pendingRequestsMutex_socket3 = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t s_writeMutex_socket3 = PTHREAD_MUTEX_INITIALIZER;
static RequestInfo *s_pendingRequests_socket3 = NULL;
#endif
#if (SIM_COUNT >= 4)
static struct ril_event s_commands_event_socket4;
static struct ril_event s_listen_event_socket4;
static SocketListenParam s_ril_param_socket4;
static pthread_mutex_t s_pendingRequestsMutex_socket4 = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t s_writeMutex_socket4 = PTHREAD_MUTEX_INITIALIZER;
static RequestInfo *s_pendingRequests_socket4 = NULL;
#endif
static struct ril_event s_wake_timeout_event;
static struct ril_event s_debug_event;
static const struct timeval TIMEVAL_WAKE_TIMEOUT = {1,0};
static pthread_mutex_t s_startupMutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t s_startupCond = PTHREAD_COND_INITIALIZER;
static pthread_mutex_t s_dispatchMutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t s_dispatchCond = PTHREAD_COND_INITIALIZER;
static RequestInfo *s_toDispatchHead = NULL;
static RequestInfo *s_toDispatchTail = NULL;
static UserCallbackInfo *s_last_wake_timeout_info = NULL;
static void *s_lastNITZTimeData = NULL;
static size_t s_lastNITZTimeDataSize;
#if RILC_LOG
static char printBuf[PRINTBUF_SIZE];
#endif
/*******************************************************************/
static int sendResponse (Parcel &p, RIL_SOCKET_ID socket_id);
static void dispatchVoid (Parcel& p, RequestInfo *pRI);
static void dispatchString (Parcel& p, RequestInfo *pRI);
static void dispatchStrings (Parcel& p, RequestInfo *pRI);
static void dispatchInts (Parcel& p, RequestInfo *pRI);
static void dispatchDial (Parcel& p, RequestInfo *pRI);
static void dispatchSIM_IO (Parcel& p, RequestInfo *pRI);
static void dispatchSIM_APDU (Parcel& p, RequestInfo *pRI);
static void dispatchCallForward(Parcel& p, RequestInfo *pRI);
static void dispatchRaw(Parcel& p, RequestInfo *pRI);
static void dispatchSmsWrite (Parcel &p, RequestInfo *pRI);
static void dispatchDataCall (Parcel& p, RequestInfo *pRI);
static void dispatchVoiceRadioTech (Parcel& p, RequestInfo *pRI);
static void dispatchSetInitialAttachApn (Parcel& p, RequestInfo *pRI);
static void dispatchCdmaSubscriptionSource (Parcel& p, RequestInfo *pRI);
static void dispatchCdmaSms(Parcel &p, RequestInfo *pRI);
static void dispatchImsSms(Parcel &p, RequestInfo *pRI);
static void dispatchImsCdmaSms(Parcel &p, RequestInfo *pRI, uint8_t retry, int32_t messageRef);
static void dispatchImsGsmSms(Parcel &p, RequestInfo *pRI, uint8_t retry, int32_t messageRef);
static void dispatchCdmaSmsAck(Parcel &p, RequestInfo *pRI);
static void dispatchGsmBrSmsCnf(Parcel &p, RequestInfo *pRI);
static void dispatchCdmaBrSmsCnf(Parcel &p, RequestInfo *pRI);
static void dispatchRilCdmaSmsWriteArgs(Parcel &p, RequestInfo *pRI);
static void dispatchNVReadItem(Parcel &p, RequestInfo *pRI);
static void dispatchNVWriteItem(Parcel &p, RequestInfo *pRI);
static void dispatchUiccSubscripton(Parcel &p, RequestInfo *pRI);
static void dispatchSimAuthentication(Parcel &p, RequestInfo *pRI);
static void dispatchDataProfile(Parcel &p, RequestInfo *pRI);
static int responseInts(Parcel &p, void *response, size_t responselen);
static int responseStrings(Parcel &p, void *response, size_t responselen);
static int responseString(Parcel &p, void *response, size_t responselen);
static int responseVoid(Parcel &p, void *response, size_t responselen);
static int responseCallList(Parcel &p, void *response, size_t responselen);
static int responseSMS(Parcel &p, void *response, size_t responselen);
static int responseSIM_IO(Parcel &p, void *response, size_t responselen);
static int responseCallForwards(Parcel &p, void *response, size_t responselen);
static int responseDataCallList(Parcel &p, void *response, size_t responselen);
static int responseSetupDataCall(Parcel &p, void *response, size_t responselen);
static int responseRaw(Parcel &p, void *response, size_t responselen);
static int responseSsn(Parcel &p, void *response, size_t responselen);
static int responseSimStatus(Parcel &p, void *response, size_t responselen);
static int responseGsmBrSmsCnf(Parcel &p, void *response, size_t responselen);
static int responseCdmaBrSmsCnf(Parcel &p, void *response, size_t responselen);
static int responseCdmaSms(Parcel &p, void *response, size_t responselen);
static int responseCellList(Parcel &p, void *response, size_t responselen);
static int responseCdmaInformationRecords(Parcel &p,void *response, size_t responselen);
static int responseRilSignalStrength(Parcel &p,void *response, size_t responselen);
static int responseCallRing(Parcel &p, void *response, size_t responselen);
static int responseCdmaSignalInfoRecord(Parcel &p,void *response, size_t responselen);
static int responseCdmaCallWaiting(Parcel &p,void *response, size_t responselen);
static int responseSimRefresh(Parcel &p, void *response, size_t responselen);
static int responseCellInfoList(Parcel &p, void *response, size_t responselen);
static int responseHardwareConfig(Parcel &p, void *response, size_t responselen);
static int responseDcRtInfo(Parcel &p, void *response, size_t responselen);
static int decodeVoiceRadioTechnology (RIL_RadioState radioState);
static int decodeCdmaSubscriptionSource (RIL_RadioState radioState);
static RIL_RadioState processRadioState(RIL_RadioState newRadioState);
#ifdef RIL_SHLIB
#if defined(ANDROID_MULTI_SIM)
extern "C" void RIL_onUnsolicitedResponse(int unsolResponse, void *data,
size_t datalen, RIL_SOCKET_ID socket_id);
#else
extern "C" void RIL_onUnsolicitedResponse(int unsolResponse, void *data,
size_t datalen);
#endif
#endif
#if defined(ANDROID_MULTI_SIM)
#define RIL_UNSOL_RESPONSE(a, b, c, d) RIL_onUnsolicitedResponse((a), (b), (c), (d))
#define CALL_ONREQUEST(a, b, c, d, e) s_callbacks.onRequest((a), (b), (c), (d), (e))
#define CALL_ONSTATEREQUEST(a) s_callbacks.onStateRequest(a)
#else
#define RIL_UNSOL_RESPONSE(a, b, c, d) RIL_onUnsolicitedResponse((a), (b), (c))
#define CALL_ONREQUEST(a, b, c, d, e) s_callbacks.onRequest((a), (b), (c), (d))
#define CALL_ONSTATEREQUEST(a) s_callbacks.onStateRequest()
#endif
static UserCallbackInfo * internalRequestTimedCallback
(RIL_TimedCallback callback, void *param,
const struct timeval *relativeTime);
/** Index == requestNumber */
static CommandInfo s_commands[] = {
#include "ril_commands.h"
};
static UnsolResponseInfo s_unsolResponses[] = {
#include "ril_unsol_commands.h"
};
/* For older RILs that do not support new commands RIL_REQUEST_VOICE_RADIO_TECH and
RIL_UNSOL_VOICE_RADIO_TECH_CHANGED messages, decode the voice radio tech from
radio state message and store it. Every time there is a change in Radio State
check to see if voice radio tech changes and notify telephony
*/
int voiceRadioTech = -1;
/* For older RILs that do not support new commands RIL_REQUEST_GET_CDMA_SUBSCRIPTION_SOURCE
and RIL_UNSOL_CDMA_SUBSCRIPTION_SOURCE_CHANGED messages, decode the subscription
source from radio state and store it. Every time there is a change in Radio State
check to see if subscription source changed and notify telephony
*/
int cdmaSubscriptionSource = -1;
/* For older RILs that do not send RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED, decode the
SIM/RUIM state from radio state and store it. Every time there is a change in Radio State,
check to see if SIM/RUIM status changed and notify telephony
*/
int simRuimStatus = -1;
static char * RIL_getRilSocketName() {
return rild;
}
extern "C"
void RIL_setRilSocketName(char * s) {
strncpy(rild, s, MAX_SOCKET_NAME_LENGTH);
}
static char *
strdupReadString(Parcel &p) {
size_t stringlen;
const char16_t *s16;
s16 = p.readString16Inplace(&stringlen);
return strndup16to8(s16, stringlen);
}
static void writeStringToParcel(Parcel &p, const char *s) {
char16_t *s16;
size_t s16_len;
s16 = strdup8to16(s, &s16_len);
p.writeString16(s16, s16_len);
free(s16);
}
static void
memsetString (char *s) {
if (s != NULL) {
memset (s, 0, strlen(s));
}
}
void nullParcelReleaseFunction (const uint8_t* data, size_t dataSize,
const size_t* objects, size_t objectsSize,
void* cookie) {
// do nothing -- the data reference lives longer than the Parcel object
}
/**
* To be called from dispatch thread
* Issue a single local request, ensuring that the response
* is not sent back up to the command process
*/
static void
issueLocalRequest(int request, void *data, int len, RIL_SOCKET_ID socket_id) {
RequestInfo *pRI;
int ret;
/* Hook for current context */
/* pendingRequestsMutextHook refer to &s_pendingRequestsMutex */
pthread_mutex_t* pendingRequestsMutexHook = &s_pendingRequestsMutex;
/* pendingRequestsHook refer to &s_pendingRequests */
RequestInfo** pendingRequestsHook = &s_pendingRequests;
#if (SIM_COUNT == 2)
if (socket_id == RIL_SOCKET_2) {
pendingRequestsMutexHook = &s_pendingRequestsMutex_socket2;
pendingRequestsHook = &s_pendingRequests_socket2;
}
#endif
pRI = (RequestInfo *)calloc(1, sizeof(RequestInfo));
pRI->local = 1;
pRI->token = 0xffffffff; // token is not used in this context
pRI->pCI = &(s_commands[request]);
pRI->socket_id = socket_id;
ret = pthread_mutex_lock(pendingRequestsMutexHook);
assert (ret == 0);
pRI->p_next = *pendingRequestsHook;
*pendingRequestsHook = pRI;
ret = pthread_mutex_unlock(pendingRequestsMutexHook);
assert (ret == 0);
RLOGD("C[locl]> %s", requestToString(request));
CALL_ONREQUEST(request, data, len, pRI, pRI->socket_id);
}
static int
processCommandBuffer(void *buffer, size_t buflen, RIL_SOCKET_ID socket_id) {
Parcel p;
status_t status;
int32_t request;
int32_t token;
RequestInfo *pRI;
int ret;
/* Hook for current context */
/* pendingRequestsMutextHook refer to &s_pendingRequestsMutex */
pthread_mutex_t* pendingRequestsMutexHook = &s_pendingRequestsMutex;
/* pendingRequestsHook refer to &s_pendingRequests */
RequestInfo** pendingRequestsHook = &s_pendingRequests;
p.setData((uint8_t *) buffer, buflen);
// status checked at end
status = p.readInt32(&request);
status = p.readInt32 (&token);
RLOGD("SOCKET %s REQUEST: %s length:%d", rilSocketIdToString(socket_id), requestToString(request), buflen);
#if (SIM_COUNT >= 2)
if (socket_id == RIL_SOCKET_2) {
pendingRequestsMutexHook = &s_pendingRequestsMutex_socket2;
pendingRequestsHook = &s_pendingRequests_socket2;
}
#if (SIM_COUNT >= 3)
else if (socket_id == RIL_SOCKET_3) {
pendingRequestsMutexHook = &s_pendingRequestsMutex_socket3;
pendingRequestsHook = &s_pendingRequests_socket3;
}
#endif
#if (SIM_COUNT >= 4)
else if (socket_id == RIL_SOCKET_4) {
pendingRequestsMutexHook = &s_pendingRequestsMutex_socket4;
pendingRequestsHook = &s_pendingRequests_socket4;
}
#endif
#endif
if (status != NO_ERROR) {
RLOGE("invalid request block");
return 0;
}
if (request < 1 || request >= (int32_t)NUM_ELEMS(s_commands)) {
Parcel pErr;
RLOGE("unsupported request code %d token %d", request, token);
// FIXME this should perhaps return a response
pErr.writeInt32 (RESPONSE_SOLICITED);
pErr.writeInt32 (token);
pErr.writeInt32 (RIL_E_GENERIC_FAILURE);
sendResponse(pErr, socket_id);
return 0;
}
pRI = (RequestInfo *)calloc(1, sizeof(RequestInfo));
pRI->token = token;
pRI->pCI = &(s_commands[request]);
pRI->socket_id = socket_id;
ret = pthread_mutex_lock(pendingRequestsMutexHook);
assert (ret == 0);
pRI->p_next = *pendingRequestsHook;
*pendingRequestsHook = pRI;
ret = pthread_mutex_unlock(pendingRequestsMutexHook);
assert (ret == 0);
/* sLastDispatchedToken = token; */
pRI->pCI->dispatchFunction(p, pRI);
return 0;
}
static void
invalidCommandBlock (RequestInfo *pRI) {
RLOGE("invalid command block for token %d request %s",
pRI->token, requestToString(pRI->pCI->requestNumber));
}
/** Callee expects NULL */
static void
dispatchVoid (Parcel& p, RequestInfo *pRI) {
clearPrintBuf;
printRequest(pRI->token, pRI->pCI->requestNumber);
CALL_ONREQUEST(pRI->pCI->requestNumber, NULL, 0, pRI, pRI->socket_id);
}
/** Callee expects const char * */
static void
dispatchString (Parcel& p, RequestInfo *pRI) {
status_t status;
size_t datalen;
size_t stringlen;
char *string8 = NULL;
string8 = strdupReadString(p);
startRequest;
appendPrintBuf("%s%s", printBuf, string8);
closeRequest;
printRequest(pRI->token, pRI->pCI->requestNumber);
CALL_ONREQUEST(pRI->pCI->requestNumber, string8,
sizeof(char *), pRI, pRI->socket_id);
#ifdef MEMSET_FREED
memsetString(string8);
#endif
free(string8);
return;
invalid:
invalidCommandBlock(pRI);
return;
}
/** Callee expects const char ** */
static void
dispatchStrings (Parcel &p, RequestInfo *pRI) {
int32_t countStrings;
status_t status;
size_t datalen;
char **pStrings;
status = p.readInt32 (&countStrings);
if (status != NO_ERROR) {
goto invalid;
}
startRequest;
if (countStrings == 0) {
// just some non-null pointer
pStrings = (char **)alloca(sizeof(char *));
datalen = 0;
} else if (((int)countStrings) == -1) {
pStrings = NULL;
datalen = 0;
} else {
datalen = sizeof(char *) * countStrings;
pStrings = (char **)alloca(datalen);
for (int i = 0 ; i < countStrings ; i++) {
pStrings[i] = strdupReadString(p);
appendPrintBuf("%s%s,", printBuf, pStrings[i]);
}
}
removeLastChar;
closeRequest;
printRequest(pRI->token, pRI->pCI->requestNumber);
CALL_ONREQUEST(pRI->pCI->requestNumber, pStrings, datalen, pRI, pRI->socket_id);
if (pStrings != NULL) {
for (int i = 0 ; i < countStrings ; i++) {
#ifdef MEMSET_FREED
memsetString (pStrings[i]);
#endif
free(pStrings[i]);
}
#ifdef MEMSET_FREED
memset(pStrings, 0, datalen);
#endif
}
return;
invalid:
invalidCommandBlock(pRI);
return;
}
/** Callee expects const int * */
static void
dispatchInts (Parcel &p, RequestInfo *pRI) {
int32_t count;
status_t status;
size_t datalen;
int *pInts;
status = p.readInt32 (&count);
if (status != NO_ERROR || count == 0) {
goto invalid;
}
datalen = sizeof(int) * count;
pInts = (int *)alloca(datalen);
startRequest;
for (int i = 0 ; i < count ; i++) {
int32_t t;
status = p.readInt32(&t);
pInts[i] = (int)t;
appendPrintBuf("%s%d,", printBuf, t);
if (status != NO_ERROR) {
goto invalid;
}
}
removeLastChar;
closeRequest;
printRequest(pRI->token, pRI->pCI->requestNumber);
CALL_ONREQUEST(pRI->pCI->requestNumber, const_cast<int *>(pInts),
datalen, pRI, pRI->socket_id);
#ifdef MEMSET_FREED
memset(pInts, 0, datalen);
#endif
return;
invalid:
invalidCommandBlock(pRI);
return;
}
/**
* Callee expects const RIL_SMS_WriteArgs *
* Payload is:
* int32_t status
* String pdu
*/
static void
dispatchSmsWrite (Parcel &p, RequestInfo *pRI) {
RIL_SMS_WriteArgs args;
int32_t t;
status_t status;
memset (&args, 0, sizeof(args));
status = p.readInt32(&t);
args.status = (int)t;
args.pdu = strdupReadString(p);
if (status != NO_ERROR || args.pdu == NULL) {
goto invalid;
}
args.smsc = strdupReadString(p);
startRequest;
appendPrintBuf("%s%d,%s,smsc=%s", printBuf, args.status,
(char*)args.pdu, (char*)args.smsc);
closeRequest;
printRequest(pRI->token, pRI->pCI->requestNumber);
CALL_ONREQUEST(pRI->pCI->requestNumber, &args, sizeof(args), pRI, pRI->socket_id);
#ifdef MEMSET_FREED
memsetString (args.pdu);
#endif
free (args.pdu);
#ifdef MEMSET_FREED
memset(&args, 0, sizeof(args));
#endif
return;
invalid:
invalidCommandBlock(pRI);
return;
}
/**
* Callee expects const RIL_Dial *
* Payload is:
* String address
* int32_t clir
*/
static void
dispatchDial (Parcel &p, RequestInfo *pRI) {
RIL_Dial dial;
RIL_UUS_Info uusInfo;
int32_t sizeOfDial;
int32_t t;
int32_t uusPresent;
status_t status;
memset (&dial, 0, sizeof(dial));
dial.address = strdupReadString(p);
status = p.readInt32(&t);
dial.clir = (int)t;
if (status != NO_ERROR || dial.address == NULL) {
goto invalid;
}
if (s_callbacks.version < 3) { // Remove when partners upgrade to version 3
uusPresent = 0;
sizeOfDial = sizeof(dial) - sizeof(RIL_UUS_Info *);
} else {
status = p.readInt32(&uusPresent);
if (status != NO_ERROR) {
goto invalid;
}
if (uusPresent == 0) {
dial.uusInfo = NULL;
} else {
int32_t len;
memset(&uusInfo, 0, sizeof(RIL_UUS_Info));
status = p.readInt32(&t);
uusInfo.uusType = (RIL_UUS_Type) t;
status = p.readInt32(&t);
uusInfo.uusDcs = (RIL_UUS_DCS) t;
status = p.readInt32(&len);
if (status != NO_ERROR) {
goto invalid;
}
// The java code writes -1 for null arrays
if (((int) len) == -1) {
uusInfo.uusData = NULL;
len = 0;
} else {
uusInfo.uusData = (char*) p.readInplace(len);
}
uusInfo.uusLength = len;
dial.uusInfo = &uusInfo;
}
sizeOfDial = sizeof(dial);
}
startRequest;
appendPrintBuf("%snum=%s,clir=%d", printBuf, dial.address, dial.clir);
if (uusPresent) {
appendPrintBuf("%s,uusType=%d,uusDcs=%d,uusLen=%d", printBuf,
dial.uusInfo->uusType, dial.uusInfo->uusDcs,
dial.uusInfo->uusLength);
}
closeRequest;
printRequest(pRI->token, pRI->pCI->requestNumber);
CALL_ONREQUEST(pRI->pCI->requestNumber, &dial, sizeOfDial, pRI, pRI->socket_id);
#ifdef MEMSET_FREED
memsetString (dial.address);
#endif
free (dial.address);
#ifdef MEMSET_FREED
memset(&uusInfo, 0, sizeof(RIL_UUS_Info));
memset(&dial, 0, sizeof(dial));
#endif
return;
invalid:
invalidCommandBlock(pRI);
return;
}
/**
* Callee expects const RIL_SIM_IO *
* Payload is:
* int32_t command
* int32_t fileid
* String path
* int32_t p1, p2, p3
* String data
* String pin2
* String aidPtr
*/
static void
dispatchSIM_IO (Parcel &p, RequestInfo *pRI) {
union RIL_SIM_IO {
RIL_SIM_IO_v6 v6;
RIL_SIM_IO_v5 v5;
} simIO;
int32_t t;
int size;
status_t status;
memset (&simIO, 0, sizeof(simIO));
// note we only check status at the end
status = p.readInt32(&t);
simIO.v6.command = (int)t;
status = p.readInt32(&t);
simIO.v6.fileid = (int)t;
simIO.v6.path = strdupReadString(p);
status = p.readInt32(&t);
simIO.v6.p1 = (int)t;
status = p.readInt32(&t);
simIO.v6.p2 = (int)t;
status = p.readInt32(&t);
simIO.v6.p3 = (int)t;
simIO.v6.data = strdupReadString(p);
simIO.v6.pin2 = strdupReadString(p);
simIO.v6.aidPtr = strdupReadString(p);
startRequest;
appendPrintBuf("%scmd=0x%X,efid=0x%X,path=%s,%d,%d,%d,%s,pin2=%s,aid=%s", printBuf,
simIO.v6.command, simIO.v6.fileid, (char*)simIO.v6.path,
simIO.v6.p1, simIO.v6.p2, simIO.v6.p3,
(char*)simIO.v6.data, (char*)simIO.v6.pin2, simIO.v6.aidPtr);
closeRequest;
printRequest(pRI->token, pRI->pCI->requestNumber);
if (status != NO_ERROR) {
goto invalid;
}
size = (s_callbacks.version < 6) ? sizeof(simIO.v5) : sizeof(simIO.v6);
CALL_ONREQUEST(pRI->pCI->requestNumber, &simIO, size, pRI, pRI->socket_id);
#ifdef MEMSET_FREED
memsetString (simIO.v6.path);
memsetString (simIO.v6.data);
memsetString (simIO.v6.pin2);
memsetString (simIO.v6.aidPtr);
#endif
free (simIO.v6.path);
free (simIO.v6.data);
free (simIO.v6.pin2);
free (simIO.v6.aidPtr);
#ifdef MEMSET_FREED
memset(&simIO, 0, sizeof(simIO));
#endif
return;
invalid:
invalidCommandBlock(pRI);
return;
}
/**
* Callee expects const RIL_SIM_APDU *
* Payload is:
* int32_t sessionid
* int32_t cla
* int32_t instruction
* int32_t p1, p2, p3
* String data
*/
static void
dispatchSIM_APDU (Parcel &p, RequestInfo *pRI) {
int32_t t;
status_t status;
RIL_SIM_APDU apdu;
memset (&apdu, 0, sizeof(RIL_SIM_APDU));
// Note we only check status at the end. Any single failure leads to
// subsequent reads filing.
status = p.readInt32(&t);
apdu.sessionid = (int)t;
status = p.readInt32(&t);
apdu.cla = (int)t;
status = p.readInt32(&t);
apdu.instruction = (int)t;
status = p.readInt32(&t);
apdu.p1 = (int)t;
status = p.readInt32(&t);
apdu.p2 = (int)t;
status = p.readInt32(&t);
apdu.p3 = (int)t;
apdu.data = strdupReadString(p);
startRequest;
appendPrintBuf("%ssessionid=%d,cla=%d,ins=%d,p1=%d,p2=%d,p3=%d,data=%s",
printBuf, apdu.sessionid, apdu.cla, apdu.instruction, apdu.p1, apdu.p2,
apdu.p3, (char*)apdu.data);
closeRequest;
printRequest(pRI->token, pRI->pCI->requestNumber);
if (status != NO_ERROR) {
goto invalid;
}
CALL_ONREQUEST(pRI->pCI->requestNumber, &apdu, sizeof(RIL_SIM_APDU), pRI, pRI->socket_id);
#ifdef MEMSET_FREED
memsetString(apdu.data);
#endif
free(apdu.data);
#ifdef MEMSET_FREED
memset(&apdu, 0, sizeof(RIL_SIM_APDU));
#endif
return;
invalid:
invalidCommandBlock(pRI);
return;
}
/**
* Callee expects const RIL_CallForwardInfo *
* Payload is:
* int32_t status/action
* int32_t reason
* int32_t serviceCode
* int32_t toa
* String number (0 length -> null)
* int32_t timeSeconds
*/
static void
dispatchCallForward(Parcel &p, RequestInfo *pRI) {
RIL_CallForwardInfo cff;
int32_t t;
status_t status;
memset (&cff, 0, sizeof(cff));
// note we only check status at the end
status = p.readInt32(&t);
cff.status = (int)t;
status = p.readInt32(&t);
cff.reason = (int)t;
status = p.readInt32(&t);
cff.serviceClass = (int)t;
status = p.readInt32(&t);
cff.toa = (int)t;
cff.number = strdupReadString(p);
status = p.readInt32(&t);
cff.timeSeconds = (int)t;
if (status != NO_ERROR) {
goto invalid;
}
// special case: number 0-length fields is null
if (cff.number != NULL && strlen (cff.number) == 0) {
cff.number = NULL;
}
startRequest;
appendPrintBuf("%sstat=%d,reason=%d,serv=%d,toa=%d,%s,tout=%d", printBuf,
cff.status, cff.reason, cff.serviceClass, cff.toa,
(char*)cff.number, cff.timeSeconds);
closeRequest;
printRequest(pRI->token, pRI->pCI->requestNumber);
CALL_ONREQUEST(pRI->pCI->requestNumber, &cff, sizeof(cff), pRI, pRI->socket_id);
#ifdef MEMSET_FREED
memsetString(cff.number);
#endif
free (cff.number);
#ifdef MEMSET_FREED
memset(&cff, 0, sizeof(cff));
#endif
return;
invalid:
invalidCommandBlock(pRI);
return;
}
static void
dispatchRaw(Parcel &p, RequestInfo *pRI) {
int32_t len;
status_t status;
const void *data;
status = p.readInt32(&len);
if (status != NO_ERROR) {
goto invalid;
}
// The java code writes -1 for null arrays
if (((int)len) == -1) {
data = NULL;
len = 0;
}
data = p.readInplace(len);
startRequest;
appendPrintBuf("%sraw_size=%d", printBuf, len);
closeRequest;
printRequest(pRI->token, pRI->pCI->requestNumber);
CALL_ONREQUEST(pRI->pCI->requestNumber, const_cast<void *>(data), len, pRI, pRI->socket_id);
return;
invalid:
invalidCommandBlock(pRI);
return;
}
static status_t
constructCdmaSms(Parcel &p, RequestInfo *pRI, RIL_CDMA_SMS_Message& rcsm) {
int32_t t;
uint8_t ut;
status_t status;
int32_t digitCount;
int digitLimit;
memset(&rcsm, 0, sizeof(rcsm));
status = p.readInt32(&t);
rcsm.uTeleserviceID = (int) t;
status = p.read(&ut,sizeof(ut));
rcsm.bIsServicePresent = (uint8_t) ut;
status = p.readInt32(&t);
rcsm.uServicecategory = (int) t;
status = p.readInt32(&t);
rcsm.sAddress.digit_mode = (RIL_CDMA_SMS_DigitMode) t;
status = p.readInt32(&t);
rcsm.sAddress.number_mode = (RIL_CDMA_SMS_NumberMode) t;
status = p.readInt32(&t);
rcsm.sAddress.number_type = (RIL_CDMA_SMS_NumberType) t;
status = p.readInt32(&t);
rcsm.sAddress.number_plan = (RIL_CDMA_SMS_NumberPlan) t;
status = p.read(&ut,sizeof(ut));
rcsm.sAddress.number_of_digits= (uint8_t) ut;
digitLimit= MIN((rcsm.sAddress.number_of_digits), RIL_CDMA_SMS_ADDRESS_MAX);
for(digitCount =0 ; digitCount < digitLimit; digitCount ++) {
status = p.read(&ut,sizeof(ut));
rcsm.sAddress.digits[digitCount] = (uint8_t) ut;
}
status = p.readInt32(&t);
rcsm.sSubAddress.subaddressType = (RIL_CDMA_SMS_SubaddressType) t;
status = p.read(&ut,sizeof(ut));
rcsm.sSubAddress.odd = (uint8_t) ut;
status = p.read(&ut,sizeof(ut));
rcsm.sSubAddress.number_of_digits = (uint8_t) ut;
digitLimit= MIN((rcsm.sSubAddress.number_of_digits), RIL_CDMA_SMS_SUBADDRESS_MAX);
for(digitCount =0 ; digitCount < digitLimit; digitCount ++) {
status = p.read(&ut,sizeof(ut));
rcsm.sSubAddress.digits[digitCount] = (uint8_t) ut;
}
status = p.readInt32(&t);
rcsm.uBearerDataLen = (int) t;
digitLimit= MIN((rcsm.uBearerDataLen), RIL_CDMA_SMS_BEARER_DATA_MAX);
for(digitCount =0 ; digitCount < digitLimit; digitCount ++) {
status = p.read(&ut, sizeof(ut));
rcsm.aBearerData[digitCount] = (uint8_t) ut;
}
if (status != NO_ERROR) {
return status;
}
startRequest;
appendPrintBuf("%suTeleserviceID=%d, bIsServicePresent=%d, uServicecategory=%d, \
sAddress.digit_mode=%d, sAddress.Number_mode=%d, sAddress.number_type=%d, ",
printBuf, rcsm.uTeleserviceID,rcsm.bIsServicePresent,rcsm.uServicecategory,
rcsm.sAddress.digit_mode, rcsm.sAddress.number_mode,rcsm.sAddress.number_type);
closeRequest;
printRequest(pRI->token, pRI->pCI->requestNumber);
return status;
}
static void
dispatchCdmaSms(Parcel &p, RequestInfo *pRI) {
RIL_CDMA_SMS_Message rcsm;
ALOGD("dispatchCdmaSms");
if (NO_ERROR != constructCdmaSms(p, pRI, rcsm)) {
goto invalid;
}
CALL_ONREQUEST(pRI->pCI->requestNumber, &rcsm, sizeof(rcsm),pRI, pRI->socket_id);
#ifdef MEMSET_FREED
memset(&rcsm, 0, sizeof(rcsm));
#endif
return;
invalid:
invalidCommandBlock(pRI);
return;
}
static void
dispatchImsCdmaSms(Parcel &p, RequestInfo *pRI, uint8_t retry, int32_t messageRef) {
RIL_IMS_SMS_Message rism;
RIL_CDMA_SMS_Message rcsm;
ALOGD("dispatchImsCdmaSms: retry=%d, messageRef=%d", retry, messageRef);
if (NO_ERROR != constructCdmaSms(p, pRI, rcsm)) {
goto invalid;
}
memset(&rism, 0, sizeof(rism));
rism.tech = RADIO_TECH_3GPP2;
rism.retry = retry;
rism.messageRef = messageRef;
rism.message.cdmaMessage = &rcsm;
CALL_ONREQUEST(pRI->pCI->requestNumber, &rism,
sizeof(RIL_RadioTechnologyFamily)+sizeof(uint8_t)+sizeof(int32_t)
+sizeof(rcsm),pRI, pRI->socket_id);
#ifdef MEMSET_FREED
memset(&rcsm, 0, sizeof(rcsm));
memset(&rism, 0, sizeof(rism));
#endif
return;
invalid:
invalidCommandBlock(pRI);
return;
}
static void
dispatchImsGsmSms(Parcel &p, RequestInfo *pRI, uint8_t retry, int32_t messageRef) {
RIL_IMS_SMS_Message rism;
int32_t countStrings;
status_t status;
size_t datalen;
char **pStrings;
ALOGD("dispatchImsGsmSms: retry=%d, messageRef=%d", retry, messageRef);
status = p.readInt32 (&countStrings);
if (status != NO_ERROR) {
goto invalid;
}
memset(&rism, 0, sizeof(rism));
rism.tech = RADIO_TECH_3GPP;
rism.retry = retry;
rism.messageRef = messageRef;
startRequest;
appendPrintBuf("%stech=%d, retry=%d, messageRef=%d, ", printBuf,
(int)rism.tech, (int)rism.retry, rism.messageRef);
if (countStrings == 0) {
// just some non-null pointer
pStrings = (char **)alloca(sizeof(char *));
datalen = 0;
} else if (((int)countStrings) == -1) {
pStrings = NULL;
datalen = 0;
} else {
datalen = sizeof(char *) * countStrings;
pStrings = (char **)alloca(datalen);
for (int i = 0 ; i < countStrings ; i++) {
pStrings[i] = strdupReadString(p);
appendPrintBuf("%s%s,", printBuf, pStrings[i]);
}
}
removeLastChar;
closeRequest;
printRequest(pRI->token, pRI->pCI->requestNumber);
rism.message.gsmMessage = pStrings;
CALL_ONREQUEST(pRI->pCI->requestNumber, &rism,
sizeof(RIL_RadioTechnologyFamily)+sizeof(uint8_t)+sizeof(int32_t)
+datalen, pRI, pRI->socket_id);
if (pStrings != NULL) {
for (int i = 0 ; i < countStrings ; i++) {
#ifdef MEMSET_FREED
memsetString (pStrings[i]);
#endif
free(pStrings[i]);
}
#ifdef MEMSET_FREED
memset(pStrings, 0, datalen);
#endif
}
#ifdef MEMSET_FREED
memset(&rism, 0, sizeof(rism));
#endif
return;
invalid:
ALOGE("dispatchImsGsmSms invalid block");
invalidCommandBlock(pRI);
return;
}
static void
dispatchImsSms(Parcel &p, RequestInfo *pRI) {
int32_t t;
status_t status = p.readInt32(&t);
RIL_RadioTechnologyFamily format;
uint8_t retry;
int32_t messageRef;
ALOGD("dispatchImsSms");
if (status != NO_ERROR) {
goto invalid;
}
format = (RIL_RadioTechnologyFamily) t;
// read retry field
status = p.read(&retry,sizeof(retry));
if (status != NO_ERROR) {
goto invalid;
}
// read messageRef field
status = p.read(&messageRef,sizeof(messageRef));
if (status != NO_ERROR) {
goto invalid;
}
if (RADIO_TECH_3GPP == format) {
dispatchImsGsmSms(p, pRI, retry, messageRef);
} else if (RADIO_TECH_3GPP2 == format) {
dispatchImsCdmaSms(p, pRI, retry, messageRef);
} else {
ALOGE("requestImsSendSMS invalid format value =%d", format);
}
return;
invalid:
invalidCommandBlock(pRI);
return;
}
static void
dispatchCdmaSmsAck(Parcel &p, RequestInfo *pRI) {
RIL_CDMA_SMS_Ack rcsa;
int32_t t;
status_t status;
int32_t digitCount;
memset(&rcsa, 0, sizeof(rcsa));
status = p.readInt32(&t);
rcsa.uErrorClass = (RIL_CDMA_SMS_ErrorClass) t;
status = p.readInt32(&t);
rcsa.uSMSCauseCode = (int) t;
if (status != NO_ERROR) {
goto invalid;
}
startRequest;
appendPrintBuf("%suErrorClass=%d, uTLStatus=%d, ",
printBuf, rcsa.uErrorClass, rcsa.uSMSCauseCode);
closeRequest;
printRequest(pRI->token, pRI->pCI->requestNumber);
CALL_ONREQUEST(pRI->pCI->requestNumber, &rcsa, sizeof(rcsa),pRI, pRI->socket_id);
#ifdef MEMSET_FREED
memset(&rcsa, 0, sizeof(rcsa));
#endif
return;
invalid:
invalidCommandBlock(pRI);
return;
}
static void
dispatchGsmBrSmsCnf(Parcel &p, RequestInfo *pRI) {
int32_t t;
status_t status;
int32_t num;
status = p.readInt32(&num);
if (status != NO_ERROR) {
goto invalid;
}
{
RIL_GSM_BroadcastSmsConfigInfo gsmBci[num];
RIL_GSM_BroadcastSmsConfigInfo *gsmBciPtrs[num];
startRequest;
for (int i = 0 ; i < num ; i++ ) {
gsmBciPtrs[i] = &gsmBci[i];
status = p.readInt32(&t);
gsmBci[i].fromServiceId = (int) t;
status = p.readInt32(&t);
gsmBci[i].toServiceId = (int) t;
status = p.readInt32(&t);
gsmBci[i].fromCodeScheme = (int) t;
status = p.readInt32(&t);
gsmBci[i].toCodeScheme = (int) t;
status = p.readInt32(&t);
gsmBci[i].selected = (uint8_t) t;
appendPrintBuf("%s [%d: fromServiceId=%d, toServiceId =%d, \
fromCodeScheme=%d, toCodeScheme=%d, selected =%d]", printBuf, i,
gsmBci[i].fromServiceId, gsmBci[i].toServiceId,
gsmBci[i].fromCodeScheme, gsmBci[i].toCodeScheme,
gsmBci[i].selected);
}
closeRequest;
if (status != NO_ERROR) {
goto invalid;
}
CALL_ONREQUEST(pRI->pCI->requestNumber,
gsmBciPtrs,
num * sizeof(RIL_GSM_BroadcastSmsConfigInfo *),
pRI, pRI->socket_id);
#ifdef MEMSET_FREED
memset(gsmBci, 0, num * sizeof(RIL_GSM_BroadcastSmsConfigInfo));
memset(gsmBciPtrs, 0, num * sizeof(RIL_GSM_BroadcastSmsConfigInfo *));
#endif
}
return;
invalid:
invalidCommandBlock(pRI);
return;
}
static void
dispatchCdmaBrSmsCnf(Parcel &p, RequestInfo *pRI) {
int32_t t;
status_t status;
int32_t num;
status = p.readInt32(&num);
if (status != NO_ERROR) {
goto invalid;
}
{
RIL_CDMA_BroadcastSmsConfigInfo cdmaBci[num];
RIL_CDMA_BroadcastSmsConfigInfo *cdmaBciPtrs[num];
startRequest;
for (int i = 0 ; i < num ; i++ ) {
cdmaBciPtrs[i] = &cdmaBci[i];
status = p.readInt32(&t);
cdmaBci[i].service_category = (int) t;
status = p.readInt32(&t);
cdmaBci[i].language = (int) t;
status = p.readInt32(&t);
cdmaBci[i].selected = (uint8_t) t;
appendPrintBuf("%s [%d: service_category=%d, language =%d, \
entries.bSelected =%d]", printBuf, i, cdmaBci[i].service_category,
cdmaBci[i].language, cdmaBci[i].selected);
}
closeRequest;
if (status != NO_ERROR) {
goto invalid;
}
CALL_ONREQUEST(pRI->pCI->requestNumber,
cdmaBciPtrs,
num * sizeof(RIL_CDMA_BroadcastSmsConfigInfo *),
pRI, pRI->socket_id);
#ifdef MEMSET_FREED
memset(cdmaBci, 0, num * sizeof(RIL_CDMA_BroadcastSmsConfigInfo));
memset(cdmaBciPtrs, 0, num * sizeof(RIL_CDMA_BroadcastSmsConfigInfo *));
#endif
}
return;
invalid:
invalidCommandBlock(pRI);
return;
}
static void dispatchRilCdmaSmsWriteArgs(Parcel &p, RequestInfo *pRI) {
RIL_CDMA_SMS_WriteArgs rcsw;
int32_t t;
uint32_t ut;
uint8_t uct;
status_t status;
int32_t digitCount;
memset(&rcsw, 0, sizeof(rcsw));
status = p.readInt32(&t);
rcsw.status = t;
status = p.readInt32(&t);
rcsw.message.uTeleserviceID = (int) t;
status = p.read(&uct,sizeof(uct));
rcsw.message.bIsServicePresent = (uint8_t) uct;
status = p.readInt32(&t);
rcsw.message.uServicecategory = (int) t;
status = p.readInt32(&t);
rcsw.message.sAddress.digit_mode = (RIL_CDMA_SMS_DigitMode) t;
status = p.readInt32(&t);
rcsw.message.sAddress.number_mode = (RIL_CDMA_SMS_NumberMode) t;
status = p.readInt32(&t);
rcsw.message.sAddress.number_type = (RIL_CDMA_SMS_NumberType) t;
status = p.readInt32(&t);
rcsw.message.sAddress.number_plan = (RIL_CDMA_SMS_NumberPlan) t;
status = p.read(&uct,sizeof(uct));
rcsw.message.sAddress.number_of_digits = (uint8_t) uct;
for(digitCount = 0 ; digitCount < RIL_CDMA_SMS_ADDRESS_MAX; digitCount ++) {
status = p.read(&uct,sizeof(uct));
rcsw.message.sAddress.digits[digitCount] = (uint8_t) uct;
}
status = p.readInt32(&t);
rcsw.message.sSubAddress.subaddressType = (RIL_CDMA_SMS_SubaddressType) t;
status = p.read(&uct,sizeof(uct));
rcsw.message.sSubAddress.odd = (uint8_t) uct;
status = p.read(&uct,sizeof(uct));
rcsw.message.sSubAddress.number_of_digits = (uint8_t) uct;
for(digitCount = 0 ; digitCount < RIL_CDMA_SMS_SUBADDRESS_MAX; digitCount ++) {
status = p.read(&uct,sizeof(uct));
rcsw.message.sSubAddress.digits[digitCount] = (uint8_t) uct;
}
status = p.readInt32(&t);
rcsw.message.uBearerDataLen = (int) t;
for(digitCount = 0 ; digitCount < RIL_CDMA_SMS_BEARER_DATA_MAX; digitCount ++) {
status = p.read(&uct, sizeof(uct));
rcsw.message.aBearerData[digitCount] = (uint8_t) uct;
}
if (status != NO_ERROR) {
goto invalid;
}
startRequest;
appendPrintBuf("%sstatus=%d, message.uTeleserviceID=%d, message.bIsServicePresent=%d, \
message.uServicecategory=%d, message.sAddress.digit_mode=%d, \
message.sAddress.number_mode=%d, \
message.sAddress.number_type=%d, ",
printBuf, rcsw.status, rcsw.message.uTeleserviceID, rcsw.message.bIsServicePresent,
rcsw.message.uServicecategory, rcsw.message.sAddress.digit_mode,
rcsw.message.sAddress.number_mode,
rcsw.message.sAddress.number_type);
closeRequest;
printRequest(pRI->token, pRI->pCI->requestNumber);
CALL_ONREQUEST(pRI->pCI->requestNumber, &rcsw, sizeof(rcsw),pRI, pRI->socket_id);
#ifdef MEMSET_FREED
memset(&rcsw, 0, sizeof(rcsw));
#endif
return;
invalid:
invalidCommandBlock(pRI);
return;
}
// For backwards compatibility in RIL_REQUEST_SETUP_DATA_CALL.
// Version 4 of the RIL interface adds a new PDP type parameter to support
// IPv6 and dual-stack PDP contexts. When dealing with a previous version of
// RIL, remove the parameter from the request.
static void dispatchDataCall(Parcel& p, RequestInfo *pRI) {
// In RIL v3, REQUEST_SETUP_DATA_CALL takes 6 parameters.
const int numParamsRilV3 = 6;
// The first bytes of the RIL parcel contain the request number and the
// serial number - see processCommandBuffer(). Copy them over too.
int pos = p.dataPosition();
int numParams = p.readInt32();
if (s_callbacks.version < 4 && numParams > numParamsRilV3) {
Parcel p2;
p2.appendFrom(&p, 0, pos);
p2.writeInt32(numParamsRilV3);
for(int i = 0; i < numParamsRilV3; i++) {
p2.writeString16(p.readString16());
}
p2.setDataPosition(pos);
dispatchStrings(p2, pRI);
} else {
p.setDataPosition(pos);
dispatchStrings(p, pRI);
}
}
// For backwards compatibility with RILs that dont support RIL_REQUEST_VOICE_RADIO_TECH.
// When all RILs handle this request, this function can be removed and
// the request can be sent directly to the RIL using dispatchVoid.
static void dispatchVoiceRadioTech(Parcel& p, RequestInfo *pRI) {
RIL_RadioState state = CALL_ONSTATEREQUEST((RIL_SOCKET_ID)pRI->socket_id);
if ((RADIO_STATE_UNAVAILABLE == state) || (RADIO_STATE_OFF == state)) {
RIL_onRequestComplete(pRI, RIL_E_RADIO_NOT_AVAILABLE, NULL, 0);
}
// RILs that support RADIO_STATE_ON should support this request.
if (RADIO_STATE_ON == state) {
dispatchVoid(p, pRI);
return;
}
// For Older RILs, that do not support RADIO_STATE_ON, assume that they
// will not support this new request either and decode Voice Radio Technology
// from Radio State
voiceRadioTech = decodeVoiceRadioTechnology(state);
if (voiceRadioTech < 0)
RIL_onRequestComplete(pRI, RIL_E_GENERIC_FAILURE, NULL, 0);
else
RIL_onRequestComplete(pRI, RIL_E_SUCCESS, &voiceRadioTech, sizeof(int));
}
// For backwards compatibility in RIL_REQUEST_CDMA_GET_SUBSCRIPTION_SOURCE:.
// When all RILs handle this request, this function can be removed and
// the request can be sent directly to the RIL using dispatchVoid.
static void dispatchCdmaSubscriptionSource(Parcel& p, RequestInfo *pRI) {
RIL_RadioState state = CALL_ONSTATEREQUEST((RIL_SOCKET_ID)pRI->socket_id);
if ((RADIO_STATE_UNAVAILABLE == state) || (RADIO_STATE_OFF == state)) {
RIL_onRequestComplete(pRI, RIL_E_RADIO_NOT_AVAILABLE, NULL, 0);
}
// RILs that support RADIO_STATE_ON should support this request.
if (RADIO_STATE_ON == state) {
dispatchVoid(p, pRI);
return;
}
// For Older RILs, that do not support RADIO_STATE_ON, assume that they
// will not support this new request either and decode CDMA Subscription Source
// from Radio State
cdmaSubscriptionSource = decodeCdmaSubscriptionSource(state);
if (cdmaSubscriptionSource < 0)
RIL_onRequestComplete(pRI, RIL_E_GENERIC_FAILURE, NULL, 0);
else
RIL_onRequestComplete(pRI, RIL_E_SUCCESS, &cdmaSubscriptionSource, sizeof(int));
}
static void dispatchSetInitialAttachApn(Parcel &p, RequestInfo *pRI)
{
RIL_InitialAttachApn pf;
int32_t t;
status_t status;
memset(&pf, 0, sizeof(pf));
pf.apn = strdupReadString(p);
pf.protocol = strdupReadString(p);
status = p.readInt32(&t);
pf.authtype = (int) t;
pf.username = strdupReadString(p);
pf.password = strdupReadString(p);
startRequest;
appendPrintBuf("%sapn=%s, protocol=%s, authtype=%d, username=%s, password=%s",
printBuf, pf.apn, pf.protocol, pf.authtype, pf.username, pf.password);
closeRequest;
printRequest(pRI->token, pRI->pCI->requestNumber);
if (status != NO_ERROR) {
goto invalid;
}
CALL_ONREQUEST(pRI->pCI->requestNumber, &pf, sizeof(pf), pRI, pRI->socket_id);
#ifdef MEMSET_FREED
memsetString(pf.apn);
memsetString(pf.protocol);
memsetString(pf.username);
memsetString(pf.password);
#endif
free(pf.apn);
free(pf.protocol);
free(pf.username);
free(pf.password);
#ifdef MEMSET_FREED
memset(&pf, 0, sizeof(pf));
#endif
return;
invalid:
invalidCommandBlock(pRI);
return;
}
static void dispatchNVReadItem(Parcel &p, RequestInfo *pRI) {
RIL_NV_ReadItem nvri;
int32_t t;
status_t status;
memset(&nvri, 0, sizeof(nvri));
status = p.readInt32(&t);
nvri.itemID = (RIL_NV_Item) t;
if (status != NO_ERROR) {
goto invalid;
}
startRequest;
appendPrintBuf("%snvri.itemID=%d, ", printBuf, nvri.itemID);
closeRequest;
printRequest(pRI->token, pRI->pCI->requestNumber);
CALL_ONREQUEST(pRI->pCI->requestNumber, &nvri, sizeof(nvri), pRI, pRI->socket_id);
#ifdef MEMSET_FREED
memset(&nvri, 0, sizeof(nvri));
#endif
return;
invalid:
invalidCommandBlock(pRI);
return;
}
static void dispatchNVWriteItem(Parcel &p, RequestInfo *pRI) {
RIL_NV_WriteItem nvwi;
int32_t t;
status_t status;
memset(&nvwi, 0, sizeof(nvwi));
status = p.readInt32(&t);
nvwi.itemID = (RIL_NV_Item) t;
nvwi.value = strdupReadString(p);
if (status != NO_ERROR || nvwi.value == NULL) {
goto invalid;
}
startRequest;
appendPrintBuf("%snvwi.itemID=%d, value=%s, ", printBuf, nvwi.itemID,
nvwi.value);
closeRequest;
printRequest(pRI->token, pRI->pCI->requestNumber);
CALL_ONREQUEST(pRI->pCI->requestNumber, &nvwi, sizeof(nvwi), pRI, pRI->socket_id);
#ifdef MEMSET_FREED
memsetString(nvwi.value);
#endif
free(nvwi.value);
#ifdef MEMSET_FREED
memset(&nvwi, 0, sizeof(nvwi));
#endif
return;
invalid:
invalidCommandBlock(pRI);
return;
}
static void dispatchUiccSubscripton(Parcel &p, RequestInfo *pRI) {
RIL_SelectUiccSub uicc_sub;
status_t status;
int32_t t;
memset(&uicc_sub, 0, sizeof(uicc_sub));
status = p.readInt32(&t);
if (status != NO_ERROR) {
goto invalid;
}
uicc_sub.slot = (int) t;
status = p.readInt32(&t);
if (status != NO_ERROR) {
goto invalid;
}
uicc_sub.app_index = (int) t;
status = p.readInt32(&t);
if (status != NO_ERROR) {
goto invalid;
}
uicc_sub.sub_type = (RIL_SubscriptionType) t;
status = p.readInt32(&t);
if (status != NO_ERROR) {
goto invalid;
}
uicc_sub.act_status = (RIL_UiccSubActStatus) t;
startRequest;
appendPrintBuf("slot=%d, app_index=%d, act_status = %d", uicc_sub.slot, uicc_sub.app_index,
uicc_sub.act_status);
RLOGD("dispatchUiccSubscription, slot=%d, app_index=%d, act_status = %d", uicc_sub.slot,
uicc_sub.app_index, uicc_sub.act_status);
closeRequest;
printRequest(pRI->token, pRI->pCI->requestNumber);
CALL_ONREQUEST(pRI->pCI->requestNumber, &uicc_sub, sizeof(uicc_sub), pRI, pRI->socket_id);
#ifdef MEMSET_FREED
memset(&uicc_sub, 0, sizeof(uicc_sub));
#endif
return;
invalid:
invalidCommandBlock(pRI);
return;
}
static void dispatchSimAuthentication(Parcel &p, RequestInfo *pRI)
{
RIL_SimAuthentication pf;
int32_t t;
status_t status;
memset(&pf, 0, sizeof(pf));
status = p.readInt32(&t);
pf.authContext = (int) t;
pf.authData = strdupReadString(p);
pf.aid = strdupReadString(p);
startRequest;
appendPrintBuf("authContext=%s, authData=%s, aid=%s", pf.authContext, pf.authData, pf.aid);
closeRequest;
printRequest(pRI->token, pRI->pCI->requestNumber);
if (status != NO_ERROR) {
goto invalid;
}
CALL_ONREQUEST(pRI->pCI->requestNumber, &pf, sizeof(pf), pRI, pRI->socket_id);
#ifdef MEMSET_FREED
memsetString(pf.authData);
memsetString(pf.aid);
#endif
free(pf.authData);
free(pf.aid);
#ifdef MEMSET_FREED
memset(&pf, 0, sizeof(pf));
#endif
return;
invalid:
invalidCommandBlock(pRI);
return;
}
static void dispatchDataProfile(Parcel &p, RequestInfo *pRI) {
int32_t t;
status_t status;
int32_t num;
status = p.readInt32(&num);
if (status != NO_ERROR) {
goto invalid;
}
{
RIL_DataProfileInfo dataProfiles[num];
RIL_DataProfileInfo *dataProfilePtrs[num];
startRequest;
for (int i = 0 ; i < num ; i++ ) {
dataProfilePtrs[i] = &dataProfiles[i];
status = p.readInt32(&t);
dataProfiles[i].profileId = (int) t;
dataProfiles[i].apn = strdupReadString(p);
dataProfiles[i].protocol = strdupReadString(p);
status = p.readInt32(&t);
dataProfiles[i].authType = (int) t;
dataProfiles[i].user = strdupReadString(p);
dataProfiles[i].password = strdupReadString(p);
status = p.readInt32(&t);
dataProfiles[i].type = (int) t;
status = p.readInt32(&t);
dataProfiles[i].maxConnsTime = (int) t;
status = p.readInt32(&t);
dataProfiles[i].maxConns = (int) t;
status = p.readInt32(&t);
dataProfiles[i].waitTime = (int) t;
status = p.readInt32(&t);
dataProfiles[i].enabled = (int) t;
appendPrintBuf("%s [%d: profileId=%d, apn =%s, protocol =%s, authType =%d, \
user =%s, password =%s, type =%d, maxConnsTime =%d, maxConns =%d, \
waitTime =%d, enabled =%d]", printBuf, i, dataProfiles[i].profileId,
dataProfiles[i].apn, dataProfiles[i].protocol, dataProfiles[i].authType,
dataProfiles[i].user, dataProfiles[i].password, dataProfiles[i].type,
dataProfiles[i].maxConnsTime, dataProfiles[i].maxConns,
dataProfiles[i].waitTime, dataProfiles[i].enabled);
}
closeRequest;
printRequest(pRI->token, pRI->pCI->requestNumber);
if (status != NO_ERROR) {
goto invalid;
}
CALL_ONREQUEST(pRI->pCI->requestNumber,
dataProfilePtrs,
num * sizeof(RIL_DataProfileInfo *),
pRI, pRI->socket_id);
#ifdef MEMSET_FREED
memset(dataProfiles, 0, num * sizeof(RIL_DataProfileInfo));
memset(dataProfilePtrs, 0, num * sizeof(RIL_DataProfileInfo *));
#endif
}
return;
invalid:
invalidCommandBlock(pRI);
return;
}
static int
blockingWrite(int fd, const void *buffer, size_t len) {
size_t writeOffset = 0;
const uint8_t *toWrite;
toWrite = (const uint8_t *)buffer;
while (writeOffset < len) {
ssize_t written;
do {
written = write (fd, toWrite + writeOffset,
len - writeOffset);
} while (written < 0 && ((errno == EINTR) || (errno == EAGAIN)));
if (written >= 0) {
writeOffset += written;
} else { // written < 0
RLOGE ("RIL Response: unexpected error on write errno:%d", errno);
close(fd);
return -1;
}
}
return 0;
}
static int
sendResponseRaw (const void *data, size_t dataSize, RIL_SOCKET_ID socket_id) {
int fd = s_ril_param_socket.fdCommand;
int ret;
uint32_t header;
pthread_mutex_t * writeMutexHook = &s_writeMutex;
RLOGE("Send Response to %s", rilSocketIdToString(socket_id));
#if (SIM_COUNT >= 2)
if (socket_id == RIL_SOCKET_2) {
fd = s_ril_param_socket2.fdCommand;
writeMutexHook = &s_writeMutex_socket2;
}
#if (SIM_COUNT >= 3)
else if (socket_id == RIL_SOCKET_3) {
fd = s_ril_param_socket3.fdCommand;
writeMutexHook = &s_writeMutex_socket3;
}
#endif
#if (SIM_COUNT >= 4)
else if (socket_id == RIL_SOCKET_4) {
fd = s_ril_param_socket4.fdCommand;
writeMutexHook = &s_writeMutex_socket4;
}
#endif
#endif
if (fd < 0) {
return -1;
}
if (dataSize > MAX_COMMAND_BYTES) {
RLOGE("RIL: packet larger than %u (%u)",
MAX_COMMAND_BYTES, (unsigned int )dataSize);
return -1;
}
pthread_mutex_lock(writeMutexHook);
header = htonl(dataSize);
ret = blockingWrite(fd, (void *)&header, sizeof(header));
if (ret < 0) {
pthread_mutex_unlock(writeMutexHook);
return ret;
}
ret = blockingWrite(fd, data, dataSize);
if (ret < 0) {
pthread_mutex_unlock(writeMutexHook);
return ret;
}
pthread_mutex_unlock(writeMutexHook);
return 0;
}
static int
sendResponse (Parcel &p, RIL_SOCKET_ID socket_id) {
printResponse;
return sendResponseRaw(p.data(), p.dataSize(), socket_id);
}
/** response is an int* pointing to an array of ints */
static int
responseInts(Parcel &p, void *response, size_t responselen) {
int numInts;
if (response == NULL && responselen != 0) {
RLOGE("invalid response: NULL");
return RIL_ERRNO_INVALID_RESPONSE;
}
if (responselen % sizeof(int) != 0) {
RLOGE("responseInts: invalid response length %d expected multiple of %d\n",
(int)responselen, (int)sizeof(int));
return RIL_ERRNO_INVALID_RESPONSE;
}
int *p_int = (int *) response;
numInts = responselen / sizeof(int);
p.writeInt32 (numInts);
/* each int*/
startResponse;
for (int i = 0 ; i < numInts ; i++) {
appendPrintBuf("%s%d,", printBuf, p_int[i]);
p.writeInt32(p_int[i]);
}
removeLastChar;
closeResponse;
return 0;
}
/** response is a char **, pointing to an array of char *'s
The parcel will begin with the version */
static int responseStringsWithVersion(int version, Parcel &p, void *response, size_t responselen) {
p.writeInt32(version);
return responseStrings(p, response, responselen);
}
/** response is a char **, pointing to an array of char *'s */
static int responseStrings(Parcel &p, void *response, size_t responselen) {
int numStrings;
if (response == NULL && responselen != 0) {
RLOGE("invalid response: NULL");
return RIL_ERRNO_INVALID_RESPONSE;
}
if (responselen % sizeof(char *) != 0) {
RLOGE("responseStrings: invalid response length %d expected multiple of %d\n",
(int)responselen, (int)sizeof(char *));
return RIL_ERRNO_INVALID_RESPONSE;
}
if (response == NULL) {
p.writeInt32 (0);
} else {
char **p_cur = (char **) response;
numStrings = responselen / sizeof(char *);
p.writeInt32 (numStrings);
/* each string*/
startResponse;
for (int i = 0 ; i < numStrings ; i++) {
appendPrintBuf("%s%s,", printBuf, (char*)p_cur[i]);
writeStringToParcel (p, p_cur[i]);
}
removeLastChar;
closeResponse;
}
return 0;
}
/**
* NULL strings are accepted
* FIXME currently ignores responselen
*/
static int responseString(Parcel &p, void *response, size_t responselen) {
/* one string only */
startResponse;
appendPrintBuf("%s%s", printBuf, (char*)response);
closeResponse;
writeStringToParcel(p, (const char *)response);
return 0;
}
static int responseVoid(Parcel &p, void *response, size_t responselen) {
startResponse;
removeLastChar;
return 0;
}
static int responseCallList(Parcel &p, void *response, size_t responselen) {
int num;
if (response == NULL && responselen != 0) {
RLOGE("invalid response: NULL");
return RIL_ERRNO_INVALID_RESPONSE;
}
if (responselen % sizeof (RIL_Call *) != 0) {
RLOGE("responseCallList: invalid response length %d expected multiple of %d\n",
(int)responselen, (int)sizeof (RIL_Call *));
return RIL_ERRNO_INVALID_RESPONSE;
}
startResponse;
/* number of call info's */
num = responselen / sizeof(RIL_Call *);
p.writeInt32(num);
for (int i = 0 ; i < num ; i++) {
RIL_Call *p_cur = ((RIL_Call **) response)[i];
/* each call info */
p.writeInt32(p_cur->state);
p.writeInt32(p_cur->index);
p.writeInt32(p_cur->toa);
p.writeInt32(p_cur->isMpty);
p.writeInt32(p_cur->isMT);
p.writeInt32(p_cur->als);
p.writeInt32(p_cur->isVoice);
p.writeInt32(p_cur->isVoicePrivacy);
writeStringToParcel(p, p_cur->number);
p.writeInt32(p_cur->numberPresentation);
writeStringToParcel(p, p_cur->name);
p.writeInt32(p_cur->namePresentation);
// Remove when partners upgrade to version 3
if ((s_callbacks.version < 3) || (p_cur->uusInfo == NULL || p_cur->uusInfo->uusData == NULL)) {
p.writeInt32(0); /* UUS Information is absent */
} else {
RIL_UUS_Info *uusInfo = p_cur->uusInfo;
p.writeInt32(1); /* UUS Information is present */
p.writeInt32(uusInfo->uusType);
p.writeInt32(uusInfo->uusDcs);
p.writeInt32(uusInfo->uusLength);
p.write(uusInfo->uusData, uusInfo->uusLength);
}
appendPrintBuf("%s[id=%d,%s,toa=%d,",
printBuf,
p_cur->index,
callStateToString(p_cur->state),
p_cur->toa);
appendPrintBuf("%s%s,%s,als=%d,%s,%s,",
printBuf,
(p_cur->isMpty)?"conf":"norm",
(p_cur->isMT)?"mt":"mo",
p_cur->als,
(p_cur->isVoice)?"voc":"nonvoc",
(p_cur->isVoicePrivacy)?"evp":"noevp");
appendPrintBuf("%s%s,cli=%d,name='%s',%d]",
printBuf,
p_cur->number,
p_cur->numberPresentation,
p_cur->name,
p_cur->namePresentation);
}
removeLastChar;
closeResponse;
return 0;
}
static int responseSMS(Parcel &p, void *response, size_t responselen) {
if (response == NULL) {
RLOGE("invalid response: NULL");
return RIL_ERRNO_INVALID_RESPONSE;
}
if (responselen != sizeof (RIL_SMS_Response) ) {
RLOGE("invalid response length %d expected %d",
(int)responselen, (int)sizeof (RIL_SMS_Response));
return RIL_ERRNO_INVALID_RESPONSE;
}
RIL_SMS_Response *p_cur = (RIL_SMS_Response *) response;
p.writeInt32(p_cur->messageRef);
writeStringToParcel(p, p_cur->ackPDU);
p.writeInt32(p_cur->errorCode);
startResponse;
appendPrintBuf("%s%d,%s,%d", printBuf, p_cur->messageRef,
(char*)p_cur->ackPDU, p_cur->errorCode);
closeResponse;
return 0;
}
static int responseDataCallListV4(Parcel &p, void *response, size_t responselen)
{
if (response == NULL && responselen != 0) {
RLOGE("invalid response: NULL");
return RIL_ERRNO_INVALID_RESPONSE;
}
if (responselen % sizeof(RIL_Data_Call_Response_v4) != 0) {
RLOGE("responseDataCallListV4: invalid response length %d expected multiple of %d",
(int)responselen, (int)sizeof(RIL_Data_Call_Response_v4));
return RIL_ERRNO_INVALID_RESPONSE;
}
// Write version
p.writeInt32(4);
int num = responselen / sizeof(RIL_Data_Call_Response_v4);
p.writeInt32(num);
RIL_Data_Call_Response_v4 *p_cur = (RIL_Data_Call_Response_v4 *) response;
startResponse;
int i;
for (i = 0; i < num; i++) {
p.writeInt32(p_cur[i].cid);
p.writeInt32(p_cur[i].active);
writeStringToParcel(p, p_cur[i].type);
// apn is not used, so don't send.
writeStringToParcel(p, p_cur[i].address);
appendPrintBuf("%s[cid=%d,%s,%s,%s],", printBuf,
p_cur[i].cid,
(p_cur[i].active==0)?"down":"up",
(char*)p_cur[i].type,
(char*)p_cur[i].address);
}
removeLastChar;
closeResponse;
return 0;
}
static int responseDataCallListV6(Parcel &p, void *response, size_t responselen)
{
if (response == NULL && responselen != 0) {
RLOGE("invalid response: NULL");
return RIL_ERRNO_INVALID_RESPONSE;
}
if (responselen % sizeof(RIL_Data_Call_Response_v6) != 0) {
RLOGE("responseDataCallListV6: invalid response length %d expected multiple of %d",
(int)responselen, (int)sizeof(RIL_Data_Call_Response_v6));
return RIL_ERRNO_INVALID_RESPONSE;
}
// Write version
p.writeInt32(6);
int num = responselen / sizeof(RIL_Data_Call_Response_v6);
p.writeInt32(num);
RIL_Data_Call_Response_v6 *p_cur = (RIL_Data_Call_Response_v6 *) response;
startResponse;
int i;
for (i = 0; i < num; i++) {
p.writeInt32((int)p_cur[i].status);
p.writeInt32(p_cur[i].suggestedRetryTime);
p.writeInt32(p_cur[i].cid);
p.writeInt32(p_cur[i].active);
writeStringToParcel(p, p_cur[i].type);
writeStringToParcel(p, p_cur[i].ifname);
writeStringToParcel(p, p_cur[i].addresses);
writeStringToParcel(p, p_cur[i].dnses);
writeStringToParcel(p, p_cur[i].gateways);
appendPrintBuf("%s[status=%d,retry=%d,cid=%d,%s,%s,%s,%s,%s,%s],", printBuf,
p_cur[i].status,
p_cur[i].suggestedRetryTime,
p_cur[i].cid,
(p_cur[i].active==0)?"down":"up",
(char*)p_cur[i].type,
(char*)p_cur[i].ifname,
(char*)p_cur[i].addresses,
(char*)p_cur[i].dnses,
(char*)p_cur[i].gateways);
}
removeLastChar;
closeResponse;
return 0;
}
static int responseDataCallList(Parcel &p, void *response, size_t responselen)
{
if (s_callbacks.version < 5) {
RLOGD("responseDataCallList: v4");
return responseDataCallListV4(p, response, responselen);
} else {
if (response == NULL && responselen != 0) {
RLOGE("invalid response: NULL");
return RIL_ERRNO_INVALID_RESPONSE;
}
// Support v6 or v9 with new rils
if (responselen % sizeof(RIL_Data_Call_Response_v6) == 0) {
RLOGD("responseDataCallList: v6");
return responseDataCallListV6(p, response, responselen);
}
if (responselen % sizeof(RIL_Data_Call_Response_v9) != 0) {
RLOGE("responseDataCallList: invalid response length %d expected multiple of %d",
(int)responselen, (int)sizeof(RIL_Data_Call_Response_v9));
return RIL_ERRNO_INVALID_RESPONSE;
}
// Write version
p.writeInt32(10);
int num = responselen / sizeof(RIL_Data_Call_Response_v9);
p.writeInt32(num);
RIL_Data_Call_Response_v9 *p_cur = (RIL_Data_Call_Response_v9 *) response;
startResponse;
int i;
for (i = 0; i < num; i++) {
p.writeInt32((int)p_cur[i].status);
p.writeInt32(p_cur[i].suggestedRetryTime);
p.writeInt32(p_cur[i].cid);
p.writeInt32(p_cur[i].active);
writeStringToParcel(p, p_cur[i].type);
writeStringToParcel(p, p_cur[i].ifname);
writeStringToParcel(p, p_cur[i].addresses);
writeStringToParcel(p, p_cur[i].dnses);
writeStringToParcel(p, p_cur[i].gateways);
writeStringToParcel(p, p_cur[i].pcscf);
appendPrintBuf("%s[status=%d,retry=%d,cid=%d,%s,%s,%s,%s,%s,%s,%s],", printBuf,
p_cur[i].status,
p_cur[i].suggestedRetryTime,
p_cur[i].cid,
(p_cur[i].active==0)?"down":"up",
(char*)p_cur[i].type,
(char*)p_cur[i].ifname,
(char*)p_cur[i].addresses,
(char*)p_cur[i].dnses,
(char*)p_cur[i].gateways,
(char*)p_cur[i].pcscf);
}
removeLastChar;
closeResponse;
}
return 0;
}
static int responseSetupDataCall(Parcel &p, void *response, size_t responselen)
{
if (s_callbacks.version < 5) {
return responseStringsWithVersion(s_callbacks.version, p, response, responselen);
} else {
return responseDataCallList(p, response, responselen);
}
}
static int responseRaw(Parcel &p, void *response, size_t responselen) {
if (response == NULL && responselen != 0) {
RLOGE("invalid response: NULL with responselen != 0");
return RIL_ERRNO_INVALID_RESPONSE;
}
// The java code reads -1 size as null byte array
if (response == NULL) {
p.writeInt32(-1);
} else {
p.writeInt32(responselen);
p.write(response, responselen);
}
return 0;
}
static int responseSIM_IO(Parcel &p, void *response, size_t responselen) {
if (response == NULL) {
RLOGE("invalid response: NULL");
return RIL_ERRNO_INVALID_RESPONSE;
}
if (responselen != sizeof (RIL_SIM_IO_Response) ) {
RLOGE("invalid response length was %d expected %d",
(int)responselen, (int)sizeof (RIL_SIM_IO_Response));
return RIL_ERRNO_INVALID_RESPONSE;
}
RIL_SIM_IO_Response *p_cur = (RIL_SIM_IO_Response *) response;
p.writeInt32(p_cur->sw1);
p.writeInt32(p_cur->sw2);
writeStringToParcel(p, p_cur->simResponse);
startResponse;
appendPrintBuf("%ssw1=0x%X,sw2=0x%X,%s", printBuf, p_cur->sw1, p_cur->sw2,
(char*)p_cur->simResponse);
closeResponse;
return 0;
}
static int responseCallForwards(Parcel &p, void *response, size_t responselen) {
int num;
if (response == NULL && responselen != 0) {
RLOGE("invalid response: NULL");
return RIL_ERRNO_INVALID_RESPONSE;
}
if (responselen % sizeof(RIL_CallForwardInfo *) != 0) {
RLOGE("responseCallForwards: invalid response length %d expected multiple of %d",
(int)responselen, (int)sizeof(RIL_CallForwardInfo *));
return RIL_ERRNO_INVALID_RESPONSE;
}
/* number of call info's */
num = responselen / sizeof(RIL_CallForwardInfo *);
p.writeInt32(num);
startResponse;
for (int i = 0 ; i < num ; i++) {
RIL_CallForwardInfo *p_cur = ((RIL_CallForwardInfo **) response)[i];
p.writeInt32(p_cur->status);
p.writeInt32(p_cur->reason);
p.writeInt32(p_cur->serviceClass);
p.writeInt32(p_cur->toa);
writeStringToParcel(p, p_cur->number);
p.writeInt32(p_cur->timeSeconds);
appendPrintBuf("%s[%s,reason=%d,cls=%d,toa=%d,%s,tout=%d],", printBuf,
(p_cur->status==1)?"enable":"disable",
p_cur->reason, p_cur->serviceClass, p_cur->toa,
(char*)p_cur->number,
p_cur->timeSeconds);
}
removeLastChar;
closeResponse;
return 0;
}
static int responseSsn(Parcel &p, void *response, size_t responselen) {
if (response == NULL) {
RLOGE("invalid response: NULL");
return RIL_ERRNO_INVALID_RESPONSE;
}
if (responselen != sizeof(RIL_SuppSvcNotification)) {
RLOGE("invalid response length was %d expected %d",
(int)responselen, (int)sizeof (RIL_SuppSvcNotification));
return RIL_ERRNO_INVALID_RESPONSE;
}
RIL_SuppSvcNotification *p_cur = (RIL_SuppSvcNotification *) response;
p.writeInt32(p_cur->notificationType);
p.writeInt32(p_cur->code);
p.writeInt32(p_cur->index);
p.writeInt32(p_cur->type);
writeStringToParcel(p, p_cur->number);
startResponse;
appendPrintBuf("%s%s,code=%d,id=%d,type=%d,%s", printBuf,
(p_cur->notificationType==0)?"mo":"mt",
p_cur->code, p_cur->index, p_cur->type,
(char*)p_cur->number);
closeResponse;
return 0;
}
static int responseCellList(Parcel &p, void *response, size_t responselen) {
int num;
if (response == NULL && responselen != 0) {
RLOGE("invalid response: NULL");
return RIL_ERRNO_INVALID_RESPONSE;
}
if (responselen % sizeof (RIL_NeighboringCell *) != 0) {
RLOGE("responseCellList: invalid response length %d expected multiple of %d\n",
(int)responselen, (int)sizeof (RIL_NeighboringCell *));
return RIL_ERRNO_INVALID_RESPONSE;
}
startResponse;
/* number of records */
num = responselen / sizeof(RIL_NeighboringCell *);
p.writeInt32(num);
for (int i = 0 ; i < num ; i++) {
RIL_NeighboringCell *p_cur = ((RIL_NeighboringCell **) response)[i];
p.writeInt32(p_cur->rssi);
writeStringToParcel (p, p_cur->cid);
appendPrintBuf("%s[cid=%s,rssi=%d],", printBuf,
p_cur->cid, p_cur->rssi);
}
removeLastChar;
closeResponse;
return 0;
}
/**
* Marshall the signalInfoRecord into the parcel if it exists.
*/
static void marshallSignalInfoRecord(Parcel &p,
RIL_CDMA_SignalInfoRecord &p_signalInfoRecord) {
p.writeInt32(p_signalInfoRecord.isPresent);
p.writeInt32(p_signalInfoRecord.signalType);
p.writeInt32(p_signalInfoRecord.alertPitch);
p.writeInt32(p_signalInfoRecord.signal);
}
static int responseCdmaInformationRecords(Parcel &p,
void *response, size_t responselen) {
int num;
char* string8 = NULL;
int buffer_lenght;
RIL_CDMA_InformationRecord *infoRec;
if (response == NULL && responselen != 0) {
RLOGE("invalid response: NULL");
return RIL_ERRNO_INVALID_RESPONSE;
}
if (responselen != sizeof (RIL_CDMA_InformationRecords)) {
RLOGE("responseCdmaInformationRecords: invalid response length %d expected multiple of %d\n",
(int)responselen, (int)sizeof (RIL_CDMA_InformationRecords *));
return RIL_ERRNO_INVALID_RESPONSE;
}
RIL_CDMA_InformationRecords *p_cur =
(RIL_CDMA_InformationRecords *) response;
num = MIN(p_cur->numberOfInfoRecs, RIL_CDMA_MAX_NUMBER_OF_INFO_RECS);
startResponse;
p.writeInt32(num);
for (int i = 0 ; i < num ; i++) {
infoRec = &p_cur->infoRec[i];
p.writeInt32(infoRec->name);
switch (infoRec->name) {
case RIL_CDMA_DISPLAY_INFO_REC:
case RIL_CDMA_EXTENDED_DISPLAY_INFO_REC:
if (infoRec->rec.display.alpha_len >
CDMA_ALPHA_INFO_BUFFER_LENGTH) {
RLOGE("invalid display info response length %d \
expected not more than %d\n",
(int)infoRec->rec.display.alpha_len,
CDMA_ALPHA_INFO_BUFFER_LENGTH);
return RIL_ERRNO_INVALID_RESPONSE;
}
string8 = (char*) malloc((infoRec->rec.display.alpha_len + 1)
* sizeof(char) );
for (int i = 0 ; i < infoRec->rec.display.alpha_len ; i++) {
string8[i] = infoRec->rec.display.alpha_buf[i];
}
string8[(int)infoRec->rec.display.alpha_len] = '\0';
writeStringToParcel(p, (const char*)string8);
free(string8);
string8 = NULL;
break;
case RIL_CDMA_CALLED_PARTY_NUMBER_INFO_REC:
case RIL_CDMA_CALLING_PARTY_NUMBER_INFO_REC:
case RIL_CDMA_CONNECTED_NUMBER_INFO_REC:
if (infoRec->rec.number.len > CDMA_NUMBER_INFO_BUFFER_LENGTH) {
RLOGE("invalid display info response length %d \
expected not more than %d\n",
(int)infoRec->rec.number.len,
CDMA_NUMBER_INFO_BUFFER_LENGTH);
return RIL_ERRNO_INVALID_RESPONSE;
}
string8 = (char*) malloc((infoRec->rec.number.len + 1)
* sizeof(char) );
for (int i = 0 ; i < infoRec->rec.number.len; i++) {
string8[i] = infoRec->rec.number.buf[i];
}
string8[(int)infoRec->rec.number.len] = '\0';
writeStringToParcel(p, (const char*)string8);
free(string8);
string8 = NULL;
p.writeInt32(infoRec->rec.number.number_type);
p.writeInt32(infoRec->rec.number.number_plan);
p.writeInt32(infoRec->rec.number.pi);
p.writeInt32(infoRec->rec.number.si);
break;
case RIL_CDMA_SIGNAL_INFO_REC:
p.writeInt32(infoRec->rec.signal.isPresent);
p.writeInt32(infoRec->rec.signal.signalType);
p.writeInt32(infoRec->rec.signal.alertPitch);
p.writeInt32(infoRec->rec.signal.signal);
appendPrintBuf("%sisPresent=%X, signalType=%X, \
alertPitch=%X, signal=%X, ",
printBuf, (int)infoRec->rec.signal.isPresent,
(int)infoRec->rec.signal.signalType,
(int)infoRec->rec.signal.alertPitch,
(int)infoRec->rec.signal.signal);
removeLastChar;
break;
case RIL_CDMA_REDIRECTING_NUMBER_INFO_REC:
if (infoRec->rec.redir.redirectingNumber.len >
CDMA_NUMBER_INFO_BUFFER_LENGTH) {
RLOGE("invalid display info response length %d \
expected not more than %d\n",
(int)infoRec->rec.redir.redirectingNumber.len,
CDMA_NUMBER_INFO_BUFFER_LENGTH);
return RIL_ERRNO_INVALID_RESPONSE;
}
string8 = (char*) malloc((infoRec->rec.redir.redirectingNumber
.len + 1) * sizeof(char) );
for (int i = 0;
i < infoRec->rec.redir.redirectingNumber.len;
i++) {
string8[i] = infoRec->rec.redir.redirectingNumber.buf[i];
}
string8[(int)infoRec->rec.redir.redirectingNumber.len] = '\0';
writeStringToParcel(p, (const char*)string8);
free(string8);
string8 = NULL;
p.writeInt32(infoRec->rec.redir.redirectingNumber.number_type);
p.writeInt32(infoRec->rec.redir.redirectingNumber.number_plan);
p.writeInt32(infoRec->rec.redir.redirectingNumber.pi);
p.writeInt32(infoRec->rec.redir.redirectingNumber.si);
p.writeInt32(infoRec->rec.redir.redirectingReason);
break;
case RIL_CDMA_LINE_CONTROL_INFO_REC:
p.writeInt32(infoRec->rec.lineCtrl.lineCtrlPolarityIncluded);
p.writeInt32(infoRec->rec.lineCtrl.lineCtrlToggle);
p.writeInt32(infoRec->rec.lineCtrl.lineCtrlReverse);
p.writeInt32(infoRec->rec.lineCtrl.lineCtrlPowerDenial);
appendPrintBuf("%slineCtrlPolarityIncluded=%d, \
lineCtrlToggle=%d, lineCtrlReverse=%d, \
lineCtrlPowerDenial=%d, ", printBuf,
(int)infoRec->rec.lineCtrl.lineCtrlPolarityIncluded,
(int)infoRec->rec.lineCtrl.lineCtrlToggle,
(int)infoRec->rec.lineCtrl.lineCtrlReverse,
(int)infoRec->rec.lineCtrl.lineCtrlPowerDenial);
removeLastChar;
break;
case RIL_CDMA_T53_CLIR_INFO_REC:
p.writeInt32((int)(infoRec->rec.clir.cause));
appendPrintBuf("%scause%d", printBuf, infoRec->rec.clir.cause);
removeLastChar;
break;
case RIL_CDMA_T53_AUDIO_CONTROL_INFO_REC:
p.writeInt32(infoRec->rec.audioCtrl.upLink);
p.writeInt32(infoRec->rec.audioCtrl.downLink);
appendPrintBuf("%supLink=%d, downLink=%d, ", printBuf,
infoRec->rec.audioCtrl.upLink,
infoRec->rec.audioCtrl.downLink);
removeLastChar;
break;
case RIL_CDMA_T53_RELEASE_INFO_REC:
// TODO(Moto): See David Krause, he has the answer:)
RLOGE("RIL_CDMA_T53_RELEASE_INFO_REC: return INVALID_RESPONSE");
return RIL_ERRNO_INVALID_RESPONSE;
default:
RLOGE("Incorrect name value");
return RIL_ERRNO_INVALID_RESPONSE;
}
}
closeResponse;
return 0;
}
static int responseRilSignalStrength(Parcel &p,
void *response, size_t responselen) {
if (response == NULL && responselen != 0) {
RLOGE("invalid response: NULL");
return RIL_ERRNO_INVALID_RESPONSE;
}
if (responselen >= sizeof (RIL_SignalStrength_v5)) {
RIL_SignalStrength_v10 *p_cur = ((RIL_SignalStrength_v10 *) response);
p.writeInt32(p_cur->GW_SignalStrength.signalStrength);
p.writeInt32(p_cur->GW_SignalStrength.bitErrorRate);
p.writeInt32(p_cur->CDMA_SignalStrength.dbm);
p.writeInt32(p_cur->CDMA_SignalStrength.ecio);
p.writeInt32(p_cur->EVDO_SignalStrength.dbm);
p.writeInt32(p_cur->EVDO_SignalStrength.ecio);
p.writeInt32(p_cur->EVDO_SignalStrength.signalNoiseRatio);
if (responselen >= sizeof (RIL_SignalStrength_v6)) {
/*
* Fixup LTE for backwards compatibility
*/
if (s_callbacks.version <= 6) {
// signalStrength: -1 -> 99
if (p_cur->LTE_SignalStrength.signalStrength == -1) {
p_cur->LTE_SignalStrength.signalStrength = 99;
}
// rsrp: -1 -> INT_MAX all other negative value to positive.
// So remap here
if (p_cur->LTE_SignalStrength.rsrp == -1) {
p_cur->LTE_SignalStrength.rsrp = INT_MAX;
} else if (p_cur->LTE_SignalStrength.rsrp < -1) {
p_cur->LTE_SignalStrength.rsrp = -p_cur->LTE_SignalStrength.rsrp;
}
// rsrq: -1 -> INT_MAX
if (p_cur->LTE_SignalStrength.rsrq == -1) {
p_cur->LTE_SignalStrength.rsrq = INT_MAX;
}
// Not remapping rssnr is already using INT_MAX
// cqi: -1 -> INT_MAX
if (p_cur->LTE_SignalStrength.cqi == -1) {
p_cur->LTE_SignalStrength.cqi = INT_MAX;
}
}
p.writeInt32(p_cur->LTE_SignalStrength.signalStrength);
p.writeInt32(p_cur->LTE_SignalStrength.rsrp);
p.writeInt32(p_cur->LTE_SignalStrength.rsrq);
p.writeInt32(p_cur->LTE_SignalStrength.rssnr);
p.writeInt32(p_cur->LTE_SignalStrength.cqi);
if (responselen >= sizeof (RIL_SignalStrength_v10)) {
p.writeInt32(p_cur->TD_SCDMA_SignalStrength.rscp);
} else {
p.writeInt32(INT_MAX);
}
} else {
p.writeInt32(99);
p.writeInt32(INT_MAX);
p.writeInt32(INT_MAX);
p.writeInt32(INT_MAX);
p.writeInt32(INT_MAX);
p.writeInt32(INT_MAX);
}
startResponse;
appendPrintBuf("%s[signalStrength=%d,bitErrorRate=%d,\
CDMA_SS.dbm=%d,CDMA_SSecio=%d,\
EVDO_SS.dbm=%d,EVDO_SS.ecio=%d,\
EVDO_SS.signalNoiseRatio=%d,\
LTE_SS.signalStrength=%d,LTE_SS.rsrp=%d,LTE_SS.rsrq=%d,\
LTE_SS.rssnr=%d,LTE_SS.cqi=%d,TDSCDMA_SS.rscp=%d]",
printBuf,
p_cur->GW_SignalStrength.signalStrength,
p_cur->GW_SignalStrength.bitErrorRate,
p_cur->CDMA_SignalStrength.dbm,
p_cur->CDMA_SignalStrength.ecio,
p_cur->EVDO_SignalStrength.dbm,
p_cur->EVDO_SignalStrength.ecio,
p_cur->EVDO_SignalStrength.signalNoiseRatio,
p_cur->LTE_SignalStrength.signalStrength,
p_cur->LTE_SignalStrength.rsrp,
p_cur->LTE_SignalStrength.rsrq,
p_cur->LTE_SignalStrength.rssnr,
p_cur->LTE_SignalStrength.cqi,
p_cur->TD_SCDMA_SignalStrength.rscp);
closeResponse;
} else {
RLOGE("invalid response length");
return RIL_ERRNO_INVALID_RESPONSE;
}
return 0;
}
static int responseCallRing(Parcel &p, void *response, size_t responselen) {
if ((response == NULL) || (responselen == 0)) {
return responseVoid(p, response, responselen);
} else {
return responseCdmaSignalInfoRecord(p, response, responselen);
}
}
static int responseCdmaSignalInfoRecord(Parcel &p, void *response, size_t responselen) {
if (response == NULL || responselen == 0) {
RLOGE("invalid response: NULL");
return RIL_ERRNO_INVALID_RESPONSE;
}
if (responselen != sizeof (RIL_CDMA_SignalInfoRecord)) {
RLOGE("invalid response length %d expected sizeof (RIL_CDMA_SignalInfoRecord) of %d\n",
(int)responselen, (int)sizeof (RIL_CDMA_SignalInfoRecord));
return RIL_ERRNO_INVALID_RESPONSE;
}
startResponse;
RIL_CDMA_SignalInfoRecord *p_cur = ((RIL_CDMA_SignalInfoRecord *) response);
marshallSignalInfoRecord(p, *p_cur);
appendPrintBuf("%s[isPresent=%d,signalType=%d,alertPitch=%d\
signal=%d]",
printBuf,
p_cur->isPresent,
p_cur->signalType,
p_cur->alertPitch,
p_cur->signal);
closeResponse;
return 0;
}
static int responseCdmaCallWaiting(Parcel &p, void *response,
size_t responselen) {
if (response == NULL && responselen != 0) {
RLOGE("invalid response: NULL");
return RIL_ERRNO_INVALID_RESPONSE;
}
if (responselen < sizeof(RIL_CDMA_CallWaiting_v6)) {
RLOGW("Upgrade to ril version %d\n", RIL_VERSION);
}
RIL_CDMA_CallWaiting_v6 *p_cur = ((RIL_CDMA_CallWaiting_v6 *) response);
writeStringToParcel(p, p_cur->number);
p.writeInt32(p_cur->numberPresentation);
writeStringToParcel(p, p_cur->name);
marshallSignalInfoRecord(p, p_cur->signalInfoRecord);
if (responselen >= sizeof(RIL_CDMA_CallWaiting_v6)) {
p.writeInt32(p_cur->number_type);
p.writeInt32(p_cur->number_plan);
} else {
p.writeInt32(0);
p.writeInt32(0);
}
startResponse;
appendPrintBuf("%snumber=%s,numberPresentation=%d, name=%s,\
signalInfoRecord[isPresent=%d,signalType=%d,alertPitch=%d\
signal=%d,number_type=%d,number_plan=%d]",
printBuf,
p_cur->number,
p_cur->numberPresentation,
p_cur->name,
p_cur->signalInfoRecord.isPresent,
p_cur->signalInfoRecord.signalType,
p_cur->signalInfoRecord.alertPitch,
p_cur->signalInfoRecord.signal,
p_cur->number_type,
p_cur->number_plan);
closeResponse;
return 0;
}
static int responseSimRefresh(Parcel &p, void *response, size_t responselen) {
if (response == NULL && responselen != 0) {
RLOGE("responseSimRefresh: invalid response: NULL");
return RIL_ERRNO_INVALID_RESPONSE;
}
startResponse;
if (s_callbacks.version == 7) {
RIL_SimRefreshResponse_v7 *p_cur = ((RIL_SimRefreshResponse_v7 *) response);
p.writeInt32(p_cur->result);
p.writeInt32(p_cur->ef_id);
writeStringToParcel(p, p_cur->aid);
appendPrintBuf("%sresult=%d, ef_id=%d, aid=%s",
printBuf,
p_cur->result,
p_cur->ef_id,
p_cur->aid);
} else {
int *p_cur = ((int *) response);
p.writeInt32(p_cur[0]);
p.writeInt32(p_cur[1]);
writeStringToParcel(p, NULL);
appendPrintBuf("%sresult=%d, ef_id=%d",
printBuf,
p_cur[0],
p_cur[1]);
}
closeResponse;
return 0;
}
static int responseCellInfoList(Parcel &p, void *response, size_t responselen)
{
if (response == NULL && responselen != 0) {
RLOGE("invalid response: NULL");
return RIL_ERRNO_INVALID_RESPONSE;
}
if (responselen % sizeof(RIL_CellInfo) != 0) {
RLOGE("responseCellInfoList: invalid response length %d expected multiple of %d",
(int)responselen, (int)sizeof(RIL_CellInfo));
return RIL_ERRNO_INVALID_RESPONSE;
}
int num = responselen / sizeof(RIL_CellInfo);
p.writeInt32(num);
RIL_CellInfo *p_cur = (RIL_CellInfo *) response;
startResponse;
int i;
for (i = 0; i < num; i++) {
appendPrintBuf("%s[%d: type=%d,registered=%d,timeStampType=%d,timeStamp=%lld", printBuf, i,
p_cur->cellInfoType, p_cur->registered, p_cur->timeStampType, p_cur->timeStamp);
p.writeInt32((int)p_cur->cellInfoType);
p.writeInt32(p_cur->registered);
p.writeInt32(p_cur->timeStampType);
p.writeInt64(p_cur->timeStamp);
switch(p_cur->cellInfoType) {
case RIL_CELL_INFO_TYPE_GSM: {
appendPrintBuf("%s GSM id: mcc=%d,mnc=%d,lac=%d,cid=%d,", printBuf,
p_cur->CellInfo.gsm.cellIdentityGsm.mcc,
p_cur->CellInfo.gsm.cellIdentityGsm.mnc,
p_cur->CellInfo.gsm.cellIdentityGsm.lac,
p_cur->CellInfo.gsm.cellIdentityGsm.cid);
appendPrintBuf("%s gsmSS: ss=%d,ber=%d],", printBuf,
p_cur->CellInfo.gsm.signalStrengthGsm.signalStrength,
p_cur->CellInfo.gsm.signalStrengthGsm.bitErrorRate);
p.writeInt32(p_cur->CellInfo.gsm.cellIdentityGsm.mcc);
p.writeInt32(p_cur->CellInfo.gsm.cellIdentityGsm.mnc);
p.writeInt32(p_cur->CellInfo.gsm.cellIdentityGsm.lac);
p.writeInt32(p_cur->CellInfo.gsm.cellIdentityGsm.cid);
p.writeInt32(p_cur->CellInfo.gsm.signalStrengthGsm.signalStrength);
p.writeInt32(p_cur->CellInfo.gsm.signalStrengthGsm.bitErrorRate);
break;
}
case RIL_CELL_INFO_TYPE_WCDMA: {
appendPrintBuf("%s WCDMA id: mcc=%d,mnc=%d,lac=%d,cid=%d,psc=%d,", printBuf,
p_cur->CellInfo.wcdma.cellIdentityWcdma.mcc,
p_cur->CellInfo.wcdma.cellIdentityWcdma.mnc,
p_cur->CellInfo.wcdma.cellIdentityWcdma.lac,
p_cur->CellInfo.wcdma.cellIdentityWcdma.cid,
p_cur->CellInfo.wcdma.cellIdentityWcdma.psc);
appendPrintBuf("%s wcdmaSS: ss=%d,ber=%d],", printBuf,
p_cur->CellInfo.wcdma.signalStrengthWcdma.signalStrength,
p_cur->CellInfo.wcdma.signalStrengthWcdma.bitErrorRate);
p.writeInt32(p_cur->CellInfo.wcdma.cellIdentityWcdma.mcc);
p.writeInt32(p_cur->CellInfo.wcdma.cellIdentityWcdma.mnc);
p.writeInt32(p_cur->CellInfo.wcdma.cellIdentityWcdma.lac);
p.writeInt32(p_cur->CellInfo.wcdma.cellIdentityWcdma.cid);
p.writeInt32(p_cur->CellInfo.wcdma.cellIdentityWcdma.psc);
p.writeInt32(p_cur->CellInfo.wcdma.signalStrengthWcdma.signalStrength);
p.writeInt32(p_cur->CellInfo.wcdma.signalStrengthWcdma.bitErrorRate);
break;
}
case RIL_CELL_INFO_TYPE_CDMA: {
appendPrintBuf("%s CDMA id: nId=%d,sId=%d,bsId=%d,long=%d,lat=%d", printBuf,
p_cur->CellInfo.cdma.cellIdentityCdma.networkId,
p_cur->CellInfo.cdma.cellIdentityCdma.systemId,
p_cur->CellInfo.cdma.cellIdentityCdma.basestationId,
p_cur->CellInfo.cdma.cellIdentityCdma.longitude,
p_cur->CellInfo.cdma.cellIdentityCdma.latitude);
p.writeInt32(p_cur->CellInfo.cdma.cellIdentityCdma.networkId);
p.writeInt32(p_cur->CellInfo.cdma.cellIdentityCdma.systemId);
p.writeInt32(p_cur->CellInfo.cdma.cellIdentityCdma.basestationId);
p.writeInt32(p_cur->CellInfo.cdma.cellIdentityCdma.longitude);
p.writeInt32(p_cur->CellInfo.cdma.cellIdentityCdma.latitude);
appendPrintBuf("%s cdmaSS: dbm=%d ecio=%d evdoSS: dbm=%d,ecio=%d,snr=%d", printBuf,
p_cur->CellInfo.cdma.signalStrengthCdma.dbm,
p_cur->CellInfo.cdma.signalStrengthCdma.ecio,
p_cur->CellInfo.cdma.signalStrengthEvdo.dbm,
p_cur->CellInfo.cdma.signalStrengthEvdo.ecio,
p_cur->CellInfo.cdma.signalStrengthEvdo.signalNoiseRatio);
p.writeInt32(p_cur->CellInfo.cdma.signalStrengthCdma.dbm);
p.writeInt32(p_cur->CellInfo.cdma.signalStrengthCdma.ecio);
p.writeInt32(p_cur->CellInfo.cdma.signalStrengthEvdo.dbm);
p.writeInt32(p_cur->CellInfo.cdma.signalStrengthEvdo.ecio);
p.writeInt32(p_cur->CellInfo.cdma.signalStrengthEvdo.signalNoiseRatio);
break;
}
case RIL_CELL_INFO_TYPE_LTE: {
appendPrintBuf("%s LTE id: mcc=%d,mnc=%d,ci=%d,pci=%d,tac=%d", printBuf,
p_cur->CellInfo.lte.cellIdentityLte.mcc,
p_cur->CellInfo.lte.cellIdentityLte.mnc,
p_cur->CellInfo.lte.cellIdentityLte.ci,
p_cur->CellInfo.lte.cellIdentityLte.pci,
p_cur->CellInfo.lte.cellIdentityLte.tac);
p.writeInt32(p_cur->CellInfo.lte.cellIdentityLte.mcc);
p.writeInt32(p_cur->CellInfo.lte.cellIdentityLte.mnc);
p.writeInt32(p_cur->CellInfo.lte.cellIdentityLte.ci);
p.writeInt32(p_cur->CellInfo.lte.cellIdentityLte.pci);
p.writeInt32(p_cur->CellInfo.lte.cellIdentityLte.tac);
appendPrintBuf("%s lteSS: ss=%d,rsrp=%d,rsrq=%d,rssnr=%d,cqi=%d,ta=%d", printBuf,
p_cur->CellInfo.lte.signalStrengthLte.signalStrength,
p_cur->CellInfo.lte.signalStrengthLte.rsrp,
p_cur->CellInfo.lte.signalStrengthLte.rsrq,
p_cur->CellInfo.lte.signalStrengthLte.rssnr,
p_cur->CellInfo.lte.signalStrengthLte.cqi,
p_cur->CellInfo.lte.signalStrengthLte.timingAdvance);
p.writeInt32(p_cur->CellInfo.lte.signalStrengthLte.signalStrength);
p.writeInt32(p_cur->CellInfo.lte.signalStrengthLte.rsrp);
p.writeInt32(p_cur->CellInfo.lte.signalStrengthLte.rsrq);
p.writeInt32(p_cur->CellInfo.lte.signalStrengthLte.rssnr);
p.writeInt32(p_cur->CellInfo.lte.signalStrengthLte.cqi);
p.writeInt32(p_cur->CellInfo.lte.signalStrengthLte.timingAdvance);
break;
}
case RIL_CELL_INFO_TYPE_TD_SCDMA: {
appendPrintBuf("%s TDSCDMA id: mcc=%d,mnc=%d,lac=%d,cid=%d,cpid=%d,", printBuf,
p_cur->CellInfo.tdscdma.cellIdentityTdscdma.mcc,
p_cur->CellInfo.tdscdma.cellIdentityTdscdma.mnc,
p_cur->CellInfo.tdscdma.cellIdentityTdscdma.lac,
p_cur->CellInfo.tdscdma.cellIdentityTdscdma.cid,
p_cur->CellInfo.tdscdma.cellIdentityTdscdma.cpid);
appendPrintBuf("%s tdscdmaSS: rscp=%d],", printBuf,
p_cur->CellInfo.tdscdma.signalStrengthTdscdma.rscp);
p.writeInt32(p_cur->CellInfo.tdscdma.cellIdentityTdscdma.mcc);
p.writeInt32(p_cur->CellInfo.tdscdma.cellIdentityTdscdma.mnc);
p.writeInt32(p_cur->CellInfo.tdscdma.cellIdentityTdscdma.lac);
p.writeInt32(p_cur->CellInfo.tdscdma.cellIdentityTdscdma.cid);
p.writeInt32(p_cur->CellInfo.tdscdma.cellIdentityTdscdma.cpid);
p.writeInt32(p_cur->CellInfo.tdscdma.signalStrengthTdscdma.rscp);
break;
}
}
p_cur += 1;
}
removeLastChar;
closeResponse;
return 0;
}
static int responseHardwareConfig(Parcel &p, void *response, size_t responselen)
{
if (response == NULL && responselen != 0) {
RLOGE("invalid response: NULL");
return RIL_ERRNO_INVALID_RESPONSE;
}
if (responselen % sizeof(RIL_HardwareConfig) != 0) {
RLOGE("responseHardwareConfig: invalid response length %d expected multiple of %d",
(int)responselen, (int)sizeof(RIL_HardwareConfig));
return RIL_ERRNO_INVALID_RESPONSE;
}
int num = responselen / sizeof(RIL_HardwareConfig);
int i;
RIL_HardwareConfig *p_cur = (RIL_HardwareConfig *) response;
p.writeInt32(num);
startResponse;
for (i = 0; i < num; i++) {
switch (p_cur[i].type) {
case RIL_HARDWARE_CONFIG_MODEM: {
writeStringToParcel(p, p_cur[i].uuid);
p.writeInt32((int)p_cur[i].state);
p.writeInt32(p_cur[i].cfg.modem.rat);
p.writeInt32(p_cur[i].cfg.modem.maxVoice);
p.writeInt32(p_cur[i].cfg.modem.maxData);
p.writeInt32(p_cur[i].cfg.modem.maxStandby);
appendPrintBuf("%s modem: uuid=%s,state=%d,rat=%08x,maxV=%d,maxD=%d,maxS=%d", printBuf,
p_cur[i].uuid, (int)p_cur[i].state, p_cur[i].cfg.modem.rat,
p_cur[i].cfg.modem.maxVoice, p_cur[i].cfg.modem.maxData, p_cur[i].cfg.modem.maxStandby);
break;
}
case RIL_HARDWARE_CONFIG_SIM: {
writeStringToParcel(p, p_cur[i].uuid);
p.writeInt32((int)p_cur[i].state);
writeStringToParcel(p, p_cur[i].cfg.sim.modemUuid);
appendPrintBuf("%s sim: uuid=%s,state=%d,modem-uuid=%s", printBuf,
p_cur[i].uuid, (int)p_cur[i].state, p_cur[i].cfg.sim.modemUuid);
break;
}
}
}
removeLastChar;
closeResponse;
return 0;
}
static void triggerEvLoop() {
int ret;
if (!pthread_equal(pthread_self(), s_tid_dispatch)) {
/* trigger event loop to wakeup. No reason to do this,
* if we're in the event loop thread */
do {
ret = write (s_fdWakeupWrite, " ", 1);
} while (ret < 0 && errno == EINTR);
}
}
static void rilEventAddWakeup(struct ril_event *ev) {
ril_event_add(ev);
triggerEvLoop();
}
static void sendSimStatusAppInfo(Parcel &p, int num_apps, RIL_AppStatus appStatus[]) {
p.writeInt32(num_apps);
startResponse;
for (int i = 0; i < num_apps; i++) {
p.writeInt32(appStatus[i].app_type);
p.writeInt32(appStatus[i].app_state);
p.writeInt32(appStatus[i].perso_substate);
writeStringToParcel(p, (const char*)(appStatus[i].aid_ptr));
writeStringToParcel(p, (const char*)
(appStatus[i].app_label_ptr));
p.writeInt32(appStatus[i].pin1_replaced);
p.writeInt32(appStatus[i].pin1);
p.writeInt32(appStatus[i].pin2);
appendPrintBuf("%s[app_type=%d,app_state=%d,perso_substate=%d,\
aid_ptr=%s,app_label_ptr=%s,pin1_replaced=%d,pin1=%d,pin2=%d],",
printBuf,
appStatus[i].app_type,
appStatus[i].app_state,
appStatus[i].perso_substate,
appStatus[i].aid_ptr,
appStatus[i].app_label_ptr,
appStatus[i].pin1_replaced,
appStatus[i].pin1,
appStatus[i].pin2);
}
closeResponse;
}
static int responseSimStatus(Parcel &p, void *response, size_t responselen) {
int i;
if (response == NULL && responselen != 0) {
RLOGE("invalid response: NULL");
return RIL_ERRNO_INVALID_RESPONSE;
}
if (responselen == sizeof (RIL_CardStatus_v6)) {
RIL_CardStatus_v6 *p_cur = ((RIL_CardStatus_v6 *) response);
p.writeInt32(p_cur->card_state);
p.writeInt32(p_cur->universal_pin_state);
p.writeInt32(p_cur->gsm_umts_subscription_app_index);
p.writeInt32(p_cur->cdma_subscription_app_index);
p.writeInt32(p_cur->ims_subscription_app_index);
sendSimStatusAppInfo(p, p_cur->num_applications, p_cur->applications);
} else if (responselen == sizeof (RIL_CardStatus_v5)) {
RIL_CardStatus_v5 *p_cur = ((RIL_CardStatus_v5 *) response);
p.writeInt32(p_cur->card_state);
p.writeInt32(p_cur->universal_pin_state);
p.writeInt32(p_cur->gsm_umts_subscription_app_index);
p.writeInt32(p_cur->cdma_subscription_app_index);
p.writeInt32(-1);
sendSimStatusAppInfo(p, p_cur->num_applications, p_cur->applications);
} else {
RLOGE("responseSimStatus: A RilCardStatus_v6 or _v5 expected\n");
return RIL_ERRNO_INVALID_RESPONSE;
}
return 0;
}
static int responseGsmBrSmsCnf(Parcel &p, void *response, size_t responselen) {
int num = responselen / sizeof(RIL_GSM_BroadcastSmsConfigInfo *);
p.writeInt32(num);
startResponse;
RIL_GSM_BroadcastSmsConfigInfo **p_cur =
(RIL_GSM_BroadcastSmsConfigInfo **) response;
for (int i = 0; i < num; i++) {
p.writeInt32(p_cur[i]->fromServiceId);
p.writeInt32(p_cur[i]->toServiceId);
p.writeInt32(p_cur[i]->fromCodeScheme);
p.writeInt32(p_cur[i]->toCodeScheme);
p.writeInt32(p_cur[i]->selected);
appendPrintBuf("%s [%d: fromServiceId=%d, toServiceId=%d, \
fromCodeScheme=%d, toCodeScheme=%d, selected =%d]",
printBuf, i, p_cur[i]->fromServiceId, p_cur[i]->toServiceId,
p_cur[i]->fromCodeScheme, p_cur[i]->toCodeScheme,
p_cur[i]->selected);
}
closeResponse;
return 0;
}
static int responseCdmaBrSmsCnf(Parcel &p, void *response, size_t responselen) {
RIL_CDMA_BroadcastSmsConfigInfo **p_cur =
(RIL_CDMA_BroadcastSmsConfigInfo **) response;
int num = responselen / sizeof (RIL_CDMA_BroadcastSmsConfigInfo *);
p.writeInt32(num);
startResponse;
for (int i = 0 ; i < num ; i++ ) {
p.writeInt32(p_cur[i]->service_category);
p.writeInt32(p_cur[i]->language);
p.writeInt32(p_cur[i]->selected);
appendPrintBuf("%s [%d: srvice_category=%d, language =%d, \
selected =%d], ",
printBuf, i, p_cur[i]->service_category, p_cur[i]->language,
p_cur[i]->selected);
}
closeResponse;
return 0;
}
static int responseCdmaSms(Parcel &p, void *response, size_t responselen) {
int num;
int digitCount;
int digitLimit;
uint8_t uct;
void* dest;
RLOGD("Inside responseCdmaSms");
if (response == NULL && responselen != 0) {
RLOGE("invalid response: NULL");
return RIL_ERRNO_INVALID_RESPONSE;
}
if (responselen != sizeof(RIL_CDMA_SMS_Message)) {
RLOGE("invalid response length was %d expected %d",
(int)responselen, (int)sizeof(RIL_CDMA_SMS_Message));
return RIL_ERRNO_INVALID_RESPONSE;
}
RIL_CDMA_SMS_Message *p_cur = (RIL_CDMA_SMS_Message *) response;
p.writeInt32(p_cur->uTeleserviceID);
p.write(&(p_cur->bIsServicePresent),sizeof(uct));
p.writeInt32(p_cur->uServicecategory);
p.writeInt32(p_cur->sAddress.digit_mode);
p.writeInt32(p_cur->sAddress.number_mode);
p.writeInt32(p_cur->sAddress.number_type);
p.writeInt32(p_cur->sAddress.number_plan);
p.write(&(p_cur->sAddress.number_of_digits), sizeof(uct));
digitLimit= MIN((p_cur->sAddress.number_of_digits), RIL_CDMA_SMS_ADDRESS_MAX);
for(digitCount =0 ; digitCount < digitLimit; digitCount ++) {
p.write(&(p_cur->sAddress.digits[digitCount]),sizeof(uct));
}
p.writeInt32(p_cur->sSubAddress.subaddressType);
p.write(&(p_cur->sSubAddress.odd),sizeof(uct));
p.write(&(p_cur->sSubAddress.number_of_digits),sizeof(uct));
digitLimit= MIN((p_cur->sSubAddress.number_of_digits), RIL_CDMA_SMS_SUBADDRESS_MAX);
for(digitCount =0 ; digitCount < digitLimit; digitCount ++) {
p.write(&(p_cur->sSubAddress.digits[digitCount]),sizeof(uct));
}
digitLimit= MIN((p_cur->uBearerDataLen), RIL_CDMA_SMS_BEARER_DATA_MAX);
p.writeInt32(p_cur->uBearerDataLen);
for(digitCount =0 ; digitCount < digitLimit; digitCount ++) {
p.write(&(p_cur->aBearerData[digitCount]), sizeof(uct));
}
startResponse;
appendPrintBuf("%suTeleserviceID=%d, bIsServicePresent=%d, uServicecategory=%d, \
sAddress.digit_mode=%d, sAddress.number_mode=%d, sAddress.number_type=%d, ",
printBuf, p_cur->uTeleserviceID,p_cur->bIsServicePresent,p_cur->uServicecategory,
p_cur->sAddress.digit_mode, p_cur->sAddress.number_mode,p_cur->sAddress.number_type);
closeResponse;
return 0;
}
static int responseDcRtInfo(Parcel &p, void *response, size_t responselen)
{
int num = responselen / sizeof(RIL_DcRtInfo);
if ((responselen % sizeof(RIL_DcRtInfo) != 0) || (num != 1)) {
RLOGE("responseDcRtInfo: invalid response length %d expected multiple of %d",
(int)responselen, (int)sizeof(RIL_DcRtInfo));
return RIL_ERRNO_INVALID_RESPONSE;
}
startResponse;
RIL_DcRtInfo *pDcRtInfo = (RIL_DcRtInfo *)response;
p.writeInt64(pDcRtInfo->time);
p.writeInt32(pDcRtInfo->powerState);
appendPrintBuf("%s[time=%d,powerState=%d]", printBuf,
pDcRtInfo->time,
pDcRtInfo->powerState);
closeResponse;
return 0;
}
/**
* A write on the wakeup fd is done just to pop us out of select()
* We empty the buffer here and then ril_event will reset the timers on the
* way back down
*/
static void processWakeupCallback(int fd, short flags, void *param) {
char buff[16];
int ret;
RLOGV("processWakeupCallback");
/* empty our wakeup socket out */
do {
ret = read(s_fdWakeupRead, &buff, sizeof(buff));
} while (ret > 0 || (ret < 0 && errno == EINTR));
}
static void onCommandsSocketClosed(RIL_SOCKET_ID socket_id) {
int ret;
RequestInfo *p_cur;
/* Hook for current context
pendingRequestsMutextHook refer to &s_pendingRequestsMutex */
pthread_mutex_t * pendingRequestsMutexHook = &s_pendingRequestsMutex;
/* pendingRequestsHook refer to &s_pendingRequests */
RequestInfo ** pendingRequestsHook = &s_pendingRequests;
#if (SIM_COUNT >= 2)
if (socket_id == RIL_SOCKET_2) {
pendingRequestsMutexHook = &s_pendingRequestsMutex_socket2;
pendingRequestsHook = &s_pendingRequests_socket2;
}
#if (SIM_COUNT >= 3)
else if (socket_id == RIL_SOCKET_3) {
pendingRequestsMutexHook = &s_pendingRequestsMutex_socket3;
pendingRequestsHook = &s_pendingRequests_socket3;
}
#endif
#if (SIM_COUNT >= 4)
else if (socket_id == RIL_SOCKET_4) {
pendingRequestsMutexHook = &s_pendingRequestsMutex_socket4;
pendingRequestsHook = &s_pendingRequests_socket4;
}
#endif
#endif
/* mark pending requests as "cancelled" so we dont report responses */
ret = pthread_mutex_lock(pendingRequestsMutexHook);
assert (ret == 0);
p_cur = *pendingRequestsHook;
for (p_cur = *pendingRequestsHook
; p_cur != NULL
; p_cur = p_cur->p_next
) {
p_cur->cancelled = 1;
}
ret = pthread_mutex_unlock(pendingRequestsMutexHook);
assert (ret == 0);
}
static void processCommandsCallback(int fd, short flags, void *param) {
RecordStream *p_rs;
void *p_record;
size_t recordlen;
int ret;
SocketListenParam *p_info = (SocketListenParam *)param;
assert(fd == p_info->fdCommand);
p_rs = p_info->p_rs;
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) { /* && p_record != NULL */
processCommandBuffer(p_record, recordlen, p_info->socket_id);
}
}
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(fd);
p_info->fdCommand = -1;
ril_event_del(p_info->commands_event);
record_stream_free(p_rs);
/* start listening for new connections again */
rilEventAddWakeup(&s_listen_event);
onCommandsSocketClosed(p_info->socket_id);
}
}
static void onNewCommandConnect(RIL_SOCKET_ID socket_id) {
// Inform we are connected and the ril version
int rilVer = s_callbacks.version;
RIL_UNSOL_RESPONSE(RIL_UNSOL_RIL_CONNECTED,
&rilVer, sizeof(rilVer), socket_id);
// implicit radio state changed
RIL_UNSOL_RESPONSE(RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED,
NULL, 0, socket_id);
// Send last NITZ time data, in case it was missed
if (s_lastNITZTimeData != NULL) {
sendResponseRaw(s_lastNITZTimeData, s_lastNITZTimeDataSize, socket_id);
free(s_lastNITZTimeData);
s_lastNITZTimeData = NULL;
}
// Get version string
if (s_callbacks.getVersion != NULL) {
const char *version;
version = s_callbacks.getVersion();
RLOGI("RIL Daemon version: %s\n", version);
property_set(PROPERTY_RIL_IMPL, version);
} else {
RLOGI("RIL Daemon version: unavailable\n");
property_set(PROPERTY_RIL_IMPL, "unavailable");
}
}
static void listenCallback (int fd, short flags, void *param) {
int ret;
int err;
int is_phone_socket;
int fdCommand = -1;
RecordStream *p_rs;
SocketListenParam *p_info = (SocketListenParam *)param;
struct sockaddr_un peeraddr;
socklen_t socklen = sizeof (peeraddr);
struct ucred creds;
socklen_t szCreds = sizeof(creds);
struct passwd *pwd = NULL;
assert (*p_info->fdCommand < 0);
assert (fd == *p_info->fdListen);
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);
return;
}
/* check the credential of the other side and only accept socket from
* phone process
* TODO remove this whold block, bypass credential check? by yhpark
*/
// errno = 0;
// is_phone_socket = 0;
//
// err = getsockopt(fdCommand, SOL_SOCKET, SO_PEERCRED, &creds, &szCreds);
//
// if (err == 0 && szCreds > 0) {
// errno = 0;
// pwd = getpwuid(creds.uid);
// if (pwd != NULL) {
// if (strcmp(pwd->pw_name, p_info->processName) == 0) {
// is_phone_socket = 1;
// } else {
// RLOGE("RILD can't accept socket from process %s", pwd->pw_name);
// }
// } else {
// RLOGE("Error on getpwuid() errno: %d", errno);
// }
// } else {
// RLOGD("Error on getsockopt() errno: %d", errno);
// }
//
// if (!is_phone_socket) {
// RLOGE("RILD must accept socket from %s", p_info->processName);
//
// close(fdCommand);
// fdCommand = -1;
//
// onCommandsSocketClosed(p_info->socket_id);
//
// /* start listening for new connections again */
// rilEventAddWakeup(p_info->listen_event);
//
// return;
// }
ret = fcntl(fdCommand, F_SETFL, O_NONBLOCK);
if (ret < 0) {
RLOGE ("Error setting O_NONBLOCK errno:%d", errno);
}
RLOGI("libril: new connection to %s", rilSocketIdToString(p_info->socket_id));
p_info->fdCommand = fdCommand;
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,
p_info->processCommandsCallback, p_info);
rilEventAddWakeup (p_info->commands_event);
onNewCommandConnect(p_info->socket_id);
}
static void freeDebugCallbackArgs(int number, char **args) {
for (int i = 0; i < number; i++) {
if (args[i] != NULL) {
free(args[i]);
}
}
free(args);
}
static void debugCallback (int fd, short flags, void *param) {
int acceptFD, option;
struct sockaddr_un peeraddr;
socklen_t socklen = sizeof (peeraddr);
int data;
unsigned int qxdm_data[6];
const char *deactData[1] = {"1"};
char *actData[1];
RIL_Dial dialData;
int hangupData[1] = {1};
int number;
char **args;
RIL_SOCKET_ID socket_id = RIL_SOCKET_1;
int sim_id = 0;
RLOGI("debugCallback for socket %s", rilSocketIdToString(socket_id));
acceptFD = accept (fd, (sockaddr *) &peeraddr, &socklen);
if (acceptFD < 0) {
RLOGE ("error accepting on debug port: %d\n", errno);
return;
}
if (recv(acceptFD, &number, sizeof(int), 0) != sizeof(int)) {
RLOGE ("error reading on socket: number of Args: \n");
return;
}
args = (char **) malloc(sizeof(char*) * number);
for (int i = 0; i < number; i++) {
int len;
if (recv(acceptFD, &len, sizeof(int), 0) != sizeof(int)) {
RLOGE ("error reading on socket: Len of Args: \n");
freeDebugCallbackArgs(i, args);
return;
}
// +1 for null-term
args[i] = (char *) malloc((sizeof(char) * len) + 1);
if (recv(acceptFD, args[i], sizeof(char) * len, 0)
!= (int)sizeof(char) * len) {
RLOGE ("error reading on socket: Args[%d] \n", i);
freeDebugCallbackArgs(i, args);
return;
}
char * buf = args[i];
buf[len] = 0;
if ((i+1) == number) {
/* The last argument should be sim id 0(SIM1)~3(SIM4) */
sim_id = atoi(args[i]);
switch (sim_id) {
case 0:
socket_id = RIL_SOCKET_1;
break;
#if (SIM_COUNT >= 2)
case 1:
socket_id = RIL_SOCKET_2;
break;
#endif
#if (SIM_COUNT >= 3)
case 2:
socket_id = RIL_SOCKET_3;
break;
#endif
#if (SIM_COUNT >= 4)
case 3:
socket_id = RIL_SOCKET_4;
break;
#endif
default:
socket_id = RIL_SOCKET_1;
break;
}
}
}
switch (atoi(args[0])) {
case 0:
RLOGI ("Connection on debug port: issuing reset.");
issueLocalRequest(RIL_REQUEST_RESET_RADIO, NULL, 0, socket_id);
break;
case 1:
RLOGI ("Connection on debug port: issuing radio power off.");
data = 0;
issueLocalRequest(RIL_REQUEST_RADIO_POWER, &data, sizeof(int), socket_id);
// Close the socket
if (socket_id == RIL_SOCKET_1 && s_ril_param_socket.fdCommand > 0) {
close(s_ril_param_socket.fdCommand);
s_ril_param_socket.fdCommand = -1;
}
#if (SIM_COUNT == 2)
else if (socket_id == RIL_SOCKET_2 && s_ril_param_socket2.fdCommand > 0) {
close(s_ril_param_socket2.fdCommand);
s_ril_param_socket2.fdCommand = -1;
}
#endif
break;
case 2:
RLOGI ("Debug port: issuing unsolicited voice network change.");
RIL_UNSOL_RESPONSE(RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED, NULL, 0, socket_id);
break;
case 3:
RLOGI ("Debug port: QXDM log enable.");
qxdm_data[0] = 65536; // head.func_tag
qxdm_data[1] = 16; // head.len
qxdm_data[2] = 1; // mode: 1 for 'start logging'
qxdm_data[3] = 32; // log_file_size: 32megabytes
qxdm_data[4] = 0; // log_mask
qxdm_data[5] = 8; // log_max_fileindex
issueLocalRequest(RIL_REQUEST_OEM_HOOK_RAW, qxdm_data,
6 * sizeof(int), socket_id);
break;
case 4:
RLOGI ("Debug port: QXDM log disable.");
qxdm_data[0] = 65536;
qxdm_data[1] = 16;
qxdm_data[2] = 0; // mode: 0 for 'stop logging'
qxdm_data[3] = 32;
qxdm_data[4] = 0;
qxdm_data[5] = 8;
issueLocalRequest(RIL_REQUEST_OEM_HOOK_RAW, qxdm_data,
6 * sizeof(int), socket_id);
break;
case 5:
RLOGI("Debug port: Radio On");
data = 1;
issueLocalRequest(RIL_REQUEST_RADIO_POWER, &data, sizeof(int), socket_id);
sleep(2);
// Set network selection automatic.
issueLocalRequest(RIL_REQUEST_SET_NETWORK_SELECTION_AUTOMATIC, NULL, 0, socket_id);
break;
case 6:
RLOGI("Debug port: Setup Data Call, Apn :%s\n", args[1]);
actData[0] = args[1];
issueLocalRequest(RIL_REQUEST_SETUP_DATA_CALL, &actData,
sizeof(actData), socket_id);
break;
case 7:
RLOGI("Debug port: Deactivate Data Call");
issueLocalRequest(RIL_REQUEST_DEACTIVATE_DATA_CALL, &deactData,
sizeof(deactData), socket_id);
break;
case 8:
RLOGI("Debug port: Dial Call");
dialData.clir = 0;
dialData.address = args[1];
issueLocalRequest(RIL_REQUEST_DIAL, &dialData, sizeof(dialData), socket_id);
break;
case 9:
RLOGI("Debug port: Answer Call");
issueLocalRequest(RIL_REQUEST_ANSWER, NULL, 0, socket_id);
break;
case 10:
RLOGI("Debug port: End Call");
issueLocalRequest(RIL_REQUEST_HANGUP, &hangupData,
sizeof(hangupData), socket_id);
break;
default:
RLOGE ("Invalid request");
break;
}
freeDebugCallbackArgs(number, args);
close(acceptFD);
}
static void userTimerCallback (int fd, short flags, void *param) {
UserCallbackInfo *p_info;
p_info = (UserCallbackInfo *)param;
p_info->p_callback(p_info->userParam);
// FIXME generalize this...there should be a cancel mechanism
if (s_last_wake_timeout_info != NULL && s_last_wake_timeout_info == p_info) {
s_last_wake_timeout_info = NULL;
}
free(p_info);
}
static void *
eventLoop(void *param) {
int ret;
int filedes[2];
ril_event_init();
pthread_mutex_lock(&s_startupMutex);
s_started = 1;
pthread_cond_broadcast(&s_startupCond);
pthread_mutex_unlock(&s_startupMutex);
ret = pipe(filedes);
if (ret < 0) {
RLOGE("Error in pipe() errno:%d", errno);
return NULL;
}
s_fdWakeupRead = filedes[0];
s_fdWakeupWrite = filedes[1];
fcntl(s_fdWakeupRead, F_SETFL, O_NONBLOCK);
ril_event_set (&s_wakeupfd_event, s_fdWakeupRead, true,
processWakeupCallback, NULL);
rilEventAddWakeup (&s_wakeupfd_event);
// Only returns on error
ril_event_loop();
RLOGE ("error in event_loop_base errno:%d", errno);
// kill self to restart on error
kill(0, SIGKILL);
return NULL;
}
extern "C" void
RIL_startEventLoop(void) {
/* spin up eventLoop thread and wait for it to get started */
s_started = 0;
pthread_mutex_lock(&s_startupMutex);
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
int result = pthread_create(&s_tid_dispatch, &attr, eventLoop, NULL);
if (result != 0) {
RLOGE("Failed to create dispatch thread: %s", strerror(result));
goto done;
}
while (s_started == 0) {
pthread_cond_wait(&s_startupCond, &s_startupMutex);
}
done:
pthread_mutex_unlock(&s_startupMutex);
}
// Used for testing purpose only.
extern "C" void RIL_setcallbacks (const RIL_RadioFunctions *callbacks) {
memcpy(&s_callbacks, callbacks, sizeof (RIL_RadioFunctions));
}
static void *transferProxy(void *arg) {
char buf[1024];
int fdRecv = ((int *) arg)[0];
int fdSend = ((int *) arg)[1];
while (true) {
RLOGI("proxy: recieve from %d", fdRecv);
int read = recv(fdRecv, buf, sizeof buf, 0);
if (read == 0) break;
if (read < 0) {
RLOGE("Failed to receive from %d", fdRecv);
return (void *) -1;
}
RLOGI("proxy: send to %d, %d bytes", fdSend, read);
int err = send(fdSend, buf, read, 0);
if (err < 0) {
RLOGE("Failed to send to %d", fdSend);
return (void *) -1;
}
}
return 0;
}
// Proxy for client
static void *startProxy(void *arg) {
struct sockaddr_in addr;
int fdConnect;
int fdListen = (int) arg;
RLOGI("fdListen: %d", arg);
while (true) {
RLOGI("Accepting original socket");
struct sockaddr_un peeraddr;
socklen_t socklen = sizeof (peeraddr);
struct ucred creds;
socklen_t szCreds = sizeof(creds);
int fdLocal = accept(fdListen, (sockaddr *) &peeraddr, &socklen);
if (fdLocal < 0) {
RLOGE("Error on accept() errno:%d", errno);
/* start listening for new connections again */
return 0;
}
RLOGI("Initializing proxy socket");
fdConnect = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (fdConnect < 0) {
RLOGE("Failed to create socket");
goto retry;
}
memset(&addr, 0, sizeof addr);
addr.sin_family = AF_INET;
addr.sin_port = htons(REMOTE_PORT);
inet_pton(AF_INET, REMOTE_ADDR, &addr.sin_addr);
if (connect(fdConnect, (struct sockaddr *) &addr, sizeof addr) < 0) {
RLOGE("Failed to connect");
goto retry;
}
RLOGI("proxy connected");
{
RLOGI("client: %d, server: %d", fdLocal, fdConnect);
int arg_a[] = { fdConnect, fdLocal };
int arg_b[] = { fdLocal, fdConnect };
pthread_t th_a, th_b;
pthread_create(&th_a, NULL, transferProxy, (void *) arg_a);
pthread_create(&th_b, NULL, transferProxy, (void *) arg_b);
int status_a, status_b;
pthread_join(th_a, (void **) &status_a);
pthread_join(th_b, (void **) &status_b);
}
retry:
RLOGI("Will retry starting proxy after 5 seconds");
close(fdLocal);
close(fdConnect);
sleep(5);
}
return 0;
}
static void startListen(RIL_SOCKET_ID socket_id, SocketListenParam* socket_listen_p) {
int fdListen = -1;
int ret;
char socket_name[10];
memset(socket_name, 0, sizeof(char)*10);
switch(socket_id) {
case RIL_SOCKET_1:
strncpy(socket_name, RIL_getRilSocketName(), 9);
break;
#if (SIM_COUNT >= 2)
case RIL_SOCKET_2:
strncpy(socket_name, SOCKET2_NAME_RIL, 9);
break;
#endif
#if (SIM_COUNT >= 3)
case RIL_SOCKET_3:
strncpy(socket_name, SOCKET3_NAME_RIL, 9);
break;
#endif
#if (SIM_COUNT >= 4)
case RIL_SOCKET_4:
strncpy(socket_name, SOCKET4_NAME_RIL, 9);
break;
#endif
default:
RLOGE("Socket id is wrong!!");
return;
}
RLOGI("Start to listen %s", rilSocketIdToString(socket_id));
#if (REMOTE_MODE == REMOTE_MODE_SERVER || REMOTE_MODE == REMOTE_MODE_SELF_TEST)
RLOGI("Initializing server socket");
struct sockaddr_in addr;
fdListen = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (fdListen == -1) {
RLOGE("Failed to create socket");
exit(-1);
}
int yes = 1;
if (setsockopt(fdListen, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) == -1) {
RLOGE("Failed to setsockopt");
exit(-1);
}
memset(&addr, 0, sizeof addr);
addr.sin_family = AF_INET;
addr.sin_port = htons(REMOTE_PORT);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
RLOGI("bind");
if (bind(fdListen, (struct sockaddr *) &addr, sizeof addr) == -1) {
RLOGE("Failed to bind socket");
close(fdListen);
exit(-1);
}
RLOGI("listen");
if (listen(fdListen, 4) < 0) {
RLOGE("Failed to listen socket");
close(fdListen);
exit(-1);
}
socket_listen_p->fdListen = fdListen;
RLOGI("ril event set");
/* note: non-persistent so we can accept only one connection at a time */
ril_event_set (socket_listen_p->listen_event, fdListen, false,
listenCallback, socket_listen_p);
rilEventAddWakeup (socket_listen_p->listen_event);
#endif
#if (REMOTE_MODE == REMOTE_MODE_ORIGINAL || REMOTE_MODE == REMOTE_MODE_CLIENT || REMOTE_MODE == REMOTE_MODE_SELF_TEST)
RLOGI("Initializing original socket");
fdListen = android_get_control_socket(socket_name);
if (fdListen < 0) {
RLOGE("Failed to get socket %s", socket_name);
exit(-1);
}
RLOGI("fdListen: %d", fdListen);
RLOGI("listen");
ret = listen(fdListen, 4);
if (ret < 0) {
RLOGE("Failed to listen on control socket '%d': %s",
fdListen, strerror(errno));
exit(-1);
}
#if (REMOTE_MODE == REMOTE_MODE_ORIGINAL)
RLOGI("ril event set");
socket_listen_p->fdListen = fdListen;
/* note: non-persistent so we can accept only one connection at a time */
ril_event_set (socket_listen_p->listen_event, fdListen, false,
listenCallback, socket_listen_p);
rilEventAddWakeup (socket_listen_p->listen_event);
#endif
#if (REMOTE_MODE == REMOTE_MODE_CLIENT || REMOTE_MODE == REMOTE_MODE_SELF_TEST)
// startProxy
pthread_t th;
pthread_create(&th, NULL, startProxy, (void *) fdListen);
#endif
#endif
}
extern "C" void
RIL_register (const RIL_RadioFunctions *callbacks) {
int ret;
int flags;
RLOGI("SIM_COUNT: %d", SIM_COUNT);
if (callbacks == NULL) {
RLOGE("RIL_register: RIL_RadioFunctions * null");
return;
}
if (callbacks->version < RIL_VERSION_MIN) {
RLOGE("RIL_register: version %d is to old, min version is %d",
callbacks->version, RIL_VERSION_MIN);
return;
}
if (callbacks->version > RIL_VERSION) {
RLOGE("RIL_register: version %d is too new, max version is %d",
callbacks->version, RIL_VERSION);
return;
}
RLOGE("RIL_register: RIL version %d", callbacks->version);
if (s_registerCalled > 0) {
RLOGE("RIL_register has been called more than once. "
"Subsequent call ignored");
return;
}
memcpy(&s_callbacks, callbacks, sizeof (RIL_RadioFunctions));
/* Initialize socket1 parameters */
s_ril_param_socket = {
RIL_SOCKET_1, /* socket_id */
-1, /* fdListen */
-1, /* fdCommand */
PHONE_PROCESS, /* processName */
&s_commands_event, /* commands_event */
&s_listen_event, /* listen_event */
processCommandsCallback, /* processCommandsCallback */
NULL /* p_rs */
};
#if (SIM_COUNT >= 2)
s_ril_param_socket2 = {
RIL_SOCKET_2, /* socket_id */
-1, /* fdListen */
-1, /* fdCommand */
PHONE_PROCESS, /* processName */
&s_commands_event_socket2, /* commands_event */
&s_listen_event_socket2, /* listen_event */
processCommandsCallback, /* processCommandsCallback */
NULL /* p_rs */
};
#endif
#if (SIM_COUNT >= 3)
s_ril_param_socket3 = {
RIL_SOCKET_3, /* socket_id */
-1, /* fdListen */
-1, /* fdCommand */
PHONE_PROCESS, /* processName */
&s_commands_event_socket3, /* commands_event */
&s_listen_event_socket3, /* listen_event */
processCommandsCallback, /* processCommandsCallback */
NULL /* p_rs */
};
#endif
#if (SIM_COUNT >= 4)
s_ril_param_socket4 = {
RIL_SOCKET_4, /* socket_id */
-1, /* fdListen */
-1, /* fdCommand */
PHONE_PROCESS, /* processName */
&s_commands_event_socket4, /* commands_event */
&s_listen_event_socket4, /* listen_event */
processCommandsCallback, /* processCommandsCallback */
NULL /* p_rs */
};
#endif
s_registerCalled = 1;
RLOGI("s_registerCalled flag set, %d", s_started);
// Little self-check
for (int i = 0; i < (int)NUM_ELEMS(s_commands); i++) {
assert(i == s_commands[i].requestNumber);
}
for (int i = 0; i < (int)NUM_ELEMS(s_unsolResponses); i++) {
assert(i + RIL_UNSOL_RESPONSE_BASE
== s_unsolResponses[i].requestNumber);
}
// New rild impl calls RIL_startEventLoop() first
// old standalone impl wants it here.
if (s_started == 0) {
RIL_startEventLoop();
}
// start listen socket1
startListen(RIL_SOCKET_1, &s_ril_param_socket);
#if (SIM_COUNT >= 2)
// start listen socket2
startListen(RIL_SOCKET_2, &s_ril_param_socket2);
#endif /* (SIM_COUNT == 2) */
#if (SIM_COUNT >= 3)
// start listen socket3
startListen(RIL_SOCKET_3, &s_ril_param_socket3);
#endif /* (SIM_COUNT == 3) */
#if (SIM_COUNT >= 4)
// start listen socket4
startListen(RIL_SOCKET_4, &s_ril_param_socket4);
#endif /* (SIM_COUNT == 4) */
#if 1
// start debug interface socket
char *inst = NULL;
if (strlen(RIL_getRilSocketName()) >= strlen(SOCKET_NAME_RIL)) {
inst = RIL_getRilSocketName() + strlen(SOCKET_NAME_RIL);
}
char rildebug[MAX_DEBUG_SOCKET_NAME_LENGTH] = SOCKET_NAME_RIL_DEBUG;
if (inst != NULL) {
strncat(rildebug, inst, MAX_DEBUG_SOCKET_NAME_LENGTH);
}
s_fdDebug = android_get_control_socket(rildebug);
if (s_fdDebug < 0) {
RLOGE("Failed to get socket : %s errno:%d", rildebug, errno);
exit(-1);
}
ret = listen(s_fdDebug, 4);
if (ret < 0) {
RLOGE("Failed to listen on ril debug socket '%d': %s",
s_fdDebug, strerror(errno));
exit(-1);
}
ril_event_set (&s_debug_event, s_fdDebug, true,
debugCallback, NULL);
rilEventAddWakeup (&s_debug_event);
#endif
}
static int
checkAndDequeueRequestInfo(struct RequestInfo *pRI) {
int ret = 0;
/* Hook for current context
pendingRequestsMutextHook refer to &s_pendingRequestsMutex */
pthread_mutex_t* pendingRequestsMutexHook = &s_pendingRequestsMutex;
/* pendingRequestsHook refer to &s_pendingRequests */
RequestInfo ** pendingRequestsHook = &s_pendingRequests;
if (pRI == NULL) {
return 0;
}
#if (SIM_COUNT >= 2)
if (pRI->socket_id == RIL_SOCKET_2) {
pendingRequestsMutexHook = &s_pendingRequestsMutex_socket2;
pendingRequestsHook = &s_pendingRequests_socket2;
}
#if (SIM_COUNT >= 3)
if (pRI->socket_id == RIL_SOCKET_3) {
pendingRequestsMutexHook = &s_pendingRequestsMutex_socket3;
pendingRequestsHook = &s_pendingRequests_socket3;
}
#endif
#if (SIM_COUNT >= 4)
if (pRI->socket_id == RIL_SOCKET_4) {
pendingRequestsMutexHook = &s_pendingRequestsMutex_socket4;
pendingRequestsHook = &s_pendingRequests_socket4;
}
#endif
#endif
pthread_mutex_lock(pendingRequestsMutexHook);
for(RequestInfo **ppCur = pendingRequestsHook
; *ppCur != NULL
; ppCur = &((*ppCur)->p_next)
) {
if (pRI == *ppCur) {
ret = 1;
*ppCur = (*ppCur)->p_next;
break;
}
}
pthread_mutex_unlock(pendingRequestsMutexHook);
return ret;
}
extern "C" void
RIL_onRequestComplete(RIL_Token t, RIL_Errno e, void *response, size_t responselen) {
RequestInfo *pRI;
int ret;
int fd = s_ril_param_socket.fdCommand;
size_t errorOffset;
RIL_SOCKET_ID socket_id = RIL_SOCKET_1;
pRI = (RequestInfo *)t;
if (!checkAndDequeueRequestInfo(pRI)) {
RLOGE ("%d %s", pRI->token, requestToString(pRI->pCI->requestNumber));
RLOGE ("RIL_onRequestComplete: invalid RIL_Token");
return;
}
socket_id = pRI->socket_id;
#if (SIM_COUNT >= 2)
if (socket_id == RIL_SOCKET_2) {
fd = s_ril_param_socket2.fdCommand;
}
#if (SIM_COUNT >= 3)
if (socket_id == RIL_SOCKET_3) {
fd = s_ril_param_socket3.fdCommand;
}
#endif
#if (SIM_COUNT >= 4)
if (socket_id == RIL_SOCKET_4) {
fd = s_ril_param_socket4.fdCommand;
}
#endif
#endif
RLOGD("RequestComplete, %s", rilSocketIdToString(socket_id));
if (pRI->local > 0) {
// Locally issued command...void only!
// response does not go back up the command socket
RLOGD("C[locl]< %s", requestToString(pRI->pCI->requestNumber));
goto done;
}
appendPrintBuf("[%04d]< %s",
pRI->token, requestToString(pRI->pCI->requestNumber));
if (pRI->cancelled == 0) {
Parcel p;
p.writeInt32 (RESPONSE_SOLICITED);
p.writeInt32 (pRI->token);
errorOffset = p.dataPosition();
p.writeInt32 (e);
if (response != NULL) {
// there is a response payload, no matter success or not.
ret = pRI->pCI->responseFunction(p, response, responselen);
/* if an error occurred, rewind and mark it */
if (ret != 0) {
RLOGE ("responseFunction error, ret %d", ret);
p.setDataPosition(errorOffset);
p.writeInt32 (ret);
}
}
if (e != RIL_E_SUCCESS) {
appendPrintBuf("%s fails by %s", printBuf, failCauseToString(e));
}
if (fd < 0) {
RLOGD ("RIL onRequestComplete: Command channel closed");
}
sendResponse(p, socket_id);
}
done:
free(pRI);
}
static void
grabPartialWakeLock() {
acquire_wake_lock(PARTIAL_WAKE_LOCK, ANDROID_WAKE_LOCK_NAME);
}
static void
releaseWakeLock() {
release_wake_lock(ANDROID_WAKE_LOCK_NAME);
}
/**
* Timer callback to put us back to sleep before the default timeout
*/
static void
wakeTimeoutCallback (void *param) {
// We're using "param != NULL" as a cancellation mechanism
if (param == NULL) {
//RLOGD("wakeTimeout: releasing wake lock");
releaseWakeLock();
} else {
//RLOGD("wakeTimeout: releasing wake lock CANCELLED");
}
}
static int
decodeVoiceRadioTechnology (RIL_RadioState radioState) {
switch (radioState) {
case RADIO_STATE_SIM_NOT_READY:
case RADIO_STATE_SIM_LOCKED_OR_ABSENT:
case RADIO_STATE_SIM_READY:
return RADIO_TECH_UMTS;
case RADIO_STATE_RUIM_NOT_READY:
case RADIO_STATE_RUIM_READY:
case RADIO_STATE_RUIM_LOCKED_OR_ABSENT:
case RADIO_STATE_NV_NOT_READY:
case RADIO_STATE_NV_READY:
return RADIO_TECH_1xRTT;
default:
RLOGD("decodeVoiceRadioTechnology: Invoked with incorrect RadioState");
return -1;
}
}
static int
decodeCdmaSubscriptionSource (RIL_RadioState radioState) {
switch (radioState) {
case RADIO_STATE_SIM_NOT_READY:
case RADIO_STATE_SIM_LOCKED_OR_ABSENT:
case RADIO_STATE_SIM_READY:
case RADIO_STATE_RUIM_NOT_READY:
case RADIO_STATE_RUIM_READY:
case RADIO_STATE_RUIM_LOCKED_OR_ABSENT:
return CDMA_SUBSCRIPTION_SOURCE_RUIM_SIM;
case RADIO_STATE_NV_NOT_READY:
case RADIO_STATE_NV_READY:
return CDMA_SUBSCRIPTION_SOURCE_NV;
default:
RLOGD("decodeCdmaSubscriptionSource: Invoked with incorrect RadioState");
return -1;
}
}
static int
decodeSimStatus (RIL_RadioState radioState) {
switch (radioState) {
case RADIO_STATE_SIM_NOT_READY:
case RADIO_STATE_RUIM_NOT_READY:
case RADIO_STATE_NV_NOT_READY:
case RADIO_STATE_NV_READY:
return -1;
case RADIO_STATE_SIM_LOCKED_OR_ABSENT:
case RADIO_STATE_SIM_READY:
case RADIO_STATE_RUIM_READY:
case RADIO_STATE_RUIM_LOCKED_OR_ABSENT:
return radioState;
default:
RLOGD("decodeSimStatus: Invoked with incorrect RadioState");
return -1;
}
}
static bool is3gpp2(int radioTech) {
switch (radioTech) {
case RADIO_TECH_IS95A:
case RADIO_TECH_IS95B:
case RADIO_TECH_1xRTT:
case RADIO_TECH_EVDO_0:
case RADIO_TECH_EVDO_A:
case RADIO_TECH_EVDO_B:
case RADIO_TECH_EHRPD:
return true;
default:
return false;
}
}
/* If RIL sends SIM states or RUIM states, store the voice radio
* technology and subscription source information so that they can be
* returned when telephony framework requests them
*/
static RIL_RadioState
processRadioState(RIL_RadioState newRadioState, RIL_SOCKET_ID socket_id) {
if((newRadioState > RADIO_STATE_UNAVAILABLE) && (newRadioState < RADIO_STATE_ON)) {
int newVoiceRadioTech;
int newCdmaSubscriptionSource;
int newSimStatus;
/* This is old RIL. Decode Subscription source and Voice Radio Technology
from Radio State and send change notifications if there has been a change */
newVoiceRadioTech = decodeVoiceRadioTechnology(newRadioState);
if(newVoiceRadioTech != voiceRadioTech) {
voiceRadioTech = newVoiceRadioTech;
RIL_UNSOL_RESPONSE(RIL_UNSOL_VOICE_RADIO_TECH_CHANGED,
&voiceRadioTech, sizeof(voiceRadioTech), socket_id);
}
if(is3gpp2(newVoiceRadioTech)) {
newCdmaSubscriptionSource = decodeCdmaSubscriptionSource(newRadioState);
if(newCdmaSubscriptionSource != cdmaSubscriptionSource) {
cdmaSubscriptionSource = newCdmaSubscriptionSource;
RIL_UNSOL_RESPONSE(RIL_UNSOL_CDMA_SUBSCRIPTION_SOURCE_CHANGED,
&cdmaSubscriptionSource, sizeof(cdmaSubscriptionSource), socket_id);
}
}
newSimStatus = decodeSimStatus(newRadioState);
if(newSimStatus != simRuimStatus) {
simRuimStatus = newSimStatus;
RIL_UNSOL_RESPONSE(RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED, NULL, 0, socket_id);
}
/* Send RADIO_ON to telephony */
newRadioState = RADIO_STATE_ON;
}
return newRadioState;
}
#if defined(ANDROID_MULTI_SIM)
extern "C"
void RIL_onUnsolicitedResponse(int unsolResponse, void *data,
size_t datalen, RIL_SOCKET_ID socket_id)
#else
extern "C"
void RIL_onUnsolicitedResponse(int unsolResponse, void *data,
size_t datalen)
#endif
{
int unsolResponseIndex;
int ret;
int64_t timeReceived = 0;
bool shouldScheduleTimeout = false;
RIL_RadioState newState;
RIL_SOCKET_ID soc_id = RIL_SOCKET_1;
#if defined(ANDROID_MULTI_SIM)
soc_id = socket_id;
#endif
if (s_registerCalled == 0) {
// Ignore RIL_onUnsolicitedResponse before RIL_register
RLOGW("RIL_onUnsolicitedResponse called before RIL_register");
return;
}
unsolResponseIndex = unsolResponse - RIL_UNSOL_RESPONSE_BASE;
if ((unsolResponseIndex < 0)
|| (unsolResponseIndex >= (int32_t)NUM_ELEMS(s_unsolResponses))) {
RLOGE("unsupported unsolicited response code %d", unsolResponse);
return;
}
// Grab a wake lock if needed for this reponse,
// as we exit we'll either release it immediately
// or set a timer to release it later.
switch (s_unsolResponses[unsolResponseIndex].wakeType) {
case WAKE_PARTIAL:
grabPartialWakeLock();
shouldScheduleTimeout = true;
break;
case DONT_WAKE:
default:
// No wake lock is grabed so don't set timeout
shouldScheduleTimeout = false;
break;
}
// Mark the time this was received, doing this
// after grabing the wakelock incase getting
// the elapsedRealTime might cause us to goto
// sleep.
if (unsolResponse == RIL_UNSOL_NITZ_TIME_RECEIVED) {
timeReceived = elapsedRealtime();
}
appendPrintBuf("[UNSL]< %s", requestToString(unsolResponse));
Parcel p;
p.writeInt32 (RESPONSE_UNSOLICITED);
p.writeInt32 (unsolResponse);
ret = s_unsolResponses[unsolResponseIndex]
.responseFunction(p, const_cast<void*>(data), datalen);
if (ret != 0) {
// Problem with the response. Don't continue;
goto error_exit;
}
// some things get more payload
switch(unsolResponse) {
case RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED:
newState = processRadioState(CALL_ONSTATEREQUEST(soc_id), soc_id);
p.writeInt32(newState);
appendPrintBuf("%s {%s}", printBuf,
radioStateToString(CALL_ONSTATEREQUEST(soc_id)));
break;
case RIL_UNSOL_NITZ_TIME_RECEIVED:
// Store the time that this was received so the
// handler of this message can account for
// the time it takes to arrive and process. In
// particular the system has been known to sleep
// before this message can be processed.
p.writeInt64(timeReceived);
break;
}
RLOGI("%s UNSOLICITED: %s length:%d", rilSocketIdToString(soc_id), requestToString(unsolResponse), p.dataSize());
ret = sendResponse(p, soc_id);
if (ret != 0 && unsolResponse == RIL_UNSOL_NITZ_TIME_RECEIVED) {
// Unfortunately, NITZ time is not poll/update like everything
// else in the system. So, if the upstream client isn't connected,
// keep a copy of the last NITZ response (with receive time noted
// above) around so we can deliver it when it is connected
if (s_lastNITZTimeData != NULL) {
free (s_lastNITZTimeData);
s_lastNITZTimeData = NULL;
}
s_lastNITZTimeData = malloc(p.dataSize());
s_lastNITZTimeDataSize = p.dataSize();
memcpy(s_lastNITZTimeData, p.data(), p.dataSize());
}
// For now, we automatically go back to sleep after TIMEVAL_WAKE_TIMEOUT
// FIXME The java code should handshake here to release wake lock
if (shouldScheduleTimeout) {
// Cancel the previous request
if (s_last_wake_timeout_info != NULL) {
s_last_wake_timeout_info->userParam = (void *)1;
}
s_last_wake_timeout_info
= internalRequestTimedCallback(wakeTimeoutCallback, NULL,
&TIMEVAL_WAKE_TIMEOUT);
}
// Normal exit
return;
error_exit:
if (shouldScheduleTimeout) {
releaseWakeLock();
}
}
/** FIXME generalize this if you track UserCAllbackInfo, clear it
when the callback occurs
*/
static UserCallbackInfo *
internalRequestTimedCallback (RIL_TimedCallback callback, void *param,
const struct timeval *relativeTime)
{
struct timeval myRelativeTime;
UserCallbackInfo *p_info;
p_info = (UserCallbackInfo *) malloc (sizeof(UserCallbackInfo));
p_info->p_callback = callback;
p_info->userParam = param;
if (relativeTime == NULL) {
/* treat null parameter as a 0 relative time */
memset (&myRelativeTime, 0, sizeof(myRelativeTime));
} else {
/* FIXME I think event_add's tv param is really const anyway */
memcpy (&myRelativeTime, relativeTime, sizeof(myRelativeTime));
}
ril_event_set(&(p_info->event), -1, false, userTimerCallback, p_info);
ril_timer_add(&(p_info->event), &myRelativeTime);
triggerEvLoop();
return p_info;
}
extern "C" void
RIL_requestTimedCallback (RIL_TimedCallback callback, void *param,
const struct timeval *relativeTime) {
internalRequestTimedCallback (callback, param, relativeTime);
}
const char *
failCauseToString(RIL_Errno e) {
switch(e) {
case RIL_E_SUCCESS: return "E_SUCCESS";
case RIL_E_RADIO_NOT_AVAILABLE: return "E_RADIO_NOT_AVAILABLE";
case RIL_E_GENERIC_FAILURE: return "E_GENERIC_FAILURE";
case RIL_E_PASSWORD_INCORRECT: return "E_PASSWORD_INCORRECT";
case RIL_E_SIM_PIN2: return "E_SIM_PIN2";
case RIL_E_SIM_PUK2: return "E_SIM_PUK2";
case RIL_E_REQUEST_NOT_SUPPORTED: return "E_REQUEST_NOT_SUPPORTED";
case RIL_E_CANCELLED: return "E_CANCELLED";
case RIL_E_OP_NOT_ALLOWED_DURING_VOICE_CALL: return "E_OP_NOT_ALLOWED_DURING_VOICE_CALL";
case RIL_E_OP_NOT_ALLOWED_BEFORE_REG_TO_NW: return "E_OP_NOT_ALLOWED_BEFORE_REG_TO_NW";
case RIL_E_SMS_SEND_FAIL_RETRY: return "E_SMS_SEND_FAIL_RETRY";
case RIL_E_SIM_ABSENT:return "E_SIM_ABSENT";
case RIL_E_ILLEGAL_SIM_OR_ME:return "E_ILLEGAL_SIM_OR_ME";
#ifdef FEATURE_MULTIMODE_ANDROID
case RIL_E_SUBSCRIPTION_NOT_AVAILABLE:return "E_SUBSCRIPTION_NOT_AVAILABLE";
case RIL_E_MODE_NOT_SUPPORTED:return "E_MODE_NOT_SUPPORTED";
#endif
default: return "<unknown error>";
}
}
const char *
radioStateToString(RIL_RadioState s) {
switch(s) {
case RADIO_STATE_OFF: return "RADIO_OFF";
case RADIO_STATE_UNAVAILABLE: return "RADIO_UNAVAILABLE";
case RADIO_STATE_SIM_NOT_READY: return "RADIO_SIM_NOT_READY";
case RADIO_STATE_SIM_LOCKED_OR_ABSENT: return "RADIO_SIM_LOCKED_OR_ABSENT";
case RADIO_STATE_SIM_READY: return "RADIO_SIM_READY";
case RADIO_STATE_RUIM_NOT_READY:return"RADIO_RUIM_NOT_READY";
case RADIO_STATE_RUIM_READY:return"RADIO_RUIM_READY";
case RADIO_STATE_RUIM_LOCKED_OR_ABSENT:return"RADIO_RUIM_LOCKED_OR_ABSENT";
case RADIO_STATE_NV_NOT_READY:return"RADIO_NV_NOT_READY";
case RADIO_STATE_NV_READY:return"RADIO_NV_READY";
case RADIO_STATE_ON:return"RADIO_ON";
default: return "<unknown state>";
}
}
const char *
callStateToString(RIL_CallState s) {
switch(s) {
case RIL_CALL_ACTIVE : return "ACTIVE";
case RIL_CALL_HOLDING: return "HOLDING";
case RIL_CALL_DIALING: return "DIALING";
case RIL_CALL_ALERTING: return "ALERTING";
case RIL_CALL_INCOMING: return "INCOMING";
case RIL_CALL_WAITING: return "WAITING";
default: return "<unknown state>";
}
}
const char *
requestToString(int request) {
/*
cat libs/telephony/ril_commands.h \
| egrep "^ *{RIL_" \
| sed -re 's/\{RIL_([^,]+),[^,]+,([^}]+).+/case RIL_\1: return "\1";/'
cat libs/telephony/ril_unsol_commands.h \
| egrep "^ *{RIL_" \
| sed -re 's/\{RIL_([^,]+),([^}]+).+/case RIL_\1: return "\1";/'
*/
switch(request) {
case RIL_REQUEST_GET_SIM_STATUS: return "GET_SIM_STATUS";
case RIL_REQUEST_ENTER_SIM_PIN: return "ENTER_SIM_PIN";
case RIL_REQUEST_ENTER_SIM_PUK: return "ENTER_SIM_PUK";
case RIL_REQUEST_ENTER_SIM_PIN2: return "ENTER_SIM_PIN2";
case RIL_REQUEST_ENTER_SIM_PUK2: return "ENTER_SIM_PUK2";
case RIL_REQUEST_CHANGE_SIM_PIN: return "CHANGE_SIM_PIN";
case RIL_REQUEST_CHANGE_SIM_PIN2: return "CHANGE_SIM_PIN2";
case RIL_REQUEST_ENTER_NETWORK_DEPERSONALIZATION: return "ENTER_NETWORK_DEPERSONALIZATION";
case RIL_REQUEST_GET_CURRENT_CALLS: return "GET_CURRENT_CALLS";
case RIL_REQUEST_DIAL: return "DIAL";
case RIL_REQUEST_GET_IMSI: return "GET_IMSI";
case RIL_REQUEST_HANGUP: return "HANGUP";
case RIL_REQUEST_HANGUP_WAITING_OR_BACKGROUND: return "HANGUP_WAITING_OR_BACKGROUND";
case RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND: return "HANGUP_FOREGROUND_RESUME_BACKGROUND";
case RIL_REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE: return "SWITCH_WAITING_OR_HOLDING_AND_ACTIVE";
case RIL_REQUEST_CONFERENCE: return "CONFERENCE";
case RIL_REQUEST_UDUB: return "UDUB";
case RIL_REQUEST_LAST_CALL_FAIL_CAUSE: return "LAST_CALL_FAIL_CAUSE";
case RIL_REQUEST_SIGNAL_STRENGTH: return "SIGNAL_STRENGTH";
case RIL_REQUEST_VOICE_REGISTRATION_STATE: return "VOICE_REGISTRATION_STATE";
case RIL_REQUEST_DATA_REGISTRATION_STATE: return "DATA_REGISTRATION_STATE";
case RIL_REQUEST_OPERATOR: return "OPERATOR";
case RIL_REQUEST_RADIO_POWER: return "RADIO_POWER";
case RIL_REQUEST_DTMF: return "DTMF";
case RIL_REQUEST_SEND_SMS: return "SEND_SMS";
case RIL_REQUEST_SEND_SMS_EXPECT_MORE: return "SEND_SMS_EXPECT_MORE";
case RIL_REQUEST_SETUP_DATA_CALL: return "SETUP_DATA_CALL";
case RIL_REQUEST_SIM_IO: return "SIM_IO";
case RIL_REQUEST_SEND_USSD: return "SEND_USSD";
case RIL_REQUEST_CANCEL_USSD: return "CANCEL_USSD";
case RIL_REQUEST_GET_CLIR: return "GET_CLIR";
case RIL_REQUEST_SET_CLIR: return "SET_CLIR";
case RIL_REQUEST_QUERY_CALL_FORWARD_STATUS: return "QUERY_CALL_FORWARD_STATUS";
case RIL_REQUEST_SET_CALL_FORWARD: return "SET_CALL_FORWARD";
case RIL_REQUEST_QUERY_CALL_WAITING: return "QUERY_CALL_WAITING";
case RIL_REQUEST_SET_CALL_WAITING: return "SET_CALL_WAITING";
case RIL_REQUEST_SMS_ACKNOWLEDGE: return "SMS_ACKNOWLEDGE";
case RIL_REQUEST_GET_IMEI: return "GET_IMEI";
case RIL_REQUEST_GET_IMEISV: return "GET_IMEISV";
case RIL_REQUEST_ANSWER: return "ANSWER";
case RIL_REQUEST_DEACTIVATE_DATA_CALL: return "DEACTIVATE_DATA_CALL";
case RIL_REQUEST_QUERY_FACILITY_LOCK: return "QUERY_FACILITY_LOCK";
case RIL_REQUEST_SET_FACILITY_LOCK: return "SET_FACILITY_LOCK";
case RIL_REQUEST_CHANGE_BARRING_PASSWORD: return "CHANGE_BARRING_PASSWORD";
case RIL_REQUEST_QUERY_NETWORK_SELECTION_MODE: return "QUERY_NETWORK_SELECTION_MODE";
case RIL_REQUEST_SET_NETWORK_SELECTION_AUTOMATIC: return "SET_NETWORK_SELECTION_AUTOMATIC";
case RIL_REQUEST_SET_NETWORK_SELECTION_MANUAL: return "SET_NETWORK_SELECTION_MANUAL";
case RIL_REQUEST_QUERY_AVAILABLE_NETWORKS : return "QUERY_AVAILABLE_NETWORKS ";
case RIL_REQUEST_DTMF_START: return "DTMF_START";
case RIL_REQUEST_DTMF_STOP: return "DTMF_STOP";
case RIL_REQUEST_BASEBAND_VERSION: return "BASEBAND_VERSION";
case RIL_REQUEST_SEPARATE_CONNECTION: return "SEPARATE_CONNECTION";
case RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE: return "SET_PREFERRED_NETWORK_TYPE";
case RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE: return "GET_PREFERRED_NETWORK_TYPE";
case RIL_REQUEST_GET_NEIGHBORING_CELL_IDS: return "GET_NEIGHBORING_CELL_IDS";
case RIL_REQUEST_SET_MUTE: return "SET_MUTE";
case RIL_REQUEST_GET_MUTE: return "GET_MUTE";
case RIL_REQUEST_QUERY_CLIP: return "QUERY_CLIP";
case RIL_REQUEST_LAST_DATA_CALL_FAIL_CAUSE: return "LAST_DATA_CALL_FAIL_CAUSE";
case RIL_REQUEST_DATA_CALL_LIST: return "DATA_CALL_LIST";
case RIL_REQUEST_RESET_RADIO: return "RESET_RADIO";
case RIL_REQUEST_OEM_HOOK_RAW: return "OEM_HOOK_RAW";
case RIL_REQUEST_OEM_HOOK_STRINGS: return "OEM_HOOK_STRINGS";
case RIL_REQUEST_SET_BAND_MODE: return "SET_BAND_MODE";
case RIL_REQUEST_QUERY_AVAILABLE_BAND_MODE: return "QUERY_AVAILABLE_BAND_MODE";
case RIL_REQUEST_STK_GET_PROFILE: return "STK_GET_PROFILE";
case RIL_REQUEST_STK_SET_PROFILE: return "STK_SET_PROFILE";
case RIL_REQUEST_STK_SEND_ENVELOPE_COMMAND: return "STK_SEND_ENVELOPE_COMMAND";
case RIL_REQUEST_STK_SEND_TERMINAL_RESPONSE: return "STK_SEND_TERMINAL_RESPONSE";
case RIL_REQUEST_STK_HANDLE_CALL_SETUP_REQUESTED_FROM_SIM: return "STK_HANDLE_CALL_SETUP_REQUESTED_FROM_SIM";
case RIL_REQUEST_SCREEN_STATE: return "SCREEN_STATE";
case RIL_REQUEST_EXPLICIT_CALL_TRANSFER: return "EXPLICIT_CALL_TRANSFER";
case RIL_REQUEST_SET_LOCATION_UPDATES: return "SET_LOCATION_UPDATES";
case RIL_REQUEST_CDMA_SET_SUBSCRIPTION_SOURCE:return"CDMA_SET_SUBSCRIPTION_SOURCE";
case RIL_REQUEST_CDMA_SET_ROAMING_PREFERENCE:return"CDMA_SET_ROAMING_PREFERENCE";
case RIL_REQUEST_CDMA_QUERY_ROAMING_PREFERENCE:return"CDMA_QUERY_ROAMING_PREFERENCE";
case RIL_REQUEST_SET_TTY_MODE:return"SET_TTY_MODE";
case RIL_REQUEST_QUERY_TTY_MODE:return"QUERY_TTY_MODE";
case RIL_REQUEST_CDMA_SET_PREFERRED_VOICE_PRIVACY_MODE:return"CDMA_SET_PREFERRED_VOICE_PRIVACY_MODE";
case RIL_REQUEST_CDMA_QUERY_PREFERRED_VOICE_PRIVACY_MODE:return"CDMA_QUERY_PREFERRED_VOICE_PRIVACY_MODE";
case RIL_REQUEST_CDMA_FLASH:return"CDMA_FLASH";
case RIL_REQUEST_CDMA_BURST_DTMF:return"CDMA_BURST_DTMF";
case RIL_REQUEST_CDMA_SEND_SMS:return"CDMA_SEND_SMS";
case RIL_REQUEST_CDMA_SMS_ACKNOWLEDGE:return"CDMA_SMS_ACKNOWLEDGE";
case RIL_REQUEST_GSM_GET_BROADCAST_SMS_CONFIG:return"GSM_GET_BROADCAST_SMS_CONFIG";
case RIL_REQUEST_GSM_SET_BROADCAST_SMS_CONFIG:return"GSM_SET_BROADCAST_SMS_CONFIG";
case RIL_REQUEST_CDMA_GET_BROADCAST_SMS_CONFIG:return "CDMA_GET_BROADCAST_SMS_CONFIG";
case RIL_REQUEST_CDMA_SET_BROADCAST_SMS_CONFIG:return "CDMA_SET_BROADCAST_SMS_CONFIG";
case RIL_REQUEST_CDMA_SMS_BROADCAST_ACTIVATION:return "CDMA_SMS_BROADCAST_ACTIVATION";
case RIL_REQUEST_CDMA_VALIDATE_AND_WRITE_AKEY: return"CDMA_VALIDATE_AND_WRITE_AKEY";
case RIL_REQUEST_CDMA_SUBSCRIPTION: return"CDMA_SUBSCRIPTION";
case RIL_REQUEST_CDMA_WRITE_SMS_TO_RUIM: return "CDMA_WRITE_SMS_TO_RUIM";
case RIL_REQUEST_CDMA_DELETE_SMS_ON_RUIM: return "CDMA_DELETE_SMS_ON_RUIM";
case RIL_REQUEST_DEVICE_IDENTITY: return "DEVICE_IDENTITY";
case RIL_REQUEST_EXIT_EMERGENCY_CALLBACK_MODE: return "EXIT_EMERGENCY_CALLBACK_MODE";
case RIL_REQUEST_GET_SMSC_ADDRESS: return "GET_SMSC_ADDRESS";
case RIL_REQUEST_SET_SMSC_ADDRESS: return "SET_SMSC_ADDRESS";
case RIL_REQUEST_REPORT_SMS_MEMORY_STATUS: return "REPORT_SMS_MEMORY_STATUS";
case RIL_REQUEST_REPORT_STK_SERVICE_IS_RUNNING: return "REPORT_STK_SERVICE_IS_RUNNING";
case RIL_REQUEST_CDMA_GET_SUBSCRIPTION_SOURCE: return "CDMA_GET_SUBSCRIPTION_SOURCE";
case RIL_REQUEST_ISIM_AUTHENTICATION: return "ISIM_AUTHENTICATION";
case RIL_REQUEST_ACKNOWLEDGE_INCOMING_GSM_SMS_WITH_PDU: return "RIL_REQUEST_ACKNOWLEDGE_INCOMING_GSM_SMS_WITH_PDU";
case RIL_REQUEST_STK_SEND_ENVELOPE_WITH_STATUS: return "RIL_REQUEST_STK_SEND_ENVELOPE_WITH_STATUS";
case RIL_REQUEST_VOICE_RADIO_TECH: return "VOICE_RADIO_TECH";
case RIL_REQUEST_GET_CELL_INFO_LIST: return"GET_CELL_INFO_LIST";
case RIL_REQUEST_SET_UNSOL_CELL_INFO_LIST_RATE: return"SET_UNSOL_CELL_INFO_LIST_RATE";
case RIL_REQUEST_SET_INITIAL_ATTACH_APN: return "RIL_REQUEST_SET_INITIAL_ATTACH_APN";
case RIL_REQUEST_IMS_REGISTRATION_STATE: return "IMS_REGISTRATION_STATE";
case RIL_REQUEST_IMS_SEND_SMS: return "IMS_SEND_SMS";
case RIL_REQUEST_SIM_TRANSMIT_APDU_BASIC: return "SIM_TRANSMIT_APDU_BASIC";
case RIL_REQUEST_SIM_OPEN_CHANNEL: return "SIM_OPEN_CHANNEL";
case RIL_REQUEST_SIM_CLOSE_CHANNEL: return "SIM_CLOSE_CHANNEL";
case RIL_REQUEST_SIM_TRANSMIT_APDU_CHANNEL: return "SIM_TRANSMIT_APDU_CHANNEL";
case RIL_REQUEST_SET_UICC_SUBSCRIPTION: return "SET_UICC_SUBSCRIPTION";
case RIL_REQUEST_ALLOW_DATA: return "ALLOW_DATA";
case RIL_REQUEST_GET_HARDWARE_CONFIG: return "GET_HARDWARE_CONFIG";
case RIL_REQUEST_SIM_AUTHENTICATION: return "SIM_AUTHENTICATION";
case RIL_REQUEST_GET_DC_RT_INFO: return "GET_DC_RT_INFO";
case RIL_REQUEST_SET_DC_RT_INFO_RATE: return "SET_DC_RT_INFO_RATE";
case RIL_REQUEST_SET_DATA_PROFILE: return "SET_DATA_PROFILE";
case RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED: return "UNSOL_RESPONSE_RADIO_STATE_CHANGED";
case RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED: return "UNSOL_RESPONSE_CALL_STATE_CHANGED";
case RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED: return "UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED";
case RIL_UNSOL_RESPONSE_NEW_SMS: return "UNSOL_RESPONSE_NEW_SMS";
case RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT: return "UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT";
case RIL_UNSOL_RESPONSE_NEW_SMS_ON_SIM: return "UNSOL_RESPONSE_NEW_SMS_ON_SIM";
case RIL_UNSOL_ON_USSD: return "UNSOL_ON_USSD";
case RIL_UNSOL_ON_USSD_REQUEST: return "UNSOL_ON_USSD_REQUEST(obsolete)";
case RIL_UNSOL_NITZ_TIME_RECEIVED: return "UNSOL_NITZ_TIME_RECEIVED";
case RIL_UNSOL_SIGNAL_STRENGTH: return "UNSOL_SIGNAL_STRENGTH";
case RIL_UNSOL_STK_SESSION_END: return "UNSOL_STK_SESSION_END";
case RIL_UNSOL_STK_PROACTIVE_COMMAND: return "UNSOL_STK_PROACTIVE_COMMAND";
case RIL_UNSOL_STK_EVENT_NOTIFY: return "UNSOL_STK_EVENT_NOTIFY";
case RIL_UNSOL_STK_CALL_SETUP: return "UNSOL_STK_CALL_SETUP";
case RIL_UNSOL_SIM_SMS_STORAGE_FULL: return "UNSOL_SIM_SMS_STORAGE_FUL";
case RIL_UNSOL_SIM_REFRESH: return "UNSOL_SIM_REFRESH";
case RIL_UNSOL_DATA_CALL_LIST_CHANGED: return "UNSOL_DATA_CALL_LIST_CHANGED";
case RIL_UNSOL_CALL_RING: return "UNSOL_CALL_RING";
case RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED: return "UNSOL_RESPONSE_SIM_STATUS_CHANGED";
case RIL_UNSOL_RESPONSE_CDMA_NEW_SMS: return "UNSOL_NEW_CDMA_SMS";
case RIL_UNSOL_RESPONSE_NEW_BROADCAST_SMS: return "UNSOL_NEW_BROADCAST_SMS";
case RIL_UNSOL_CDMA_RUIM_SMS_STORAGE_FULL: return "UNSOL_CDMA_RUIM_SMS_STORAGE_FULL";
case RIL_UNSOL_RESTRICTED_STATE_CHANGED: return "UNSOL_RESTRICTED_STATE_CHANGED";
case RIL_UNSOL_ENTER_EMERGENCY_CALLBACK_MODE: return "UNSOL_ENTER_EMERGENCY_CALLBACK_MODE";
case RIL_UNSOL_CDMA_CALL_WAITING: return "UNSOL_CDMA_CALL_WAITING";
case RIL_UNSOL_CDMA_OTA_PROVISION_STATUS: return "UNSOL_CDMA_OTA_PROVISION_STATUS";
case RIL_UNSOL_CDMA_INFO_REC: return "UNSOL_CDMA_INFO_REC";
case RIL_UNSOL_OEM_HOOK_RAW: return "UNSOL_OEM_HOOK_RAW";
case RIL_UNSOL_RINGBACK_TONE: return "UNSOL_RINGBACK_TONE";
case RIL_UNSOL_RESEND_INCALL_MUTE: return "UNSOL_RESEND_INCALL_MUTE";
case RIL_UNSOL_CDMA_SUBSCRIPTION_SOURCE_CHANGED: return "UNSOL_CDMA_SUBSCRIPTION_SOURCE_CHANGED";
case RIL_UNSOL_CDMA_PRL_CHANGED: return "UNSOL_CDMA_PRL_CHANGED";
case RIL_UNSOL_EXIT_EMERGENCY_CALLBACK_MODE: return "UNSOL_EXIT_EMERGENCY_CALLBACK_MODE";
case RIL_UNSOL_RIL_CONNECTED: return "UNSOL_RIL_CONNECTED";
case RIL_UNSOL_VOICE_RADIO_TECH_CHANGED: return "UNSOL_VOICE_RADIO_TECH_CHANGED";
case RIL_UNSOL_CELL_INFO_LIST: return "UNSOL_CELL_INFO_LIST";
case RIL_UNSOL_RESPONSE_IMS_NETWORK_STATE_CHANGED: return "RESPONSE_IMS_NETWORK_STATE_CHANGED";
case RIL_UNSOL_UICC_SUBSCRIPTION_STATUS_CHANGED: return "UNSOL_UICC_SUBSCRIPTION_STATUS_CHANGED";
case RIL_UNSOL_SRVCC_STATE_NOTIFY: return "UNSOL_SRVCC_STATE_NOTIFY";
case RIL_UNSOL_HARDWARE_CONFIG_CHANGED: return "HARDWARE_CONFIG_CHANGED";
case RIL_UNSOL_DC_RT_INFO_CHANGED: return "UNSOL_DC_RT_INFO_CHANGED";
case RIL_REQUEST_SHUTDOWN: return "SHUTDOWN";
default: return "<unknown request>";
}
}
const char *
rilSocketIdToString(RIL_SOCKET_ID socket_id)
{
switch(socket_id) {
case RIL_SOCKET_1:
return "RIL_SOCKET_1";
#if (SIM_COUNT >= 2)
case RIL_SOCKET_2:
return "RIL_SOCKET_2";
#endif
#if (SIM_COUNT >= 3)
case RIL_SOCKET_3:
return "RIL_SOCKET_3";
#endif
#if (SIM_COUNT >= 4)
case RIL_SOCKET_4:
return "RIL_SOCKET_4";
#endif
default:
return "not a valid RIL";
}
}
} /* namespace android */
diff --git a/libril/ril.cpp b/libril/ril.cpp
index feaf60f..8fc6145 100644
--- a/libril/ril.cpp
+++ b/libril/ril.cpp
@@ -17,6 +17,16 @@
#define LOG_TAG "RILC"
+#define REMOTE_MODE_SERVER 0
+#define REMOTE_MODE_CLIENT 1
+#define REMOTE_MODE_ORIGINAL 2
+#define REMOTE_MODE_SELF_TEST 3
+
+#define REMOTE_MODE REMOTE_MODE_SERVER
+
+#define REMOTE_ADDR "000.000.000.000"
+#define REMOTE_PORT 1100
+
#include <hardware_legacy/power.h>
#include <telephony/ril.h>
@@ -30,6 +40,8 @@
#include <binder/Parcel.h>
#include <cutils/jstring.h>
+#include <arpa/inet.h>
+#include <sys/socket.h>
#include <sys/types.h>
#include <sys/limits.h>
#include <pwd.h>
@@ -91,7 +103,7 @@ namespace android {
#define PRINTBUF_SIZE 8096
// Enable RILC log
-#define RILC_LOG 0
+#define RILC_LOG 1
#if RILC_LOG
#define startRequest sprintf(printBuf, "(")
@@ -3500,41 +3512,43 @@ static void listenCallback (int fd, short flags, void *param) {
/* check the credential of the other side and only accept socket from
* phone process
+ * TODO remove this whold block, bypass credential check? by yhpark
*/
- errno = 0;
- is_phone_socket = 0;
-
- err = getsockopt(fdCommand, SOL_SOCKET, SO_PEERCRED, &creds, &szCreds);
-
- if (err == 0 && szCreds > 0) {
- errno = 0;
- pwd = getpwuid(creds.uid);
- if (pwd != NULL) {
- if (strcmp(pwd->pw_name, p_info->processName) == 0) {
- is_phone_socket = 1;
- } else {
- RLOGE("RILD can't accept socket from process %s", pwd->pw_name);
- }
- } else {
- RLOGE("Error on getpwuid() errno: %d", errno);
- }
- } else {
- RLOGD("Error on getsockopt() errno: %d", errno);
- }
-
- if (!is_phone_socket) {
- RLOGE("RILD must accept socket from %s", p_info->processName);
- close(fdCommand);
- fdCommand = -1;
-
- onCommandsSocketClosed(p_info->socket_id);
-
- /* start listening for new connections again */
- rilEventAddWakeup(p_info->listen_event);
-
- return;
- }
+// errno = 0;
+// is_phone_socket = 0;
+//
+// err = getsockopt(fdCommand, SOL_SOCKET, SO_PEERCRED, &creds, &szCreds);
+//
+// if (err == 0 && szCreds > 0) {
+// errno = 0;
+// pwd = getpwuid(creds.uid);
+// if (pwd != NULL) {
+// if (strcmp(pwd->pw_name, p_info->processName) == 0) {
+// is_phone_socket = 1;
+// } else {
+// RLOGE("RILD can't accept socket from process %s", pwd->pw_name);
+// }
+// } else {
+// RLOGE("Error on getpwuid() errno: %d", errno);
+// }
+// } else {
+// RLOGD("Error on getsockopt() errno: %d", errno);
+// }
+//
+// if (!is_phone_socket) {
+// RLOGE("RILD must accept socket from %s", p_info->processName);
+//
+// close(fdCommand);
+// fdCommand = -1;
+//
+// onCommandsSocketClosed(p_info->socket_id);
+//
+// /* start listening for new connections again */
+// rilEventAddWakeup(p_info->listen_event);
+//
+// return;
+// }
ret = fcntl(fdCommand, F_SETFL, O_NONBLOCK);
@@ -3819,6 +3833,101 @@ extern "C" void RIL_setcallbacks (const RIL_RadioFunctions *callbacks) {
memcpy(&s_callbacks, callbacks, sizeof (RIL_RadioFunctions));
}
+static void *transferProxy(void *arg) {
+ char buf[1024];
+ int fdRecv = ((int *) arg)[0];
+ int fdSend = ((int *) arg)[1];
+
+ while (true) {
+ RLOGI("proxy: recieve from %d", fdRecv);
+ int read = recv(fdRecv, buf, sizeof buf, 0);
+ if (read == 0) break;
+ if (read < 0) {
+ RLOGE("Failed to receive from %d", fdRecv);
+ return (void *) -1;
+ }
+
+ RLOGI("proxy: send to %d, %d bytes", fdSend, read);
+ int err = send(fdSend, buf, read, 0);
+ if (err < 0) {
+ RLOGE("Failed to send to %d", fdSend);
+ return (void *) -1;
+ }
+ }
+
+ return 0;
+}
+
+// Proxy for client
+static void *startProxy(void *arg) {
+ struct sockaddr_in addr;
+ int fdConnect;
+ int fdListen = (int) arg;
+
+ RLOGI("fdListen: %d", arg);
+
+ while (true) {
+ RLOGI("Accepting original socket");
+
+ struct sockaddr_un peeraddr;
+ socklen_t socklen = sizeof (peeraddr);
+
+ struct ucred creds;
+ socklen_t szCreds = sizeof(creds);
+
+ int fdLocal = accept(fdListen, (sockaddr *) &peeraddr, &socklen);
+
+ if (fdLocal < 0) {
+ RLOGE("Error on accept() errno:%d", errno);
+ /* start listening for new connections again */
+ return 0;
+ }
+
+ RLOGI("Initializing proxy socket");
+
+ fdConnect = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
+
+ if (fdConnect < 0) {
+ RLOGE("Failed to create socket");
+ goto retry;
+ }
+
+ memset(&addr, 0, sizeof addr);
+
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons(REMOTE_PORT);
+ inet_pton(AF_INET, REMOTE_ADDR, &addr.sin_addr);
+
+ if (connect(fdConnect, (struct sockaddr *) &addr, sizeof addr) < 0) {
+ RLOGE("Failed to connect");
+ goto retry;
+ }
+
+ RLOGI("proxy connected");
+
+ {
+ RLOGI("client: %d, server: %d", fdLocal, fdConnect);
+ int arg_a[] = { fdConnect, fdLocal };
+ int arg_b[] = { fdLocal, fdConnect };
+
+ pthread_t th_a, th_b;
+ pthread_create(&th_a, NULL, transferProxy, (void *) arg_a);
+ pthread_create(&th_b, NULL, transferProxy, (void *) arg_b);
+
+ int status_a, status_b;
+ pthread_join(th_a, (void **) &status_a);
+ pthread_join(th_b, (void **) &status_b);
+ }
+retry:
+ RLOGI("Will retry starting proxy after 5 seconds");
+ close(fdLocal);
+ close(fdConnect);
+ sleep(5);
+ }
+
+ return 0;
+}
+
static void startListen(RIL_SOCKET_ID socket_id, SocketListenParam* socket_listen_p) {
int fdListen = -1;
int ret;
@@ -3852,12 +3961,70 @@ static void startListen(RIL_SOCKET_ID socket_id, SocketListenParam* socket_liste
RLOGI("Start to listen %s", rilSocketIdToString(socket_id));
+ #if (REMOTE_MODE == REMOTE_MODE_SERVER || REMOTE_MODE == REMOTE_MODE_SELF_TEST)
+
+ RLOGI("Initializing server socket");
+
+ struct sockaddr_in addr;
+ fdListen = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
+ if (fdListen == -1) {
+ RLOGE("Failed to create socket");
+ exit(-1);
+ }
+
+ int yes = 1;
+ if (setsockopt(fdListen, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) == -1) {
+ RLOGE("Failed to setsockopt");
+ exit(-1);
+ }
+
+ memset(&addr, 0, sizeof addr);
+
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons(REMOTE_PORT);
+ addr.sin_addr.s_addr = htonl(INADDR_ANY);
+
+ RLOGI("bind");
+
+ if (bind(fdListen, (struct sockaddr *) &addr, sizeof addr) == -1) {
+ RLOGE("Failed to bind socket");
+ close(fdListen);
+ exit(-1);
+ }
+
+ RLOGI("listen");
+
+ if (listen(fdListen, 4) < 0) {
+ RLOGE("Failed to listen socket");
+ close(fdListen);
+ exit(-1);
+ }
+
+ socket_listen_p->fdListen = fdListen;
+
+ RLOGI("ril event set");
+
+ /* note: non-persistent so we can accept only one connection at a time */
+ ril_event_set (socket_listen_p->listen_event, fdListen, false,
+ listenCallback, socket_listen_p);
+
+ rilEventAddWakeup (socket_listen_p->listen_event);
+
+ #endif
+ #if (REMOTE_MODE == REMOTE_MODE_ORIGINAL || REMOTE_MODE == REMOTE_MODE_CLIENT || REMOTE_MODE == REMOTE_MODE_SELF_TEST)
+
+ RLOGI("Initializing original socket");
+
fdListen = android_get_control_socket(socket_name);
if (fdListen < 0) {
RLOGE("Failed to get socket %s", socket_name);
exit(-1);
}
+ RLOGI("fdListen: %d", fdListen);
+
+ RLOGI("listen");
+
ret = listen(fdListen, 4);
if (ret < 0) {
@@ -3865,6 +4032,11 @@ static void startListen(RIL_SOCKET_ID socket_id, SocketListenParam* socket_liste
fdListen, strerror(errno));
exit(-1);
}
+
+ #if (REMOTE_MODE == REMOTE_MODE_ORIGINAL)
+
+ RLOGI("ril event set");
+
socket_listen_p->fdListen = fdListen;
/* note: non-persistent so we can accept only one connection at a time */
@@ -3872,6 +4044,16 @@ static void startListen(RIL_SOCKET_ID socket_id, SocketListenParam* socket_liste
listenCallback, socket_listen_p);
rilEventAddWakeup (socket_listen_p->listen_event);
+
+ #endif
+ #if (REMOTE_MODE == REMOTE_MODE_CLIENT || REMOTE_MODE == REMOTE_MODE_SELF_TEST)
+
+ // startProxy
+ pthread_t th;
+ pthread_create(&th, NULL, startProxy, (void *) fdListen);
+
+ #endif
+ #endif
}
extern "C" void
@@ -4093,7 +4275,9 @@ RIL_onRequestComplete(RIL_Token t, RIL_Errno e, void *response, size_t responsel
pRI = (RequestInfo *)t;
+
if (!checkAndDequeueRequestInfo(pRI)) {
+ RLOGE ("%d %s", pRI->token, requestToString(pRI->pCI->requestNumber));
RLOGE ("RIL_onRequestComplete: invalid RIL_Token");
return;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment