开关按钮位置:
  设置--> 更多--> 移动网络--> 增强型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. 深入selenium三种等待方式使用

    深入selenium三种等待方式使用 处理由于网络延迟造成没法找到网页元素 方法一 用time模块不推荐使用 用time模块中的time.sleep来完成等待 from selenium import ...

  2. Hacking/Penetrating tester bookmark collection

    Blogs http://carnal0wnage.blogspot.com/ http://www.mcgrewsecurity.com/ http://www.gnucitizen.org/blo ...

  3. YARN HA部署架构

    hadoop001: zk rm(zkfc线程) nm hadoop002: zk rm(zkfc线程) nm hadoop003: zk nm RMStateStore: 存储在ZK的/rmstor ...

  4. frp内网渗透实现ssh外网访问家里树莓派(树莓派raspbian系统+腾讯云contos7)

    只有信用卡大小的它,同时也是一台功能完备的电脑(树莓派),把内网能玩的功能都玩了个遍,自然就有了外网访问这台树莓派的需求.一样也是查阅了无数文章,研究了无数个方案,最终试验成功用FRP实现了内网穿透, ...

  5. RDMA 相关 简要摘录

    RDMA (Remote Direct Memory Access) 全称为 远程直接内存访问 其出现的目的:为了解决网络传输中服务端数据处理的延迟而产生的.其将数据直接从一台计算机的内存传输到另一台 ...

  6. 打包Python文件为exe

    pip install pyinstaller 然后就在终端里执行命令 cd 到目标文件的目录下 执行 pyinstaller  -F  ***.py 即可生成exe

  7. PHP转Go系列:map映射

    映射的定义 初识映射会很懵,因为在PHP中没有映射类型的定义.其实没那么复杂,任何复杂的类型在PHP中都可以用数组表示,映射也不例外. $array['name'] = '平也'; $array['s ...

  8. Shadow Map -- 点阴影(全方位)

    昨晚终于把点阴影(深度CubeMap)程序调通了,思想不难,基本就是在上节定向光阴影基础上稍作修改,但是CG程序不太方便Debug,需要输出中间效果图进行判断,耽搁了一会儿. 过程如下: 1.将深度渲 ...

  9. go语言设计模式之Strategy

    package main import ( "flag" "fmt" "image" "image/color" &qu ...

  10. UVA 503 Parallelepiped walk

    https://vjudge.net/problem/UVA-503 题目 给出一个长方体和长方体上两点的坐标,求两点的沿着长方体表面走的最小距离 题解 沿着表面走就是在展开图上面走,如果分类讨论就需 ...