IMS的基础常识:
https://www.cnblogs.com/moon-lights/p/7018789.html
http://www.360doc.com/content/15/0624/06/9966538_480253246.shtml
http://www.txrjy.com/thread-879446-1-1.html

本次的IMS注册流程分析基于MT6580_O平台。关于IMS的相关流程,MTK释放的文档讲得已经蛮详细了,本次记录的内容纯属在文档的基础上加上自己的理解,以便日后的复习,仅供参考。
IMS的整体框架图如下:

其中MAL层以so库文件的形式存在,代码不对外开放。
ImsService.java在framework中是比较核心的类,IMS的多数功能都依赖于ImsService展开,其作用是:
Create ImsRILAdapter which to communicate with RJILD
Create ImsAdapter which to communicate with IMSM
Provide turn on/off Ims interface to ImsManager and ImsSwitchController to enable/disable IMS
Listen Registration information and notify ImsManager to broadcast to the receivers.
Listen incoming call indicator to create ImsCallsessionProxy to handle incoming call.

MTK的IMS设计中,能接触到的部分,主要分为两个方面:
一. 开关的控制
二. IMS的注册过程

一.开关的控制

这里的开关有两个,一个是settings下的”增强型4G LTE模式”选项,这个是用户能接触到的VOLTE的开关。一个是radio的开关。它们的时序图如下:

这个”增强型4G LTE模式”,控制着是否启用ims的哪些功能,主要有volte,vilte,wfc等等,具体看代码中的实现:

