一、組件職責與定位
組件 | 所在進程 | 核心職責 | 關鍵特性 |
---|---|---|---|
CallsManager | Telecom系統進程 | 通話狀態機核心:管理所有Call對象的生命周期(創建、狀態更新、銷毀)。監聽Call狀態變化并通知所有觀察者(如InCallController )。 | 通過mListeners 集合維護觀察者列表(如InCallController 、Ringer 等)。 |
InCallController | Telecom系統進程 | 跨進程通信橋梁:監聽CallsManager 的Call事件,綁定InCallService 服務(如InCallServiceImpl )。將Call狀態封裝為ParcelableCall 對象傳遞給UI進程。 | 通過bindServiceAsUser() 綁定InCallService ,觸發UI進程啟動。 |
InCallPresenter | Dialer應用進程 | MVP模式中的Presenter:接收InCallService 的Call狀態更新,控制InCallActivity 的創建/銷毀。管理子Presenter(如CallCardPresenter )和界面邏輯。 | 通過InCallAdapter 將用戶操作(接聽/掛斷)轉發給CallsManager 。 |
InCallActivity | Dialer應用進程 | 界面容器:承載通話UI的Activity,動態加載Fragment(如CallCardFragment )。僅響應界面事件,業務邏輯委托給InCallPresenter 。 | 布局僅為FrameLayout ,具體UI由Fragment實現。 |
二、核心交互流程(以去電MO為例)
-
Call創建與狀態同步
CallsManager
創建Call對象,觸發onCallAdded
回調。InCallController
監聽到事件,綁定InCallService
服務(跨進程)。- 綁定成功后,
InCallServiceImpl
通知InCallPresenter
啟動InCallActivity
。
-
界面啟動與用戶操作
InCallPresenter
調用startActivity()
啟動InCallActivity
,加載通話UI。- 用戶點擊“撥號”后,
InCallPresenter
通過InCallAdapter
調用CallsManager.placeOutgoingCall()
。
-
底層通話建立
CallsManager
通過ConnectionService
與Modem交互,Call狀態變為DIALING
→ACTIVE
。- 狀態變化經
InCallController
同步至UI進程,觸發InCallPresenter
更新界面(如顯示通話計時)。
三、與Call對象的交互關系
-
Call的生命周期管理
- 創建:
CallsManager
在去電/來電時創建Call對象,分配唯一ID。 - 狀態流轉:Call狀態(
DIALING
、RINGING
、ACTIVE
等)由CallsManager
驅動,通過setCallState()
更新。 - 銷毀:通話結束時,
CallsManager
移除Call并觸發onCallRemoved
。
- 創建:
-
Call數據的跨進程傳遞
InCallController
將Call轉換為ParcelableCall
(可序列化對象),通過Binder傳遞至UI進程。InCallPresenter
解析ParcelableCall
,更新界面元素(如聯系人姓名、通話時長)。
-
用戶操作與Call狀態聯動
- 接聽/掛斷等操作通過
InCallAdapter
回調至CallsManager
,后者調用Call.answer()
或Call.disconnect()
。 - 狀態變化反向同步至UI,形成閉環(例如掛斷后界面關閉)。
- 接聽/掛斷等操作通過
四、設計特點與架構價值
-
分層解耦
- 上層(UI層):
InCallActivity
僅負責渲染,InCallPresenter
處理邏輯,符合MVP模式。 - 下層(服務層):
CallsManager
專注狀態機,InCallController
處理跨進程通信。
- 上層(UI層):
-
跨進程高效同步
- 通過Binder機制實現Telecom進程與Dialer進程的實時狀態同步(
ParcelableCall
序列化)。
- 通過Binder機制實現Telecom進程與Dialer進程的實時狀態同步(
-
可擴展性
CallsManager
的監聽器模式支持動態添加組件(如Ringer
振鈴模塊、CallAudioManager
音頻控制)。InCallPresenter
可管理多類子Presenter,適應不同通話場景(如視頻通話、會議)。
五、鏈路
這一架構通過狀態驅動(CallsManager
)與界面邏輯分離(MVP模式)實現高內聚低耦合:
- 核心鏈路:
CallsManager → InCallController → InCallPresenter → InCallActivity
構成狀態傳遞閉環; - 交互本質:Call對象作為載體,在進程間傳遞狀態,驅動UI與底層服務協同。
其設計充分體現了Android系統服務的模塊化思想,為通話功能提供了穩定可擴展的基礎。
六、Call 狀態
1. DIALING(撥號中)
- 定義:用戶發起呼叫后,系統開始連接對方但尚未接通的階段。
- 觸發時機:
- 用戶撥號后立即進入此狀態,無論是否開始響鈴。
- 若需選擇通話賬戶(如VoIP或SIM卡),會先進入
SELECT_PHONE_ACCOUNT
狀態,確認后轉為DIALING
。
- 行為特征:
- 主叫方聽回鈴音或等待提示音,被叫方設備未響鈴。
- 若撥號失敗(如無信號),會轉為
DISCONNECTED
(連接斷開)。
2. RINGING(響鈴中)
- 定義:被叫方收到來電請求,設備開始響鈴或震動的狀態。
- 觸發時機:
- 主叫方撥號后,被叫方網絡收到呼叫請求時觸發。
- 若被叫方正在通話中,此狀態可能伴隨
CALL_WAITING
(呼叫等待)提示。
- 行為特征:
- 被叫方設備響鈴,顯示來電界面。
- 主叫方仍處于
DIALING
狀態,直至被叫方接聽。
3. ACTIVE(通話中)
- 定義:雙方已建立連接,可實時雙向通話。
- 觸發時機:
- 被叫方接聽來電后,主被叫雙方均進入此狀態。
- 從
HOLDING
(通話保持)狀態恢復時也會切換至此。
- 行為特征:
- 通話計時器啟動,界面顯示通話時長。
- 支持操作如靜音(
MUTE
)、保持(HOLD
)、多方通話等。
4. HOLDING(保持中)
- 通話被主動暫停(如接聽新來電),雙方暫時中斷語音連接。
- 界面顯示“已保持”,恢復后回到
ACTIVE
。
5. DISCONNECTING(斷開中)
- 用戶掛斷電話后,系統釋放資源的中間狀態,隨后轉為
DISCONNECTED
。
6. DISCONNECTED(已斷開)
- 通話完全結束,資源已釋放。界面顯示掛斷提示(如通話時長總結)。
7. CALL_WAITING(呼叫等待)
- 用戶通話中時第三方來電,當前通話保持,新來電進入
RINGING
狀態。
狀態轉換關系
通話狀態的典型生命周期流程如下:
- 特殊場景:
- 通話保持時新來電:
ACTIVE → HOLDING
(原通話) +RINGING
(新來電)。 - 撥號失敗:
DIALING → DISCONNECTED
。
- 通話保持時新來電:
各個層的差異
DriverCall.State | Call.State(opt/telephony) | Connection.State(base/telecomm) | CallState(services/Telecomm) | Call.State(base/telecomm) | Call.State(Dialler) |
---|---|---|---|---|---|
ACTIVE | ACTIVE | STATE_ACTIVE | ACTIVE | STATE_ACTIVE | ACTIVE |
HOLDING | HOLDING | STATE_HOLDING | ON_HOLD | STATE_HOLDING | ONHOLD |
DIALING | DIALING | STATE_DIALING | DIALING | STATE_DIALING | DIALING |
ALERTING | ALERTING | RINGALERTING | |||
INCOMING | INCOMING | STATE_RINGING | RINGING | STATE_RINGING | INCOMING |
WAITING | WAITING | CALL_WAITING | |||
IDLE | IDLE | ||||
DISCONNECTED | STATE_DISCONNECTED | DISCONNECTED | STATE_DISCONNECTED | DISCONNECTED | |
DISCONNECTING | DISCONNECTING | STATE_DISCONNECTING | DISCONNECTING | ||
STATE_INITIALIZING | CONNECTING | STATE_CONNECTING | CONNECTING | ||
STATE_NEW | NEW | STATE_NEW | |||
STATE_PULLING_CALL | STATE_PULLING_CALL | ||||
SELECT_PHONE_ACCOUNT | STATE_SELECT_PHONE_ACCOUNT | SELECT_PHONE_ACCOUNT | |||
ABORTED | STATE_DISCONNECTED | DISCONNECTED | |||
STATE_PRE_DIAL_WAIT | |||||
INVALID | |||||
CONFERENCED | |||||
BLOCKED | |||||
WAIT_ACCOUNT_RESPONSE |
七、MT 與 MO
在Android通話系統中,MO(Mobile Originated,移動始發)和MT(Mobile Terminated,移動終止) 分別指代用戶主動撥打電話(主叫)和接聽來電(被叫)的流程。
1. MO(去電流程)
定義:用戶主動發起呼叫的過程,即“撥打電話”。
核心步驟:
- 撥號觸發:用戶在Dialer應用的撥號界面(
DialpadFragment
)點擊撥號按鈕,通過Intent.ACTION_CALL
發起請求。 - 權限檢查:
- 系統檢查
CALL_PHONE
權限及默認撥號器身份(TelecomUtil.hasCallPhonePermission()
)。 - 緊急呼叫(如
ACTION_CALL_EMERGENCY
)繞過權限限制。
- 系統檢查
- Telecom服務處理:
TelecomServiceImpl.placeCall()
驗證號碼合法性,并通過CallsManager
創建通話對象(Call
)。
- UI啟動與狀態更新:
- 系統啟動
InCallActivity
,根據通話狀態(如DIALING
)顯示撥號界面。 - 底層Modem返回
DIALING
狀態后,界面更新為撥號中。
- 系統啟動
- 呼叫建立:
- 被叫方接聽后,狀態轉為
ACTIVE
,通話計時開始。
- 被叫方接聽后,狀態轉為
流程圖簡化:
2. MT(來電流程)
定義:用戶接收來電并接聽的過程,即“接聽電話”。
核心步驟:
- 來電通知:
- Modem檢測到來電,通過RIL層上報
RINGING
狀態至CallsManager
。
- Modem檢測到來電,通過RIL層上報
- 鈴聲與震動:
CallNotifier
調用Ringer
播放鈴聲(非DIALING
狀態獨有)。
- UI啟動:
- 系統啟動
InCallActivity
,顯示來電界面(如聯系人信息、接聽/掛斷按鈕)。
- 系統啟動
- 用戶響應:
- 接聽:狀態轉為
ACTIVE
,建立雙向通話。 - 拒接:狀態轉為
DISCONNECTED
。
- 接聽:狀態轉為
流程圖簡化:
3. MO與MT的核心區別
維度 | MO(主叫) | MT(被叫) |
---|---|---|
觸發起點 | 用戶主動撥號 | 網絡側下發來電請求 |
關鍵狀態 | DIALING (撥號中) | RINGING (響鈴中) |
系統組件 | DialpadFragment 觸發Intent | RIL /CallsManager 檢測來電狀態 |
特殊處理 | 緊急呼叫權限繞過 | 鈴聲播放(Ringer ) |
VoLTE角色 | 主叫UE構造SIP INVITE | 被叫S-CSCF觸發業務邏輯(如彩鈴) |
注意點
- MO:用戶撥號 → 權限檢查 → Telecom處理 → 界面顯示
DIALING
→ 通話建立(ACTIVE
)。 - MT:網絡下發來電 → 播放鈴聲 → 界面顯示
RINGING
→ 用戶接聽(ACTIVE
)或拒接(DISCONNECTED
)。
本質差異在于觸發源(用戶主動 vs. 網絡被動)和核心狀態(DIALING
vs.RINGING
)。理解兩者區別對開發通話功能、優化用戶體驗及設計測試用例至關重要。