Android 7.0 IMS框架详解

本文主要讲解IP Multimedia Subsystem (IMS)在Android 7.0上由谷歌Android实现的部分内容。 
从APP侧一直到Telephony Framework,是不区分CS流程还是PS流程的。到了Telephony Framework模块,会依据IMS相关的状态信息(Registration Status,Service Status等)和用户设置信息(Volte Enable?Wifi Calling Enable?UT Enable?等 )进而判断出,Call、SMS等是否需要优先走IMS的流程。 
整体来看,IMS框架如下图: 
《Android 7.0 IMS框架详解》
通常都是由Phone对象或者ImsPhoneCallTracker对象直接得到ImsManager对象

mImsManager = ImsManager.getInstance(mPhone.getContext(), mPhone.getPhoneId());
  • 1
  • 1

接着再通过ImsManager对象间接地得到ImsConfig、ImsUt、ImsCall等重要对象,然后根据请求不同而走不同的通道与Vendor RIL通信,与Call相关的走ImsCall,与补充业务相关的走ImsUt,与IMS功能的能力、参数相关的走ImsConfig,所以分工是十分明确的。谷歌为了规范高通/MTK等芯片厂商的行为,所以定义了IImsService、IImsConfig、IImsCallSession和IImsUt等接口,再由各芯片厂商来实现这些接口,谷歌只需要处理好上层调用接口的逻辑即可。

http://blog.csdn.net/linyongan 

接下来分别讲一下各个类

ImsPhone

ImsPhone是为了与CS Call区分开,用来处理IMS相关事务的Phone实例,以setCallWaiting为例:

    public void setCallWaiting(boolean enable, Message onComplete) {
        if (isPhoneTypeGsm()) {
            Phone imsPhone = mImsPhone;
            //判断是否符合IMS的条件
            if ((imsPhone != null)
                    && ((imsPhone.getServiceState().getState() == ServiceState.STATE_IN_SERVICE)
                    || imsPhone.isUtEnabled())) {
                //走IMS流程
                imsPhone.setCallWaiting(enable, onComplete);
                return;
            }
            //走CS流程
            mCi.setCallWaiting(enable, CommandsInterface.SERVICE_CLASS_VOICE, onComplete);
        } else {
            loge("method setCallWaiting is NOT supported in CDMA!");
        }
    }
  • 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

然而仅仅有Phone实例是不够的,还需要有对应地CallTracker、Call以及Connection对象,所以就有了下面这张图: 
《Android 7.0 IMS框架详解》
ImsPhone实例是在IMS Service启动之后被创建的,接着会初始化ImsPhoneCallTracker对象。

ImsPhoneCallTracker

ImsPhoneCallTracker在初始化的时候会注册监听IMS InComing call

intentfilter.addAction(ImsManager.ACTION_IMS_INCOMING_CALL);
  • 1
  • 1

同时将Action为“ACTION_IMS_INCOMING_CALL”的PendingIntent传递给IMS Service,这样子就可以监听到IMS MT Call了。

ImsPhoneCallTracker内部会初始化四个ImsPhoneCall对象,

    public ImsPhoneCall mRingingCall = new ImsPhoneCall(this, ImsPhoneCall.CONTEXT_RINGING);
    public ImsPhoneCall mForegroundCall = new ImsPhoneCall(this,
            ImsPhoneCall.CONTEXT_FOREGROUND);
    public ImsPhoneCall mBackgroundCall = new ImsPhoneCall(this,
            ImsPhoneCall.CONTEXT_BACKGROUND);
    public ImsPhoneCall mHandoverCall = new ImsPhoneCall(this, ImsPhoneCall.CONTEXT_HANDOVER);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

比GsmCdmaCallTracker多了一个Handover Call,比如VoWiFi与VoLTE相互切换就是通过Handover来实现的。

还有一点ImsPhoneCallTracker与GsmCdmaCallTracker不一样的就是

    protected void handlePollCalls(AsyncResult ar) {
    }
  • 1
  • 2
  • 1
  • 2

ImsPhoneCallTracker的handlePollCalls()方法是空的,是因为IMS Call状态消息的上报和获取modem当前Call List信息等这些逻辑需要高通/MTK来实现,ImsPhoneCallTracker则通过ImsCall.Listener来监听Ims Call的状态变化信息,然后再根据ImsCall的状态,更新当前ImsPhoneConnection与四种ImsPhoneCall的绑定关系。 
比如: 
1. A<—>B正在通话,这通电话对应的Connection会与mForegroundCall绑定; 
2. 此时A再呼叫C,那么A<—>B这通电话的Connection就会先与mBackgroundCall绑定,这种切换是由mBackgroundCall与mForegroundCall互换Connection集合和状态实现的;

mForegroundCall.switchWith(mBackgroundCall);
  • 1
  • 1

3.然后A<—>C接通之后,A<—>C这通电话对应的Connection会与mForegroundCall绑定。 
就是这样子。每个ImsPhoneCall最多绑定5个ImsPhoneConnection,这个值规定在ImsPhoneCallTracker中:

static final int MAX_CONNECTIONS_PER_CALL = 5;
  • 1
  • 1

