当前位置:   article > 正文

Android打电话流程学习(一)_android phone电话呼入流程

android phone电话呼入流程

目录

1. Android电话的层次设计

2. RIL架构

2.1 介绍

2.2 RIL初始化

2.3 RIL交互

2.3.1 主动请求

2.3.2 被动请求

3. RIL层事件注册过程

4. Phone层事件注册过程

5. CallManager层事件注册过程

参考文献


1. Android电话的层次设计

Framework层的RIL中的RILReceiver线程从RILD服务进程中读取modem发送上来的来电消息等信息,通过消息注册-响应机制来通知应用层处理。

上图清晰地显示了各层之间的消息处理关系,CallManager连接Framework层和应用层的Phone,CallManager处理GSMPhone注册的消息事件,并且触发CallManager注册的消息事件,而CallNotifier处理CallManager消息,这样就将RIL层的消息一级一级传送的应用层的Phone了。

2. RIL架构

2.1 介绍

Android的无线接口层(RIL)提供了Android电话服务(android.telephony)与无线电硬件之间的抽象层。RIL是通讯无关的,提供基于GSM的网络支持。

下图显示了RIL位于Android电话系统架构中的位置,其中实线框表示Android部分,虚线框表示合作伙伴所专用的部分。

RIL的架构:

 RIL 整体架构分为三层,最上层为 RIL-Java 适配层,中间层即为 RILD, 下层为 Modem. RIL-Java 通过 socket 与 RILD 层对接,RILD 层与 Modem 通过串口对接。

 RIL是手机上 Modem (基带芯片,WCDMA,CDMA2000 等就是指基带芯片的不同技术) 与 android 系统通讯的桥梁,RIL 的角色非常重要,RIL 被设计成能够可靠的高效的传输数据一个模块。

RIL包含两个基本部件:

  • RIL守护进程(RIL Daemon):RIL守护进程初始化Vendor RIL,用于通过 socket 和 framework 通讯以及处理整个 RIL 的 event。管理所有来自Android通讯服务的通讯,将其作为被请求的命令(solicited commands)调度给Vendor RIL。
  • Vendor RIL:ril.h文件中的无线电专用Vendor RIL掌管着所有和无线电硬件的通讯,并且通过未被请求的命令(unsolicited commands)分发给RIL Daemon。手机厂商自己实现的部分,之所以这样设计是因为不同的厂商使用的 Modem 不一样,而 RIL 又和 Modem 紧密联系,所以 Android 有把和 Modem 联系紧密的部分和公共部分剥离开,让不同的厂商可以自己实现 vendor RIL 以适应厂商自己的 Modem。

[来源于通信百科]

  • RIL(Radio Interface Layer)

    目前的智能机在硬件上多采用双cpu的架构,一个是基带处理器,主要处理数字信号、语音信号的编码解码以及GSM通信协议,另一个是应用处理器,运行操作系统和各种应用程序。基带处理器、射频和其它外围芯片作为一个模块,成为GSM/GPRS MODEM,提供AT命令接口。网络的应用已经是一个需求的热点,而目前的GSM模块大多都能支持GPRS功能。应用处理器通过AT命令集与带GPRS功能的无线通讯模块通信,为实现网络的应用提供了一个最底层的支持。 从软件的角度来看,RIL(Radio Interface Layer)工作在PPP、TCP/IP协议之下,负责数据的可靠传输、AT命令的发送以及response的解析。当然,除了对网络的支持,RIL也支持SMS、Voice Call等功能。从这一点来看,RIL的性能好坏影响着所有无线通信应用相关的软件,而软件设计的合理性又影响着RIL的性能。

  • Windows Mobile上的RIL

    Windows Mobile是用在智能手机上的主流操作系统之一。微软是这样介绍RIL的:作为Windows Mobile的一个非常重要的组件,RIL使各种无线语音和数据应用成为可能。运行在Windows Mobile上的软件可以通过RIL无缝地与GSM/GPRS或者CDMA2000 1X modem通信。RIL的位置处于无线基带系统的协议栈之上,Windows Mobile的CellCore层之下。由于RIL隐藏了硬件上的一些细节,OEM厂商可以根据自己的需要将不同型号的无线modem集成到它们的产品之中。

  • Android上的RIL

    Android是目前最流行智能手机操作系统之一,Android的RIL位于应用程序框架与内核之间,分成了两个部分,一个部分是rild,它负责socket与应用程序框架进行通信。另外一个部分是Vendor RIL,这个部分负责向下是通过两种方式与radio进行通信,它们是直接与radio通信的AT指令通道和用于传输包数据的通道,数据通道用于手机的上网功能。 对于RIL的java框架部分,也被分成了两个部分,一个是RIL模块,这个模块主要用于与下层的rild进行通信,另外一个是Phone模块,这个模块直接暴露电话功能接口给应用开发用户,供他们调用以进行电话功能的实现。

