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

MTK IMS框架简析(2)——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服务:

//启用volte语音服务

RIL_REQUEST_SET_VOLTE_ENABLE

RIL_REQUEST_SET_IMS_VOICE_ENABLE

//启动ims功能

RIL_REQUEST_SET_IMS_ENABLE

1

2

3

4

5

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

//ImsManager.java

private void setAdvanced4GMode(boolean turnOn) throws ImsException {

checkAndThrowExceptionIfServiceUnavailable();

try {

ImsConfig config = getConfigInterface();

if (config != null) {

//设置启用volte语音

config.setFeatureValue(ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_LTE,

TelephonyManager.NETWORK_TYPE_LTE, turnOn ? 1 : 0, null);

}

} catch (ImsException e) {

}

//启用ims服务

if (turnOn) {

turnOnIms();

} else if (isImsTurnOffAllowed()) {

turnOffIms();

}

}

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中:

//ImsConfig.java

public static class FeatureConstants {

public static final int FEATURE_TYPE_UNKNOWN = -1;

/**

* FEATURE_TYPE_VOLTE supports features defined in 3GPP and

* GSMA IR.92 over LTE.

*/

public static final int FEATURE_TYPE_VOICE_OVER_LTE = 0;

/**

* FEATURE_TYPE_LVC supports features defined in 3GPP and

* GSMA IR.94 over LTE.

*/

public static final int FEATURE_TYPE_VIDEO_OVER_LTE = 1;

/**

* FEATURE_TYPE_VOICE_OVER_WIFI supports features defined in 3GPP and

* GSMA IR.92 over WiFi.

*/

public static final int FEATURE_TYPE_VOICE_OVER_WIFI = 2;

/**

* FEATURE_TYPE_VIDEO_OVER_WIFI supports features defined in 3GPP and

* GSMA IR.94 over WiFi.

*/

public static final int FEATURE_TYPE_VIDEO_OVER_WIFI = 3;

}

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。

//ImsConfigImpl.java

public void setFeatureValue(int feature, int network, int value, ImsConfigListener listener) {

try {

try {

//将设置值保存到数据库

mStorage.setFeatureValue(feature, network, value);

//不同的feature需要不同的设置,这里只分析volte的处理

switch(feature) {

case ImsConfig.FeatureConstants.FEATURE_TYPE_VIDEO_OVER_LTE:

case ImsConfig.FeatureConstants.FEATURE_TYPE_VIDEO_OVER_WIFI:

...

break;

case ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_WIFI:

...

break;

case ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_LTE:

int oldVoLTEValue = SystemProperties.getInt(PROPERTY_VOLTE_ENALBE, 0);

int wfcEnable = SystemProperties.getInt(PROPERTY_WFC_ENALBE, 0);

if (value != oldVoLTEValue) {

//打开

if (value == ImsConfig.FeatureValueConstants.ON) {

//设置property

SystemProperties.set(PROPERTY_VOLTE_ENALBE,"1");

//向rild-ims下发RIL_REQUEST_SET_VOLTE_ENABLE

mRilAdapter.turnOnVolte(null);

if (wfcEnable == 0){

//向rild-ims下发RIL_REQUEST_SET_IMS_VOICE_ENABLE

mRilAdapter.turnOnImsVoice(null);

}

} else {//关闭

SystemProperties.set(PROPERTY_VOLTE_ENALBE,"0");

mRilAdapter.turnOffVolte(null);

if (wfcEnable == 0){

mRilAdapter.turnOffImsVoice(null);

}

}

}

break;

default:

break;

}

...

} catch (ImsException e) {

...

}

} catch (RemoteException e) {

throw new RuntimeException(e);

}

}

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执行。

//ImsManager.java

private void turnOnIms() throws ImsException {

checkAndThrowExceptionIfServiceUnavailable();

try {

mImsService.turnOnIms(mPhoneId);

} catch (RemoteException e) {

throw new ImsException("turnOnIms() ", e, ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);

}

}

1

2

3

4

5

6

7

8

9

10

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

//ImsService.java

@Override

public void turnOnIms(int phoneId) {

if (mActivePhoneId != phoneId) {

mActivePhoneId = phoneId;

}

if (mImsState != PhoneConstants.IMS_STATE_ENABLE) {

mImsRILAdapter.turnOnIms(mHandler.obtainMessage(EVENT_SET_IMS_ENABLED_DONE));

mImsState = PhoneConstants.IMS_STATE_ENABLING;

} else {

}

}

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消息的监听,消息上报后便会由它处理。

//ImsService.java

mImsRILAdapter.registerForImsEnableStart(mHandler, EVENT_IMS_ENABLING_URC, null);

1

2

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

//ImsService.java

case EVENT_IMS_ENABLING_URC:

//+EIMS: 1

