Android8.0 Rild守护进程

电话是一种开放的通信渠道,任何人都可以随时向任何电话号码致电或者发送短信,因此 Android 用户需要能够轻松屏蔽骚扰电话和短信。在 Android N 推出之前,Android 用户只能依靠下载的应用来限制来自骚扰电话号码的来电和短信。但是,由于没有适当的 API 来屏蔽来电和短信,这些应用大部分要么达不到预期效果,要么用户体验不佳。

在这里插入图片描述

一些制造商可能会提供他们自己的开箱即用型屏蔽解决方案,但是如果用户更换设备,由于缺乏互用性,他们的屏蔽列表可能会完全丢失。最后,即便用户采用了提供此类功能的拨号应用和短信客户端,他们可能仍需在每个应用中执行屏蔽操作,才能有效屏蔽来电和短信。Android 7.0 版本引入了 BlockedNumberProvider 内容提供程序,该程序可以存储用户指定的无法通过电话通讯(通话、短信、彩信)与他们联系的电话号码列表。系统会参考屏蔽列表中的号码,限制来自这些号码的来电和短信。Android 7.0 不仅会显示屏蔽号码列表,还可让用户添加和删除号码。

1. 启动Rild后台进程

hardware\ril\rild\rild.c

int main(int argc, char **argv) {
    // vendor ril lib path either passed in as -l parameter, or read from rild.libpath property
    const char *rilLibPath = NULL;
    // ril arguments either passed in as -- parameter, or read from rild.libargs property
    char **rilArgv;
    //厂商ril库句柄
    void *dlHandle;
    //厂商ril库回调
    const RIL_RadioFunctions *(*rilInit)(const struct RIL_Env *, int, char **);
    // Pointer to sap init function in vendor ril
    RIL_RadioFunctions *(*rilUimInit)(const struct RIL_Env *, int, char **);
    const char *err_str = NULL;
    // functions returned by ril init function in vendor ril
    const RIL_RadioFunctions *funcs;
    ......
     //打开厂商库
    dlHandle = dlopen(rilLibPath, RTLD_NOW);
    //启动事件循环
    RIL_startEventLoop();
    //调用系统库
    rilInit =(const RIL_RadioFunctions *(*)(const struct RIL_Env *, int, char **))dlsym(dlHandle, "RIL_Init");
    rilUimInit =(RIL_RadioFunctions *(*)(const struct RIL_Env *, int, char **))dlsym(dlHandle, "RIL_SAP_Init");
    //初始化rilInit
    funcs = rilInit(&s_rilEnv, argc, rilArgv);
    //注册回调函数
    RIL_register(funcs);
    //注册套接
    if (rilUimInit) {
        RIL_register_socket(rilUimInit, RIL_SAP_SOCKET, argc, rilArgv);
    }
done:
    .....
    rilc_thread_pool();
    .....
}

2. 启动事件循环

hardware\ril\libril\ril.cpp

