开关VoLTE流程分析(一)
开关按钮位置:
设置--> 更多--> 移动网络--> 增强型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流程分析(一)的更多相关文章
- Android8.1 开关VOLTE流程分析
前言 最近有需求需要实现插卡默认打开Volte功能,顺带研究了下Volte的流程,在此做个记录 开始 从Settings设置界面入手,网络和互联网-->移动网络-->VoLTE高清通话(电 ...
- 开关VoLTE流程分析(二)
AT指令,暂未发现发送AT请求的frameworks接口,通过打印信息总结AT指令: AT+EIMSVOICE: Enable/Disable IMS Voice Capability+EIMSVOI ...
- Android7.0 Phone应用源码分析(一) phone拨号流程分析
1.1 dialer拨号 拨号盘点击拨号DialpadFragment的onClick方法会被调用 public void onClick(View view) { int resId = view. ...
- Solr4.8.0源码分析(5)之查询流程分析总述
Solr4.8.0源码分析(5)之查询流程分析总述 前面已经写到,solr查询是通过http发送命令,solr servlet接受并进行处理.所以solr的查询流程从SolrDispatchsFilt ...
- 8、Struts2 运行流程分析
1.流程分析: 请求发送给 StrutsPrepareAndExecuteFilter StrutsPrepareAndExecuteFilter 询问 ActionMapper: 该请求是否是一个 ...
- freeswitch呼叫流程分析
今天翻文档时发现之前整理的关于freeswitch呼叫相关的内容,写成博文分享出来也方便我以后查阅. 整体结构图 FreeswitchCore 模块加载过程 freeswitch主程序初始化时会从mo ...
- u-boot 流程分析
u-boot 介绍: 对于计算机来说 , 从一开始上机通电是无法直接启动操作系统的 , 这中间需要一个引导过程 , 嵌入式Linux系统同样离不开引导程序 , 这个启动程序就叫启动加载程序(Boot ...
- thttpd和cgilua安装与运行流程分析
安装 参考如下博文安装thttpd软件 http://blog.csdn.net/21aspnet/article/details/7045845 http://blog.csdn.net/drago ...
- 【转】Hostapd工作流程分析
[转]Hostapd工作流程分析 转自:http://blog.chinaunix.net/uid-30081165-id-5290531.html Hostapd是一个运行在用户态的守护进程,可以通 ...
随机推荐
- 汇总:ASP.NET Core中HttpContext获取传参数据,有哪些方式
一.原生方式: 1.POST(以ajax请求为案例,教大家用法) $.ajax({ type: "post", dataType: "json", cache: ...
- C#-Excel导入工资条群发邮箱
第一次写随笔,一名在实习的程序猿,做的一个小应用,需要的朋友可以参考参考, 使用WinForm实现了一个导入Excel,群发工资条的功能.功能已经实现,还不够完善,. 大致运用了OleDbConnec ...
- C++ 深入浅出工厂模式(进阶篇)
介绍 前文初始篇C++ 深入浅出工厂模式(初始篇),主要阐述了简单工厂模式.工厂方法模式和抽象工厂模式的结构.特点和缺陷等.以上三种方式,在新增产品时,要么修改工厂类,要么需新增具体的工厂类,说明工厂 ...
- JavaScript 赋值
JavaScript 赋值运算符 赋值运算符向 JavaScript 变量赋值. 运算符 例子 等同于 = x = y x = y += x += y x = x + y -= x -= y x = ...
- WebViewJavascriptBridge的详细使用
参考链接: https://www.jianshu.com/p/d12ec047ce52 https://www.jianshu.com/p/ba6358b1eec3 有demo:https://ww ...
- Mac版Sourcetree的安装使用
本人也在亲测,感觉很有效,和大家分享,参考链接: https://www.jianshu.com/p/b8d0547a8449
- 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 ...
- Python 对列表嵌套的数据进行排序
利用sorted(iterable[, key][, reverse]) key:指定一个接收一个参数的函数,这个函数用于从每个元素中提取一个用于比较的关键字,默认值为None(直接比较元素) rev ...
- Quasar framework 配置vue apollo
Quasar 整合 vue-apollo 确保你已经知道quasar 和 vue apollo 在quasar中使用vue apollo客户端时出现的一点小问题 在quasar项目中使用vue-apo ...
- charles使用(安装、mock、限速、断点功能)
我们在进行B/S架构的Web项目开发时,在前端页面与后台交互的调试的时候,通常使用在JSP中加入“debugger;”断点,然后使用浏览器的F12开发者工具来查看可能出错的地方的数据.或者使用Http ...