RIL 流程

RIL 流程RIL 分为 RILJ 和 RILC 部分 而 RIL 和 modem 通信通过 socket 发送的是串口 ATcommand 其实只要熟悉 linux 编程 rild 部分确实很好理解 花了 4 天左右认认真真分析在初始化 nbsp reference ril 库的时候 创建客户端 socket 连接到 modem 而通过 atchannel 的 at send command full nolock 发送 AT

RIL 分为RILJ 和RILC 部分,而RIL 和modem 通信通过socket ,发送的是串口 AT command

[其实只要熟悉linux 编程,rild 部分确实很好理解]花了4天左右认认真真分析

ril

在初始化 reference-ril 库的时候,创建 客户端socket 连接到modem,而通过atchannel 的at_send_command_full_nolock发送AT command到modem,通过轮询 readline 读取返回信息

hardware/ril/reference-ril/reference-ril.c

const RIL_RadioFunctions *RIL_Init(const struct RIL_Env *env, int argc, char argv){ //.... fd = socket_local_client( s_device_path,ANDROID_SOCKET_NAMESPACE_FILESYSTEM, SOCK_STREAM ); } 

hardware/ril/reference-ril/atchannel.c

 static const char *readline(){ //.... count = read(s_fd, p_read,MAX_AT_RESPONSE - (p_read - s_ATBuffer)); }

代码段 小部件

但是RILJ和RILC 通信的,其实在开机启动的时候,在init.rc文件中,会配置socket 管道,RIL.java和rild.c会根据socketname 相互得到socket,并且,RIL.java 端会充当客户端,rild.c 端充当服务器端

service rild /system/bin/rild class main socket rild0 stream 660 root radio 

上面的rild进程 申明创建socket rild0 权限是660 owner是root 归属于radio ,并且在RIL.java中会创建rild0的socket

class RILReceiver implements Runnable { static final String[] SOCKET_NAME_RIL = {"rild0", "rild1", "rild2"}; @Override public void run() { rilSocket = SOCKET_NAME_RIL[0]; s = new LocalSocket(); l = new LocalSocketAddress(rilSocket, LocalSocketAddress.Namespace.RESERVED); s.connect(l); } }

 重点在RILC端,因为rild守护进程随开机启动,所以rild.c开机就启动,rild的socket 服务器端如下

hardware/ril/rild/rild.c

int main(int argc, char argv) { if (strncmp(clientId, "0", MAX_CLIENT_ID_LENGTH)) { strlcat(rild, clientId, MAX_SOCKET_NAME_LENGTH); RIL_setRilSocketName(rild); //socketname =rild0 } }

hardware/ril/libril/ril.cpp

static void startListen(RIL_SOCKET_ID socket_id, SocketListenParam* socket_listen_p) { switch(socket_id) { case RIL_SOCKET_1: strncpy(socket_name, RIL_getRilSocketName(), 9); break; fdListen = android_get_control_socket(socket_name); ret = listen(fdListen, 4); }

在startListen 找到socket 使得RILJ和RILC 通信,但是如何读写数据?

的到了socket ,就可以接收RILJ发送的请求消息

hardware/ril/libril/ril.cpp

static void processCommandsCallback(int fd, short flags, void *param) { for (;;) { /* loop until EAGAIN/EINTR, end of stream, or other error */ //获取消息 存入p_record buffer中 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, p_info->socket_id); } } }
int record_stream_get_next (RecordStream *p_rs, void p_outRecord, size_t *p_outRecordLen) { countRead = read (p_rs->fd, p_rs->read_end, p_rs->buffer_end - p_rs->read_end); ret = getNextRecord (p_rs, p_outRecordLen); *p_outRecord = ret; }

在processCommandBuffer 过程中将请求消息,转化为 AT指令通过dispatchFunction方法,最后通过   at_send_command_full_nolock发送给modem

 

最后就是读取modem 返回的消息,并且返回给RILJ端口

在轮询readerLoop,通过 readline获取返回数据,然后通过

s_unsolHandler (line1, line2) 
processLine(line); 

处理读取的一行数据

modem 上报分为主动上报和主动上报,也就和URC 和非URC

static void processLine(const char *line) { if (sp_response == NULL) { /* no command pending */ handleUnsolicited(line); //主动上报 } else if (isFinalResponseSuccess(line)) { sp_response->success = 1; handleFinalResponse(line); //非主动上报 }
/ add an intermediate response to sp_response*/ static void addIntermediate(const char *line) { ATLine *p_new; p_new = (ATLine *) malloc(sizeof(ATLine)); p_new->line = strdup(line); /* note: this adds to the head of the list, so the list will be in reverse order of lines received. the order is flipped again before passing on to the command issuer */ p_new->p_next = sp_response->p_intermediates; sp_response->p_intermediates = p_new; }
/ assumes s_commandmutex is held */ static void handleFinalResponse(const char *line) { sp_response->finalResponse = strdup(line); pthread_cond_signal(&s_commandcond); }

当处理 handleFinalResponse 时候,说明modem 已经返回数据完毕,但是在读取中会走addIntermediate ,数据全部保存在sp_response中,当读取完成会通过handleFinalResponse 唤醒在阻塞在at_send_command_full_nolock 函数中,通过  pthread_cond_wait 等待handleFinalResponse 释放s_commandcond,最后将数据保存在pp_outResponse

 

如果返回数据成功,会通过 RIL_onRequestComplete返回,直接write写回 RILJ客户端

RIL_onRequestComplete(t, RIL_E_SUCCESS, &response, sizeof(int));
sendResponse(p, socket_id);
static int blockingWrite(int fd, const void *buffer, size_t len) { while (writeOffset < len) { ssize_t written; do { written = write (fd, toWrite + writeOffset, len - writeOffset); } while (written < 0 && ((errno == EINTR) || (errno == EAGAIN))); } return 0; }

 

当然主动上报直接回调 onUnsolicited 通過 RIL_onUnsolicitedResponse 将数据写回RILJ

ret = sendResponse(p, soc_id);

 

 

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/215620.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月18日 下午1:49
下一篇 2026年3月18日 下午1:50


相关推荐

  • TCP Flags标志位介绍[通俗易懂]

    TCP Flags标志位介绍[通俗易懂]传输控制协议(TransmissionControlProtocol,TCP)是一种传输层协议。TCP使数据包从源到目的地的传输更加顺畅。它是一种面向连接的端到端协议。每个数据包由TCP包裹在一个报头中,该报头由10个强制字段共20个字节和一个0到40字节的可选数据字段组成。如下图所示:来自于https://www.geeksforgeeks.org1.源端口号(SourcePort):16bits,该字段标识发送方应用程序的端口号。2.目…

    2022年7月16日
    20
  • 怎么安装纯净版win10_影视大全纯净版app下载

    怎么安装纯净版win10_影视大全纯净版app下载文章目录1.制作系统安装盘1.1准备U盘以及一台用来制作安装盘的电脑1.2下载WIN10安装包1.3制作完成的系统安装盘1.4U盘格式化应选择的文件系统2.安装WIN10操作系统前的准备2.1插入系统安装盘2.2设置U盘(系统安装盘)为第一启动项2.3注意:启动引导方式的选择2.4补充:磁盘分区格式(MBR分区和GPT分区)和启动引导(Legacy和UEFI)的关系3.开始安装WIN10操作系统3.1将系统直接安装到固态硬盘内(不分区)3.2将固态硬盘分区后,将系统安装到其中一个

    2022年8月11日
    10
  • linux内存分析工具pmap

    linux内存分析工具pmappmap 工具是 linux 的工具 能够查看进程用了多少内存 还能分析内存用在上面环节 对于一些长期占用内存居高不下的程序可以分析其行为 命令简单 信息简洁

    2025年7月24日
    5
  • 时间复杂度计算例题

    时间复杂度计算例题时间复杂度计算例题

    2026年3月19日
    2
  • mysql opkg源_OpenWrt opkg 在线源默认配置

    mysql opkg源_OpenWrt opkg 在线源默认配置destroot/destram/tmplists_dirext/var/opkg-listsoptionoverlay_root/overlaysrc/gzbarrier_breaker_basehttp://downloads.openwrt.org/barrier_breaker/14.07/x86/generic/packages/basesrc/gzbarrier_…

    2022年6月2日
    50
  • chmod 用法_举例说明chmod的两种用法

    chmod 用法_举例说明chmod的两种用法chmod[options]modefiles只能文件属主或特权用户才能使用该功能来改变文件存取模式。mode可以是数字形式或以whoopcodepermission形式表示。who是可选的,默认是a(所有用户)。只能选择一个opcode(操作码)。可指定多个mode,以逗号分开。options:-c,–changes只输出被改变文件的信息

    2022年10月20日
    4

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号