extern "C" void
RIL_startEventLoop(void) {
    ......
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
    //启动线程,运行 eventLoop
    int result = pthread_create(&s_tid_dispatch, &attr, eventLoop, NULL);
    while (s_started == 0) {
        pthread_cond_wait(&s_startupCond, &s_startupMutex);
    }
    ......

hardware\ril\libril\ril.cpp

static void *
eventLoop(void *param) {
    int ret;
    int filedes[2];
    //初始化事件链表
    ril_event_init();
    //创建管道
    ret = pipe(filedes);
    //读写唤醒描述符
    s_fdWakeupRead = filedes[0];
    s_fdWakeupWrite = filedes[1];
    //执行
    fcntl(s_fdWakeupRead, F_SETFL, O_NONBLOCK);
    //设置事件描述符和事件处理函数
    ril_event_set (&s_wakeupfd_event, s_fdWakeupRead, true,
                processWakeupCallback, NULL);
    rilEventAddWakeup (&s_wakeupfd_event);
    //开始ril事件循环
    ril_event_loop();
    ......

    return NULL;
}

hardware\ril\libril\ril_event.cpp

void ril_event_init()
{
    MUTEX_INIT();
    FD_ZERO(&readFds);
    init_list(&timer_list); //初始化事件链表
    init_list(&pending_list);
    memset(watch_table, 0, sizeof(watch_table));
}

static void init_list(struct ril_event * list)
{
    memset(list, 0, sizeof(struct ril_event));
    list->next = list;
    list->prev = list;
    list->fd = -1; //存储文件描述符
}

hardware\ril\libril\ril_event.cpp

void ril_event_loop()
{
    int n;
    fd_set rfds;
    struct timeval tv;
    struct timeval * ptv;


    for (;;) {
        ......
        n = select(nfds, &rfds, NULL, NULL, ptv); //开始select
        ......
        // Check for timeouts
        processTimeouts();
        // Check for read-ready
        processReadReadies(&rfds, n);
        // Fire away
        firePending();
    }
}

static void processReadReadies(fd_set * rfds, int n)
{
    for (int i = 0; (i < MAX_FD_EVENTS) && (n > 0); i++) {
        struct ril_event * rev = watch_table[i];
        if (rev != NULL && FD_ISSET(rev->fd, rfds)) {
            addToList(rev, &pending_list); //添加到挂起列表
            if (rev->persist == false) {
                removeWatch(rev, i); //从描述符观察表中移除
            }
            n--;
        }
    }
}

static void firePending()
{
    struct ril_event * ev = pending_list.next;
    while (ev != &pending_list) {
        struct ril_event * next = ev->next;
        removeFromList(ev);
        ev->func(ev->fd, 0, ev->param); //执行函数 processWakeupCallback
        ev = next;
    }
}

hardware\ril\libril\ril.cpp

static void processWakeupCallback(int fd, short flags, void *param) {
    char buff[16];
    int ret;
    //循环从套接端读取
    do {
        ret = read(s_fdWakeupRead, &buff, sizeof(buff));
    } while (ret > 0 || (ret < 0 && errno == EINTR));
}

hardware\ril\libril\ril.cpp

static void rilEventAddWakeup(struct ril_event *ev) {
    ril_event_add(ev);
    triggerEvLoop();
}

hardware\ril\libril\ril_event.cpp

void ril_event_add(struct ril_event * ev)
{
    for (int i = 0; i < MAX_FD_EVENTS; i++) {
        if (watch_table[i] == NULL) {
            watch_table[i] = ev; //加入事件观察表中
            ev->index = i; //加索引
            FD_SET(ev->fd, &readFds);
            if (ev->fd >= nfds) nfds = ev->fd+1;
            break;
        }
    }
}

hardware\ril\libril\ril.cpp

static void triggerEvLoop() {
    int ret;
    if (!pthread_equal(pthread_self(), s_tid_dispatch)) {
          //循环触发唤醒事件循环
         do {
            ret = write (s_fdWakeupWrite, " ", 1);
         } while (ret < 0 && errno == EINTR);
    }
}

3. 启动RIL库

hardware\ril\reference-ril\reference-ril.c

const RIL_RadioFunctions *RIL_Init(const struct RIL_Env *env, int argc, char **argv)
{
    ......
    //启动线程,开始主循环
    ret = pthread_create(&s_tid_mainloop, &attr, mainLoop, NULL); 
    ......
    return &s_callbacks; //返回操作结构体
}

//函数回调结构表
static const RIL_RadioFunctions s_callbacks = {
    RIL_VERSION,
    onRequest,
    currentState,
    onSupports,
    onCancel,
    getVersion
};

hardware\ril\reference-ril\reference-ril.c
开始打开BP(基带处理器)

static void *
mainLoop(void *param __unused)
{
    int fd;
    int ret;
    at_set_on_reader_closed(onATReaderClosed);
    at_set_on_timeout(onATTimeout);
    for (;;) {
        fd = -1;
        while  (fd < 0) {
            if (isInEmulator()) {
                fd = qemu_pipe_open("pipe:qemud:gsm"); //模拟
            } else if (s_port > 0) {
                fd = socket_network_client("localhost", s_port, SOCK_STREAM); //网络
            } else if (s_device_socket) { //本地
                fd = socket_local_client(s_device_path,
                                         ANDROID_SOCKET_NAMESPACE_FILESYSTEM,
                                         SOCK_STREAM);
            } else if (s_device_path != NULL) {
                fd = open (s_device_path, O_RDWR); //打开基带处理器
                if ( fd >= 0 && !memcmp( s_device_path, "/dev/ttyS", 9 ) ) {
                    /* disable echo on serial ports */
                    struct termios  ios;
                    tcgetattr( fd, &ios );
                    ios.c_lflag = 0;  /* disable ECHO, ICANON, etc... */
                    tcsetattr( fd, TCSANOW, &ios );
                }
            }
            ......
        }

        s_closed = 0;
        ret = at_open(fd, onUnsolicited); // 开始基带处理通讯,出入文件描述符,回调处理函数
        RIL_requestTimedCallback(initializeCallback, NULL, &TIMEVAL_0);
        ......
    }
}

4. 未经请求的AT通讯

hardware\ril\reference-ril\atchannel.c

int at_open(int fd, ATUnsolHandler h)
{
    int ret;
    pthread_t tid;
    pthread_attr_t attr;

    s_fd = fd;
    s_unsolHandler = h; //回调处理句柄
    s_readerClosed = 0;
    //开线程循环读取
    ret = pthread_create(&s_tid_reader, &attr, readerLoop, &attr);
    ......
    return 0;
}

hardware\ril\reference-ril\atchannel.c
循环读取基带处理器的AT指令

static void *readerLoop(void *arg __unused)
{
    for (;;) {
        const char * line;

        line = readline(); //读取AT命令

        if (line == NULL) {
            break;
        }

        if(isSMSUnsolicited(line)) { //是未经请求的回复
            char *line1;
            const char *line2;

            // The scope of string returned by 'readline()' is valid only
            // till next call to 'readline()' hence making a copy of line
            // before calling readline again.
            line1 = strdup(line);
            line2 = readline();

            if (line2 == NULL) {
                free(line1);
                break;
            }

            if (s_unsolHandler != NULL) {
                s_unsolHandler (line1, line2); //回调
            }
            free(line1);
        } else {
            processLine(line); //处理
        }
    }

    onReaderClosed();

    return NULL;
}

hardware\ril\reference-ril\atchannel.c
读取AT命令行

static const char *readline()
{
    ssize_t count;

    char *p_read = NULL;
    char *p_eol = NULL;
    char *ret;

    /* this is a little odd. I use *s_ATBufferCur == 0 to
     * mean "buffer consumed completely". If it points to a character, than
     * the buffer continues until a \0
     */
    if (*s_ATBufferCur == '\0') {
        /* empty buffer */
        s_ATBufferCur = s_ATBuffer;
        *s_ATBufferCur = '\0';
        p_read = s_ATBuffer;
    } else {   /* *s_ATBufferCur != '\0' */
        /* there's data in the buffer from the last read */

        // skip over leading newlines
        while (*s_ATBufferCur == '\r' || *s_ATBufferCur == '\n')
            s_ATBufferCur++;

        p_eol = findNextEOL(s_ATBufferCur);

        if (p_eol == NULL) {
            /* a partial line. move it up and prepare to read more */
            size_t len;

            len = strlen(s_ATBufferCur);

            memmove(s_ATBuffer, s_ATBufferCur, len + 1);
            p_read = s_ATBuffer + len;
            s_ATBufferCur = s_ATBuffer;
        }
        /* Otherwise, (p_eol !- NULL) there is a complete line  */
        /* that will be returned the while () loop below        */
    }

    while (p_eol == NULL) {
        if (0 == MAX_AT_RESPONSE - (p_read - s_ATBuffer)) {
            RLOGE("ERROR: Input line exceeded buffer\n");
            /* ditch buffer and start over again */
            s_ATBufferCur = s_ATBuffer;
            *s_ATBufferCur = '\0';
            p_read = s_ATBuffer;
        }

        do {
            //循环读取AT指令数据
            count = read(s_fd, p_read,
                            MAX_AT_RESPONSE - (p_read - s_ATBuffer));
        } while (count < 0 && errno == EINTR);

        if (count > 0) {
            AT_DUMP( "<< ", p_read, count );

            p_read[count] = '\0';

            // skip over leading newlines
            while (*s_ATBufferCur == '\r' || *s_ATBufferCur == '\n')
                s_ATBufferCur++;

            p_eol = findNextEOL(s_ATBufferCur);
            p_read += count;
        } else if (count <= 0) {
            /* read error encountered or EOF reached */
            if(count == 0) {
                RLOGD("atchannel: EOF reached");
            } else {
                RLOGD("atchannel: read error %s", strerror(errno));
            }
            return NULL;
        }
    }

    /* a full line in the buffer. Place a \0 over the \r and return */

    ret = s_ATBufferCur;
    *p_eol = '\0';
    s_ATBufferCur = p_eol + 1; /* this will always be <= p_read,    */
                              /* and there will be a \0 at *p_read */

    RLOGD("AT< %s\n", ret);
    return ret;
}

hardware\ril\reference-ril\atchannel.c
处理命令行

static void processLine(const char *line)
{
    pthread_mutex_lock(&s_commandmutex);

    if (sp_response == NULL) {
        /* no command pending */
        handleUnsolicited(line); //处理未经请求的回复
    } else if (isFinalResponseSuccess(line)) {
        sp_response->success = 1;
        handleFinalResponse(line);
    } else if (isFinalResponseError(line)) {
        sp_response->success = 0;
        handleFinalResponse(line);
    } else if (s_smsPDU != NULL && 0 == strcmp(line, "> ")) {
        // See eg. TS 27.005 4.3
        // Commands like AT+CMGS have a "> " prompt
        writeCtrlZ(s_smsPDU);
        s_smsPDU = NULL;
    } else switch (s_type) {
        case NO_RESULT:
            handleUnsolicited(line);
            break;
        case NUMERIC:
            if (sp_response->p_intermediates == NULL
                && isdigit(line[0])
            ) {
                addIntermediate(line);
            } else {
                /* either we already have an intermediate response or
                   the line doesn't begin with a digit */
                handleUnsolicited(line);
            }
            break;
        case SINGLELINE:
            if (sp_response->p_intermediates == NULL
                && strStartsWith (line, s_responsePrefix)
            ) {
                addIntermediate(line);
            } else {
                /* we already have an intermediate response */
                handleUnsolicited(line);
            }
            break;
        case MULTILINE:
            if (strStartsWith (line, s_responsePrefix)) {
                addIntermediate(line);
            } else {
                handleUnsolicited(line);
            }
        break;

        default: /* this should never be reached */
            RLOGE("Unsupported AT command type %d\n", s_type);
            handleUnsolicited(line);
        break;
    }

    pthread_mutex_unlock(&s_commandmutex);
}

hardware\ril\reference-ril\atchannel.c
回调处理

static void handleUnsolicited(const char *line)
{
    if (s_unsolHandler != NULL) {
        s_unsolHandler(line, NULL);
    }
}

hardware\ril\reference-ril\reference-ril.c
处理来自基带处理器的AT指令

static void onUnsolicited (const char *s, const char *sms_pdu)
{
    char *line = NULL, *p;
    int err;

    /* Ignore unsolicited responses until we're initialized.
     * This is OK because the RIL library will poll for initial state
     */
    if (sState == RADIO_STATE_UNAVAILABLE) {
        return;
    }

    if (strStartsWith(s, "%CTZV:")) {
        /* TI specific -- NITZ time */
        char *response;

        line = p = strdup(s);
        at_tok_start(&p);

        err = at_tok_nextstr(&p, &response);

        if (err != 0) {
            RLOGE("invalid NITZ line %s\n", s);
        } else {
            RIL_onUnsolicitedResponse (
                RIL_UNSOL_NITZ_TIME_RECEIVED,
                response, strlen(response));
        }
        free(line);
    } else if (strStartsWith(s,"+CRING:")
                || strStartsWith(s,"RING")
                || strStartsWith(s,"NO CARRIER")
                || strStartsWith(s,"+CCWA")
    ) {
        RIL_onUnsolicitedResponse (
            RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED,
            NULL, 0);
#ifdef WORKAROUND_FAKE_CGEV
        RIL_requestTimedCallback (onDataCallListChanged, NULL, NULL); //TODO use new function
#endif /* WORKAROUND_FAKE_CGEV */
    } else if (strStartsWith(s,"+CREG:")
                || strStartsWith(s,"+CGREG:")
    ) {
        RIL_onUnsolicitedResponse (
            RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED,
            NULL, 0);
#ifdef WORKAROUND_FAKE_CGEV
        RIL_requestTimedCallback (onDataCallListChanged, NULL, NULL);
#endif /* WORKAROUND_FAKE_CGEV */
    } else if (strStartsWith(s, "+CMT:")) {
        RIL_onUnsolicitedResponse (
            RIL_UNSOL_RESPONSE_NEW_SMS,
            sms_pdu, strlen(sms_pdu));
    } else if (strStartsWith(s, "+CDS:")) {
        RIL_onUnsolicitedResponse (
            RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT,
            sms_pdu, strlen(sms_pdu));
    } else if (strStartsWith(s, "+CGEV:")) {
        /* Really, we can ignore NW CLASS and ME CLASS events here,
         * but right now we don't since extranous
         * RIL_UNSOL_DATA_CALL_LIST_CHANGED calls are tolerated
         */
        /* can't issue AT commands here -- call on main thread */
        RIL_requestTimedCallback (onDataCallListChanged, NULL, NULL);
#ifdef WORKAROUND_FAKE_CGEV
    } else if (strStartsWith(s, "+CME ERROR: 150")) {
        RIL_requestTimedCallback (onDataCallListChanged, NULL, NULL);
#endif /* WORKAROUND_FAKE_CGEV */
    } else if (strStartsWith(s, "+CTEC: ")) {
        int tech, mask;
        switch (parse_technology_response(s, &tech, NULL))
        {
            case -1: // no argument could be parsed.
                RLOGE("invalid CTEC line %s\n", s);
                break;
            case 1: // current mode correctly parsed
            case 0: // preferred mode correctly parsed
                mask = 1 << tech;
                if (mask != MDM_GSM && mask != MDM_CDMA &&
                     mask != MDM_WCDMA && mask != MDM_LTE) {
                    RLOGE("Unknown technology %d\n", tech);
                } else {
                    setRadioTechnology(sMdmInfo, tech);
                }
                break;
        }
    } else if (strStartsWith(s, "+CCSS: ")) {
        int source = 0;
        line = p = strdup(s);
        if (!line) {
            RLOGE("+CCSS: Unable to allocate memory");
            return;
        }
        if (at_tok_start(&p) < 0) {
            free(line);
            return;
        }
        if (at_tok_nextint(&p, &source) < 0) {
            RLOGE("invalid +CCSS response: %s", line);
            free(line);
            return;
        }
        SSOURCE(sMdmInfo) = source;
        RIL_onUnsolicitedResponse(RIL_UNSOL_CDMA_SUBSCRIPTION_SOURCE_CHANGED,
                                  &source, sizeof(source));
    } 
    ......
}

hardware\ril\libril\ril.cpp
响应请求

#if defined(ANDROID_MULTI_SIM)
extern "C"
void RIL_onUnsolicitedResponse(int unsolResponse, const void *data,
                                size_t datalen, RIL_SOCKET_ID socket_id)
#else
extern "C"
void RIL_onUnsolicitedResponse(int unsolResponse, const void *data,
                                size_t datalen)
#endif
{
    int unsolResponseIndex;
   
    unsolResponseIndex = unsolResponse - RIL_UNSOL_RESPONSE_BASE;

   
    // Grab a wake lock if needed for this reponse,
    // as we exit we'll either release it immediately
    // or set a timer to release it later.
    switch (s_unsolResponses[unsolResponseIndex].wakeType) {
        case WAKE_PARTIAL:
            grabPartialWakeLock();
            shouldScheduleTimeout = true;
        break;

        case DONT_WAKE:
        default:
            // No wake lock is grabed so don't set timeout
            shouldScheduleTimeout = false;
            break;
    }

    appendPrintBuf("[UNSL]< %s", requestToString(unsolResponse));

    int responseType;
    if (s_callbacks.version >= 13
                && s_unsolResponses[unsolResponseIndex].wakeType == WAKE_PARTIAL) {
        responseType = RESPONSE_UNSOLICITED_ACK_EXP;
    } else {
        responseType = RESPONSE_UNSOLICITED;
    }

    pthread_rwlock_t *radioServiceRwlockPtr = radio::getRadioServiceRwlock((int) soc_id);
    int rwlockRet = pthread_rwlock_rdlock(radioServiceRwlockPtr);
    assert(rwlockRet == 0);
    //执行响应函数
    ret = s_unsolResponses[unsolResponseIndex].responseFunction(
            (int) soc_id, responseType, 0, RIL_E_SUCCESS, const_cast<void*>(data),
            datalen);

    ......
}

hardware\ril\libril\ril.cpp

static UnsolResponseInfo s_unsolResponses[] = {
#include "ril_unsol_commands.h"
};

hardware\ril\libril\ril_unsol_commands.h
函数表,由responseFunction查表调用

 {RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED, radio::radioStateChangedInd, WAKE_PARTIAL},
 {RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED, radio::callStateChangedInd, WAKE_PARTIAL},
 {RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED, radio::networkStateChangedInd, WAKE_PARTIAL},
 {RIL_UNSOL_RESPONSE_NEW_SMS, radio::newSmsInd, WAKE_PARTIAL},
 ......

5. 经请求的AT通讯

hardware\ril\libril\ril.cpp
注册回调函数

extern "C" void
RIL_register (const RIL_RadioFunctions *callbacks) {
    int ret;
    int flags;
    //内存分配
    memcpy(&s_callbacks, callbacks, sizeof (RIL_RadioFunctions));
    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);
    }
    //注册
    radio::registerService(&s_callbacks, s_commands);

}

