RILJ对象的交互机制

RILJ交互机制:

GsmCdmaCallTracker与RILJ对象的交互完成的通话控制,以及通话状态和通话基本信息的保存,更新等操作,交互方式不用说就知道有两类:

  • CallTracker对象主动发起
  • CallTracker对象被动接收

接下来讲解一下我理解的流程:

GsmCdmaPhone作为一个Facade(门面)模式控制这三个Tracker类分别是:GsmCdmaCallTracker(语音通话模型)和ServiceStateTracker(网络服务)和DcTracker(移动数据业务)处理,也是 数据下发的入口比如:dial (请求拨号),acceptCall(接听电话),rejectCall(拒接电话)等等..

 

主动发起

主动发起我们用rejectCall()(挂断方法)方法作为讲解:

先看一下流程图:

RILJ对象的交互机制_第1张图片

 

 

讲解:

首先电话发起一个挂断请求从Dialer->Telecom-TeleService->GsmCdmaPhone.java中调用rejectCall()这个方法表示挂断

GsmCdmaPhone.java

  @Override
    public void rejectCall() throws CallStateException {
        mCT.rejectCall();
    }

这里的mCT(GsmCdmaCallTracker.java类)。

 

GmsCdmaCallTracker.java

 //拒接电话
    public void rejectCall() throws CallStateException {
        // AT指令,通话保持或挂断电话
        // 非响领状态时,将挂断通话保持的电话
        if (mRingingCall.getState().isRinging()) {
            mCi.rejectCall(obtainCompleteMessage());//调用RIL对象的拒接来电请求方法
        } else {
            throw new CallStateException("phone not ringing");
        }
    }

这个方法我们重点讲解一下obtainCompleteMessage()方法他内部是创建一个Message消息进行返回

private Message obtainCompleteMessage() {
        return obtainCompleteMessage(EVENT_OPERATION_COMPLETE);
}
private Message obtainCompleteMessage(int what) {
        mPendingOperations++;
        mLastRelevantPoll = null;
        mNeedsPoll = true;

        if (DBG_POLL) log("obtainCompleteMessage: pendingOperations=" +
                mPendingOperations + ", needsPoll=" + mNeedsPoll);

        return obtainMessage(what);
    }

这里创建了一个Message对象

          GsmCdmaCallTracker对象首先调用obtainCompleteMessage创建Message消息对象接着调用RILJ对象中对应的通话控制方法,同时传递刚创建的Message消息对象作为回调参数。

在RIL中完成通话管理和通话控制后,RILJ对象发起ENEVT_OPERATION_COMPLETE类型的Handler Callback(回调)

