RIL 机制---消息RILJ中的处理
来源:互联网 发布:微信数据储存到sd卡里 编辑:程序博客网 时间:2024/06/05 08:16
9,RILJ
接收子线程要完成的就是对接收数据的处理操作。还分为两步去分析:
1、如何接收的消息;
2、消息的处理流程。
9.1数据接收过程
接收子线程RILReceiver的run方法主要代码如下,
class RILReceiver implements Runnable { byte[] buffer; RILReceiver() { buffer = new byte[RIL_MAX_COMMAND_BYTES]; } @Override public void run() { int retryCount = 0; String rilSocket = "rild"; try {for (;;) { LocalSocket s = null; LocalSocketAddress l; if (mInstanceId == null || mInstanceId == 0 ) { rilSocket = SOCKET_NAME_RIL[0]; } else { rilSocket = SOCKET_NAME_RIL[mInstanceId]; } try { s = new LocalSocket(); l = new LocalSocketAddress(rilSocket, LocalSocketAddress.Namespace.RESERVED); s.connect(l); } catch (IOException ex){ ••• try { Thread.sleep(SOCKET_OPEN_RETRY_MILLIS);//休眠4s } catch (InterruptedException er) { } retryCount++; continue; } retryCount = 0; mSocket = s; Rlog.i(RILJ_LOG_TAG, "(" + mInstanceId + ") Connected to '" + rilSocket + "' socket"); int length = 0; try { InputStream is = mSocket.getInputStream(); for (;;) { Parcel p; length = readRilMessage(is, buffer); if (length < 0) { // End-of-stream reached break; } p = Parcel.obtain(); p.unmarshall(buffer, 0, length); p.setDataPosition(0); //Rlog.v(RILJ_LOG_TAG, "Read packet: " + length + " bytes"); processResponse(p); p.recycle(); } } ••• try { //关闭Socket,然后重新打开 mSocket.close(); } catch (IOException ex) { } mSocket = null; RILRequest.resetSerial();//清除 // Clear request list on close clearRequestList(RADIO_NOT_AVAILABLE, false); //清除所有请求 }} catch (Throwable tr) { Rlog.e(RILJ_LOG_TAG,"Uncaught exception", tr); } /* We're disconnected so we don't know the ril version */ notifyRegistrantsRilConnectionChanged(-1); //通知ril连接状态改变 } }
逻辑也挺简单,主要是2个for循环,
1,第一个for循环打开开了Socket的通道,并且为RIL中的全局变量mSocket赋值。
LocalSocket mSocket;
发送子线程RILSender就是利用该mSocket往RILD发送消息。
2,第二个for循环,首先调用readRilMessage方法从Socket中读取消息,然后调用processResponse方法进行消息处理。
如果读取的过程出现异常,将会关闭Socket通道,并且清除RILRequest系列号和请求列表,重新打开Socket。
readRilMessage方法如下,
private static int readRilMessage(InputStream is, byte[] buffer) throws IOException { int countRead; int offset; int remaining; int messageLength; // First, read in the length of the message offset = 0; remaining = 4; //先读取数据的长度 do { countRead = is.read(buffer, offset, remaining); if (countRead < 0 ) { Rlog.e(RILJ_LOG_TAG, "Hit EOS reading message length"); return -1; } offset += countRead; remaining -= countRead; } while (remaining > 0); //计算数据长度 messageLength = ((buffer[0] & 0xff) << 24) | ((buffer[1] & 0xff) << 16) | ((buffer[2] & 0xff) << 8) | (buffer[3] & 0xff); // Then, re-use the buffer and read in the message itself offset = 0; remaining = messageLength;//再读取有效数据 do { countRead = is.read(buffer, offset, remaining); if (countRead < 0 ) { Rlog.e(RILJ_LOG_TAG, "Hit EOS reading message. messageLength=" + messageLength + " remaining=" + remaining); return -1; } offset += countRead; remaining -= countRead; } while (remaining > 0); return messageLength; }
可以看出,返回的数据分为两部分,数据长度+数据内容,通过对InputStream的连续读取得到了完整的数据,
并把数据的长度返回出来,而数据的内容通过buffer带出来。发送子线程RILSender发送数据时也是包含2部分,数据长度和内容。
再次说明一下,RIL层收到的消息分为2种:
1,第一种是Modem主动上报的消息,比如新短信的提醒,、来电、Modem状态的改变等,这类消息称为URC消息, 在此称为上报消息。
2,第二种是由终端(RILJ)发送给Modem(RIL)后,Modem给出的回应,属于非URC消息,在此称为回应消息。
对于URC消息来说,只需要调用相应的通知机制即可;而对于非URC消息,我们还需要把相应的数据返回给当初发送请求的单位。
既然RILC层对消息的处理方式不同,那么对应的在RILJ中也要分开处理:
processResponse方法如下,
private void processResponse (Parcel p) { int type; type = p.readInt(); if (type == RESPONSE_UNSOLICITED) { processUnsolicited (p);// 上报消息处理 } else if (type == RESPONSE_SOLICITED) { RILRequest rr = processSolicited (p);//回应消息处理 if (rr != null) { rr.release(); decrementWakeLock(); } } }
上报消息是通过processUnsolicited方法处理的,而回应消息是由processSolicited方法处理的,分别介绍两种处理流程。
9.2. 上报消息处理
processUnsolicited方法如下,
private void processUnsolicited (Parcel p) { int response; Object ret;//读取当前消息的消息码 response = p.readInt(); try {switch(response) { //先处理 case RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED: ret = responseVoid(p); break; case RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED: ret = responseVoid(p); break; case RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED: ret = responseVoid(p); break;•••switch(response) { //再次处理 case RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED: /* has bonus radio state int */ RadioState newState = getRadioStateFromInt(p.readInt()); if (RILJ_LOGD) unsljLogMore(response, newState.toString()); switchToRadioState(newState); break; case RIL_UNSOL_RESPONSE_IMS_NETWORK_STATE_CHANGED: if (RILJ_LOGD) unsljLog(response); mImsNetworkStateChangedRegistrants .notifyRegistrants(new AsyncResult(null, null, null)); break; case RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED: if (RILJ_LOGD) unsljLog(response); mCallStateRegistrants .notifyRegistrants(new AsyncResult(null, null, null)); break;•••
上面代码只挑出部分消息的处理代码,从中可以看到,上报消息的处理要经过两个switch语句的处理:
1、第一个switch:
根据不同的消息码对数据进行初步解析,得到上报的有效数据。
例如,responseVoid, responseInts等。
2、第二个switch
对有效数据进行不同的处理,主要就是调用相应的管理者去做相应的通知。
消息码是int类型,并且消息码的定义RILJ和RIL肯定保持一致:
1, RILJ的消息码定义在RILConstants.java文件中。
2, RILC的消息码定义在ril.h文件中。
例如,2个文件对RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED定义如下,
RILConstants.java中定义为,
int RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED = 1000;
ril.h中定义为,
#define RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED 1000
9.3 回应消息处理
回应消息是在processSolicited方法中处理的,主要分3个步骤,
9.3.1,获取封装消息的RILRequest对象
int serial, error;boolean found = false;serial = p.readInt();//获取系列号,每个RILRequest对象有唯一的系列号error = p.readInt();RILRequest rr;rr = findAndRemoveRequestFromList(serial);
findAndRemoveRequestFromList方法如下,
private RILRequest findAndRemoveRequestFromList(int serial) { RILRequest rr = null; synchronized (mRequestList) { rr = mRequestList.get(serial); if (rr != null) { mRequestList.remove(serial); } } return rr; }
从mRequestList稀疏list中根据serial获取,获取到之后从mRequestList移除。
mRequestList定义如下,
SparseArray<RILRequest> mRequestList = new SparseArray<RILRequest>();
RILRequest对象是在子线程RILSender的handleMessage方法在通过socket发送之前添加到mRequestList,如下,
ynchronized (mRequestList) { mRequestList.append(rr.mSerial, rr); }
这样RILRequest对象刚好一一对应起来。
9.3.2,根据RILRequest对象的mRequest变量获取RIL的回应的消息
try {switch (rr.mRequest) { case RIL_REQUEST_GET_SIM_STATUS: ret = responseIccCardStatus(p); break; case RIL_REQUEST_ENTER_SIM_PIN: ret = responseInts(p); break; case RIL_REQUEST_ENTER_SIM_PUK: ret = responseInts(p); break; case RIL_REQUEST_ENTER_SIM_PIN2: ret = responseInts(p); break; ••••
根据不同的消息码(mRequest)对数据进行初步解析,得到回应的有效数据。
例如,4.1小节中拨号dial方法中消息对应的mRequest变量为RIL_REQUEST_DIAL,
case RIL_REQUEST_DIAL: ret = responseVoid(p); break;private Object responseVoid(Parcel p) { return null; }
在7.4 小节论述过,modem上报的消息并不一定包含数据。
Modem回应消息的内容有2种,一种返回空消息,另外一种返回查询的内容。
拨号对应的返回消息是空的,而发送消息返回的消息有封装数据的,解析数据的方法responseSMS方法如下,
private Object responseSMS(Parcel p) { int messageRef, errorCode; String ackPDU; messageRef = p.readInt(); ackPDU = p.readString(); errorCode = p.readInt(); SmsResponse response = new SmsResponse(messageRef, ackPDU, errorCode); return response; }
然后看下reference-ril中从Modem读取数据后对数据进行打包,ril_commands.h有关代码如下,
{RIL_REQUEST_SEND_SMS, dispatchStrings, responseSMS},
RIL_REQUEST_SEND_SMS消息码对应的打包方法为responseSMS。
看到了吧,RILJ对应的解析方法为responseSMS,这是一一对应的。
9.3.3,将有效数据返回给当初的请求者
if (rr.mResult != null) { AsyncResult.forMessage(rr.mResult, ret, null); rr.mResult.sendToTarget(); }
在回应消息的处理流程中,同样要先得到RILC层上报的有效数据,但是得到数据之后并不像
上报消息那样主动的去通知相应的管理者去做通知,而是需要根据当前消息的mResult把有效数据发送给当初的发送者,由发送者自己去处理消息。
同样的,和上报消息一样,消息码分别保存在RILConstants.java和ril.h中,并且int数值完全一一对应。
这样,整个消息的流程走下来,终于都走完了。
- RIL 机制---消息RILJ中的处理
- RIL 机制---消息从RILJ到RIL
- RIL 机制---消息从RIL到RILJ
- RIL 机制---消息从RIL到reference-ril
- RIL 机制---消息从reference-ril到RIL
- DELPHI中的消息处理机制
- ELPHI中的消息处理机制
- DELPHI中的消息处理机制
- DELPHI中的消息处理机制
- DELPHI中的消息处理机制
- DELPHI中的消息处理机制
- DELPHI中的消息处理机制
- RIL框架结构及RILJ的运行机制
- RIL 机制---消息从reference-ril到Modem
- DELPHI中的消息处理机制(收藏)
- anroid中的消息处理机制--基本概念
- Looper中的消息队列处理机制
- Looper中的消息队列处理机制
- Megatextures in Rage
- Spark流处理中的DStrem.foreachRDD()方法
- JAVA总结
- matlab常用函数
- Id tech5虚拟纹理
- RIL 机制---消息RILJ中的处理
- POJ1067 HDU1527 取石子游戏
- Java Web MVC简单实现
- 软工文档总结
- 卡马克在光线追踪,id tech6,射线跟踪,控制台,物理学等的谈话 第一部分
- 有趣的排序
- HDU2516 取石子游戏
- 信息系统项目管理师考试基本信息说明
- 欢迎使用CSDN-markdown编辑器