<三>--RIL层代码分析---RIL_register()

来源:互联网 发布:ubuntu vscode调试php 编辑:程序博客网 时间:2024/04/30 03:16
 

 ril/rild/rild.c->main()为函数入口

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

1.消息队列select为非阻塞的去轮询事件
2.read的阻塞的去读取上层发下来的命令,并响应

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


int main(int argc, char **argv)

{
    const char * rilLibPath = NULL;
    char **rilArgv;
    void *dlHandle;
    const RIL_RadioFunctions *(*rilInit)(const struct RIL_Env *, int, char **);
    const RIL_RadioFunctions *funcs;
    char libPath[PROPERTY_VALUE_MAX];
    unsigned char hasLibArgs = 0;

   ........

OpenLib:
#endif
    switchUser();
/*打开dlopen()函数,就会动态去加载动态库vendor RIL 获取由RIL_register(funcs);注册进来的参数,并解析*/
    dlHandle = dlopen(rilLibPath, RTLD_NOW);

    if (dlHandle == NULL) {
        fprintf(stderr, "dlopen failed: %s\n", dlerror());
        exit(-1);
    }
/*消息队列的入口,添加到select,用阻塞方式去读取那些ril_event_set()的数据##每当看到打印信息,不按顺序打下来说明阻塞##*/
     RIL_startEventLoop();
/*通过dlsym函数得到rilInit函数指针的引用*/
    rilInit = (const RIL_RadioFunctions *(*)(const struct RIL_Env *, int, char **))dlsym(dlHandle, "RIL_Init");

    if (rilInit == NULL) {
        fprintf(stderr, "RIL_Init not defined or exported in %s\n", rilLibPath);
        exit(-1);
    }

    if (hasLibArgs) {
        rilArgv = argv + i - 1;
        argc = argc -i + 1;
    } else {
        static char * newArgv[MAX_LIB_ARGS];
        static char args[PROPERTY_VALUE_MAX];
        rilArgv = newArgv;
        property_get(LIB_ARGS_PROPERTY, args, "");
        argc = make_argv(args, rilArgv);
    }

    // Make sure there's a reasonable argv[0]
    rilArgv[0] = argv[0];
/*利用得到的rilInit函数指针,调用真正的RIL_Init ,实际是动态加载动态库去链接reference-ril.c ,由dlopen()函数加载*/
    funcs = rilInit(&s_rilEnv, argc, rilArgv);
/*RIL_register作用一:把vendor RIL(即RIL_init) 注册到reference-ril库去等待,dopen()函数加载链接
附:RIL_init通过是onRequest()方法,将上层来的请求进行映射后转换成对应的AT命令发给硬件,rild通过RIL_register注册这一指针。
  RIL_register作用二:创建rild socket主要是等待java层得数据通过,传到下一层,还创建debug socket*/
    RIL_register(funcs);

done:

    while(1) {
        // sleep(UINT32_MAX) seems to return immediately on bionic
        sleep(0x00ffffff);
    }

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

所有文件:

hardware/ril/libril$ ls

Android.mk              NOTICE     ril_event.h       ril.cpp       ril_event.cpp   ril_commands.h  ril_unsol_commands.h

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

funcs =rilInit(&s_rilEnv, argc, rilArgv);//实际是通过动态加载动态库的方式执行reference-ril.c中的RIL_Init

由RIL_Init的返回值开始的,这是一个RIL_RadioFunctions结构的指针。
typedef struct {
    int version;        /* set to RIL_VERSION */
    RIL_RequestFunc onRequest;
    RIL_RadioStateRequest onStateRequest;
    RIL_Supports supports;
    RIL_Cancel onCancel;
    RIL_GetVersion getVersion;
} RIL_RadioFunctions;
其中最重要的是onRequest域,上层来的请求都由这个函数进行映射后转换成对应的AT命令发给硬件。rild通过RIL_register注册这一指针。
RIL_register中要完成的另外一个任务,就是打开前面提到的跟上层通信的socket接口(s_fdListen是主接口,s_fdDebug供调试时使用)。
然后将这两个socket接口使用任务一中实现的机制进行注册(仅列出s_fdListen)
ril_event_set (&s_listen_event, s_fdListen, false,
                listenCallback, NULL);
rilEventAddWakeup (&s_listen_event);
这样将两个socket加到任务一中建立起来多路复用I/O的检查句柄集合中,一旦有上层来的(调试)请求,event机制便能响应处理了。

总结:0.监听所有socket

           1.RIL_register()把ril_init()初始化后的vendor RIL注册到libril.so等待dlopen()h函数加载,调用,再后到select机制中的ril_event_loop()函数轮询

            2.获取连个socket(rild socket和debug socket),而rild socket 是用来和java层通信得,debug socket是用来调试的

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

ril/libril/ril.cpp->RIL_register 函数

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

/*注册rild socket端口事件监听到事件循环中和bedug socket
*/
extern "C" void
RIL_register (const RIL_RadioFunctions *callbacks) {//说明已经初始化完了 ,才回调
    int ret;
    int flags;
LOGD("-----RIL.C-RIL_register(func)-RIL.CPP---RIL_register-");
    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");
      LOGD("RIL_register has been called more than once. "
                "Subsequent call ignored");
        return;
    }
//1:换个马甲
    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

//2:获取init.rc定义的rild socket,,#define SOCKET_NAME_RIL "rild"

    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
/*如果ril socket 端口一有数据,就去执行listencallback函数
   这个函数就建立起与客户端的监听话柄
   s_fdLiten继续监听其他客户端的链接*/

     /* note: non-persistent so we can accept only one connection at a time */
    ril_event_set(&s_listen_event, s_fdListen, false, listenCallback, NULL);  将此处端口加入到select队列去

    rilEventAddWakeup (&s_listen_event);

#if 1

       // start debug interface socket 获取debug 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);

    rilEventAddWakeup (&s_debug_event);
#endif

}

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
// Initialize an event
void ril_event_set(struct ril_event * ev, int fd, bool persist, ril_event_cb func, void * param)
{
LOGD("----RIL_evnent.cpp-shi-xian--void ril_event_set(struct ril_event * ev, int fd, bool persist, ril_event_cb func, void * param)-");
    dlog("~~~~ ril_event_set %x ~~~~", (unsigned int)ev);
    memset(ev, 0, sizeof(struct ril_event));
    ev->fd = fd;
    ev->index = -1;
    ev->persist = persist;
    ev->func = func;
    ev->param = param;
    fcntl(fd, F_SETFL, O_NONBLOCK);
}
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

