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

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

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

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

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

有如下打印信息:

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

  1. public static void setEnhanced4gLteModeSetting(Context context, boolean enabled) {
  2. int value = enabled ? 1 : 0;
  3.      //设置Settings.Global.ENHANCED_4G_MODE_ENABLED变量
  4. android.provider.Settings.Global.putInt(
  5. context.getContentResolver(),
  6. android.provider.Settings.Global.ENHANCED_4G_MODE_ENABLED, value);
  7.  
  8. if (isNonTtyOrTtyOnVolteEnabled(context)) { //不支持TTY或者VoLTE支持TTY
  9. ImsManager imsManager = ImsManager.getInstance(context,
  10. SubscriptionManager.getDefaultVoicePhoneId()); //获取ImsManager对象
  11. if (imsManager != null) {
  12. try {
  13. imsManager.setAdvanced4GMode(enabled); //设置VoLTE
  14. } catch (ImsException ie) {
  15. // do nothing
  16. }
  17. }
  18. }
  19. }

设置VoLTE

  1. private void setAdvanced4GMode(boolean turnOn) throws ImsException {
  2. checkAndThrowExceptionIfServiceUnavailable();
  3.  
  4. try {
  5. ImsConfig config = getConfigInterface(); //IMS 配置参数
  6. if (config != null) {
  7.                              //设置FeatureConstants.FEATURE_TYPE_VOICE_OVER_LTE网络参数
  8. config.setFeatureValue(ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_LTE,
  9. TelephonyManager.NETWORK_TYPE_LTE, turnOn ? 1 : 0, null);
  10. }
  11. } catch (ImsException e) {
  12. log("setAdvanced4GMode() : " + e);
  13. }
  14.  
  15. log("setAdvanced4GMode():" + turnOn);
  16. if (turnOn) {
  17. turnOnIms(); //打开IMS 服务
  18. } else if (isImsTurnOffAllowed()) {
  19. log("setAdvanced4GMode() : imsServiceAllowTurnOff -> turnOffIms");
  20. turnOffIms(); //关闭IMS 服务
  21. }

有如下打印信息:

打开IMS 服务

  1. private void turnOnIms() throws ImsException {
  2. checkAndThrowExceptionIfServiceUnavailable();
  3.  
  4. try {
  5. mImsService.turnOnIms(mPhoneId);
  6. } catch (RemoteException e) {
  7. throw new ImsException("turnOnIms() ", e, ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
  8. }
  9. }

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

  1.        //绑定IMS Service
  2. private void createImsService(boolean checkService) {
  3. if (checkService) { //判断IMS Service 服务是否已经存在
  4. IBinder binder = ServiceManager.checkService(getImsServiceName(mPhoneId));
  5.  
  6. if (binder == null) {
  7. /// M: add for debug @{
  8. if (DBG) log("ImsManager: createImsService binder is null");
  9. /// @}
  10. return;
  11. }
  12. }
  13. //获取指向Service的IBinder对象
  14. IBinder b = ServiceManager.getService(getImsServiceName(mPhoneId));
  15.  
  16. if (b != null) {
  17. try {
  18. b.linkToDeath(mDeathRecipient, 0);
  19. } catch (RemoteException e) {
  20. }
  21. }
  22.  
  23. mImsService = IImsService.Stub.asInterface(b);
  24. /// M: add for debug @{
  25. if (DBG) log("ImsManager: mImsService = " + mImsService);
  26. /// @}
  27.         }

getImsServiceName()获取IMS Service 名:

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

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

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

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

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

有如下打印信息:

获取主PhoneID

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

  1. /**
  2. * Get main capability phone id.
  3. * @return The phone id with highest capability.
  4. */
  5. public int getMainCapabilityPhoneId() {
  6. return RadioCapabilitySwitchUtil.getMainCapabilityPhoneId();
  7. }

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

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

getConfigInterface()的实现:

  1. public ImsConfig getConfigInterface() throws ImsException {
  2. checkAndThrowExceptionIfServiceUnavailable();
  3. // M: Remove cache of ImsConfig in AOSP, always get ImsConfig with mainCapability Id
  4. mConfig = getConfigInterface(mPhoneId, mImsService, mContext);
  5. return mConfig;
  6. }
  7.  
  8. public static ImsConfig getConfigInterface(int phoneId, IImsService service, Context context) throws ImsException {
  9. ImsConfig config = null;
  10.  
  11. try {
  12. if (service == null) { //获取IMS服务
  13. IBinder b = ServiceManager.getService(getImsServiceName(phoneId));
  14. service = IImsService.Stub.asInterface(b);
  15. }
  16.  
  17. IImsConfig binder = service.getConfigInterface(phoneId); //调用ImsService的getConfigInterface()接口
  18. if (binder == null) {
  19. throw new ImsException("getConfigInterface()",
  20. ImsReasonInfo.CODE_LOCAL_SERVICE_UNAVAILABLE);
  21. }
  22.  
  23. config = new ImsConfig(binder, context); //初始化ImsConfig对象
  24. } catch (RemoteException e) {
  25. throw new ImsException("getConfigInterface()", e,
  26. ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
  27. }
  28. if (DBG) log("getConfigInterface(), config= " + config);
  29. return config;

根据PhoneID创建IImsConfig

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

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

  1. //Config interface to get/set IMS service/capability parameters.
  2. public IImsConfig getConfigInterface(int phoneId) {
  3. // Always get main capability phone Id for ImsConfig
  4. phoneId = getMainCapabilityPhoneId();
  5. Rlog.w(LOG_TAG, "Get config interface on main capability phone " + phoneId);
  6.  
  7. IImsConfig instance = null;
  8. Rlog.w(LOG_TAG, "getConfigInterface phone " + phoneId);
  9. synchronized (mImsConfigInstanceMap) {
  10. if (mImsConfigInstanceMap.containsKey(phoneId)) {
  11. instance = mImsConfigInstanceMap.get(phoneId);
  12. } else {
  13. instance = new ImsConfigImpl(mContext, mImsRILAdapter, phoneId);
  14. mImsConfigInstanceMap.put(phoneId, instance);
  15. }
  16. }
  17. 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

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

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

  1. if (config != null) {
  2. config.setFeatureValue(ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_LTE,
  3. TelephonyManager.NETWORK_TYPE_LTE, turnOn ? 1 : 0, null);
  4. }
  5.  
  6. /**
  7. * Sets the value for IMS feature item for specified network type.
  8. *
  9. * @param feature, as defined in FeatureConstants.
  10. * @param network, as defined in android.telephony.TelephonyManager#NETWORK_TYPE_XXX.
  11. * @param value, as defined in FeatureValueConstants.
  12. * @param listener, provided if caller needs to be notified for set result.
  13. * @return void
  14. *
  15. * @throws ImsException if calling the IMS service results in an error.
  16. */
  17. public void setFeatureValue(int feature, int network, int value,
  18. ImsConfigListener listener) throws ImsException {
  19. if (DBG) {
  20. Rlog.d(TAG, "setFeatureValue: feature = " + feature + ", network =" + network +
  21. ", value =" + value + ", listener =" + listener);
  22. }
  23. try {
  24. miConfig.setFeatureValue(feature, network, value, listener);
  25. } catch (RemoteException e) {
  26. throw new ImsException("setFeatureValue()", e,
  27. ImsReasonInfo.CODE_LOCAL_SERVICE_UNAVAILABLE);
  28. }
  29. }

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

ImsConfigImpl类setFeatureValue()方法的实现:

  1. public void setFeatureValue(int feature, int network, int value, ImsConfigListener listener) {
  2. try {
  3. try {
  4. if (DEBUG) Log.d(TAG, "setFeatureValue(" +
  5. feature + ", " + network + ", " + value + ") on phone " + mPhoneId +
  6. " from pid " + Binder.getCallingPid() + ", uid " + Binder.getCallingUid() +
  7. ", listener " + listener);
  8. mStorage.setFeatureValue(feature, network, value); //ImsConfigStorage存储变量信息
  9.  
  10. case ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_LTE:
  11. int oldVoLTEValue = SystemProperties.getInt(PROPERTY_VOLTE_ENALBE, 0);
  12. int wfcEnable = SystemProperties.getInt(PROPERTY_WFC_ENALBE, 0);
  13. if (value != oldVoLTEValue) {
  14. if (value == ImsConfig.FeatureValueConstants.ON) {
  15. SystemProperties.set(PROPERTY_VOLTE_ENALBE,"1");//根据参数设置变量
  16. //mRilAdapter.turnOnVolte(null);
  17. if (wfcEnable == 0){
  18. //mRilAdapter.turnOnImsVoice(null);
  19. }
  20. } else {
  21. SystemProperties.set(PROPERTY_VOLTE_ENALBE,"0");
  22. //mRilAdapter.turnOffVolte(null);
  23. if (wfcEnable == 0){
  24. //mRilAdapter.turnOffImsVoice(null);
  25. }
  26. }
  27. }
  28. break;

开关VoLTE流程分析(一)的更多相关文章

  1. Android8.1 开关VOLTE流程分析

    前言 最近有需求需要实现插卡默认打开Volte功能,顺带研究了下Volte的流程,在此做个记录 开始 从Settings设置界面入手,网络和互联网-->移动网络-->VoLTE高清通话(电 ...

  2. 开关VoLTE流程分析(二)

    AT指令,暂未发现发送AT请求的frameworks接口,通过打印信息总结AT指令: AT+EIMSVOICE: Enable/Disable IMS Voice Capability+EIMSVOI ...

  3. Android7.0 Phone应用源码分析(一) phone拨号流程分析

    1.1 dialer拨号 拨号盘点击拨号DialpadFragment的onClick方法会被调用 public void onClick(View view) { int resId = view. ...

  4. Solr4.8.0源码分析(5)之查询流程分析总述

    Solr4.8.0源码分析(5)之查询流程分析总述 前面已经写到,solr查询是通过http发送命令,solr servlet接受并进行处理.所以solr的查询流程从SolrDispatchsFilt ...

  5. 8、Struts2 运行流程分析

    1.流程分析: 请求发送给 StrutsPrepareAndExecuteFilter StrutsPrepareAndExecuteFilter 询问 ActionMapper: 该请求是否是一个 ...

  6. freeswitch呼叫流程分析

    今天翻文档时发现之前整理的关于freeswitch呼叫相关的内容,写成博文分享出来也方便我以后查阅. 整体结构图 FreeswitchCore 模块加载过程 freeswitch主程序初始化时会从mo ...

  7. u-boot 流程分析

    u-boot 介绍: 对于计算机来说 , 从一开始上机通电是无法直接启动操作系统的 , 这中间需要一个引导过程 , 嵌入式Linux系统同样离不开引导程序 ,  这个启动程序就叫启动加载程序(Boot ...

  8. thttpd和cgilua安装与运行流程分析

    安装 参考如下博文安装thttpd软件 http://blog.csdn.net/21aspnet/article/details/7045845 http://blog.csdn.net/drago ...

  9. 【转】Hostapd工作流程分析

    [转]Hostapd工作流程分析 转自:http://blog.chinaunix.net/uid-30081165-id-5290531.html Hostapd是一个运行在用户态的守护进程,可以通 ...

随机推荐

  1. 汇总:ASP.NET Core中HttpContext获取传参数据,有哪些方式

    一.原生方式: 1.POST(以ajax请求为案例,教大家用法) $.ajax({ type: "post", dataType: "json", cache: ...

  2. C#-Excel导入工资条群发邮箱

    第一次写随笔,一名在实习的程序猿,做的一个小应用,需要的朋友可以参考参考, 使用WinForm实现了一个导入Excel,群发工资条的功能.功能已经实现,还不够完善,. 大致运用了OleDbConnec ...

  3. C++ 深入浅出工厂模式(进阶篇)

    介绍 前文初始篇C++ 深入浅出工厂模式(初始篇),主要阐述了简单工厂模式.工厂方法模式和抽象工厂模式的结构.特点和缺陷等.以上三种方式,在新增产品时,要么修改工厂类,要么需新增具体的工厂类,说明工厂 ...

  4. JavaScript 赋值

    JavaScript 赋值运算符 赋值运算符向 JavaScript 变量赋值. 运算符 例子 等同于 = x = y x = y += x += y x = x + y -= x -= y x = ...

  5. WebViewJavascriptBridge的详细使用

    参考链接: https://www.jianshu.com/p/d12ec047ce52 https://www.jianshu.com/p/ba6358b1eec3 有demo:https://ww ...

  6. Mac版Sourcetree的安装使用

    本人也在亲测,感觉很有效,和大家分享,参考链接: https://www.jianshu.com/p/b8d0547a8449

  7. Data Management Technology(2) -- Data Model

    1.Data Model Model Is the abstraction of real world Reveal the essence of objects, help people to lo ...

  8. Python 对列表嵌套的数据进行排序

    利用sorted(iterable[, key][, reverse]) key:指定一个接收一个参数的函数,这个函数用于从每个元素中提取一个用于比较的关键字,默认值为None(直接比较元素) rev ...

  9. Quasar framework 配置vue apollo

    Quasar 整合 vue-apollo 确保你已经知道quasar 和 vue apollo 在quasar中使用vue apollo客户端时出现的一点小问题 在quasar项目中使用vue-apo ...

  10. charles使用(安装、mock、限速、断点功能)

    我们在进行B/S架构的Web项目开发时,在前端页面与后台交互的调试的时候,通常使用在JSP中加入“debugger;”断点,然后使用浏览器的F12开发者工具来查看可能出错的地方的数据.或者使用Http ...