欢迎转载,转载请注明出处 xianzhu21.space

RIL 简介

RIL(Radio Interface Layer) 是一种 HAL(Hardware Abstraction Layer),它提供控制 Modem 的统一接口。而 RILJ 是一种给 Java 层提供与 RIL 通信的Android Framework 层服务。RILJ 通过 Unix Socket 与 RIL 守护进程通信,可以说 RILJ 是Telephony 框架中 Java 层的最底层。

RILJ 有 2 种服务机制——req/resp 和 ind 服务。因为网络服务需要异步操作,RILJ 中有 2 个线程——RILSender 和 RILReceiver,分别处理向 RIL 守护程序发送数据和从 RIL 守护程序接收数据。

req/resp 服务机制

req/resp服务机制的流程是

  1. 客户端发送特定类型的 Message 对象给 RILJ
  2. RILJ 用 Message 对象生成 RILRequest 对象,发送给 RILSender 线程
  3. RILSender 线程先把 RILRequest 对象加到 RILRequest List,然后将 RILRequest 对象的数据序列化后用 Socket 发送给 RIL 守护进程
  4. RILReceiver 接收 RIL 守护进程发送的结果,并从 RILRequest List 中找到相应的 RILRequest,取出客户端发送的 Message 对象,把结果存到 Message 对象中并发送给客户端的 Handler 对象
  5. 客户端的 Handler 对象根据 Message 对象类型处理结果

下面结合源码一一分析每一个步骤。以 Android 6 源码分析,但 Android 4, 5, 6 的 MO 在 RIL 部分的代码基本没有改变。

MO in Framework
MO in Framework

上图是 MO (Mobile Origination, 即拨打电话) 在 Framework 层的时序图。

1. 客户端发送给 RILJ

首先 Phone(GsmPhone 为例,CdmaPhone 类似)对象调用 GsmCallTracker(继承自 Handler)对象的 dial,GsmCallTracker 对象调用 CommandInterface对象 (即RIL对象)的dial方法。

/* GsmCallTacker.java */
synchronized Connection dial (String dialString, int clirMode, UUSInfo uusInfo, Bundle intentExtras)
        throws CallStateException {
    ...
    // 调用CommandInterface对象,即RIL对象的dial()方法
    // obtainCompleteMessage(EVENT_DIAL_CALL_RESULT)方法是获取
    // msg.what为EVENT_DIAL_CALL_RESULT的Message对象
    mCi.dial(mPendingMO.getAddress(), clirMode, uusInfo,
            obtainCompleteMessage(EVENT_DIAL_CALL_RESULT));
    ...
}

2. RILJ 发送给 RILSender 线程

接下来分析RIL的dial方法。

/* RIL.java */
@Override
public void dial(String address, int clirMode, UUSInfo uusInfo, Message result) {
    // 获取RILRequest对象,包含客户端传递的Message对象
    RILRequest rr = RILRequest.obtain(RIL_REQUEST_DIAL, result);
    // 写入数据
    rr.mParcel.writeString(address);
    rr.mParcel.writeInt(clirMode);
    ...
    send(rr);
}

RIL 的 dial 方法中利用 GsmCallTracker 传递过来的 Message 对象获取 RILRequest 对象。RILRequest 类主要有 4 个成员变量。int mSerial 是用来唯一标识 RILRequest 对象的变量,int mRequest 是 RILSender 用于区分 RILRequest 类型的变量,MO 中为 RIL_REQUEST_DIAL,Message mResult 是存储结果的 Message 对象,是从 GsmCallTracker 传递过来的,Parcel mParcel 是存储请求数据的 Parcel 对象。

/* RIL.java */
static RILRequest obtain(int request, Message result) {
    RILRequest rr = null;
    synchronized(sPoolSync) {
        if (sPool != null) {
            rr = sPool;
            sPool = rr.mNext;
            rr.mNext = null;
            sPoolSize--;
        }
    }
    if (rr == null) {
        rr = new RILRequest();
    }
    // 唯一序列号
    rr.mSerial = sNextSerial.getAndIncrement();
    // RILRequest类型
    rr.mRequest = request;
    // 用来保存结果的Message对象,从客户端传递过来
    rr.mResult = result;
    // 获取用来存储请求数据的Parcel对象
    rr.mParcel = Parcel.obtain();
    if (result != null && result.getTarget() == null) {
        throw new NullPointerException("Message target must not be null");
    }
    // first elements in any RIL Parcel
    rr.mParcel.writeInt(request);
    rr.mParcel.writeInt(rr.mSerial);
    return rr;
}