hardware\ril\libril\ril_service.cpp
回调函数和函数路由表

void radio::registerService(RIL_RadioFunctions *callbacks, CommandInfo *commands) {
    using namespace android::hardware;
    int simCount = 1;
    const char *serviceNames[] = {
            android::RIL_getServiceName()
            #if (SIM_COUNT >= 2)
            , RIL2_SERVICE_NAME
            #if (SIM_COUNT >= 3)
            , RIL3_SERVICE_NAME
            #if (SIM_COUNT >= 4)
            , RIL4_SERVICE_NAME
            #endif
            #endif
            #endif
            };

    #if (SIM_COUNT >= 2)
    simCount = SIM_COUNT;
    #endif

    configureRpcThreadpool(1, true /* callerWillJoin */); //RPC线程池
    for (int i = 0; i < simCount; i++) { //一张sim卡对应一项服务
        pthread_rwlock_t *radioServiceRwlockPtr = getRadioServiceRwlock(i);
        int ret = pthread_rwlock_wrlock(radioServiceRwlockPtr);
        assert(ret == 0);

        radioService[i] = new RadioImpl;
        radioService[i]->mSlotId = i;
        oemHookService[i] = new OemHookImpl;
        oemHookService[i]->mSlotId = i;
        RLOGD("registerService: starting IRadio %s", serviceNames[i]);
        android::status_t status = radioService[i]->registerAsService(serviceNames[i]);
        status = oemHookService[i]->registerAsService(serviceNames[i]);

        ret = pthread_rwlock_unlock(radioServiceRwlockPtr);
        assert(ret == 0);
    }

    s_vendorFunctions = callbacks;
    s_commands = commands;
}

hardware\ril\libril\ril_service.cpp
s_vendorFunctions为上述RIL_RadioFunctions

#if defined(ANDROID_MULTI_SIM)
#define CALL_ONREQUEST(a, b, c, d, e) \
        s_vendorFunctions->onRequest((a), (b), (c), (d), ((RIL_SOCKET_ID)(e)))
#define CALL_ONSTATEREQUEST(a) s_vendorFunctions->onStateRequest((RIL_SOCKET_ID)(a))
#else
#define CALL_ONREQUEST(a, b, c, d, e) s_vendorFunctions->onRequest((a), (b), (c), (d))
#define CALL_ONSTATEREQUEST(a) s_vendorFunctions->onStateRequest()
#endif

hardware\ril\libril\ril_service.cpp

bool dispatchVoid(int serial, int slotId, int request) {
    RequestInfo *pRI = android::addRequestToList(serial, slotId, request);
    if (pRI == NULL) {
        return false;
    }
    CALL_ONREQUEST(request, NULL, 0, pRI, slotId);
    return true;
}

hardware\ril\reference-ril\reference-ril.c
宏调用

static void
onRequest (int request, void *data, size_t datalen, RIL_Token t)
{
    ATResponse *p_response;
    int err;
    ......
    switch (request) {
        ......
        case RIL_REQUEST_HANGUP_WAITING_OR_BACKGROUND:
            // 3GPP 22.030 6.5.5
            // "Releases all held calls or sets User Determined User Busy
            //  (UDUB) for a waiting call."
            at_send_command("AT+CHLD=0", NULL); //发送AT指令
        default:
            RLOGD("Request not supported. Tech: %d",TECH(sMdmInfo));
            RIL_onRequestComplete(t, RIL_E_REQUEST_NOT_SUPPORTED, NULL, 0); //处理请求
            break;
    }
}

