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流程分析(二)的更多相关文章

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

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

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

    开关按钮位置: 设置--> 更多--> 移动网络--> 增强型4G LTE模式 控件初始化addEnhanced4GLteSwitchPreference,该设置开关使用了Switc ...

  3. Android 7.1 WindowManagerService 屏幕旋转流程分析 (二)

    一.概述 从上篇[Android 7.1 屏幕旋转流程分析]知道实际的旋转由WindowManagerService来完成,这里接着上面具体详细展开. 调了三个函数完成了三件事,即首先调用update ...

  4. Gradle之Android Gradle Plugin 主要流程分析(二)

    [Android 修炼手册]Gradle 篇 -- Android Gradle Plugin 主要流程分析 预备知识 理解 gradle 的基本开发 了解 gradle task 和 plugin ...

  5. Android 4.4 音量调节流程分析(二)

    之前在Android 4.4 音量调节流程分析(一)里已经有简单的分析音量控制的流程,今天想接着继续分析下音量大小计算的方法.对于任一播放文件而言其本身都有着固定大小的音量Volume_Max,而在A ...

  6. MSM8909中LK阶段LCM屏适配与显示流程分析(二)

    1.前言 在前面的文章MSM8909中LK阶段LCM屏适配与显示流程分析(一),链接如下: https://www.cnblogs.com/Cqlismy/p/12019317.html 介绍了如何使 ...

  7. Uboot启动流程分析(二)

    1.前言 在前面的文章Uboot启动流程分析(一)中,链接如下: https://www.cnblogs.com/Cqlismy/p/12000889.html 已经简单地分析了low_level_i ...

  8. Nginx-HTTP之静态网页访问流程分析二

    11. HTTP 阶段执行 下面会依次执行以下阶段: NGX_HTTP_SERVER_REWRITE_PHASE: 在将请求的 URI 与 location 表达式匹配前,修改请求的 URI (所谓重 ...

  9. Uboot启动流程分析(三)

    1.前言 在前面的文章Uboot启动流程分析(二)中,链接如下: https://www.cnblogs.com/Cqlismy/p/12002764.html 已经对_main函数的整个大体调用流程 ...

随机推荐

  1. 子进程回收资源两种方式,僵尸进程与孤儿进程,守护进程,进程间数据隔离,进程互斥锁,队列,IPC机制,线程,守护线程,线程池,回调函数add_done_callback,TCP服务端实现并发

    子进程回收资源两种方式 - 1) join让主进程等待子进程结束,并回收子进程资源,主进程再结束并回收资源. - 2) 主进程 “正常结束” ,子进程与主进程一并被回收资源. from multipr ...

  2. InfoQ一波文章:菜鸟核心技术/Intel发布CPU新架构3D堆栈法/BDL/PaddlePaddle/百度第三代Spider/Tera

    菜鸟智慧新物流核心技术全解析   孟靖 阅读数:63192018 年 12 月 14 日 16:00   2018 年天猫双 11 全球狂欢节已正式落下帷幕,最终成交额定格在 2135 亿元,物流订单 ...

  3. nginx 服务端口权限13的问题

    参考此文:https://blog.csdn.net/RunSnail2018/article/details/81185138

  4. python之路—从入门到放弃

    python基础部分 函数 初识函数 函数进阶 装饰器函数 迭代器和生成器 内置函数和匿名函数 递归函数 常用模块 常用模块 模块和包 面向对象 初识面向对象 面向对象进阶 网络编程 网络编程 并发编 ...

  5. Visualforce 页面的生命周期

    了解 Visualforce 页面的生命周期可以让我们明白其各个元素的执行顺序.改变逻辑,从而提高开发效率,避免不必要的错误. 在官方文档中有详细的讲解.本文摘取其中的要点,作为一个总结. Visua ...

  6. string方法介绍

    #_*_coding:utf-8_*_#作者:王佃元#日期:2019/12/9#string操作print('hello'*2) #乘法操作,输出对应次数print('helloworld'[2:]) ...

  7. 【LG5171】Earthquake

    [LG5171Earthquake] 题面 洛谷 题解 本题需要用到类欧几里得算法. 前置知识:类欧几里得 就是求函数\[\varphi (a,b,c,n)=\sum_{i=0}^n \left\lf ...

  8. SpringBoot 2.x 整合Lombok

    Lombok的官方介绍 Project Lombok is a java library that automatically plugs into your editor and build too ...

  9. linux _文件目录与权限

    1. 目录相关 . 代表次层目录 .. 代表上一层目录 - 代表前一个工作目录 ~ 代表目前使用者身份所在home目录 ~account 代表account这个使用者的home目录 cd 切换目录(c ...

  10. JAVA Api 调用Hbase报错锦集

    1. 报错 java.lang.NoClassDefFoundError: org/apache/hadoop/hbase/protobuf/generated/MasterProtos$Master ...