ril.cpp解析

来源:互联网 发布:sql身份证取性别 编辑:程序博客网 时间:2024/06/08 16:05
/* //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 <telephony/ril.h>#include <cutils/sockets.h>#include <cutils/jstring.h>#include <cutils/record_stream.h>#include <utils/Log.h>#include <pthread.h>#include <utils/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>/*AT指令的格式AT Command Set For Nokia CDMAA short description, the syntax, and the possible setting values are presented for each AT command. The syntax for the AT commands listed in this document conforms with the industry-wide notation. Commands can be given as single commands (for example, AT+CRM=1) or concatenated in a string of commands (for example, AT+CRM=1;+CSO=33). For commands with more than one parameter (for example, AT+FIS=n,n,n,n,n,n,n,n), a comma can be used to skip over a parameter so that its valueis not changed. For instance, if +FIS is initially 0,0,0,0,0,0,0,0, issuing “AT+FIS=,,1,,,,,7” changes +FIS to 0,0,1,0,0,0,0,7.Computers use AT commands to communicate with modems. Most communications applications, however, have a user interface that hides the AT commands from the user. AT commands can be issued via a communications application. When the software in the Nokia product has received an AT command, it responds with a message that is displayed on the screen of the used device, whichcan also be the mobile device.The AT commands listed in this document are supported by all Nokia products and all operators.AT Command SyntaxThe “AT” or “at ” prefix must be added to the beginning of each command line. Several AT commands can be typed on the same line, and in such cases the “AT” or “at” prefixis needed only once, at the beginning of the command line.The marking n used in the command syntax is the setting value typed in as a part of the command. If the value is optional, it is indicated in the Syntax column of the tables. When a setting value is set with an AT command, the setting is valid until you change it or reboot the device.Basic commandsA basic command has no ‘+’ prefix. If there is no default value, the setting of that command is not stored in the non-volatile memory.S-register commandsThe existence and values of an S-register command can be queried by giving the command with aquestion mark (for example, ATS3?).Extended commandsExtended command have a ‘+’ prefix.Some extended commands take more than one value (for example, AT+DS=n,n,n,n), and some extended commands take character strings as values instead of numbers (for example AT+MA=<string>).Command lineA command line consists of the Attention code, followed by one or more commands, followed by the end of line code. The Attention code is the character pair “AT” or “at.” By default,the end of line character is the ASCII CR character (decimal 13), unless it is changed by the S3 command. The basic and S-register commands can follow each other on the command line. An extended command must be terminated with a semicolon (;) if another command follows it on a single command line. A semicolon is not required after the last command on the line.ATCMD1 CMD2=12; +CMD1; +CMD2=,,15; +CMD2?; +CMD2=?<CR>commands line prefixbasic command (no + prefix)subparameterextended command (prefixed with +)extended commands are delimited with semicolonread command for checking current subparameter valuessubparameters may be omittedbest command for checking possible subparameter valuescommand line terminationAlmost all extended commands have a test command (=?) for testing the existence of the command and to give information about the type of its subparameters. Almost all parameter type commands also have a read command (?) to check the current values of subparameters. Action type commandsdo not store the values of any of their possible subparameters, and therefore they do not have a read command.AT Command Set For Nokia CDMA Products 14Forum.Nokia.comIf verbose responses are enabled with the ATV1 command and all commands in a command line have been successfully performed, the result code <CR><LF>OK<CR><LF> is sent from the terminal adaptor to the terminal equipment. If numeric responses are enabled with the ATV0 command, the result code 0<CR> is sent instead.If the command syntax is incorrect, an ERROR string is returned.例子:Command:AT+CGMI<CR>Response:<CR><LF>Nokia<CR><LF><CR><LF>OK<CR><LF>*/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 ANDROID_PARTIAL_WAKE_LOCK_PATH "/sys/android_power/acquire_partial_wake_lock"#define ANDROID_FULL_WAKE_LOCK_PATH "/sys/android_power/acquire_full_wake_lock"#define ANDROID_WAKE_UNLOCK_PATH "/sys/android_power/release_wake_lock"#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])/* 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)           \            LOGD("[%04d]> %s %s", token, requestToString(req), printBuf)    #define startResponse           sprintf(printBuf, "%s {", printBuf)    #define closeResponse           sprintf(printBuf, "%s}", printBuf)    #define printResponse           LOGD("%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...)#endifenum WakeType {DONT_WAKE, WAKE_PARTIAL, WAKE_FULL};/*一次请求的dispatch和response函数*/typedef struct {    int requestNumber;    void (*dispatchFunction) (Parcel &p, struct RequestInfo *pRI);    //只有成功了才回调,主要功能是处理返回值,把返回的数据写到Parcel里面    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;/*一次请求的信息,保包含了token*/typedef struct RequestInfo {    int32_t token;      //this is not RIL_Token ,是一个整形值    CommandInfo *pCI; //包含了request号,处理函数和处理返回值的函数    struct RequestInfo *p_next;//链表的下一个元素    char cancelled; //是否已经cancel了    /*    responses to local commands do not go back to command process    如果是本地发起的一个request,就不要再将回复发到command进程    */    char local;         } RequestInfo;/*timeout的event使用的,和RequestInfo对应,RequestInfo里面存的是一个来自客户端(或者debug)的请求信息,UserCallbackInfo存的是一个来自内部的请求(不是local,local对应于debug事件)*/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; //RIL_Register已经调用,s_callbacks已经赋值static pthread_t s_tid_dispatch; static pthread_t s_tid_reader; //本文件的这个线程值没有使用static int s_started = 0; //用于标识event_loop已经开始了static int s_fdListen = -1; //监听客户端连接的server句柄,连接以后会得到s_fdCommand句柄static int s_fdCommand = -1; //接收来自客户端命令的句柄,所有的request都来自这个句柄static int s_fdDebug = -1;//监听Debug命令的句柄,连接以后会生成另外一个fd,不过是临时变量//下面两个是唤醒多路复用(select)的pipe的两端句柄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 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 responseContexts(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);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_SHLIBextern "C" void RIL_onUnsolicitedResponse(int unsolResponse, void *data,                                 size_t datalen);#endif//内部发起的timer_eventstatic 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"};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 voidmemsetString (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  构建本地请求(通常来自debug)的RequestInfo结构 */static voidissueLocalRequest(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);    LOGD("C[locl]> %s", requestToString(request));//调用请求,这是个同步函数    s_callbacks.onRequest(request, data, len, pRI);}static intprocessCommandBuffer(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) {        LOGE("invalid request block");        return 0;    }    if (request < 1 || request >= (int32_t)NUM_ELEMS(s_commands)) {        LOGE("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 voidinvalidCommandBlock (RequestInfo *pRI){    LOGE("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 voiddispatchString (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 voiddispatchStrings (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 voiddispatchInts (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 voiddispatchSmsWrite (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 voiddispatchDial (Parcel &p, RequestInfo *pRI){    RIL_Dial dial;    int32_t t;    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;    }    startRequest;    appendPrintBuf("%snum=%s,clir=%d", printBuf, dial.address, dial.clir);    closeRequest;    printRequest(pRI->token, pRI->pCI->requestNumber);    s_callbacks.onRequest(pRI->pCI->requestNumber, &dial, sizeof(dial), pRI);#ifdef MEMSET_FREED    memsetString (dial.address);#endif    free (dial.address);    #ifdef MEMSET_FREED    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  */static voiddispatchSIM_IO (Parcel &p, RequestInfo *pRI){    RIL_SIM_IO simIO;    int32_t t;    status_t status;    memset (&simIO, 0, sizeof(simIO));    // note we only check status at the end         status = p.readInt32(&t);    simIO.command = (int)t;    status = p.readInt32(&t);    simIO.fileid = (int)t;    simIO.path = strdupReadString(p);    status = p.readInt32(&t);    simIO.p1 = (int)t;    status = p.readInt32(&t);    simIO.p2 = (int)t;    status = p.readInt32(&t);    simIO.p3 = (int)t;    simIO.data = strdupReadString(p);    simIO.pin2 = strdupReadString(p);    startRequest;    appendPrintBuf("%scmd=0x%X,efid=0x%X,path=%s,%d,%d,%d,%s,pin2=%s", printBuf,        simIO.command, simIO.fileid, (char*)simIO.path,        simIO.p1, simIO.p2, simIO.p3,        (char*)simIO.data,  (char*)simIO.pin2);    closeRequest;    printRequest(pRI->token, pRI->pCI->requestNumber);        if (status != NO_ERROR) {        goto invalid;    }       s_callbacks.onRequest(pRI->pCI->requestNumber, &simIO, sizeof(simIO), pRI);#ifdef MEMSET_FREED    memsetString (simIO.path);    memsetString (simIO.data);    memsetString (simIO.pin2);#endif    free (simIO.path);    free (simIO.data);    free (simIO.pin2);    #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 intblockingWrite(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);        if (written >= 0) {            writeOffset += written;        } else {   // written < 0            LOGE ("RIL Response: unexpected error on write errno:%d", errno);            close(fd);            return -1;        }    }    return 0;}static intsendResponseRaw (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) {        LOGE("RIL: packet larger than %u (%u)",                MAX_COMMAND_BYTES, (unsigned int )dataSize);        return -1;    }        // FIXME is blocking here ok? issue #550970    pthread_mutex_lock(&s_writeMutex);    header = htonl(dataSize);    ret = blockingWrite(fd, (void *)&header, sizeof(header));    if (ret < 0) {        return ret;    }    blockingWrite(fd, data, dataSize);    if (ret < 0) {        return ret;    }    pthread_mutex_unlock(&s_writeMutex);    return 0;}static intsendResponse (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) {        LOGE("invalid response: NULL");        return RIL_ERRNO_INVALID_RESPONSE;    }    if (responselen % sizeof(int) != 0) {        LOGE("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 */static int responseStrings(Parcel &p, void *response, size_t responselen){    int numStrings;        if (response == NULL && responselen != 0) {        LOGE("invalid response: NULL");        return RIL_ERRNO_INVALID_RESPONSE;    }    if (responselen % sizeof(char *) != 0) {        LOGE("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) {        LOGE("invalid response: NULL");        return RIL_ERRNO_INVALID_RESPONSE;    }    if (responselen % sizeof (RIL_Call *) != 0) {        LOGE("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);        writeStringToParcel (p, p_cur->number);        appendPrintBuf("%s[%s,id=%d,toa=%d,%s,%s,als=%d,%s,%s],", printBuf,            callStateToString(p_cur->state),            p_cur->index, p_cur->toa,            (p_cur->isMpty)?"mpty":"norm",            (p_cur->isMT)?"mt":"mo",            p_cur->als,            (p_cur->isVoice)?"voc":"nonvoc",            (char*)p_cur->number);    }    removeLastChar;    closeResponse;    return 0;}static int responseSMS(Parcel &p, void *response, size_t responselen){    if (response == NULL) {        LOGE("invalid response: NULL");        return RIL_ERRNO_INVALID_RESPONSE;    }    if (responselen != sizeof (RIL_SMS_Response) ) {        LOGE("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);    startResponse;    appendPrintBuf("%s%d,%s", printBuf, p_cur->messageRef,        (char*)p_cur->ackPDU);    closeResponse;    return 0;}static int responseContexts(Parcel &p, void *response, size_t responselen){    if (response == NULL && responselen != 0) {        LOGE("invalid response: NULL");        return RIL_ERRNO_INVALID_RESPONSE;    }    if (responselen % sizeof(RIL_PDP_Context_Response) != 0) {        LOGE("invalid response length %d expected multiple of %d",                 (int)responselen, (int)sizeof(RIL_PDP_Context_Response));        return RIL_ERRNO_INVALID_RESPONSE;    }    int num = responselen / sizeof(RIL_PDP_Context_Response);    p.writeInt32(num);    RIL_PDP_Context_Response *p_cur = (RIL_PDP_Context_Response *) 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);        writeStringToParcel(p, p_cur[i].apn);        writeStringToParcel(p, p_cur[i].address);        appendPrintBuf("%s[cid=%d,%s,%s,%s,%s],", printBuf,            p_cur[i].cid,            (p_cur[i].active==0)?"down":"up",            (char*)p_cur[i].type,            (char*)p_cur[i].apn,            (char*)p_cur[i].address);    }    removeLastChar;    closeResponse;    return 0;}static int responseRaw(Parcel &p, void *response, size_t responselen){    if (response == NULL && responselen != 0) {        LOGE("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) {        LOGE("invalid response: NULL");        return RIL_ERRNO_INVALID_RESPONSE;    }    if (responselen != sizeof (RIL_SIM_IO_Response) ) {        LOGE("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) {        LOGE("invalid response: NULL");        return RIL_ERRNO_INVALID_RESPONSE;    }    if (responselen % sizeof(RIL_CallForwardInfo *) != 0) {        LOGE("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) {        LOGE("invalid response: NULL");        return RIL_ERRNO_INVALID_RESPONSE;    }    if (responselen != sizeof(RIL_SuppSvcNotification)) {        LOGE("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;}/** * 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;    LOGV("processWakeupCallback");    /* empty our wakeup socket out */    do {        ret = read(s_fdWakeupRead, &buff, sizeof(buff));    } while (ret > 0 || (ret < 0 && errno == EINTR)); }/*有人connect了,但它可能没有权限,所以又被我们关闭了*/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) {            LOGE("error on reading command socket errno:%d\n", errno);        } else {            LOGW("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 */        ril_event_add(&s_listen_event);        onCommandsSocketClosed();    }}static void onNewCommandConnect(){    // 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();        LOGI("RIL Daemon version: %s\n", version);                property_set(PROPERTY_RIL_IMPL, version);    } else {        LOGI("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);/*Linux 2.2支持Unix域套接字的一个附加特性:可以获取对端的“可信任证明”(pid、uid和gid)。*/    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 ) {        LOGE("Error on accept() errno:%d", errno);        /* start listening for new connections again */        ril_event_add(&s_listen_event);return;    }    /* check the credential of the other side and only accept socket from     * phone process     */     errno = 0;    is_phone_socket = 0;    /*Linux 2.2支持Unix域套接字的一个附加特性:可以获取对端的“可信任证明”(pid、uid和gid)。*/    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 {  LOGE("RILD can't accept socket from process %s", pwd->pw_name);}      } else {LOGE("Error on getpwuid() errno: %d", errno);      }    } else {      LOGD("Error on getsockopt() errno: %d", errno);    }    if ( !is_phone_socket ) {      LOGE("RILD must accept socket from %s", PHONE_PROCESS);              close(s_fdCommand);      s_fdCommand = -1;      onCommandsSocketClosed();      /* start listening for new connections again */      ril_event_add(&s_listen_event);      return;    }    ret = fcntl(s_fdCommand, F_SETFL, O_NONBLOCK);    if (ret < 0) {        LOGE ("Error setting O_NONBLOCK errno:%d", errno);    }    LOGI("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);    ril_event_add (&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) {        LOGE ("error accepting on debug port: %d\n", errno);        return;    }    if (recv(acceptFD, &number, sizeof(int), 0) != sizeof(int)) {        LOGE ("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)) {            LOGE ("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)             != sizeof(char) * len) {            LOGE ("error reading on socket: Args[%d] \n", i);            freeDebugCallbackArgs(i, args);            return;        }        char * buf = args[i];        buf[len] = 0;    }    switch (atoi(args[0])) {        case 0:            LOGI ("Connection on debug port: issuing reset.");            issueLocalRequest(RIL_REQUEST_RESET_RADIO, NULL, 0);            break;        case 1:            LOGI ("Connection on debug port: issuing radio power off.");            data = 0;            issueLocalRequest(RIL_REQUEST_RADIO_POWER, &data, sizeof(int));            // Close the socket            close(s_fdCommand);            s_fdCommand = -1;            break;        case 2:            LOGI ("Debug port: issuing unsolicited network change.");            RIL_onUnsolicitedResponse(RIL_UNSOL_RESPONSE_NETWORK_STATE_CHANGED,                                      NULL, 0);            break;        case 3:            LOGI ("Debug port: QXDM log enable.");            qxdm_data[0] = 65536;            qxdm_data[1] = 16;            qxdm_data[2] = 1;            qxdm_data[3] = 32;            qxdm_data[4] = 0;            qxdm_data[4] = 8;            issueLocalRequest(RIL_REQUEST_OEM_HOOK_RAW, qxdm_data,                               6 * sizeof(int));            break;        case 4:            LOGI ("Debug port: QXDM log disable.");            qxdm_data[0] = 65536;            qxdm_data[1] = 16;            qxdm_data[2] = 0;            qxdm_data[3] = 32;            qxdm_data[4] = 0;            qxdm_data[4] = 8;            issueLocalRequest(RIL_REQUEST_OEM_HOOK_RAW, qxdm_data,                              6 * sizeof(int));            break;        case 5:            LOGI("Debug port: Radio On");            data = 1;            issueLocalRequest(RIL_REQUEST_RADIO_POWER, &data, sizeof(int));            sleep(2);            // Set network selection automatic.            issueLocalRequest(RIL_REQUEST_SET_NETWORK_SELECTION_AUTOMATIC, NULL, 0);            break;        case 6:            LOGI("Debug port: Setup PDP, Apn :%s\n", args[1]);            actData[0] = args[1];            issueLocalRequest(RIL_REQUEST_SETUP_DEFAULT_PDP, &actData,                               sizeof(actData));            break;        case 7:            LOGI("Debug port: Deactivate PDP");            issueLocalRequest(RIL_REQUEST_DEACTIVATE_DEFAULT_PDP, &deactData,                               sizeof(deactData));            break;        case 8:            LOGI("Debug port: Dial Call");            dialData.clir = 0;            dialData.address = args[1];            issueLocalRequest(RIL_REQUEST_DIAL, &dialData, sizeof(dialData));            break;        case 9:            LOGI("Debug port: Answer Call");            issueLocalRequest(RIL_REQUEST_ANSWER, NULL, 0);            break;        case 10:            LOGI("Debug port: End Call");            issueLocalRequest(RIL_REQUEST_HANGUP, &hangupData,                               sizeof(hangupData));            break;        default:            LOGE ("Invalid request");            break;    }    freeDebugCallbackArgs(number, args);    close(acceptFD);}static void userTimerCallback (int fd, short flags, void *param){    UserCallbackInfo *p_info;    p_info = (UserCallbackInfo *)param;    p_info->p_callback(p_info->userParam);    // FIXME generalize this...there should be a cancel mechanism    if (s_last_wake_timeout_info != NULL && s_last_wake_timeout_info == p_info) {        s_last_wake_timeout_info = NULL;    }    free(p_info);}static void *eventLoop(void *param){    int ret;    int filedes[2];    ril_event_init();    pthread_mutex_lock(&s_startupMutex);    s_started = 1;    pthread_cond_broadcast(&s_startupCond);    pthread_mutex_unlock(&s_startupMutex);    ret = pipe(filedes);    if (ret < 0) {        LOGE("Error in pipe() errno:%d", errno);        return NULL;    }    s_fdWakeupRead = filedes[0];    s_fdWakeupWrite = filedes[1];    fcntl(s_fdWakeupRead, F_SETFL, O_NONBLOCK);    ril_event_set (&s_wakeupfd_event, s_fdWakeupRead, true,                processWakeupCallback, NULL);    ril_event_add (&s_wakeupfd_event);    // Only returns on error    ril_event_loop();    LOGE ("error in event_loop_base errno:%d", errno);    return NULL;}extern "C" void RIL_startEventLoop(void){    int ret;    pthread_attr_t attr;        /* spin up eventLoop thread and wait for it to get started */    s_started = 0;    pthread_mutex_lock(&s_startupMutex);    pthread_attr_init (&attr);    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);        ret = pthread_create(&s_tid_dispatch, &attr, eventLoop, NULL);    while (s_started == 0) {        pthread_cond_wait(&s_startupCond, &s_startupMutex);    }    pthread_mutex_unlock(&s_startupMutex);    if (ret < 0) {        LOGE("Failed to create dispatch thread errno:%d", errno);        return;    }}// Used for testing purpose only.extern "C" void RIL_setcallbacks (const RIL_RadioFunctions *callbacks) {    memcpy(&s_callbacks, callbacks, sizeof (RIL_RadioFunctions));}extern "C" void RIL_register (const RIL_RadioFunctions *callbacks){    int ret;    int flags;    if (callbacks == NULL         || ! (callbacks->version == RIL_VERSION || callbacks->version == 1)    ) {        LOGE(            "RIL_register: RIL_RadioFunctions * null or invalid version"            " (expected %d)", RIL_VERSION);        return;    }    if (s_registerCalled > 0) {        LOGE("RIL_register has been called more than once. "                "Subsequent call ignored");        return;    }    memcpy(&s_callbacks, callbacks, sizeof (RIL_RadioFunctions));    s_registerCalled = 1;    // Little self-check    for (int i = 0; i < (int)NUM_ELEMS(s_commands) ; i++) {        assert(i == s_commands[i].requestNumber);    }    for (int i = 0; i < (int)NUM_ELEMS(s_unsolResponses) ; i++) {        assert(i + RIL_UNSOL_RESPONSE_BASE                 == s_unsolResponses[i].requestNumber);    }    // New rild impl calls RIL_startEventLoop() first    // old standalone impl wants it here.    if (s_started == 0) {        RIL_startEventLoop();    }    // start listen socket#if 0    ret = socket_local_server (SOCKET_NAME_RIL,             ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);    if (ret < 0) {        LOGE("Unable to bind socket errno:%d", errno);        exit (-1);    }    s_fdListen = ret;#else    s_fdListen = android_get_control_socket(SOCKET_NAME_RIL);    if (s_fdListen < 0) {        LOGE("Failed to get socket '" SOCKET_NAME_RIL "'");        exit(-1);    }    ret = listen(s_fdListen, 4);    if (ret < 0) {        LOGE("Failed to listen on control socket '%d': %s",             s_fdListen, strerror(errno));        exit(-1);    }#endif    /* note: non-persistent so we can accept only one connection at a time */    ril_event_set (&s_listen_event, s_fdListen, false,                 listenCallback, NULL);    ril_event_add (&s_listen_event);#if 1    // start debug interface socket    s_fdDebug = android_get_control_socket(SOCKET_NAME_RIL_DEBUG);    if (s_fdDebug < 0) {        LOGE("Failed to get socket '" SOCKET_NAME_RIL_DEBUG "' errno:%d", errno);        exit(-1);    }    ret = listen(s_fdDebug, 4);    if (ret < 0) {        LOGE("Failed to listen on ril debug socket '%d': %s",             s_fdDebug, strerror(errno));        exit(-1);    }    ril_event_set (&s_debug_event, s_fdDebug, true,                debugCallback, NULL);    ril_event_add (&s_debug_event);#endif}//把已经收到response的RequestInfo从s_pendingRequests列表里面清掉static intcheckAndDequeueRequestInfo(struct RequestInfo *pRI){    int ret = 0;        if (pRI == NULL) {        return 0;    }    pthread_mutex_lock(&s_pendingRequestsMutex);    for(RequestInfo **ppCur = &s_pendingRequests         ; *ppCur != NULL         ; ppCur = &((*ppCur)->p_next)    ) {        if (pRI == *ppCur) {            ret = 1;            *ppCur = (*ppCur)->p_next;            break;        }    }    pthread_mutex_unlock(&s_pendingRequestsMutex);    return ret;}//将response通知给客户端extern "C" voidRIL_onRequestComplete(RIL_Token t, RIL_Errno e, void *response, size_t responselen){    RequestInfo *pRI;    int ret;    size_t errorOffset;    pRI = (RequestInfo *)t;//检查这个RequestInfo*是否在s_pendingRequests里面,如果在,就从链表里面清除    if (!checkAndDequeueRequestInfo(pRI)) {        LOGE ("RIL_onRequestComplete: invalid RIL_Token");        return;    }//如果是local的请求(一般来自debug),那就不要再发给command socket了    if (pRI->local > 0) {        // Locally issued command...void only!        // response does not go back up the command socket        LOGD("C[locl]< %s", requestToString(pRI->pCI->requestNumber));        goto done;    }    appendPrintBuf("[%04d]< %s",        pRI->token, requestToString(pRI->pCI->requestNumber));    if (pRI->cancelled == 0) {        Parcel p;        p.writeInt32 (RESPONSE_SOLICITED);        p.writeInt32 (pRI->token);/*这个地方的意思是保存写失败或是成功的偏移量,如果:1. request返回成功(写入成功),并且调用responseFunction写数据到Parcel成功,那么OK2. request返回成功(写入成功), 并且调用responseFunction写数据到Parce失败,那么把失败的原因写到刚刚写入成功的位置3. request失败,直接将失败原因写到Parcel里面*/        errorOffset = p.dataPosition();        p.writeInt32 (e);        if (e == RIL_E_SUCCESS) {            /* process response on success */            ret = pRI->pCI->responseFunction(p, response, responselen);            /* if an error occurred, rewind and mark it */            if (ret != 0) {//如果调用responseFunction写入Parcel失败,将错误的原因替换掉刚刚写入的成功值                p.setDataPosition(errorOffset);                p.writeInt32 (ret);            }        } else {            appendPrintBuf("%s returns %s", printBuf, failCauseToString(e));        }        if (s_fdCommand < 0) {            LOGD ("RIL onRequestComplete: Command channel closed");        }//将打包好的Parcel数据写入到客户端的s_fdCommand socket里面        sendResponse(p);    }done:    free(pRI);}static voidgrabFullWakeLock(){    int fd;    fd = open (ANDROID_FULL_WAKE_LOCK_PATH, O_WRONLY);    if (fd < 0) {        LOGW ("Cannot open " ANDROID_FULL_WAKE_LOCK_PATH);        return;    }    write (fd, ANDROID_WAKE_LOCK_NAME, strlen(ANDROID_WAKE_LOCK_NAME));    close (fd);}static voidgrabPartialWakeLock(){    int fd;    fd = open (ANDROID_PARTIAL_WAKE_LOCK_PATH, O_WRONLY);    if (fd < 0) {        LOGW ("Cannot open " ANDROID_PARTIAL_WAKE_LOCK_PATH);        return;    }    write (fd, ANDROID_WAKE_LOCK_NAME, strlen(ANDROID_WAKE_LOCK_NAME));    close (fd);}static voidreleaseWakeLock(){    int fd;    fd = open (ANDROID_WAKE_UNLOCK_PATH, O_WRONLY);    if (fd < 0) {        LOGW ("Cannot open " ANDROID_WAKE_UNLOCK_PATH);        return;    }    write (fd, ANDROID_WAKE_LOCK_NAME, strlen(ANDROID_WAKE_LOCK_NAME));    close (fd);}/** * Timer callback to put us back to sleep before the default timeout */static voidwakeTimeoutCallback (void *param){    // We're using "param != NULL" as a cancellation mechanism    if (param == NULL) {        //LOGD("wakeTimeout: releasing wake lock");        releaseWakeLock();    } else {        //LOGD("wakeTimeout: releasing wake lock CANCELLED");    }}extern "C"void RIL_onUnsolicitedResponse(int unsolResponse, void *data,                                 size_t datalen){    int unsolResponseIndex;    int ret;   //如果RIL_Register还没有调用,s_callbacks还么初始化,不处理unsolicited response    if (s_registerCalled == 0) {        // Ignore RIL_onUnsolicitedResponse before RIL_register        LOGW("RIL_onUnsolicitedResponse called before RIL_register");        return;    }            unsolResponseIndex = unsolResponse - RIL_UNSOL_RESPONSE_BASE;    if (unsolResponseIndex < 0         || unsolResponseIndex >= (int32_t)NUM_ELEMS(s_unsolResponses)) {        LOGE("unsupported unsolicited response code %d", unsolResponse);        return;    }    appendPrintBuf("[UNSL]< %s", requestToString(unsolResponse));        Parcel p;    p.writeInt32 (RESPONSE_UNSOLICITED);    p.writeInt32 (unsolResponse);  //也是处理数据写入到parcel里面    ret = s_unsolResponses[unsolResponseIndex]                .responseFunction(p, data, datalen);    // some things get more payload    switch(unsolResponse) {        case RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED:            p.writeInt32(s_callbacks.onStateRequest());            appendPrintBuf("%s {%s}", printBuf,                radioStateToString(s_callbacks.onStateRequest()));        break;        case RIL_UNSOL_NITZ_TIME_RECEIVED:             // FIXME use monotonic system time instead            time_t timeReceived = time(NULL);            // Store the time this was received in case it is delayed            p.writeInt32(timeReceived);                    break;    }            if (ret != 0) {        // Problem with the response. Don't continue;                return;    }//把数据发给客户端    ret = sendResponse(p);    if (ret != 0 && unsolResponse == RIL_UNSOL_NITZ_TIME_RECEIVED) {        // Unfortunately, NITZ time is not poll/update like everything        // else in the system. So, if the upstream client isn't connected,        // keep a copy of the last NITZ response (with receive time noted        // above) around so we can deliver it when it is connected                if (s_lastNITZTimeData != NULL) {            free (s_lastNITZTimeData);            s_lastNITZTimeData = NULL;        }        s_lastNITZTimeData = malloc(p.dataSize());        s_lastNITZTimeDataSize = p.dataSize();        memcpy(s_lastNITZTimeData, p.data(), p.dataSize());    }    bool shouldScheduleTimeout = false;        switch (s_unsolResponses[unsolResponseIndex].wakeType) {        case WAKE_PARTIAL:            grabPartialWakeLock();            shouldScheduleTimeout = true;        break;        case WAKE_FULL:            grabFullWakeLock();            shouldScheduleTimeout = true;        break;        case DONT_WAKE:        default:            break;    }    // For now, we automatically go back to sleep after TIMEVAL_WAKE_TIMEOUT    // FIXME The java code should handshake here to release wake lock    if (shouldScheduleTimeout) {        // Cancel the previous request        if (s_last_wake_timeout_info != NULL) {            s_last_wake_timeout_info->userParam = (void *)1;        }                s_last_wake_timeout_info             = internalRequestTimedCallback(wakeTimeoutCallback, NULL,                                             &TIMEVAL_WAKE_TIMEOUT);    }}/** FIXME generalize this if you track UserCAllbackInfo, clear it      when the callback occurs     用来产生添加到按照timer驱动的ril_event列表里面*/static UserCallbackInfo *internalRequestTimedCallback (RIL_TimedCallback callback, void *param,                                 const struct timeval *relativeTime){    struct timeval myRelativeTime;    UserCallbackInfo *p_info;    int ret;    p_info = (UserCallbackInfo *) malloc (sizeof(UserCallbackInfo));    p_info->p_callback = callback;     p_info->userParam = param;    if (relativeTime == NULL) {        /* treat null parameter as a 0 relative time */        memset (&myRelativeTime, 0, sizeof(myRelativeTime));    } else {        /* FIXME I think event_add's tv param is really const anyway */        memcpy (&myRelativeTime, relativeTime, sizeof(myRelativeTime));    }    ril_event_set(&(p_info->event), -1, false, userTimerCallback, p_info);    ril_timer_add(&(p_info->event), &myRelativeTime);    if (!pthread_equal(pthread_self(), s_tid_dispatch)) {        /* trigger event loop to wakeup            No reason to to this if we're in the event loop thread */        do {                    ret = write (s_fdWakeupWrite, " ", 1);        } while (ret < 0 && errno == EINTR);    }        return p_info;}//内部发起的内部处理函数,提交内部的timer event,不用上报给客户端extern "C" voidRIL_requestTimedCallback (RIL_TimedCallback callback, void *param,                                 const struct timeval *relativeTime){    internalRequestTimedCallback (callback, param, relativeTime);}const char *failCauseToString(RIL_Errno e){    switch(e) {        case RIL_E_SUCCESS: return "E_SUCCESS";        case RIL_E_RADIO_NOT_AVAILABLE: return "E_RAIDO_NOT_AVAILABLE";        case RIL_E_GENERIC_FAILURE: return "E_GENERIC_FAILURE";        case RIL_E_PASSWORD_INCORRECT: return "E_PASSWORD_INCORRECT";        case RIL_E_SIM_PIN2: return "E_SIM_PIN2";        case RIL_E_SIM_PUK2: return "E_SIM_PUK2";        case RIL_E_REQUEST_NOT_SUPPORTED: return "E_REQUEST_NOT_SUPPORTED";        case RIL_E_CANCELLED: return "E_CANCELLED";        case RIL_E_OP_NOT_ALLOWED_DURING_VOICE_CALL: return "E_OP_NOT_ALLOWED_DURING_VOICE_CALL";        case RIL_E_OP_NOT_ALLOWED_BEFORE_REG_TO_NW: return "E_OP_NOT_ALLOWED_BEFORE_REG_TO_NW";        case RIL_E_SMS_SEND_FAIL_RETRY: return "E_SMS_SEND_FAIL_RETRY";        default: return "<unknown error>";    }}const char *radioStateToString(RIL_RadioState s){    switch(s) {        case RADIO_STATE_OFF: return "RADIO_OFF";        case RADIO_STATE_UNAVAILABLE: return "RADIO_UNAVAILABLE";        case RADIO_STATE_SIM_NOT_READY: return "RADIO_SIM_NOT_READY";        case RADIO_STATE_SIM_LOCKED_OR_ABSENT: return "RADIO_SIM_LOCKED_OR_ABSENT";        case RADIO_STATE_SIM_READY: return "RADIO_SIM_READY";        default: return "<unknown state>";    }}const char *callStateToString(RIL_CallState s){    switch(s) {        case RIL_CALL_ACTIVE : return "ACTIVE";        case RIL_CALL_HOLDING: return "HOLDING";        case RIL_CALL_DIALING: return "DIALING";        case RIL_CALL_ALERTING: return "ALERTING";        case RIL_CALL_INCOMING: return "INCOMING";        case RIL_CALL_WAITING: return "WAITING";        default: return "<unknown state>";    }}const char *requestToString(int request) {/* cat libs/telephony/ril_commands.h \ | egrep "^ *{RIL_" \ | sed -re 's/\{RIL_([^,]+),[^,]+,([^}]+).+/case RIL_\1: return "\1";/' cat libs/telephony/ril_unsol_commands.h \ | egrep "^ *{RIL_" \ | sed -re 's/\{RIL_([^,]+),([^}]+).+/case RIL_\1: return "\1";/'*/    switch(request) {        case RIL_REQUEST_GET_SIM_STATUS: return "GET_SIM_STATUS";        case RIL_REQUEST_ENTER_SIM_PIN: return "ENTER_SIM_PIN";        case RIL_REQUEST_ENTER_SIM_PUK: return "ENTER_SIM_PUK";        case RIL_REQUEST_ENTER_SIM_PIN2: return "ENTER_SIM_PIN2";        case RIL_REQUEST_ENTER_SIM_PUK2: return "ENTER_SIM_PUK2";        case RIL_REQUEST_CHANGE_SIM_PIN: return "CHANGE_SIM_PIN";        case RIL_REQUEST_CHANGE_SIM_PIN2: return "CHANGE_SIM_PIN2";        case RIL_REQUEST_ENTER_NETWORK_DEPERSONALIZATION: return "ENTER_NETWORK_DEPERSONALIZATION";        case RIL_REQUEST_GET_CURRENT_CALLS: return "GET_CURRENT_CALLS";        case RIL_REQUEST_DIAL: return "DIAL";        case RIL_REQUEST_GET_IMSI: return "GET_IMSI";        case RIL_REQUEST_HANGUP: return "HANGUP";        case RIL_REQUEST_HANGUP_WAITING_OR_BACKGROUND: return "HANGUP_WAITING_OR_BACKGROUND";        case RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND: return "HANGUP_FOREGROUND_RESUME_BACKGROUND";        case RIL_REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE: return "SWITCH_WAITING_OR_HOLDING_AND_ACTIVE";        case RIL_REQUEST_CONFERENCE: return "CONFERENCE";        case RIL_REQUEST_UDUB: return "UDUB";        case RIL_REQUEST_LAST_CALL_FAIL_CAUSE: return "LAST_CALL_FAIL_CAUSE";        case RIL_REQUEST_SIGNAL_STRENGTH: return "SIGNAL_STRENGTH";        case RIL_REQUEST_REGISTRATION_STATE: return "REGISTRATION_STATE";        case RIL_REQUEST_GPRS_REGISTRATION_STATE: return "GPRS_REGISTRATION_STATE";        case RIL_REQUEST_OPERATOR: return "OPERATOR";        case RIL_REQUEST_RADIO_POWER: return "RADIO_POWER";        case RIL_REQUEST_DTMF: return "DTMF";        case RIL_REQUEST_SEND_SMS: return "SEND_SMS";        case RIL_REQUEST_SEND_SMS_EXPECT_MORE: return "SEND_SMS_EXPECT_MORE";        case RIL_REQUEST_SETUP_DEFAULT_PDP: return "SETUP_DEFAULT_PDP";        case RIL_REQUEST_SIM_IO: return "SIM_IO";        case RIL_REQUEST_SEND_USSD: return "SEND_USSD";        case RIL_REQUEST_CANCEL_USSD: return "CANCEL_USSD";        case RIL_REQUEST_GET_CLIR: return "GET_CLIR";        case RIL_REQUEST_SET_CLIR: return "SET_CLIR";        case RIL_REQUEST_QUERY_CALL_FORWARD_STATUS: return "QUERY_CALL_FORWARD_STATUS";        case RIL_REQUEST_SET_CALL_FORWARD: return "SET_CALL_FORWARD";        case RIL_REQUEST_QUERY_CALL_WAITING: return "QUERY_CALL_WAITING";        case RIL_REQUEST_SET_CALL_WAITING: return "SET_CALL_WAITING";        case RIL_REQUEST_SMS_ACKNOWLEDGE: return "SMS_ACKNOWLEDGE";        case RIL_REQUEST_GET_IMEI: return "GET_IMEI";        case RIL_REQUEST_GET_IMEISV: return "GET_IMEISV";        case RIL_REQUEST_ANSWER: return "ANSWER";        case RIL_REQUEST_DEACTIVATE_DEFAULT_PDP: return "DEACTIVATE_DEFAULT_PDP";        case RIL_REQUEST_QUERY_FACILITY_LOCK: return "QUERY_FACILITY_LOCK";        case RIL_REQUEST_SET_FACILITY_LOCK: return "SET_FACILITY_LOCK";        case RIL_REQUEST_CHANGE_BARRING_PASSWORD: return "CHANGE_BARRING_PASSWORD";        case RIL_REQUEST_QUERY_NETWORK_SELECTION_MODE: return "QUERY_NETWORK_SELECTION_MODE";        case RIL_REQUEST_SET_NETWORK_SELECTION_AUTOMATIC: return "SET_NETWORK_SELECTION_AUTOMATIC";        case RIL_REQUEST_SET_NETWORK_SELECTION_MANUAL: return "SET_NETWORK_SELECTION_MANUAL";        case RIL_REQUEST_QUERY_AVAILABLE_NETWORKS : return "QUERY_AVAILABLE_NETWORKS ";        case RIL_REQUEST_DTMF_START: return "DTMF_START";        case RIL_REQUEST_DTMF_STOP: return "DTMF_STOP";        case RIL_REQUEST_BASEBAND_VERSION: return "BASEBAND_VERSION";        case RIL_REQUEST_SEPARATE_CONNECTION: return "SEPARATE_CONNECTION";        case RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE: return "SET_PREFERRED_NETWORK_TYPE";        case RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE: return "GET_PREFERRED_NETWORK_TYPE";        case RIL_REQUEST_GET_NEIGHBORING_CELL_IDS: return "GET_NEIGHBORING_CELL_IDS";        case RIL_REQUEST_SET_MUTE: return "SET_MUTE";        case RIL_REQUEST_GET_MUTE: return "GET_MUTE";        case RIL_REQUEST_QUERY_CLIP: return "QUERY_CLIP";        case RIL_REQUEST_LAST_PDP_FAIL_CAUSE: return "LAST_PDP_FAIL_CAUSE";        case RIL_REQUEST_PDP_CONTEXT_LIST: return "PDP_CONTEXT_LIST";        case RIL_REQUEST_RESET_RADIO: return "RESET_RADIO";        case RIL_REQUEST_OEM_HOOK_RAW: return "OEM_HOOK_RAW";        case RIL_REQUEST_OEM_HOOK_STRINGS: return "OEM_HOOK_STRINGS";    case RIL_REQUEST_SET_BAND_MODE: return "SET_BAND_MODE";    case RIL_REQUEST_QUERY_AVAILABLE_BAND_MODE: return "QUERY_AVAILABLE_BAND_MODE";        case RIL_REQUEST_STK_GET_PROFILE: return "STK_GET_PROFILE";        case RIL_REQUEST_STK_SET_PROFILE: return "STK_SET_PROFILE";        case RIL_REQUEST_STK_SEND_ENVELOPE_COMMAND: return "STK_SEND_ENVELOPE_COMMAND";        case RIL_REQUEST_STK_SEND_TERMINAL_RESPONSE: return "STK_SEND_TERMINAL_RESPONSE";        case RIL_REQUEST_STK_HANDLE_CALL_SETUP_REQUESTED_FROM_SIM: return "STK_HANDLE_CALL_SETUP_REQUESTED_FROM_SIM";        case RIL_REQUEST_SCREEN_STATE: return "SCREEN_STATE";        case RIL_REQUEST_EXPLICIT_CALL_TRANSFER: return "EXPLICIT_CALL_TRANSFER";        case RIL_REQUEST_SET_LOCATION_UPDATES: return "SET_LOCATION_UPDATES";        case RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED: return "UNSOL_RESPONSE_RADIO_STATE_CHANGED";        case RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED: return "UNSOL_RESPONSE_CALL_STATE_CHANGED";        case RIL_UNSOL_RESPONSE_NETWORK_STATE_CHANGED: return "UNSOL_RESPONSE_NETWORK_STATE_CHANGED";        case RIL_UNSOL_RESPONSE_NEW_SMS: return "UNSOL_RESPONSE_NEW_SMS";        case RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT: return "UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT";        case RIL_UNSOL_RESPONSE_NEW_SMS_ON_SIM: return "UNSOL_RESPONSE_NEW_SMS_ON_SIM";        case RIL_UNSOL_ON_USSD: return "UNSOL_ON_USSD";        case RIL_UNSOL_ON_USSD_REQUEST: return "UNSOL_ON_USSD_REQUEST(obsolete)";        case RIL_UNSOL_NITZ_TIME_RECEIVED: return "UNSOL_NITZ_TIME_RECEIVED";        case RIL_UNSOL_SIGNAL_STRENGTH: return "UNSOL_SIGNAL_STRENGTH";        case RIL_UNSOL_STK_SESSION_END: return "UNSOL_STK_SESSION_END";        case RIL_UNSOL_STK_PROACTIVE_COMMAND: return "UNSOL_STK_PROACTIVE_COMMAND";        case RIL_UNSOL_STK_EVENT_NOTIFY: return "UNSOL_STK_EVENT_NOTIFY";        case RIL_UNSOL_STK_CALL_SETUP: return "UNSOL_STK_CALL_SETUP";        case RIL_UNSOL_SIM_SMS_STORAGE_FULL: return "UNSOL_SIM_SMS_STORAGE_FUL";        case RIL_UNSOL_SIM_REFRESH: return "UNSOL_SIM_REFRESH";        case RIL_UNSOL_PDP_CONTEXT_LIST_CHANGED: return "UNSOL_PDP_CONTEXT_LIST_CHANGED";        case RIL_UNSOL_CALL_RING: return "UNSOL_CALL_RING";        default: return "<unknown request>";    }}} /* namespace android */

原创粉丝点击