if (mActivePhoneId != phoneId) {

mActivePhoneId = phoneId;

}

// notify AP Ims Service is up

intent = new Intent(ImsManager.ACTION_IMS_SERVICE_UP);

intent.putExtra(ImsManager.EXTRA_PHONE_ID, mActivePhoneId);

mContext.sendBroadcast(intent);

// enable ImsAdapter

enableImsAdapter();

mImsState = PhoneConstants.IMS_STATE_ENABLE;

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并没有开源:

#README

IMS relay module, handling NAS bearer, P-CSCF address discovery, IMS AKA and relay message among IMCB/IMSA/MAL modules

WHAT IT DOES?

=============

handle the request from IMCB/IMSA/MAL module

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()方法。

ImsAdapter.java

public void enableImsAdapter() {

synchronized (ImsEnabledThreadLock) {

if (!misImsAdapterEnabled) {

if (mIO.connectSocket() == true) {

//调用所有VaEventDispatcher的enableRequest方法

mImsEventDispatcher.enableRequest();

misImsAdapterEnabled = true;

synchronized (mIO.VaSocketIOThreadLock) {

mIO.VaSocketIOThreadLock.notify();

}

//启用ims栈(向volte_imsm下发一条消息)

enableImsStack();

} else {

sendMessageDelayed(

obtainMessage(MSG_IMSA_RETRY_IMS_ENABLE),

IMSA_RETRY_SOCKET_TIME);

}

}

}

}

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卡的变动。

DataDispatcher.java

public void enableRequest() {

synchronized (mHandler) {

Arrays.fill(mSimStatus, false);

IntentFilter filter = new IntentFilter();

filter.addAction(TelephonyManager.ACTION_PRECISE_DATA_CONNECTION_STATE_CHANGED);

filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);

mContext.registerReceiver(mBroadcastReceiver, filter);

mIsEnable = true;

}

}

1

2

3

4

5

6

7

8

9

10

11

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

private void enableImsStack() {

// Send IMS Enable to IMSM

VaEvent event = new VaEvent(Util.getDefaultVoltePhoneId(), MSG_ID_IMS_ENABLE_IND);

mIO.writeEvent(event);

return;

}

1

2

3

4

5

6

7

消息的定义如下:

int MSG_ID_IMS_ENABLE_IND = 900003; // MSG_ID_WRAP_IMSPA_IMSM_ENABLE_IND

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。

DataDispatcher.java

private void handleDefaultBearerActivationRequest(VaEvent event) {

//apn type为IMS

String apnType = PhoneConstants.APN_TYPE_IMS;

int phoneId = event.getPhoneId();

//请求数据封装成TransactionParam

DataDispatcherUtil.PdnActivationInd actInd = mDataDispatcherUtil

.extractDefaultPdnActInd(event);

TransactionParam param = new TransactionParam(actInd.transactionId,

event.getRequestID(), phoneId, apnType);

...

putTransaction(param);

if (apnType == PhoneConstants.APN_TYPE_IMS) {

int subId = SubscriptionManager.getSubIdUsingPhoneId(phoneId);

if (mSimStatus[phoneId] || subId > 0) {

mSimStatus[phoneId] = true;

//判断是否有合法的ims apn

if (!isImsApnExists(phoneId)) {

rejectDefaultBearerDataConnActivation(param, FAILCAUSE_UNKNOWN, 500);

return;

}

//设置超时,如果超过10秒没有进入开始连接的状态即触发

mHandler.removeMessages(MSG_ON_NOTIFY_ACTIVE_DATA_TIMEOUT);

mHandler.sendMessageDelayed(mHandler.obtainMessage(

MSG_ON_NOTIFY_ACTIVE_DATA_TIMEOUT, param),

MAX_NETWORK_ACTIVE_TIMEOUT_MS);

} else {

return;

}

}

//发起IMS连接请求

if (requestNwRequest(apnType, phoneId) < 0) {

rejectDefaultBearerDataConnActivation(param, FAILCAUSE_UNKNOWN, 0);

}

}

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发起连接请求。

private int requestNwRequest(String requestApnType, int phoneId) {

...

NetworkCallback nwCb = mDataNetworkRequests[pos].nwCb;

Builder builder = new NetworkRequest.Builder();

//IMS & EIMS

builder.addCapability(APN_CAP_LIST[pos]);

builder.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);

//指定为当前subId

builder.setNetworkSpecifier(String.valueOf(subId));

mDataNetworkRequests[pos].nwRequest = builder.build();

NetworkRequest nwRequest = mDataNetworkRequests[pos].nwRequest;

releaseNwRequest(requestApnType);

