1OutgoingCallBroadcaster.java
点击拨号盘拨打按钮后,进入通话的Phone包。此时首先进入的函数是OutgoingCallBroadcaster.java,该类是一个Activity。
由activity的生命周期可知,第一次进入时应调用onCreate()函数。(在该类中也只实现了这个函数。)解析一下这个函数:
1.1)首先获取Intent对象,获取拨出的号码。
1.2)接着判断号码是否为紧急号码,如果是紧急号码,将callNow变量赋值为true,启动InCallScreen,并发送广播。而在receiver里面判断callNow为ture就直接finish,而不再重复启动InCallScreen;如果不是紧急号码,将callNow变量赋值为false,发送广播“Intent.ACTION_NEW_OUTGOING_CALL”。

2OutgoingCallReceiver.java
广播发送后OutgoingCallReceiver将会收到该息。该类是一个内部类,在类OutgoingCallBroadcaster里面,作用是接收OutgoingCallBroadcaster发送的广播,判断是否已经启动InCallScreen。没有启动的话就进行一些初始化,如:对OTA进行初始化。接收到广播之后,从Intent里面取出电话号码及其URi。然后,设置Intent为ACTION_CALL,并带上号码和uri。启动InCallScreen。关闭该Activity。
OTA:Over-the-Air Technology空中下载技术,是通过移动通信(GSM或CDMA)的空中接口对SIM卡数据及应用进行远程管理的技术。空中接口可以采用WAP、GPRS、CDMA1X及短消息技术。OTA技术的应用,使得移动通信不仅可以提供语音和数据服务,而且还能提供新业务下载。
GSM:Global System for Mobile Communications,中文为全球移动通讯系统,俗称"全球通"。
CDMA:Code Division Multiple Access,又称码分多址,是在无线通讯上使用的技术,CDMA允许所有的使用者同时使用全部频带(1.2288Mhz),并且把其他使用者发出的讯号视为杂讯,完全不必考虑到讯号碰撞 (collision) 的问题。CDMA的优点包括:CDMA中所提供的语音编码技术,其通话品质比目前的GSM好,而且可以把用户对话时周围环境的噪音降低,使通话更为清晰。

3InCallScreen.java
该类extends了Acitivity,并且implements了OnClickListener,OnTouchListener和OnQueryCompleteListener。该类主要是负责通话的那一个界面,并且还负责菜单项各种按键事件和触摸时间的处理。同时本类还复写的finish()方法,所以一般不会被finish掉,调用这个方法时它又把自己放回栈中。InCallScreen可以接收这个Intent并启动。
3.1)onCreate(第一次)
3.1.1)callScreenOnCreate获得通话界面被创建的时间。
3.1.2)PhoneApp唤醒后台的服务程序。
3.1.3)判断当前的通话状态(IDLE =没有通话行为,RINGING =正在通话或呼叫等待,OFFHOOK = The phone is off hook. At least one call exists that is dialing, active or holding and no calls are ringing or waiting.),如果正在通话,不会出现键盘锁。接着设置mPhone and mForegroundCall/mBackgroundCall/mRingingCall。
3.1.4)getBluetoothHandsfree设置蓝牙耳机,如果存在蓝牙耳机,则安装该设备。
3.1.5)initInCallScreen加载各种view组建。
3.1.6)对通话的各种状态进行广播。(registerForPreciseCallStateChanged,registerForDisconnect,registerForMmiInitiateregisterForMmiComplete,registerForCallWaiting,registerForSuppServiceFailed,registerForCdmaOtaStatusChange)
3.1.7)internalResolveIntent判断是否使用了OTA技术,通过该判断设置通话界面的样式。
3.1.8)callScreenCreated记录通话界面创建完成后的时间
3.2)onNewIntent(非第一次)。
我们重新启动一个Intent时调用该函数。由于我们围绕唯一的一个InCallScreen实例来完成通过的这个过程,那么除了第一次被创建的InCallScreen,只要有来电或者去电,该程序就会发生。如果InCallScreen已经在前台,该程序也会发生。
3.2.1)setIntent保存该Intent,以至于将来我们可以获得该intent。
3.2.2)internalResolveIntent
3.3)onResume
进行一些初始化操作,如:获取一个PhoneApp对象,解开Keyguard Notification的statusBar给Disable。还内置了一个Handler可以回调处理一些事件,比如:PHONE_STATE_CHANGED,PHONE_DISCONNECT,EVENT_HEADSET_PLUG_STATE_CHANGED。同时有一个独立的BroadcastReceiver处理ACTION_HEADSET_PLUG,比如插入耳机等。
3.3.1)首先对锁屏情况下的来电除了处理。
3.3.2)disableStatusBar当正在通话界面时,使得状态栏可用。
3.3.3)setIgnoreTouchUserActivity忽略通话过程中无意的触碰事件,使得这些无意的触碰不会阻止设备进入休眠。
3.3.4)registerReceiver监听广播
3.3.5)startDialerSession当在前台是,保持一个dialer session。首先判断时候需要播放本地铃声,如果需要,则判断双音多频是否可用,如果可用,则创建一个声音播放器。
3.3.6)isBluetoothAudioConnected做一个是否蓝牙连接的判断。
3.3.7)如果是cdma通话,则初始化OTA状态,进而如果是采用了OTA,则设置InCallScreenMode为OTA通话模型。
3.3.8)clearDisconnected在检查该通话状态之前,切断其他网络连接。
3.3.9)syncWithPhoneState同步通话界面与Phone的当前状态。如果没有同步成功,则dismissAllDialogs();结束当前的所以通话,endInCallScreenSession();关闭通话界面的显示。
3.3.10)updateWakeState设置基于当前Phone的唤醒状态和屏幕超时,以及通话界面的当前状态。
3.3.11)enableTouchLock当onresume时“触摸锁“叠加是不可见的,尤其是这个检查可确保用户通话按MUNU来唤醒屏幕后将不会被锁。但如果拨号盘是打开的,而又需要通话计时,则造就了“触摸锁“覆盖。