从传入来的参数,可知道,是注册的ril_init返回的指针RIL_RadioFunctions 参数
说明,到这步的时候,vendor RIL 初始化已经完成(就是ril_init)

若rild socket数据来,就回去执行listencallback函数,这个listencallback函数主要是执行java层通过riled socket来的数据

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
static void listenCallback (int fd, short flags, void *param) {
    int ret;
    int err;
    int is_phone_socket;
    RecordStream *p_rs;

    struct sockaddr_un peeraddr;
    socklen_t socklen = sizeof (peeraddr);

    struct ucred creds;
    socklen_t szCreds = sizeof(creds);

    struct passwd *pwd = NULL;

    assert (s_fdCommand < 0);
    assert (fd == s_fdListen);
 LOGD("   --shi-xian-ril_regiter()----- ril_event_set (&s_debug_event, s_fdDebug, true,debugCallback, NULL);");
//连接JAVA层来的sockcet
    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 */
        rilEventAddWakeup(&s_listen_event);
       return;
    }

    /* check the credential of the other side and only accept socket from
     * phone process
     */
    errno = 0;
    is_phone_socket = 0;

    err = getsockopt(s_fdCommand, SOL_SOCKET, SO_PEERCRED, &creds, &szCreds);

    if (err == 0 && szCreds > 0) {
        errno = 0;
        pwd = getpwuid(creds.uid);
        if (pwd != NULL) {
            if (strcmp(pwd->pw_name, PHONE_PROCESS) == 0) {
                is_phone_socket = 1;
            } else {
                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 */
      rilEventAddWakeup(&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");
//有数据来的时候,把s_fdCommand绑定到record_stream_new 。目的就是保证数据的完整性
    p_rs = record_stream_new(s_fdCommand, MAX_COMMAND_BYTES);
//当有数据来的时候,函数就去执行processCommandsCallback澹()函数,把数据读到p_record中
    ril_event_set(&s_commands_event, s_fdCommand, 1, processCommandsCallback, p_rs);

    rilEventAddWakeup(&s_commands_event);

    onNewCommandConnect();
}

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
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;
LOGD("--SHI-XIAN--ril_regieter-----static void processCommandsCallback(int fd, short flags, void *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 */
        //阻塞方式获取数据 到p_record 利用RecordStream机制保证数据完整
            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 开始监听新的连接*/
        rilEventAddWakeup(&s_listen_event);

说明:它只是把事件添加到里面而已,添加完后,再回去ril_event_loop()去监听新的事件,反复的轮询

        onCommandsSocketClosed();
    }
}

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

上面数据来了,就要都得去找请求队列的序列号,就的做执行processCommandBuffer->status = p.readInt32 (&token);

假设是接收了dial指令,pRI->PCI->dispatchFunction(p,pRI),调用dispatchDial(p,pRI)

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
static int
processCommandBuffer(void *buffer, size_t buflen) {
    Parcel p;
    status_t status;
    int32_t request;
    int32_t token;
    RequestInfo *pRI;
    int ret;
LOGD("---shixian -processCommandBuffer---");
    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;
}

 

原创粉丝点击