rild 源码分析

来源:互联网 发布:富盈网络水军 编辑:程序博客网 时间:2024/06/05 11:44

转载请标明出处 - http://blog.csdn.net/idnix/article/details/8647669


关注libril 、 reference-ril 、 rild 这三个目录,通过查看 Android.mk 可知编译后将产生 libril.so 、 libreference-ril.so 、 rild 。

[plain] view plaincopy
  1. ~/android-4.2.2_r1/hardware/ril/$ ls -hl  
  2. total 24K  
  3. -rw-r--r-- 1 idnix idnix 2.3K 2013-02-27 10:59 CleanSpec.mk  
  4. drwxr-xr-x 3 idnix idnix 4.0K 2013-02-27 10:59 include/  
  5. drwxr-xr-x 2 idnix idnix 4.0K 2013-02-27 10:59 libril/  
  6. drwxr-xr-x 3 idnix idnix 4.0K 2013-02-27 10:59 mock-ril/  
  7. drwxr-xr-x 2 idnix idnix 4.0K 2013-03-05 17:50 reference-ril/  
  8. drwxr-xr-x 2 idnix idnix 4.0K 2013-03-07 17:42 rild/  


运行机制图示:



首先要启动 rild 。在 ~/android-4.2.2_r1/system/core/rootdir/init.rc 里有 rild 启动相关的配置:

[plain] view plaincopy
  1. service ril-daemon /system/bin/rild  
  2.     class main  
  3.     socket rild stream 660 root radio  
  4.     socket rild-debug stream 660 radio system  
  5.     user root  
  6.     group radio cache inet misc audio log  


在启动 rild 守护进程时,可以使用参数指定 libreference-ril.so 的路径和 Modem 串口设备文件。用法如下:

[plain] view plaincopy
  1. Usage: rild -l <ril impl library> [-- <args for impl library>]  
  2. eg:rild -l /system/lib/your_libreference-ril.so --d /dev/ttyU0  

若 init.rc 中未指定 库 和 AT 接口,那么 rild 会则系统将从 rild.c 的两个宏定义中进行获取:

[plain] view plaincopy
  1. #define LIB_PATH_PROPERTY "rild.libpath"  
  2. #define LIB_ARGS_PROPERTY "rild.libargs"  

而这两个属性值是在 ~/android-4.2.2_r1/build/target/board/generic/system.prop 中指定的:

[plain] view plaincopy
  1. #  
  2. # system.prop for generic sdk   
  3. #  
  4.   
  5. rild.libpath=/system/lib/libreference-ril.so  
  6. rild.libargs=-d /dev/ttyS0  

如果经历上面两个过程仍未找到正确的 libreference-ril.so ,那么 rild 将使用 rild.c 中定义的路径来找库文件。

[cpp] view plaincopy
  1. #define  REFERENCE_RIL_PATH  "/system/lib/libreference-ril.so"  


$ gvim rild.c