2.2 RIL初始化

Android在启动时初始化通讯栈和Vendor RIL,描述如下:

  • RILL Daemon读取rild.lib路径和rild.libargs系统参数,决定应该使用的Vendor RIL库和向Vendor RIL提供的初始化参数;
  • RILL Daemon加载Vendor RIL库,执行RIL_Init初始化RIL并为RIL函数获取参数;
  • RILL Daemon调用Android通讯栈中RIL_register,为Vendor RIL函数提供参考。 

  RILL Daemon源码请参考//device/commands/rild/rild.c

2.3 RIL交互

RIL句柄提供了两种交互方式:

  • 主动请求命令(Solicited commands):主动请求命令来自RIL lib,比如DIAL和HANGUP。
  • 被动请求命令(Unsolicited responses):被动请求命令来自基带,比如CALL_STATE_CHANGED 和 NEW_SMS。

2.3.1 主动请求

以下代码片段属于主动请求命令:
  void OnRequest (int request_id, void *data, size_t datalen, RIL_Token t);
  void OnRequestComplete (RIL_Token t, RIL_Error e, void *response, size_t responselen);
  
有超过60个主动请求命令:

  • SIM PIN,IO和IMSI/IMEI(11)
  • 电话状态和动作(拨号,应答,静音…)(16)
  • 网络状态查询(4)
  • 网络设置(禁止,转发,选择…)(12)
  • 短信(3)
  • PDP连接(4)
  • 电源和复位(2)
  • 辅助服务(5)
  • 供应商定义及其支持(4)

下图表明了Android系统一个主动请求的电话过程:

2.3.2 被动请求

以下代码片段属于被动请求命令:
  void OnUnsolicitedResponse (int unsolResponse, void *data, size_t datalen);
  
有超过10条被动请求命令:

  • 网络状态改变(4)
  • 新短信通知(3)
  • 新USSD通知(2)
  • 信号强度和时间改变(2)

下图表明Android系统中一个被动请求的电话过程:

3. RIL层事件注册过程

