本文只对应用层进行分析
1.来电流程分析
PhoneApp在初始化时会实例CallNotifier对象,Callnotifier主要是对电话状态的监听,通知事件
PhoneApp创建一个CallNotifier // Create the CallNotifer singleton, which handles // asynchronous events from the telephony layer (like // launching the incoming-call UI when an incoming call comes // in.) notifier = CallNotifier.init(this, phone, ringer, mBtHandsfree, new CallLogAsync());
Callnotifier实现对电话状态的监听
/** Private constructor; @see init() */ private CallNotifier(PhoneApp app, Phone phone, Ringer ringer, BluetoothHandsfree btMgr, CallLogAsync callLog) { mApplication = app; mCM = app.mCM; mCallLog = callLog; mAudioManager = (AudioManager) mApplication.getSystemService(Context.AUDIO_SERVICE); registerForNotifications();//状态监听
registerForNotifications方法注册电话状态监听
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); }
mCM.registerForNewRingingConnection(this, PHONE_NEW_RINGING_CONNECTION, null); 监听来电,在handleMessage函数内处理
@Override public void handleMessage(Message msg) { switch (msg.what) { case PHONE_NEW_RINGING_CONNECTION: log("RINGING... (new)"); onNewRingingConnection((AsyncResult) msg.obj); mSilentRingerRequested = false; break;
转到onNewRingingConnection处理来电,最后转到showIncomingCall函数启动InCallScreen界面,当然还有处理一些状态更新,响铃之类的
/** * Handles a "new ringing connection" event from the telephony layer. */ 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)) { // Immediately reject the call, without even indicating to the user // that an incoming call occurred. (This will generally send the // caller straight to voicemail, just as if we *had* shown the // incoming-call UI and the user had declined the call.) PhoneUtils.hangupRingingCall(ringing); return; } if (c == null) { Log.w(LOG_TAG, "CallNotifier.onNewRingingConnection(): null connection!"); // Should never happen, but if it does just bail out and do nothing. return; } if (!c.isRinging()) { Log.i(LOG_TAG, "CallNotifier.onNewRingingConnection(): connection not ringing!"); // This is a very strange case: an incoming call that stopped // ringing almost instantly after the onNewRingingConnection() // event. There's nothing we can do here, so just bail out // without doing anything. (But presumably we'll log it in // the call log when the disconnect event comes in...) return; } // Stop any signalInfo tone being played on receiving a Call stopSignalInfoTone(); Call.State state = c.getState(); // State will be either INCOMING or WAITING. if (VDBG) log("- connection is ringing! state = " + state); // if (DBG) PhoneUtils.dumpCallState(mPhone); // No need to do any service state checks here (like for // "emergency mode"), since in those states the SIM won't let // us get incoming connections in the first place. // TODO: Consider sending out a serialized broadcast Intent here // (maybe "ACTION_NEW_INCOMING_CALL"), *before* starting the // ringer and going to the in-call UI. The intent should contain // the caller-id info for the current connection, and say whether // it would be a "call waiting" call or a regular ringing call. // If anybody consumed the broadcast, we'd bail out without // ringing or bringing up the in-call UI. // // This would give 3rd party apps a chance to listen for (and // intercept) new ringing connections. An app could reject the // incoming call by consuming the broadcast and doing nothing, or // it could "pick up" the call (without any action by the user!) // via some future TelephonyManager API. // // See bug 1312336 for more details. // We'd need to protect this with a new "intercept incoming calls" // system permission. // Obtain a partial wake lock to make sure the CPU doesn't go to // sleep before we finish bringing up the InCallScreen. // (This will be upgraded soon to a full wake lock; see // showIncomingCall().) if (VDBG) log("Holding wake lock on new incoming connection."); mApplication.requestWakeState(PhoneApp.WakeState.PARTIAL); // - don't ring for call waiting connections // - do this before showing the incoming call panel if (PhoneUtils.isRealIncomingCall(state)) { startIncomingCallQuery(c); } else { if (PhoneUtils.PhoneSettings.vibCallWaiting(mApplication)) { mApplication.vibrate(200,300,500); } if (VDBG) log("- starting call waiting tone..."); if (mCallWaitingTonePlayer == null) { mCallWaitingTonePlayer = new InCallTonePlayer(InCallTonePlayer.TONE_CALL_WAITING); mCallWaitingTonePlayer.start(); } // in this case, just fall through like before, and call // showIncomingCall(). if (DBG) log("- showing incoming call (this is a WAITING call)..."); showIncomingCall(); } // Note we *don't* post a status bar notification here, since // we're not necessarily ready to actually show the incoming call // to the user. (For calls in the INCOMING state, at least, we // still need to run a caller-id query, and we may not even ring // at all if the "send directly to voicemail" flag is set.) // // Instead, we update the notification (and potentially launch the // InCallScreen) from the showIncomingCall() method, which runs // when the caller-id query completes or times out. if (VDBG) log("- onNewRingingConnection() done."); }
2.拨号流程分析
拨号主要是从拨号盘按下call按键开始,进入OutgoingCallBroadcaster处理,
- 1楼oWintersun前天 16:17
- 学习 学习