日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android Telephony分析(三) ---- RILJ详解

發布時間:2025/3/15 Android 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android Telephony分析(三) ---- RILJ详解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言

本文主要講解RILJ工作原理,以便更好地分析代碼,分析業務的流程。?
這里說的RILJ指的是RIL.java (frameworks\opt\telephony\src\java\com\Android\internal\telephony) ,?
RILC指的是Ril.cpp (hardware\ril\libril)

1. RILJ的創建

RILJ的繼承關系如下:?

可以看到RILJ繼承自BaseCommands并且實現了CommandsInterface接口,RILJ中有兩個子線程RILSender和RILReceiver。?
再看看RILJ的構造函數:

public RIL(Context context, int preferredNetworkType, int cdmaSubscription) { super(context); //發送子線程,mInstanceId就是PhoneIDmSenderThread = new HandlerThread("RILSender" + mInstanceId);mSenderThread.start(); //接收子線程 mReceiver = new RILReceiver();mReceiverThread = new Thread(mReceiver, "RILReceiver" + mInstanceId);mReceiverThread.start(); }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

在RILJ初始化的時候,啟動了RILSender線程用于發送數據,啟動了RILReceiver線程用于接收數據。?
在《Android Telephony分析(一) — Phone詳解 》的第二小節中曾經說到,在創建Phone實例之前會先創建RILJ,一個Phone實例對應一個RILJ實例。?
在CallTracker.java、Phone.java、ServiceStateTracker.java我們常常看到的

public CommandsInterface mCi;
  • 1
  • 1

mCi對象都是RILJ實例。


http://blog.csdn.net/linyongan?


2. RILJ的工作原理

RILJ、RILC、Modem的工作流程:

RILJRILJRILCRILCModemModem發送Request發送RequestModem處理solicited/unSolicited Responsesolicited/unSolicited Response

RILJ里有RILSender線程用于向RILC發送數據和RILReceiver用于接收來自RILC的數據,但是這些數據的發送和接收是一個異步的過程。?
結合同步,才能更好地理解異步:

同步:發送方發出數據后,等接收方發回響應以后才發下一個數據包。?
異步:發送方發出數據后,不等接收方發回響應,接著發送下個數據包。

理解這個概念之后,我們再去分析代碼,我們就以打電話為例吧。

2.1 RILSender發送Request

前面的撥號流程省略,我們直接從GsmCdmaCallTracker.java的dial()方法開始分析:

public synchronized Connection dial(String dialString, int clirMode, UUSInfo uusInfo,Bundle intentExtras)throws CallStateException {...//先通過obtainCompleteMessage方法得到一個MessagemCi.dial(mPendingMO.getAddress(), clirMode, uusInfo, obtainCompleteMessage());...}private MessageobtainCompleteMessage() {//該消息類型是EVENT_OPERATION_COMPLETEreturn obtainCompleteMessage(EVENT_OPERATION_COMPLETE);}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

在調用RILJ的方法發起撥號請求之前,先創建一個Message對象,這個Message對象主要用于,當RILJ發起撥號請求,modem返回消息之后,RILJ再通過Message.sendToTarget,這樣回調就可以通知GsmCdmaCallTracker,后文2.2.1小節會詳細講。?
接著在RILJ中:

//有一個RILRequest列表SparseArray<RILRequest> mRequestList = new SparseArray<RILRequest>();@Overridepublic voiddial(String address, int clirMode, UUSInfo uusInfo, Message result) {//得到一個RILRequest對象,需要留意result這個Message被存儲在哪里RILRequest rr = RILRequest.obtain(RIL_REQUEST_DIAL, result);//將參數放到RILRequest對象中rr.mParcel.writeString(address);rr.mParcel.writeInt(clirMode);if (uusInfo == null) {rr.mParcel.writeInt(0); // UUS information is absent} else {rr.mParcel.writeInt(1); // UUS information is presentrr.mParcel.writeInt(uusInfo.getType());rr.mParcel.writeInt(uusInfo.getDcs());rr.mParcel.writeByteArray(uusInfo.getUserData());}//輸出標志性log,"> "代表RILJ向RILC發送請求。if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));//Android N新增,作用是打印log?mEventLog.writeRilDial(rr.mSerial, clirMode, uusInfo);//發送請求send(rr);}static RILRequest obtain(int request, Message result) {RILRequest rr = null;......//【重點】外面傳遞進來的Message對象最終賦值給了rr.mResultrr.mResult = result;......return rr;}send(RILRequest rr) {Message msg;if (mSocket == null) {rr.onError(RADIO_NOT_AVAILABLE, null);rr.release();return;}msg = mSender.obtainMessage(EVENT_SEND, rr);acquireWakeLock();msg.sendToTarget();}@Override public voidhandleMessage(Message msg) {switch (msg.what) {case EVENT_SEND:......synchronized (mRequestList) {//把RILRequest對象也會被添加到mRequestList列表中//等到RILC回應RILJ時,再把RILRequest對象取出來mRequestList.append(rr.mSerial, rr);}byte[] data;//將數據轉換成bytedata = rr.mParcel.marshall();......//向socket寫入數據s.getOutputStream().write(dataLength);s.getOutputStream().write(data);}}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68

就這樣,整個主動向RILC發出請求的流程就將完了。

2.2 RILReceiver接收Response

在RILReceiver線程中

class RILReceiver implements Runnable {@Overridepublic voidrun() {...... processResponse(p);......}}private voidprocessResponse (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發出的Request的回應消息的處理RILRequest rr = processSolicited (p, type);if (rr != null) {if (type == RESPONSE_SOLICITED) {decrementWakeLock(rr);}rr.release();}}}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

RILC上報給RILJ的消息可以分成兩類:?
1. Solicited Response—>對之前RILJ發出的Request進行回應的消息。(一個Request對應一個Response)?
2. UnSolicited Response—>modem主動上報的消息。(單方向,由RILC發給RILJ)

2.2.1 處理Solicited Response

繼續上面撥號的例子,在RILJ發起撥號請求后,modem處理完之后,返回消息給RILC,最后通知到RILJ。

private RILRequestprocessSolicited (Parcel p, int type) {RILRequest rr; //把RILRequest對象從mRequestList列表中取出來rr = findAndRemoveRequestFromList(serial); //省略對數據的處理.....//輸出標志性log,"< "代表RILC向RILJ反饋信息。if (RILJ_LOGD) riljLog(rr.serialString() + "< " + requestToString(rr.mRequest)+ " " + retToString(rr.mRequest, ret));if (rr.mResult != null) { AsyncResult.forMessage(rr.mResult, ret, null); //是否還記得上面2.1小節中說到rr.mResult存儲的是什么對象嗎?//這就是在調用RILJ的dial方法前創建的Message對象!//Message.sendToTarget,這樣通過回調,流程就回到調用RILJ的dial方法的地方了。rr.mResult.sendToTarget(); } return rr; }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

2.2.2 處理Solicited Response

這里以撥打電話后,modem上報call的狀態變化消息RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED為例

private voidprocessUnsolicited (Parcel p, int type) {int response; Object ret; //讀取當前上報消息的號碼 response = p.readInt(); //根據號碼找到相應的邏輯處理switch(response) { case RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED: ret = responseVoid(p); break;.......} //根據號碼找到相應的邏輯處理switch(response) { case RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED:if (RILJ_LOGD) unsljLog(response);//【重點】通過RegistrantList機制,繼續上報消息mCallStateRegistrants.notifyRegistrants(new AsyncResult(null, null, null));break;}} }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

關于RegistrantList機制,請看上一篇文章《Android Telephony分析(二) —- RegistrantList詳解》?
接著會通知到注冊監聽Call狀態變化的人:

public GsmCdmaCallTracker (GsmCdmaPhone phone) {this.mPhone = phone;mCi = phone.mCi;//注冊監聽Call狀態變化,GsmCdmaCallTracker本質上是Handler//所以第一個參數傳遞thismCi.registerForCallStateChanged(this, EVENT_CALL_STATE_CHANGE, null);}public void registerForCallStateChanged(Handler h, int what, Object obj) {Registrant r = new Registrant (h, what, obj);//加入mCallStateRegistrants這個RegistrantList中mCallStateRegistrants.add(r);}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

最終會在GsmCdmaCallTracker的handleMessage方法中對EVENT_CALL_STATE_CHANGE進行處理。?
modem主動上報消息的流程也講解完了。


3 .學以致用

學習完本篇博客的知識,怎么去分析調用RILJ的方法主動發起Request的流程和modem主動上報消息的流程呢??
這里還是以第二小節撥號的代碼為例,其他業務流程都可以舉一反三。?
1.主動發起Request這類代碼流程,核心是誰創建Message,之后還是誰對該Message進行處理。

GsmCdmaCallTrackerGsmCdmaCallTrackerRILJRILJModemModem創建Message(EVENT_OPERATION_COMPLETE)dialdialModem處理processSolicited()rr.mResult.sendToTargethandleMessage()

2.modem主動上報消息這類代碼流程,核心是誰注冊監聽了這個消息,那么還是誰對該消息進行處理。

GsmCdmaCallTrackerGsmCdmaCallTrackerRILJRILJModemModemregisterForCallStateChanged()Call狀態變化processUnsolicited()mCallStateRegistrants.notifyRegistrants()handleMessage()

最后可以通過log中的“>”和“<”判斷消息的方向。

D/RILJ ( 2795): [5655]> DIAL D/RILJ ( 2795): [5655]< DIAL
  • 1
  • 2
  • 1
  • 2

“>”:是RILJ發請求給modem。?

“<”:是modem上報消息給RILJ。


原文地址:http://blog.csdn.net/linyongan/article/details/52066306

總結

以上是生活随笔為你收集整理的Android Telephony分析(三) ---- RILJ详解的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。