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 。
- ~/android-4.2.2_r1/hardware/ril/$ ls -hl
- total 24K
- -rw-r--r-- 1 idnix idnix 2.3K 2013-02-27 10:59 CleanSpec.mk
- drwxr-xr-x 3 idnix idnix 4.0K 2013-02-27 10:59 include/
- drwxr-xr-x 2 idnix idnix 4.0K 2013-02-27 10:59 libril/
- drwxr-xr-x 3 idnix idnix 4.0K 2013-02-27 10:59 mock-ril/
- drwxr-xr-x 2 idnix idnix 4.0K 2013-03-05 17:50 reference-ril/
- 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 启动相关的配置:
- service ril-daemon /system/bin/rild
- class main
- socket rild stream 660 root radio
- socket rild-debug stream 660 radio system
- user root
- group radio cache inet misc audio log
在启动 rild 守护进程时,可以使用参数指定 libreference-ril.so 的路径和 Modem 串口设备文件。用法如下:
- Usage: rild -l <ril impl library> [-- <args for impl library>]
- eg:rild -l /system/lib/your_libreference-ril.so --d /dev/ttyU0
若 init.rc 中未指定 库 和 AT 接口,那么 rild 会则系统将从 rild.c 的两个宏定义中进行获取:
- #define LIB_PATH_PROPERTY "rild.libpath"
- #define LIB_ARGS_PROPERTY "rild.libargs"
而这两个属性值是在 ~/android-4.2.2_r1/build/target/board/generic/system.prop 中指定的:
- #
- # system.prop for generic sdk
- #
- rild.libpath=/system/lib/libreference-ril.so
- rild.libargs=-d /dev/ttyS0
如果经历上面两个过程仍未找到正确的 libreference-ril.so ,那么 rild 将使用 rild.c 中定义的路径来找库文件。
- #define REFERENCE_RIL_PATH "/system/lib/libreference-ril.so"
$ gvim rild.c
- /* //device/system/rild/rild.c
- **
- ** 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.
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <dlfcn.h>
- #include <string.h>
- #include <stdint.h>
- #include <unistd.h>
- #include <fcntl.h>
- #include <errno.h>
- #include <telephony/ril.h>
- #define LOG_TAG "RILD"
- #include <utils/Log.h>
- #include <cutils/properties.h>
- #include <cutils/sockets.h>
- #include <linux/capability.h>
- #include <linux/prctl.h>
- #include <private/android_filesystem_config.h>
- #include "hardware/qemu_pipe.h"
- #define LIB_PATH_PROPERTY "rild.libpath"
- #define LIB_ARGS_PROPERTY "rild.libargs"
- #define MAX_LIB_ARGS 16
- static void usage(const char *argv0)
- {
- fprintf(stderr, "Usage: %s -l <ril impl library> [-- <args for impl library>]\n", argv0);
- exit(-1);
- }
- extern void RIL_register (const RIL_RadioFunctions *callbacks);
- extern void RIL_onRequestComplete(RIL_Token t, RIL_Errno e,
- void *response, size_t responselen);
- extern void RIL_onUnsolicitedResponse(int unsolResponse, const void *data,
- size_t datalen);
- extern void RIL_requestTimedCallback (RIL_TimedCallback callback,
- void *param, const struct timeval *relativeTime);
- static struct RIL_Env s_rilEnv = {
- RIL_onRequestComplete,
- RIL_onUnsolicitedResponse,
- RIL_requestTimedCallback
- };
- extern void RIL_startEventLoop();
- static int make_argv(char * args, char ** argv)
- {
- // Note: reserve argv[0]
- int count = 1;
- char * tok;
- char * s = args;
- while ((tok = strtok(s, " \0"))) {
- argv[count] = tok;
- s = NULL;
- count++;
- }
- return count;
- }
- /*
- * switchUser - Switches UID to radio, preserving CAP_NET_ADMIN capabilities.
- * Our group, cache, was set by init.
- */
- void switchUser() {
- prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
- setuid(AID_RADIO);
- struct __user_cap_header_struct header;
- struct __user_cap_data_struct cap;
- header.version = _LINUX_CAPABILITY_VERSION;
- header.pid = 0;
- cap.effective = cap.permitted = (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW);
- cap.inheritable = 0;
- capset(&header, &cap);
- }
- 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;
- int i;
- umask(S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH | S_IXOTH);
- for (i = 1; i < argc ;) {
- if (0 == strcmp(argv[i], "-l") && (argc - i > 1)) {
- rilLibPath = argv[i + 1];
- i += 2;
- } else if (0 == strcmp(argv[i], "--")) {
- i++;
- hasLibArgs = 1;
- break;
- } else {
- usage(argv[0]);
- }
- }
- if (rilLibPath == NULL) {
- if ( 0 == property_get(LIB_PATH_PROPERTY, libPath, NULL)) {
- // No lib sepcified on the command line, and nothing set in props.
- // Assume "no-ril" case.
- goto done;
- } else {
- rilLibPath = libPath;
- }
- }
- /* special override when in the emulator */
- #if 1
- {
- static char* arg_overrides[3];
- static char arg_device[32];
- int done = 0;
- #define REFERENCE_RIL_PATH "/system/lib/libreference-ril.so"
- /* first, read /proc/cmdline into memory */
- char buffer[1024], *p, *q;
- int len;
- int fd = open("/proc/cmdline",O_RDONLY);
- if (fd < 0) {
- ALOGD("could not open /proc/cmdline:%s", strerror(errno));
- goto OpenLib;
- }
- do {
- len = read(fd,buffer,sizeof(buffer)); }
- while (len == -1 && errno == EINTR);
- if (len < 0) {
- ALOGD("could not read /proc/cmdline:%s", strerror(errno));
- close(fd);
- goto OpenLib;
- }
- close(fd);
- if (strstr(buffer, "android.qemud=") != NULL)
- {
- /* the qemud daemon is launched after rild, so
- * give it some time to create its GSM socket
- */
- int tries = 5;
- #define QEMUD_SOCKET_NAME "qemud"
- while (1) {
- int fd;
- sleep(1);
- fd = qemu_pipe_open("qemud:gsm");
- if (fd < 0) {
- fd = socket_local_client(
- QEMUD_SOCKET_NAME,
- ANDROID_SOCKET_NAMESPACE_RESERVED,
- SOCK_STREAM );
- }
- if (fd >= 0) {
- close(fd);
- snprintf( arg_device, sizeof(arg_device), "%s/%s",
- ANDROID_SOCKET_DIR, QEMUD_SOCKET_NAME );
- arg_overrides[1] = "-s";
- arg_overrides[2] = arg_device;
- done = 1;
- break;
- }
- ALOGD("could not connect to %s socket: %s",
- QEMUD_SOCKET_NAME, strerror(errno));
- if (--tries == 0)
- break;
- }
- if (!done) {
- ALOGE("could not connect to %s socket (giving up): %s",
- QEMUD_SOCKET_NAME, strerror(errno));
- while(1)
- sleep(0x00ffffff);
- }
- }
- /* otherwise, try to see if we passed a device name from the kernel */
- if (!done) do {
- #define KERNEL_OPTION "android.ril="
- #define DEV_PREFIX "/dev/"
- p = strstr( buffer, KERNEL_OPTION );
- if (p == NULL)
- break;
- p += sizeof(KERNEL_OPTION)-1;
- q = strpbrk( p, " \t\n\r" );
- if (q != NULL)
- *q = 0;
- snprintf( arg_device, sizeof(arg_device), DEV_PREFIX "%s", p );
- arg_device[sizeof(arg_device)-1] = 0;
- arg_overrides[1] = "-d";
- arg_overrides[2] = arg_device;
- done = 1;
- } while (0);
- if (done) {
- argv = arg_overrides;
- argc = 3;
- i = 1;
- hasLibArgs = 1;
- rilLibPath = REFERENCE_RIL_PATH;
- ALOGD("overriding with %s %s", arg_overrides[1], arg_overrides[2]);
- }
- }
- OpenLib:
- #endif
- switchUser(); //设置 rild 的组用户为 radio
- dlHandle = dlopen(rilLibPath, RTLD_NOW); //通过 dlopen 来加载动态库
- if (dlHandle == NULL) {
- ALOGE("dlopen failed: %s", dlerror());
- exit(-1);
- }
- RIL_startEventLoop(); //调用 ril.cpp 中的 RIL_startEventLoop 函数,libril.so 开始循环监听 socket 事件。
- //获得指向 libreference-ril.so 中 RIL_Init 函数的指针 rilInit
- rilInit = (const RIL_RadioFunctions *(*)(const struct RIL_Env *, int, char **))dlsym(dlHandle, "RIL_Init");
- if (rilInit == NULL) {
- ALOGE("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];
- //调用 libreference-ril.so 中的 RIL_Init 函数
- //注意传入的参数和返回值
- funcs = rilInit(&s_rilEnv, argc, rilArgv);
- //调用 libril.so 中的 RIL_register 函数
- //把前面的到的 funcs 作为参数传递给 RIL_register
- RIL_register(funcs);
- done:
- while(1) {
- // sleep(UINT32_MAX) seems to return immediately on bionic
- sleep(0x00ffffff);
- }
- }
由代码可知:
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 源码分析》中介绍
- rild 源码分析
- Android Rild模块源码分析
- Android之rild进程启动源码分析
- Android之rild进程启动源码分析
- Android之rild进程启动源码分析
- Android之rild进程启动源码分析
- Android之rild进程启动源码分析
- Rild层代码分析
- Android之rild进程启动源码分析(个人认为写的比较完善的一个)
- Android4.4 RIL源码分析——RILD的启动过程
- Android4.4 RIL源码分析——RILD的运行过程(Solicited)
- Android4.4 RIL源码分析——RILD的运行过程(Unsolicited)
- Ril分析一 rild进程
- Android 电话系统rild分析
- rild
- rild
- RILD
- RILD
- uva 704
- XMPP聊天客户端环境搭建
- 有中国电信手机一定要看。CTWAP和CTNET是什么意思?有什么区别?
- UVa:357 Let Me Count The Ways
- Ubuntu右键菜单添加新建OpenOffice文件
- rild 源码分析
- hdu 1002
- .Net MVC4 使用心得(五)细节问题Url.Action和Html.ActionLink
- 简单介绍Java EE容器
- VC++之屏幕抓取
- 第一篇文章
- xml--通过jdom解析及生产XML
- J2EE初学者要理解的几个问题
- operator new和operator delete->优化内存分配