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 values
if (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 not
try {
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
@Override
public 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 true
if (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 state
if (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 modify
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
getContext().sendBroadcast(intent);
// Notify content observers
getContext().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() {
@Override
public 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;
}
}
}
};
@Override
public 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() {
@Override
public 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
@Override
public 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 pdn连接的建立,一个是sip的注册。
IMS的开关设置完后,会根据相应的状态发起IMS的注册过程。
ImsService中注册监听了很多内容,比如:
public ImsService(Context context) {
log("init");
mContext = context;
/// Get Number of Phones
mNumOfPhones = TelephonyManager.getDefault().getPhoneCount();
/// M: keep old logic for 92gen and before
if (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 changed
ril.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]
案例:
向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
分析:
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