4Profiler.java
该类对通话各个时间点进行记录。
static long sTimeCallScreenRequested;//通话界面被请求的时间
static long sTimeCallScreenOnCreate;//通话界面被创建的时间
static long sTimeCallScreenCreated;//通话界面创建完成后的时间
static long sTimeIncomingCallPanelRequested;//正在通话时,通话界面被请求的时间
static long sTimeIncomingCallPanelOnCreate;//正在通话时,通话界面被创建的时间
static long sTimeIncomingCallPanelCreated;//正在通话时,通话界面创建完成后的时间

5PhoneUtils.java
负责Phone对象的生成,主要调用phone.getForegroundCall(),phone.getBackgroundCall(),phone.getRingingCall(),phone.dial()。
5.1)placeCall(Phone phone, String number, Uri contactRef)
拨打传入的电话号码,该函数被InCallScreen中的placeCall调用。
参数phone手机对象;参数number用户要拨打的号码;参数contactRef要么是“tel:”,要么是“content://contacts”,取决于通话初始化,该参数引发呼叫;返回CALL_STATUS_DIALED,CALL_STATUS_DIALED_MMI,或CALL_STATUS_FAILED。
5.2)placeCallVia(Context context,Phone phone,String number,Uri contactRef,Uri gatewayUri)
使用第三方提供的网关拨打号码,该函数被InCallScreen中的placeCall调用。如果电话号码是紧急号码,GSM MMI码或者CDMA码则不能被呼叫。如果连接成立,这个方法发出一个同步调用阻止查询来电信息,使本地采用异步查询。
参数phone手机对象;参数context执行CallerInfo查询;参数number用户要拨打的号码,如果号码不能建立连接,则仅被用于建立电话卡,并更新通话记录;参数contactRef要么是“tel:”,要么是“content://contacts”,该参数引发呼叫;参数gatewayUri用于设置连接的地址;返回CALL_STATUS_DIALED或CALL_STATUS_FAILED。

6PhoneApp.java
该类是一个普通的java类,主要负责Phone对象顶层应用的生成。这是一个虚拟的Phone对象,它从framework层取得一个Phone对象。该类继承自Application,同时能常驻内存,他和PhoneUtils一起处理电话操作。在oncreate方法里面进行各种全局的初始化:获取Phone对象 NotificationMgr对象,PowerManager对象,SimCard对象等。同时内置的Handler可以回调处理各种事件,如:EVENT_SIM_ABSENT,EVENT_SIM_NETWORK_LOCKED,EVENT_UPDATE_INCALL_NOTIFICATION等。

