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. 在网页中怎样给已发布的Flash添加链接的方法(zhuan)

    因为网页中的 Flash 是以控件形式出现的,优先级别较高,所以直接对它加链接是无效的,不过可以用按钮控件 BUTTON 来实现. 具体步骤 1.直接在按钮上加上onClick事件打开指定页面: &l ...

  2. AES加密算法实现

    AES算法是一种对称加密算法,是美国国家标准技术研究所NIST旨在取代DES的21世纪的加密标准. 下文实例中,密钥采用了直接写死的方式,实际使用中可以配合RSA加密算法加密密钥,从而达到更好的安全效 ...

  3. 洛谷P3392 涂国旗

    P3392 涂国旗 107通过 507提交 题目提供者kkksc03 标签 难度普及- 提交  讨论  题解 最新讨论 直接读字符会wa WA?-- 为什么不对... 跪求找错 快点给钱 这不就是荷兰 ...

  4. 1 《JavaScript高级程序设计》学习笔记(1)

    欢迎关注本人的微信公众号"前端小填填",专注前端技术的基础和项目开发的学习. 首先,我将从<JavaScript高级程序设计>这本JavaScript学习者必看的经典教 ...

  5. Cacti修改采集精度为1分钟

    前言: 基础知识:建议先了解一下 rrdtool 及 rrd 数据库的工作原理,参考阅读<rrdtool学习笔记> cacti主要使用了rrdtool这个工具来绘图,所以看上去比zabbi ...

  6. spring3 项目更新

    列志华 (组长) http://www.cnblogs.com/liezhihua/ 团队guihub https://github.com/LWHTF/OrderingFood 黄柏堂 http:/ ...

  7. C#学习网站记录

    C# 编程指南--Microfsoft官方C#编程指南 https://msdn.microsoft.com/zh-cn/library/67ef8sbd(v=vs.100).aspx

  8. java 平台 权限管理

    最近在做公司内部的物流业务平台的权限管理,感触颇多.记录一下 权限管理分两部分:数据权限和操作权限. 数据权限: 这个是和用户相关的. 因为平台是多机构的,所以再考虑数据权限的时候,是按照机构来管理的 ...

  9. SQL日期格式化应用大全

    Sql Server 中一个非常强大的日期格式化函数Select CONVERT(varchar(100), GETDATE(), 0): 05 16 2006 10:57AMSelect CONVE ...

  10. 第六百一十六天 how can I 坚持

    有时间还是多学点东西吧,webservice.. 晚上看了个电影<我们的十年>,乔任梁死了..买了个大柚子,上火好难受.有些困惑啊. 有没有梦想,只是不想让人来到这这个世界,什么都没留下就 ...