接下来调用 RIL 的 send 方法,传递刚获取到的 RILRequest 对象。send 方法将 RILRequest 对象存到 Message 对象后发送给 RILSender 处理。

/* RIL.java */
private void send(RILRequest rr) {
    Message msg;
    if (mSocket == null) {
        rr.onError(RADIO_NOT_AVAILABLE, null);
        rr.release();
        return;
    }
    // 获取RILSender的Message对象
    msg = mSender.obtainMessage(EVENT_SEND, rr);
    acquireWakeLock();
    // Message对象发送给RILSender对象
    msg.sendToTarget();
}

3. RILSender 线程发送给 RIL 守护进程

接下来我们来分析 RILSender 的工作机制。

RILSender 继承自 Handler,实现了 Runnable 接口。RIL 在构造方法中创建 HandlerThread 线程来执行 RILSender。

/* RIL.java */
public RIL(Context context, int preferredNetworkType, int cdmaSubscription, Integer instanceId) {
    ...
    mSenderThread = new HanlderThread("RILSender" + mInstanceId);
    mSenderThread.start();

    Looper looper = mSenderThread.getLooper();
    mSender =  new RILSender(looper);
    ...
}

RILSender 接收 RIL 发送的 Message 对象后在 handleMessage 方法中处理 RILRequest 对象,然后利用 RILReceiver 创建的 LocalSocket 对象把 RIL req 数据发送给 RIL 守护进程。

/* RIL.java */
class RILSender extends Handler implements Runnable {
    public RILSender(Looper looper) {
        super(looper);
    }

    @Override
    public void handleMessage(Message msg) {
        // 从Message对象取RILRequest对象
        RILRequest rr = (RILRequest)(msg.obj);
        ...

        switch (msg.what) {
            case EVENT_SEND:
                try {
                    LocalSocket s;
                    // mSocket为RILReceiver创建的LocalSocket对象
                    s = mSocket;
                    ...
                    byte[] data;
                    // 对Parcel对象编组,以便用Socket发送给RILC
                    data = rr.mParcel.marshall();
                    // 把RILRequest对象加入到RILRequest List,以便RIL resp服务查找
                    synchronized (mRequestList) {
                        mRequestList.append(rr.mSerial, rr);
                        rr.mParcel.recycle();
                        rr.mParcel = null;
                    }
                    ...
                    // parcel length in big endan
                    dataLength[0] = dataLength[1] = 0;
                    dataLength[2] = (byte)((data.length >> 8) & 0xff);
                    dataLength[3] = (byte)((data.length) & 0xff);

                    // 发送给RIL守护进程
                    s.getOutputStream().write(dataLength);
                    s.getOutputStream().write(data);
                } catch ...
                break;
            ...
        }
    }
}

4. RILReceiver 接收 RIL 守护进程发送的结果,处理后发送给客户端的 Handler

首先从 socket 中读取数据,然后根据类型(resp 服务或 ind 服务)处理。从 mRequestList 中根据 serial 值取出 RILRequest 对象并删除。然后从RILRequest 对象中取出客户端的 Message 对象,把 rild 返回的数据存到 Message 对象中,然后发送给客户端来处理返回的数据。

/* RIL.java */
class RILReceiver implements Runnable {
    byte[] buffer;
    ...
    @Override
    public void
    run() {
        ...
        try {
            // 连接rild的socket
            s = new LocalSocket();
            l = new LocalSocketAddress(rilSocket,
                    LocalSocketAddress.Namespace.RESERVED);
            s.connect(l);
        } catch (IOException ex){
            ...
        }
        // 把socket保存到mSocket成员变了,共RILSender调用
        mSocket = s;
        ...
        int length = 0;
        try {
            InputStream is = mSocket.getInputStream();
            for (;;) {
                Parcel p;
                // 从socket中读取数据存到buffer
                length = readRilMessage(is, buffer);
                if (length < 0) {
                    // End-of-stream reached
                    break;
                }
                // 把数据反编组保存到Parcel对象中
                p = Parcel.obtain();
                p.unmarshall(buffer, 0, length);
                p.setDataPosition(0);

                // Rlog.v(RILJ_LOG_TAG, "Read packet: " + length + " bytes");
                // 处理数据
                processResponse(p);
                p.recycle();
            }
        } catch {}
        ...
    }
}

