当前位置: 代码迷 >> Android >> Android 4.0 Phone拨号跟来电流程分析
  详细解决方案

Android 4.0 Phone拨号跟来电流程分析

热度:57   发布时间:2016-05-01 14:59:46.0
Android 4.0 Phone拨号和来电流程分析


本文只对应用层进行分析

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
学习 学习
  相关解决方案