1.TwelveKeyDialer.java,onKeyDown()->dialButtonPressed()
2.OutgoingCallBroadcaster.java,onCreate()
sendOrderedBroadcast(broadcastIntent, PERMISSION,
new OutgoingCallReceiver(), null, Activity.RESULT_OK, number, null);
3.OutgoingCallBroadcaster.java,OutgoingCallReceiver()
onReceive->context.startActivity(newIntent);
4.InCallScreen.java,onCreate(第一次)/onNewIntent(非第一次)
5.InCallScreen.java,placeCall
6.PhoneUtils.java,placeCall
7.CdmaPhone.java,dial
8.RIL.java,dial
RILRequest rr = RILRequest.obtain(RIL_REQUEST_DIAL, result);
...
send(rr);
接听电话的流程:
1.创建CDMAPhone时,mCT = new CdmaCallTracker(this);
2.创建CDMACallTracker时,cm.registerForCallStateChanged(this, EVENT_CALL_STATE_CHANGE, null);-->
BaseCommands.mCallStateRegistrants.add(r);
3.RIL中的RILReceiver线程首先读取从rild中传来的数据:RIL.processResponse->RIL.processSolicited
4.对应于incoming call,RIL.java收到RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED消息,触发mCallStateRegistrants中的所有记录。
5.CdmaCallTracker处理EVENT_CALL_STATE_CHANGE,调用pollCallsWhenSafe
6.函数pollCallsWhenSafe处理:
lastRelevantPoll = obtainMessage(EVENT_POLL_CALLS_RESULT);
cm.getCurrentCalls(lastRelevantPoll);
7.RIL.getCurrentCalls
RILRequest rr = RILRequest.obtain(RIL_REQUEST_GET_CURRENT_CALLS, result);
...
send(rr);
8.接着RIL调用processSolicited处理RIL_REQUEST_GET_CURRENT_CALLS的返回结果。
9.CdmaCallTracker的handleMessage被触发,处理时间EVENT_POLL_CALLS_RESULT,调用函数handlePollCalls
10.CdmaCallTracker.handlePollCalls调用phone.notifyNewRingingConnection(newRinging);
11.PhoneApp中创建CallNotifier
12.mPhone.registerForNewRingingConnection(this, PHONE_NEW_RINGING_CONNECTION, null);
13.CallNotifier.java,onNewRingingConnection()->startIncomingCallQuery()->startGetCallerInfo()
14.CallNofifier.java,onPhoneStateChanged()
15.InCallScreen.java,onPhoneStateChanged()
16.CallNotifier.java,onQueryComplete()->onCustomRingQueryComplete()(mRinger.ring()响铃,PhoneUtils.showIncomingCallUi()更新UI)
17.如果接通电话,则调用InCallScreen.java,handleOnscreenButtonClick()->internalAnswerCall()->PhoneUtils.answerCall(mPhone);(停止响铃,然后再接听电话)
18.CallNotifier.java,operationComplete()
18.状态改变InCallScreen.java,onPhoneStateChanged()更新界面,完成接听电话功能。
挂断电话的流程:
1.来电流程同上1-16。
2.拖动挂断界面InCallTouchUi.java,onTrigger()
2.InCallScreen.java,internalHangupRingingCall()->PhoneUtils.hangupRingingCall()->PhoneUtils.hangup()->
CdmaCall.hangup()
3.CdmaCallTracker.java,hangup()(先只看第一种情况)->cm.hangupWaitingOrBackground
4.RIL.java,hangupWaitingOrBackground()
注1:dialButtonPressed()函数,会启动一个intent.该intent的ACTION是ACTION_CALL_PRIVILEGED。我们在Intent.java中可以看到ACTION_CALL_PRIVILEGED实际上就是CALL_PRIVILEGED。在phone包下,查看AndroidManifest.xml可以看到<activity-alias
/>标签。这个标签的意思是说,这个Activity是另一个Activity的别名,真实的Activity在标签中用“android:targetActivity = OutgoingCallBroadcast”标出,所以 “ACTION_CALL_PRIVILEGED”启动的PrivilegedOutgoingCallBroadcast 所对应的真实“身份”是“OutgoingCallBroadcast”。
注2:InCallScreen.java
在首次oncreate后,就算通话结束也只会调用其onstop方法,此类一直不会被finish()掉。当onstop后,若重新打电话,则会调用onnewintent()方法,不会再经过oncreate。onCreate(第一次)增加FLAG参数:FLAG_DISMISS_KEYGUARD(这个参数的作用主要在于解除锁屏,比如锁屏时来电,这时候就需要先解除锁屏再显示画面,这样用户就能在锁屏时接收到来电了~)
InCallScreen布局及各个功能
(1)包含CallCard类:CallCard负责通话主要界面(callcard里面又包含call_card_person_info,这个就不细说了),如显示保持恢复按钮,电话头像,通话时间,通话号码或人名以及通话人头像。
(2)包含dtmf_twelve_key_dialer配置文件:主要负责通话中拨号键盘的布局
(3)包含InCallTouchUi这个重要的类:主要负责来电时的锁屏界面(往左滑是拒绝来电,往右滑是接听来电),该类继承SlidingTab来实现滑屏效果,后面会说到运用SlidingTab能实现自己的来电锁屏界面
(4)包含incallmenu类,主要负责MENU菜单的一些操作(如挂断电话,免提,合并通话等),虽然incallmenu负责MENU的绘画及布局,但是实际onclick后的操作是由incallscreen类来操控的