private void processResponse (Parcel p) {
    int type;
    type = p.readInt();
    if (type == RESPONSE_UNSOLICITED) {
        // 处理ind服务,即rild自发发送的数据
        processUnsolicited (p);
    } else if (type == RESPONSE_SOLICITED) {
        // 处理resp服务,即请求rild后返回的数据
        RILRequest rr = processSolicited (p);
        if (rr != null) {
            rr.release();
            decrementWakeLock();
        }
    }
}

private RILRequest processSolicited (Parcel p) {
    int serial, error;
    boolean found = false;

    serial = p.readInt();
    error = p.readInt();

    RILRequest rr;
    // 在mRequestList中取出RILRequest对象,然后删除
    rr = findAndRemoveRequestFromList(serial);
    ...
    if (error == 0 || p.dataAvail() > 0) {
        try {switch (rr.mRequest) {
        ...
        // responseVoid方法中直接返回null
        case RIL_REQUEST_DIAL: ret =  responseVoid(p); break;
        ...
        }} // catch {}
    }
    ...
    if (error == 0) {
        if (rr.mResult != null) {
            // 处理RILRequest对象的数据
            // 用AsyncResult对象包一下m.obj和ret然后再赋给m.obj
            /*
            public static AsyncResult
            forMessage(Message m, Object r, Throwable ex) {
                AsyncResult ret;
                ret = new AsyncResult (m.obj, r, ex);
                m.obj = ret;
                return ret;}
            */
            AsyncResult.forMessage(rr.mResult, ret, null);
            // 发送给客户端的Handler对象来处理
            rr.mResult.sendToTarget();
        }
    }
    return rr;
}

5. 客户端的 Handler 对象根据 Message 对象类型处理结果

GsmCallTracker 对象处理返回的 Message 对象

/* GsmCallTracker.java */
@Override
public void handleMessage (Message msg) {
    AsyncResult ar;
    ...
    switch (msg.what) {
        ...
        case EVENT_DIAL_CALL_RESULT:
            ar = (AsyncResult) msg.obj;
            if (ar.exception != null) {
                log("dial call failed!!");
                mHelper.PendingHangupRequestUpdate();
            }
            operationComplete();
        break;
        ...
    }
}

RILJ 的 req/resp 服务的整个流程如下图所示。

RIL req/resp
RIL req/resp service

ind 服务机制

ind 服务机制的流程是

  1. RILReceiver 从 rild 获得消息,然后在 processUnsolicited 方法中根据 reponse 类型获得底层传过来的数据。
  2. 再根据 response 类型,调用相应的 Registrant 对象的 notifyRegistrant 方法或 RegistrantList 对象的 notifyRegistrants 方法。
  3. 把数据封装成 AsyncResult 对象,发送给相应的注册对象。

我们以来电为例来说明 ind 服务的流程。

1. RILReceiver 获取 rild 发来的消息

第一步跟 req/resp 服务中 RILReceiver 接收消息的代码一致,在 processResponse 方法中 ind 服务的消息会调用 processUnsolicited 方法。这里不再赘述。

2. 调用相应的 Registrant 对象的 notifyRegistrant 方法

下面的代码是 processUnsolicited 方法的处理过程,最后会调用 mRingRegistrant 的 notifyRegistrant 方法。

/* RIL.java */
private void processUnsolicited (Parcel p) {
    int response;
    Object ret;

    response = p.readInt();

    try {switch(response) {
        ...
        // 从 Pacel 对象中获取数据,保存在 char 数组中
        case RIL_UNSOL_CALL_RING: ret =  responseCallRing(p); break;

    }} // catch

    switch(response) {
        ...
        case RIL_UNSOL_CALL_RING:
                if (RILJ_LOGD) unsljLogRet(response, ret);
                if (mRingRegistrant != null) {
                    // mRingRegistrant不空说明有注册对象,调用notifyRegistrant方法来通知注册对象
                    mRingRegistrant.notifyRegistrant(new AsyncResult (null, ret, null));
                }
                break;
        ...
    }
}

