开关VoLTE流程分析(二)
AT指令,暂未发现发送AT请求的frameworks接口,通过打印信息总结AT指令:
AT+EIMSVOICE: Enable/Disable IMS Voice Capability
+EIMSVOICE=<config>
<config>: integer
0 disable IMS Voice capability
1 enable IMS Voice capability
note:This command should set from AP side while boot-up;
At runtime, AP side could set the command anytime, and IMS module will apply the setting for next round of IMS registration;
而后有如下打印信息,发送RIL_REQUEST_SET_IMS_ENABLE请求:
此发送接口在ImsService.java 类中的onRequestImsSwitch():
public void onRequestImsSwitch(int simIdx, boolean isImsOn) { int phoneId = getMainCapabilityPhoneId(); if (DBG) {
Rlog.d(LOG_TAG,"onRequestImsSwitch simIdx=" + simIdx +
" isImsOn=" + isImsOn + " mainCapability id=" + phoneId);
} if (mActivePhoneId != phoneId) {
mActivePhoneId = phoneId;
} if (isImsOn) {
if (mImsState != PhoneConstants.IMS_STATE_ENABLE) { //如果是关闭状态
mImsRILAdapter.turnOnIms(mHandler.obtainMessage(EVENT_SET_IMS_ENABLED_DONE));
mImsState = PhoneConstants.IMS_STATE_ENABLING;
} else {
Rlog.d(LOG_TAG, "Ims already enable and ignore to send AT command.");
}
}
ImsRILAdapter类封装消息请求,通过send()发送RIL接收端;
ImsIntentReceiver广播接收器,根据log打印信息:
在PhoneBase类中定义了mImsIntentReceiver广播接收器:
private BroadcastReceiver mImsIntentReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Rlog.d(LOG_TAG, "mImsIntentReceiver: action " + intent.getAction());
if (intent.hasExtra(ImsManager.EXTRA_PHONE_ID)) {
int extraPhoneId = intent.getIntExtra(ImsManager.EXTRA_PHONE_ID,
SubscriptionManager.INVALID_PHONE_INDEX);
Rlog.d(LOG_TAG, "mImsIntentReceiver: extraPhoneId = " + extraPhoneId);
if (extraPhoneId == SubscriptionManager.INVALID_PHONE_INDEX ||
extraPhoneId != getPhoneId()) {
return;
}
} synchronized (PhoneProxy.lockForRadioTechnologyChange) {
//接收广播ACTION_IMS_SERVICE_UP
if (intent.getAction().equals(ImsManager.ACTION_IMS_SERVICE_UP)) {
......
mImsServiceReady = true;
updateImsPhone();
ImsManager.updateImsServiceConfig(mContext, mPhoneId, false);
//接收广播ACTION_IMS_SERVICE_DOWN
} else if (intent.getAction().equals(ImsManager.ACTION_IMS_SERVICE_DOWN)) {
mImsServiceReady = false;
updateImsPhone();
}
}
}
};
updateImsPhone()方法如下:
protected void updateImsPhone() {
Rlog.d(LOG_TAG, "updateImsPhone"
+ " mImsServiceReady=" + mImsServiceReady); if (mImsServiceReady && (mImsPhone == null)) {
//创建mImsPhone notifyDataRegStateRilRadioTechnologyChanged
mImsPhone = PhoneFactory.makeImsPhone(mNotifier, this);
CallManager.getInstance().registerPhone(mImsPhone); //CallManager里添加Phone对象
mImsPhone.registerForSilentRedial(
this, EVENT_INITIATE_SILENT_REDIAL, null); //注册消息,该消息的处理由该类处理
} else if (!mImsServiceReady && (mImsPhone != null)) {
CallManager.getInstance().unregisterPhone(mImsPhone);
mImsPhone.unregisterForSilentRedial(this); mImsPhone.dispose();
// Potential GC issue if someone keeps a reference to ImsPhone.
// However: this change will make sure that such a reference does
// not access functions through NULL pointer.
//mImsPhone.removeReferences();
mImsPhone = null;
} EVENT_INITIATE_SILENT_REDIAL 消息的处理:
case EVENT_INITIATE_SILENT_REDIAL:
Rlog.d(LOG_TAG, "Event EVENT_INITIATE_SILENT_REDIAL Received");
ar = (AsyncResult) msg.obj;
if ((ar.exception == null) && (ar.result != null)) {
String dialString = (String) ar.result;
if (TextUtils.isEmpty(dialString)) return;
try {
dialInternal(dialString, null, VideoProfile.STATE_AUDIO_ONLY, null);
} catch (CallStateException e) {
Rlog.e(LOG_TAG, "silent redial failed: " + e);
}
}
break;
ServiceState服务状态,有如下打印信息:
vendor/mediatek/proprietary/frameworks/opt/tedongle/src/java/android/tedongle/ServiceState.java
private void setNullState(int state) {
if (DBG) Rlog.d(LOG_TAG, "[ServiceState] setNullState=" + state);
mVoiceRegState = state;
mDataRegState = state;
mVoiceRoamingType = ROAMING_TYPE_NOT_ROAMING;
mDataRoamingType = ROAMING_TYPE_NOT_ROAMING;
.......
}
setNullState()该方法传入的参数是3,可判定被该方法调用:
public void setStateOff() {
setNullState(STATE_POWER_OFF);
}
ServiceState 的定义:
/**
* Normal operation condition, the phone is registered
* with an operator either in home network or in roaming.
*/
public static final int STATE_IN_SERVICE = 0;
/**
* Phone is not registered with any operator, the phone
* can be currently searching a new operator to register to, or not
* searching to registration at all, or registration is denied, or radio
* signal is not available.
*/
public static final int STATE_OUT_OF_SERVICE = 1;
/**
* The phone is registered and locked. Only emergency numbers are allowed. {@more}
*/
public static final int STATE_EMERGENCY_ONLY = 2;
/**
* Radio of telephony is explicitly powered off.
*/
public static final int STATE_POWER_OFF = 3;
注册消息:
private void registerIndicationReceiver() {
if (DBG) log("registerIndicationReceiver");
IntentFilter intentfilter = new IntentFilter();
intentfilter.addAction(ImsManager.ACTION_IMS_INCOMING_CALL_INDICATION);//注册来电通知
mPhone.getContext().registerReceiver(mIndicationReceiver, intentfilter); }
notifyDataRegStateRilRadioTechnologyChanged:
在GsmServiceStateTracker类的pollStateDone()方法中,调用notifyDataRegStateRilRadioTechnologyChanged():
if (hasDataRegStateChanged || hasRilDataRadioTechnologyChanged) {
notifyDataRegStateRilRadioTechnologyChanged();
//WLAN 判断
if (ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN
== mSS.getRilDataRadioTechnology()) {
mPhone.notifyDataConnection(Phone.REASON_IWLAN_AVAILABLE);
} else {
mPhone.notifyDataConnection(null);
}
} protected void notifyDataRegStateRilRadioTechnologyChanged() {
int rat = mSS.getRilDataRadioTechnology();
int drs = mSS.getDataRegState();
if (DBG) log("notifyDataRegStateRilRadioTechnologyChanged: drs=" + drs + " rat=" + rat);
//设置TelephonyProperties.PROPERTY_DATA_NETWORK_TYPE属性
mPhoneBase.setSystemProperty(TelephonyProperties.PROPERTY_DATA_NETWORK_TYPE,
ServiceState.rilRadioTechnologyToString(rat));
mDataRegStateOrRatChangedRegistrants.notifyResult(new Pair<Integer, Integer>(drs, rat));
}
mDataRegStateOrRatChangedRegistrants通知者注册函数:
public void registerForDataRegStateOrRatChanged(Handler h, int what, Object obj) {
Registrant r = new Registrant(h, what, obj);
mDataRegStateOrRatChangedRegistrants.add(r); //添加监听者
notifyDataRegStateRilRadioTechnologyChanged();
}
该注册函数在ImsPhone的构造函数中被调用:
ImsPhone(Context context, PhoneNotifier notifier, Phone defaultPhone) { mDefaultPhone = (PhoneBase) defaultPhone;
/// M: ALPS02759855. ImsPhoneCallTracker may change service state earlier. @{
// mCT = new ImsPhoneCallTracker(this);
// mSS.setStateOff();
mSS.setStateOff(); //此处即在"ServiceState服务状态"中提到的
mCT = new ImsPhoneCallTracker(this);
/// @} mPhoneId = mDefaultPhone.getPhoneId(); // This is needed to handle phone process crashes
// Same property is used for both CDMA & IMS phone.
mIsPhoneInEcmState = SystemProperties.getBoolean(
TelephonyProperties.PROPERTY_INECM_MODE, false); PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, LOG_TAG);
mWakeLock.setReferenceCounted(false); if (mDefaultPhone.getServiceStateTracker() != null) {
mDefaultPhone.getServiceStateTracker()
.registerForDataRegStateOrRatChanged(this,
EVENT_DEFAULT_PHONE_DATA_STATE_CHANGED, null); //注册数据状态变化通知消息
}
updateDataServiceState();
}
EVENT_DATA_CONNECTION_DRS_OR_RAT_CHANGED消息的处理
在DataConnection.java中处理:
case EVENT_DATA_CONNECTION_DRS_OR_RAT_CHANGED:
ar = (AsyncResult) msg.obj;
Pair<Integer, Integer> drsRatPair = (Pair<Integer, Integer>) ar.result;
mDataRegState = drsRatPair.first;
if (mRilRat != drsRatPair.second) {
updateTcpBufferSizes(drsRatPair.second);
}
mRilRat = drsRatPair.second;
if (DBG) {
log("DcDefaultState: EVENT_DATA_CONNECTION_DRS_OR_RAT_CHANGED"
+ " drs=" + mDataRegState
+ " mRilRat=" + mRilRat);
} ServiceState ss = mPhone.getServiceState(); //实例化ServiceState
// M: [C2K][IRAT] Get network type from IRAT controller
// TODO: check if the message is handled before
// IratController update its current RAT.
if (CdmaFeatureOptionUtils.isCdmaLteDcSupport()) {
//can get networkType from svltePhoneProxy to get right network type
ServiceState svlteSs = SvlteUtils.getSvltePhoneProxy(mPhone.getPhoneId())
.getSvlteServiceState();
if (svlteSs != null) {
ss = svlteSs;
}
}
int networkType = ss.getDataNetworkType(); mNetworkInfo.setSubtype(networkType,
TelephonyManager.getNetworkTypeName(networkType));
if (mNetworkAgent != null) {
updateNetworkInfoSuspendState();
mNetworkAgent.sendNetworkCapabilities(makeNetworkCapabilities());
mNetworkAgent.sendNetworkInfo(mNetworkInfo);
mNetworkAgent.sendLinkProperties(mLinkProperties);
}
break;
设置网络参数
public void setDataRegState(int state) {
mDataRegState = state;
if (DBG) Rlog.d(LOG_TAG, "[ServiceState] setDataRegState=" + mDataRegState);
} public void setRilDataRadioTechnology(int rt) {
this.mRilDataRadioTechnology = rt;
if (DBG) Rlog.d(LOG_TAG, "[ServiceState] setDataRadioTechnology=" + mRilDataRadioTechnology);
}
开关VoLTE流程分析(二)的更多相关文章
- Android8.1 开关VOLTE流程分析
前言 最近有需求需要实现插卡默认打开Volte功能,顺带研究了下Volte的流程,在此做个记录 开始 从Settings设置界面入手,网络和互联网-->移动网络-->VoLTE高清通话(电 ...
- 开关VoLTE流程分析(一)
开关按钮位置: 设置--> 更多--> 移动网络--> 增强型4G LTE模式 控件初始化addEnhanced4GLteSwitchPreference,该设置开关使用了Switc ...
- Android 7.1 WindowManagerService 屏幕旋转流程分析 (二)
一.概述 从上篇[Android 7.1 屏幕旋转流程分析]知道实际的旋转由WindowManagerService来完成,这里接着上面具体详细展开. 调了三个函数完成了三件事,即首先调用update ...
- Gradle之Android Gradle Plugin 主要流程分析(二)
[Android 修炼手册]Gradle 篇 -- Android Gradle Plugin 主要流程分析 预备知识 理解 gradle 的基本开发 了解 gradle task 和 plugin ...
- Android 4.4 音量调节流程分析(二)
之前在Android 4.4 音量调节流程分析(一)里已经有简单的分析音量控制的流程,今天想接着继续分析下音量大小计算的方法.对于任一播放文件而言其本身都有着固定大小的音量Volume_Max,而在A ...
- MSM8909中LK阶段LCM屏适配与显示流程分析(二)
1.前言 在前面的文章MSM8909中LK阶段LCM屏适配与显示流程分析(一),链接如下: https://www.cnblogs.com/Cqlismy/p/12019317.html 介绍了如何使 ...
- Uboot启动流程分析(二)
1.前言 在前面的文章Uboot启动流程分析(一)中,链接如下: https://www.cnblogs.com/Cqlismy/p/12000889.html 已经简单地分析了low_level_i ...
- Nginx-HTTP之静态网页访问流程分析二
11. HTTP 阶段执行 下面会依次执行以下阶段: NGX_HTTP_SERVER_REWRITE_PHASE: 在将请求的 URI 与 location 表达式匹配前,修改请求的 URI (所谓重 ...
- Uboot启动流程分析(三)
1.前言 在前面的文章Uboot启动流程分析(二)中,链接如下: https://www.cnblogs.com/Cqlismy/p/12002764.html 已经对_main函数的整个大体调用流程 ...
随机推荐
- 子进程回收资源两种方式,僵尸进程与孤儿进程,守护进程,进程间数据隔离,进程互斥锁,队列,IPC机制,线程,守护线程,线程池,回调函数add_done_callback,TCP服务端实现并发
子进程回收资源两种方式 - 1) join让主进程等待子进程结束,并回收子进程资源,主进程再结束并回收资源. - 2) 主进程 “正常结束” ,子进程与主进程一并被回收资源. from multipr ...
- InfoQ一波文章:菜鸟核心技术/Intel发布CPU新架构3D堆栈法/BDL/PaddlePaddle/百度第三代Spider/Tera
菜鸟智慧新物流核心技术全解析 孟靖 阅读数:63192018 年 12 月 14 日 16:00 2018 年天猫双 11 全球狂欢节已正式落下帷幕,最终成交额定格在 2135 亿元,物流订单 ...
- nginx 服务端口权限13的问题
参考此文:https://blog.csdn.net/RunSnail2018/article/details/81185138
- python之路—从入门到放弃
python基础部分 函数 初识函数 函数进阶 装饰器函数 迭代器和生成器 内置函数和匿名函数 递归函数 常用模块 常用模块 模块和包 面向对象 初识面向对象 面向对象进阶 网络编程 网络编程 并发编 ...
- Visualforce 页面的生命周期
了解 Visualforce 页面的生命周期可以让我们明白其各个元素的执行顺序.改变逻辑,从而提高开发效率,避免不必要的错误. 在官方文档中有详细的讲解.本文摘取其中的要点,作为一个总结. Visua ...
- string方法介绍
#_*_coding:utf-8_*_#作者:王佃元#日期:2019/12/9#string操作print('hello'*2) #乘法操作,输出对应次数print('helloworld'[2:]) ...
- 【LG5171】Earthquake
[LG5171Earthquake] 题面 洛谷 题解 本题需要用到类欧几里得算法. 前置知识:类欧几里得 就是求函数\[\varphi (a,b,c,n)=\sum_{i=0}^n \left\lf ...
- SpringBoot 2.x 整合Lombok
Lombok的官方介绍 Project Lombok is a java library that automatically plugs into your editor and build too ...
- linux _文件目录与权限
1. 目录相关 . 代表次层目录 .. 代表上一层目录 - 代表前一个工作目录 ~ 代表目前使用者身份所在home目录 ~account 代表account这个使用者的home目录 cd 切换目录(c ...
- JAVA Api 调用Hbase报错锦集
1. 报错 java.lang.NoClassDefFoundError: org/apache/hadoop/hbase/protobuf/generated/MasterProtos$Master ...