ims Registered and Volte enable on Android N

转载请注明出处: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作为参数。
   
   
  1. /**
  2. * Returns the IMS Registration Status
  3. * @hide
  4. */
  5. public boolean isImsRegistered() {
  6. try {
  7. ITelephony telephony = getITelephony();
  8. if (telephony == null)
  9. return false;
  10. return telephony.isImsRegistered();
  11. } catch (RemoteException ex) {
  12. return false;
  13. } catch (NullPointerException ex) {
  14. return false;
  15. }
  16. }

    
    
  1. /**
  2. * Returns the IMS Registration Status
  3. * using subId
  4. * @hide
  5. */
  6. public boolean isImsRegisteredForSubscriber(int subId) {
  7. try {
  8. ITelephony telephony = getITelephony();
  9. if (telephony == null)
  10. return false;
  11. return telephony.isImsRegisteredForSubscriber(subId);
  12. } catch (RemoteException ex) {
  13. return false;
  14. } catch (NullPointerException ex) {
  15. return false;
  16. }
  17. }

下面这个方法返回的是VoLTE status
   
   
  1. /**
  2. * Returns the Status of Volte
  3. * @hide
  4. */
  5. public boolean isVolteAvailable() {
  6. try {
  7. return getITelephony().isVolteAvailable();
  8. } catch (RemoteException ex) {
  9. return false;
  10. } catch (NullPointerException ex) {
  11. return false;
  12. }
  13. }
到现在为止我们知道TelephonyManager.java中有三个hide方法返回ims registered和VoLTE Status,但都是hide方法,不对第三方应用公开。

packages/services/Telephony
PhoneInterfacemanager.java
到了这可以看到,两个方法调用的都是Phone.java 里的registered()方法(当然,实际调用的是ImsPhone.java里的同名方法)。
    
    
  1. @Override
  2. public boolean isImsRegistered() {
  3. return mPhone.registered();
  4. }
  5. /*
  6. * {@hide}
  7. * Returns the IMS Registration Status based on subId
  8. */
  9. public boolean isImsRegisteredForSubscriber(int subId) {
  10. final Phone phone = getPhone(subId);
  11. if (phone != null) {
  12. return phone.isImsRegistered();
  13. }
  14. return false;
  15. }
然后下面这个是VoLTE的, isVolteAvailable和isVolteEnabled居然是等价的,意味着开启即可用?
    
    
  1. /*
  2. * {@hide}
  3. * Returns the IMS Registration Status
  4. */
  5. public boolean isVolteAvailable() {
  6. return mPhone.isVolteEnabled();
  7. }
然后观察到这个类里面还有个方法来设置ims registration status的,但是吧其实这个方法没有使用到。
    
    
  1. public void setImsRegistrationState(boolean registered) {
  2. enforceModifyPermission();
  3. mPhone.setImsRegistrationState(registered);
  4. }
Phone.java
这个方法只在GsmCdmaPhone.java里面重写了,但是GsmCdmaPhone会有ims服务?
    
    
  1. /**
  2. * Set IMS registration state
  3. */
  4. public void setImsRegistrationState(boolean registered) {
  5. }

ImsRegistered的最终取值

fw/opt/telephony
ImsPhone.java
下面便是Ims registered 取值的终点,接下来看的 赋值(更新)的地方。
setImsRegistered()正是给mImsRegistered 赋值的地方
   
   
  1. @Override
  2. public boolean isImsRegistered() {
  3. return mImsRegistered;
  4. }
  5. public void setImsRegistered(boolean value) {
  6. mImsRegistered = value;
  7. }
而Volte的取值还需再跟进一步
    
    
  1. @Override
  2. public boolean isVolteEnabled() {
  3. return mCT.isVolteEnabled();
  4. }

VolteEnabled的最终取值

fw/opt/telephony
ImsPhoneCallTracker.java
来自一个布尔值,其实是一个布尔数组里面的其中一个值。
    
    
  1. public boolean isVolteEnabled() {
  2. return mImsFeatureEnabled[ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_LTE];
  3. }

Ims Registered 的更新

巧合的是ims registered的更新也是在这个类里面
   
   
  1. /**
  2. * Listen to the IMS service state change
  3. *
  4. */
  5. private ImsConnectionStateListener mImsConnectionStateListener =
  6. new ImsConnectionStateListener() {
  7. @Override
  8. public void onImsConnected() {
  9. if (DBG) log("onImsConnected");
  10. mPhone.setServiceState(ServiceState.STATE_IN_SERVICE);
  11. mPhone.setImsRegistered(true);
  12. mMetrics.writeOnImsConnectionState(mPhone.getPhoneId(),
  13. ImsConnectionState.State.CONNECTED, null);
  14. }
  15. @Override
  16. public void onImsDisconnected(ImsReasonInfo imsReasonInfo) {
  17. if (DBG) log("onImsDisconnected imsReasonInfo=" + imsReasonInfo);
  18. mPhone.setServiceState(ServiceState.STATE_OUT_OF_SERVICE);
  19. mPhone.setImsRegistered(false);
  20. mPhone.processDisconnectReason(imsReasonInfo);
  21. mMetrics.writeOnImsConnectionState(mPhone.getPhoneId(),
  22. ImsConnectionState.State.DISCONNECTED, imsReasonInfo);
  23. }
  24. @Override
  25. public void onImsProgressing() {
  26. if (DBG) log("onImsProgressing");
  27. mPhone.setServiceState(ServiceState.STATE_OUT_OF_SERVICE);
  28. mPhone.setImsRegistered(false);
  29. mMetrics.writeOnImsConnectionState(mPhone.getPhoneId(),
  30. ImsConnectionState.State.PROGRESSING, null);
  31. }
  32. ...
  33. }
上面的代码显示,在Ims 连接后设置setImsRegistered 为true,在 断开后正在连接的时候都设置为false。

VolteEnable 的更新 

fw/opt/telephony
ImsPhoneCallTracker.java
Volte的更新也来自ImsConnectionStateListener,更新的是我们取值的那个布尔变量。
除此之外还有两个地方用到了ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_LTE, 但是和这里无关。
其一:
还是在ImsConnectionStateListener里面,
    
    
  1. /**
  2. * Listen to the IMS service state change
  3. *
  4. */
  5. private ImsConnectionStateListener mImsConnectionStateListener =
  6. new ImsConnectionStateListener() {
  7. ...
  8. @Override
  9. public void onFeatureCapabilityChanged(int serviceClass,
  10. int[] enabledFeatures, int[] disabledFeatures) {
  11. if (serviceClass == ImsServiceClass.MMTEL) {
  12. boolean tmpIsVideoCallEnabled = isVideoCallEnabled();
  13. // Check enabledFeatures to determine capabilities. We ignore disabledFeatures.
  14. StringBuilder sb;
  15. if (DBG) {
  16. sb = new StringBuilder(120);
  17. sb.append("onFeatureCapabilityChanged: ");
  18. }
  19. for (int i = ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_LTE;
  20. i <= ImsConfig.FeatureConstants.FEATURE_TYPE_UT_OVER_WIFI &&
  21. i < enabledFeatures.length; i++) {
  22. if (enabledFeatures[i] == i) {
  23. // If the feature is set to its own integer value it is enabled.
  24. if (DBG) {
  25. sb.append(mImsFeatureStrings[i]);
  26. sb.append(":true ");
  27. }
  28. mImsFeatureEnabled[i] = true;
  29. } else if (enabledFeatures[i]
  30. == ImsConfig.FeatureConstants.FEATURE_TYPE_UNKNOWN) {
  31. // FEATURE_TYPE_UNKNOWN indicates that a feature is disabled.
  32. if (DBG) {
  33. sb.append(mImsFeatureStrings[i]);
  34. sb.append(":false ");
  35. }
  36. mImsFeatureEnabled[i] = false;
这个方法重写自:
ImsConnectionStateListener.java
这个是跟IMS连接紧密相关的
      
      
  1. /**
  2. * Called when its current IMS connection feature capability changes.
  3. */
  4. public void onFeatureCapabilityChanged(int serviceClass,
  5. int[] enabledFeatures, int[] disabledFeatures) {
  6. // no-op
  7. }
上面的方法调用自:
fw/opt/net
ImsManager.java
    
    
  1. @Override
  2. public void registrationFeatureCapabilityChanged(int serviceClass,
  3. int[] enabledFeatures, int[] disabledFeatures) {
  4. log("registrationFeatureCapabilityChanged :: serviceClass=" +
  5. serviceClass);
  6. if (mListener != null) {
  7. mListener.onFeatureCapabilityChanged(serviceClass,
  8. enabledFeatures, disabledFeatures);
  9. }
  10. }

后面两种是在ImsManager.java 这个类中的更新,更新的值保存在新建的ImsConfig对象中,值得注意的是,并没有哪块代码去getFeatureValue。如读者不关心这部分可以直接跳到文末总结部分。
其二:
fw/opt/net
ImsManager.java 
可以看到首先创建了一个ImsConfig对象,然后通过setFeatureValue()方法对ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_LTE进行更新。
    
    
  1. private void setLteFeatureValues(boolean turnOn) {
  2. log("setLteFeatureValues: " + turnOn);
  3. try {
  4. ImsConfig config = getConfigInterface();
  5. if (config != null) {
  6. config.setFeatureValue(ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_LTE,
  7. TelephonyManager.NETWORK_TYPE_LTE, turnOn ? 1 : 0, mImsConfigListener);
  8. if (isVtEnabledByPlatform(mContext)) {
  9. boolean ignoreDataEnabledChanged = getBooleanCarrierConfig(mContext,
  10. CarrierConfigManager.KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS);
  11. boolean enableViLte = turnOn && isVtEnabledByUser(mContext) &&
  12. (ignoreDataEnabledChanged || isDataEnabled());
  13. config.setFeatureValue(ImsConfig.FeatureConstants.FEATURE_TYPE_VIDEO_OVER_LTE,
  14. TelephonyManager.NETWORK_TYPE_LTE,
  15. enableViLte ? 1 : 0,
  16. mImsConfigListener);
  17. }
  18. }
  19. } catch (ImsException e) {
  20. loge("setLteFeatureValues: exception ", e);
  21. }
  22. }
查看方法调用得知,是用户在界面上开启enhanced_4g_lte这个开关才更新的,我们推断这次更新只和用户设置有关系,和网络没有关系,但这似乎是不合理的。
除了更新ImsConfig还更新了Settings 数据库中的存储。
图 略
 
其三:
    
    
  1. /**
  2. * Update VoLTE config
  3. * @return whether feature is On
  4. * @throws ImsException
  5. */
  6. private boolean updateVolteFeatureValue() throws ImsException {
  7. boolean available = isVolteEnabledByPlatform(mContext);//平台支持
  8. boolean enabled = isEnhanced4gLteModeSettingEnabledByUser(mContext);//开关打开
  9. boolean isNonTty = isNonTtyOrTtyOnVolteEnabled(mContext);
  10. boolean isFeatureOn = available && enabled && isNonTty;
  11. log("updateVolteFeatureValue: available = " + available
  12. + ", enabled = " + enabled
  13. + ", nonTTY = " + isNonTty);
  14. getConfigInterface().setFeatureValue(
  15. ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_LTE,
  16. TelephonyManager.NETWORK_TYPE_LTE,
  17. isFeatureOn ?
  18. ImsConfig.FeatureValueConstants.ON :
  19. ImsConfig.FeatureValueConstants.OFF,
  20. mImsConfigListener);
  21. return isFeatureOn;
  22. }
查看方法调用我们推断,这次更新依赖于Ims网络服务。但是这个更新条件的Action是Action to broadcast when ImsService is up。这样看来这里似乎只有在IMS服务建立的时候才会执行。
图 略
其中Intent action
    
    
  1. /**
  2. * Action to broadcast when ImsService is up.
  3. * Internal use only.
  4. * @hide
  5. */
  6. public static final String ACTION_IMS_SERVICE_UP =
  7. "com.android.ims.IMS_SERVICE_UP";

整理流程:

 

总结

ImsRegistered的取值来自ImsPhone.java的mImsRegistered,这个值 取决于ims网络连接状态。在Telephony中的接口为hide方法,对第三方不可见。
VolteAvailable的取值来自ImsPhoneCallTracker.java的 ImsConnectionStateListener, ImsConnectionStateListener监听onFeatureCapabilityChanged来更新(布尔值)。 在Telephony中的接口为hide方法,同样对第三方不可见。
以上两者更新的关键方法都在ImsPhoneCallTracker.java的 ImsConnectionStateListener里。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值