开关按钮位置:
  设置--> 更多--> 移动网络--> 增强型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;

开关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. Slickflow.NET 开源工作流引擎快速入门之二: 简单并行分支流程代码编写示例

    前言:对于急切想了解引擎功能的开发人员,在下载版本后,就想尝试编写代码,完成一个流程的开发和测试.本文试图从一个最简单的并行分支流程来示例说明,如何快速了解引擎代码的编写. 版本:.NET Core2 ...

  2. Implement Dependent Reference Properties 实现从属引用属性 (XPO)

    In this lesson, you will learn how to implement properties whose values can depend on other properti ...

  3. HTML基础——表格的应用

    一.表格标签 1.基本格式: 每个表格由 table 标签开始. 每个表格行由 tr 标签开始. 每个表格数据由 td 标签开始. 例如: <html> <head> < ...

  4. C#后台架构师成长之路-高阶知识体系核心

    了解了这些东西,熟悉了运用基本都是高工级别的了,其他修修补补就行了.... 1.三种预定义特性:attributeUsage.Conditional.obsolete,允许创建自定义特性,派生自Sys ...

  5. 读书笔记_python网络编程3_(2)

    2.UDP 2.0.数据包表示较短的信息,大小通常不会超过几千字节,在浏览器与服务器进行会话/电子邮件客户端与ISP的邮件服务器进行会话时,这些独立而小型的数据包是如何组成会话的呢? 2.0.1.IP ...

  6. Linux CentOS 6.5 卸载、tar安装MySQL

    卸载系统自带MySQL 1. 查看系统当前是否安装有MySQL rpm -qa|grep -i mysql 2. 卸载当前版本的MySQL yum remove mysql mysql-server ...

  7. 【解决 FTP】windows访问Linux的vsftpd(FTP服务器)问题200 Switching to ASCII mode,227 Entering Passive Mode

    转载:关于FTP主动模式(active mode)与被动模式(passive mode)的工作原理: 主动模式(服务器向客户端敲门,然后客户端开门)FTP:客户机与服务器之间建立连接时,客户机是大于1 ...

  8. LInux:网络连接的设置

    主机名的配置 主机名的配置(配置文件/etc/hostname) 1.使用 hostname 命令临时设置主机名 命令格式:hostname [新主机名] 2.永久设置主机名 命令格式:hostnam ...

  9. 利用Mac的功能键|如何在Mac上使用F键

    Mac键盘的顶部是一组按键,这些按键的特征是F后跟1-12数字.这些键称为Mac功能键,使您可以通过按几个键来更改某些设置并快速访问Mac功能. 如果您是Mac的所有者,是时候学习这些键各自可以做什么 ...

  10. sed命令总结

    目录 1.概述 2.查 1.打印整行(一或多) 2.正则打印包含关键字的行 2.增 3.删 4.改 5.后向引用 6.结合 7.练习 我叫张贺,贪财好色.一名合格的LINUX运维工程师,专注于LINU ...