您的位置:首页 > 其它

RIL源码分析

2015-10-18 20:08 239 查看
前面已经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;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: