转载请注明出处:http://blog.csdn.net/aaa111/article/details/73872220
文前
代码基于mkm-mr1 android 7.1.2
本篇记录了调查ims Registered状态和VoLTE enable状态的一些取值和更新的关键方法。
初衷是调查ims
registered
状态和 VoLTE Available
有没有对外提供接口,以及这两者有什么逻辑上的关系。
PS:本文采取“双线叙事”,同时调查ims Registered和Volte enable的关键方法,如果读者感觉有点乱,可以一次只看ims或者volte(这意味着你要看两遍,其实是我懒不想分开写)。
正文
TelephonyManager.java向系统其他应用(Settings,SystemUI)提供接口,为什么说是“
系统其他应用
”呢?
因为以下几个方法都是@hide方法,不对第三方应用公开。
fw/base/telephony
TelephonyManager.java
以下两个方法都是获得ims registered的方法,区别在于第二个方法需传入subId作为参数。
/*** Returns the IMS Registration Status* @hide*/public boolean isImsRegistered() {try {ITelephony telephony = getITelephony();if (telephony == null)return false;return telephony.isImsRegistered();} catch (RemoteException ex) {return false;} catch (NullPointerException ex) {return false;}}
/** * Returns the IMS Registration Status * using subId * @hide */ public boolean isImsRegisteredForSubscriber(int subId) { try { ITelephony telephony = getITelephony(); if (telephony == null) return false; return telephony.isImsRegisteredForSubscriber(subId); } catch (RemoteException ex) { return false; } catch (NullPointerException ex) { return false; } }
下面这个方法返回的是VoLTE status
/*** Returns the Status of Volte* @hide*/public boolean isVolteAvailable() {try {return getITelephony().isVolteAvailable();} catch (RemoteException ex) {return false;} catch (NullPointerException ex) {return false;}}
到现在为止我们知道TelephonyManager.java中有三个hide方法返回ims registered和VoLTE Status,但都是hide方法,不对第三方应用公开。
packages/services/Telephony
PhoneInterfacemanager.java
到了这可以看到,两个方法调用的都是Phone.java 里的registered()方法(当然,实际调用的是ImsPhone.java里的同名方法)。
@Override public boolean isImsRegistered() { return mPhone.registered(); } /* * {@hide} * Returns the IMS Registration Status based on subId */ public boolean isImsRegisteredForSubscriber(int subId) { final Phone phone = getPhone(subId); if (phone != null) { return phone.isImsRegistered(); } return false; }
然后下面这个是VoLTE的,
isVolteAvailable和isVolteEnabled居然是等价的,意味着开启即可用?
/* * {@hide} * Returns the IMS Registration Status */ public boolean isVolteAvailable() { return mPhone.isVolteEnabled(); }
然后观察到这个类里面还有个方法来设置ims registration status的,但是吧其实这个方法没有使用到。
public void setImsRegistrationState(boolean registered) { enforceModifyPermission(); mPhone.setImsRegistrationState(registered); }
Phone.java
这个方法只在GsmCdmaPhone.java里面重写了,但是GsmCdmaPhone会有ims服务?
/** * Set IMS registration state */ public void setImsRegistrationState(boolean registered) { }
ImsRegistered的最终取值
fw/opt/telephony
ImsPhone.java
下面便是Ims registered
取值的终点,接下来看的
赋值(更新)的地方。
setImsRegistered()正是给mImsRegistered 赋值的地方
@Overridepublic boolean isImsRegistered() {return mImsRegistered;}public void setImsRegistered(boolean value) {mImsRegistered = value;}
而Volte的取值还需再跟进一步
@Override public boolean isVolteEnabled() { return mCT.isVolteEnabled(); }
VolteEnabled的最终取值
fw/opt/telephony
ImsPhoneCallTracker.java
来自一个布尔值,其实是一个布尔数组里面的其中一个值。
public boolean isVolteEnabled() { return mImsFeatureEnabled[ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_LTE]; }
Ims Registered 的更新
巧合的是ims registered的更新也是在这个类里面
/*** Listen to the IMS service state change**/private ImsConnectionStateListener mImsConnectionStateListener =new ImsConnectionStateListener() {@Overridepublic void onImsConnected() {if (DBG) log("onImsConnected");mPhone.setServiceState(ServiceState.STATE_IN_SERVICE);mPhone.setImsRegistered(true);mMetrics.writeOnImsConnectionState(mPhone.getPhoneId(),ImsConnectionState.State.CONNECTED, null);}@Overridepublic void onImsDisconnected(ImsReasonInfo imsReasonInfo) {if (DBG) log("onImsDisconnected imsReasonInfo=" + imsReasonInfo);mPhone.setServiceState(ServiceState.STATE_OUT_OF_SERVICE);mPhone.setImsRegistered(false);mPhone.processDisconnectReason(imsReasonInfo);mMetrics.writeOnImsConnectionState(mPhone.getPhoneId(),ImsConnectionState.State.DISCONNECTED, imsReasonInfo);}@Overridepublic void onImsProgressing() {if (DBG) log("onImsProgressing");mPhone.setServiceState(ServiceState.STATE_OUT_OF_SERVICE);mPhone.setImsRegistered(false);mMetrics.writeOnImsConnectionState(mPhone.getPhoneId(),ImsConnectionState.State.PROGRESSING, null);}...}
上面的代码显示,在Ims
连接后设置setImsRegistered 为true,在
断开后和
正在连接的时候都设置为false。
VolteEnable 的更新
fw/opt/telephony
ImsPhoneCallTracker.java
Volte的更新也来自ImsConnectionStateListener,更新的是我们取值的那个布尔变量。
除此之外还有两个地方用到了ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_LTE,
但是和这里无关。
其一:
还是在ImsConnectionStateListener里面,
/** * Listen to the IMS service state change * */ private ImsConnectionStateListener mImsConnectionStateListener = new ImsConnectionStateListener() { ... @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. StringBuilder sb; if (DBG) { sb = new StringBuilder(120); sb.append("onFeatureCapabilityChanged: "); } for (int i = ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_LTE; i <= ImsConfig.FeatureConstants.FEATURE_TYPE_UT_OVER_WIFI && i < enabledFeatures.length; i++) { if (enabledFeatures[i] == i) { // If the feature is set to its own integer value it is enabled. if (DBG) { sb.append(mImsFeatureStrings[i]); sb.append(":true "); } mImsFeatureEnabled[i] = true; } else if (enabledFeatures[i] == ImsConfig.FeatureConstants.FEATURE_TYPE_UNKNOWN) { // FEATURE_TYPE_UNKNOWN indicates that a feature is disabled. if (DBG) { sb.append(mImsFeatureStrings[i]); sb.append(":false "); } mImsFeatureEnabled[i] = false;
这个方法重写自:
ImsConnectionStateListener.java
这个是跟IMS连接紧密相关的
/** * Called when its current IMS connection feature capability changes. */ public void onFeatureCapabilityChanged(int serviceClass, int[] enabledFeatures, int[] disabledFeatures) { // no-op }
上面的方法调用自:
fw/opt/net
ImsManager.java
@Override public void registrationFeatureCapabilityChanged(int serviceClass, int[] enabledFeatures, int[] disabledFeatures) { log("registrationFeatureCapabilityChanged :: serviceClass=" + serviceClass); if (mListener != null) { mListener.onFeatureCapabilityChanged(serviceClass, enabledFeatures, disabledFeatures); } }
后面两种是在ImsManager.java 这个类中的更新,更新的值保存在新建的ImsConfig对象中,值得注意的是,并没有哪块代码去getFeatureValue。如读者不关心这部分可以直接跳到文末总结部分。
其二:
fw/opt/net
ImsManager.java
可以看到首先创建了一个ImsConfig对象,然后通过setFeatureValue()方法对ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_LTE进行更新。
private 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 (isVtEnabledByPlatform(mContext)) { boolean ignoreDataEnabledChanged = getBooleanCarrierConfig(mContext, CarrierConfigManager.KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS); boolean enableViLte = turnOn && isVtEnabledByUser(mContext) && (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); } }
查看方法调用得知,是用户在界面上开启enhanced_4g_lte这个开关才更新的,我们推断这次更新只和用户设置有关系,和网络没有关系,但这似乎是不合理的。
除了更新ImsConfig还更新了Settings 数据库中的存储。
图 略
其三:
/** * Update VoLTE config * @return whether feature is On * @throws ImsException */ private boolean updateVolteFeatureValue() throws ImsException { boolean available = isVolteEnabledByPlatform(mContext);//平台支持 boolean enabled = isEnhanced4gLteModeSettingEnabledByUser(mContext);//开关打开 boolean isNonTty = isNonTtyOrTtyOnVolteEnabled(mContext); boolean isFeatureOn = available && enabled && isNonTty; log("updateVolteFeatureValue: available = " + available + ", enabled = " + enabled + ", nonTTY = " + isNonTty); getConfigInterface().setFeatureValue( ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_LTE, TelephonyManager.NETWORK_TYPE_LTE, isFeatureOn ? ImsConfig.FeatureValueConstants.ON : ImsConfig.FeatureValueConstants.OFF, mImsConfigListener); return isFeatureOn; }
查看方法调用我们推断,这次更新依赖于Ims网络服务。但是这个更新条件的Action是Action to broadcast when ImsService is up。这样看来这里似乎只有在IMS服务建立的时候才会执行。
图 略
其中Intent action
/** * Action to broadcast when ImsService is up. * Internal use only. * @hide */ public static final String ACTION_IMS_SERVICE_UP = "com.android.ims.IMS_SERVICE_UP";
整理流程:
总结
ImsRegistered的取值来自ImsPhone.java的mImsRegistered,这个值
取决于ims网络连接状态。在Telephony中的接口为hide方法,对第三方不可见。
VolteAvailable的取值来自ImsPhoneCallTracker.java的
ImsConnectionStateListener,
ImsConnectionStateListener监听onFeatureCapabilityChanged来更新(布尔值)。
在Telephony中的接口为hide方法,同样对第三方不可见。
以上两者更新的关键方法都在ImsPhoneCallTracker.java的
ImsConnectionStateListener里。
本文深入探讨了Android系统中IMS Registered状态和VoLTE Available状态的实现原理,包括它们的获取方法及更新机制。

1万+

被折叠的 条评论
为什么被折叠?