ImsManager.java

    public void setAdvanced4GMode(boolean turnOn) throws ImsException {checkAndThrowExceptionIfServiceUnavailable();// if turnOn: first set feature values then call turnOnIms()// if turnOff: only set feature values if IMS turn off is not allowed. If turn off is// allowed, first call turnOffIms() then set feature valuesif (turnOn) {setLteFeatureValues(turnOn);log("setAdvanced4GMode: turnOnIms");turnOnIms();} else {if (isImsTurnOffAllowed()) {log("setAdvanced4GMode: turnOffIms");turnOffIms();}setLteFeatureValues(turnOn);}}protected void setLteFeatureValues(boolean turnOn) {log("setLteFeatureValues: " + turnOn);try {ImsConfig config = getConfigInterface();if (config != null) {config.setFeatureValue(ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_LTE,TelephonyManager.NETWORK_TYPE_LTE, turnOn ? 1 : 0, mImsConfigListener);if (isVolteEnabledByPlatformForSlot()) {boolean ignoreDataEnabledChanged = getBooleanCarrierConfig(mContext,CarrierConfigManager.KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS);boolean enableViLte = turnOn && isVtEnabledByUserForSlot() &&(ignoreDataEnabledChanged || isDataEnabled());config.setFeatureValue(ImsConfig.FeatureConstants.FEATURE_TYPE_VIDEO_OVER_LTE,TelephonyManager.NETWORK_TYPE_LTE,enableViLte ? 1 : 0,mImsConfigListener);}}} catch (ImsException e) {loge("setLteFeatureValues: exception ", e);}}

ims开启的功能用feature,network,value,phoneId等参数值来表示,除了保持在SystemProperties中,还保存在了数据库imsconfig.db 中的tb_feature 表中,并对数据库进行了监听,如果数据库有更新,发出一个广播(ImsConfigContract.ACTION_IMS_FEATURE_CHANGED)通知数据库的变化:

ImsConfigStorage.java

        private void updateFeature(int featureId, int network, int value) {int curValue = -1;boolean result = false;ContentValues cv = new ContentValues();cv.put(ImsConfigContract.Feature.PHONE_ID, mPhoneId);cv.put(ImsConfigContract.Feature.FEATURE_ID, featureId);cv.put(ImsConfigContract.Feature.NETWORK_ID, network);cv.put(ImsConfigContract.Feature.VALUE, value);// Check exist or nottry {curValue = getFeatureValue(featureId, network);if (DEBUG) Log.d(TAG, "updateFeature() comparing: curValue: " +curValue + ", value:" + value);if (!checkIfBroadcastOnce(featureId, mPhoneId) || curValue != value || curValue == -1) {mContentResolver.update(ImsConfigContract.Feature.getUriWithFeatureId(mPhoneId, featureId, network),cv, null, null);}} catch (ImsException e) {Log.e(TAG, "updateFeature() ImsException featureId:" + featureId +", value:" + value);mContentResolver.insert(ImsConfigContract.Feature.CONTENT_URI, cv);}}

ImsConfigProvider.java

    @Overridepublic int update(Uri uri, ContentValues values, String selection,String[] selectionArgs) {int count = 0;Arguments args = new Arguments(OperationMode.MODE_UPDATE, uri, values, selection, selectionArgs);try {SQLiteDatabase db = mDatabaseHelper.getWritableDatabase();count = db.update(args.table, values, args.selection, args.selectionArgs);if (count > 0) {notifyChange(uri, args, values);}} catch (SQLiteFullException e) {onDiskFull(e);}return count;}private void notifyChange(Uri uri, Arguments args, ContentValues cv) {//final long oldId = Binder.clearCallingIdentity();try {int itemId, mimeType;String simState;int value = -1;boolean isECCBroadcastFlag = false;boolean isFeatureEnabled = false;boolean isSimStateAllow = false;String valueStr = "";Intent intent;switch (args.table) {......case ImsConfigContract.TABLE_FEATURE:simState = LatestSimState.get(Integer.parseInt(args.phoneId));Log.d(TAG, "getSimState() for checking whether broadcast phoneId: " +Integer.parseInt(args.phoneId) + ", Sim state: " + simState);itemId = Integer.parseInt(args.itemId);value = cv.getAsInteger(ImsConfigContract.Feature.VALUE);if (simState == null) {simState = "";}// ECCAllowBroadcast: The flag is used to allow broadcast for PS ECC// when sim is absent and the calculated platform support of VoLTE is trueif (ECCAllowBroadcast.get(Integer.parseInt(args.phoneId)) == null) {isECCBroadcastFlag = false;} else {isECCBroadcastFlag = (simState.equals(IccCardConstants.INTENT_VALUE_ICC_ABSENT) &&ECCAllowBroadcast.get(Integer.parseInt(args.phoneId)) &&itemId == ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_LTE);isFeatureEnabled = (value == ImsConfig.FeatureValueConstants.ON);if (isECCBroadcastFlag && !isFeatureEnabled) {ECCAllowBroadcast.put(Integer.parseInt(args.phoneId), false);Log.d(TAG, "Sim absent but the calculated VoLTE is false," +" so no need broadcast");}}/// M: Sync volte setting value. @{boolean isForceNotify =(itemId == ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_LTE) &&(SystemProperties.getInt(PROPERTY_IMSCONFIG_FORCE_NOTIFY, 0) == 1);Log.d(TAG, "isForceNotify " + isForceNotify);/// @}// Check SIM stateif (simState.equals(IccCardConstants.INTENT_VALUE_ICC_READY) ||simState.equals(IccCardConstants.INTENT_VALUE_ICC_IMSI) ||simState.equals(IccCardConstants.INTENT_VALUE_ICC_LOADED)) {isSimStateAllow = true;} else {isSimStateAllow = false;}if (isSimStateAllow || (isECCBroadcastFlag && isFeatureEnabled) ||isForceNotify) {// For observers who don't have dedicated process, use broadcast mechanism.intent = new Intent(ImsConfigContract.ACTION_IMS_FEATURE_CHANGED, uri);intent.putExtra(ImsConfigContract.EXTRA_PHONE_ID, Integer.parseInt(args.phoneId));intent.putExtra(ImsConfigContract.EXTRA_CHANGED_ITEM, itemId);intent.putExtra(ImsConfigContract.EXTRA_NEW_VALUE, value); // need to modifyintent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);getContext().sendBroadcast(intent);// Notify content observersgetContext().getContentResolver().notifyChange(uri, null);ECCAllowBroadcast.put(Integer.parseInt(args.phoneId), false);Log.d(TAG, "Update uri " + uri + " on phone " + args.phoneId + " value: " + value);}break;......                                                    

ImsConfigContract.ACTION_IMS_FEATURE_CHANGED 广播最后被WifiOffloadService接收,并从数据库中查询当前IMS所支持的功能的最新状态,并将结果返回给回调函数onGetFeatureResponse()
WifiOffloadService.java

    private BroadcastReceiver mFeatureValueReceiver = new BroadcastReceiver() {@Overridepublic void onReceive(Context context, Intent intent) {if (intent == null || intent.getAction() == null) {return;}if (intent.getAction().equals(ImsConfig.ACTION_IMS_FEATURE_CHANGED)) {int feature = intent.getIntExtra(ImsConfig.EXTRA_CHANGED_ITEM, -1);int phoneId = intent.getIntExtra(EXTRA_PHONE_ID, -1);Log.d(TAG,"onRecevied IMS feature changed phoneId: " + phoneId + ", feature: " + feature);if (checkInvalidSimIdx(phoneId, "ignore it for invalid SIM id")) return;if (checkNullObject(mCfgListeners[phoneId], "no CfgListener")) return;ImsManager imsMgr = ImsManager.getInstance(mContext, phoneId);if (checkNullObject(imsMgr, "can't get ImsManager")) return;try {ImsConfig imsCfg = imsMgr.getConfigInterface();if (checkNullObject(imsCfg, "can't get ImsConfig")) return;imsCfg. (feature, getNetworkTypeByFeature(feature), mCfgListeners[phoneId]);} catch (ImsException e) {Log.e(TAG, "getFeatureValue has exception: " + e);return;}}}};            @Overridepublic void onGetFeatureResponse(int feature, int network, int value, int status) {if (status == ImsConfig.OperationStatusConstants.FAILED) {Log.d(TAG, "onGetFeatureResponse: get feature failed:" + feature);return;}Log.d(TAG, "onGetFeatureResponse: sim=" + mPhoneId + ", feature=" + feature+ ", value=" + value);fetchFeatureValue(feature, value);notifyMalUserProfile(mPhoneId);}        

然后通过jni 函数nativeSetWosProfile 向MAL 设置IMS feature 参数,由MAL 决定turn on/off IMS,通过函数onRequestImsSwitch() 向WifiOffloadService 返回,WifiOffloadService 通过此方法通知了所有注册监听它的类,比如ImsService。所以最后在ImsService的onRequestImsSwitch()方法中对turnOnIms\turnOffIms方法对RIL发起开关ims功能的动作。如下:

    protected void onRequestImsSwitch(int simIdx, boolean isImsOn) {Message msg = mHandler.obtainMessage(EVENT_ON_REQUEST_IMS_SWITCH, simIdx, (isImsOn)? 1: 0);mHandler.sendMessage(msg);}private Handler mHandler = new Handler() {@Overridepublic void handleMessage(Message msg) {Log.d(TAG, "handleMessage: " + messageToString(msg) + " = " + msg);switch (msg.what) {......case EVENT_ON_REQUEST_IMS_SWITCH:int simIdx = msg.arg1;boolean isImsOn = msg.arg2 == 1;notifyOnRequestImsSwitch(simIdx, isImsOn);break;           ......}}}private void notifyOnRequestImsSwitch(int simIdx, boolean isImsOn) {Log.d(TAG, "onRequestImsSwitch simIdx: " + simIdx + ", isImsOn: " + isImsOn);int i = mListeners.beginBroadcast();while (i > 0) {i--;try {mListeners.getBroadcastItem(i).onRequestImsSwitch(simIdx, isImsOn);} catch (RemoteException e) {// The RemoteCallbackList will take care of removing// the dead object for us.Log.e(TAG, "onRequestImsSwitch: RemoteException occurs!");}}mListeners.finishBroadcast();}     

ImsService.java

        @Overridepublic void onRequestImsSwitch(int simIdx, boolean isImsOn) {if (ImsCommonUtil.supportMdAutoSetupIms()) {return;}int mainCapabilityPhoneId = ImsCommonUtil.getMainCapabilityPhoneId();log("onRequestImsSwitch simIdx=" + simIdx +" isImsOn=" + isImsOn + " mainCapabilityPhoneId=" + mainCapabilityPhoneId);if (simIdx >= mNumOfPhones) {loge("onRequestImsSwitch can't enable/disable ims due to wrong sim id");}if (ImsCommonUtil.supportMims() == false) {if (simIdx != mainCapabilityPhoneId) {logw("onRequestImsSwitch, ignore not MainCapabilityPhoneId request");return;}}            if (isImsOn) {if (mImsState[simIdx] != MtkPhoneConstants.IMS_STATE_ENABLE|| mExpectedImsState[simIdx] == MtkPhoneConstants.IMS_STATE_DISABLED) {mImsRILAdapters[simIdx].turnOnIms(mHandler[simIdx].obtainMessage(EVENT_SET_IMS_ENABLED_DONE));mExpectedImsState[simIdx] = MtkPhoneConstants.IMS_STATE_ENABLE;mImsState[simIdx] = MtkPhoneConstants.IMS_STATE_ENABLING;} else {log("Ims already enable and ignore to send AT command.");}} else {if (mImsState[simIdx] != MtkPhoneConstants.IMS_STATE_DISABLED|| mExpectedImsState[simIdx] == MtkPhoneConstants.IMS_STATE_ENABLE) {mImsRILAdapters[simIdx].turnOffIms(mHandler[simIdx].obtainMessage(EVENT_SET_IMS_DISABLE_DONE));mExpectedImsState[simIdx] = MtkPhoneConstants.IMS_STATE_DISABLED;mImsState[simIdx] = MtkPhoneConstants.IMS_STATE_DISABLING;} else {log("Ims already disabled and ignore to send AT command.");}}}}            

如果RIL处理完开关ims的操作后,会给ImsService发一个携带EVENT_SET_IMS_ENABLED_DONE,EVENT_SET_IMS_DISABLE_DONE的消息,在ImsService中,并没有对这两个消息做特殊的处理。仅仅是一些打印。

同理,Radio开关的流程大致上也跟”增强型4G LTE模式开关”差不多,只是在MAL中的处理可能有些差异。

DEBUG:

1. Enable Volte
D/ImsConfigImpl( 3729): setFeatureValue(0, 13, 1) on phone 1 from pid 3721, uid 1001, listener null
//update database
D/ImsConfigProvider( 3729): Update uri content://com.mediatek.ims.config.provider/tb_feature/1/0/13 on phone 1 value: 1
//notify Mal user profile
D/WifiOffloadService( 3760): notifyMalUserProfile simId: 1 mIsVolteEnabled: true, mIsVilteEnabled: false mIsWfcEnabled: false
mFqdn: mIsWifiEnabled: true mHasWiFiDisabledPending: false mWfcMode: 3 mDataRoamingEnabled: 0 mIsAllowTurnOffIms: true
D/WifiOffloadService( 3760): onRequestImsSwitch simIdx: 1 isImsOn: true
//send AT
I/AT ( 1062): AT> AT+EIMSVOICE=1 (RIL_CMD2_READER_3, tid:529387332688)
I/AT ( 1062): AT> AT+EIMSVOLTE=1 (RIL_CMD2_READER_3, tid:529387332688)
I/AT ( 1062): AT> AT+EIMS=1 (RIL_CMD2_READER_3, tid:529387332688)2. Enable Vilte
D/ImsConfigImpl( 3729): setFeatureValue(1, 13, 1) on phone 1 from pid 3721, uid 1001, listener null
//update database
D/ImsConfigProvider( 3729): Update uri content://com.mediatek.ims.config.provider/tb_feature/1/1/13 on phone 1 value: 1
//notify Mal user profile
D/WifiOffloadService( 3760): notifyMalUserProfile simId: 1 mIsVolteEnabled: true, mIsVilteEnabled: true mIsWfcEnabled: false
mFqdn: mIsWifiEnabled: true mHasWiFiDisabledPending: false mWfcMode: 3 mDataRoamingEnabled: 0 mIsAllowTurnOffIms: true
//send At
I/AT ( 1062): AT> AT+EIMSCCP=1 (RIL_CMD2_READER_3, tid:529387332688)

二. IMS的注册过程

IMS的注册过程有两个,一个是ims pdn连接的建立,一个是sip的注册。

IMS的开关设置完后,会根据相应的状态发起IMS的注册过程。

ImsService中注册监听了很多内容,比如:

    public ImsService(Context context) {log("init");mContext = context;/// Get Number of PhonesmNumOfPhones = TelephonyManager.getDefault().getPhoneCount();/// M: keep old logic for 92gen and beforeif (ImsCommonUtil.supportMdAutoSetupIms() == false) {mImsAdapter = new ImsAdapter(context);}mHandler = new MyHandler[mNumOfPhones];mImsRILAdapters = new ImsCommandsInterface[mNumOfPhones];for(int i = 0; i < mNumOfPhones; i++) {mHandler[i] = new MyHandler(i);ImsRILAdapter ril = new ImsRILAdapter(context, i);/// register for radio state changedril.registerForNotAvailable(mHandler[i], EVENT_RADIO_NOT_AVAILABLE, null);ril.registerForOff(mHandler[i], EVENT_RADIO_OFF, null);ril.registerForOn(mHandler[i], EVENT_RADIO_ON, null);ril.registerForImsRegistrationInfo(mHandler[i], EVENT_IMS_REGISTRATION_INFO, null);ril.registerForImsEnableStart(mHandler[i], EVENT_IMS_ENABLING_URC, null);ril.registerForImsEnableComplete(mHandler[i], EVENT_IMS_ENABLED_URC, null);ril.registerForImsDisableStart(mHandler[i], EVENT_IMS_DISABLING_URC, null);ril.registerForImsDisableComplete(mHandler[i], EVENT_IMS_DISABLED_URC, null);ril.setOnIncomingCallIndication(mHandler[i], EVENT_INCOMING_CALL_INDICATION, null);ril.registerForCallProgressIndicator(mHandler[i], EVENT_SIP_CODE_INDICATION, null);ril.registerForImsDeregisterComplete(mHandler[i], EVENT_IMS_DEREG_URC, null);ril.registerForMultiImsCount(mHandler[i], EVENT_MULTI_IMS_COUNT_URC, null);/// M: Listen for network initiated USSI @{ril.setOnNetworkInitUSSI(mHandler[i], EVENT_ON_NETWORK_INIT_USSI, null);/// @}/// M: register for IMS RTP report event @{ril.registerForImsRTPInfo(mHandler[i], EVENT_IMS_RTP_INFO_URC, null);/// @}/// M: Sync volte setting value. @{ril.registerForVolteSettingChanged(mHandler[i], EVENT_IMS_VOLTE_SETTING_URC, null);/// @}mImsRILAdapters[i] = ril;}            

比较重要的状态有,ims开关相关的EVENT_IMS_ENABLING_URC,ims注册状态相关的EVENT_IMS_REGISTRATION_INFO,ims通话相关EVENT_INCOMING_CALL_INDICATION等等。
在上面已经说过的ims开关的设置,ImsService会向RIL发起turn on/off ims开关的操作。而RIL开关ims操作后返回的EVENT_SET_IMS_ENABLED_DONE消息中,并没有明显的后续处理。是因为ImsService对开关ims状态的处理放在了EVENT_IMS_ENABLING_URC中。如时序图所示,EVENT_IMS_ENABLING_URC的消息处理主要有三个部分:
1.通知MAL处理
2.在DataDispatcher中注册广播
3.发广播通知数据库更新

以上,通知MAL处理的具体实现我们看不到,省略不提。在DataDispatcher中注册广播,这个广播的处理是:如果当前的数据连接状态变更,且携带failure信息,则通知MAL。

        public void onReceive(Context context, Intent intent) {String action = intent.getAction();if (action.equalsIgnoreCase(TelephonyManager.ACTION_PRECISE_DATA_CONNECTION_STATE_CHANGED)) {String type = intent.getStringExtra(PhoneConstants.DATA_APN_TYPE_KEY);String failure = intent.getStringExtra(PhoneConstants.DATA_FAILURE_CAUSE_KEY);if (failure != null && failure.length() > 0) {logd("onReceive, intent action is " + intent.getAction());logd("APN: " + type + " failCause: " + failure);switch(type) {case PhoneConstants.APN_TYPE_IMS:Handler imsHandle = mImsConnection.getHandler();imsHandle.sendMessage(imsHandle.obtainMessage(MSG_ID_WRAP_IMSM_IMSPA_PDN_ACT_FAIL, failure));break;case PhoneConstants.APN_TYPE_EMERGENCY:Handler emcHandle = mEmcConnection.getHandler();emcHandle.sendMessage(emcHandle.obtainMessage(MSG_ID_WRAP_IMSM_IMSPA_PDN_ACT_FAIL, failure));break;default:loge("UnKnown APN: " + type);break;}}}}                

从时序图中,我们可以看到,ims开关设置后,ims主动发起requestNetwork()的动作(建立PDN连接请求),有三个触发地方:
1.MAL处理结束后,通知DataDispatcher发起PDN连接
2.监听SIM卡状态,主副卡切换时发起PDN连接
3.监听RIL层的ims链路情况,合适时机发起PDN连接

发起PDN连接还是需要通过ConnectivityManager,之后会有ims apn的检查过程,PDN的连接过程可以参考 路由配置信息的获取

ims pdn连接建立的过程,需要建立在正常4G pdn连接的基础上,这部分的判断应该是被封装在了MAL中,我们无法查看。

DEBUG:

D/ImsService( 3729): receive EVENT_IMS_ENABLING_URC, mActivePhoneId = 1, phoneId = 1
//MAL-IMSM send MSG_ID_WRAP_IMSM_IMSPA_PDN_ACT_REQ
D/MAL-IMSM(10037): send MSG_ID_WRAP_IMSM_IMSPA_PDN_ACT_REQ, transaction_id = 16, rat_type = 0, emergency_ind = 0
(vendor/mediatek/proprietary/frameworks/opt/mal/volte_imsm/src/imsm_handler.c:2031)
//dispatch MSG_ID_WRAP_IMSM_IMSPA_PDN_ACT_REQ
D/[ImsAdapter]( 3729): dumpEvent:
phone_id:1,request_id:MSG_ID_WRAP_IMSM_IMSPA_PDN_ACT_REQ,data_len:4,event:[B@3f853cc
D/[ImsEventDispatcher]( 3729): dispatchCallback: request ID:MSG_ID_WRAP_IMSM_IMSPA_PDN_ACT_REQ
I/DataDispatcher( 3729): [dedicate] DataDispatcher receives request [900008, 4, phoneId: 1]
D/DataDispatcher( 3729): [dedicate] DataDispatcher handleDefaultBearerActivationRequest
//SETUP_DATA_CALL
D/RILJ ( 3721): [4116]> SETUP_DATA_CALL 14 2 ims 0 IPV4V6 5 [SUB1]
D/RILJ ( 3721): [4116]< SETUP_DATA_CALL DataCallResponse: {version=11 status=0 retry=0 cid=4 active=2 type=IPV6
ifname=ccmni4 mtu=0 rat=1 addresses=[FE80:0000:0000:0000:5220:368e:3Ba8:A680] dnses=[211.136.112.50,211.136.150.66]
gateways=[FE80:0000:0000:0000:5220:368e:3Ba8:A680]
pcscf=[36.9.128.20.134.1.16.16.0.0.0.0.0.0.0.9,36.9.128.20.130.1.48.16.0.0.0.0.0.0.0.9]} [SUB1]

ims pdn连接建立后,接下来就是sip注册的过程了。MAL中处理完sip注册过程后,会通知ImsService进行处理。见时序图。
sip注册:

鉴权: 即认证,是识别某实体或用户的身份,并确保该实体或用户为合法用户身份的方法。归
属网络通过用户初始注册过程对用户进行鉴权。当用户终端发起初始注册时, S-CSCF 根据
REGISTER 消息中携带的头域以及用户在HSS 上开户时选择的鉴权方式对终端进行鉴权目前固
定终端使用HTTP Digest 鉴权方式,也即使用用户名和密码进行鉴权。注册过程的鉴权与认证保
证了网络的安全性。
注册信令流程图:

DEBUG:

//1st register
I/VoLTE SIPTX(10758): [SIPTX-IO] Send SIP (2409:8014:8601:1010::9: 5060 )[131073:196610] ==> { REGISTER
sip:ims.mnc000.mcc460.3gppnetwork.org SIP/2.0 }
I/VoLTE SIPTX(10758): [SIPTX-IO] Send Success]
I/VoLTE SIPTX(10758): [SIPTX-IO] Recv SIP (2409:8014:8601:1010::9: 5060 )[131073:196610] <== { SIP/2.0 401 Unauthorized }
//second register
I/VoLTE SIPTX(10758): [SIPTX-IO] Send SIP (2409:8014:8601:1010::9: 9900 )[131073:262147] ==> { REGISTER
sip:ims.mnc000.mcc460.3gppnetwork.org SIP/2.0 }
I/VoLTE SIPTX(10758): [SIPTX-IO] Send Success]
I/VoLTE SIPTX(10758): [SIPTX-IO] Recv SIP (2409:8014:8601:1010::9: 9900 )[131073:262147] <== { SIP/2.0 200 OK }
//reigiter state
I/AT ( 1062): AT< +CIREGU: 1,d (RIL_URC2_READER, tid:0)
D/RILJ ( 3721): [UNSL]< RIL_UNSOL_IMS_REGISTRATION_INFO [SUB1]

三.IMS注册问题的一些例子

案例:
向MAL 设置IMS feature 参数失败
1.

问题分析:
在离开飞行模式的时候,MAL 出现了异常,处于not ready 状态,此时FW 不会向MAL 设置IMS feature 参数,注册流程
终止,MAL 是封装的库文件,需要MTK 修改。
// key log —- MAL isn’t ready
06-27 18:07:22.339748 1484 1529 D WifiOffloadService: onMalReset
06-27 18:07:30.628588 1484 1497 D WifiOffloadService: notifyMalRadioInfo return directly due to MAL isn’t ready yet.
https://drive.google.com/open?id=0B4KdjNMUeozNZE50QWp5TmRDQVU

2.

问题分析:
在分析发现进入飞行模式前,wfo 获取的数据库中的值是disable 的导致,向MAL 设置的vilte feature 也是disable,所以
无法使用vilte。进一步分析发现条件不满足,vilte feature 未写入数据库。

3.

分析:
分析发现ims enable 之后, 未收到volte_imsm 上报的IMS PDN 激活请求,MSG_ID_WRAP_IMSM_IMSPA_PDN_ACT_REQ,
导致未发起pdn 连接。
正常log:
D/ImsEventDispatcher: dispatchCallback: request ID:MSG_ID_WRAP_IMSM_IMSPA_PDN_ACT_REQ
I/DataDispatcher( 3729): [dedicate] DataDispatcher receives request [900008, 4, phoneId: 1]
D/DataDispatcher( 3729): [dedicate] DataDispatcher handleDefaultBearerActivationRequest
属于MAL 封装库,需要MTK 修改
https://drive.google.com/open?id=0B4KdjNMUeozNLWJwaDFHdDlkSDg

4.

分析:
log 中发现未找到IMS APN 参数,导致没有发起PDN 请求,需要在apns-conf.xml 中添加对应运营商apn 参数
https://share.weiyun.com/18012b10941f0e727515e80555bb8880

5.

分析:
拨打IMS emergency call 时,需要建立IMS emergency pdn,此问题apn 表中未配置Emergency apn 参数,导致未发起PDN 请求。
https://pan.baidu.com/s/1geRYFUr

6.

问题分析:
UE 发register 消息,网络未响应,超时后注册失败。MTK 提供优化方案,建立TCP 连接失败后,跳过UDP 连接,重新
发起下一次连接。
//走TCP 失败,三次握手失败, 10s timeout
15:10:42.930051 100.96.153.29 10.55.41.196 TCP 76 59518 → 5060 [SYN] Seq=0 Win=65535 Len=0
MSS=1200 SACK_PERM=1 TSval=4294942468 TSecr=0 WS=256
15:10:43.921538 100.96.153.29 10.55.41.196 TCP 76 [TCP Retransmission] 59518 → 5060 [SYN] Seq=0
Win=65535 Len=0 MSS=1200 SACK_PERM=1 TSval=4294942568 TSecr=0 WS=256
15:10:49.931533 100.96.153.29 10.55.41.196 TCP 76 [TCP Retransmission] 59518 → 5060 [SYN] Seq=0
Win=65535 Len=0 MSS=1200 SACK_PERM=1 TSval=4294943169 TSecr=0 WS=256
//走UDP, 110s timeout,注册失败
15:10:52.943226 100.96.153.29 10.55.41.196 IPv4 1516 Fragmented IP protocol (proto=UDP 17, off=0, ID=fa25)
[Reassembled in #349]
15:10:52.943489 100.96.153.29 10.55.41.196 SIP 341 Request: REGISTER
sip:ims.mnc092.mcc404.3gppnetwork.org (1 binding) |
15:12:42.950612 100.96.153.29 10.55.41.196 IPv4 1516 Fragmented IP protocol (proto=UDP 17, off=0, ID=0b72)
[Reassembled in #1599]
15:12:42.950642 100.96.153.29 10.55.41.196 SIP 341 Request: REGISTER
sip:ims.mnc092.mcc404.3gppnetwork.org (1 binding) |
http://pan.baidu.com/s/1o8A3CAQ

7.

分析:
User Agent 客制化引起NVRAM_EF_IMS_PROFILE_LID 的值不符合预期。
09-11 17:30:24.037077 4584 4626 I AT : AT> AT+EIMSVOICE=1 (RIL_CMD2_READER_3, tid:493392720976)
09-11 17:30:24.042894 4584 4626 I AT : AT> AT+EIMSVOLTE=1 (RIL_CMD2_READER_3, tid:493392720976)
09-11 17:30:24.049705 4584 4626 I AT : AT> AT+EIMS=1 (RIL_CMD2_READER_3, tid:493392720976)
09-11 17:30:24.052815 4584 4640 I AT : AT< +EIMS: 1 (RIL_URC2_READER, tid:0)
//nv execption
09-11 17:30:27.022221 7393 7393 I VoLTE IMCB-2: connection status change for module 7 as error_num 0
imcb_imcb_comm_error_handler()@0#609
118311, 0, 203151, 18:32:41:073 2017/09/11, MOD_IMC, MOD_DHL, DHL_IMC_SAP,
MSG_ID_DHL_IMC_EM_DUMP_NVRAM_IND
Local_Parameter –> Len = 3192, Addr = 0xA686C2C8
dhl_imc_em_dump_nvram_ind_struct = (struct)
ref_count = 0x01
lp_reserved = 0x13
msg_len = 0x0c78
ims_profile = (struct)
ua_config = (struct)
local_port = 0x000013c4
pcscf_port_number = 0x00000000
ipsec_local_port_start = 0x00000000
ipsec_local_port_range = 0x00000000

8.

分析:
IMCB 版本和modem 侧IMC 版本不匹配导致
//log
10-30 10:22:29.494560 1829 1829 I VoLTE imcb-2: imcb and IMC verno un-sync!!! disable imcb/IMC connection!!!!
@0#3524

IMS的注册流程分析相关推荐

  1. 从注册流程 分析如何安全退出多个Activity 多种方式(附DEMO)

      退出Activity注册Android遍历 目录(?)[+] 前言 知识结构 具体方案 方案1 方法采用FLAG_ACTIVITY_CLEAR_TOP退出整个程序多activity 方案2 方法通 ...

  2. 从注册流程 分析如何安全退出多个Activity 多种方式(附DEMO)

    http://blog.csdn.net/vipzjyno1/article/details/25423543 前言 由于一个同学问到我如何按照一个流程走好之后回到首页,我以前看到过4个解决方案,后来 ...

  3. Dubbo注册流程分析

    Dubbo注册流程分析 官网简介 Apache Dubbo 是一款微服务开发框架,它提供了 RPC通信 与 微服务治理 两大关键能力.这意味着,使用 Dubbo 开发的微服务,将具备相互之间的远程发现 ...

  4. Android AOSP 6.0.1 registerReceiver广播注册流程分析

    广播作为 Android 开发的四大组间之一,当我们发送广播以后,发生了什么?广播接收者最终如何收到了广播. 一.复盘广播的使用 在 Android 开发中使用广播分为三个步骤: 1.新建广播接收者 ...

  5. 基于GBT28181:SIP协议组件开发-----------第三篇SIP注册流程分析实现

    原创文章,引用请保证原文完整性,尊重作者劳动,原文地址http://www.cnblogs.com/qq1269122125/p/3941172.html,qq:1269122125. 上两章节简要的 ...

  6. Android8.1 开关VOLTE流程分析

    前言 最近有需求需要实现插卡默认打开Volte功能,顺带研究了下Volte的流程,在此做个记录 开始 从Settings设置界面入手,网络和互联网-->移动网络-->VoLTE高清通话(电 ...

  7. VoLTE技术(含IMS注册/去注册流程、IMS呼叫流程、呼叫保持流程、二次协商过程)

    文章目录 VoLTE技术 IMS简介 SIP消息结构 IMS注册流程 IMS去注册流程 什么是Ghost Call 预留资源的呼叫流程 挂断电话流程(主动挂断.拒接) SDP协议,二次协商过程 呼叫保 ...

  8. nio的epoll和selector实现流程分析

    一.NETTY底层使用的是NIO的selector和epoll进行实现的,select,poll,epoll都是IO多路复用的机制.I/O多路复用就是通过一种机制,一个进程可以监视多个描述符,一旦某个 ...

  9. soul网关系列(六):客户端注册soul流程分析

    探寻spring mvc客户端初始化接入soul至入库的流程 目录 一.soul的数据流综述 二.客户端的流程 2.1 接入soul网关的流程回顾 2.2 soul-spring-boot-start ...

最新文章

  1. gulp复制整个文件夹或文件到指定目录(包括拷贝单个文件)
  2. 查看php-fpm 占用内存情况
  3. 【hibernate merge】session1.merge(T entity)方法的含义和update方法的区别
  4. springboot 上传异常捕获_Spring Boot 全局异常处理(下)
  5. java web redis_java web网页版redis客户端工具
  6. python ssh库paramiko学习
  7. 获取工程的exe文件的所在目录
  8. PostgreSQL 11 preview - Faster partition pruning
  9. 计算机硬盘 u盘和光盘属于,磁盘U盘光盘的区别
  10. 用linux给诺基亚手机刷机,凤凰刷机怎么给诺基亚手机刷机 凤凰给诺基亚手机刷机教程...
  11. 软件项目管理期末复习---项目立项
  12. FreeImage的学习总结总结(三)
  13. 威斯敏斯特教堂(西敏寺)墓碑上的话(WestMinster Abbey,When I was young and free...,修身齐家治国平天下)...
  14. CFA一级学习笔记--衍生品(一)--概念以及定义
  15. TLD(Tracking-Learning-Detection)一种目标跟踪算法(相关资料很全)
  16. 福昕PDF不可编辑解决方法
  17. 简谈Oracle体系结构
  18. android之manifest
  19. redis mysql qps_测算Redis处理实际生产请求的QPS/TPS
  20. 小熊派开发板移植RT-FOTA

热门文章

  1. 弹道控制C++模拟教程
  2. java 实现发送短信验证码(网易云)
  3. android布局高度大于屏幕高度,Android CoordinatorLayout + AppbarLayout + Viewpager布局超过屏幕高度...
  4. (转)Python成长之路【第九篇】:Python基础之面向对象
  5. C语言单元测试embUnit入门学习
  6. 20几岁男人应该懂得50件事
  7. 不同的人生不同的追求
  8. Android初学之自定义简单蛛网(雷达)图
  9. 超详细的--STP理论
  10. 神(gai)奇(si)的MIUI优化