zoukankan      html  css  js  c++  java
  • 开关VoLTE流程分析(一)

    开关按钮位置:
      设置--> 更多--> 移动网络--> 增强型4G LTE模式

    控件初始化addEnhanced4GLteSwitchPreference,该设置开关使用了SwitchPreference控件,addEnhanced4GLteSwitchPreference()添加控件(packages/services/telephony/src/com/android/phone/MobileNetworkSettings.java)

        private void addEnhanced4GLteSwitchPreference(PreferenceScreen preferenceScreen) {
            log("[addEnhanced4GLteSwitchPreference] ImsEnabled :"
                    + ImsManager.isVolteEnabledByPlatform(this));
            if (mButton4glte != null) { //去掉Google原生开关按钮
                log("[addEnhanced4GLteSwitchPreference] Remove mButton4glte!");
                preferenceScreen.removePreference(mButton4glte);
            }
            if (ImsManager.isVolteEnabledByPlatform(this)) { //判断是否支持VoLTE
                int order = mButtonEnabledNetworks.getOrder() + 1;
                         //VoLTE开关初始化
                mEnhancedButton4glte = new Enhanced4GLteSwitchPreference(this, mPhone.getSubId()); 
                /// Still use Google's key, title, and summary.
                mEnhancedButton4glte.setKey(BUTTON_4G_LTE_KEY); //Key用于SharePreference存储信息
                if (ImsManager.isWfcEnabledByPlatform(this)) { //判断是否支持WIFI Call
                    mEnhancedButton4glte.setTitle(R.string.wfc_volte_switch_title);
                } else {
                    mEnhancedButton4glte.setTitle(R.string.enhanced_4g_lte_mode_title);
                }
                mEnhancedButton4glte.setSummary(R.string.enhanced_4g_lte_mode_summary);
                mEnhancedButton4glte.setOnPreferenceChangeListener(this); //设置监听接口,状态发生变化onPreferenceChange()方法将被调用
                mEnhancedButton4glte.setOrder(order);
                //preferenceScreen.addPreference(mEnhancedButton4glte);
            }

    监听方法onPreferenceChangeMTK,该接听方法onPreferenceChangeMTK(),重新原生onPreferenceChange();

        private boolean onPreferenceChangeMTK(Preference preference, Object objValue) {
            log("[onPreferenceChangeMTK] preference = " + preference.getTitle());
            if (mEnhancedButton4glte == preference) { 
                log("[onPreferenceChangeMTK] IsChecked = " + mEnhancedButton4glte.isChecked());
                Enhanced4GLteSwitchPreference ltePref = (Enhanced4GLteSwitchPreference) preference;
                ltePref.setChecked(!ltePref.isChecked()); //设置控件状态,默认关闭是false,打开即是true
                ImsManager.setEnhanced4gLteModeSetting(this, ltePref.isChecked()); //设置VoLTE参数
                return true;
            }
            return false;
        }

    有如下打印信息:

    设置VoLTE状态setEnhanced4gLteModeSetting,frameworks/opt/net/ims/src/java/com/android/ims/ImsManager.java

        public static void setEnhanced4gLteModeSetting(Context context, boolean enabled) {
            int value = enabled ? 1 : 0;
              //设置Settings.Global.ENHANCED_4G_MODE_ENABLED变量
            android.provider.Settings.Global.putInt(
                    context.getContentResolver(),
                    android.provider.Settings.Global.ENHANCED_4G_MODE_ENABLED, value);
    
            if (isNonTtyOrTtyOnVolteEnabled(context)) { //不支持TTY或者VoLTE支持TTY
                ImsManager imsManager = ImsManager.getInstance(context,
                        SubscriptionManager.getDefaultVoicePhoneId()); //获取ImsManager对象
                if (imsManager != null) {
                    try {
                        imsManager.setAdvanced4GMode(enabled); //设置VoLTE
                    } catch (ImsException ie) {
                        // do nothing
                    }
                }
            }
        }

    设置VoLTE

        private void setAdvanced4GMode(boolean turnOn) throws ImsException {
            checkAndThrowExceptionIfServiceUnavailable();
    
            try {
                ImsConfig config = getConfigInterface(); //IMS 配置参数
                if (config != null) {
                                 //设置FeatureConstants.FEATURE_TYPE_VOICE_OVER_LTE网络参数
                    config.setFeatureValue(ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_LTE,
                            TelephonyManager.NETWORK_TYPE_LTE, turnOn ? 1 : 0, null);
                }
            } catch (ImsException e) {
                log("setAdvanced4GMode() : " + e);
            }
    
            log("setAdvanced4GMode():" + turnOn);
            if (turnOn) {
                turnOnIms(); //打开IMS 服务
            } else if (isImsTurnOffAllowed()) {
                log("setAdvanced4GMode() : imsServiceAllowTurnOff -> turnOffIms");
                turnOffIms(); //关闭IMS 服务
            }

    有如下打印信息:

    打开IMS 服务

        private void turnOnIms() throws ImsException {
            checkAndThrowExceptionIfServiceUnavailable();
    
            try {
                mImsService.turnOnIms(mPhoneId);
            } catch (RemoteException e) {
                throw new ImsException("turnOnIms() ", e, ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
            }
        }

    mImsService 是IImsService 的实例对象,该对象在createImsService()中创建:

           //绑定IMS Service
        private void createImsService(boolean checkService) {
            if (checkService) { //判断IMS Service 服务是否已经存在
                IBinder binder = ServiceManager.checkService(getImsServiceName(mPhoneId));
    
                if (binder == null) {
                    /// M: add for debug @{
                    if (DBG) log("ImsManager: createImsService binder is null");
                    /// @}
                    return;
                }
            }
            //获取指向Service的IBinder对象
            IBinder b = ServiceManager.getService(getImsServiceName(mPhoneId));
    
            if (b != null) {
                try {
                    b.linkToDeath(mDeathRecipient, 0);
                } catch (RemoteException e) {
                }
            }
    
            mImsService = IImsService.Stub.asInterface(b);
            /// M: add for debug @{
            if (DBG) log("ImsManager: mImsService = " + mImsService);
            /// @}
            }

    getImsServiceName()获取IMS Service 名:

        private static String getImsServiceName(int phoneId) {
            // TODO: MSIM implementation needs to decide on service name as a function of phoneId
            return IMS_SERVICE;  //服务名即"ims"
        }

    而getImsServiceName()方法在ImsManager类的构造方法中即被调用,所以mImsService对象开机即获取到。

    方法turnOnIms,调用mImsService的turnOnIms()方法在IImsService.Stub继承类中实现:

    vendor/mediatek/proprietary/packages/services/ims/src/com/mediatek/ims/ImsService.java

        /**
         * Used for turning on IMS when its in OFF state.
         */
        @Override
        public void turnOnIms(int phoneId) {
            Rlog.d(LOG_TAG, "turnOnIms, mActivePhoneId = " + mActivePhoneId +
                " phoneId = " + phoneId);
            phoneId = getMainCapabilityPhoneId();
            Rlog.d(LOG_TAG, "turnOnIms, MainCapabilityPhoneId = " + phoneId);
    
            if (mActivePhoneId != phoneId) {
                mActivePhoneId = phoneId;
            }
        }
       /**
        * to get main capability phone id.
        *
        * @return The phone id with highest capability.
        */
       private int getMainCapabilityPhoneId() { //此接口可能获取主卡phoneID
                 //获取服务"phoneEx"
           ITelephonyEx telephony = ITelephonyEx.Stub.asInterface(
                   ServiceManager.getService(mContext.TELEPHONY_SERVICE_EX));
    
           if (telephony != null) {
               try {
                   int mainPhoneId = telephony.getMainCapabilityPhoneId(); //调用getMainCapabilityPhoneId()方法
                   Rlog.d(LOG_TAG, "getMainCapabilityPhoneId: mainPhoneId = " + mainPhoneId);
                   return mainPhoneId;
               }
               ..........
           } 
       }

    有如下打印信息:

    获取主PhoneID

    PhoneInterfaceManagerEx extends ITelephonyEx.Stub;
    packages/services/telephony/src/com/mediatek/phone/PhoneInterfaceManagerEx.java

        /**
         * Get main capability phone id.
         * @return The phone id with highest capability.
         */
        public int getMainCapabilityPhoneId() {
            return RadioCapabilitySwitchUtil.getMainCapabilityPhoneId();
        }

    创建ImsConfig,在setAdvanced4GMode()接口中,获取ImsConfig对象:

                ImsConfig config = getConfigInterface();
                if (config != null) {
                    config.setFeatureValue(ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_LTE,
                            TelephonyManager.NETWORK_TYPE_LTE, turnOn ? 1 : 0, null);
                }

    getConfigInterface()的实现:

        public ImsConfig getConfigInterface() throws ImsException {
            checkAndThrowExceptionIfServiceUnavailable();
            // M: Remove cache of ImsConfig in AOSP, always get ImsConfig with mainCapability Id 
            mConfig = getConfigInterface(mPhoneId, mImsService, mContext);
            return mConfig;
        }
    
        public static ImsConfig getConfigInterface(int phoneId, IImsService service, Context context) throws ImsException {
            ImsConfig config = null;
    
            try {
                if (service == null) { //获取IMS服务
                    IBinder b = ServiceManager.getService(getImsServiceName(phoneId));
                    service = IImsService.Stub.asInterface(b); 
                }
    
                IImsConfig binder = service.getConfigInterface(phoneId); //调用ImsService的getConfigInterface()接口
                if (binder == null) {
                    throw new ImsException("getConfigInterface()",
                                ImsReasonInfo.CODE_LOCAL_SERVICE_UNAVAILABLE);
                }
    
                config = new ImsConfig(binder, context); //初始化ImsConfig对象
            } catch (RemoteException e) {
                throw new ImsException("getConfigInterface()", e,
                    ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
            }
            if (DBG) log("getConfigInterface(), config= " + config);
            return config;

    根据PhoneID创建IImsConfig

    根据Log打印信息,获取Main Phone ID创建ImsConfig配置文件:

     

    该接口ImsService.java中定义:
    vendor/mediatek/proprietary/packages/services/ims/src/com/mediatek/ims/ImsService.java

      //Config interface to get/set IMS service/capability parameters.
        public IImsConfig getConfigInterface(int phoneId) {
            // Always get main capability phone Id for ImsConfig
            phoneId = getMainCapabilityPhoneId();
            Rlog.w(LOG_TAG, "Get config interface on main capability phone " + phoneId);
    
            IImsConfig instance = null;
            Rlog.w(LOG_TAG, "getConfigInterface phone " + phoneId);
            synchronized (mImsConfigInstanceMap) {
                if (mImsConfigInstanceMap.containsKey(phoneId)) {
                    instance = mImsConfigInstanceMap.get(phoneId);
                } else {
                    instance = new ImsConfigImpl(mContext, mImsRILAdapter, phoneId);
                    mImsConfigInstanceMap.put(phoneId, instance);
                }
            }
            return instance;

    IImsConfig是一个接口类,定义:
    frameworks/base/telephony/java/com/android/ims/internal/IImsConfig.aidl
    该类由ImsConfigImpl类继承,实现其接口函数;

    初始化ImsConfig对象,ImsConfigImpl对象的初始化后,传给ImsConfig类的构造函数,创建ImsConfig:

    frameworks/opt/net/ims/src/java/com/android/ims/ImsConfig.java

        public ImsConfig(IImsConfig iconfig, Context context) {
            if (DBG) Rlog.d(TAG, "ImsConfig creates");
            miConfig = iconfig; //IImsConfig对象由ImsConfigImpl初始化完成
            mContext = context;
        }

    设置FeatureValue,在setAdvanced4GMode()接口中,设置FeatureValue,调用ImsConfig接口:

                if (config != null) {
                    config.setFeatureValue(ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_LTE,
                            TelephonyManager.NETWORK_TYPE_LTE, turnOn ? 1 : 0, null);
                }
    
        /**
         * Sets the value for IMS feature item for specified network type.
         *
         * @param feature, as defined in FeatureConstants.
         * @param network, as defined in android.telephony.TelephonyManager#NETWORK_TYPE_XXX.
         * @param value, as defined in FeatureValueConstants.
         * @param listener, provided if caller needs to be notified for set result.
         * @return void
         *
         * @throws ImsException if calling the IMS service results in an error.
         */
        public void setFeatureValue(int feature, int network, int value,
                ImsConfigListener listener) throws ImsException {
            if (DBG) {
                Rlog.d(TAG, "setFeatureValue: feature = " + feature + ", network =" + network +
                        ", value =" + value + ", listener =" + listener);
            }
            try {
                miConfig.setFeatureValue(feature, network, value, listener);
            } catch (RemoteException e) {
                throw new ImsException("setFeatureValue()", e,
                        ImsReasonInfo.CODE_LOCAL_SERVICE_UNAVAILABLE);
            }
        }

    miConfig是IImsConfig接口类对象,其setFeatureValue()方法在ImsConfigImpl类中实现;

    ImsConfigImpl类setFeatureValue()方法的实现:

        public void setFeatureValue(int feature, int network, int value, ImsConfigListener listener) {
            try {
                try {
                    if (DEBUG) Log.d(TAG, "setFeatureValue(" +
                          feature + ", " + network + ", " + value + ") on phone " + mPhoneId +
                          " from pid " + Binder.getCallingPid() + ", uid " + Binder.getCallingUid() +
                          ", listener " + listener);
                    mStorage.setFeatureValue(feature, network, value); //ImsConfigStorage存储变量信息
    
                        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) {
                                    SystemProperties.set(PROPERTY_VOLTE_ENALBE,"1");//根据参数设置变量                                 
                                    //mRilAdapter.turnOnVolte(null);
                                    if (wfcEnable == 0){
                                        //mRilAdapter.turnOnImsVoice(null);
                                    }
                                } else {
                                    SystemProperties.set(PROPERTY_VOLTE_ENALBE,"0");
                                    //mRilAdapter.turnOffVolte(null);
                                    if (wfcEnable == 0){
                                        //mRilAdapter.turnOffImsVoice(null);
                                    }
                                }
                            }
                            break;
  • 相关阅读:
    获取Android控件宽高
    Android面试题:大图加载,防止OOM
    Android面试题:讲一讲Glide的原理
    面试题:实现一个容器,提供两个方法,add,size;写两个线程,线程1添加10个元素到容器中,线程2实现监控元素的个数,当个数到5个时,线程2给出提示并结束
    Java线程中断的三种方法
    Java的四种引用:强引用、软引用,弱引用和虚引用
    Bellman-Ford(可解决负权边)--时间复杂度优化
    【Leetcode 动态规划、深度优先搜索】不同路径(62)、 不同路径 II(63)、不同路径 III(980)
    ElasticSearch scroll分页查询
    MySQL Myisam引擎和Innodb引擎的区别
  • 原文地址:https://www.cnblogs.com/kaifyou/p/6283021.html
Copyright © 2011-2022 走看看