1、开关按钮位置:

  设置--> 更多--> 移动网络--> 增强型4G LTE模式

2、该设置开关使用了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);
        }

3、该接听方法是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;
    }

有如下打印信息:

4、设置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 服务
        }

有如下打印信息:

5、打开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对象开机即获取到。

6、调用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;
           }
           ..........
       }
   }

有如下打印信息:

7、获取主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();
    }

frameworks/opt/telephony/src/java/com/mediatek/internal/telephony/RadioCapabilitySwitchUtil.java

    /**
     * Get main capability phone ID.
     *
     * @return Phone ID with main capability
     */
    public static int getMainCapabilityPhoneId() {
        int phoneId = 0;
        if (SystemProperties.getBoolean("ro.mtk_dt_support", false) == true) {
            int swapMode = SystemProperties.getInt("persist.ril.simswitch.swapmode", 3);
            if (swapMode == SIM_SWITCH_MODE_DUAL_TALK) {
                phoneId = 0;
            } else if (swapMode == SIM_SWITCH_MODE_DUAL_TALK_SWAP) {
                phoneId = 1;
            }
        } else {
            phoneId = SystemProperties.getInt(PhoneConstants.PROPERTY_CAPABILITY_SWITCH, 1) - 1;
        }
        if (CdmaFeatureOptionUtils.isCdmaLteDcSupport()) {
            if (phoneId == PhoneConstants.SIM_ID_1) {
                if (SvlteUtils.getSvltePhoneProxy(phoneId).getActivePhone().
                    getPhoneName()== "CDMA") {
                    // for svlte project, we need re-mapping slot 0 to DC phone
                    phoneId = SubscriptionManager.LTE_DC_PHONE_ID_1;
                }
            }
            if (phoneId == PhoneConstants.SIM_ID_2) {
                if (SvlteUtils.getSvltePhoneProxy(phoneId).getActivePhone().
                    getPhoneName()== "CDMA") {
                    // for svlte project, we need re-mapping slot 1 to DC phone
                    phoneId = SubscriptionManager.LTE_DC_PHONE_ID_2;
                }
            }
        }
        Log.d(LOG_TAG, "[RadioCapSwitchUtil] getMainCapabilityPhoneId " + phoneId);
        return phoneId;

VoLTE 注册流程的更多相关文章

  1. wifi万能钥匙自媒体平台开放注册(付注册流程)

    12月13日,有网友爆料,wifi万能钥匙自媒体开放注册,看来自媒体还没有达到饱和阶段,也印证了自媒体时代才刚刚到来.现在这个自媒体的时代,几乎大多互联网企业都开通了自己的自媒体,比较知名的像今日头条 ...

  2. 源程序版本管理软件和项目管理软件,Github注册流程

    目前流行的源程序版本管理软件和项目管理软件:Microsoft TFS,Github,SVN,Coding 各自的优缺点: Microsoft TFS: 优点: tfs核心的,是对敏捷,msf,cmm ...

  3. GitHub注册流程(中英对比)

    GitHub注册流程(中英对比) 注明:为方便完成注册,将以中英文网页截图对应展示. 1. 注册邮箱:        点击GitHub官网进行邮箱注册. 2. 制定个人计划:        页面跳转至 ...

  4. 迅为4412开发板Linux驱动教程——总线_设备_驱动注册流程详解

    本文转自:http://www.topeetboard.com 视频下载地址: 驱动注册:http://pan.baidu.com/s/1i34HcDB 设备注册:http://pan.baidu.c ...

  5. 从注册流程 分析如何安全退出多个Activity 多种方式(附DEMO)

      退出Activity注册Android遍历   目录(?)[+] 前言 知识结构 具体方案 方案1 方法采用FLAG_ACTIVITY_CLEAR_TOP退出整个程序多activity 方案2 方 ...

  6. python selenium自动化(二)自动化注册流程

    需求:使用python selenium来自动测试一个网站注册的流程. 假设这个网站的注册流程分为三步,需要提供比较多的信息: 在这个流程里面,需要用户填入信息.在下拉菜单中选择.选择单选的radio ...

  7. Android安全问题 抢先接收广播 - 内因篇之广播接收器注册流程

    导读:本文说明系统是如何注册动态广播以及静态广播,这里主要注意其注册的顺序 这篇文章主要是针对我前两篇文章 android安全问题  抢先开机启动 - 结果篇 android安全问题  抢先拦截短信 ...

  8. 基于GBT28181:SIP协议组件开发-----------第三篇SIP注册流程分析实现

    原创文章,引用请保证原文完整性,尊重作者劳动,原文地址http://www.cnblogs.com/qq1269122125/p/3941172.html,qq:1269122125. 上两章节简要的 ...

  9. 基于GBT28181:SIP协议组件开发-----------第四篇SIP注册流程eXosip2实现(一)

    原创文章,引用请保证原文完整性,尊重作者劳动,原文地址http://www.cnblogs.com/qq1269122125/p/3945294.html. 上章节讲解了利用自主开发的组件SIP组件l ...

随机推荐

  1. Visual Studio 2012 trial version

    Update: vs2012.5.iso http://download.microsoft.com/download/9/F/1/9F1DEA0F-97CC-4CC4-9B4D-0DB45B8261 ...

  2. ListFragment创建及其生命周期

    相同的ListFragment 带有一个无参构造 一个有参构造 在该Fragment所依附的Activity视图创建时被实例化一次 方法周期分别为1.无参构造2.onInflate3.onAttach ...

  3. This kind of launch is configured to open the Debug perspective when it suspends.

    This kind of launch is configured to open the Debug perspective when it suspends. 因为设置了断点才会弹出这个,不需要调 ...

  4. 2016-11-02: boost::enable_shared_from_this

    使用场景 当类对象被shared_ptr管理时,需要在类自己定义的函数中把当前对象作为参数传递给其他函数时,必须传递一个shared_ptr,否则就不能保持shared_ptr管理这个类对象的语义.因 ...

  5. cs11_adventure c++_lab1

    exercise1.cc #include <iostream> #include <vector> #include <stdlib.h> #include &l ...

  6. ssh访问控制,多次失败登录即封掉IP,防止暴力破解

    ssh访问控制,多次失败登录即封掉IP,防止暴力破解 一.系统:Centos6.3 64位 二.方法:读取/var/log/secure,查找关键字 Failed,例如(注:文中的IP地址特意做了删减 ...

  7. 【转载】new和malloc的区别

    本篇随笔为转载,原贴地址:C++中new和malloc的十点区别. 前言 几个星期前去面试C++研发的实习岗位,面试官问了个问题: new与malloc有什么区别? 这是个老生常谈的问题.当时我回答n ...

  8. 在指定时间干,必须干(kbmmw 中的事件调度)

    从去年开始,kbmmw 慢慢增加内涵,除了完善各种服务外,陆续增加和扩展了作为一个中间件必须有的功能, 例如,权限管理.日志系统.调度系统.内存调试等功能. 今天给大家介绍一下kbmmw 的调度事件, ...

  9. CSS3基础03(3D②) 求粉丝

    3 D (3.1)rotateY 围绕着Y轴进行旋转 (1)正数是(站在右边推),负数是(站在左边推) (2.1)定义元素背过去是否可见 backface-visibility: visible|hi ...

  10. 配置 Haproxy 防范 DDOS 攻击

    作为 load balancer, Happroxy 常常作为服务器的前端,向外界用户提供服务的入口,如果能在入口处处理安全相关问题,将极大简化后端的设计.事实上,Haproxy 不仅仅是一款开源出色 ...