精华内容
下载资源
问答
  • 流程图: 来电流程其实不需要看

     

    流程图:

    来电流程其实不需要看

    展开全文
  • Android6.0来电流程

    2018-02-20 11:12:15
    发出来电通知(frameworks\opt\telephony) 1. framwork/opt/telephony/…/RIL.java作用:RIL-Java在本质上就是一个RIL代理,起到一个转发的作用,是Android Java概念空间中的电话系统的起点...

    先放出6.0的MT时序图大家有个直观感受,下面代码一步步进行分析

    这里写图片描述

    第一部分:RIL–>GSMPhone Call状态变化 -> 发出来电通知(frameworks\opt\telephony)

    1. framwork/opt/telephony/…/RIL.java

    作用:RIL-Java在本质上就是一个RIL代理,起到一个转发的作用,是Android Java概念空间中的电话系统的起点。 
    RIL接收到RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED消息

    private void processUnsolicited (Parcel p) {
    ...
    switch(response) {
    ...
    case RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED:
                    if (RILJ_LOGD) unsljLog(response);
     2、然后经由mCallStateRegistrants.notifyRegistrants发出通知
                   mCallStateRegistrants.notifyRegistrants(new AsyncResult(null, null, null));
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    BaseCommands.Java registerForCallStateChanged() mCallStateRegistrants.add(r);

     @Override
        public void registerForCallStateChanged(Handler h, int what, Object obj) {
            Registrant r = new Registrant (h, what, obj);
    //添加到观察者列表 
            mCallStateRegistrants.add(r);
        }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    重点1:这其实是观察者模式的一种实现形式 
    1.RefistrantList 通知者 2.Registrant 观察者,这是一个一对多的关系,在有事件更新时,凡是在名单上登记过的对象,都会收到通知。 
    RegistrantList通知者支持对通知者的增加(add/addUnique)删除(remove),并且能够发出通知(notifyRegitrants);而Registrant作为观察者,响应通知者发出的notifyRegistrant通知。 
    整体上这个消息注册机制分为两部分,消息注册和消息通知。当调用regist方法时将Message存放进去,当其调用notify方法时将所有Message取出并发送到MessageQueue中等待处理。

    3. framwork/opt/telephony/…GSMCallTracker.java

    作用:GSMCallTracker在本质上是一个Handler。GSMCallTracker是Android的通话管理层。GSMCallTracker建立了ConnectionList来管理现行的通话连接,并向上层提供电话调用接口。 
    查找察者被调用的地方, 两处被响应处理处理,其中一处:GSMCallTracker handleMessage

    ...//registerForCallStateChanged调用
     mCi.registerForCallStateChanged(this, EVENT_CALL_STATE_CHANGE, null);
    ...
     @Override
        public void
    //响应处理
        handleMessage (Message msg) {
    ...
     case EVENT_CALL_STATE_CHANGE: //MT第一次
    //调用父类CallTracker查询Call List方法
         pollCallsWhenSafe();
         break;
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    4、pollCallsWhenSafe()方法在CallTracker.java中实现

    protected void pollCallsWhenSafe() {
    
            mNeedsPoll = true;
    
            if (checkNoOperationsPending()) {
                mLastRelevantPoll = obtainMessage(EVENT_POLL_CALLS_RESULT);
        5//RIL.java中的getCurrentCalls方法  
                mCi.getCurrentCalls(mLastRelevantPoll);
            }
        }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    回到RIL.java getCurrentCalls 将RIL_REQUEST_GET_CURRENT_CALLS 消息封装成RILRequest 
    类型并发送。

    @Override
        public void getCurrentCalls (Message result) {
            RILRequest rr = RILRequest.obtain(RIL_REQUEST_GET_CURRENT_CALLS, result);
            send(rr);
        }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 1
    • 2
    • 3
    • 4
    • 5
    • 1
    • 2
    • 3
    • 4
    • 5

    RIL.java 有三处接收处理RIL_REQUEST_GET_CURRENT_CALLS消息,真正的逻辑处理在processSolicited方法

    private RILRequest processSolicited (Parcel p) {
    ...
    case RIL_REQUEST_GET_CURRENT_CALLS: ret =  responseCallList(p); break;
    ...
    if (rr.mResult != null) {
                        AsyncResult.forMessage(rr.mResult, ret, null);
                        rr.mResult.sendToTarget();//发出handler消息通知
                    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    6、回到framworks/opt/telephony/…/telephony/gsm/GSMCallTracker.java

    rr.mResult.sendToTarget()发出handler消息通知后,会在GSMCallTracker中的handleMessage方法中响应。并且它的消息类型是“EVENT_POLL_CALLS_RESULT”

    @Override
        public void handleMessage (Message msg) {
            ...
            case EVENT_POLL_CALLS_RESULT:
                    ar = (AsyncResult)msg.obj;
                    if (msg == mLastRelevantPoll) {
                        mNeedsPoll = false;
                        mLastRelevantPoll = null;
             7、        handlePollCalls((AsyncResult)msg.obj);
                    }
                break;
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    8、handlePollCalls方法根据RIL发出的Call List对象判断Call的状态,并发出不同的通知,

    1) 新来电的通知是: phone.notifyNewRingingConnection; 
    另外两个是 
    2) 通话断开通知 onDisconnected; 
    3) Call状态变化通知 phone.notifiyPreciseCallStateChanged. 
    (当状态改变之后便会通过GsmPhone的notifyPreciseCallStateChanged()方法发起响应) 
    来电的时候发出的是phone.notifyNewRingConnection通知,进入到notifyNewRingConnection方法

    handlePollCalls(){
    ...
    if (newRinging != null) {
                mPhone.notifyNewRingingConnection(newRinging);
            }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 1
    • 2
    • 3
    • 4
    • 5
    • 1
    • 2
    • 3
    • 4
    • 5

    9、framworks/opt/telephony/…/telephony/gsm/GSMPhone.java

     public void notifyNewRingingConnection(Connection c) {
            super.notifyNewRingingConnectionP(c);
        }
    • 1
    • 2
    • 3
    • 1
    • 2
    • 3
    • 1
    • 2
    • 3

    调用父类 PhoneBase.java(为com.android.internal.telephony.phone接口实现。) 
    notifyNewRingingConnectionP()发出来电通知 mNewRingingConnectionRegistrants.notifyRegistrants(ar);

    /**
         * Notify registrants of a new ringing Connection.
         * Subclasses of Phone probably want to replace this with a
         * version scoped to their packages
         */
        public void notifyNewRingingConnectionP(Connection cn) {
            if (!mIsVoiceCapable)
                return;
            AsyncResult ar = new AsyncResult(null, cn, null);
            mNewRingingConnectionRegistrants.notifyRegistrants(ar);
        }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    重点2: RegistrantList.java \frameworks\base\core\java\android\os 
    notifyRegistrants方法实现

        public /*synchronized*/ void notifyRegistrants(AsyncResult ar){
            internalNotifyRegistrants(ar.result, ar.exception);
        }
        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);
           }
        }
        /*package*/ 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);
            }
        }   
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    注册为观察者的方法为:

    // Inherited documentation suffices.
        @Override
        public void registerForNewRingingConnection(
                Handler h, int what, Object obj) {
            checkCorrectThread(h);
    
            mNewRingingConnectionRegistrants.addUnique(h, what, obj);
        }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    通过log发现PstnIncomingCallNotifier.java调用registerForNewRingingConnection()

    01-05 07:10:05.517962  1596  1596 D Telephony: PstnIncomingCallNotifier: handleNewRingingConnection
    • 1
    • 1
    • 1

    第二部分:PstnIncomingCallNotifier–>Call 接收Framework层到通知–>准备创建连接

    10、packages/services/Telephony/…/PstnIncomingCallNotifier.java(packages\services\telephony)

    作用:监听来之相关电话对象的来电事件和通知Telecom在每次发生的时候,这一实例的存在为了每个电话的通话服务

    registerForNotifications方法调用registerForNewRingingConnection

        private void registerForNotifications() {
            Phone newPhone = mPhoneProxy.getActivePhone();
            if (newPhone != mPhoneBase) {
                unregisterForNotifications();
    
                if (newPhone != null) {
                    Log.i(this, "Registering: %s", newPhone);
                    mPhoneBase = newPhone;
                    //调用registerForNewRingingConnection方法
                    mPhoneBase.registerForNewRingingConnection(
                            mHandler, EVENT_NEW_RINGING_CONNECTION, null);
                    mPhoneBase.registerForCallWaiting(
                            mHandler, EVENT_CDMA_CALL_WAITING, null);
                    mPhoneBase.registerForUnknownConnection(mHandler, EVENT_UNKNOWN_CONNECTION,
                            null);
                }
            }
        }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    11、handle 处理EVENT_NEW_RINGING_CONNECTION消息

    private final Handler mHandler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
            ...
                case EVENT_NEW_RINGING_CONNECTION:
                        handleNewRingingConnection((AsyncResult) msg.obj);
                        break;
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    12、从之前的log看: 由handleNewRingingConnection方法,处理新的来电连接。

        private void handleNewRingingConnection(AsyncResult asyncResult) {
            Log.d(this, "handleNewRingingConnection");
            Connection connection = (Connection) asyncResult.result;
            if (connection != null) {
                Call call = connection.getCall();
    
                //在发送intent到Telecom之前最后一次验证ringing 状态
                if (call != null && call.getState().isRinging()) {
                    sendIncomingCallIntent(connection);
                }
            }
        }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    13、sendIncomingCallIntent方法

    发送incoming 
    call intent到telecom,发送的Connection 类型,里面包括isIncoming getState isRinging等

        /**
         * Sends the incoming call intent to telecom.
         */
        private void sendIncomingCallIntent(Connection connection) {
            Bundle extras = null;
            if (connection.getNumberPresentation() == TelecomManager.PRESENTATION_ALLOWED &&
                    !TextUtils.isEmpty(connection.getAddress())) {
                extras = new Bundle();
                Uri uri = Uri.fromParts(PhoneAccount.SCHEME_TEL, connection.getAddress(), null);
                extras.putParcelable(TelephonyManager.EXTRA_INCOMING_NUMBER, uri);
            }
            TelecomManager.from(mPhoneProxy.getContext()).addNewIncomingCall(
                    TelecomAccountRegistry.makePstnPhoneAccountHandle(mPhoneProxy), extras);
        }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    14、addNewIncomingCall()定义在: framworks/base/telecomm/java/android/telecom/TelecomManager.java

    作用:TelecomManager的功能则主要是对TelecomService提供的远程接口的封装,然后提供给应用使用。 
    来电时触发 addNewIncomingCall方法

    
        @SystemApi
        public void addNewIncomingCall(PhoneAccountHandle phoneAccount, Bundle extras) {
            try {
                if (isServiceConnected()) {
                    getTelecomService().addNewIncomingCall(
                            phoneAccount, extras == null ? new Bundle() : extras);
                }
            } catch (RemoteException e) {
                Log.e(TAG, "RemoteException adding a new incoming call: " + phoneAccount, e);
            }
        }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    15、 packages/services/Telecomm/src/com/android/server/telecom/TelecomServiceImpl.java

    继承自ITelecomService,TelecomService的接口由TeleComManager封装,并其供给应用使用, 
    重点2:telecom进程讲解 
    addNewIncomingCall 
    新建intent 设定intent 的ACTION 、addFalgs等

            /**
             * @see android.telecom.TelecomManager#addNewIncomingCall
             */
            @Override
            public void addNewIncomingCall(PhoneAccountHandle phoneAccountHandle, Bundle extras) {
                synchronized (mLock) {
                        long token = Binder.clearCallingIdentity();
                        try {
                            Intent intent = new Intent(TelecomManager.ACTION_INCOMING_CALL);
                            intent.putExtra(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE,
                                phoneAccountHandle);
                            intent.putExtra(CallIntentProcessor.KEY_IS_INCOMING_CALL, true);
                            if (extras != null) {
                                intent.putExtra(TelecomManager.EXTRA_INCOMING_CALL_EXTRAS, extras);
                            }
                            CallIntentProcessor.processIncomingCallIntent(mCallsManager, intent);
                        } finally {
                            Binder.restoreCallingIdentity(token);
                        }
                }
            }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    CallIntentProcessor.java (packages\services\telecomm\src\com\android\server\telecom)

        static void processIncomingCallIntent(CallsManager callsManager, Intent intent) {
            callsManager.processIncomingCallIntent(phoneAccountHandle, clientExtras);
        }
    • 1
    • 2
    • 3
    • 1
    • 2
    • 3
    • 1
    • 2
    • 3

    19、packages/services/Telecomm/src/com/android/server/telecom/CallsManager.java

    作用: 
    CallManager类提供了一个抽象层,以供phoneApp访问和控制call等操作。它实现了Phone接口。CallManager提供呼叫和连接控制以及Channel能力。CallManager提供三种类型的API: 
    1,呼叫控制和操作,如dial()和hangup(); 
    2,Channel的能力,如canconference(); 
    3,注册通知。接着将Phone注册进mCM,Phone状态改变之后InCallUI就能够收到变化消息了。

        void processIncomingCallIntent(PhoneAccountHandle phoneAccountHandle, Bundle extras) {
            ....
            Call call = new Call(
                    mContext,
                    this,
                    mLock,
                    mConnectionServiceRepository,
                    mContactsAsyncHelper,
                    mCallerInfoAsyncQueryFactory,
                    handle,
                    null /* gatewayInfo */,
                    null /* connectionManagerPhoneAccount */,
                    phoneAccountHandle,
                    true /* isIncoming */,
                    false /* isConference */);
            call.setIntentExtras(extras);
            call.addListener(this);
    20、new一个Call 对象 把前面的参数传进来,然后调用call中建立连接的方法startCreateConnection
            call.startCreateConnection(mPhoneAccountRegistrar);
        }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    21、packages/services/Telecomm/src/com/android/server/telecom/Call.java

    作用:封装的一个给定的电话在其整个生命周期的各个方面,从电话意图被telecom接收开始 
    开始建立连接队列,一旦完成创建,就应当有一个活动active的连接了存在service里。

        void startCreateConnection(PhoneAccountRegistrar phoneAccountRegistrar) {
            Preconditions.checkState(mCreateConnectionProcessor == null);
            mCreateConnectionProcessor = new CreateConnectionProcessor(this, mRepository, this,
                    phoneAccountRegistrar, mContext);
            mCreateConnectionProcessor.process();
        }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    第三部分:ConnectionServicesAdapter–>CallsManager 处理这个创建的连接–>成功来电 CallsManager–>Phone 成功来电–>准备启动界面

    22、packages/services/Telecomm/src/com/android/server/telecom/CreateConnectionProcessor.java

        void process() {
            Log.v(this, "process");
            clearTimeout();
            mAttemptRecords = new ArrayList<>();
            if (mCall.getTargetPhoneAccount() != null) {
                mAttemptRecords.add(new CallAttemptRecord(
                        mCall.getTargetPhoneAccount(), mCall.getTargetPhoneAccount()));
            }
            adjustAttemptsForConnectionManager();
            adjustAttemptsForEmergency();
            mAttemptRecordIterator = mAttemptRecords.iterator();
            attemptNextPhoneAccount();
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    23、service试图建立连接

    private void attemptNextPhoneAccount() {
    ...
    if (mResponse != null && attempt != null) {
                Log.i(this, "Trying attempt %s", attempt);
                ConnectionServiceWrapper service =
                        mRepository.getService(
                                attempt.connectionManagerPhoneAccount.getComponentName());
                if (service == null) {
                    Log.i(this, "Found no connection service for attempt %s", attempt);
                    attemptNextPhoneAccount();
                } else {
                    mCall.setConnectionManagerPhoneAccount(attempt.connectionManagerPhoneAccount);
                    mCall.setTargetPhoneAccount(attempt.targetPhoneAccount);
                    mCall.setConnectionService(service);
                    Log.i(this, "Attempting to call from %s", service.getComponentName());
                    service.createConnection(mCall, new Response(service));
                }
            } 
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    24、packages/services/Telecomm/src/com/android/server/telecom/ConnectionServiceWrapper.java 为拨出的电话建立连接,或者attach一个已经存在的来电。

        void createConnection(final Call call, final CreateConnectionResponse response) {
            mBinder.bind(callback);
        }
    • 1
    • 2
    • 3
    • 1
    • 2
    • 3
    • 1
    • 2
    • 3

    25、ServiceBinder.java (packages\services\telecomm\src\com\android\server\telecom)

    作用:抽象类用来进行绑定和解除绑定到指定的服务接口的工作。子类提供服务的意图和组件名称和这个类调用受保护方法在类绑定,未绑定或者失败的时候 
    执行绑定到服务的操作(如果还没有绑定)然后执行指定的回调方法

           void bind(BindCallback callback, Call call) {
                Log.d(ServiceBinder.this, "bind()");
                // Reset any abort request if we're asked to bind again.
                clearAbort();
                if (!mCallbacks.isEmpty()) {
                    // Binding already in progress, append to the list of callbacks and bail out.
                    mCallbacks.add(callback);
                    return;
                }
                mCallbacks.add(callback);
                if (mServiceConnection == null) {
                    Intent serviceIntent = new Intent(mServiceAction).setComponent(mComponentName);
                    ServiceConnection connection = new ServiceBinderConnection(call);
                    Log.event(call, Log.Events.BIND_CS, mComponentName);
                    final int bindingFlags = Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE;
                    final boolean isBound;
                    if (mUserHandle != null) {
                        isBound = mContext.bindServiceAsUser(serviceIntent, connection, bindingFlags,
                                mUserHandle);
                    } else {
                        isBound = mContext.bindService(serviceIntent, connection, bindingFlags);
                    }
                    if (!isBound) {
                        handleFailedConnection();
                        return;
                    }
                } else {
                    Log.d(ServiceBinder.this, "Service is already bound.");
                    Preconditions.checkNotNull(mBinder);
                    handleSuccessfulConnection();
                }
            }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    26、上面的执行完之后,顺序执行到onServiceConnected

    onServiceConnected

     private final class ServiceBinderConnection implements ServiceConnection {
            @Override
            public void onServiceConnected(ComponentName componentName, IBinder binder) {
                ThreadUtil.checkOnMainThread();
                Log.i(this, "Service bound %s", componentName);//这句log被打印出来了
                // Unbind request was queued so unbind immediately.
                if (mIsBindingAborted) {
                    clearAbort();
                    logServiceDisconnected("onServiceConnected");
                    mContext.unbindService(this);
                    handleFailedConnection();
                    return;
                }
                mServiceConnection = this;
                setBinder(binder);
                handleSuccessfulConnection();
            }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    27、

        private void handleSuccessfulConnection() {
            for (BindCallback callback : mCallbacks) {
                callback.onSuccess();
            }
            mCallbacks.clear();
        }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    28、回调上面的onSuccess() 执行mServiceInterface.createConnectioncreateConnection的具体实现在ConnectionService.java (frameworks\base\telecomm\java\android\telecom)

    作用:一个提供电话连接到Android设备上运行的进程。

            @Override
            public void createConnection(
                    PhoneAccountHandle connectionManagerPhoneAccount,
                    String id,
                    ConnectionRequest request,
                    boolean isIncoming,
                    boolean isUnknown) {
                //chengzhi
                SomeArgs args = SomeArgs.obtain();
                args.arg1 = connectionManagerPhoneAccount;
                args.arg2 = id;
                args.arg3 = request;
                args.argi1 = isIncoming ? 1 : 0;
                args.argi2 = isUnknown ? 1 : 0;
    29、        mHandler.obtainMessage(MSG_CREATE_CONNECTION, args).sendToTarget();
            }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    30、

    case MSG_CREATE_CONNECTION: {
                             createConnection(
                                        connectionManagerPhoneAccount,
                                        id,
                                        request,
                                        isIncoming,
                                        isUnknown);
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    31、这个方法可以被telecom用来创建呼出电话或者一个已存在的来电。任何一种情况,telecom都会循环经过一系列的服务和 调用createConnection util a connection service取消或者成功完成创建。

        private void createConnection(
                final PhoneAccountHandle callManagerAccount,
                final String callId,
                final ConnectionRequest request,
                boolean isIncoming,
                boolean isUnknown) {
            Connection connection = isUnknown ? onCreateUnknownConnection(callManagerAccount, request)
                    : isIncoming ? onCreateIncomingConnection(callManagerAccount, request)
                    : onCreateOutgoingConnection(callManagerAccount, request);
            .....
            mAdapter.handleCreateConnectionComplete
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    32、前面建立连接成功了,后面处理成功的连接,后面执行mAdapter.handleCreateConnectionComplete

    ConnectionServiceAdapter>CallsManager 处理这个创建的连接>成功来电

    33~34.ConnectionServiceAdapter.java (frameworks\base\telecomm\java\android\telecom)

    作用:提供iconnectionservice实现与系统的手机应用程序的交互方法。

        void handleCreateConnectionComplete(
                String id,
                ConnectionRequest request,
                ParcelableConnection connection) {
            for (IConnectionServiceAdapter adapter : mAdapters) {
                try {
                    //chengzhi 03
                    adapter.handleCreateConnectionComplete(id, request, connection);
                } catch (RemoteException e) {
                }
            }
        }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    CallsManager>Phone 成功来电>准备启动界面

    34. packages/services/Telecomm/src/com/android/server/telecom/ConnectionServiceWrapper.java

    作用:Telecomm 层的连接管理者

        private final class Adapter extends IConnectionServiceAdapter.Stub {
    
            @Override
            public void handleCreateConnectionComplete(
                    String callId,
                    ConnectionRequest request,
                    ParcelableConnection connection) {
                logIncoming("handleCreateConnectionComplete %s", request);
                        if (mCallIdMapper.isValidCallId(callId)) {
                            ConnectionServiceWrapper.this
                                    .handleCreateConnectionComplete(callId, request, connection);
                        }
            }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    ConnectionServiceAdapterServant.java (frameworks\base\telecomm\java\android\telecom)

        private final IConnectionServiceAdapter mStub = new IConnectionServiceAdapter.Stub() {
            @Override
            public void handleCreateConnectionComplete(
                    String id,
                    ConnectionRequest request,
                    ParcelableConnection connection) {
                SomeArgs args = SomeArgs.obtain();
                args.arg1 = id;
                args.arg2 = request;
                args.arg3 = connection;
                mHandler.obtainMessage(MSG_HANDLE_CREATE_CONNECTION_COMPLETE, args).sendToTarget();
            }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    34、 handleMessage处理消息 MSG_HANDLE_CREATE_CONNECTION_COMPLETE

            // Internal method defined to centralize handling of RemoteException
            private void internalHandleMessage(Message msg) throws RemoteException {
                switch (msg.what) {
                    case MSG_HANDLE_CREATE_CONNECTION_COMPLETE: {
                        SomeArgs args = (SomeArgs) msg.obj;
                        try {
                            mDelegate.handleCreateConnectionComplete(
                                    (String) args.arg1,
                                    (ConnectionRequest) args.arg2,
                                    (ParcelableConnection) args.arg3);
                        } finally {
                            args.recycle();
                        }
                        break;
                    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    35、 如果成功连接 ConnectionServiceWrapper.java (packages\services\telecomm\src\com\android\server\telecom)

        private void handleCreateConnectionComplete(
                String callId,
                ConnectionRequest request,
                ParcelableConnection connection) {
            // TODO: Note we are not using parameter "request", which is a side effect of our tacit
            // assumption that we have at most one outgoing connection attempt per ConnectionService.
            // This may not continue to be the case.
            if (connection.getState() == Connection.STATE_DISCONNECTED) {
                // A connection that begins in the DISCONNECTED state is an indication of
                // failure to connect; we handle all failures uniformly
                removeCall(callId, connection.getDisconnectCause());
            } else {
                // Successful connection
                if (mPendingResponses.containsKey(callId)) {
                    mPendingResponses.remove(callId)
                            .handleCreateConnectionSuccess(mCallIdMapper, connection);
                }
            }
        }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    重写 handleCreateConnectionSuccess方法

    36. packages/services/Telecomm/src/com/android/server/telecom/Call.java handleCreateConnetionSucess()

    @Override
        public void handleCreateConnectionSuccess(
                CallIdMapper idMapper,
                ParcelableConnection connection) {
            Log.v(this, "handleCreateConnectionSuccessful %s", connection);
            mCreateConnectionProcessor = null;
            setTargetPhoneAccount(connection.getPhoneAccount());
            setHandle(connection.getHandle(), connection.getHandlePresentation());
            setCallerDisplayName(
                    connection.getCallerDisplayName(), connection.getCallerDisplayNamePresentation());
            setCallCapabilities(connection.getCapabilities());
            setVideoProvider(connection.getVideoProvider());
            setVideoState(connection.getVideoState());
            setRingbackRequested(connection.isRingbackRequested());
            setIsVoipAudioMode(connection.getIsVoipAudioMode());
            setStatusHints(connection.getStatusHints());
    
            mConferenceableCalls.clear();
            for (String id : connection.getConferenceableConnectionIds()) {
                mConferenceableCalls.add(idMapper.getCall(id));
            }
    
            if (mIsUnknown) {
                for (Listener l : mListeners) {
                    l.onSuccessfulUnknownCall(this, getStateFromConnectionState(connection.getState()));
                }
            } else if (mIsIncoming) {
                // We do not handle incoming calls immediately when they are verified by the connection
                // service. We allow the caller-info-query code to execute first so that we can read the
                // direct-to-voicemail  property before deciding if we want to show the incoming call to
                // the user or if we want to reject the call.
                mDirectToVoicemailQueryPending = true;
    
                // Timeout the direct-to-voicemail lookup execution so that we dont wait too long before
                // showing the user the incoming call screen.
                mHandler.postDelayed(mDirectToVoicemailRunnable, Timeouts.getDirectToVoicemailMillis(
                        mContext.getContentResolver()));
            } else {
                for (Listener l : mListeners) {
                    l.onSuccessfulOutgoingCall(this,
                            getStateFromConnectionState(connection.getState()));
                }
            }
        }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    37、 Runnable mDirectToVoicemailRunnable

        private final Runnable mDirectToVoicemailRunnable = new Runnable() {
            @Override
            public void run() {
                processDirectToVoicemail();
            }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 1
    • 2
    • 3
    • 4
    • 5
    • 1
    • 2
    • 3
    • 4
    • 5

    38、processDirectToVoicemail

    final class Call implements CreateConnectionResponse {
        /**
         * Listener for events on the call.
         */
        interface Listener {
            void onSuccessfulIncomingCall(Call call);
    ...
        private void processDirectToVoicemail() {
            if (mDirectToVoicemailQueryPending) {
                if (mCallerInfo != null && mCallerInfo.shouldSendToVoicemail) {
                    Log.i(this, "Directing call to voicemail: %s.", this);
                    // TODO: Once we move State handling from CallsManager to Call, we
                    // will not need to set STATE_RINGING state prior to calling reject.
                    setState(CallState.RINGING);
                    reject(false, null);
                } else {
                    // TODO: Make this class (not CallsManager) responsible for changing
                    // the call state to STATE_RINGING.
                    // TODO: Replace this with state transition to STATE_RINGING.
                    for (Listener l : mListeners) {
                        l.onSuccessfulIncomingCall(this);
                    }
                }
                mDirectToVoicemailQueryPending = false;
            }
        }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    39. package/services/Telecomm/src/com/android/server/telecom/CallsManager.java

    39.1@Override onSuccessfulIncomingCall if 判断后 addCall()

    public final class CallsManager extends Call.ListenerBase {
    ...
        @Override
        public void onSuccessfulIncomingCall(Call incomingCall) {
            Log.d(this, "onSuccessfulIncomingCall");
            setCallState(incomingCall, CallState.RINGING);
    
            if (hasMaximumRingingCalls(incomingCall.getTargetPhoneAccount().getId())) {
                incomingCall.reject(false, null);
                // since the call was not added to the list of calls, we have to call the missed
                // call notifier and the call logger manually.
                mMissedCallNotifier.showMissedCallNotification(incomingCall);
                mCallLogManager.logCall(incomingCall, Calls.MISSED_TYPE);
            } else {
                incomingCall.mIsActiveSub = true;
                addCall(incomingCall);
                setActiveSubscription(incomingCall.getTargetPhoneAccount().getId());
            }
        }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    39.2 addCall()

        /**
         * Adds the specified call to the main list of live calls.
         *
         * @param call The call to add.
         */
        private void addCall(Call call) {
            Log.v(this, "addCall(%s)", call);
    
            call.addListener(this);
            mCalls.add(call);
    
            // TODO: Update mForegroundCall prior to invoking
            // onCallAdded for calls which immediately take the foreground (like the first call).
            for (CallsManagerListener listener : mListeners) {
                listener.onCallAdded(call);
            }
            updateForegroundCall();
        }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    第四部分:CallList–>InCallActivity 开始启动界面 –>显示来电

    40、package/services/Telecomm/src/com/android/server/telecom/InCallController.java

    作用:结合并提供服务,通过它可以将更新发送到呼叫程序。这类被创建和拥有的callsmanager保持绑定到(被调用的应用程序中实现)。

    重写onCallAdded –>

        @Override
        public void onCallAdded(Call call) {
            if (!isBoundToServices()) {
                bindToServices(call);
            } else {
                adjustServiceBindingsForEmergency();
                Log.i(this, "onCallAdded: %s", call);
                // Track the call if we don't already know about it.
                addCall(call);
                for (Map.Entry<ComponentName, IInCallService> entry : mInCallServices.entrySet()) {
                    ComponentName componentName = entry.getKey();
                    IInCallService inCallService = entry.getValue();
                    ParcelableCall parcelableCall = toParcelableCall(call,
                            true /* includeVideoProvider */);
                    try {
                        inCallService.addCall(parcelableCall);
                    } catch (RemoteException ignored) {
                    }
                }
            }
        }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    41、bindToServices – bindToInCallService

        InCallServiceConnection inCallServiceConnection = new InCallServiceConnection();
    
        private class InCallServiceConnection implements ServiceConnection {
            /** {@inheritDoc} */
            @Override public void onServiceConnected(ComponentName name, IBinder service) {
                Log.d(this, "onServiceConnected: %s", name);
                onConnected(name, service);
            }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    42 、

        private void onConnected(ComponentName componentName, IBinder service) {
            addCall(call);
        }
    • 1
    • 2
    • 3
    • 1
    • 2
    • 3
    • 1
    • 2
    • 3

    43. framworks/base/telecomm/java/android/telecom/InCallService.java

    作用:这个服务可以被任何希望提供管理电话的用户界面的应用实现, 
    当那个服务存在一个电话telecom就去绑定这个服务并用它去通知任何活动状态和最近断开的呼叫的被调用的应用 
    @Override 
    addCall()

        /** Manages the binder calls so that the implementor does not need to deal with it. */
        private final class InCallServiceBinder extends IInCallService.Stub {
            @Override
            public void setInCallAdapter(IInCallAdapter inCallAdapter) {
                mHandler.obtainMessage(MSG_SET_IN_CALL_ADAPTER, inCallAdapter).sendToTarget();
            }
    
            @Override
            public void addCall(ParcelableCall call) {
                mHandler.obtainMessage(MSG_ADD_CALL, call).sendToTarget();
            }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    44. handleMessage 处理消息 MSG_ADD_CALL

        /** Default Handler used to consolidate binder method calls onto a single thread. */
        private final Handler mHandler = new Handler(Looper.getMainLooper()) {
            @Override
            public void handleMessage(Message msg) {
                if (mPhone == null && msg.what != MSG_SET_IN_CALL_ADAPTER) {
                    return;
                }
    
                switch (msg.what) {
                    case MSG_SET_IN_CALL_ADAPTER:
                        mPhone = new Phone(new InCallAdapter((IInCallAdapter) msg.obj));
                        onPhoneCreated(mPhone);
                        break;
                    case MSG_ADD_CALL:
                        mPhone.internalAddCall((ParcelableCall) msg.obj);
                        break;
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    45. framworks/base/telecomm/java/android/telecom/Phone.java

    作用:一个统一的虚拟设备提供语音手段(和其他)设备上的通信。 
    internalAddCall()

        final void internalAddCall(ParcelableCall parcelableCall) {
            Call call = new Call(this, parcelableCall.getId(), mInCallAdapter,
                    parcelableCall.mIsActiveSub);
            mCallByTelecomCallId.put(parcelableCall.getId(), call);
            mCalls.add(call);
            checkCallTree(parcelableCall);
            call.internalUpdate(parcelableCall, mCallByTelecomCallId);
            fireCallAdded(call);
         }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    45.1 fireCallAdded()

        private void fireCallAdded(Call call) {
            for (Listener listener : mListeners) {
                listener.onCallAdded(this, call);
            }
        }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 1
    • 2
    • 3
    • 4
    • 5
    • 1
    • 2
    • 3
    • 4
    • 5

    46、onCallAdded()@SystemApi系统Api,一个空的实现方法 其他使用的地方会 @Override

    @SystemApi
    public final class Phone {
    
        public abstract static class Listener {
        ...
        public void onCallAdded(Phone phone, Call call) { }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    47. pacakge/apps/InCallUI/src/com/android/incallui/CallList.java

    作用:保持主动呼叫的列表和通知感兴趣的类关于这个列表的变化,因为他们是从堆栈收到电话, 
    对这个类变化的主要听众是InCallPresenter 
    @Override 
    onCallAdded

        /**
         * Static singleton accessor method.
         */
        public static CallList getInstance() {
            return sInstance;
        }
    
        private Phone.Listener mPhoneListener = new Phone.Listener() {
            @Override
            public void onCallAdded(Phone phone, android.telecom.Call telecommCall) {
                Call call = new Call(telecommCall);
                if (call.getState() == Call.State.INCOMING) {
                    onIncoming(call, call.getCannedSmsResponses());
                } else {
                    onUpdate(call);
                }
            }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    48、执行了下面的方法,但再往后的步骤不是从这里走的。

    onIncoming()

        /**
         * Called when a single call has changed.
         */
        public void onIncoming(Call call, List<String> textMessages) {
            Log.d(this, "onIncoming - " + call);
    
            // Update active subscription from call object. it will be set by
            // Telecomm service for incoming call and whenever active sub changes.
            if (call.mIsActiveSub) {
                long sub = call.getSubId();
                Log.d(this, "onIncoming - sub:" + sub + " mSubId:" + mSubId);
                if (sub != mSubId) {
                    setActiveSubscription(sub);
                }
            }
    
            if (updateCallInMap(call)) {
                Log.i(this, "onIncoming - " + call);
            }
            updateCallTextMap(call, textMessages);
    
            for (Listener listener : mListeners) {
                listener.onIncomingCall(call);
            }
        }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    49. //pacakge/apps/InCallUI/src/com/android/incallui/InCallPresenter.java

    作用:接受来至CallList的更新并通知InCallActivity(UI)的变化。负责为一个新的呼叫启动活动和当通话断开时结束activity

    onIncomingCall是一个接口以下是它的实现

        /**
         * Called when there is a new incoming call.
         *
         * @param call
         */
        @Override
        public void onIncomingCall(Call call) {
            InCallState newState = startOrFinishUi(InCallState.INCOMING);
            InCallState oldState = mInCallState;
    
            Log.i(this, "Phone switching state: " + oldState + " -> " + newState);
            mInCallState = newState;
    
            for (IncomingCallListener listener : mIncomingCallListeners) {
                listener.onIncomingCall(oldState, mInCallState, call);
            }
    
            if (CallList.getInstance().isDsdaEnabled() && (mInCallActivity != null)) {
                mInCallActivity.updateDsdaTab();
            }
        }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    50、startUi

      showInCall(false /* showDialpad */, !showAccountPicker /* newOutgoingCall */);
    • 1
    • 1
    • 1

    51、showInCall

        public void showInCall(final boolean showDialpad, final boolean newOutgoingCall) {
            Log.i(this, "Showing InCallActivity");
            mContext.startActivity(getInCallIntent(showDialpad, newOutgoingCall));
        }
    • 1
    • 2
    • 3
    • 4
    • 1
    • 2
    • 3
    • 4
    • 1
    • 2
    • 3
    • 4

    总结

    以下是MT流程的类图,我们就根据这个图做下最后总结

    这里写图片描述

    展开全文
  • Android电话来电流程源码分析

    千次阅读 2013-08-21 10:50:18
    Android的Phone设计的相当复杂,只有了解了Phone的设计框架才能把握电话的拨号或来电流程,在Android电话拨打流程源码分析中已经分析介绍了电话拨打流程,这里介绍一下电话的来电流程。 要理解这节内容,首先要知道...

    Android的Phone设计的相当复杂,只有了解了Phone的设计框架才能把握电话的拨号或来电流程,在Android电话拨打流程源码分析中已经分析介绍了电话拨打流程,这里介绍一下电话的来电流程。

    要理解这节内容,首先要知道Android电话的层次设计


    Framework层的RIL中的RILReceiver线程从rild服务进程中读取modem发送上来的来电消息等信息,通过消息注册-响应机制来通知上层处理,上图清晰地显示了各层之间的消息处理关系,CallManager连接Framework层和应用层的Phone,

    CallManager处理GSMPhone注册的消息事件,并且触发CallManager注册的消息事件,而CallNotifier处理CallManager消息,这样就将RIL层的消息一级一级传送的应用层的Phone了。

    RIL层事件注册过程

    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。
    frameworks\base\telephony\java\com\android\internal\telephony\gsm\ GsmCallTracker.java 
    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动态数组中。
    frameworks\base\core\java\android\os\RegistrantList.java

    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状态的,即来电状态

    Phone层事件注册过程

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

    mCM = CallManager.getInstance();
    mCM.registerPhone(phone);
    函数registerPhone为构造的相应类型的phone对象注册一些事件
    frameworks\base\telephony\java\com\android\internal\telephony\CallManager.java
    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来处理这些消息。

    CallManager层事件注册过程

    在启动PhoneApp时,同样也会创建一个CallNotifier对象
    notifier = CallNotifier.init(this, phone, ringer, mBtHandsfree, new CallLogAsync());
    参数phone是通过PhoneFactory.getDefaultPhone()创建而来的,创建过程在前面已经详细介绍了。
    参数ringer的构造过程如下:
    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;
        }
    }
    CallNotifier对象构造过程:
    packages\apps\Phone\src\com\android\phone\CallNotifier.java
    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);
    }
    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类的消息注册方法:


    电话状态改变事件处理

    我们已经知道在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处理该消息。
    frameworks\base\core\java\android\os\Registrant.java
    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类表示。

    这里介绍一下RILRequest数据结构

    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);

    展开全文
  • Android_Phone源代码来电流程解读
  • Android的Phone设计的相当复杂,只有了解了Phone的设计框架才能把握电话的拨号或来电流程,在Android电话拨打流程源码分析中已经分析介绍了电话拨打流程,这里介绍一下电话的来电流程。 要理解这节内容,首先要知道...
  • Android O来电call流程

    2019-06-18 17:38:25
    Version:1.0 StartHTML:0000000194 EndHTML:0000209014 StartFragment:0000024273 EndFragment:0000208974 SourceURL:file:///Y:\Desktop\学习\新建文件夹\%5bAndroid%20O...Android O来电call流程 frameworkte...
  • Android N 来电流程(MT)

    千次阅读 2017-01-06 14:06:06
    流程图基于MTK平台 Android N,普通来电,本流程只作为沟通学习使用本篇文章写作顺序是从modem上报消息,一层一层上报到incallUI,读者可以根据需求选择阅读顺序。frameworks/opt/telephony/当对方拨打电话后,...
  • Android5.0 来电流程

    2015-06-04 13:21:32
    1.从Framework开始: RIL.java接受到状态改变信号开始:
  • 文章:《Android 4.4 Kitkat Phone工作流程浅析(七)__来电(MT)响铃流程》中涉及的时序图 http://blog.csdn.net/yihongyuelan/article/details/24640819
  •  下面是响铃之后到接听的流程  首先,加入是通过Touch接听  通过Touch,首先触发的是InCallTouchUi类,当移到接听位置后,由于InCallScreen实现了OnTouchListener,  所以将会出发InCallScreen的handl...
  • Android 8.0来电流程分析(二)

    千次阅读 2018-02-07 17:39:06
    Telephony-Service 1.上篇分析到PstnIncommingCallNotifier 中handleMessage处理来电消息,继续跟进分析 switch (msg.what) { case EVENT_NEW_RINGING_CONNECTION: handleNewRingi
  • Android 8.0来电流程分析(一)

    千次阅读 多人点赞 2018-01-21 11:19:10
    来电时底层会上报消息到RIL层,在Android8.0上目前已经做了修改,不再使用Socket进行通信,而是使用ril_service服务进行通信,O的系统上引入了HIDL机制,telephony的framework层引用底层的服务就用到了此机制,这也...
  • Android 8.0来电流程分析(三)

    千次阅读 2018-02-08 15:34:11
    2.这里用到了迭代器模式,一个来电触发三个对象的处理, 最后创建一个IncomingCallFilter并调用performFiltering public void performFiltering () { Log.addEvent(mCall, LogUtils.Events....
  • Android系统通话模块,来电和去电流程分析,从app层到framework层。
  • 今天就被一个问题困扰了一下午--来电后按声音按键需要静音!因为是双Phone对象所以对应的RINGER也有两个! 分析一下解BUG流程! 最开始以为按键处理会在InCallScreen.java里面的 [code="java"] ...
  • CallNotifier构造方法中调用registerForNotifications() 方法,触发PHONE_INCOMING_RINGprivate void registerForNotifications() {mCM.registerForIncomingRing(this, PHONE_INCOMING_RING, null);...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 4,165
精华内容 1,666
关键字:

android来电流程