mRingRegistrant 是 Registrant 对象,Registrant 机制其实是订阅者模式。RIL 继承自 BaseCommand 类,Registrant 对象和 RegistrantList 对象是在BaseCommand 中创建的,因此 RIL 类也拥有 mRingRegistrant。

3. 把数据发送给相应的注册对象

在这里首先说明 Registrant 的机制,先看下 Registrant 类的代码。

/* Registrant.java */
public class Registrant
{
    public Registrant(Handler h, int what, Object obj)
    {
        refH = new WeakReference(h);
        this.what = what;
        userObj = obj;
    }

    // 这个方法还有其他3个方法重载,参数分别是空、Object对象和Throwable对象
    public void notifyRegistrant(AsyncResult ar)
    {
        internalNotifyRegistrant (ar.result, ar.exception);
    }

    /*package*/ void internalNotifyRegistrant (Object result, Throwable exception)
    {
        Handler h = getHandler();
        if (h == null) {
            clear();
        } else {
            Message msg = Message.obtain();
            msg.what = what;
            msg.obj = new AsyncResult(userObj, result, exception);
            h.sendMessage(msg); // 把数据给注册对象的Handler发送Message
        }
    }

    public Handler getHandler()
    {
        if (refH == null)
            return null;

        return (Handler) refH.get();
    }

    // 拥有 3 个成员变量,它们的值都是构造方法中注册对象传递过来的
    WeakReference   refH; // 存储 Handler 对象的弱引用
    int             what; // 注册对象用来区分不同的 Registrant 对象,注册对象可能会注册很多 Registrant
    Object          userObj;
}

RegistrantList 类跟 Registrant 类似,该类中有一个 ArrayList,每注册一次就创建一个 Registrant 对象后加入到 ArrayList中,而internalNotifyRegistrants 方法中遍历调用每个 Registrant 对象的 internalNotifyRegistrant 方法。

接下来看一下 mRingRegistrant 的注册方法,在 BaseCommand 类中。

/* BaseCommand.java */
// 很简单的一个方法,就是用注册对象的三个变量把mRingRegistrant实例化
@Override
public void setOnCallRing(Handler h, int what, Object obj) {
    mRingRegistrant = new Registrant (h, what, obj);
}

@Override
public void unSetOnCallRing(Handler h) {
    if (mRingRegistrant != null && mRingRegistrant.getHandler() == h) {
        mRingRegistrant.clear();
        mRingRegistrant = null;
    }
}

PhoneBase 类在构造方法中注册了 mRingRegistrant。

/* PhoneBase.java */
protected PhoneBase(String name, PhoneNotifier notifier, Context context, CommandsInterface ci,
            boolean unitTestMode, int phoneId) {
    ...
    mCi = ci;
    // 注册mRingRegistrant
    mCi.setOnCallRing(this, EVENT_CALL_RING, null);
    ...
}

@Override
public void handleMessage(Message msg) {
    AsyncResult ar;
    ...
    switch(msg.what) {
        // 在handleMessage方法中处理mRingRegistrant发送的消息
        case EVENT_CALL_RING:
            Rlog.d(LOG_TAG, "Event EVENT_CALL_RING Received state=" + getState());
            ar = (AsyncResult)msg.obj;
            if (ar.exception == null) {
                PhoneConstants.State state = getState();
                if ((!mDoesRilSendMultipleCallRing)
                        && ((state == PhoneConstants.State.RINGING) ||
                                (state == PhoneConstants.State.IDLE))) {
                    mCallRingContinueToken += 1;
                    sendIncomingCallRingNotification(mCallRingContinueToken);
                } else {
                    notifyIncomingRing();
                }
            }
            break;
        ...
    }
}

ind 服务机制就是客户端注册 Registrant,RILReceiver 接收消息后调用相应的 Registrant.notifyRegistrant 方法,在该方法中把消息发送给客户端的 Handler,最终在客户端的 handleMessge 方法中处理消息。流程图如下所示。

RIL ind
RIL ind service

to be continued…

Xianzhu21

Xianzhu21
An Android framework developer.

Window Touchable Region

当用户触屏后,InputReader 从驱动读取一个输入事件加入到队列,InputDispatcher 从队列中读取一个输入事件准备分发。如果该输入事件是一个触摸事件...
Continue reading

Dropping event bug in Dialog

Published on March 10, 2020

InputChannel and InputDispatcher in Android

Published on February 27, 2020