[frameworks\base\telephony\java\com\android\internal\telephony\PhoneFactory.java]

  1. public static void makeDefaultPhone(Context context) {
  2. synchronized(Phone.class) {
  3. if (!sMadeDefaults) {
  4. sLooper = Looper.myLooper();
  5. sContext = context;
  6. if (sLooper == null) {
  7. throw new RuntimeException("PhoneFactory.makeDefaultPhone must be called from Looper thread");
  8. }
  9. int retryCount = 0;
  10. for(;;) {
  11. boolean hasException = false;
  12. retryCount ++;
  13. try {
  14. new LocalServerSocket("com.android.internal.telephony");
  15. } catch (java.io.IOException ex) {
  16. hasException = true;
  17. }
  18. if ( !hasException ) {
  19. break;
  20. } else if (retryCount > SOCKET_OPEN_MAX_RETRY) {
  21. throw new RuntimeException("PhoneFactory probably already running");
  22. } else {
  23. try {
  24. Thread.sleep(SOCKET_OPEN_RETRY_MILLIS);
  25. } catch (InterruptedException er) {
  26. }
  27. }
  28. }
  29. sPhoneNotifier = new DefaultPhoneNotifier();
  30. // Get preferred network mode
  31. int preferredNetworkMode = RILConstants.PREFERRED_NETWORK_MODE;
  32. if (TelephonyManager.getLteOnCdmaModeStatic() == PhoneConstants.LTE_ON_CDMA_TRUE) {
  33. preferredNetworkMode = Phone.NT_MODE_GLOBAL;
  34. }
  35. //从数据库中读取网络模式
  36. int networkMode = Settings.Global.getInt(context.getContentResolver(),
  37. Settings.Global.PREFERRED_NETWORK_MODE, preferredNetworkMode);
  38. Log.i(LOG_TAG, "Network Mode set to " + Integer.toString(networkMode));
  39. int cdmaSubscription;
  40. int lteOnCdma = TelephonyManager.getLteOnCdmaModeStatic();
  41. switch (lteOnCdma) {
  42. case PhoneConstants.LTE_ON_CDMA_FALSE:
  43. cdmaSubscription = CdmaSubscriptionSourceManager.SUBSCRIPTION_FROM_NV;
  44. Log.i(LOG_TAG, "lteOnCdma is 0 use SUBSCRIPTION_FROM_NV");
  45. break;
  46. case PhoneConstants.LTE_ON_CDMA_TRUE:
  47. cdmaSubscription = CdmaSubscriptionSourceManager.SUBSCRIPTION_FROM_RUIM;
  48. Log.i(LOG_TAG, "lteOnCdma is 1 use SUBSCRIPTION_FROM_RUIM");
  49. break;
  50. case PhoneConstants.LTE_ON_CDMA_UNKNOWN:
  51. default:
  52. //Get cdmaSubscription mode from Settings.System
  53. cdmaSubscription = Settings.Global.getInt(context.getContentResolver(),
  54. Settings.Global.PREFERRED_CDMA_SUBSCRIPTION,
  55. preferredCdmaSubscription);
  56. Log.i(LOG_TAG, "lteOnCdma not set, using PREFERRED_CDMA_SUBSCRIPTION");
  57. break;
  58. }
  59. Log.i(LOG_TAG, "Cdma Subscription set to " + cdmaSubscription);
  60. //reads the system properties and makes commandsinterface
  61. sCommandsInterface = new RIL(context, networkMode, cdmaSubscription);
  62. // Instantiate UiccController so that all other classes can just call getInstance()
  63. UiccController.make(context, sCommandsInterface);
  64. //根据网络模式得到电话类型
  65. int phoneType = TelephonyManager.getPhoneType(networkMode);
  66. //根据电话类型创建对应类型的Phone对象,并且使用创建的Phone对象来构造PhoneProxy代理对象
  67. if (phoneType == PhoneConstants.PHONE_TYPE_GSM) {
  68. Log.i(LOG_TAG, "Creating GSMPhone");
  69. sProxyPhone = new PhoneProxy(new GSMPhone(context,sCommandsInterface, sPhoneNotifier));
  70. } else if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) {
  71. switch (TelephonyManager.getLteOnCdmaModeStatic()) {
  72. case PhoneConstants.LTE_ON_CDMA_TRUE:
  73. Log.i(LOG_TAG, "Creating CDMALTEPhone");
  74. sProxyPhone = new PhoneProxy(new CDMALTEPhone(context,sCommandsInterface, sPhoneNotifier));
  75. break;
  76. case PhoneConstants.LTE_ON_CDMA_FALSE:
  77. default:
  78. Log.i(LOG_TAG, "Creating CDMAPhone");
  79. sProxyPhone = new PhoneProxy(new CDMAPhone(context,sCommandsInterface, sPhoneNotifier));
  80. break;
  81. }
  82. }
  83. sMadeDefaults = true;
  84. }
  85. }
  86. }

在PhoneFactory的makeDefaultPhone函数中,首先构造一个DefaultPhoneNotifier对象和RIL对象,然后从数据库中读取网络模式,根据网络模式得到对应的电话类型,从而构造对应的Phone对象,并为该Phone对象创建一个PhoneProxy代理对象。对于GSM网络,会构造一个GSMPhone对象。

