zoukankan      html  css  js  c++  java
  • MTK IMS框架简析(2)——IMS注册过程

    本文链接:https://blog.csdn.net/meiliqiang/article/details/78501947, 感谢作者

    MTK IMS框架简析(2)——IMS注册过程

    标签: Phone  IMS

     
     

    之前在《MTK IMS框架简析(1)——代码架构及模块初始化》 中已经分析了ims代码的构成和重点类的初始化,接下来以启用VOLTE子功能为例,具体分析AP侧IMS服务的注册过程。


    概要

    IMS注册前提是系统启用了volte或wifi calling等功能,Volte开关一般在网络设置界面会提供(如下图),用户切换开关状态将触发ims的注册或注销。 
    这里写图片描述

    启用Volte后的消息传递序列(这里时序图避免复杂化,只表现消息的正向传递,忽略消息的返回)

    frameworkframeworkims appims apprild imsrild imsvolte_imsmvolte_imsmrildrildTurn on IMS feature打开IMS子功能RIL_REQUEST_SET_VOLTE_ENABLERIL_REQUEST_SET_IMS_VOICE_ENABLERIL_REQUEST_SET_IMS_ENABLERIL_UNSOL_IMS_ENABLE_STARTIMS_SERVICE_UPMSG_ID_IMS_ENABLE_INDMSG_ID_WRAP_IMSM_IMSPA_PDN_ACT_REQRequest Network建立IMS承载SETUP_DATA_CALL(ims apn)MSG_ID_WRAP_IMSPA_IMSM_PDN_ACT_ACK_RESP成功建立承载RIL_UNSOL_IMS_REGISTRATION_INFO上报IMS注册状态

    整个过程大致分为3步: 
    1. 设置并启用ims 
    2. 建立ims承载 
    3. 注册ims服务 
    接下来结合代码详细分析。


    IMS注册过程

    从界面启用IMS

    此过程会向rild-ims下发3个消息,通知rild需要打开哪些ims业务,然后开启ims服务:

    1.  
      //启用volte语音服务
    2.  
      RIL_REQUEST_SET_VOLTE_ENABLE
    3.  
      RIL_REQUEST_SET_IMS_VOICE_ENABLE
    4.  
      //启动ims功能
    5.  
      RIL_REQUEST_SET_IMS_ENABLE
    • 1
    • 2
    • 3
    • 4
    • 5

    这里就从用户打开界面开关开始分析。 
    ImsManager::setAdvanced4GMode方法为volte功能的开关,设置界面即通过此接口实现volte开关。 
    1. 向ImsConfig设置了feature(ImsConfig::setFeatureValue) 
    2. 打开ims (turnOnIms)。

    1.  
      //ImsManager.java
    2.  
      private void setAdvanced4GMode(boolean turnOn) throws ImsException {
    3.  
      checkAndThrowExceptionIfServiceUnavailable();
    4.  
      try {
    5.  
      ImsConfig config = getConfigInterface();
    6.  
      if (config != null) {
    7.  
      //设置启用volte语音
    8.  
      config.setFeatureValue(ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_LTE,
    9.  
      TelephonyManager.NETWORK_TYPE_LTE, turnOn ? 1 : 0, null);
    10.  
      }
    11.  
      } catch (ImsException e) {
    12.  
      }
    13.  
      //启用ims服务
    14.  
      if (turnOn) {
    15.  
      turnOnIms();
    16.  
      } else if (isImsTurnOffAllowed()) {
    17.  
      turnOffIms();
    18.  
      }
    19.  
      }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    ImsConfig::setFeatureValue 作用是告诉ril目前要启用ims的哪些功能. 
    当前讨论的例子是打开volte,因此参数为”FEATURE_TYPE_VOICE_OVER_LTE”。 
    其他业务的定义在ImsConfig.java中:

    1.  
      //ImsConfig.java
    2.  
      public static class FeatureConstants {
    3.  
      public static final int FEATURE_TYPE_UNKNOWN = -1;
    4.  
       
    5.  
      /**
    6.  
      * FEATURE_TYPE_VOLTE supports features defined in 3GPP and
    7.  
      * GSMA IR.92 over LTE.
    8.  
      */
    9.  
      public static final int FEATURE_TYPE_VOICE_OVER_LTE = 0;
    10.  
       
    11.  
      /**
    12.  
      * FEATURE_TYPE_LVC supports features defined in 3GPP and
    13.  
      * GSMA IR.94 over LTE.
    14.  
      */
    15.  
      public static final int FEATURE_TYPE_VIDEO_OVER_LTE = 1;
    16.  
       
    17.  
      /**
    18.  
      * FEATURE_TYPE_VOICE_OVER_WIFI supports features defined in 3GPP and
    19.  
      * GSMA IR.92 over WiFi.
    20.  
      */
    21.  
      public static final int FEATURE_TYPE_VOICE_OVER_WIFI = 2;
    22.  
       
    23.  
      /**
    24.  
      * FEATURE_TYPE_VIDEO_OVER_WIFI supports features defined in 3GPP and
    25.  
      * GSMA IR.94 over WiFi.
    26.  
      */
    27.  
      public static final int FEATURE_TYPE_VIDEO_OVER_WIFI = 3;
    28.  
      }
    • 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

    ImsConfig实际上是ims app/ImsConfigImpl的代理,setFeatureValue方法具体逻辑在ImsConfigImpl中。 
    这里传入的feature为FEATURE_TYPE_VOICE_OVER_LTE,因此会向rild-ims下发2个消息:RIL_REQUEST_SET_VOLTE_ENABLE及RIL_REQUEST_SET_IMS_VOICE_ENABLE。

    1.  
      //ImsConfigImpl.java
    2.  
      public void setFeatureValue(int feature, int network, int value, ImsConfigListener listener) {
    3.  
      try {
    4.  
      try {
    5.  
      //将设置值保存到数据库
    6.  
      mStorage.setFeatureValue(feature, network, value);
    7.  
      //不同的feature需要不同的设置,这里只分析volte的处理
    8.  
      switch(feature) {
    9.  
      case ImsConfig.FeatureConstants.FEATURE_TYPE_VIDEO_OVER_LTE:
    10.  
      case ImsConfig.FeatureConstants.FEATURE_TYPE_VIDEO_OVER_WIFI:
    11.  
      ...
    12.  
      break;
    13.  
      case ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_WIFI:
    14.  
      ...
    15.  
      break;
    16.  
      case ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_LTE:
    17.  
      int oldVoLTEValue = SystemProperties.getInt(PROPERTY_VOLTE_ENALBE, 0);
    18.  
      int wfcEnable = SystemProperties.getInt(PROPERTY_WFC_ENALBE, 0);
    19.  
      if (value != oldVoLTEValue) {
    20.  
      //打开
    21.  
      if (value == ImsConfig.FeatureValueConstants.ON) {
    22.  
      //设置property
    23.  
      SystemProperties.set(PROPERTY_VOLTE_ENALBE,"1");
    24.  
      //向rild-ims下发RIL_REQUEST_SET_VOLTE_ENABLE
    25.  
      mRilAdapter.turnOnVolte(null);
    26.  
      if (wfcEnable == 0){
    27.  
      //向rild-ims下发RIL_REQUEST_SET_IMS_VOICE_ENABLE
    28.  
      mRilAdapter.turnOnImsVoice(null);
    29.  
      }
    30.  
      } else {//关闭
    31.  
      SystemProperties.set(PROPERTY_VOLTE_ENALBE,"0");
    32.  
      mRilAdapter.turnOffVolte(null);
    33.  
      if (wfcEnable == 0){
    34.  
      mRilAdapter.turnOffImsVoice(null);
    35.  
      }
    36.  
      }
    37.  
      }
    38.  
      break;
    39.  
      default:
    40.  
      break;
    41.  
      }
    42.  
      ...
    43.  
      } catch (ImsException e) {
    44.  
      ...
    45.  
      }
    46.  
      } catch (RemoteException e) {
    47.  
      throw new RuntimeException(e);
    48.  
      }
    49.  
      }
    • 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
    • 45
    • 46
    • 47
    • 48
    • 49

    ImsConfig处理完成,继续执行ImsManager::turnOnIms,这同样是aidl调用,实际操作由ImsService.turnOnIms执行。

    1.  
      //ImsManager.java
    2.  
      private void turnOnIms() throws ImsException {
    3.  
      checkAndThrowExceptionIfServiceUnavailable();
    4.  
       
    5.  
      try {
    6.  
      mImsService.turnOnIms(mPhoneId);
    7.  
      } catch (RemoteException e) {
    8.  
      throw new ImsException("turnOnIms() ", e, ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
    9.  
      }
    10.  
      }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    turnOnIms同样是向rild-ims下发消息:RIL_REQUEST_SET_IMS_ENABLE。

    1.  
      //ImsService.java
    2.  
      @Override
    3.  
      public void turnOnIms(int phoneId) {
    4.  
      if (mActivePhoneId != phoneId) {
    5.  
      mActivePhoneId = phoneId;
    6.  
      }
    7.  
       
    8.  
      if (mImsState != PhoneConstants.IMS_STATE_ENABLE) {
    9.  
      mImsRILAdapter.turnOnIms(mHandler.obtainMessage(EVENT_SET_IMS_ENABLED_DONE));
    10.  
      mImsState = PhoneConstants.IMS_STATE_ENABLING;
    11.  
      } else {
    12.  
      }
    13.  
      }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    下发了这3条消息后,等待ImsRilAdapter上报RIL_UNSOL_IMS_ENABLE_START来确认IMS服务已经启用。 
    这里写图片描述

    ImsService在构造方法中注册了RIL_UNSOL_IMS_ENABLE_START消息的监听,消息上报后便会由它处理。

    1.  
      //ImsService.java
    2.  
      mImsRILAdapter.registerForImsEnableStart(mHandler, EVENT_IMS_ENABLING_URC, null);
    • 1
    • 2

    ImsService中对RIL_UNSOL_IMS_ENABLE_START的处理如下: 
    1. 发送ACTION_IMS_SERVICE_UP广播; 
    2. 调用enableImsAdapter()

    1.  
      //ImsService.java
    2.  
      case EVENT_IMS_ENABLING_URC:
    3.  
      //+EIMS: 1
    4.  
      if (mActivePhoneId != phoneId) {
    5.  
      mActivePhoneId = phoneId;
    6.  
      }
    7.  
      // notify AP Ims Service is up
    8.  
      intent = new Intent(ImsManager.ACTION_IMS_SERVICE_UP);
    9.  
      intent.putExtra(ImsManager.EXTRA_PHONE_ID, mActivePhoneId);
    10.  
      mContext.sendBroadcast(intent);
    11.  
      // enable ImsAdapter
    12.  
      enableImsAdapter();
    13.  
      mImsState = PhoneConstants.IMS_STATE_ENABLE;
    14.  
      break;
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    《MTK IMS框架简析(1)——代码架构及模块初始化》 中提到过,ACTION_IMS_SERVICE_UP会触发ImsPhone和相关telephony类的初始化,因此这里跳过。 
    而ImsAdatper的流程涉及到建立ims承载,在第二节中继续分析。

    以流程图小结这部分: 
    这里写图片描述


    建立IMS PDN连接

    在ims注册之前,需要建立专用的数据连接。连接的建立由volte_imsm.so来触发,与普通数据连接一样,通过ConnectivityManager请求网络,并由telephony发起SETUP_DATA_CALL。

    先了解下volte_imsm.so的作用。根据readme文件的描述,volte_imsm.so库用于建立承载,P-CSCF,鉴权等过程,MTK并没有开源:

    1.  
      #README
    2.  
      IMS relay module, handling NAS bearer, P-CSCF address discovery, IMS AKA and relay message among IMCB/IMSA/MAL modules
    3.  
       
    4.  
      WHAT IT DOES?
    5.  
      =============
    6.  
      handle the request from IMCB/IMSA/MAL module
    7.  
      Send the event to IMCB/IMSA/MAL module, and receive the Response
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    ims app负责与volte_imsm.so对接,一张图来表示相关的工作过程。 
    这里写图片描述

    VaSocketIO运作在线程中,负责维护socket和输入输出,循环从socket中读取消息交由ImsEventDispatcher。 
    ImsEventDispatcher根据消息的类型分发给对应的VaEventDispatcher处理。 
    实现了VaEventDispatcher的类共有4个,分别负责:通话,数据,补充业务还有Timer(具体作用尚需研究)。 
    ImsAdapter负责控制功能的总开关。

    大概清楚这块流程后,下面接着第一节的思路,继续分析ImsAdapter:enableImsAdapter()方法。

    1.  
      ImsAdapter.java
    2.  
      public void enableImsAdapter() {
    3.  
      synchronized (ImsEnabledThreadLock) {
    4.  
      if (!misImsAdapterEnabled) {
    5.  
      if (mIO.connectSocket() == true) {
    6.  
      //调用所有VaEventDispatcher的enableRequest方法
    7.  
      mImsEventDispatcher.enableRequest();
    8.  
      misImsAdapterEnabled = true;
    9.  
      synchronized (mIO.VaSocketIOThreadLock) {
    10.  
      mIO.VaSocketIOThreadLock.notify();
    11.  
      }
    12.  
      //启用ims栈(向volte_imsm下发一条消息)
    13.  
      enableImsStack();
    14.  
      } else {
    15.  
      sendMessageDelayed(
    16.  
      obtainMessage(MSG_IMSA_RETRY_IMS_ENABLE),
    17.  
      IMSA_RETRY_SOCKET_TIME);
    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

    DataDispatcher负责建立承载相关处理,直接看DataDispatcher.enableRequest()方法的处理: 
    注册DATA_CONNECTION_STATE_CHANGED和SIM_STATE_CHANGED的监听。监听这2个消息是为了维护ims的连接,响应Data和SIM卡的变动。

    1.  
      DataDispatcher.java
    2.  
      public void enableRequest() {
    3.  
      synchronized (mHandler) {
    4.  
      Arrays.fill(mSimStatus, false);
    5.  
      IntentFilter filter = new IntentFilter();
    6.  
      filter.addAction(TelephonyManager.ACTION_PRECISE_DATA_CONNECTION_STATE_CHANGED);
    7.  
      filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
    8.  
      mContext.registerReceiver(mBroadcastReceiver, filter);
    9.  
      mIsEnable = true;
    10.  
      }
    11.  
      }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    返回到ImsAdapter继续看enableImsStack()方法。从方法的命名上看,作用是启用ims栈, 
    向volte_imsm发送MSG_ID_IMS_ENABLE_IND消息:

    1.  
      private void enableImsStack() {
    2.  
      // Send IMS Enable to IMSM
    3.  
      VaEvent event = new VaEvent(Util.getDefaultVoltePhoneId(), MSG_ID_IMS_ENABLE_IND);
    4.  
      mIO.writeEvent(event);
    5.  
       
    6.  
      return;
    7.  
      }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    消息的定义如下:

    1.  
      int MSG_ID_IMS_ENABLE_IND = 900003; // MSG_ID_WRAP_IMSPA_IMSM_ENABLE_IND
    2.  
      int MSG_ID_IMS_DISABLE_IND = 900004; // MSG_ID_WRAP_IMSPA_IMSM_DISABLE_IND,
    • 1
    • 2

    从Log看,MSG_ID_WRAP_IMSPA_IMSM_ENABLE_IND消息的作用应该是初始化volte_imsm相关模块,VoLTE Stack/UA/REG等模块被初始化: 
    这里写图片描述

    volte_imsm随后会上报MSG_ID_WRAP_IMSM_IMSPA_PDN_ACT_REQ,通知上层发起IMS PDN连接,消息由DataDispatcher处理。 
    这里写图片描述

    消息分发到DataDispatcher::handleDefaultBearerActivationRequest方法: 
    将请求数据封装成TransactionParam,设置超时处理,最后调用requestNwRequest方法。这里能看到请求的apn类型是IMS。

    1.  
      DataDispatcher.java
    2.  
      private void handleDefaultBearerActivationRequest(VaEvent event) {
    3.  
      //apn type为IMS
    4.  
      String apnType = PhoneConstants.APN_TYPE_IMS;
    5.  
      int phoneId = event.getPhoneId();
    6.  
      //请求数据封装成TransactionParam
    7.  
      DataDispatcherUtil.PdnActivationInd actInd = mDataDispatcherUtil
    8.  
      .extractDefaultPdnActInd(event);
    9.  
      TransactionParam param = new TransactionParam(actInd.transactionId,
    10.  
      event.getRequestID(), phoneId, apnType);
    11.  
      ...
    12.  
      putTransaction(param);
    13.  
      if (apnType == PhoneConstants.APN_TYPE_IMS) {
    14.  
      int subId = SubscriptionManager.getSubIdUsingPhoneId(phoneId);
    15.  
      if (mSimStatus[phoneId] || subId > 0) {
    16.  
      mSimStatus[phoneId] = true;
    17.  
      //判断是否有合法的ims apn
    18.  
      if (!isImsApnExists(phoneId)) {
    19.  
      rejectDefaultBearerDataConnActivation(param, FAILCAUSE_UNKNOWN, 500);
    20.  
      return;
    21.  
      }
    22.  
      //设置超时,如果超过10秒没有进入开始连接的状态即触发
    23.  
      mHandler.removeMessages(MSG_ON_NOTIFY_ACTIVE_DATA_TIMEOUT);
    24.  
      mHandler.sendMessageDelayed(mHandler.obtainMessage(
    25.  
      MSG_ON_NOTIFY_ACTIVE_DATA_TIMEOUT, param),
    26.  
      MAX_NETWORK_ACTIVE_TIMEOUT_MS);
    27.  
      } else {
    28.  
      return;
    29.  
      }
    30.  
      }
    31.  
      //发起IMS连接请求
    32.  
      if (requestNwRequest(apnType, phoneId) < 0) {
    33.  
      rejectDefaultBearerDataConnActivation(param, FAILCAUSE_UNKNOWN, 0);
    34.  
      }
    35.  
      }
    • 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

    requestNwRequest方法实例化NetworkRequest并填充数据后,通过ConnectivityManager.requestNetwork发起连接请求。

    1.  
      private int requestNwRequest(String requestApnType, int phoneId) {
    2.  
      ...
    3.  
      NetworkCallback nwCb = mDataNetworkRequests[pos].nwCb;
    4.  
      Builder builder = new NetworkRequest.Builder();
    5.  
      //IMS & EIMS
    6.  
      builder.addCapability(APN_CAP_LIST[pos]);
    7.  
      builder.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
    8.  
      //指定为当前subId
    9.  
      builder.setNetworkSpecifier(String.valueOf(subId));
    10.  
      mDataNetworkRequests[pos].nwRequest = builder.build();
    11.  
      NetworkRequest nwRequest = mDataNetworkRequests[pos].nwRequest;
    12.  
      releaseNwRequest(requestApnType);
    13.  
      synchronized (mAPNStatuses) {
    14.  
      ApnStatus apnStatus = mAPNStatuses.get(requestApnType);
    15.  
      apnStatus.mName = requestApnType;//IMS
    16.  
      apnStatus.mStatus = TelephonyManager.DATA_DISCONNECTED;
    17.  
      apnStatus.isSendReq = true;
    18.  
      apnStatus.ifaceName = "";
    19.  
      //发起request
    20.  
      getConnectivityManager().requestNetwork(nwRequest, nwCb,
    21.  
      ConnectivityManager.MAX_NETWORK_REQUEST_TIMEOUT_MS);
    22.  
      }
    23.  
      ...
    24.  
       
    25.  
      return nRet;
    26.  
      }
    27.  
      private static final int[] APN_CAP_LIST = new int[] {
    28.  
      NetworkCapabilities.NET_CAPABILITY_IMS,
    29.  
      NetworkCapabilities.NET_CAPABILITY_EIMS
    30.  
      };
    • 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

    接下来SETUP_DATA_CALL的工作由ConnectivityService和telephony数据模块完成。返回成功后,检查手机的网络接口发现新建了一个Interface——ccmni4

    1.  
      root@x6:/ # ifconfig
    2.  
      lo Link encap:Local Loopback
    3.  
      inet addr:127.0.0.1 Mask:255.0.0.0
    4.  
      inet6 addr: ::1/128 Scope: Host
    5.  
      UP LOOPBACK RUNNING MTU:65536 Metric:1
    6.  
      RX packets:46 errors:0 dropped:0 overruns:0 frame:0
    7.  
      TX packets:46 errors:0 dropped:0 overruns:0 carrier:0
    8.  
      collisions:0 txqueuelen:0
    9.  
      RX bytes:3992 TX bytes:3992
    10.  
       
    11.  
      ccmni4 Link encap:Ethernet HWaddr 12:7A:92:06:07:BE
    12.  
      inet6 addr: 2409:8809:8590:da21:279:6506:7e0d:afdc/64 Scope: Global
    13.  
      inet6 addr: fe80::279:6506:7e0d:afdc/64 Scope: Link
    14.  
      UP RUNNING NOARP MTU:1410 Metric:1
    15.  
      RX packets:26 errors:0 dropped:0 overruns:0 frame:0
    16.  
      TX packets:29 errors:0 dropped:0 overruns:0 carrier:0
    17.  
      collisions:0 txqueuelen:1000
    18.  
      RX bytes:17494 TX bytes:18434
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    ccmni4是mtk在底层指定的ims默认承载接口的名称,连接建立后DataDispatcher还需要检查这个Interface的名字是否正确,最后发送ACT消息通知volte_imsm连接已经建立

    1.  
      //DataDispatcher.java
    2.  
      private static final String IMS_INTERFACE_NAME = "ccmni4";
    3.  
       
    4.  
      private void handleDefaultBearerActivationResponse(Network network, String type) {
    5.  
       
    6.  
      TransactionParam deacTrans = findTransaction
    7.  
      (VaConstants.MSG_ID_WRAP_IMSM_IMSPA_PDN_DEACT_REQ, type);
    8.  
      synchronized (mAPNStatuses) {
    9.  
      ApnStatus apnStatus = mAPNStatuses.get(type);
    10.  
      if (deacTrans == null) {
    11.  
      apnStatus.mStatus = TelephonyManager.DATA_CONNECTED;
    12.  
      ConnectivityManager cm = (ConnectivityManager) mContext
    13.  
      .getSystemService(Context.CONNECTIVITY_SERVICE);
    14.  
      LinkProperties mLink = cm.getLinkProperties(network);
    15.  
      ...
    16.  
      apnStatus.ifaceName = mLink.getInterfaceName();
    17.  
      //检查iface名字是否为"ccmni4"
    18.  
      if (IMS_INTERFACE_NAME.equals(apnStatus.ifaceName)
    19.  
      || EMERGENCY_INTERFACE_NAME.equals(apnStatus.ifaceName)) {
    20.  
      //发送MSG_ID_WRAP_IMSM_IMSPA_PDN_ACT_REQ通知volte_imsm
    21.  
      responseDefaultBearerDataConnActivated(
    22.  
      findTransaction(VaConstants.MSG_ID_WRAP_IMSM_IMSPA_PDN_ACT_REQ, type),
    23.  
      network.netId, apnStatus.ifaceName);
    24.  
      }
    25.  
      ...
    26.  
      }
    27.  
      ...
    28.  
      }
    29.  
      }
    • 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

    这里写图片描述

    这部分的代码量较多,理解了设计意图后其实结构和流程都比较简单,同样以流程图总结: 
    这里写图片描述


    注册IMS服务

    完成注册

    IMS注册基于SIP,这部分由ims核心模块处理,需要分析协议和模块设计,这里先不作深入探讨。 
    转载自网络

    注册成功后,返回200 OK。 
    这里写图片描述

    rild_ims将注册状态及capability通过RIL_UNSOL_IMS_REGISTRATION_INFO消息上报: 
    这里写图片描述 
    ImsService在构造方法中注册过对RIL_UNSOL_IMS_REGISTRATION_INFO的监听,因此处理方法就在ImsService的handler中能找到。

     mImsRILAdapter.registerForImsRegistrationInfo(mHandler, EVENT_IMS_REGISTRATION_INFO, null);
    • 1

    ImsService 处理: 
    从EVENT_IMS_REGISTRATION_INFO中读取到ims注册状态和Capability,并通知监听者。

    1.  
      //ImsService.java
    2.  
      //IMS所支持的capability
    3.  
      private static final int IMS_VOICE_OVER_LTE = 1;
    4.  
      private static final int IMS_RCS_OVER_LTE = 2;
    5.  
      private static final int IMS_SMS_OVER_LTE = 4;
    6.  
      private static final int IMS_VIDEO_OVER_LTE = 8;
    7.  
      private static final int IMS_VOICE_OVER_WIFI = 16;
    8.  
       
    9.  
      public void handleMessage(Message msg) {
    10.  
      AsyncResult ar;
    11.  
      Intent intent;
    12.  
      int phoneId = getMainCapabilityPhoneId();
    13.  
      switch (msg.what) {
    14.  
      case EVENT_IMS_REGISTRATION_INFO:
    15.  
      ar = (AsyncResult) msg.obj;
    16.  
      //根据协议的规定,CIREGU返回消息的第一字段表示注册状态,第二个表示capability
    17.  
      /**
    18.  
      * According to 3GPP TS 27.007 +CIREGU format
    19.  
      *
    20.  
      * AsyncResult.result is an Object[]
    21.  
      * ((Object[])AsyncResult.result)[0] is integer type to indicate the IMS regiration status.
    22.  
      * 0: not registered
    23.  
      * 1: registered
    24.  
      * ((Object[])AsyncResult.result)[1] is numeric value in hexadecimal format to indicate the IMS capability.
    25.  
      * 1: RTP-based transfer of voice according to MMTEL (see 3GPP TS 24.173 [87])
    26.  
      * 2: RTP-based transfer of text according to MMTEL (see 3GPP TS 24.173 [87])
    27.  
      * 4: SMS using IMS functionality (see 3GPP TS 24.341[101])
    28.  
      * 8: RTP-based transfer of video according to MMTEL (see 3GPP TS 24.183 [87])
    29.  
      *
    30.  
      */
    31.  
       
    32.  
      //对比socketId是否当前的active phoneId
    33.  
      int socketId = ((int[]) ar.result)[2];
    34.  
      if (socketId != mActivePhoneId) {
    35.  
      break;
    36.  
      }
    37.  
       
    38.  
      int newImsRegInfo = ServiceState.STATE_POWER_OFF;
    39.  
      //读取Ims的注册状态
    40.  
      if (((int[]) ar.result)[0] == 1) {
    41.  
      newImsRegInfo = ServiceState.STATE_IN_SERVICE;
    42.  
      } else {
    43.  
      newImsRegInfo = ServiceState.STATE_OUT_OF_SERVICE;
    44.  
      }
    45.  
      //读取当前支持的capability
    46.  
      int newImsExtInfo = ((int[]) ar.result)[1];
    47.  
      mImsRegInfo = newImsRegInfo;
    48.  
       
    49.  
      //通知ims注册状态更新
    50.  
      notifyRegistrationStateChange(mImsRegInfo);
    51.  
       
    52.  
      if ((mImsRegInfo == ServiceState.STATE_IN_SERVICE)) {
    53.  
      mImsExtInfo = newImsExtInfo;
    54.  
      } else {
    55.  
      mImsExtInfo = 0;
    56.  
      }
    57.  
      //通知ims capability更新
    58.  
      notifyRegistrationCapabilityChange(mImsExtInfo);
    59.  
      break;
    60.  
      ...
    61.  
      }
    62.  
      ...
    63.  
      }
    • 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
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63

    从LOG来看,此次CIREGU指令返回的结果是“1,5”,按照定义,1表示已注册,5代表同时支持IMS_VOICE_OVER_LTE和IMS_SMS_OVER_LTE,即语音和短信业务。

    AT< +CIREGU: 1,5
    • 1

    注册状态的同步

    ImsManager获得注册状态和capability后,回调ImsPhoneCallTracker中实例化的ImsConnectionStateListener,数据最终将传递到ImsPhone。 
    ImsPhone中有ServiceState实例来标记data和ims voice服务状态,并有布尔值mImsRegistered来标记ims注册情况。

    1.  
      //ImsManager.java
    2.  
      private class ImsRegistrationListenerProxy extends IImsRegistrationListener.Stub {
    3.  
      private int mServiceClass;
    4.  
      private ImsConnectionStateListener mListener;
    5.  
       
    6.  
      public ImsRegistrationListenerProxy(int serviceClass,
    7.  
      ImsConnectionStateListener listener) {
    8.  
      mServiceClass = serviceClass;
    9.  
      mListener = listener;
    10.  
      }
    11.  
       
    12.  
      ...
    13.  
       
    14.  
      @Override
    15.  
      public void registrationConnected() {
    16.  
      if (mListener != null) {
    17.  
      mListener.onImsConnected();
    18.  
      }
    19.  
      }
    20.  
       
    21.  
      @Override
    22.  
      public void registrationProgressing() {
    23.  
      if (mListener != null) {
    24.  
      mListener.onImsProgressing();
    25.  
      }
    26.  
      }
    27.  
       
    28.  
      @Override
    29.  
      public void registrationDisconnected(ImsReasonInfo imsReasonInfo) {
    30.  
      if (mListener != null) {
    31.  
      mListener.onImsDisconnected(imsReasonInfo);
    32.  
      }
    33.  
      }
    34.  
       
    35.  
      @Override
    36.  
      public void registrationResumed() {
    37.  
      if (mListener != null) {
    38.  
      mListener.onImsResumed();
    39.  
      }
    40.  
      }
    41.  
       
    42.  
      @Override
    43.  
      public void registrationSuspended() {
    44.  
      if (mListener != null) {
    45.  
      mListener.onImsSuspended();
    46.  
      }
    47.  
      }
    48.  
       
    49.  
      @Override
    50.  
      public void registrationFeatureCapabilityChanged(int serviceClass,
    51.  
      int[] enabledFeatures, int[] disabledFeatures) {
    52.  
      if (mListener != null) {
    53.  
      mListener.onFeatureCapabilityChanged(serviceClass,
    54.  
      enabledFeatures, disabledFeatures);
    55.  
      }
    56.  
      }
    57.  
       
    58.  
      }
    • 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
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58

    ImsPhoneCallTracker如何处理注册信息和capability的上报: 
    1. 注册状态同步到ImsPhone; 
    2. Capability同步到mImsFeatureEnabled数组中,标记可用的ims业务; 
    3. 最后发出ACTION_IMS_STATE_CHANGED广播。

    1.  
      ImsPhoneCallTracker.java
    2.  
      /**
    3.  
      * Listen to the IMS service state change
    4.  
      *
    5.  
      */
    6.  
      private ImsConnectionStateListener mImsConnectionStateListener =
    7.  
      new ImsConnectionStateListener() {
    8.  
      @Override
    9.  
      public void onImsConnected() {
    10.  
      mPhone.setServiceState(ServiceState.STATE_IN_SERVICE);
    11.  
      mPhone.setImsRegistered(true);
    12.  
      }
    13.  
       
    14.  
      @Override
    15.  
      public void onImsDisconnected(ImsReasonInfo imsReasonInfo) {
    16.  
      mPhone.setServiceState(ServiceState.STATE_OUT_OF_SERVICE);
    17.  
      mPhone.setImsRegistered(false);
    18.  
      mPhone.processDisconnectReason(imsReasonInfo);
    19.  
      if (imsReasonInfo != null && imsReasonInfo.getExtraMessage() != null
    20.  
      && !imsReasonInfo.getExtraMessage().equals("")) {
    21.  
      mImsRegistrationErrorCode = Integer.parseInt(imsReasonInfo.getExtraMessage());
    22.  
      }
    23.  
      }
    24.  
       
    25.  
      @Override
    26.  
      public void onImsProgressing() {
    27.  
      }
    28.  
       
    29.  
      @Override
    30.  
      public void onImsResumed() {
    31.  
      mPhone.setServiceState(ServiceState.STATE_IN_SERVICE);
    32.  
      }
    33.  
       
    34.  
      @Override
    35.  
      public void onImsSuspended() {
    36.  
      mPhone.setServiceState(ServiceState.STATE_OUT_OF_SERVICE);
    37.  
      }
    38.  
       
    39.  
      @Override
    40.  
      public void onFeatureCapabilityChanged(int serviceClass,
    41.  
      int[] enabledFeatures, int[] disabledFeatures) {
    42.  
      if (serviceClass == ImsServiceClass.MMTEL) {
    43.  
      boolean tmpIsVideoCallEnabled = isVideoCallEnabled();
    44.  
      // Check enabledFeatures to determine capabilities. We ignore disabledFeatures.
    45.  
      for (int i = ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_LTE;
    46.  
      i <= ImsConfig.FeatureConstants.FEATURE_TYPE_VIDEO_OVER_WIFI; i++) {
    47.  
      if (enabledFeatures[i] == i) {
    48.  
      mImsFeatureEnabled[i] = true;
    49.  
      } else if (enabledFeatures[i]
    50.  
      == ImsConfig.FeatureConstants.FEATURE_TYPE_UNKNOWN) {
    51.  
      mImsFeatureEnabled[i] = false;
    52.  
      } else {
    53.  
      }
    54.  
      }
    55.  
      if (tmpIsVideoCallEnabled != isVideoCallEnabled()) {
    56.  
      mPhone.notifyForVideoCapabilityChanged(isVideoCallEnabled());
    57.  
      }
    58.  
       
    59.  
      for (ImsPhoneConnection connection : mConnections) {
    60.  
      connection.updateWifiState();
    61.  
      }
    62.  
       
    63.  
      mPhone.onFeatureCapabilityChanged();
    64.  
      broadcastImsStatusChange();
    65.  
      }
    66.  
      }
    67.  
      };
    • 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
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67

    ImsPhone更新ServiceState的Log:

    1.  
      06-02 16:47:44.925 D/ImsPhone( 2170): updateDataServiceState:
    2.  
      defSs = 0 0 voice home data home 中国移动 中国移动 46000 中国移动 中国移动 46000 LTE LTE_CA CSS not supported 0 0 RoamInd=-1 DefRoamInd=-1 EmergOnly=false Ril Voice Regist state: 1 Ril Data Regist state: 1 mProprietaryDataRadioTechnology: 0 VoiceRejectCause: 0 DataRejectCause: -1 IsDataRoamingFromRegistration=false
    3.  
      //imsServiceState
    4.  
      imsSs = 0 0 voice home data home null null null null null null Unknown LTE_CA CSS not supported -1 -1 RoamInd=-1 DefRoamInd=-1 EmergOnly=false Ril Voice Regist state: 0 Ril Data Regist state: 0 mProprietaryDataRadioTechnology: 0 VoiceRejectCause: -1 DataRejectCause: -1 IsDataRoamingFromRegistration=false
    • 1
    • 2
    • 3
    • 4

    小结

    以上分析只分析了AP侧流程,相对于完整的ims注册过程来说并不完整,核心部分的协议及信令流程许多对上层来说是透明的,需要对这些部分深入了解后再做补充。

     
    版权声明:本文为meiliqiang原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
    本文链接:https://blog.csdn.net/meiliqiang/article/details/78501947
  • 相关阅读:
    存储过程之六—触发器
    存储过程之五—条件和异常处理
    存储过程之四—游标
    json的那些事
    聊聊js中的typeof
    JavaScript各种继承方式和优缺点
    两边宽度已知,如何让中间自适应
    html5笔记——<section> 标签
    vue实现仿淘宝结账页面
    vue2.0在table中实现全选和反选
  • 原文地址:https://www.cnblogs.com/tonyxiao/p/15610174.html
Copyright © 2011-2022 走看看