synchronized (mAPNStatuses) {

ApnStatus apnStatus = mAPNStatuses.get(requestApnType);

apnStatus.mName = requestApnType;//IMS

apnStatus.mStatus = TelephonyManager.DATA_DISCONNECTED;

apnStatus.isSendReq = true;

apnStatus.ifaceName = "";

//发起request

getConnectivityManager().requestNetwork(nwRequest, nwCb,

ConnectivityManager.MAX_NETWORK_REQUEST_TIMEOUT_MS);

}

...

return nRet;

}

private static final int[] APN_CAP_LIST = new int[] {

NetworkCapabilities.NET_CAPABILITY_IMS,

NetworkCapabilities.NET_CAPABILITY_EIMS

};

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

root@x6:/ # ifconfig

lo Link encap:Local Loopback

inet addr:127.0.0.1 Mask:255.0.0.0

inet6 addr: ::1/128 Scope: Host

UP LOOPBACK RUNNING MTU:65536 Metric:1

RX packets:46 errors:0 dropped:0 overruns:0 frame:0

TX packets:46 errors:0 dropped:0 overruns:0 carrier:0

collisions:0 txqueuelen:0

RX bytes:3992 TX bytes:3992

ccmni4 Link encap:Ethernet HWaddr 12:7A:92:06:07:BE

inet6 addr: 2409:8809:8590:da21:279:6506:7e0d:afdc/64 Scope: Global

inet6 addr: fe80::279:6506:7e0d:afdc/64 Scope: Link

UP RUNNING NOARP MTU:1410 Metric:1

RX packets:26 errors:0 dropped:0 overruns:0 frame:0

TX packets:29 errors:0 dropped:0 overruns:0 carrier:0

collisions:0 txqueuelen:1000

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连接已经建立

//DataDispatcher.java

private static final String IMS_INTERFACE_NAME = "ccmni4";

private void handleDefaultBearerActivationResponse(Network network, String type) {

TransactionParam deacTrans = findTransaction

(VaConstants.MSG_ID_WRAP_IMSM_IMSPA_PDN_DEACT_REQ, type);

synchronized (mAPNStatuses) {

ApnStatus apnStatus = mAPNStatuses.get(type);

if (deacTrans == null) {

apnStatus.mStatus = TelephonyManager.DATA_CONNECTED;

ConnectivityManager cm = (ConnectivityManager) mContext

.getSystemService(Context.CONNECTIVITY_SERVICE);

LinkProperties mLink = cm.getLinkProperties(network);

...

apnStatus.ifaceName = mLink.getInterfaceName();

//检查iface名字是否为"ccmni4"

if (IMS_INTERFACE_NAME.equals(apnStatus.ifaceName)

|| EMERGENCY_INTERFACE_NAME.equals(apnStatus.ifaceName)) {

//发送MSG_ID_WRAP_IMSM_IMSPA_PDN_ACT_REQ通知volte_imsm

responseDefaultBearerDataConnActivated(

findTransaction(VaConstants.MSG_ID_WRAP_IMSM_IMSPA_PDN_ACT_REQ, type),

network.netId, apnStatus.ifaceName);

}

...

}

...

}

}

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,并通知监听者。

//ImsService.java

//IMS所支持的capability

private static final int IMS_VOICE_OVER_LTE = 1;

private static final int IMS_RCS_OVER_LTE = 2;

private static final int IMS_SMS_OVER_LTE = 4;

private static final int IMS_VIDEO_OVER_LTE = 8;

private static final int IMS_VOICE_OVER_WIFI = 16;

public void handleMessage(Message msg) {

AsyncResult ar;

Intent intent;

int phoneId = getMainCapabilityPhoneId();

switch (msg.what) {

case EVENT_IMS_REGISTRATION_INFO:

ar = (AsyncResult) msg.obj;

//根据协议的规定,CIREGU返回消息的第一字段表示注册状态,第二个表示capability

/**

* According to 3GPP TS 27.007 +CIREGU format

*

* AsyncResult.result is an Object[]

* ((Object[])AsyncResult.result)[0] is integer type to indicate the IMS regiration status.

* 0: not registered

* 1: registered

* ((Object[])AsyncResult.result)[1] is numeric value in hexadecimal format to indicate the IMS capability.

* 1: RTP-based transfer of voice according to MMTEL (see 3GPP TS 24.173 [87])

* 2: RTP-based transfer of text according to MMTEL (see 3GPP TS 24.173 [87])

* 4: SMS using IMS functionality (see 3GPP TS 24.341[101])

* 8: RTP-based transfer of video according to MMTEL (see 3GPP TS 24.183 [87])

*

*/

//对比socketId是否当前的active phoneId

int socketId = ((int[]) ar.result)[2];

if (socketId != mActivePhoneId) {

break;

}

int newImsRegInfo = ServiceState.STATE_POWER_OFF;

//读取Ims的注册状态

if (((int[]) ar.result)[0] == 1) {

newImsRegInfo = ServiceState.STATE_IN_SERVICE;

} else {

newImsRegInfo = ServiceState.STATE_OUT_OF_SERVICE;

}

//读取当前支持的capability

int newImsExtInfo = ((int[]) ar.result)[1];

mImsRegInfo = newImsRegInfo;

//通知ims注册状态更新

notifyRegistrationStateChange(mImsRegInfo);

if ((mImsRegInfo == ServiceState.STATE_IN_SERVICE)) {

mImsExtInfo = newImsExtInfo;

} else {

mImsExtInfo = 0;

}

//通知ims capability更新

notifyRegistrationCapabilityChange(mImsExtInfo);

break;

...

}

...

}

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注册情况。

