http://blog.csdn.net/aaa111/article/details/52876403
电话管理是Android 系统支持的重要的业务之一,提供接听电话,收发短信、电话薄、网络事件监听、读取用户信息等功能。
从下到上可以分为四层:硬件驱动层、RIL daemon层、Telephony框架实现层、 PHONE应用层,下层为上层提供服务,每层之间采用不同的通讯方式交互。RIL daemon层实现为单独的一个开机启动的进程(rild命令),通过AT命令硬件驱动层交互,TelephonyJava框架实现层包括一个RIL抽象层,RIL抽象层中通过一个本地socket与RIL daemon层(rild)交互,PHONE应用层通过BINDER机制与Telephony框架交互。
一、framework telephony层:
android/frameworks/opt/telephony/src/java/com/android/internal/telephony/RIL
RIL层:radio interface layer 多媒体接口层, 主要是与modem进行串口通信,手机网络、通话、短信方面的
功能:接收unsolicited 和solicited 信息
主要由phone进程创建
现在主要了解callTracker这个通话方面的内容(ServiceStateTracker、DataConnectionTracker)
modem传来的来电通知
case RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED:
if (RILJ_LOGD) unsljLog(response);
mCallStateRegistrants
.notifyRegistrants(new AsyncResult(null, null, null));
RIL的父类,主要是定义各个观察者 RegistrantList
BaseCommands.java
mCallStateRegistrants
GsmCdmaCallTracker.java (Handler类,说明calltracker只是一个信息的集中转发中心而已)
public GsmCdmaCallTracker (GsmCdmaPhone phone) {
this.mPhone = phone;
mCi = phone.mCi;
mCi.registerForCallStateChanged(this, EVENT_CALL_STATE_CHANGE, null);
mCi.registerForOn(this, EVENT_RADIO_AVAILABLE, null);
@Override
public void handleMessage(Message msg) {
case EVENT_CALL_STATE_CHANGE:
pollCallsWhenSafe();
break;
CallTracker.java
protected void pollCallsWhenSafe() {
mNeedsPoll = true;
if (checkNoOperationsPending()) {
mLastRelevantPoll = obtainMessage(EVENT_POLL_CALLS_RESULT);
mCi.getCurrentCalls(mLastRelevantPoll);
}
}
由于一开始的RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED只是一个通知,并没有附加其他消息
所以这里会下发一个查询当前所有通话的状态表
RIL.java
解析并填充DriverCall
private Object
responseCallList(Parcel p) {
ArrayList<DriverCall> response;
DriverCall dc;
response.add(dc);
return response;
GsmCdmaCallTracker.java
@Override
public void handleMessage(Message msg) {
AsyncResult ar;
switch (msg.what) {
case EVENT_POLL_CALLS_RESULT:
Rlog.d(LOG_TAG, "Event EVENT_POLL_CALLS_RESULT Received");
if (msg == mLastRelevantPoll) {
if (DBG_POLL) log(
"handle EVENT_POLL_CALL_RESULT: set needsPoll=F");
mNeedsPoll = false;
mLastRelevantPoll = null;
handlePollCalls((AsyncResult)msg.obj);
}
break;
首先查看DriverCall类
DriverCall实际反映了Modem端真实的通话连接信息
+CLCC:List current calls 列出当前所有的通话
+CLIP:Calling line identified presented 来电显示
//+CLCC: 1,0,2,0,0,\"+18005551212\",145
// index,isMT,state,mode,isMpty(,number,TOA)?
//+CLIP: "02151082965",129,"",,"",0
GsmCdmaCallTracker.java
处理轮询得到的所有通话(进行当前modem端与上层端的通话同步--GsmCdmaConnection<-->DriverCall)
@Override
protected synchronized void handlePollCalls(AsyncResult ar) {
for (int i = 0, curDC = 0, dcSize = polledCalls.size()
; i < mConnections.length; i++) {
GsmCdmaConnection conn = mConnections[i];
DriverCall dc = null;
if (conn == null && dc != null) {
mConnections[i] = new GsmCdmaConnection(mPhone, dc, this, i);//(1)
if (newRinging != null) {
mPhone.notifyNewRingingConnection(newRinging);//(2)
}
updatePhoneState();//(3)
if (hasNonHangupStateChanged || newRinging != null || hasAnyCallDisconnected) {
mPhone.notifyPreciseCallStateChanged();//(4)
updateMetrics(mConnections);
}
(1) :
基本每一个DriverCall都对应一个通话链接GsmCdmaConnection
GsmCdmaConnection.java
//DriverCall ---> GsmCdmaCall
/** This is probably an MT call that we first saw in a CLCC response or a hand over. */
GsmCdmaCallTracker mOwner;
GsmCdmaCall mParent;
public GsmCdmaConnection (GsmCdmaPhone phone, DriverCall dc, GsmCdmaCallTracker ct, int index) {
mOwner = ct;
mParent = parentFromDCState(dc.state);
mParent.attach(this, dc);
private GsmCdmaCall
parentFromDCState (DriverCall.State state) {
switch (state) {
case ACTIVE:
case DIALING:
case ALERTING:
return mOwner.mForegroundCall;
//break;
case HOLDING:
return mOwner.mBackgroundCall;
//break;
case INCOMING:
case WAITING:
return mOwner.mRingingCall;
//break;
default:
throw new RuntimeException("illegal call state: " + state);
}
}
GsmCdmaCallTracker.java
//***** Constants
public static final int MAX_CONNECTIONS_GSM = 19; //7 allowed in GSM + 12 from IMS for SRVCC
private static final int MAX_CONNECTIONS_PER_CALL_GSM = 5; //only 5 connections allowed per call
private static final int MAX_CONNECTIONS_CDMA = 8;
private static final int MAX_CONNECTIONS_PER_CALL_CDMA = 1; //only 1 connection allowed per call
public GsmCdmaCall mRingingCall = new GsmCdmaCall(this);
// A call that is ringing or (call) waiting
public GsmCdmaCall mForegroundCall = new GsmCdmaCall(this);
public GsmCdmaCall mBackgroundCall = new GsmCdmaCall(this);
GsmCdmaCall.java
//mRingingCall / mForegroundCall / mBackgroundCall 每一种类型的call对应多路通话链接, 而且很明显DriverCall ---》GsmCdmaCall
//***** Called from GsmCdmaConnection
public void attach(Connection conn, DriverCall dc) {
mConnections.add(conn);
mState = stateFromDCState (dc.state);
}
//双模单待无线语音呼叫连续性 Single Radio Voice Call Continuity (SRVCC)
//Hand Over -- 切换,属于移动通信网络中的技术术语。
所谓切换,就是指当移动台在通话过程中从一个基站覆盖区移动到另一个基站覆盖区,或者由于外界干扰而造成通话质量下降时,必须改变原有的话音信道而转接到一条新的空闲话音信道上去,以继续保持通话的过程。切换是移动通信系统中一项非常重要的技术,切换失败会导致掉话,影响网络的运行质量。因此,切换成功率(包括切入和切出)是我们网络考核的一项重要指标,如何提高切换成功率,降低切换掉话率是我们网络优化工作的重点之一
(2):
GsmCdmaPhone.java
public void notifyNewRingingConnection(Connection c) {
super.notifyNewRingingConnectionP(c);
}
Phone.java
private final RegistrantList mNewRingingConnectionRegistrants
= new RegistrantList();
/**
* Notifies when a new ringing or waiting connection has appeared.<p>
*
* Messages received from this:
* Message.obj will be an AsyncResult
* AsyncResult.userObj = obj
* AsyncResult.result = a Connection. <p>
* Please check Connection.isRinging() to make sure the Connection
* has not dropped since this message was posted.
* If Connection.isRinging() is true, then
* Connection.getCall() == Phone.getRingingCall()
*/
public void registerForNewRingingConnection(
Handler h, int what, Object obj) {
checkCorrectThread(h);
mNewRingingConnectionRegistrants.addUnique(h, what, obj);
}
/**
* 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);
}
android/frameworks/opt/telephony/src/java/com/android/internal/telephony/CallManager.java:580: phone.registerForNewRingingConnection(handler, EVENT_NEW_RINGING_CONNECTION,
android/packages/services/Telephony/src/com/android/services/telephony/PstnIncomingCallNotifier.java:111: mPhone.registerForNewR