IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Android RIL详解 -> 正文阅读

[移动开发]Android RIL详解

目录

一、前言

二、框架

三、什么是RIL

四、RIL请求消息

五、RIL Receiver

六、RIL Sender

一、前言

Android作为一个通用的移动平台,其首要的功能就是通话、短信以及上网等通信功能。那么,从系统的角度来看,Android究竟是怎么实现与网络的交互的了? 就来看一看Android中负责通信功能的Telephony中间层,通常也被称之为RIL(Radio Interface Layer)。

由于 Android 开发者使用的 Modem 是不一样的,各种指令格式,初始化序列都可能不一样,GSM 和 CDMA 就差别更大了,所以为了消除这些差别,Android 设计者将RIL做了一个抽象,使用一个虚拟电话的概念。

这个虚拟电话对象就是GSMPhone、CDMAPhone, Phone 对象所提供的功能协议,以及要求下层的支撑环境都有一个统一的描述,这个底层描述的实现就是靠RIL来完成适配。

// 电话状态跟踪
public abstract class CallTracker extends Handler

// 无线服务状态跟踪
public class ServiceStateTracker extends Handler

// 数据连接状态跟踪
public class DcTracker extends Handler;

以上三个 Tracker 对象负责与 RIL 类的 Java 对象进行交互,而这些交互在 RIL 层中的处理是与 Modem 基于串口连接的AT命令的发送和执行,最终完成语音通话、网络服务状态和网络数据连接的控制和管理。

二、框架

Android手机要实现与网络端的通信,需要跨越两个层:

  • RIL Java(RILJ):负责将上层APP的通信请求发送给HAL层;
  • RIL C++(RILD):系统守护进程,负责将RILJ的请求命令发送给CP(Communication Processor)

三、什么是RIL

简单的说,RIL(Radio Interface Layer),就是将应用程序的通信请求发送给CP的中间层,其包括两个部分,一个是Java层RILJ,一个是C++层(不妨看作是CP对应的HAL层)RILD。

