本文鏈接:https://blog.csdn.net/meiliqiang/article/details/78501947, 感謝作者
MTK IMS框架簡析(2)——IMS注冊過程
之前在《MTK IMS框架簡析(1)——代碼架構及模塊初始化》 中已經分析了ims代碼的構成和重點類的初始化,接下來以啟用VOLTE子功能為例,具體分析AP側IMS服務的注冊過程。
概要
IMS注冊前提是系統啟用了volte或wifi calling等功能,Volte開關一般在網絡設置界面會提供(如下圖),用戶切換開關狀態將觸發ims的注冊或注銷。
啟用Volte后的消息傳遞序列(這里時序圖避免復雜化,只表現消息的正向傳遞,忽略消息的返回)
整個過程大致分為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
-
-
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並沒有開源:
-
-
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;
-
}
-
-
...
-
-
-
public void registrationConnected() {
-
if (mListener != null) {
-
mListener.onImsConnected();
-
}
-
}
-
-
-
public void registrationProgressing() {
-
if (mListener != null) {
-
mListener.onImsProgressing();
-
}
-
}
-
-
-
public void registrationDisconnected(ImsReasonInfo imsReasonInfo) {
-
if (mListener != null) {
-
mListener.onImsDisconnected(imsReasonInfo);
-
}
-
}
-
-
-
public void registrationResumed() {
-
if (mListener != null) {
-
mListener.onImsResumed();
-
}
-
}
-
-
-
public void registrationSuspended() {
-
if (mListener != null) {
-
mListener.onImsSuspended();
-
}
-
}
-
-
-
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() {
-
-
public void onImsConnected() {
-
mPhone.setServiceState(ServiceState.STATE_IN_SERVICE);
-
mPhone.setImsRegistered( true);
-
}
-
-
-
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());
-
}
-
}
-
-
-
public void onImsProgressing() {
-
}
-
-
-
public void onImsResumed() {
-
mPhone.setServiceState(ServiceState.STATE_IN_SERVICE);
-
}
-
-
-
public void onImsSuspended() {
-
mPhone.setServiceState(ServiceState.STATE_OUT_OF_SERVICE);
-
}
-
-
-
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注冊過程來說並不完整,核心部分的協議及信令流程許多對上層來說是透明的,需要對這些部分深入了解后再做補充。