Android的Phone设计的相当复杂,只有了解了Phone的设计框架才能把握电话的拨号或来电流程,在Android电话拨打流程源码分析中已经分析介绍了电话拨打流程,这里介绍一下电话的来电流程。
要理解这节内容,首先要知道Android电话的层次设计
Framework层的RIL中的RILReceiver线程从rild服务进程中读取modem发送上来的来电消息等信息,通过消息注册-响应机制来通知上层处理,上图清晰地显示了各层之间的消息处理关系,CallManager连接Framework层和应用层的Phone,
CallManager处理GSMPhone注册的消息事件,并且触发CallManager注册的消息事件,而CallNotifier处理CallManager消息,这样就将RIL层的消息一级一级传送的应用层的Phone了。
frameworks\base\telephony\java\com\android\internal\telephony\ PhoneFactory.java
public static void makeDefaultPhone(Context context) { synchronized(Phone.class) { if (!sMadeDefaults) { sLooper = Looper.myLooper(); sContext = context; if (sLooper == null) { throw new RuntimeException("PhoneFactory.makeDefaultPhone must be called from Looper thread"); } int retryCount = 0; for(;;) { boolean hasException = false; retryCount ++; try { new LocalServerSocket("com.android.internal.telephony"); } catch (java.io.IOException ex) { hasException = true; } if ( !hasException ) { break; } else if (retryCount > SOCKET_OPEN_MAX_RETRY) { throw new RuntimeException("PhoneFactory probably already running"); } else { try { Thread.sleep(SOCKET_OPEN_RETRY_MILLIS); } catch (InterruptedException er) { } } } sPhoneNotifier = new DefaultPhoneNotifier(); // Get preferred network mode int preferredNetworkMode = RILConstants.PREFERRED_NETWORK_MODE; if (TelephonyManager.getLteOnCdmaModeStatic() == PhoneConstants.LTE_ON_CDMA_TRUE) { preferredNetworkMode = Phone.NT_MODE_GLOBAL; } //从数据库中读取网络模式 int networkMode = Settings.Global.getInt(context.getContentResolver(), Settings.Global.PREFERRED_NETWORK_MODE, preferredNetworkMode); Log.i(LOG_TAG, "Network Mode set to " + Integer.toString(networkMode)); int cdmaSubscription; int lteOnCdma = TelephonyManager.getLteOnCdmaModeStatic(); switch (lteOnCdma) { case PhoneConstants.LTE_ON_CDMA_FALSE: cdmaSubscription = CdmaSubscriptionSourceManager.SUBSCRIPTION_FROM_NV; Log.i(LOG_TAG, "lteOnCdma is 0 use SUBSCRIPTION_FROM_NV"); break; case PhoneConstants.LTE_ON_CDMA_TRUE: cdmaSubscription = CdmaSubscriptionSourceManager.SUBSCRIPTION_FROM_RUIM; Log.i(LOG_TAG, "lteOnCdma is 1 use SUBSCRIPTION_FROM_RUIM"); break; case PhoneConstants.LTE_ON_CDMA_UNKNOWN: default: //Get cdmaSubscription mode from Settings.System cdmaSubscription = Settings.Global.getInt(context.getContentResolver(), Settings.Global.PREFERRED_CDMA_SUBSCRIPTION, preferredCdmaSubscription); Log.i(LOG_TAG, "lteOnCdma not set, using PREFERRED_CDMA_SUBSCRIPTION"); break; } Log.i(LOG_TAG, "Cdma Subscription set to " + cdmaSubscription); //reads the system properties and makes commandsinterface sCommandsInterface = new RIL(context, networkMode, cdmaSubscription); // Instantiate UiccController so that all other classes can just call getInstance() UiccController.make(context, sCommandsInterface); //根据网络模式得到电话类型 int phoneType = TelephonyManager.getPhoneType(networkMode); //根据电话类型创建对应类型的Phone对象,并且使用创建的Phone对象来构造PhoneProxy代理对象 if (phoneType == PhoneConstants.PHONE_TYPE_GSM) { Log.i(LOG_TAG, "Creating GSMPhone"); sProxyPhone = new PhoneProxy(new GSMPhone(context,sCommandsInterface, sPhoneNotifier)); } else if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) { switch (TelephonyManager.getLteOnCdmaModeStatic()) { case PhoneConstants.LTE_ON_CDMA_TRUE: Log.i(LOG_TAG, "Creating CDMALTEPhone"); sProxyPhone = new PhoneProxy(new CDMALTEPhone(context,sCommandsInterface, sPhoneNotifier)); break; case PhoneConstants.LTE_ON_CDMA_FALSE: default: Log.i(LOG_TAG, "Creating CDMAPhone"); sProxyPhone = new PhoneProxy(new CDMAPhone(context,sCommandsInterface, sPhoneNotifier)); break; } } sMadeDefaults = true; } } }在PhoneFactory的makeDefaultPhone函数中,首先构造一个DefaultPhoneNotifier对象和RIL对象,然后从数据库中读取网络模式,根据网络模式得到对应的电话类型,从而构造对应的Phone对象,并为该Phone对象创建一个PhoneProxy代理对象。对于GSM网络,会构造一个GSMPhone对象
frameworks\base\telephony\java\com\android\internal\telephony\gsm\ GSMPhone.java
public GSMPhone (Context context, CommandsInterface ci, PhoneNotifier notifier, boolean unitTestMode) { super(notifier, context, ci, unitTestMode); mCM.setPhoneType(Phone.PHONE_TYPE_GSM); mIccCard.set(MsUiccController.getInstance(this).getIccCard()); mIccRecords = mIccCard.get().getIccRecords(); mCT = new GsmCallTracker(this); mSST = new GsmServiceStateTracker (this); mSMS = new GsmSMSDispatcher(this, mSmsStorageMonitor, mSmsUsageMonitor); if (!unitTestMode) { mSimPhoneBookIntManager = new SimPhoneBookInterfaceManager(this); mSimSmsIntManager = new SimSmsInterfaceManager(this, mSMS); mSubInfo = new PhoneSubInfo(this); } mCM.registerForAvailable(this, EVENT_RADIO_AVAILABLE, null); registerForSimRecordEvents(); mCM.registerForOffOrNotAvailable(this, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null); mCM.registerForOn(this, EVENT_RADIO_ON, null); mCM.setOnUSSD(this, EVENT_USSD, null); mCM.setOnSuppServiceNotification(this, EVENT_SSN, null); mSST.registerForNetworkAttached(this, EVENT_REGISTERED_TO_NETWORK, null); mHandlerThread = new HandlerThread("GSMPhone_AsyncThread"); mHandlerThread.start(); mAsyncThread = new AsyncThread(mHandlerThread.getLooper()); if (false) { try { //debugSocket = new LocalServerSocket("com.android.internal.telephony.debug"); debugSocket = new ServerSocket(); debugSocket.setReuseAddress(true); debugSocket.bind (new InetSocketAddress("127.0.0.1", 6666)); debugPortThread = new Thread( new Runnable() { public void run() { for(;;) { try { Socket sock; sock = debugSocket.accept(); Log.i(LOG_TAG, "New connection; resetting radio"); mCM.resetRadio(null); sock.close(); } catch (IOException ex) { Log.w(LOG_TAG, "Exception accepting socket", ex); } } } }, "GSMPhone debug"); debugPortThread.start(); } catch (IOException ex) { Log.w(LOG_TAG, "Failure to open com.android.internal.telephony.debug socket", ex); } } //Change the system property SystemProperties.set(TelephonyProperties.CURRENT_ACTIVE_PHONE, new Integer(Phone.PHONE_TYPE_GSM).toString()); }在构造GSMPhone对象时,首先使用父类的成员变量CommandsInterfac mCM设置电话类型,由于RIL类实现了CommandsInterfac接口,因此mCM引用RIL对象。在构造GSMPhone对象时通过参数传入并设置父类PhoneBase的成员变量mCM。
frameworks\base\telephony\java\com\android\internal\telephony\ PhoneBase.java
protected PhoneBase(PhoneNotifier notifier, Context context, CommandsInterface ci, boolean unitTestMode) { this.mNotifier = notifier; this.mContext = context; mLooper = Looper.myLooper(); mCM = ci; setPropertiesByCarrier(); setUnitTestMode(unitTestMode); SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context); mDnsCheckDisabled = sp.getBoolean(DNS_SERVER_CHECK_DISABLED_KEY, false); mCM.setOnCallRing(this, EVENT_CALL_RING, null); mIsVoiceCapable = mContext.getResources().getBoolean(com.android.internal.R.bool.config_voice_capable); mDoesRilSendMultipleCallRing = SystemProperties.getBoolean( TelephonyProperties.PROPERTY_RIL_SENDS_MULTIPLE_CALL_RING, true); Log.d(LOG_TAG, "mDoesRilSendMultipleCallRing=" + mDoesRilSendMultipleCallRing); mCallRingDelay = SystemProperties.getInt( TelephonyProperties.PROPERTY_CALL_RING_DELAY, 3000); Log.d(LOG_TAG, "mCallRingDelay=" + mCallRingDelay); // Initialize device storage and outgoing SMS usage monitors for SMSDispatchers. mSmsStorageMonitor = new SmsStorageMonitor(this); mSmsUsageMonitor = new SmsUsageMonitor(context); }构造GSMPhone对象同时也会创建一个GsmCallTracker对象,GSMCallTracker实现了电话的拨打(Dial)、接听/拒绝(accept/reject)、挂断(hangup)、保持(hold)、切换以及电话会议等功能,它还负责查询Modem当前有多少路通话,维护电话状态等功能。GSMCallTracker中包含了GsmConnection、RegistrantList、 GSMCall和Phone.State等类的对象实例。在GSMCallTracker构造函数中向RIL类实例注册了RegistrantList,当通话状态及射频Radio状态变化时,就会通知GSMCallTracker。
GsmCallTracker (GSMPhone phone) { this.phone = phone; cm = phone.mCM; cm.registerForCallStateChanged(this, EVENT_CALL_STATE_CHANGE, null); cm.registerForVideoCallStateChanged(this, EVENT_CALL_STATE_CHANGE, null); cm.registerForOn(this, EVENT_RADIO_AVAILABLE, null); cm.registerForNotAvailable(this, EVENT_RADIO_NOT_AVAILABLE, null); sendEmptyMessage(EVENT_INITIALIZE); }cm引用RIL对象,在这里注册了电话状态改变事件,视频电话状态改变事件,无线开关事件等。由于RIL实现了CommandsInterface接口,并继承于BaseCommands抽象类,registerForCallStateChanged函数实现在RIL的父类BaseCommands中
这里为RIL注册了一些消息事件,并指定GsmCallTracker来处理这些消息。
frameworks\base\telephony\java\com\android\internal\telephony\BaseCommands.java
public void registerForCallStateChanged(Handler h, int what, Object obj) { Registrant r = new Registrant (h, what, obj); mCallStateRegistrants.add(r); }该函数通过Handler及对应的事件消息来构造一个Registrant对象,并将其注册到mCallStateRegistrants对象中,mCallStateRegistrants为RegistrantList类型变量,定义在RIL的父类BaseCommands中,RegistrantList类是用于保存注册的处理指定消息的所有Handler,RegistrantList类首先将某个消息及处理该消息的Handler封装成Registrant对象,并将该对象保存到成员变量registrants动态数组中。
ArrayList registrants = new ArrayList(); public synchronized void add(Handler h, int what, Object obj){ add(new Registrant(h, what, obj)); } public synchronized void add(Registrant r){ removeCleared(); registrants.add(r); }对于电话状态改变事件,注册的Handle对象为GsmCallTracker,因此在电话状态改变事件到来时,GsmCallTracker将处理EVENT_CALL_STATE_CHANGE消息事件。
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状态的,即来电状态
mCM = CallManager.getInstance(); mCM.registerPhone(phone);函数registerPhone为构造的相应类型的phone对象注册一些事件
public boolean registerPhone(Phone phone) { Phone basePhone = getPhoneBase(phone); if (basePhone != null && !mPhones.contains(basePhone)) { if (DBG) { Log.d(LOG_TAG, "registerPhone(" + phone.getPhoneName() + " " + phone + ")"); } if (mPhones.isEmpty()) { mDefaultPhone = basePhone; } mPhones.add(basePhone); mRingingCalls.add(basePhone.getRingingCall()); mBackgroundCalls.add(basePhone.getBackgroundCall()); mForegroundCalls.add(basePhone.getForegroundCall()); registerForPhoneStates(basePhone); return true; } return false; }registerForPhoneStates函数用于注册电话状态变化事件
private void registerForPhoneStates(Phone phone) { // for common events supported by all phones phone.registerForPreciseCallStateChanged(mHandler, EVENT_PRECISE_CALL_STATE_CHANGED, null); phone.registerForDisconnect(mHandler, EVENT_DISCONNECT, null); phone.registerForNewRingingConnection(mHandler, EVENT_NEW_RINGING_CONNECTION, null); phone.registerForUnknownConnection(mHandler, EVENT_UNKNOWN_CONNECTION, null); phone.registerForIncomingRing(mHandler, EVENT_INCOMING_RING, null); phone.registerForRingbackTone(mHandler, EVENT_RINGBACK_TONE, null); phone.registerForInCallVoicePrivacyOn(mHandler, EVENT_IN_CALL_VOICE_PRIVACY_ON, null); phone.registerForInCallVoicePrivacyOff(mHandler, EVENT_IN_CALL_VOICE_PRIVACY_OFF, null); phone.registerForDisplayInfo(mHandler, EVENT_DISPLAY_INFO, null); phone.registerForSignalInfo(mHandler, EVENT_SIGNAL_INFO, null); phone.registerForResendIncallMute(mHandler, EVENT_RESEND_INCALL_MUTE, null); phone.registerForMmiInitiate(mHandler, EVENT_MMI_INITIATE, null); phone.registerForMmiComplete(mHandler, EVENT_MMI_COMPLETE, null); phone.registerForSuppServiceFailed(mHandler, EVENT_SUPP_SERVICE_FAILED, null); phone.registerForServiceStateChanged(mHandler, EVENT_SERVICE_STATE_CHANGED, null); // for events supported only by GSM and CDMA phone if (phone.getPhoneType() == PhoneConstants.PHONE_TYPE_GSM || phone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA) { phone.setOnPostDialCharacter(mHandler, EVENT_POST_DIAL_CHARACTER, null); } // for events supported only by CDMA phone if (phone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA ){ phone.registerForCdmaOtaStatusChange(mHandler, EVENT_CDMA_OTA_STATUS_CHANGE, null); phone.registerForSubscriptionInfoReady(mHandler, EVENT_SUBSCRIPTION_INFO_READY, null); phone.registerForCallWaiting(mHandler, EVENT_CALL_WAITING, null); phone.registerForEcmTimerReset(mHandler, EVENT_ECM_TIMER_RESET, null); } }此时的Phone类型为GsmPhone,其父类为PhoneBase,这里为PhoneBase注册了一些消息事件,并指定CallManager类的mHandler来处理这些消息。
notifier = CallNotifier.init(this, phone, ringer, mBtHandsfree, new CallLogAsync());参数phone是通过PhoneFactory.getDefaultPhone()创建而来的,创建过程在前面已经详细介绍了。
ringer = Ringer.init(this); static Ringer init(Context context) { synchronized (Ringer.class) { if (sInstance == null) { sInstance = new Ringer(context); } else { Log.wtf(LOG_TAG, "init() called multiple times! sInstance = " + sInstance); } return sInstance; } } private Ringer(Context context) { mContext = context; mPowerManager = IPowerManager.Stub.asInterface(ServiceManager.getService(Context.POWER_SERVICE)); mVibrator = new SystemVibrator(); }参数mBtHandsfree的构造过程如下:
mBtHandsfree = BluetoothHandsfree.init(this, mCM); static BluetoothHandsfree init(Context context, CallManager cm) { synchronized (BluetoothHandsfree.class) { if (sInstance == null) { sInstance = new BluetoothHandsfree(context, cm); } else { Log.wtf(TAG, "init() called multiple times! sInstance = " + sInstance); } return sInstance; } }
static CallNotifier init(PhoneApp app, Phone phone, Ringer ringer, BluetoothHandsfree btMgr, CallLogAsync callLog) { synchronized (CallNotifier.class) { if (sInstance == null) { sInstance = new CallNotifier(app, phone, ringer, btMgr, callLog); } else { Log.wtf(LOG_TAG, "init() called multiple times! sInstance = " + sInstance); } return sInstance; } } protected CallNotifier(PhoneApp app, Phone phone, Ringer ringer, BluetoothHandsfree btMgr, CallLogAsync callLog) { mApplication = app; mCM = app.mCM; mCallLog = callLog; mLndAsync = new LndAsync(); telMgr = (TelephonyManager) app.getSystemService(Context.TELEPHONY_SERVICE); mAudioManager = (AudioManager) mApplication.getSystemService(Context.AUDIO_SERVICE); registerForNotifications(); try { mSignalInfoToneGenerator = new ToneGenerator(AudioManager.STREAM_VOICE_CALL, TONE_RELATIVE_VOLUME_SIGNALINFO); } catch (RuntimeException e) { Log.e(LOG_TAG, "CallNotifier: Exception caught while creating " + "mSignalInfoToneGenerator: " + e); mSignalInfoToneGenerator = null; } mRinger = ringer; mBluetoothHandsfree = btMgr; listen(); }这构造CallNotifier对象过程中,为CallManager层注册了一些消息事件,并指定CallNotifier来处理这些消息
private void registerForNotifications() { mCM.registerForNewRingingConnection(this, PHONE_NEW_RINGING_CONNECTION, null); mCM.registerForPreciseCallStateChanged(this, PHONE_STATE_CHANGED, null); mCM.registerForDisconnect(this, PHONE_DISCONNECT, null); mCM.registerForUnknownConnection(this, PHONE_UNKNOWN_CONNECTION_APPEARED, null); mCM.registerForIncomingRing(this, PHONE_INCOMING_RING, null); mCM.registerForCdmaOtaStatusChange(this, EVENT_OTA_PROVISION_CHANGE, null); mCM.registerForCallWaiting(this, PHONE_CDMA_CALL_WAITING, null); mCM.registerForDisplayInfo(this, PHONE_STATE_DISPLAYINFO, null); mCM.registerForSignalInfo(this, PHONE_STATE_SIGNALINFO, null); mCM.registerForInCallVoicePrivacyOn(this, PHONE_ENHANCED_VP_ON, null); mCM.registerForInCallVoicePrivacyOff(this, PHONE_ENHANCED_VP_OFF, null); mCM.registerForRingbackTone(this, PHONE_RINGBACK_TONE, null); mCM.registerForResendIncallMute(this, PHONE_RESEND_MUTE, null); }
我们已经知道在RIL中分别创建了两个线程,一个用于往rild套接字中写入数据,一个用于从该套接字中读取rild服务进程发送上来的数据。对于来电事件,RILReceiver会读取到rild发送过来的来电信息。
frameworks\base\telephony\java\com\android\internal\telephony\RIL.java
try { InputStream is = mSocket.getInputStream(); for (;;) { Parcel p; //从rild套接字中读取消息 length = readRilMessage(is, buffer); if (length < 0) { // End-of-stream reached break; } //将读取到的数据序列化到Parcel对象中 p = Parcel.obtain(); p.unmarshall(buffer, 0, length); p.setDataPosition(0); //数据处理 processResponse(p); p.recycle(); } } catch (java.io.IOException ex) { Log.i(LOG_TAG, "'" + SOCKET_NAME_RIL + "' socket closed", ex); } catch (Throwable tr) { Log.e(LOG_TAG, "Uncaught exception read length=" + length + "Exception:" + tr.toString()); }这段代码是RILReceiver线程不断循环读取来自rild的AT Response,调用processResponse进行处理,根据返回结果中不同的Request号,调用到相应的responseXXX函数簇,获取AT执行结果。
private void processResponse (Parcel p) { int type; type = p.readInt(); if (type == RESPONSE_UNSOLICITED) { processUnsolicited (p); } else if (type == RESPONSE_SOLICITED) { processSolicited (p); } releaseWakeLockIfDone(); }
在Android之rild进程启动源码分析介绍了,rild服务进程会接收到两种类型的消息,一种是Ap向Bp发送请求,Bp给Ap发送回复消息,一种是Bp主动给Ap发送事件,对于请求响应事件,调用processSolicited函数来处理,而对于BP主动发起的事件则调用processUnsolicited函数来处理。来电属于BP主动发起的请求事件,因此processUnsolicited函数将处理来电请求
protected void processUnsolicited (Parcel p) { int response; Object ret; response = p.readInt(); try { switch(response) { case RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED: ret = responseVoid(p); break; default: throw new RuntimeException("Unrecognized unsol response: " + response); } } catch (Throwable tr) { Log.e(LOG_TAG, "Exception processing unsol response: " + response + "Exception:" + tr.toString()); return; } switch(response) { case RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED: if (RILJ_LOGD) unsljLog(response); mCallStateRegistrants.notifyRegistrants(new AsyncResult(null, null, null)); break; } }mCallStateRegistrants为RegistrantList类型变量,前面已经介绍了消息注册过程,这里调用RegistrantList的notifyRegistrants函数来通知所有注册过该消息的Handler处理该消息。
frameworks\base\core\java\android\os\RegistrantList.java
public void notifyRegistrants(){ internalNotifyRegistrants(null, null); } private synchronized void internalNotifyRegistrants (Object result, Throwable exception){ for (int i = 0, s = registrants.size(); i < s ; i++) { Registrant r = (Registrant) registrants.get(i); r.internalNotifyRegistrant(result, exception); } }这里循环遍历成员变量registrants中保存的所有Registrant对象,前面介绍到,在注册某个Handler处理指定消息时,首先将其封装为Registrant对象,这里取出该消息对应的所有Registrant对象,并调用该对象的internalNotifyRegistrant函数来触发注册的Handler处理该消息。
void internalNotifyRegistrant (Object result, Throwable exception){ Handler h = getHandler(); if (h == null) { clear(); } else { Message msg = Message.obtain(); msg.what = what; msg.obj = new AsyncResult(userObj, result, exception); h.sendMessage(msg); } }该函数其是就是向注册的Handler中发送消息,消息为注册的消息类型。由于在构造GsmCallTracker对象时,已经在BaseCommands中注册了EVENT_CALL_STATE_CHANGE消息的处理Handler为GsmCallTracker对象本身,
cm.registerForCallStateChanged(this, EVENT_CALL_STATE_CHANGE, null);
因此mCallStateRegistrants.notifyRegistrants(new AsyncResult(null, null, null))将向GsmCallTracker对象发送EVENT_CALL_STATE_CHANGE的消息
frameworks\base\telephony\java\com\android\internal\telephony\CallTracker.java
public void handleMessage (Message msg) { AsyncResult ar; switch (msg.what) { case EVENT_CALL_STATE_CHANGE: pollCallsWhenSafe(); break; } }函数最终调用pollCallsWhenSafe来处理EVENT_CALL_STATE_CHANGE消息,pollCallsWhenSafe用于查询当前的通话状态。
protected void pollCallsWhenSafe() { needsPoll = true; if (checkNoOperationsPending()) { lastRelevantPoll = obtainMessage(EVENT_POLL_CALLS_RESULT); cm.getCurrentCalls(lastRelevantPoll); } }函数checkNoOperationsPending就是判断变量pendingOperations是否等于0,如果等于0,则调用CommandsInterface的getCurrentCalls函数来发送一个EVENT_POLL_CALLS_RESULT消息,该函数实现在RIL.java中。
AT命令CLCC查询结果对应于Connection类中的成员变量,一 路电话对应一个对象。
frameworks\base\telephony\java\com\android\internal\telephony\RIL.java
public void getCurrentCalls (Message result) { RILRequest rr = RILRequest.obtain(RIL_REQUEST_GET_CURRENT_CALLS, result); if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); send(rr); }
函数首先根据传进来的参数获取一个RILRequest请求对象,并调用send函数通过RILSender线程向rild服务进程发送RIL_REQUEST_GET_CURRENT_CALLS请求,请求查询当前所有的电话连接,使用CLCC 命令查询,底层返回来的查询结果如下 格式 |序号|0表示来电、1表示去电|电话状态|数据业务还是语音业务|是否是视频会议|号码
CLCC : 1、 0、 2、 0、 0 1881234578 …..
每个通话连接用通话列表用DriverCall类表示。Android使用了一个RILRequest对象池来管理RILRequest
static RILRequest obtain(int request, Message result) { RILRequest rr = null; synchronized(sPoolSync) { if (sPool != null) { rr = sPool; sPool = rr.mNext; rr.mNext = null; sPoolSize--; } } if (rr == null) { rr = new RILRequest(); } synchronized(sSerialMonitor) { rr.mSerial = sNextSerial++; } rr.mRequest = request; rr.mResult = result; rr.mp = Parcel.obtain(); if (result != null && result.getTarget() == null) { throw new NullPointerException("Message target must not be null"); } rr.mp.writeInt(request); rr.mp.writeInt(rr.mSerial); return rr; }当Phone进程从framework层向rild服务进程发送完RIL_REQUEST_GET_CURRENT_CALLS请求后,就等待接收rild返回对该消息的处理结果,RILReceiver线程将读取到该消息事件,并调用processSolicited函数来处理。
frameworks\base\telephony\java\com\android\internal\telephony\RIL.java
protected void processSolicited (Parcel p) { int serial, error; boolean found = false; serial = p.readInt(); error = p.readInt(); RILRequest rr; rr = findAndRemoveRequestFromList(serial); if (rr == null) { Log.w(LOG_TAG, "Unexpected solicited response! sn: "+ serial + " error: " + error); return; } Object ret = null; if (error == 0 || p.dataAvail() > 0) { try { switch (rr.mRequest) { case RIL_REQUEST_GET_CURRENT_CALLS: ret = responseCallList(p); break; } } catch (Throwable tr) { if (rr.mResult != null) { AsyncResult.forMessage(rr.mResult, null, tr); rr.mResult.sendToTarget(); } rr.release(); return; } } if (error != 0) { rr.onError(error, ret); rr.release(); return; } if (rr.mResult != null) { AsyncResult.forMessage(rr.mResult, ret, null); rr.mResult.sendToTarget(); } rr.release(); }
读取RIL请求序列号并依次在RILRequest列表中查找已发送过的RILRequest请求
protected RILRequest findAndRemoveRequestFromList(int serial) { synchronized (mRequestsList) { // 通过序号从变量列表mRequestsList中查找出指定的RILRequest for (int i = 0, s = mRequestsList.size() ; i < s ; i++) { RILRequest rr = mRequestsList.get(i); if (rr.mSerial == serial) { mRequestsList.remove(i); if (mRequestMessagesWaiting > 0) mRequestMessagesWaiting--; return rr; } } } return null; }若AT执行成功并有结果数据需要获取,则进入到switch-case语句根据请求号调用相应的responseXXX函数获得AT执行结果数据,放置在Object对象ret中;在取AT执行结果时若有异常发生,则ret保持为null空值。若AT执行发生错误时,则调用RILRequest的onError函数,这里的请求号为RIL_REQUEST_GET_CURRENT_CALLS,因此通过函数responseCallList读取查询结果
protected Object responseCallList(Parcel p) { int num; int voiceSettings; ArrayList<DriverCall> response; //保存通话列表 DriverCall dc; num = p.readInt();//读取通话列表数目 response = new ArrayList<DriverCall>(num); //根据CLCC查询到的通话列表创建DriverCall for (int i = 0 ; i < num ; i++) { dc = new DriverCall(); dc.state = DriverCall.stateFromCLCC(p.readInt()); dc.index = p.readInt(); dc.TOA = p.readInt(); dc.isMpty = (0 != p.readInt()); dc.isMT = (0 != p.readInt()); dc.als = p.readInt(); voiceSettings = p.readInt(); dc.isVoice = (0 == voiceSettings) ? false : true; dc.isVoicePrivacy = (0 != p.readInt()); dc.number = p.readString(); int np = p.readInt(); dc.numberPresentation = DriverCall.presentationFromCLIP(np); dc.name = p.readString(); dc.namePresentation = p.readInt(); int uusInfoPresent = p.readInt(); if (uusInfoPresent == 1) { dc.uusInfo = new UUSInfo(); dc.uusInfo.setType(p.readInt()); dc.uusInfo.setDcs(p.readInt()); byte[] userData = p.createByteArray(); dc.uusInfo.setUserData(userData); riljLogv(String.format("Incoming UUS : type=%d, dcs=%d, length=%d", dc.uusInfo.getType(), dc.uusInfo.getDcs(), dc.uusInfo.getUserData().length)); riljLogv("Incoming UUS : data (string)=" + new String(dc.uusInfo.getUserData())); riljLogv("Incoming UUS : data (hex): " + IccUtils.bytesToHexString(dc.uusInfo.getUserData())); } else { riljLogv("Incoming UUS : NOT present!"); } // Make sure there's a leading + on addresses with a TOA of 145 dc.number = PhoneNumberUtils.stringFromStringAndTOA(dc.number, dc.TOA); response.add(dc); if (dc.isVoicePrivacy) { mVoicePrivacyOnRegistrants.notifyRegistrants(); riljLog("InCall VoicePrivacy is enabled"); } else { mVoicePrivacyOffRegistrants.notifyRegistrants(); riljLog("InCall VoicePrivacy is disabled"); } } Collections.sort(response); if ((num == 0) && mTestingEmergencyCall.getAndSet(false)) { if (mEmergencyCallbackModeRegistrant != null) { riljLog("responseCallList: call ended, testing emergency call," + " notify ECM Registrants"); mEmergencyCallbackModeRegistrant.notifyRegistrant(); } } return response; }
GsmConnection的集合connections集合对象是一个数组,数组编号是从0开始的,所以我们会看到会有一个dc.index == i+1;的操作,对应关系就是这里建立的。之后会把底层查的DriverCall对象和GsmCallTracker中保存的GsmConnection对象进行比较。如DriverCall对象为空,我们本地保持的GsmConnection对象存在,很显然,是这路电话挂断了,反之如过DriverCall对象有,GsmConnection对象不存在,则是一个来电。最后使用forMessage函数将返回的结果封装到Message中的 obj中,并发送的消息的目标Handler处理,前面发送的是RIL_REQUEST_GET_CURRENT_CALLS请求,该请求中包含的一个EVENT_POLL_CALLS_RESULT消息。由于EVENT_POLL_CALLS_RESULT消息是从CallTracker中发出来的,而CallTracker是个抽象类,其handleMessage函数是由其子类GsmCallTracker实现的,因此EVENT_POLL_CALLS_RESULT是由GsmCallTracker来处理
frameworks\base\telephony\java\com\android\internal\telephony\gsm\GsmCallTracker.java
public void handleMessage (Message msg) { AsyncResult ar; switch (msg.what) { case EVENT_POLL_CALLS_RESULT: ar = (AsyncResult)msg.obj; if (msg == lastRelevantPoll) { needsPoll = false; lastRelevantPoll = null; handlePollCalls((AsyncResult)msg.obj); mMoveToBack = false; } break; } }
msg.obj中保存了查询到的所有DriverCall,函数直接调用handlePollCalls进行处理
protected synchronized void handlePollCalls(AsyncResult ar) { List polledCalls; if (ar.exception == null) { polledCalls = (List)ar.result; } else if (isCommandExceptionRadioNotAvailable(ar.exception)) { // just a dummy empty ArrayList to cause the loop // to hang up all the calls polledCalls = new ArrayList(); } else { // Radio probably wasn't ready--try again in a bit // But don't keep polling if the channel is closed pollCallsAfterDelay(); return; } Connection newRinging = null; //or waiting boolean hasNonHangupStateChanged = false; // Any change besides boolean needsPollDelay = false; boolean unknownConnectionAppeared = false; for (int i = 0, curDC = 0, dcSize = polledCalls.size(); i < connections.length; i++) { GsmConnection conn = connections[i]; DriverCall dc = null; // polledCall list is sparse if (curDC < dcSize) { dc = (DriverCall) polledCalls.get(curDC); if (dc.index == i+1) { curDC++; } else { dc = null; } } if (conn == null && dc != null) { // Connection appeared in CLCC response that we don't know about if (pendingMO != null && pendingMO.compareTo(dc)) { if (DBG_POLL) log("poll: pendingMO=" + pendingMO); // It's our pending mobile originating call connections[i] = pendingMO; pendingMO.index = i; pendingMO.update(dc); pendingMO = null; // Someone has already asked to hangup this call if (hangupPendingMO) { hangupPendingMO = false; try { hangup(connections[i]); } catch (CallStateException ex) { Log.e(LOG_TAG, "unexpected error on hangup"); } return; } } else { connections[i] = new GsmConnection(phone.getContext(), dc, this, i); // it's a ringing call if (connections[i].getCall() == ringingCall) { newRinging = connections[i]; } else { if (dc.state != DriverCall.State.ALERTING && dc.state != DriverCall.State.DIALING) { connections[i].connectTime = System.currentTimeMillis(); } unknownConnectionAppeared = true; } } hasNonHangupStateChanged = true; } else if (conn != null && dc == null) { // Connection missing in CLCC response that we were // tracking. droppedDuringPoll.add(conn); // Dropped connections are removed from the CallTracker // list but kept in the GsmCall list connections[i] = null; } else if (conn != null && dc != null && !conn.compareTo(dc)) { // Connection in CLCC response does not match what // we were tracking. Assume dropped call and new call droppedDuringPoll.add(conn); connections[i] = new GsmConnection (phone.getContext(), dc, this, i); if (connections[i].getCall() == ringingCall) { newRinging = connections[i]; } // else something strange happened hasNonHangupStateChanged = true; } else if (conn != null && dc != null) { /* implicit conn.compareTo(dc) */ boolean changed; changed = conn.update(dc); hasNonHangupStateChanged = hasNonHangupStateChanged || changed; } if (REPEAT_POLLING) { if (dc != null) { // FIXME with RIL, we should not need this anymore if ((dc.state == DriverCall.State.DIALING /*&& cm.getOption(cm.OPTION_POLL_DIALING)*/) || (dc.state == DriverCall.State.ALERTING /*&& cm.getOption(cm.OPTION_POLL_ALERTING)*/) || (dc.state == DriverCall.State.INCOMING /*&& cm.getOption(cm.OPTION_POLL_INCOMING)*/) || (dc.state == DriverCall.State.WAITING /*&& cm.getOption(cm.OPTION_POLL_WAITING)*/) ) { // Sometimes there's no unsolicited notification // for state transitions needsPollDelay = true; } } } } // This is the first poll after an ATD. // We expect the pending call to appear in the list // If it does not, we land here if (pendingMO != null) { droppedDuringPoll.add(pendingMO); pendingMO = null; hangupPendingMO = false; } if (newRinging != null) { phone.notifyNewRingingConnection(newRinging); } // clear the "local hangup" and "missed/rejected call" // cases from the "dropped during poll" list // These cases need no "last call fail" reason for (int i = droppedDuringPoll.size() - 1; i >= 0 ; i--) { GsmConnection conn = droppedDuringPoll.get(i); if (conn.isIncoming() && conn.getConnectTime() == 0) { // Missed or rejected call Connection.DisconnectCause cause; if (conn.cause == Connection.DisconnectCause.LOCAL) { cause = Connection.DisconnectCause.INCOMING_REJECTED; } else { cause = Connection.DisconnectCause.INCOMING_MISSED; } droppedDuringPoll.remove(i); conn.onDisconnect(cause); } else if (conn.cause == Connection.DisconnectCause.LOCAL) { // Local hangup droppedDuringPoll.remove(i); conn.onDisconnect(Connection.DisconnectCause.LOCAL); } else if (conn.cause == Connection.DisconnectCause.INVALID_NUMBER) { droppedDuringPoll.remove(i); conn.onDisconnect(Connection.DisconnectCause.INVALID_NUMBER); } } // Any non-local disconnects: determine cause if (droppedDuringPoll.size() > 0) { cm.getLastCallFailCause(obtainNoPollCompleteMessage(EVENT_GET_LAST_CALL_FAIL_CAUSE)); } if (needsPollDelay) { pollCallsAfterDelay(); } // Cases when we can no longer keep disconnected Connection's // with their previous calls // 1) the phone has started to ring // 2) A Call/Connection object has changed state... // we may have switched or held or answered (but not hung up) if (newRinging != null || hasNonHangupStateChanged) { internalClearDisconnected(); } updatePhoneState(); if (unknownConnectionAppeared) { phone.notifyUnknownConnection(); } if (hasNonHangupStateChanged || newRinging != null) { phone.notifyPreciseCallStateChanged(); } }对于新的来电使用phone.notifyNewRingingConnection(newRinging)触发CallManager中的mHandler来处理该消息,在前面介绍了在构造PhoneApp的onCreate函数中,首先得到CallManager实例对象,然后调用该对象的registerPhone方法为Phone层注册消息事件,注册的处理消息的Handler为CallManager的变量mHandler。
frameworks\base\telephony\java\com\android\internal\telephony\CallManager.java
public void handleMessage(Message msg) { switch (msg.what) { case EVENT_NEW_RINGING_CONNECTION: if (VDBG) Log.d(LOG_TAG, " handleMessage (EVENT_NEW_RINGING_CONNECTION)"); if (getActiveFgCallState().isDialing() || hasMoreThanOneRingingCall()) { Connection c = (Connection) ((AsyncResult) msg.obj).result; try { Log.d(LOG_TAG, "silently drop incoming call: " + c.getCall()); c.getCall().hangup(); } catch (CallStateException e) { Log.w(LOG_TAG, "new ringing connection", e); } } else { mNewRingingConnectionRegistrants.notifyRegistrants((AsyncResult) msg.obj); } break; } }mNewRingingConnectionRegistrants.notifyRegistrants((AsyncResult) msg.obj)将触发mNewRingingConnectionRegistrants中注册的handler处理PHONE_NEW_RINGING_CONNECTION消息,在前面我们也介绍了,在PhoneApp的onCreate函数中构造CallNotifier对象时,通过registerForNotifications函数注册了CallNotifier来处理该消息。
packages\apps\Phone\src\com\android\phone\CallNotifier.java
public void handleMessage(Message msg) { switch (msg.what) { case PHONE_NEW_RINGING_CONNECTION: log("RINGING... (new)"); onNewRingingConnection((AsyncResult) msg.obj); mSilentRingerRequested = false; } }该函数直接调用onNewRingingConnection来处理来电
private void onNewRingingConnection(AsyncResult r) { Connection c = (Connection) r.result; log("onNewRingingConnection(): state = " + mCM.getState() + ", conn = { " + c + " }"); Call ringing = c.getCall(); Phone phone = ringing.getPhone(); // Check for a few cases where we totally ignore incoming calls. if (ignoreAllIncomingCalls(phone)) { PhoneUtils.hangupRingingCall(ringing); return; } if (!c.isRinging()) { Log.i(LOG_TAG, "CallNotifier.onNewRingingConnection(): connection not ringing!"); return; } // Stop any signalInfo tone being played on receiving a Call stopSignalInfoTone(); Call.State state = c.getState(); if (VDBG) log("- connection is ringing! state = " + state); if (VDBG) log("Holding wake lock on new incoming connection."); mApplication.requestWakeState(PhoneGlobals.WakeState.PARTIAL); if (PhoneUtils.isRealIncomingCall(state)) { startIncomingCallQuery(c); } else { if (VDBG) log("- starting call waiting tone..."); if (mCallWaitingTonePlayer == null) { mCallWaitingTonePlayer = new InCallTonePlayer(InCallTonePlayer.TONE_CALL_WAITING); mCallWaitingTonePlayer.start(); } if (DBG) log("- showing incoming call (this is a WAITING call)..."); showIncomingCall(); } if (VDBG) log("- onNewRingingConnection() done."); }通过函数showIncomingCall来启动InCallScreen界面,并开启来电铃声
private void showIncomingCall() { log("showIncomingCall()... phone state = " + mCM.getState()); try { ActivityManagerNative.getDefault().closeSystemDialogs("call"); } catch (RemoteException e) { } mApplication.requestWakeState(PhoneGlobals.WakeState.FULL); if (DBG) log("- updating notification from showIncomingCall()..."); mApplication.notificationMgr.updateNotificationAndLaunchIncomingCallUi(); }最后通过NotificationMgr类来启动来电界面
public void updateNotificationAndLaunchIncomingCallUi() { updateInCallNotification(true); }在函数updateInCallNotification中通过以下语句来启动来电界面
Intent inCallIntent = mApp.createInCallIntent(currentCall.getPhone().getPhoneId()); PendingIntent inCallPendingIntent =PendingIntent.getActivity(mContext, 0, inCallIntent, 0); builder.setContentIntent(inCallPendingIntent);