@Override
    public void handleMessage(Message msg) {//接收并且处理RILJ发出的Handle消息 。handleMessge方法接收并响应RILJ对象发出的Handler消息。
     
        AsyncResult ar;
        switch (msg.what) {
            .......
            .....
            case EVENT_OPERATION_COMPLETE://有四个方法全是EVENT_OPERATION_COMPLETE  (dial,acceptCall,rejectCall,hangup)
                //最终还是获取了EVENT_POLL_CALLS_RESULT调用 handlePoolCalls()
                operationComplete();
            break;
        ....
        .......
}

      GsmCdmaCallTracker对象响应ENEVT_OPERATION_COMPLETE类型的Handler消息,将调用operationComplete()方法。那么我们来看看这个方法:

//与RILJ交互的回调处理
    private void operationComplete() {
        mPendingOperations--;

        if (DBG_POLL) log("operationComplete: pendingOperations=" +
                mPendingOperations + ", needsPoll=" + mNeedsPoll);

        if (mPendingOperations == 0 && mNeedsPoll) {
            //携带EVENT_POOL_CALLS_RESULT查询当前的CallList列表
            mLastRelevantPoll = obtainMessage(EVENT_POLL_CALLS_RESULT);//EVENT_POLL_CALLS_RESULT
            //获取最新状态  往底层发送消息连接成功了  携带  EVENT_POLL_CALLS_RESULT消息
            mCi.getCurrentCalls(mLastRelevantPoll);
        } else if (mPendingOperations < 0) {
            // this should never happen
            Rlog.e(LOG_TAG,"GsmCdmaCallTracker.pendingOperations < 0");
            mPendingOperations = 0;
        }
    }

这里很重要可以看到obtainMessage(EVENT_POLL_CALLS_RESULT)获取了Message消息对象,调用mCi.getCurrentCalls(mLastRelevantPoll)开始查询Call List列表

RIL.java

@Override
    public void getCurrentCalls(Message result) {
        IRadio radioProxy = getRadioProxy(result);//区别与7.0的代码,获取一个Radio代理进行通信
        if (radioProxy != null) {
            RILRequest rr = obtainRequest(RIL_REQUEST_GET_CURRENT_CALLS, result,
                    mRILDefaultWorkSource);//创建一个请求消息
            if (RILJ_LOGD) {
                riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
            }
            try {
                radioProxy.getCurrentCalls(rr.mSerial);//向底层发起请求
            } catch (RemoteException | RuntimeException e) {
                handleRadioProxyExceptionForRR(rr, "getCurrentCalls", e);
            }
        }
    }

    在RIL完成查询Call List列表后,发起EVENT_POLL_CALL_RESULT类型的Handler消息,最终调用handlePollCalls()方法.

由于handlePollCalls()方法逻辑太多所以不展示于此

 

主动发起请求:

GsmCdmaCallTracker对象向RILJ对象发起两次请求第一次发起管理或者控制通话请求,第二次发起查询当前通话列表请求(就是获取Call Lit)。  RILJ对象处理的两次请求并且发起两次处理的结果的Callback消息回调,两次消息回调的Handler类型分别是EVENT_OPENACTION_COMPLETE 和 ENENT_POLL_CALLS_RESULT

 

 

被动接收

我们被动接收或者主动下发,首先我们先看一下GsmCdmaCallTracker里面的构造方法,他内部注册了三个消息:

public GsmCdmaCallTracker (GsmCdmaPhone phone) {
        this.mPhone = phone;
        mCi = phone.mCi;
        mCi.registerForCallStateChanged(this, EVENT_CALL_STATE_CHANGE, null);//注册EVENT_CALL_STATE_CHANGE 状态 通话状态变化
        mCi.registerForOn(this, EVENT_RADIO_AVAILABLE, null);                //EVENT_RADIO_AVAILABLE无线通信模块可用状态
        mCi.registerForNotAvailable(this, EVENT_RADIO_NOT_AVAILABLE, null);  //EVENT_RADIO_NOT_AVAILABLE 无线通信模块不可用状态
        .......
    }

这里向RILJ注册了三种类型的Handler消息,我们这里只看EVENT_CALL_STATE_CHANGE状态

先来看一下初始化注册流程图:

RILJ对象的交互机制_第2张图片

 

这一块开机启动TeleService的过程就会注册这些Hanler就拿EVENT_CALL_STATE_CHANGE变化状态。

 

接下来我们来看一下被动接收Handle消息
首先来看一下流程图:

 

RILJ对象的交互机制_第3张图片

 

被动接收通话状态变化的消息处理流程,仅仅只表现在RILJ与GsmCdmaCallTracker两个对象之间的交互流程,共有两次交互过程:

  • 第一次交互过程
    RILJ对象向GsmCdmaCallTracker对象发起了EVENT_CALL_STATE_CHANGE类型的Handler Callback消息通知。
  • 第二次交互过程
    GsmCdmaCallTracker对象调用mCi.getCurrentCalls方法,采用Handler消息回调的处理方式查询当前最新的Call List列表
  1. 步骤一,Radio的回调
  2. 步骤二,通知GsmCdmaCallTracker中的Handler,他注册的位置可以查看上面从初始化流程。
  3. 步骤三,进入Handler Message携带这一个EVENT_CALL_STATE_CHANGE消息进行匹配选择 Handle内部会调用pollCallsWhenSafe()方法
  4. 步骤四,调用父类的CallTracker 里面的pollCallWhenSafe()方法首先会生成EVENT_POLL_CALLS_RESULT类型的Handler消息消息对象,接着使用此对象作为参数发起mCi.getCurrentCalls调用,向RILJ对象发出查询最新的Call List列表消息
  5. 步骤五,mCi.getCurrentCalls调用,向RILJ对象发出查询最新的Call List列表消息
  6. 步骤六,在RIL中完成查询Call List列表后,发起EVENT_POLL_CALLS_RESULT类型的HandlerCallback消息回调
  7. 步骤七,GsmCdmaCallTracker对象最终调用handlerPollCalls方法响应EVENT_POLL_CALLS_RESULT类型的Handler消息

 

代码流程:

GsmCdmaCallTracker.java
内部的Handler

 public void handleMessage(Message msg) {//接收并且处理RILJ发出的Handle消息 。handleMessge方法接收并响应RILJ对象发出的Handler消息。
        AsyncResult ar;
           switch (msg.what) {  
                ......
                case EVENT_CALL_STATE_CHANGE: //来电入口 通话状态改变 等等....
                    pollCallsWhenSafe();
                break;
                .......
                .........
}

这里对应着步骤三     进入pollCallsWhenSafe()方法

CallTracker.java

/**
     * 当Voice Call状态和Radio状态发生改变是,RILJ对象会向GsmCdmaCallTracker对象发出三个( EVENT_CALL_STATE_CHANGE , EVENT_RADIO_AVAILABLE ,EVENT_RADIO_NOT_AVAILABLE)
     * 对应的Handle消息;GsmCdmaCallTracker对象接收到这三个类型的Handler消息后,最后创建一个Message消息对象,在调用mCi.getCurrentCalls()方法,
     * 向RILJ对象查询当前Call List(通话列表)。
     */
    protected void pollCallsWhenSafe() { //向RIL发起getCurrentCalls查询CallList调用
        mNeedsPoll = true;
        if (checkNoOperationsPending()) {
            mLastRelevantPoll = obtainMessage(EVENT_POLL_CALLS_RESULT);//创建Message消息对象
            //去查询当前的Call情况,此方法会调用到RIL中对应的方法去(Phone 创建的时候对mCi进行初始化,使得具有RIL通信功能,其mCi就调用的是RIL.java)
            mCi.getCurrentCalls(mLastRelevantPoll); //这里携带这一个消息 EVENT_POLL_CALLS_RESULT 获取Call List
        }
    }

调用父类的CallTracker 里面的pollCallWhenSafe()方法首先会生成EVENT_POLL_CALLS_RESULT类型的Handler消息消息对象,接着使用此对象作为参数发起mCi.getCurrentCalls调用,向RILJ对象发出查询最新的Call List列表消息

 

 public void handleMessage(Message msg) {//接收并且处理RILJ发出的Handle消息 。handleMessge方法接收并响应RILJ对象发出的Handler消息。
        AsyncResult ar;
        switch (msg.what) {
            case EVENT_POLL_CALLS_RESULT:
                Rlog.d(LOG_TAG, "Event EVENT_POLL_CALLS_RESULT Received");
                Log.v("TelephonyFlowsendAck","GsmCdmaCallTracker  handleMessage EVENT_POLL_CALLS_RESULT 处理4种状态后,通知 phone 更新状态。");
                if (msg == mLastRelevantPoll) {
                    if (DBG_POLL) log(
                            "handle EVENT_POLL_CALL_RESULT: set needsPoll=F");
                    mNeedsPoll = false;
                    mLastRelevantPoll = null;
                    handlePollCalls((AsyncResult)msg.obj);//handlePollCalls 处理4种状态后,通知 phone 更新状态。
                }
            break;
        }
}

这里对应着组后一步

 

 

结语:
这篇文章为了提高TelephonyFramework的流程收悉度,特此做笔记记下来,如果有问题请提出做修改,也可以讨论噢,谢谢!

你可能感兴趣的:(RILJ对象的交互机制)