ImsPhoneCallTracker还负责监听IMS service的状态变化

private ImsConnectionStateListener mImsConnectionStateListener =
        new ImsConnectionStateListener() {
        //IMS已注册上
        public void onImsConnected() {}
        //IMS已断开,有时候会上报断开的原因
        public void onImsDisconnected(ImsReasonInfo imsReasonInfo) {}
        //IMS处于正在注册状态
        public void onImsProgressing() {}
        //"VoLTE", "ViLTE", "VoWiFi", "ViWiFi",
        //"UTLTE", "UTWiFi"等功能的能力变化
        public void onFeatureCapabilityChanged() {}
        ......
}
  • 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

如果遇到IMS注册不上的问题,应该去看IMS注册时的SIP信令流程。 
《Android 7.0 IMS框架详解》
备注:此图来自网络。

ImsManager

ImsManager作为IMS框架的核心,是任意IMS action的出发点。ImsManager的职责主要有以下3点: 
1. 向上提供ImsConfig、ImsUt、ImsCall等重要对象,得到这些对象就可以跟Vendor RIL通信了。

 public ImsUtInterface getSupplementaryServiceConfiguration(){}
 public ImsConfig getConfigInterface(){}
 public ImsCall makeCall(){}
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

2 .向APP提供设置IMS相关功能的接口

//设置VoLTE打开或者关闭
public static void setVtSetting(Context context, boolean enabled) {}
//设置WiFi Calling打开或者关闭
public static void setWfcSetting(Context context, boolean enabled) {}
//设置WiFi Calling的模式,如WiFi Only、WiFi优先...
public static void setWfcMode(Context context, int wfcMode) {}
//设置4G LTE增强模式打开或者关闭
public static void setEnhanced4gLteModeSetting(Context context, boolean enabled) {}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

3.向上传递IMS注册状态变化的消息,是由ImsManager来通知ImsPhoneCallTracker的。

ImsService

谷歌定义好了ImsServiceBase抽象类和IImsService接口,接着由芯片厂商实现ImsService。 
ImsConfig、ImsUt、ImsCall等对象最终是依靠ImsService来创建的, 
由此可见,其他三种通信方式都是依赖着ImsService的。

ImsManager—>ImsService—>Vendor RIL 
这种通信方式主要用来通知modem turn on/off Ims。 
使用场景就是在VoLTE、WFC和Advanced4GMode等功能被用户手动enable/disable时,就要响应地通知modem turn on/off Ims了。

ImsConfig

ImsManager—>ImsConfig—>Vendor RIL 
ImsConfig主要就是提供接口给上层动态地去控制IMS功能的能力、参数等。 
ImsConfig类中虽然只有7个方法,但是功能强大,特别是下面几个方法

public int getProvisionedValue();
public int setProvisionedValue();
public String getProvisionedStringValue();
public int setProvisionedStringValue();
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

这些方法为开发者打开了一扇大门!通向底层NV的大门!(不同芯片厂商可能有差异)比如,在UI界面上点击了打开WFC的按钮,就可以间接地修改到NV的某一项。 
目前Android 7.0中支持的NV只有几十个,但是这并不能满足OEM所有的需求,所以有时候还需扩展这个接口。

还有就是,如果要开发IMS接口的话,建议也是加在这里,其他通道都不太合适。

ImsCall

ImsManager—>ImsCall—>ImsCallSession—>Vendor RIL 
这个就很明显了,这条通道是专门处理IMS Call相关事务的,创建ImsCall的方式有两种: 
1. IMS MO Call时,通过ImsManager.makeCall()来创建; 
2. IMS MT Call时,通过ImsManager.takeCall()来创建。 
在ImsCall中,每个对Call操作的方法(accept/reject/hold/resume/merge等等)都会有对应的回调方法:

    /** * @see Listener#onCallResumed, Listener#onCallResumeFailed */
    public void resume(){
        ......
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

如果resume成功则通过onCallResumed()方法通知上层,如果resume失败则通过onCallResumeFailed()方法通知上层,一般的流程如下:

ImsPhoneCallTrackerImsPhoneCallTrackerImsCallImsCallVendor RILVendor RILresume()resume()Vendor RIL处理onCallResumed()

ImsUt

ImsManager—>ImsUt—>Vendor RIL 
这条通道是专门提供向上提供设置补充业务接口的,如呼叫转移、呼叫限制、呼叫等待、outgoing Caller Id display等等。

最后,更多关于IMS的内容,请查阅如下协议文档: 
– GSMA IR.92 : features for voice and sms profile 
– GSMA IR.94 : video calling feature 
– 3GPP TS 24.229 : IMS call control (SIP and SDP) 
– 3GPP TS 26.114 : IMS media handling and interaction 
– 3GPP TS 26.111 : Codec for CS multimedia telephony service (H.324) 

– 3GPP TS 24.623 : XCAP over the Ut interface for manipulating supplementary services

原文地址: http://blog.csdn.net/linyongan/article/details/53350493

    原文作者:Omni-Space
    原文地址: https://blog.csdn.net/omnispace/article/details/69951919
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