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. 外壳exe通过反射调用dll时

    外壳exe通过反射调用dll时,dll是 4.0的框架,外壳exe也需要编译成4.0的框架,如果dll本身有调用32位的dll,那么外壳exe也需要编译成32位. 调试时报的那个错,直接继续运行,不影 ...

  2. Python体验(08)-图形界面之工具栏和状态栏

    # coding=utf-8 import wx # 导入必须的Python包 class MenuForm(wx.Frame): def OnQuit(self,event): self.Close ...

  3. 使用wcf服务捕捉到“POST http://yourIP/WCFService.svc 405 (Method Not Allowed) ”错误!

    在程序中使用了一个wcf服务,调试时无任何问题(win7 64位,iis6.1),发布到部门服务器上没有问题(server2008 64位),但是部署到实际服务器上时(server2008 iis6. ...

  4. Jmeter plugin jp@gc - PerfMon Metrics Collector

    Jmeter由于是开源工具,所以目前有很多插件可以供使用,最简单的方法是先把Plugin Manager安装了 下载地址:https://jmeter-plugins.org/wiki/Plugins ...

  5. 关于oracle中创建新表时将我们要用的表的结构和数据都复制过去

    今天在oracle中遇到了一个问题,就是给我查询出来了一张表的数据,只有部分的字段,让我将这张表的结构和数据放到新的临时表中,并进行数据的查询. 我是这样做的: 如:create table tabl ...

  6. neutron floatingip-delete

  7. iOS CoreAnimate

    iOS CoreAnimate 东西比较多,这篇笔记是入门用的,主要讲述的是静态的图形绘画处理问题.(当然动画也只是一小部分)理解相关的概念问题:   参考资料 http://segmentfault ...

  8. WEB文件上传漏洞介绍解决办法

    引用:http://blog.csdn.net/kobejayandy/article/details/35861499 问题: -1. 上传文件WEB脚本语言,服务器的WEB容器解释并执行了用户上传 ...

  9. ue4框架C++语法汇总文章

    1.Run external .exe file TCHAR* url = TEXT("C:\\windows\\system32\\calc.exe"); FPlatformPr ...

  10. ES6 学习笔记(1)

    恰逢换工作之际,新公司的是以 ES6 + webpack + vue 为技术栈, 正好ES6是我下个学习目标, 因此买了阮老师的 ES6标准入门,也当是支持阮老师了. 笔记将会照着这本书的阅读展开而做 ...