7CallNotifier.java
监听Phone状态的改变和来自telephony层各种事件,并触发任何有关的UI行为(如开始的铃声和来电的用户界面,打在通话音,更新通知,写呼叫记录条目等)。
7.1)在构造函数中,实现
mPhone.registerForNewRingingConnection(this, PHONE_NEW_RINGING_CONNECTION, null);/*当有新来电或等待连接时Notifies。收到的讯息是:Message.obj将是一个AsyncResult,AsyncResult.userObj=obj,AsyncResult.result=a Connection。因为这个消息已经过时,所以通过检测Connection.isRinging()以确保连接有效。如果Connection.isRinging()为true,那么Connection.getCall()==Phone.getRingingCall()*/
mPhone.registerForPreciseCallStateChanged(this, PHONE_STATE_CHANGED, null);/*为通话状态的改变注册notification。通过调用PreciseCallState以获取更准确的通话状态。*/
mPhone.registerForDisconnect(this, PHONE_DISCONNECT, null);/*当由于本地或远程电话挂断或者出现错误挂断通话时Notifies。收到的讯息是:Message.obj will be an AsyncResult,AsyncResult.userObj = obj,AsyncResult.result = a Connection object that is no longer connected.*/
mPhone.registerForUnknownConnection(this, PHONE_UNKNOWN_CONNECTION_APPEARED, null);/*当以前未跟踪non-ringing/waiting连接时Notifies。这可能是由于一些其他实体(如SIM卡应用)发起呼叫。*/
mPhone.registerForIncomingRing(this, PHONE_INCOMING_RING, null);/*当有来电话响铃时Notifies。收到的讯息是:Message.obj will be an AsyncResult,AsyncResult.userObj = obj,AsyncResult.result = a Connection.*/
另外如果是CDMA通讯类型,还执行:
mPhone.registerForCdmaOtaStatusChange(this, EVENT_OTA_PROVISION_CHANGE, null);/*当CDMA OTA提供者位置改变时注册notification*/
mPhone.registerForCallWaiting(this, PHONE_CDMA_CALL_WAITING, null);/*当CDMA呼叫等待时注册notification*/
mPhone.registerForDisplayInfo(this, PHONE_STATE_DISPLAYINFO, null);/*为来自网络显示信息通知注册。Message.obj将包含一个AsyncResult。AsyncResult.result将是一个SuppServiceNotification实例。*/
mPhone.registerForSignalInfo(this, PHONE_STATE_SIGNALINFO, null);/*为来自网络的信号信息通知注册。Message.obj将包含一个AsyncResult。AsyncResult.result将是一个SuppServiceNotification实例。*/
mPhone.registerForInCallVoicePrivacyOn(this, PHONE_ENHANCED_VP_ON, null);/*当sInCall VoicePrivacy可用时注册notification*/
mPhone.registerForInCallVoicePrivacyOff(this, PHONE_ENHANCED_VP_OFF, null);/*当sInCall VoicePrivacy不可用时注册notification*/
mPhone.registerForCdmaFwdBurstDtmf(this, PHONE_CDMA_FWD_BURST_DTMF, null);/*为 CDMA Forward Burst DTMF的事件通知设置处理程序*/
mPhone.registerForCdmaFwdContDtmfStart(this, PHONE_CDMA_FWD_CONT_DTMF_START, null);/*为 CDMA Forward Burst DTMF启动的事件通知设置处理程序*/
mPhone.registerForCdmaFwdContDtmfStop(this, PHONE_CDMA_FWD_CONT_DTMF_STOP, null);/*为 CDMA Forward Burst DTMF停止的事件通知设置处理程序*/
如果是GSM类型,则执行:
mPhone.registerForRingbackTone(this, PHONE_RINGBACK_TONE, null);/*当带外回铃音(专业术语CRBT:COLOR RING BACK TONE,回铃音定义:当别人打电话给您时,他(她)听到的声音叫做回铃音。回铃音是指拨打电话的呼叫方所听到的对方电话的声音,当拨通电话时听到通话音,通常是长音;而当对方占线时则听到忙音,声音短促,有时,忙音会变成人声语音提示。)时Notifies。收到的讯息是:Message.obj将是一个AsyncResult,AsyncResult.userObj=obj,AsyncResult.result=true表示开始播放回铃音;=false表示停止。*/
mPhone.registerForResendIncallMute(this, PHONE_RESEND_MUTE, null);/*为复位上行静音状态成上行音频注册处理程序。*/
7.2)整个类由函数handleMessage串起来。

来自: http://hi.baidu.com/wentaokou/blog/item/816c6844d469aa32cefca31b.html

更多相关文章

  1. Fragment和Activity之间传值的问题
  2. Dagger2 基础入门与使用
  3. getSystemService 的参数
  4. Android中铃声总结【安卓源码解析一】
  5. Android应用程序组件间通信(一)——Intent类简介
  6. Android(安卓)Widget事件
  7. Android使用SharedPreferences保存数组
  8. Android(安卓)内功心法(1.9)——java设计模式之装饰模式
  9. Android开发之Memory类的分析

随机推荐

  1. Android(安卓)中看不见的外部存储路径
  2. android中自定义控件之TitleBar实现
  3. Android(安卓)逆向常用命令
  4. Android(安卓)Studio配置CMake开发NDK
  5. Android(安卓)Studio 报错Emulator: PANI
  6. 关于.jks和.keystore文件互相转换问题
  7. Android(安卓)React Native组件的生命周
  8. Android10 insmod源码分析
  9. AIDL使用入门
  10. 在mac上无法使用Android(安卓)Studio的解