[cpp] view plaincopy
  1. /* //device/system/rild/rild.c 
  2. ** 
  3. ** Copyright 2006, The Android Open Source Project 
  4. ** 
  5. ** Licensed under the Apache License, Version 2.0 (the "License"); 
  6. ** you may not use this file except in compliance with the License. 
  7. ** You may obtain a copy of the License at 
  8. ** 
  9. **     http://www.apache.org/licenses/LICENSE-2.0 
  10. ** 
  11. ** Unless required by applicable law or agreed to in writing, software 
  12. ** distributed under the License is distributed on an "AS IS" BASIS, 
  13. ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
  14. ** See the License for the specific language governing permissions and 
  15. ** limitations under the License. 
  16. */  
  17.   
  18. #include <stdio.h>  
  19. #include <stdlib.h>  
  20. #include <dlfcn.h>  
  21. #include <string.h>  
  22. #include <stdint.h>  
  23. #include <unistd.h>  
  24. #include <fcntl.h>  
  25. #include <errno.h>  
  26.   
  27. #include <telephony/ril.h>  
  28. #define LOG_TAG "RILD"  
  29. #include <utils/Log.h>  
  30. #include <cutils/properties.h>  
  31. #include <cutils/sockets.h>  
  32. #include <linux/capability.h>  
  33. #include <linux/prctl.h>  
  34.   
  35. #include <private/android_filesystem_config.h>  
  36. #include "hardware/qemu_pipe.h"  
  37.   
  38. #define LIB_PATH_PROPERTY   "rild.libpath"  
  39. #define LIB_ARGS_PROPERTY   "rild.libargs"  
  40. #define MAX_LIB_ARGS        16  
  41.   
  42. static void usage(const char *argv0)  
  43. {  
  44.     fprintf(stderr, "Usage: %s -l <ril impl library> [-- <args for impl library>]\n", argv0);  
  45.     exit(-1);  
  46. }  
  47.   
  48. extern void RIL_register (const RIL_RadioFunctions *callbacks);  
  49.   
  50. extern void RIL_onRequestComplete(RIL_Token t, RIL_Errno e,  
  51.                            void *response, size_t responselen);  
  52.   
  53. extern void RIL_onUnsolicitedResponse(int unsolResponse, const void *data,  
  54.                                 size_t datalen);  
  55.   
  56. extern void RIL_requestTimedCallback (RIL_TimedCallback callback,  
  57.                                void *param, const struct timeval *relativeTime);  
  58.   
  59.   
  60. static struct RIL_Env s_rilEnv = {  
  61.     RIL_onRequestComplete,  
  62.     RIL_onUnsolicitedResponse,  
  63.     RIL_requestTimedCallback  
  64. };  
  65.   
  66. extern void RIL_startEventLoop();  
  67.   
  68. static int make_argv(char * args, char ** argv)  
  69. {  
  70.     // Note: reserve argv[0]  
  71.     int count = 1;  
  72.     char * tok;  
  73.     char * s = args;  
  74.   
  75.     while ((tok = strtok(s, " \0"))) {  
  76.         argv[count] = tok;  
  77.         s = NULL;  
  78.         count++;  
  79.     }  
  80.     return count;  
  81. }  
  82.   
  83. /* 
  84.  * switchUser - Switches UID to radio, preserving CAP_NET_ADMIN capabilities. 
  85.  * Our group, cache, was set by init. 
  86.  */  
  87. void switchUser() {  
  88.     prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);  
  89.     setuid(AID_RADIO);  
  90.   
  91.     struct __user_cap_header_struct header;  
  92.     struct __user_cap_data_struct cap;  
  93.     header.version = _LINUX_CAPABILITY_VERSION;  
  94.     header.pid = 0;  
  95.     cap.effective = cap.permitted = (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW);  
  96.     cap.inheritable = 0;  
  97.     capset(&header, &cap);  
  98. }  
  99.   
  100. int main(int argc, char **argv)  
  101. {  
  102.     const char * rilLibPath = NULL;  
  103.     char **rilArgv;  
  104.     void *dlHandle;  
  105.     const RIL_RadioFunctions *(*rilInit)(const struct RIL_Env *, intchar **);  
  106.     const RIL_RadioFunctions *funcs;  
  107.     char libPath[PROPERTY_VALUE_MAX];  
  108.     unsigned char hasLibArgs = 0;  
  109.   
  110.     int i;  
  111.   
  112.     umask(S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH | S_IXOTH);  
  113.     for (i = 1; i < argc ;) {  
  114.         if (0 == strcmp(argv[i], "-l") && (argc - i > 1)) {  
  115.             rilLibPath = argv[i + 1];  
  116.             i += 2;  
  117.         } else if (0 == strcmp(argv[i], "--")) {  
  118.             i++;  
  119.             hasLibArgs = 1;  
  120.             break;  
  121.         } else {  
  122.             usage(argv[0]);  
  123.         }  
  124.     }  
  125.   
  126.     if (rilLibPath == NULL) {  
  127.         if ( 0 == property_get(LIB_PATH_PROPERTY, libPath, NULL)) {  
  128.             // No lib sepcified on the command line, and nothing set in props.  
  129.             // Assume "no-ril" case.  
  130.             goto done;  
  131.         } else {  
  132.             rilLibPath = libPath;  
  133.         }  
  134.     }  
  135.   
  136.     /* special override when in the emulator */  
  137. #if 1  
  138.     {  
  139.         static char*  arg_overrides[3];  
  140.         static char   arg_device[32];  
  141.         int           done = 0;  
  142.   
  143. #define  REFERENCE_RIL_PATH  "/system/lib/libreference-ril.so"  
  144.   
  145.         /* first, read /proc/cmdline into memory */  
  146.         char          buffer[1024], *p, *q;  
  147.         int           len;  
  148.         int           fd = open("/proc/cmdline",O_RDONLY);  
  149.   
  150.         if (fd < 0) {  
  151.             ALOGD("could not open /proc/cmdline:%s", strerror(errno));  
  152.             goto OpenLib;  
  153.         }  
  154.   
  155.         do {  
  156.             len = read(fd,buffer,sizeof(buffer)); }  
  157.         while (len == -1 && errno == EINTR);  
  158.   
  159.         if (len < 0) {  
  160.             ALOGD("could not read /proc/cmdline:%s", strerror(errno));  
  161.             close(fd);  
  162.             goto OpenLib;  
  163.         }  
  164.         close(fd);  
  165.   
  166.         if (strstr(buffer, "android.qemud=") != NULL)  
  167.         {  
  168.             /* the qemud daemon is launched after rild, so 
  169.             * give it some time to create its GSM socket 
  170.             */  
  171.             int  tries = 5;  
  172. #define  QEMUD_SOCKET_NAME    "qemud"  
  173.   
  174.             while (1) {  
  175.                 int  fd;  
  176.   
  177.                 sleep(1);  
  178.   
  179.                 fd = qemu_pipe_open("qemud:gsm");  
  180.                 if (fd < 0) {  
  181.                     fd = socket_local_client(  
  182.                                 QEMUD_SOCKET_NAME,  
  183.                                 ANDROID_SOCKET_NAMESPACE_RESERVED,  
  184.                                 SOCK_STREAM );  
  185.                 }  
  186.                 if (fd >= 0) {  
  187.                     close(fd);  
  188.                     snprintf( arg_device, sizeof(arg_device), "%s/%s",  
  189.                                 ANDROID_SOCKET_DIR, QEMUD_SOCKET_NAME );  
  190.   
  191.                     arg_overrides[1] = "-s";  
  192.                     arg_overrides[2] = arg_device;  
  193.                     done = 1;  
  194.                     break;  
  195.                 }  
  196.                 ALOGD("could not connect to %s socket: %s",  
  197.                     QEMUD_SOCKET_NAME, strerror(errno));  
  198.                 if (--tries == 0)  
  199.                     break;  
  200.             }  
  201.             if (!done) {  
  202.                 ALOGE("could not connect to %s socket (giving up): %s",  
  203.                     QEMUD_SOCKET_NAME, strerror(errno));  
  204.                 while(1)  
  205.                     sleep(0x00ffffff);  
  206.             }  
  207.         }  
  208.   
  209.         /* otherwise, try to see if we passed a device name from the kernel */  
  210.         if (!done) do {  
  211. #define  KERNEL_OPTION  "android.ril="  
  212. #define  DEV_PREFIX     "/dev/"  
  213.   
  214.             p = strstr( buffer, KERNEL_OPTION );  
  215.             if (p == NULL)  
  216.                 break;  
  217.   
  218.             p += sizeof(KERNEL_OPTION)-1;  
  219.             q  = strpbrk( p, " \t\n\r" );  
  220.             if (q != NULL)  
  221.                 *q = 0;  
  222.   
  223.             snprintf( arg_device, sizeof(arg_device), DEV_PREFIX "%s", p );  
  224.             arg_device[sizeof(arg_device)-1] = 0;  
  225.             arg_overrides[1] = "-d";  
  226.             arg_overrides[2] = arg_device;  
  227.             done = 1;  
  228.   
  229.         } while (0);  
  230.   
  231.         if (done) {  
  232.             argv = arg_overrides;  
  233.             argc = 3;  
  234.             i    = 1;  
  235.             hasLibArgs = 1;  
  236.             rilLibPath = REFERENCE_RIL_PATH;  
  237.   
  238.             ALOGD("overriding with %s %s", arg_overrides[1], arg_overrides[2]);  
  239.         }  
  240.     }  
  241. OpenLib:  
  242. #endif  
  243.     switchUser();    //设置 rild 的组用户为 radio  
  244.   
  245.     dlHandle = dlopen(rilLibPath, RTLD_NOW);    //通过 dlopen 来加载动态库  
  246.   
  247.     if (dlHandle == NULL) {  
  248.         ALOGE("dlopen failed: %s", dlerror());  
  249.         exit(-1);  
  250.     }  
  251.   
  252.     RIL_startEventLoop();    //调用 ril.cpp 中的 RIL_startEventLoop 函数,libril.so 开始循环监听 socket 事件。  
  253.   
  254.     //获得指向 libreference-ril.so 中 RIL_Init 函数的指针 rilInit   
  255.     rilInit = (const RIL_RadioFunctions *(*)(const struct RIL_Env *, intchar **))dlsym(dlHandle, "RIL_Init");  
  256.   
  257.     if (rilInit == NULL) {  
  258.         ALOGE("RIL_Init not defined or exported in %s\n", rilLibPath);  
  259.         exit(-1);  
  260.     }  
  261.   
  262.     if (hasLibArgs) {  
  263.         rilArgv = argv + i - 1;  
  264.         argc = argc -i + 1;  
  265.     } else {  
  266.         static char * newArgv[MAX_LIB_ARGS];  
  267.         static char args[PROPERTY_VALUE_MAX];  
  268.         rilArgv = newArgv;  
  269.         property_get(LIB_ARGS_PROPERTY, args, "");  
  270.         argc = make_argv(args, rilArgv);  
  271.     }  
  272.   
  273.     // Make sure there's a reasonable argv[0]  
  274.     rilArgv[0] = argv[0];  
  275.   
  276.     //调用 libreference-ril.so 中的 RIL_Init 函数  
  277.     //注意传入的参数和返回值  
  278.     funcs = rilInit(&s_rilEnv, argc, rilArgv);  
  279.   
  280.     //调用 libril.so 中的 RIL_register 函数  
  281.     //把前面的到的 funcs 作为参数传递给 RIL_register  
  282.     RIL_register(funcs);  
  283.   
  284. done:  
  285.   
  286.     while(1) {  
  287.         // sleep(UINT32_MAX) seems to return immediately on bionic  
  288.         sleep(0x00ffffff);  
  289.     }  
  290. }  

由代码可知:
1. rild 会调用 ril.cpp 中的 RIL_startEventLoop 函数
2. rild 会调用 reference-ril.c 中的 RIL_Init 函数
3. rild 会调用 ril.cpp 中的 RIL_register 函数

1 和 3 我将在 《libril.so 源码分析》(http://blog.csdn.net/idnix/article/details/8665358)中介绍
2 我将在 《libreference-ril.so 源码分析》中介绍
原创粉丝点击