前面已经RILD进行了分析,现在就对RILJ进行简单的分析
1.绪论
所有上层对RIL层的请求,最终都需要在RILJ中转换为RIL层可识别的命令,然后通过Socket通道传输下去
同时,RIL层据的上报,也要通过RILJ进行解码,还原为上层容易识别的格式
RILJ有两个主要特点:
1、开启了两个独立线程分别负责发送数据和接收数据
2、数据的发送和接收是异步的,采用令牌系统来找到当初的请求者
2.RILRequest令牌系统
class RILRequest {
........
private static Object sPoolSync = new Object(); //sPool分配与回收的互斥锁
private static RILRequest sPool = null;//代表了一个RILRequest对象的链表
private static int sPoolSize = 0;// 当前sPool所在链表的长度
private static final int MAX_POOL_SIZE = 4; // sPool的最大个数
........
int mSerial; //令牌,每生成(obtain)一个新的请求,都将产生一个递增的,唯一的mSerial。当从RILC中得到一个数据后,我们就是通过mSerial找到当初发送这个请求的对象
int mRequest; // 请求码,需要和RIL层中的ril_commands.h文件内定义的请求码一致
Message mResult; // 生成当前请求的请求者。从RILC中得到数据后,需要把数据处理后返回给mResult指向的对象
Parcel mParcel; // 附加数据
RILRequest mNext; // 链表结构,代表下一个RILRequest
........
static RILRequest obtain(int request, Message result) { // 生成一个RILRequest的消息对象
// 如果sPool所在链表不为空则从该链表中获取一个RILRequest对象,否则新构造一个
RILRequest rr = null;
synchronized(sPoolSync) {
if (sPool != null) {
rr = sPool;
sPool = rr.mNext;
rr.mNext = null;
sPoolSize--;
}
}
if (rr == null) {
rr = new RILRequest();
}
// 初始化令牌mSerial,AtomicInteger的getAndIncrement可保证当前请求的令牌是唯一的,递增的
rr.mSerial = sNextSerial.getAndIncrement();
rr.mRequest = request;// 初始化请求码mRequest
rr.mResult = result;// 初始化请求者mResult
rr.mParcel = Parcel.obtain();
if (result != null && result.getTarget() == null) {
throw new NullPointerException("Message target must not be null");
}
// 写入请求码与请求者
rr.mParcel.writeInt(request);
rr.mParcel.writeInt(rr.mSerial);
return rr;
}
void release() { // 释放资源
synchronized (sPoolSync) {
if (sPoolSize < MAX_POOL_SIZE) { // 如果当前sPool链表还没有满,则将当前RILRequest对象添加到链表中以便复用
mNext = sPool;
sPool = this;
sPoolSize++;
mResult = null;
}
}
}
private RILRequest() {} // 构造函数,内容为空
static void resetSerial() {........} // 重置令牌
String serialString() {........} // 生成包含mSerial的字串,主要用于打印Log
void onError(int error, Object ret) {........} // 异常处理
}
3.发送子线程
1、如何把数据发送到mSenderThread中;
// 创建mSender的时候就是用mSenderThread的looper来创建的,即用mSender发送消息即可发送到mSenderThread中
public RIL(Context context, int preferredNetworkType, int cdmaSubscription) {
super(context);
........
//发送子线程
mSenderThread = new HandlerThread("RILSender");
mSenderThread.start();
Looper looper = mSenderThread.getLooper();
//mSender是发送子线程的Handler,通过他可以发送数据
mSender = new RILSender(looper);
........
//接收子线程
mReceiver = new RILReceiver();
mReceiverThread = new Thread(mReceiver, "RILReceiver");
mReceiverThread.start();
........
}
// 发送短消息
public void sendSMS (String smscPDU, String pdu, Message result) {
// 构建一个请求
RILRequest rr = RILRequest.obtain(RIL_REQUEST_SEND_SMS, result);
constructGsmSendSmsRilRequest(rr, smscPDU, pdu);
if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
//发送
send(rr);
}
........
private void send(RILRequest rr) {
Message msg;
// 如果Socket通道还没有打开
if (mSocket == null) {
rr.onError(RADIO_NOT_AVAILABLE, null);
rr.release();
return;
}
// 生成mSender的消息
msg = mSender.obtainMessage(EVENT_SEND, rr);
acquireWakeLock();
// 发送给子线程
msg.sendToTarget();
}
2、mSenderThread是如何把请求发送给RILC的
class RILSender extends Handler implements Runnable {
........
@Override
public void run() {}
@Override
public void handleMessage(Message msg) {
RILRequest rr = (RILRequest)(msg.obj);
RILRequest req = null;
switch (msg.what) {
case EVENT_SEND:
try {
LocalSocket s;
// 得到Socket通道
s = mSocket;
........
// 获取数据的长度
dataLength[0] = dataLength[1] = 0;
dataLength[2] = (byte)((data.length >> 8) & 0xff);
dataLength[3] = (byte)((data.length) & 0xff);
//Rlog.v(RILJ_LOG_TAG, "writing packet: " + data.length + " bytes");
// 通过Socket通道将数据长度与数据发送出去
s.getOutputStream().write(dataLength);
s.getOutputStream().write(data);
} catch (IOException ex) {
........
} catch (RuntimeException exc) {
........
}
break;
case EVENT_WAKE_LOCK_TIMEOUT:
........
break;
}
}
}
4.接收子线程
1、如何接收的消息
// 读取ril传回的数据
private static int readRilMessage(InputStream is, byte[] buffer) throws IOException {
........
do { // 先读取数据的长度
countRead = is.read(buffer, offset, remaining);// 从InputStream中读取数据
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;
}
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 (;;) { // 如果出现异常,将会关闭socket并清除令牌和请求列表,并重新打开Socket通道
//开启Socket通道
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){
........
}
retryCount = 0;
mSocket = s;
Rlog.i(RILJ_LOG_TAG, "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);
// 处理数据【见详情】
processResponse(p);
p.recycle();
}
} catch (java.io.IOException ex) {
........
}
Rlog.i(RILJ_LOG_TAG, "Disconnected from '" + rilSocket + "' socket");
setRadioState (RadioState.RADIO_UNAVAILABLE);
//关闭Socket,等下一次for循环的时候会重新打开Socket
try {
mSocket.close();
} catch (IOException ex) {
}
mSocket = null;
//清除令牌
RILRequest.resetSerial();
//清除所有请求
clearRequestList(RADIO_NOT_AVAILABLE, false);
}
} catch (Throwable tr) {
Rlog.e(RILJ_LOG_TAG,"Uncaught exception", tr);
}
//通知ril连接状态改变
notifyRegistrantsRilConnectionChanged(-1);
}
}
2、消息的处理流程
private void processResponse (Parcel p) { // 信息处理
int type;
type = p.readInt();//得到数据的类型,是URC消息还是非URC消息
if (type == RESPONSE_UNSOLICITED) {
processUnsolicited (p); //URC消息的处理【见详情】
} else if (type == RESPONSE_SOLICITED) {
RILRequest rr = processSolicited (p); //非URC消息的处理
if (rr != null) {
rr.release();
decrementWakeLock();
}
}
}
//URC消息的处理
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; // responseVoid当前消息的附带数据为空
case RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED: ret = responseVoid(p); break;
case RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED: ret = responseVoid(p); break;
case RIL_UNSOL_RESPONSE_NEW_SMS: ret = responseString(p); break; // responseString当前消息的附带数据为String型,需要得到String
........
}
........
}
// 再处理
switch(response) {
case RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED: // Radio状态改变
RadioState newState = getRadioStateFromInt(p.readInt());
if (RILJ_LOGD) unsljLogMore(response, newState.toString());
switchToRadioState(newState);
break;
case RIL_UNSOL_RESPONSE_IMS_NETWORK_STATE_CHANGED:
mImsNetworkStateChangedRegistrants.notifyRegistrants(new AsyncResult(null, null, null));
break;
case RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED: //通知call状态改变
if (RILJ_LOGD) unsljLog(response);
mCallStateRegistrants.notifyRegistrants(new AsyncResult(null, null, null));
break;
case RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED: //通知网络状态改变
if (RILJ_LOGD) unsljLog(response);
mVoiceNetworkStateRegistrants.notifyRegistrants(new AsyncResult(null, null, null));
break;
case RIL_UNSOL_RESPONSE_NEW_SMS: {
if (RILJ_LOGD) unsljLog(response);
// FIXME this should move up a layer
String a[] = new String[2];
a[1] = (String)ret;
SmsMessage sms; // 新短信
sms = SmsMessage.newFromCMT(a);
if (mGsmSmsRegistrant != null) { //发送短信通知
mGsmSmsRegistrant.notifyRegistrant(new AsyncResult(null, sms, null));
}
break;
}
case RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT: //短信报告
if (RILJ_LOGD) unsljLogRet(response, ret);
if (mSmsStatusRegistrant != null) {
mSmsStatusRegistrant.notifyRegistrant(
new AsyncResult(null, ret, null));
}
break;
........
}
}
//非URC消息的处理
private RILRequest processSolicited (Parcel p) {
int serial, error;
boolean found = false;
serial = p.readInt();
error = p.readInt();
RILRequest rr;
// 得到当前的RILRequest对象,然后从mRequestList中将其删除
rr = findAndRemoveRequestFromList(serial);
if (rr == null) {
Rlog.w(RILJ_LOG_TAG, "Unexpected solicited response! sn: "
+ serial + " error: " + error);
return null;
}
Object ret = null;
if (error == 0 || p.dataAvail() > 0) {
// either command succeeds or command fails but with data payload
try {
switch (rr.mRequest) { //得到RIL上报的数据
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;
........
}
}
........
}
........
switch (rr.mRequest) { //对PUK的两个消息需要单独的通知其管理者
case RIL_REQUEST_ENTER_SIM_PUK:
case RIL_REQUEST_ENTER_SIM_PUK2:
if (mIccStatusChangedRegistrants != null) {
if (RILJ_LOGD) {
riljLog("ON enter sim puk fakeSimStatusChanged: reg count="
+ mIccStatusChangedRegistrants.size());
}
mIccStatusChangedRegistrants.notifyRegistrants();
}
break;
}
if (error != 0) {
........
} else {
if (RILJ_LOGD) riljLog(rr.serialString() + "< " + requestToString(rr.mRequest)
+ " " + retToString(rr.mRequest, ret));
//将返回值返回给当初的请求者,由请求者去决定如何处理数据
if (rr.mResult != null) {
AsyncResult.forMessage(rr.mResult, ret, null);
rr.mResult.sendToTarget();
}
}
return rr;
}