RILJ属于系统Phone进程的一部分,随Phone进程启动而加载;而RILD守护进程是通过Android的Init进程进行加载的。
下图是一个Android RIL的一个结构图。整个通信过程有四个层:

  1. 最上层的是应用程序,如通话,短信以及SIM卡管理,它们主要负责将用户的指令发送到RIL Framework(以后统称RILJ);
  2. RILJ为上层提供了通用的API,如TelephonyManager(包括通话,网络状态; SubscriptionManager(卡状态)以及SmsManager等,同时RILJ还负责维持与RILD的通信,并将上层的请求发送给RILD;
  3. RILD是系统的守护进程,对于支持通话功能的移动平台是必不可少的。RILD的功能主要功能是将RILJ发送过来的请求继续传递给CP,同时会及时将CP的状态变化发送给RILJ;
  4. Linux驱动层:kernel驱动层接受到数据后,将指令传给CP,最后由CP发送给网络端,等网络返回结果后,CP将传回给RILD;

四、RIL请求消息

RIL Solicited消息

终端主动请求消息: Dial 拨号、Answer 接听电话、Hangup 挂断电话

public interface RILConstants {

    -----------------------------------------
    int RIL_REQUEST_GET_SIM_STATUS = 1;
    -----------------------------------------
    int RIL_REQUEST_DIAL = 10;
    int RIL_REQUEST_GET_IMSI = 11;
    int RIL_REQUEST_HANGUP = 12;
    -----------------------------------------
    int RIL_REQUEST_GET_IMEI = 38;
    -----------------------------------------
    int RIL_REQUEST_UPDATE_ADN_RECORD = 141;
    -----------------------------------------

    int RIL_RESPONSE_ACKNOWLEDGEMENT = 800;

}

RIL?Unsolicited消息

Modem 硬件主动上报的消息: 来电、接通电话、接收短信、基站信息等消息


public interface RILConstants {

    int RIL_UNSOL_RESPONSE_BASE = 1000;
    int RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED = 1000;
    int RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED = 1001;
    int RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED = 1002;
    int RIL_UNSOL_RESPONSE_NEW_SMS = 1003;
    int RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT = 1004;
    int RIL_UNSOL_RESPONSE_NEW_SMS_ON_SIM = 1005;

    ----------------------------------------------------------

    int RIL_UNSOL_RESPONSE_ADN_INIT_DONE = 1047;
    int RIL_UNSOL_RESPONSE_ADN_RECORDS = 1048;

}

RILJ CommandsInterface.java

public interface CommandsInterface {

    // Radio 无线通信模块的状态
    enum RadioState {
        RADIO_OFF,         /* Radio explicitly powered off (eg CFUN=0) */
        RADIO_UNAVAILABLE, /* Radio unavailable (eg, resetting or not booted) */
        RADIO_ON;          /* Radio is on */

        public boolean isOn() /* and available...*/ {
            return this == RADIO_ON;
        }

        public boolean isAvailable() {
            return this != RADIO_UNAVAILABLE;
        }
    }

}

BaseCommands.java

public abstract class BaseCommands implements CommandsInterface {

    // RegistrantList 注册的消息列表
    protected RegistrantList mCallStateRegistrants = new RegistrantList();

    protected RegistrantList mDataNetworkStateRegistrants = new RegistrantList();

    protected RegistrantList mSignalInfoRegistrants = new RegistrantList();
}

RIL.Java–RILRequest?

// 请求消息体
class RILRequest {

    static AtomicInteger sNextSerial = new AtomicInteger(0);  // 下一个 RILRequest 对象编号

    private static Object sPoolSync = new Object();  // 用于同步访问

    private static RILRequest sPool = null; // 保存下一个处理的 RILRequest 对象

    private static int sPoolSize = 0;

    private static final int MAX_POOL_SIZE = 4;  // 缓存池大小

    int mSerial;  // 当前请求编号

    int mRequest; // RIL 请求类型

    Message mResult; // 保存 RIL 请求的Message对象

    RILRequest mNext;  // 下一个 RILRequest 处理对象

    /** * Retrieves a new RILRequest instance from the pool. * * @param request RIL_REQUEST_* * @param result sent when operation completes * @return a RILRequest instance from the pool. */
    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();

        rr.mRequest = request;
        rr.mResult = result;
        rr.mParcel = Parcel.obtain();

        rr.mWakeLockType = RIL.INVALID_WAKELOCK;
        rr.mStartTimeMs = SystemClock.elapsedRealtime();
        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 请求返回异常或者失败的处理
    void onError(int error, Object ret) {
        CommandException ex;

        ex = CommandException.fromRilErrno(error);

        if (RIL.RILJ_LOGD) Rlog.d(LOG_TAG, serialString() + "< "
            + RIL.requestToString(mRequest)
            + " error: " + ex + " ret=" + RIL.retToString(mRequest, ret));

        if (mResult != null) {
            AsyncResult.forMessage(mResult, ret, ex);
            mResult.sendToTarget();
        }

        if (mParcel != null) {
            mParcel.recycle();
            mParcel = null;
        }
    }

}

?RIL.Java

public final class RIL extends BaseCommands implements CommandsInterface {

    HandlerThread mSenderThread;
    RILSender mSender;

    Thread mReceiverThread;
    RILReceiver mReceiver;

    // 请求消息对象列表
    // RILJ 发起请求消息时,将 RILRequest 请求对象保存在 mRequestsList 列表中;
    // RILC 处理完成返回消息后,将此消息从 mRequestsList 列表移除,
    // 这说明正常情况下 Request 和 Response处于一一对应的关系
    SparseArray<RILRequest> mRequestList = new SparseArray<RILRequest>();

    // 向RILC发出请求消息
    class RILSender extends Handler implements Runnable {

        @Override
        public void handleMessage(Message msg) {
            RILRequest rr = (RILRequest)(msg.obj);
            RILRequest req = null;

            switch (msg.what) {
                case EVENT_SEND:
                case EVENT_SEND_ACK:
                        LocalSocket s;

                        s = mSocket;
                        ---------------------------------------------
                        // 向 Socket 写入请求消息
                        s.getOutputStream().write(dataLength);
                        s.getOutputStream().write(data);
                        ---------------------------------------------
                     break;
            }
        }

    }

    // 接收RILC发出的消息
    class RILReceiver implements Runnable {

        // 循环监听mSocket上报的消息
        @Override
        public void run() {
            ------------------------------------------------------------------
                for (;;) {
                    ----------------------------------------------------------
                    s = new LocalSocket();
                    l = new LocalSocketAddress(rilSocket,
                            LocalSocketAddress.Namespace.RESERVED);
                    s.connect(l);
                    ----------------------------------------------------------


                    InputStream is = mSocket.getInputStream();

                    for (;;) {
                        Parcel p;

                        length = readRilMessage(is, buffer);

                        p = Parcel.obtain();
                        p.unmarshall(buffer, 0, length);
                        p.setDataPosition(0);

                        //Rlog.v(RILJ_LOG_TAG, "Read packet: " + length + " bytes");

                        processResponse(p);  // 处理 RILC 上报的消息
                        p.recycle();

                    }

                }
            --------------------------------------------------------------------
        }

    }

    // RILC 返回的消息处理
    private void processResponse (Parcel p) {
        int type;

        type = p.readInt();

        if (type == RESPONSE_UNSOLICITED || type == RESPONSE_UNSOLICITED_ACK_EXP) {
            // 处理 Modem 主动上报的消息
            processUnsolicited (p, type);
        } else if (type == RESPONSE_SOLICITED || type == RESPONSE_SOLICITED_ACK_EXP) {
            // 处理 RILJ 请求返回的消息
            RILRequest rr = processSolicited (p, type);
            if (rr != null) {
                if (type == RESPONSE_SOLICITED) {
                    decrementWakeLock(rr);
                }
                rr.release();
                return;
            }
        } else if (type == RESPONSE_SOLICITED_ACK) {
            int serial;
            serial = p.readInt();

            RILRequest rr;
            synchronized (mRequestList) {
                rr = mRequestList.get(serial);
            }
            if (rr == null) {
                Rlog.w(RILJ_LOG_TAG, "Unexpected solicited ack response! sn: " + serial);
            } else {
                decrementWakeLock(rr);
                if (RILJ_LOGD) {
                    riljLog(rr.serialString() + " Ack < " + requestToString(rr.mRequest));
                }
            }
        }
    }

    // 处理 Modem 主动上报的消息
    private void processUnsolicited(Parcel p, int type) {
        int response;
        Object ret;

        response = p.readInt();

        // 组装返回对象ret
        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;
                -----------------------------------------------
            }
        } catch (Throwable tr) {
            Rlog.e(RILJ_LOG_TAG, "Exception processing unsol response: " + response +
                    "Exception:" + tr.toString());
            return;
        }

        // 发送出 Registant消息通知
        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_SIGNAL_STRENGTH:
                // Note this is set to "verbose" because it happens
                // frequently
                if (RILJ_LOGV) unsljLogvRet(response, ret);

                // 发出消息通知,此通知是 ServiceStaterTracker接收和处理的
                if (mSignalStrengthRegistrant != null) {
                    mSignalStrengthRegistrant.notifyRegistrant(
                            new AsyncResult(null, ret, null));
                }
                break;
        }

    }

    // 处理客户端向 RILC 请求返回的消息
    private RILRequest processSolicited(Parcel p, int type) {
        int serial, error;
        boolean found = false;

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

        RILRequest rr;

        // 从 mRequestList中找到消息,并从列表移除,从而保证请求消息和返回消息的一一对应关系
        rr = findAndRemoveRequestFromList(serial);

        if (rr == null) {
            Rlog.w(RILJ_LOG_TAG, "Unexpected solicited response! sn: "
                    + serial + " error: " + error);
            return null;
        }
        ----------------------------------------------------------------------
        if (error == 0 || p.dataAvail() > 0) {
            // either command succeeds or command fails but with data payload
            try {
                switch (rr.mRequest) {
                    case RIL_REQUEST_GET_SIM_STATUS:
                        ret = responseIccCardStatus(p);
                        break;
                    case RIL_REQUEST_DIAL:
                        ret = responseVoid(p);
                        break;
                    case RIL_REQUEST_GET_IMSI:
                        ret = responseString(p);
                        break;
                    ---------------------------------------------------------------
            } catch (Throwable tr) {
                // Exceptions here usually mean invalid RIL responses

                Rlog.w(RILJ_LOG_TAG, rr.serialString() + "< "
                        + requestToString(rr.mRequest)
                        + " exception, possible invalid RIL response", tr);

                if (rr.mResult != null) {
                    AsyncResult.forMessage(rr.mResult, null, tr);
                    rr.mResult.sendToTarget();
                }
                return rr;
            }
        }
        ---------------------------------------------------------------------------
        if (error == 0) {

            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();
            }
        }
        -----------------------------------------------------------------------------
    }

    // 向 RILC 发送请求消息
    private void send(RILRequest rr) {
        Message msg;

        if (mSocket == null) {
            rr.onError(RADIO_NOT_AVAILABLE, null);
            rr.release();
            return;
        }

        msg = mSender.obtainMessage(EVENT_SEND, rr);
        acquireWakeLock(rr, FOR_WAKELOCK);
        msg.sendToTarget();
    }

    @Override
    public void getIMEI(Message result) {
        RILRequest rr = RILRequest.obtain(RIL_REQUEST_GET_IMEI, result);

        if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));

        send(rr);
    }

    @Override
    public void getSignalStrength (Message result) {
        RILRequest rr
                = RILRequest.obtain(RIL_REQUEST_SIGNAL_STRENGTH, result);

        if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));

        send(rr);
    }


    // 打开移动数据链接
    @Override
    public void setupDataCall(int radioTechnology, int profile, String apn,
            String user, String password, int authType, String protocol,
            Message result) {
        RILRequest rr
                = RILRequest.obtain(RIL_REQUEST_SETUP_DATA_CALL, result);

        rr.mParcel.writeInt(7);

        rr.mParcel.writeString(Integer.toString(radioTechnology + 2));
        rr.mParcel.writeString(Integer.toString(profile));
        rr.mParcel.writeString(apn);
        rr.mParcel.writeString(user);
        rr.mParcel.writeString(password);
        rr.mParcel.writeString(Integer.toString(authType));
        rr.mParcel.writeString(protocol);

        if (RILJ_LOGD) riljLog(rr.serialString() + "> "
                + requestToString(rr.mRequest) + " " + radioTechnology + " "
                + profile + " " + apn + " " + user + " "
                + password + " " + authType + " " + protocol);

        mMetrics.writeRilSetupDataCall(mInstanceId, rr.mSerial,
                radioTechnology, profile, apn, authType, protocol);

        send(rr);
    }

}

五、RIL Receiver

接收步骤

  1. 分析接收到的Parcel,根据类型不同进行处理
  2. 根据数据中的Token(mSerail),反查mRequest,找到对应的请求信息
  3. 将是数据转换成结果数据
  4. 将结果放在RequestMessage中发回到请求的发起者

六、RIL Sender

发送步骤

  1. 生成RILRequest,此时将生成m_Serial(请求的Token)并将请求号,数据,及其Result Message 对象填入到RILRequest中
  2. 使用send将RILRequest打包到EVENT_SEND消息中发送到到RIL Sender Handler
  3. RilSender 接收到EVENT_SEND消息,将RILRequest通过套接口发送到RILD,同时将RILRequest保存在mRequest中以便应答消息的返回

?

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-02-26 11:42:07  更:2022-02-26 11:44:06 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 15:28:59-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码