//ImsManager.java

private class ImsRegistrationListenerProxy extends IImsRegistrationListener.Stub {

private int mServiceClass;

private ImsConnectionStateListener mListener;

public ImsRegistrationListenerProxy(int serviceClass,

ImsConnectionStateListener listener) {

mServiceClass = serviceClass;

mListener = listener;

}

...

@Override

public void registrationConnected() {

if (mListener != null) {

mListener.onImsConnected();

}

}

@Override

public void registrationProgressing() {

if (mListener != null) {

mListener.onImsProgressing();

}

}

@Override

public void registrationDisconnected(ImsReasonInfo imsReasonInfo) {

if (mListener != null) {

mListener.onImsDisconnected(imsReasonInfo);

}

}

@Override

public void registrationResumed() {

if (mListener != null) {

mListener.onImsResumed();

}

}

@Override

public void registrationSuspended() {

if (mListener != null) {

mListener.onImsSuspended();

}

}

@Override

public void registrationFeatureCapabilityChanged(int serviceClass,

int[] enabledFeatures, int[] disabledFeatures) {

if (mListener != null) {

mListener.onFeatureCapabilityChanged(serviceClass,

enabledFeatures, disabledFeatures);

}

}

}

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广播。

ImsPhoneCallTracker.java

/**

* Listen to the IMS service state change

*

*/

private ImsConnectionStateListener mImsConnectionStateListener =

new ImsConnectionStateListener() {

@Override

public void onImsConnected() {

mPhone.setServiceState(ServiceState.STATE_IN_SERVICE);

mPhone.setImsRegistered(true);

}

@Override

public void onImsDisconnected(ImsReasonInfo imsReasonInfo) {

mPhone.setServiceState(ServiceState.STATE_OUT_OF_SERVICE);

mPhone.setImsRegistered(false);

mPhone.processDisconnectReason(imsReasonInfo);

if (imsReasonInfo != null && imsReasonInfo.getExtraMessage() != null

&& !imsReasonInfo.getExtraMessage().equals("")) {

mImsRegistrationErrorCode = Integer.parseInt(imsReasonInfo.getExtraMessage());

}

}

@Override

public void onImsProgressing() {

}

@Override

public void onImsResumed() {

mPhone.setServiceState(ServiceState.STATE_IN_SERVICE);

}

@Override

public void onImsSuspended() {

mPhone.setServiceState(ServiceState.STATE_OUT_OF_SERVICE);

}

@Override

public void onFeatureCapabilityChanged(int serviceClass,

int[] enabledFeatures, int[] disabledFeatures) {

if (serviceClass == ImsServiceClass.MMTEL) {

boolean tmpIsVideoCallEnabled = isVideoCallEnabled();

// Check enabledFeatures to determine capabilities. We ignore disabledFeatures.

for (int i = ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_LTE;

i <= ImsConfig.FeatureConstants.FEATURE_TYPE_VIDEO_OVER_WIFI; i++) {

if (enabledFeatures[i] == i) {

mImsFeatureEnabled[i] = true;

} else if (enabledFeatures[i]

== ImsConfig.FeatureConstants.FEATURE_TYPE_UNKNOWN) {

mImsFeatureEnabled[i] = false;

} else {

}

}

if (tmpIsVideoCallEnabled != isVideoCallEnabled()) {

mPhone.notifyForVideoCapabilityChanged(isVideoCallEnabled());

}

for (ImsPhoneConnection connection : mConnections) {

connection.updateWifiState();

}

mPhone.onFeatureCapabilityChanged();

broadcastImsStatusChange();

}

}

};

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:

06-02 16:47:44.925 D/ImsPhone( 2170): updateDataServiceState:

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

//imsServiceState

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注册过程来说并不完整,核心部分的协议及信令流程许多对上层来说是透明的,需要对这些部分深入了解后再做补充。

相关推荐

殷顗南蛮校尉
365账号投注被限制

殷顗南蛮校尉

📅 09-13 👁️ 8841
无冕之王荷兰,世界杯三获亚军却还不是最悲催!有一队四次输决赛
“saivian赛比安”网络传销案
365账号投注被限制

“saivian赛比安”网络传销案

📅 01-26 👁️ 4837