[frameworks\base\telephony\java\com\android\internal\telephony\gsm\GSMPhone.java]

  1. public GSMPhone (Context context, CommandsInterface ci, PhoneNotifier notifier, boolean unitTestMode) {
  2. super(notifier, context, ci, unitTestMode);
  3. mCM.setPhoneType(Phone.PHONE_TYPE_GSM);
  4. mIccCard.set(MsUiccController.getInstance(this).getIccCard());
  5. mIccRecords = mIccCard.get().getIccRecords();
  6. mCT = new GsmCallTracker(this);
  7. mSST = new GsmServiceStateTracker (this);
  8. mSMS = new GsmSMSDispatcher(this, mSmsStorageMonitor, mSmsUsageMonitor);
  9. if (!unitTestMode) {
  10. mSimPhoneBookIntManager = new SimPhoneBookInterfaceManager(this);
  11. mSimSmsIntManager = new SimSmsInterfaceManager(this, mSMS);
  12. mSubInfo = new PhoneSubInfo(this);
  13. }
  14. mCM.registerForAvailable(this, EVENT_RADIO_AVAILABLE, null);
  15. registerForSimRecordEvents();
  16. mCM.registerForOffOrNotAvailable(this, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
  17. mCM.registerForOn(this, EVENT_RADIO_ON, null);
  18. mCM.setOnUSSD(this, EVENT_USSD, null);
  19. mCM.setOnSuppServiceNotification(this, EVENT_SSN, null);
  20. mSST.registerForNetworkAttached(this, EVENT_REGISTERED_TO_NETWORK, null);
  21. mHandlerThread = new HandlerThread("GSMPhone_AsyncThread");
  22. mHandlerThread.start();
  23. mAsyncThread = new AsyncThread(mHandlerThread.getLooper());
  24. if (false) {
  25. try {
  26. //debugSocket = new LocalServerSocket("com.android.internal.telephony.debug");
  27. debugSocket = new ServerSocket();
  28. debugSocket.setReuseAddress(true);
  29. debugSocket.bind (new InetSocketAddress("127.0.0.1", 6666));
  30. debugPortThread
  31. = new Thread(
  32. new Runnable() {
  33. public void run() {
  34. for(;;) {
  35. try {
  36. Socket sock;
  37. sock = debugSocket.accept();
  38. Log.i(LOG_TAG, "New connection; resetting radio");
  39. mCM.resetRadio(null);
  40. sock.close();
  41. } catch (IOException ex) {
  42. Log.w(LOG_TAG,
  43. "Exception accepting socket", ex);
  44. }
  45. }
  46. }
  47. },
  48. "GSMPhone debug");
  49. debugPortThread.start();
  50. } catch (IOException ex) {
  51. Log.w(LOG_TAG, "Failure to open com.android.internal.telephony.debug socket", ex);
  52. }
  53. }
  54. //Change the system property
  55. SystemProperties.set(TelephonyProperties.CURRENT_ACTIVE_PHONE,
  56. new Integer(Phone.PHONE_TYPE_GSM).toString());
  57. }

在构造GSMPhone对象时,首先使用父类的成员变量CommandsInterfac mCM设置电话类型,由于RIL类实现了CommandsInterfac接口,因此mCM引用RIL对象。在构造GSMPhone对象时通过参数传入并设置父类PhoneBase的成员变量mCM。

[frameworks\base\telephony\java\com\android\internal\telephony\PhoneBase.java]

  1. protected PhoneBase(PhoneNotifier notifier, Context context, CommandsInterface ci,
  2. boolean unitTestMode) {
  3. this.mNotifier = notifier;
  4. this.mContext = context;
  5. mLooper = Looper.myLooper();
  6. mCM = ci;
  7. setPropertiesByCarrier();
  8. setUnitTestMode(unitTestMode);
  9. SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
  10. mDnsCheckDisabled = sp.getBoolean(DNS_SERVER_CHECK_DISABLED_KEY, false);
  11. mCM.setOnCallRing(this, EVENT_CALL_RING, null);
  12. mIsVoiceCapable = mContext.getResources().getBoolean(com.android.internal.R.bool.config_voice_capable);
  13. mDoesRilSendMultipleCallRing = SystemProperties.getBoolean(
  14. TelephonyProperties.PROPERTY_RIL_SENDS_MULTIPLE_CALL_RING, true);
  15. Log.d(LOG_TAG, "mDoesRilSendMultipleCallRing=" + mDoesRilSendMultipleCallRing);
  16. mCallRingDelay = SystemProperties.getInt(
  17. TelephonyProperties.PROPERTY_CALL_RING_DELAY, 3000);
  18. Log.d(LOG_TAG, "mCallRingDelay=" + mCallRingDelay);
  19. // Initialize device storage and outgoing SMS usage monitors for SMSDispatchers.
  20. mSmsStorageMonitor = new SmsStorageMonitor(this);
  21. mSmsUsageMonitor = new SmsUsageMonitor(context);
  22. }

构造GSMPhone对象同时也会创建一个GsmCallTracker对象,GSMCallTracker实现了电话的拨打 (Dial)、接听/拒绝 (accept/reject)、挂断 (hangup)、保持 (hold)、切换以及电话会议等功能,它还负责查询Modem当前有多少路通话,维护电话状态等功能。

GSMCallTracker中包含了GsmConnection、RegistrantList、 GSMCall和Phone.State等类的对象实例。在GSMCallTracker构造函数中向RIL类实例注册了RegistrantList,当通话状态及射频Radio状态变化时,就会通知GSMCallTracker。

[frameworks\base\telephony\java\com\android\internal\telephony\gsm\GsmCallTracker.java]

  1. GsmCallTracker (GSMPhone phone) {
  2. this.phone = phone;
  3. cm = phone.mCM;
  4. cm.registerForCallStateChanged(this, EVENT_CALL_STATE_CHANGE, null);
  5. cm.registerForVideoCallStateChanged(this, EVENT_CALL_STATE_CHANGE, null);
  6. cm.registerForOn(this, EVENT_RADIO_AVAILABLE, null);
  7. cm.registerForNotAvailable(this, EVENT_RADIO_NOT_AVAILABLE, null);
  8. sendEmptyMessage(EVENT_INITIALIZE);
  9. }

cm引用RIL对象,在这里注册了电话状态改变事件,视频电话状态改变事件,无线开关事件等。由于RIL实现了CommandsInterface接口,并继承于BaseCommands抽象类,registerForCallStateChanged函数实现在RIL的父类BaseCommands中。

这里为RIL注册了一些消息事件,并指定GsmCallTracker来处理这些消息。

[frameworks\base\telephony\java\com\android\internal\telephony\BaseCommands.java]

  1. public void registerForCallStateChanged(Handler h, int what, Object obj) {
  2. Registrant r = new Registrant (h, what, obj);
  3. mCallStateRegistrants.add(r);
  4. }

该函数通过Handler及对应的事件消息来构造一个Registrant对象,并将其注册到mCallStateRegistrants对象中,mCallStateRegistrants为RegistrantList类型变量,定义在RIL的父类BaseCommands中,RegistrantList类是用于保存注册的处理指定消息的所有Handler,RegistrantList类首先将某个消息及处理该消息的Handler封装成Registrant对象,并将该对象保存到成员变量registrants动态数组中。

[frameworks\base\core\java\android\os\RegistrantList.java]

  1. ArrayList registrants = new ArrayList();
  2. public synchronized void add(Handler h, int what, Object obj){
  3. add(new Registrant(h, what, obj));
  4. }
  5. public synchronized void add(Registrant r){
  6. removeCleared();
  7. registrants.add(r);
  8. }

对于电话状态改变事件,注册的Handle对象为GsmCallTracker,因此在电话状态改变事件到来时,GsmCallTracker将处理EVENT_CALL_STATE_CHANGE消息事件。

GsmCallTracker

  • EVENT_POLL_CALLS_RESULT
  • EVENT_OPERATION_COMPLETE
  • EVENT_SWITCH_RESULT
  • EVENT_CONFERENCE_RESULT
  • EVENT_SEPAEATE_RESULT
  • EVENT_ECT_RESULT
  • EVENT_GET_LAST_CALL_FALL_CAUSE
  • EVENT_REPOLL_AFTER_DELAY
  • EVENT_CALL_STATE_CHANGE
  • EVENT_RADIO_AVAILABLE
  • EVENT_RADIO_NOT_AVAILABLE
  • EVENT_INITIALIZE

GsmCallTracker有三个成员变量:

  • GsmCall ringingCall = new GsmCall(this) 前台Call,其中对应的Connection是ACTIVE,DIALING,ALERTING状态的,即激活状态
  • GsmCall foregroundCall = new GsmCall(this)后台Call,其中对应的Connection是HOLDING状态的,即保持状态;
  • GsmCall backgroundCall = new GsmCall(this)来电Call,其中对应的Connection是INCOMING,WAITING状态的,即来电状态。

4. Phone层事件注册过程

在Phone进程启动时,PhoneApp的onCreate函数首先被调用,PhoneApp会构造各种全局对象,同时也会注册一些事件。

  1. mCM = CallManager.getInstance();
  2. mCM.registerPhone(phone);

函数registerPhone为构造的相应类型的phone对象注册一些事件。

[frameworks\base\telephony\java\com\android\internal\telephony\CallManager.java]

  1. public boolean registerPhone(Phone phone) {
  2. Phone basePhone = getPhoneBase(phone);
  3. if (basePhone != null && !mPhones.contains(basePhone)) {
  4. if (DBG) {
  5. Log.d(LOG_TAG, "registerPhone(" +
  6. phone.getPhoneName() + " " + phone + ")");
  7. }
  8. if (mPhones.isEmpty()) {
  9. mDefaultPhone = basePhone;
  10. }
  11. mPhones.add(basePhone);
  12. mRingingCalls.add(basePhone.getRingingCall());
  13. mBackgroundCalls.add(basePhone.getBackgroundCall());
  14. mForegroundCalls.add(basePhone.getForegroundCall());
  15. registerForPhoneStates(basePhone);
  16. return true;
  17. }
  18. return false;
  19. }

registerForPhoneStates函数用于注册电话状态变化事件。

  1. private void registerForPhoneStates(Phone phone) {
  2. // for common events supported by all phones
  3. phone.registerForPreciseCallStateChanged(mHandler, EVENT_PRECISE_CALL_STATE_CHANGED, null);
  4. phone.registerForDisconnect(mHandler, EVENT_DISCONNECT, null);
  5. phone.registerForNewRingingConnection(mHandler, EVENT_NEW_RINGING_CONNECTION, null);
  6. phone.registerForUnknownConnection(mHandler, EVENT_UNKNOWN_CONNECTION, null);
  7. phone.registerForIncomingRing(mHandler, EVENT_INCOMING_RING, null);
  8. phone.registerForRingbackTone(mHandler, EVENT_RINGBACK_TONE, null);
  9. phone.registerForInCallVoicePrivacyOn(mHandler, EVENT_IN_CALL_VOICE_PRIVACY_ON, null);
  10. phone.registerForInCallVoicePrivacyOff(mHandler, EVENT_IN_CALL_VOICE_PRIVACY_OFF, null);
  11. phone.registerForDisplayInfo(mHandler, EVENT_DISPLAY_INFO, null);
  12. phone.registerForSignalInfo(mHandler, EVENT_SIGNAL_INFO, null);
  13. phone.registerForResendIncallMute(mHandler, EVENT_RESEND_INCALL_MUTE, null);
  14. phone.registerForMmiInitiate(mHandler, EVENT_MMI_INITIATE, null);
  15. phone.registerForMmiComplete(mHandler, EVENT_MMI_COMPLETE, null);
  16. phone.registerForSuppServiceFailed(mHandler, EVENT_SUPP_SERVICE_FAILED, null);
  17. phone.registerForServiceStateChanged(mHandler, EVENT_SERVICE_STATE_CHANGED, null);
  18. // for events supported only by GSM and CDMA phone
  19. if (phone.getPhoneType() == PhoneConstants.PHONE_TYPE_GSM ||
  20. phone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA) {
  21. phone.setOnPostDialCharacter(mHandler, EVENT_POST_DIAL_CHARACTER, null);
  22. }
  23. // for events supported only by CDMA phone
  24. if (phone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA ){
  25. phone.registerForCdmaOtaStatusChange(mHandler, EVENT_CDMA_OTA_STATUS_CHANGE, null);
  26. phone.registerForSubscriptionInfoReady(mHandler, EVENT_SUBSCRIPTION_INFO_READY, null);
  27. phone.registerForCallWaiting(mHandler, EVENT_CALL_WAITING, null);
  28. phone.registerForEcmTimerReset(mHandler, EVENT_ECM_TIMER_RESET, null);
  29. }
  30. }

此时的Phone类型为GsmPhone,其父类为PhoneBase,这里为PhoneBase注册了一些消息事件,并指定CallManager类的mHandler来处理这些消息。

GsmPhone

  • EVENT_RADIO_AVAILABLE
  • EVENT_RADIO_ON
  • EVENT_REGISTERED_TO_NETWORK
  • EVENT_SIM_RECORDS_LOADED
  • EVENT_GET_BASEBAND_VERSION_DONE
  • EVENT_GET_IMEI_DONE
  • EVENT_GET_IMEISV DONE
  • EVENT_USSD
  • EVENT_RADIO_OFF_OR_NOT_AVAILABLE
  • EVENT_SSN
  • EVENT_SET_CALL_BARRING_DONE
  • EVENT_GET_CALL_BARRING_DONE
  • EVENT_CHANGE_CALL_BARRING_PASSWORD_DONE
  • EVENT_SET_VM_NUMBER_DONE
  • EVENT_GET_CALL_FORWARD_DONE
  • EVENT_NEW_ICC_SMS
  • EVENT_SET_NETWORK_AUTOMATIC
  • EVENT_ICC_RECORD_EVENTS
  • EVENT_SET_NETWORK_MANUAL_COMPLETE
  • EVENT_SET_NETWORK_AUTOMATIC_COMPLETE
  • EVENT_SET_CLIR_COMPLETE

PhoneBase

  • EVENT_CALL_RING
  • EVENT_CALL_RING_CONTINUE

5. CallManager层事件注册过程

在启动PhoneApp时,同样也会创建一个CallNotifier对象

notifier = CallNotifier.init(this, phone, ringer, mBtHandsfree, new CallLogAsync());

参数phone是通过PhoneFactory.getDefaultPhone()创建而来的,创建过程在前面已经详细介绍了。
参数ringer的构造过程如下:

  1. ringer = Ringer.init(this);
  2. static Ringer init(Context context) {
  3. synchronized (Ringer.class) {
  4. if (sInstance == null) {
  5. sInstance = new Ringer(context);
  6. } else {
  7. Log.wtf(LOG_TAG, "init() called multiple times! sInstance = " + sInstance);
  8. }
  9. return sInstance;
  10. }
  11. }
  12. private Ringer(Context context) {
  13. mContext = context;
  14. mPowerManager = IPowerManager.Stub.asInterface(ServiceManager.getService(Context.POWER_SERVICE));
  15. mVibrator = new SystemVibrator();
  16. }

参数mBtHandsfree的构造过程如下:

  1. mBtHandsfree = BluetoothHandsfree.init(this, mCM);
  2. static BluetoothHandsfree init(Context context, CallManager cm) {
  3. synchronized (BluetoothHandsfree.class) {
  4. if (sInstance == null) {
  5. sInstance = new BluetoothHandsfree(context, cm);
  6. } else {
  7. Log.wtf(TAG, "init() called multiple times! sInstance = " + sInstance);
  8. }
  9. return sInstance;
  10. }
  11. }

CallNotifier对象构造过程:

[packages\apps\Phone\src\com\android\phone\CallNotifier.java]

  1. static CallNotifier init(PhoneApp app, Phone phone, Ringer ringer,
  2. BluetoothHandsfree btMgr, CallLogAsync callLog) {
  3. synchronized (CallNotifier.class) {
  4. if (sInstance == null) {
  5. sInstance = new CallNotifier(app, phone, ringer, btMgr, callLog);
  6. } else {
  7. Log.wtf(LOG_TAG, "init() called multiple times! sInstance = " + sInstance);
  8. }
  9. return sInstance;
  10. }
  11. }
  12. protected CallNotifier(PhoneApp app, Phone phone, Ringer ringer,
  13. BluetoothHandsfree btMgr, CallLogAsync callLog) {
  14. mApplication = app;
  15. mCM = app.mCM;
  16. mCallLog = callLog;
  17. mLndAsync = new LndAsync();
  18. telMgr = (TelephonyManager) app.getSystemService(Context.TELEPHONY_SERVICE);
  19. mAudioManager = (AudioManager) mApplication.getSystemService(Context.AUDIO_SERVICE);
  20. registerForNotifications();
  21. try {
  22. mSignalInfoToneGenerator = new ToneGenerator(AudioManager.STREAM_VOICE_CALL,
  23. TONE_RELATIVE_VOLUME_SIGNALINFO);
  24. } catch (RuntimeException e) {
  25. Log.e(LOG_TAG, "CallNotifier: Exception caught while creating " +
  26. "mSignalInfoToneGenerator: " + e);
  27. mSignalInfoToneGenerator = null;
  28. }
  29. mRinger = ringer;
  30. mBluetoothHandsfree = btMgr;
  31. listen();
  32. }

这构造CallNotifier对象过程中,为CallManager层注册了一些消息事件,并指定CallNotifier来处理这些消息。

  1. private void registerForNotifications() {
  2. mCM.registerForNewRingingConnection(this, PHONE_NEW_RINGING_CONNECTION, null);
  3. mCM.registerForPreciseCallStateChanged(this, PHONE_STATE_CHANGED, null);
  4. mCM.registerForDisconnect(this, PHONE_DISCONNECT, null);
  5. mCM.registerForUnknownConnection(this, PHONE_UNKNOWN_CONNECTION_APPEARED, null);
  6. mCM.registerForIncomingRing(this, PHONE_INCOMING_RING, null);
  7. mCM.registerForCdmaOtaStatusChange(this, EVENT_OTA_PROVISION_CHANGE, null);
  8. mCM.registerForCallWaiting(this, PHONE_CDMA_CALL_WAITING, null);
  9. mCM.registerForDisplayInfo(this, PHONE_STATE_DISPLAYINFO, null);
  10. mCM.registerForSignalInfo(this, PHONE_STATE_SIGNALINFO, null);
  11. mCM.registerForInCallVoicePrivacyOn(this, PHONE_ENHANCED_VP_ON, null);
  12. mCM.registerForInCallVoicePrivacyOff(this, PHONE_ENHANCED_VP_OFF, null);
  13. mCM.registerForRingbackTone(this, PHONE_RINGBACK_TONE, null);
  14. mCM.registerForResendIncallMute(this, PHONE_RESEND_MUTE, null);
  15. }
  1. 当有PHONE_NEW_RINGING_CONNECTION类型消息到来时,意味着一个RINGING或WAITING的连接(connection)出现,此时handleMessage函数调用onNewRingingConnection来处理。后者先检查Settings里的设置是否可以接听电话;然后进 行响铃(见InCallTonePlayer)和显示InCallScreen的UI,见PhoneUtils.showIncomingCallUi()和PhoneApp.displayCallScreen()两个函数。通话过程中的铃音提示由线程类InCallTonePlayer完成。
  2. 当有PHONE_INCOMING_RING类型的消息到来时,意味着RIL层受到Ring,此处播放铃音。它使用的是Ringer.ring()函数,它会创建一个线程去播放铃音,见Ringer.makeLooper函数。
  3. 当有PHONE_STATE_CHANGED消息时,表明Phone的状态发生了改变,比如响铃后接通了电话,此时处理函数是onPhoneStateChanged,比如再次确认停止铃音、更新状态栏列的状态通知等。
  4. 当有PHONE_DISCONNECT消息时,表明电话连接已挂断或RingCall断掉。其处理函数是onDisconnect。它清理现场诸如音频通道恢复、来电响铃的停止确认、对InCallScreen的UI清理、若有未接电话须在状态栏显示等。

CallManager类的消息注册方法:

参考文献

Android电话来电流程源码分析

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/在线问答5/article/detail/988302
推荐阅读
相关标签
  

闽ICP备14008679号