blob: 41e2fd244fd5559072eb4b70d399bdbf9092ba10 [file] [log] [blame]
/* //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"
#include <hardware_legacy/power.h>
#include <telephony/ril.h>
#include <telephony/ril_cdma_sms.h>
#include <cutils/sockets.h>
#include <cutils/jstring.h>
#include <cutils/record_stream.h>
#include <utils/Log.h>
#include <utils/SystemClock.h>
#include <pthread.h>
#include <binder/Parcel.h>
#include <cutils/jstring.h>
#include <sys/types.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 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 0
#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
} RequestInfo;
typedef struct UserCallbackInfo {
RIL_TimedCallback p_callback;
void *userParam;
struct ril_event event;
struct UserCallbackInfo *p_next;
} UserCallbackInfo;
/*******************************************************************/
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_fdListen = -1;
static int s_fdCommand = -1;
static int s_fdDebug = -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 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_pendingRequestsMutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t s_writeMutex = PTHREAD_MUTEX_INITIALIZER;
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_pendingRequests = NULL;
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 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 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 dispatchCdmaSubscriptionSource (Parcel& p, RequestInfo *pRI);
static void dispatchCdmaSms(Parcel &p, RequestInfo *pRI);
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 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 decodeVoiceRadioTechnology (RIL_RadioState radioState);
static int decodeCdmaSubscriptionSource (RIL_RadioState radioState);
static RIL_RadioState processRadioState(RIL_RadioState newRadioState);
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);
#ifdef RIL_SHLIB
extern "C" void RIL_onUnsolicitedResponse(int unsolResponse, void *data,
size_t datalen);
#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 *
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) {
RequestInfo *pRI;
int ret;
pRI = (RequestInfo *)calloc(1, sizeof(RequestInfo));
pRI->local = 1;
pRI->token = 0xffffffff; // token is not used in this context
pRI->pCI = &(s_commands[request]);
ret = pthread_mutex_lock(&s_pendingRequestsMutex);
assert (ret == 0);
pRI->p_next = s_pendingRequests;
s_pendingRequests = pRI;
ret = pthread_mutex_unlock(&s_pendingRequestsMutex);
assert (ret == 0);
RLOGD("C[locl]> %s", requestToString(request));
s_callbacks.onRequest(request, data, len, pRI);
}
static int
processCommandBuffer(void *buffer, size_t buflen) {
Parcel p;
status_t status;
int32_t request;
int32_t token;
RequestInfo *pRI;
int ret;
p.setData((uint8_t *) buffer, buflen);
// status checked at end
status = p.readInt32(&request);
status = p.readInt32 (&token);
if (status != NO_ERROR) {
RLOGE("invalid request block");
return 0;
}
if (request < 1 || request >= (int32_t)NUM_ELEMS(s_commands)) {
RLOGE("unsupported request code %d token %d", request, token);
// FIXME this should perhaps return a response
return 0;
}
pRI = (RequestInfo *)calloc(1, sizeof(RequestInfo));
pRI->token = token;
pRI->pCI = &(s_commands[request]);
ret = pthread_mutex_lock(&s_pendingRequestsMutex);
assert (ret == 0);
pRI->p_next = s_pendingRequests;
s_pendingRequests = pRI;
ret = pthread_mutex_unlock(&s_pendingRequestsMutex);
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);
s_callbacks.onRequest(pRI->pCI->requestNumber, NULL, 0, pRI);
}
/** 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);
s_callbacks.onRequest(pRI->pCI->requestNumber, string8,
sizeof(char *), pRI);
#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);
s_callbacks.onRequest(pRI->pCI->requestNumber, pStrings, datalen, pRI);
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);
s_callbacks.onRequest(pRI->pCI->requestNumber, const_cast<int *>(pInts),
datalen, pRI);
#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);
s_callbacks.onRequest(pRI->pCI->requestNumber, &args, sizeof(args), pRI);
#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);
s_callbacks.onRequest(pRI->pCI->requestNumber, &dial, sizeOfDial, pRI);
#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);
s_callbacks.onRequest(pRI->pCI->requestNumber, &simIO, size, pRI);
#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_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);
s_callbacks.onRequest(pRI->pCI->requestNumber, &cff, sizeof(cff), pRI);
#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);
s_callbacks.onRequest(pRI->pCI->requestNumber, const_cast<void *>(data), len, pRI);
return;
invalid:
invalidCommandBlock(pRI);
return;
}
static void
dispatchCdmaSms(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) {
goto invalid;
}
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);
s_callbacks.onRequest(pRI->pCI->requestNumber, &rcsm, sizeof(rcsm),pRI);
#ifdef MEMSET_FREED
memset(&rcsm, 0, sizeof(rcsm));
#endif
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);
s_callbacks.onRequest(pRI->pCI->requestNumber, &rcsa, sizeof(rcsa),pRI);
#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;
}
s_callbacks.onRequest(pRI->pCI->requestNumber,
gsmBciPtrs,
num * sizeof(RIL_GSM_BroadcastSmsConfigInfo *),
pRI);
#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;
}
s_callbacks.onRequest(pRI->pCI->requestNumber,
cdmaBciPtrs,
num * sizeof(RIL_CDMA_BroadcastSmsConfigInfo *),
pRI);
#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);
s_callbacks.onRequest(pRI->pCI->requestNumber, &rcsw, sizeof(rcsw),pRI);
#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 = s_callbacks.onStateRequest();
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 = s_callbacks.onStateRequest();
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 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) {
int fd = s_fdCommand;
int ret;
uint32_t header;
if (s_fdCommand < 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(&s_writeMutex);
header = htonl(dataSize);
ret = blockingWrite(fd, (void *)&header, sizeof(header));
if (ret < 0) {
pthread_mutex_unlock(&s_writeMutex);
return ret;
}
ret = blockingWrite(fd, data, dataSize);
if (ret < 0) {
pthread_mutex_unlock(&s_writeMutex);
return ret;
}
pthread_mutex_unlock(&s_writeMutex);
return 0;
}
static int
sendResponse (Parcel &p) {
printResponse;
return sendResponseRaw(p.data(), p.dataSize());
}
/** 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("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("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("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("invalid response length %d expected multiple of %d",
(int)responselen, (int)sizeof(RIL_Data_Call_Response_v4));
return RIL_ERRNO_INVALID_RESPONSE;
}
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 responseDataCallList(Parcel &p, void *response, size_t responselen)
{
// Write version
p.writeInt32(s_callbacks.version);
if (s_callbacks.version < 5) {
return responseDataCallListV4(p, response, responselen);
} else {
if (response == NULL && responselen != 0) {
RLOGE("invalid response: NULL");
return RIL_ERRNO_INVALID_RESPONSE;
}
if (responselen % sizeof(RIL_Data_Call_Response_v6) != 0) {
RLOGE("invalid response length %d expected multiple of %d",
(int)responselen, (int)sizeof(RIL_Data_Call_Response_v6));
return RIL_ERRNO_INVALID_RESPONSE;
}
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 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("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("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("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_v6 *p_cur = ((RIL_SignalStrength_v6 *) 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)) {
p.writeInt32(p_cur->LTE_SignalStrength.signalStrength);
/*
* ril version <=6 receives negative values for rsrp
* workaround for backward compatibility
*/
p_cur->LTE_SignalStrength.rsrp =
((s_callbacks.version <= 6) && (p_cur->LTE_SignalStrength.rsrp < 0 )) ?
-(p_cur->LTE_SignalStrength.rsrp) : p_cur->LTE_SignalStrength.rsrp;
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);
} else {
memset(&p_cur->LTE_SignalStrength, sizeof (RIL_LTE_SignalStrength), 0);
}
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]",
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);
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 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;
}
/**
* 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() {
int ret;
RequestInfo *p_cur;
/* mark pending requests as "cancelled" so we dont report responses */
ret = pthread_mutex_lock(&s_pendingRequestsMutex);
assert (ret == 0);
p_cur = s_pendingRequests;
for (p_cur = s_pendingRequests
; p_cur != NULL
; p_cur = p_cur->p_next
) {
p_cur->cancelled = 1;
}
ret = pthread_mutex_unlock(&s_pendingRequestsMutex);
assert (ret == 0);
}
static void processCommandsCallback(int fd, short flags, void *param) {
RecordStream *p_rs;
void *p_record;
size_t recordlen;
int ret;
assert(fd == s_fdCommand);
p_rs = (RecordStream *)param;
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);
}
}
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(s_fdCommand);
s_fdCommand = -1;
ril_event_del(&s_commands_event);
record_stream_free(p_rs);
/* start listening for new connections again */
rilEventAddWakeup(&s_listen_event);
onCommandsSocketClosed();
}
}
static void onNewCommandConnect() {
// Inform we are connected and the ril version
int rilVer = s_callbacks.version;
RIL_onUnsolicitedResponse(RIL_UNSOL_RIL_CONNECTED,
&rilVer, sizeof(rilVer));
// implicit radio state changed
RIL_onUnsolicitedResponse(RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED,
NULL, 0);
// Send last NITZ time data, in case it was missed
if (s_lastNITZTimeData != NULL) {
sendResponseRaw(s_lastNITZTimeData, s_lastNITZTimeDataSize);
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;
RecordStream *p_rs;
struct sockaddr_un peeraddr;
socklen_t socklen = sizeof (peeraddr);
struct ucred creds;
socklen_t szCreds = sizeof(creds);
struct passwd *pwd = NULL;
assert (s_fdCommand < 0);
assert (fd == s_fdListen);
s_fdCommand = accept(s_fdListen, (sockaddr *) &peeraddr, &socklen);
if (s_fdCommand < 0 ) {
RLOGE("Error on accept() errno:%d", errno);
/* start listening for new connections again */
rilEventAddWakeup(&s_listen_event);
return;
}
/* check the credential of the other side and only accept socket from
* phone process
*/
errno = 0;
is_phone_socket = 0;
err = getsockopt(s_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, PHONE_PROCESS) == 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", PHONE_PROCESS);
close(s_fdCommand);
s_fdCommand = -1;
onCommandsSocketClosed();
/* start listening for new connections again */
rilEventAddWakeup(&s_listen_event);
return;
}
ret = fcntl(s_fdCommand, F_SETFL, O_NONBLOCK);
if (ret < 0) {
RLOGE ("Error setting O_NONBLOCK errno:%d", errno);
}
RLOGI("libril: new connection");
p_rs = record_stream_new(s_fdCommand, MAX_COMMAND_BYTES);
ril_event_set (&s_commands_event, s_fdCommand, 1,
processCommandsCallback, p_rs);
rilEventAddWakeup (&s_commands_event);
onNewCommandConnect();
}
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;
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 =