RIL源码分析

  前面已经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;
    }

你可能感兴趣的:(RIL源码分析)