hardware\ril\libril\ril.cpp
同上未经请求的回复,对应一张函数表,AT命令的请求相应均由函数跳转表路由到hardware\ril\libril\ril_service.cpp 去执行

static CommandInfo s_commands[] = {
#include "ril_commands.h"
};

6. RIL抽象服务

hardware\ril\libril\ril_service.cpp

Return<void> RadioImpl::getModemActivityInfo(int32_t serial) { //查询活跃信息
#if VDBG
    RLOGD("getModemActivityInfo: serial %d", serial);
#endif
    dispatchVoid(serial, mSlotId, RIL_REQUEST_GET_ACTIVITY_INFO); //上述请求派发函数
    return Void();
}

hardware\ril\libril\ril_service.cpp

struct RadioImpl : public IRadio {
    int32_t mSlotId;
    sp<IRadioResponse> mRadioResponse;
    sp<IRadioIndication> mRadioIndication;

    Return<void> setResponseFunctions(
            const ::android::sp<IRadioResponse>& radioResponse,
            const ::android::sp<IRadioIndication>& radioIndication);
}

intermediates\hardware\interfaces\radio\1.0\android.hardware.radio@1.0_genc++_headers\gen\android\hardware\radio\1.0\IRadio.h
一项HAL的Binder服务接口;在hardware\interfaces\radio\1.0\vts\functional提供了一些接口和测试案例

struct IRadio : public ::android::hidl::base::V1_0::IBase {
    virtual bool isRemote() const override { return false; }
    ......
    }

暂且分析到这,以后在扩展到上层系统框架。

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值