blob: 4a5e7d9dedda154d1367d0b69f1ce136ca680727 [file] [log] [blame]
</
/* //device/libs/telephony/ril.cpp
**
** Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
** Not a Contribution
** 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 <telephony/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 <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 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;
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_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 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 dispatchUiccSubscripton(Parcel &p, RequestInfo *pRI);
static void dispatchNetworkManual (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 responseStringsDataRegistrationState(Parcel &p, void *response, size_t responselen);
static int responseStringsNetworks(Parcel &p, void *response, size_t responselen);
static int responseStrings(Parcel &p, void *response, size_t responselen, bool network_search);
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 responseGetDataCallProfile(Parcel &p, void *response, size_t responselen);
static int responseSSData(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);
static bool isServiceTypeCfQuery(RIL_SsServiceType serType, RIL_SsRequestType reqType);
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 * 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) {
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 char * */
static void
dispatchNetworkManual (Parcel& p, RequestInfo *pRI) {
status_t status;
size_t datalen;
char **pStrings;
datalen = sizeof(char *) * 2;
startRequest;
pStrings = (char **)alloca(datalen);
pStrings[0] = strdupReadString(p);
appendPrintBuf("%s%s,", printBuf, pStrings[0]);
pStrings[1] = strdup("NOCHANGE");
closeRequest;
printRequest(pRI->token, pRI->pCI->requestNumber);
s_callbacks.onRequest(pRI->pCI->requestNumber, pStrings, datalen, pRI);
if (pStrings != NULL) {
for (int i = 0 ; i < 2 ; 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 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;
}
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
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;
s_callbacks.onRequest(pRI->pCI->requestNumber, &rism,
sizeof(RIL_RadioTechnologyFamily)+sizeof(uint8_t)+sizeof(int32_t)
+sizeof(rcsm),pRI);
#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("%sformat=%d,", printBuf, rism.format);
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;
s_callbacks.onRequest(pRI->pCI->requestNumber, &rism,
sizeof(RIL_RadioTechnologyFamily)+sizeof(uint8_t)+sizeof(int32_t)
+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
}
#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);
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 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, auth_type=%d, username=%s, password=%s",
printBuf, pf.apn, pf.protocol, pf.auth_type, pf.username, pf.password);
closeRequest;
printRequest(pRI->token, pRI->pCI->requestNumber);
if (status != NO_ERROR) {
goto invalid;
}
s_callbacks.onRequest(pRI->pCI->requestNumber, &pf, sizeof(pf), pRI);
#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 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);
s_callbacks.onRequest(pRI->pCI->requestNumber, &uicc_sub, sizeof(uicc_sub), pRI);
#ifdef MEMSET_FREED
memset(&uicc_sub, 0, sizeof(uicc_sub));
#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) {
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) {
return responseStrings(p, response, responselen, false);
}
static int responseStringsNetworks(Parcel &p, void *response, size_t responselen) {
return responseStrings(p, response, responselen, true);
}
/** response is a char **, pointing to an array of char *'s */
static int responseStrings(Parcel &p, void *response, size_t responselen, bool network_search) {
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 *);
#ifdef RIL_RESPONSE_5_ELEMENTS
if (network_search == true) {
// we only want four entries for each network
p.writeInt32 (numStrings - (numStrings / 5));
} else {
p.writeInt32 (numStrings);
}
int sCount = 0;
#else
p.writeInt32 (numStrings);
#endif
/* each string*/
startResponse;
for (int i = 0 ; i < numStrings ; i++) {
#ifdef RIL_RESPONSE_5_ELEMENTS
sCount++;
// ignore the fifth string that is returned by newer QCOM libOEM_ril.so.
if (network_search == true && sCount % 5 == 0) {
sCount = 0;
continue;
}
#endif
appendPrintBuf("%s%s,", printBuf, (char*)p_cur[i]);
writeStringToParcel (p, p_cur[i]);
}
removeLastChar;
closeResponse;
}
return 0;
}
/*
* RIL_RADIO_TECHNOLOGY: 18 (QCOM HSPAP_DC) ==> 30 (CM HSPAP_DC)
*/
static int responseStringsDataRegistrationState(Parcel &p, void *response, size_t responselen) {
if (response == NULL && responselen != 0) {
ALOGE("invalid response: NULL");
return RIL_ERRNO_INVALID_RESPONSE;
}
if (responselen % sizeof(char *) != 0) {
ALOGE("invalid response length %d expected multiple of %d\n",
(int)responselen, (int)sizeof(char *));
return RIL_ERRNO_INVALID_RESPONSE;
}
char **p_cur = (char **) response;
if (p_cur[3] != NULL) {
if (strncmp(p_cur[3], "18", 2) == 0) {
ALOGE("DATA_REGISTRATION_STATE: old radio tech=18 (QCOM HSPAP_DC), new radio tech=30 (CM HSPAP_DC)");
// RIL_RADIO_TECHNOLOGY_DCHSPAP = 30
strncpy(p_cur[3], "30", 2);
}
}
return responseStrings(p, response, responselen);
}
/**
* 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);
#ifndef HCRADIO
p.writeInt32(p_cur[i].suggestedRetryTime);
#endif
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_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;
}
// Write as a byteArray
p.writeInt32(infoRec->rec.display.alpha_len);
p.write(infoRec->rec.display.alpha_buf,
infoRec->rec.display.alpha_len);
break;
case RIL_CDMA_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_v9_CAF *p_cur = ((RIL_SignalStrength_v9_CAF *) 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_v8)) {
p.writeInt32(p_cur->LTE_SignalStrength.timingAdvance);
if (responselen >= sizeof (RIL_SignalStrength_v9_CAF)) {
p.writeInt32(p_cur->TD_SCDMA_SignalStrength.rscp);
} else {
p.writeInt32(INT_MAX);
}
} else {
p.writeInt32(INT_MAX);
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);
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]",
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 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("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;
}
}
p_cur += 1;
}
removeLastChar;
closeResponse;
return 0;
}
static int responseSSData(Parcel &p, void *response, size_t responselen) {
RLOGD("In responseSSData");
int num;
if (response == NULL && responselen != 0) {
RLOGE("invalid response: NULL");
return RIL_ERRNO_INVALID_RESPONSE;
}
if (responselen != sizeof(RIL_StkCcUnsolSsResponse)) {
RLOGE("invalid response length %d, expected %d",
(int)responselen, (int)sizeof(RIL_StkCcUnsolSsResponse));
return RIL_ERRNO_INVALID_RESPONSE;
}
startResponse;
RIL_StkCcUnsolSsResponse *p_cur = (RIL_StkCcUnsolSsResponse *) response;
p.writeInt32(p_cur->serviceType);
p.writeInt32(p_cur->requestType);
p.writeInt32(p_cur->teleserviceType);
p.writeInt32(p_cur->serviceClass);
p.writeInt32(p_cur->result);
if (isServiceTypeCfQuery(p_cur->serviceType, p_cur->requestType)) {
RLOGD("responseSSData CF type, num of Cf elements %d", p_cur->cfData.numValidIndexes);
if (p_cur->cfData.numValidIndexes > NUM_SERVICE_CLASSES) {
RLOGE("numValidIndexes is greater than max value %d, "
"truncating it to max value", NUM_SERVICE_CLASSES);
p_cur->cfData.numValidIndexes = NUM_SERVICE_CLASSES;
}
/* number of call info's */
p.writeInt32(p_cur->cfData.numValidIndexes);
for (int i = 0; i < p_cur->cfData.numValidIndexes; i++) {
RIL_CallForwardInfo cf = p_cur->cfData.cfInfo[i];
p.writeInt32(cf.status);
p.writeInt32(cf.reason);
p.writeInt32(cf.serviceClass);
p.writeInt32(cf.toa);
writeStringToParcel(p, cf.number);
p.writeInt32(cf.timeSeconds);
appendPrintBuf("%s[%s,reason=%d,cls=%d,toa=%d,%s,tout=%d],", printBuf,
(cf.status==1)?"enable":"disable", cf.reason, cf.serviceClass, cf.toa,
(char*)cf.number, cf.timeSeconds);
RLOGD("Data: %d,reason=%d,cls=%d,toa=%d,num=%s,tout=%d],", cf.status,
cf.reason, cf.serviceClass, cf.toa, (char*)cf.number, cf.timeSeconds);
}
} else {
p.writeInt32 (SS_INFO_MAX);
/* each int*/
for (int i = 0; i < SS_INFO_MAX; i++) {
appendPrintBuf("%s%d,", printBuf, p_cur->ssInfo[i]);
RLOGD("Data: %d",p_cur->ssInfo[i]);
p.writeInt32(p_cur->ssInfo[i]);
}
}
removeLastChar;
closeResponse;
return 0;
}
static bool isServiceTypeCfQuery(RIL_SsServiceType serType, RIL_SsRequestType reqType) {
if ((reqType == SS_INTERROGATION) &&
(serType == SS_CFU ||
serType == SS_CF_BUSY ||
serType == SS_CF_NO_REPLY ||
serType == SS_CF_NOT_REACHABLE ||
serType == SS_CF_ALL ||
serType == SS_CF_ALL_CONDITIONAL)) {
return true;
}
return false;
}
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;