Android6.0來電流程
先放出6.0的MT時序圖大家有個直觀感受,下面程式碼一步步進行分析
第一部分:RIL–>GSMPhone Call狀態變化 -> 發出來電通知(frameworks\opt\telephony)
1. framwork/opt/telephony/…/RIL.java
作用:RIL-Java在本質上就是一個RIL代理,起到一個轉發的作用,是Android Java概念空間中的電話系統的起點。
RIL接收到RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED訊息
private void processUnsolicited (Parcel p) {
...
switch(response) {
...
case RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED:
if (RILJ_LOGD) unsljLog(response);
2、然後經由mCallStateRegistrants.notifyRegistrants發出通知
mCallStateRegistrants.notifyRegistrants(new AsyncResult(null, null, null));
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
BaseCommands.Java registerForCallStateChanged() mCallStateRegistrants.add(r);
@Override
public void registerForCallStateChanged(Handler h, int what, Object obj) {
Registrant r = new Registrant (h, what, obj);
//新增到觀察者列表
mCallStateRegistrants.add(r);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 1
- 2
- 3
- 4
- 5
- 6
- 1
- 2
- 3
- 4
- 5
- 6
重點1:這其實是觀察者模式的一種實現形式
1.RefistrantList 通知者 2.Registrant 觀察者,這是一個一對多的關係,在有事件更新時,凡是在名單上登記過的物件,都會收到通知。
RegistrantList通知者支援對通知者的增加(add/addUnique)刪除(remove),並且能夠發出通知(notifyRegitrants);而Registrant作為觀察者,響應通知者發出的notifyRegistrant通知。
整體上這個訊息註冊機制分為兩部分,訊息註冊和訊息通知。當呼叫regist方法時將Message存放進去,當其呼叫notify方法時將所有Message取出併發送到MessageQueue中等待處理。
3. framwork/opt/telephony/…GSMCallTracker.java
作用:GSMCallTracker在本質上是一個Handler。GSMCallTracker是Android的通話管理層。GSMCallTracker建立了ConnectionList來管理現行的通話連線,並向上層提供電話呼叫介面。
查詢察者被呼叫的地方, 兩處被響應處理處理,其中一處:GSMCallTracker handleMessage
...//registerForCallStateChanged呼叫
mCi.registerForCallStateChanged(this, EVENT_CALL_STATE_CHANGE, null);
...
@Override
public void
//響應處理
handleMessage (Message msg) {
...
case EVENT_CALL_STATE_CHANGE: //MT第一次
//呼叫父類CallTracker查詢Call List方法
pollCallsWhenSafe();
break;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
4、pollCallsWhenSafe()方法在CallTracker.java中實現
protected void pollCallsWhenSafe() {
mNeedsPoll = true;
if (checkNoOperationsPending()) {
mLastRelevantPoll = obtainMessage(EVENT_POLL_CALLS_RESULT);
5、 //RIL.java中的getCurrentCalls方法
mCi.getCurrentCalls(mLastRelevantPoll);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
回到RIL.java getCurrentCalls 將RIL_REQUEST_GET_CURRENT_CALLS 訊息封裝成RILRequest
型別併發送。
@Override
public void getCurrentCalls (Message result) {
RILRequest rr = RILRequest.obtain(RIL_REQUEST_GET_CURRENT_CALLS, result);
send(rr);
}
- 1
- 2
- 3
- 4
- 5
- 1
- 2
- 3
- 4
- 5
- 1
- 2
- 3
- 4
- 5
RIL.java 有三處接收處理RIL_REQUEST_GET_CURRENT_CALLS訊息,真正的邏輯處理在processSolicited方法
private RILRequest processSolicited (Parcel p) {
...
case RIL_REQUEST_GET_CURRENT_CALLS: ret = responseCallList(p); break;
...
if (rr.mResult != null) {
AsyncResult.forMessage(rr.mResult, ret, null);
rr.mResult.sendToTarget();//發出handler訊息通知
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
6、回到framworks/opt/telephony/…/telephony/gsm/GSMCallTracker.java
rr.mResult.sendToTarget()發出handler訊息通知後,會在GSMCallTracker中的handleMessage方法中響應。並且它的訊息型別是“EVENT_POLL_CALLS_RESULT”
@Override
public void handleMessage (Message msg) {
...
case EVENT_POLL_CALLS_RESULT:
ar = (AsyncResult)msg.obj;
if (msg == mLastRelevantPoll) {
mNeedsPoll = false;
mLastRelevantPoll = null;
7、 handlePollCalls((AsyncResult)msg.obj);
}
break;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
8、handlePollCalls方法根據RIL發出的Call List物件判斷Call的狀態,併發出不同的通知,
1) 新來電的通知是: phone.notifyNewRingingConnection;
另外兩個是
2) 通話斷開通知 onDisconnected;
3) Call狀態變化通知 phone.notifiyPreciseCallStateChanged.
(當狀態改變之後便會通過GsmPhone的notifyPreciseCallStateChanged()方法發起響應)
來電的時候發出的是phone.notifyNewRingConnection通知,進入到notifyNewRingConnection方法
handlePollCalls(){
...
if (newRinging != null) {
mPhone.notifyNewRingingConnection(newRinging);
}
- 1
- 2
- 3
- 4
- 5
- 1
- 2
- 3
- 4
- 5
- 1
- 2
- 3
- 4
- 5
9、framworks/opt/telephony/…/telephony/gsm/GSMPhone.java
public void notifyNewRingingConnection(Connection c) {
super.notifyNewRingingConnectionP(c);
}
- 1
- 2
- 3
- 1
- 2
- 3
- 1
- 2
- 3
呼叫父類 PhoneBase.java(為com.android.internal.telephony.phone介面實現。)
notifyNewRingingConnectionP()發出來電通知 mNewRingingConnectionRegistrants.notifyRegistrants(ar);
/**
* Notify registrants of a new ringing Connection.
* Subclasses of Phone probably want to replace this with a
* version scoped to their packages
*/
public void notifyNewRingingConnectionP(Connection cn) {
if (!mIsVoiceCapable)
return;
AsyncResult ar = new AsyncResult(null, cn, null);
mNewRingingConnectionRegistrants.notifyRegistrants(ar);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
重點2: RegistrantList.java \frameworks\base\core\java\android\os
notifyRegistrants方法實現
public /*synchronized*/ void notifyRegistrants(AsyncResult ar){
internalNotifyRegistrants(ar.result, ar.exception);
}
private synchronized void internalNotifyRegistrants (Object result, Throwable exception){
for (int i = 0, s = registrants.size(); i < s ; i++) {
Registrant r = (Registrant) registrants.get(i);
r.internalNotifyRegistrant(result, 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);
}
}
- 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
- 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
- 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
註冊為觀察者的方法為:
// Inherited documentation suffices.
@Override
public void registerForNewRingingConnection(
Handler h, int what, Object obj) {
checkCorrectThread(h);
mNewRingingConnectionRegistrants.addUnique(h, what, obj);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
通過log發現PstnIncomingCallNotifier.java呼叫registerForNewRingingConnection()
01-05 07:10:05.517962 1596 1596 D Telephony: PstnIncomingCallNotifier: handleNewRingingConnection
- 1
- 1
- 1
第二部分:PstnIncomingCallNotifier–>Call 接收Framework層到通知–>準備建立連線
10、packages/services/Telephony/…/PstnIncomingCallNotifier.java(packages\services\telephony)
作用:監聽來之相關電話物件的來電事件和通知Telecom在每次發生的時候,這一例項的存在為了每個電話的通話服務
registerForNotifications方法呼叫registerForNewRingingConnection
private void registerForNotifications() {
Phone newPhone = mPhoneProxy.getActivePhone();
if (newPhone != mPhoneBase) {
unregisterForNotifications();
if (newPhone != null) {
Log.i(this, "Registering: %s", newPhone);
mPhoneBase = newPhone;
//呼叫registerForNewRingingConnection方法
mPhoneBase.registerForNewRingingConnection(
mHandler, EVENT_NEW_RINGING_CONNECTION, null);
mPhoneBase.registerForCallWaiting(
mHandler, EVENT_CDMA_CALL_WAITING, null);
mPhoneBase.registerForUnknownConnection(mHandler, EVENT_UNKNOWN_CONNECTION,
null);
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
11、handle 處理EVENT_NEW_RINGING_CONNECTION訊息
private final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
...
case EVENT_NEW_RINGING_CONNECTION:
handleNewRingingConnection((AsyncResult) msg.obj);
break;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 1
- 2
- 3
- 4
- 5
- 6
- 7
12、從之前的log看: 由handleNewRingingConnection方法,處理新的來電連線。
private void handleNewRingingConnection(AsyncResult asyncResult) {
Log.d(this, "handleNewRingingConnection");
Connection connection = (Connection) asyncResult.result;
if (connection != null) {
Call call = connection.getCall();
//在傳送intent到Telecom之前最後一次驗證ringing 狀態
if (call != null && call.getState().isRinging()) {
sendIncomingCallIntent(connection);
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
13、sendIncomingCallIntent方法
傳送incoming
call intent到telecom,傳送的Connection 型別,裡面包括isIncoming getState isRinging等
/**
* Sends the incoming call intent to telecom.
*/
private void sendIncomingCallIntent(Connection connection) {
Bundle extras = null;
if (connection.getNumberPresentation() == TelecomManager.PRESENTATION_ALLOWED &&
!TextUtils.isEmpty(connection.getAddress())) {
extras = new Bundle();
Uri uri = Uri.fromParts(PhoneAccount.SCHEME_TEL, connection.getAddress(), null);
extras.putParcelable(TelephonyManager.EXTRA_INCOMING_NUMBER, uri);
}
TelecomManager.from(mPhoneProxy.getContext()).addNewIncomingCall(
TelecomAccountRegistry.makePstnPhoneAccountHandle(mPhoneProxy), extras);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
14、addNewIncomingCall()定義在: framworks/base/telecomm/java/android/telecom/TelecomManager.java
作用:TelecomManager的功能則主要是對TelecomService提供的遠端介面的封裝,然後提供給應用使用。
來電時觸發 addNewIncomingCall方法
@SystemApi
public void addNewIncomingCall(PhoneAccountHandle phoneAccount, Bundle extras) {
try {
if (isServiceConnected()) {
getTelecomService().addNewIncomingCall(
phoneAccount, extras == null ? new Bundle() : extras);
}
} catch (RemoteException e) {
Log.e(TAG, "RemoteException adding a new incoming call: " + phoneAccount, e);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 1
-
相關推薦
Android6.0來電流程
先放出6.0的MT時序圖大家有個直觀感受,下面程式碼一步步進行分析 第一部分:RIL–>GSMPhone Call狀態變化 -> 發出來電通知(frameworks\opt\telephony) 1. framwork/opt/telephony/…/RIL.ja
Android6.0來電號碼電話薄名稱匹配
本文將介紹系統接收到來電之後,如何在電話薄中進行匹配聯絡人的流程。分析將從另外一篇文章(基於Android6.0的RIL框架層模組分析)中提到的與本文內容相關的程式碼開始。 //packages/service/***/Call.java public void handleCr
Android6.0 Telephony流程分析——PhoneApp啟動主要類關係分析
本文程式碼以MTK平臺Android 6.0為分析物件,與Google原生AOSP有些許差異,請讀者知悉。 PhoneApp(包名com.android.phone)主要程式碼位於 packages/
高通 NXP NFC(PN547PN548) 移植流程 android6.0
一、驅動部分 首先向NXP 的 fae要android 6.0 bring up的程式碼,如:NFC_NCIHALx_AR0F.4.3.0_M_NoSE 結構目錄如下: 1. 新增驅動檔案 高通平臺需使用pn544節點,所以將驅動中的裝置節點名字修改為pn544即可; 2. 修改平臺配置 在init.qco
android Telephony學習 --- 第七篇 android7.0 來電(MT)流程
我們先看下7.0來電大體流程: ##Framework modem接收到來電通知訊息後,以AT指令的方式上報RIL層,RIL層通過sokcet將訊息傳送給RILJ, 上報事件ID: RIL_UNSOL
Android6.0 原始碼修改之遮蔽系統簡訊功能和來電功能
一、遮蔽系統簡訊功能 1、遮蔽所有簡訊 android 4.2 簡訊傳送流程分析可參考這篇 戳這 原始碼位置 vendor\mediatek\proprietary\packages\apps\Mms\src\com\android\mms\trans
[RK3288][Android6.0] RTC驅動的上層呼叫流程
Platform: Rockchip OS: Android 6.0 Kernel: 3.10.92 說明: RTC驅動在註冊的時候提供了兩個字元裝置給使用者空間供操作。 1. /dev/alarm, android特有裝置,為了提高平臺無關性而加
[RK3288][Android6.0] 系統除錯串列埠驅動流程小結
Platform: ROCKCHIP OS: Android 6.0 Kernel: 3.10.92 rk3288提供了fiq debugger功能, 因此rk將debug uart和普通uart區分開來, debug uart的初始化整合到了fiq debugger程式碼中完成,不過uart的初始化 方法還
android6.0系統Healthd分析及低電量自動關機流程
系統平臺:android6.0概述Healthd是android4.4之後提出來的一種中介模型,該模型向下監聽來自底層的電池事件,向上傳遞電池資料資訊給Framework層的BatteryService用以計算電池電量相關狀態資訊,BatteryServcie通過傳遞來的資料來計算電池電量顯示
Android6.0亮屏流程之Keyguard Window繪製
亮滅屏問題一直是Android模組最常見的問題之一。 由於問題出現問題的地方涉及到公司程式碼,我這裡僅僅只作原生程式碼模組的分析 其實在看過另外一篇關於android亮屏
Android6.0 Reset恢復出廠設定流程分析
點選Settings應用中的恢復出廠設定按鈕後流程分析:先使用grep命令搜尋"恢復出廠設定"字串,找到相應的佈局檔案: packages/apps/Settings/res/xml/privacy_settings.xml <PreferenceScree
[Android6.0][RK3399] Type-C 驅動流程分析
基本概念 USB 控制器 OHCI(Open Host Controller Interface) 是支援USB1.1的標準,但它不僅僅是針對USB,還支援其他的一些介面,比如它還支援Apple的火線(Firewire,IEEE 1394
[Android6.0][RK3399] 雙屏異顯程式碼實現流程分析(一)
Platform: RK3399 OS: Android 6.0 Version: v2016.08 本文分為兩部分。 《[RK3399] 雙屏異顯程式碼實現流程分析(一)》為分析 RK video 部分標準的程式碼(base on 2017.
[RK3288][Android6.0] 系統按鍵驅動流程分析
Rockchip的按鍵驅動位於 kernel/drivers/input/keyboard/rk_keys.c 預設支援的keys在dts中定義: 其中power key作為普通gpio,具有喚醒功能。而其他按鍵比如,volume up/down 可以通
[RK3288][Android6.0] DDR Frequency控制流程小結
freq-table = < /*status freq(KHz)*/ SYS_STATUS_NORMAL 400000 SYS_STATUS_SUSPEND 200000 SYS_STATUS_VIDEO_108
android6.0 開機啟動流程
這篇部落格講下android開機啟動流程,init那部分之前在分析init程序的時候,講過了,我們就不看了。當然我們結合log看。 整個開機的時間,我們一SurfaceFlinger來算,先從如下log開始,下面這句log,是在SurfaceFlinger的建構函式的第一句
[RK3288][Android6.0] Audio的音量設定流程小結
Platform: Rockchip OS: Android 6.0 Kernel: 3.10.92 說明一: AudioManager提供了兩個調節音量介面 adjustSuggestedSt
[RK3288][Android6.0] 網路服務Netd初始化流程小結
Platform: Rockchip OS: Android 6.0 Kernel: 3.10.92 Netd: Network Daemon. 負責網路配置,操作,管理,查詢等功能. 封裝底層各種型別網路,如PPP,SOFTAP等,給framework提供統一介面. 說
Android6.0系統啟動流程分析三:SystemServer程序
在上一篇部落格 Android6.0系統啟動流程分析二:zygote程序一文中,我們隊Zygote程序的有了一定的瞭解。我們知道Zygote程序會啟動SystemServer程序,但我們並沒有在上篇文章中分析SystemServer程序的相關內容。這篇部落格,我
Android6.0 Telephony Frameworks之資料業務建立流程
資料業務(資料網路,即SIM卡上網)的建立需滿足兩個條件:1.選擇並激活合適的APN;2.PS域已處於Attached狀態。預設狀態下,手機開機後就會發起PS附著的信令給網路。而所有資料網路的請求(開啟關閉資料開關、切換資料卡、修改APN等)都必須經過DcTacker.ja