android 系统数据业务---模式切换分析(上)

原创 2017年07月17日 19:55:15

5 setPreferredNetworkType详解

5.1 RIL处理

RIL.java中setPreferredNetworkType方法如下,

@Override
public void setPreferredNetworkType(int networkType , Message response) {
      RILRequest rr = RILRequest.obtain(
          RILConstants.RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE, response);
rr.mParcel.writeInt(1);
      rr.mParcel.writeInt(networkType);
mPreferredNetworkType = networkType;
if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
                + " : " + networkType);
send(rr);
}

发送的是RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE类型的消息。

 

每一个通过RIL发送的消息都会有对应的返回消息,RIL中的processSolicited方法会对

RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE类型的消息处理如下,

A,首先获取ril库上报的数据,

case RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE: ret =  responseVoid(p); break;

responseVoid方法返回的是null,

B,然后进行回调,

if (rr.mResult != null) {
      AsyncResult.forMessage(rr.mResult, ret, null);
      rr.mResult.sendToTarget();
}

AsyncResult 回调就一个原则,谁发起谁处理。

回看MobileNetworkSettings的onPreferenceChange方法,

mPhone.setPreferredNetworkType(modemNetworkMode, mHandler
    .obtainMessage(MyHandler.MESSAGE_SET_PREFERRED_NETWORK_TYPE));

调用PhoneProxy的setPreferredNetworkType携带的是MESSAGE_SET_PREFERRED_NETWORK_TYPE消息,

因此AsyncResult 回调到MobileNetworkSettings, MobileNetworkSettings中对MESSAGE_SET_PREFERRED_NETWORK_TYPE

消息处理如下,

case MESSAGE_SET_PREFERRED_NETWORK_TYPE:
      handleSetPreferredNetworkTypeResponse(msg);
    break;

handleSetPreferredNetworkTypeResponse方法如下,

private void handleSetPreferredNetworkTypeResponse(Message msg) {
   AsyncResult ar = (AsyncResult) msg.obj;
   final int phoneSubId = mPhone.getSubId();
if (ar.exception == null) {
          int networkMode = Integer.valueOf(
               mButtonPreferredNetworkMode.getValue()).intValue();
         android.provider.Settings.Global.putInt(mPhone.getContext().getContentResolver(),
          android.provider.Settings.Global.PREFERRED_NETWORK_MODE + phoneSubId,
                        networkMode );
         networkMode = Integer.valueOf(mButtonEnabledNetworks.getValue()).intValue();
         android.provider.Settings.Global.putInt(mPhone.getContext().getContentResolver(),
          android.provider.Settings.Global.PREFERRED_NETWORK_MODE + phoneSubId,
                        networkMode );
      } else { 
mPhone.getPreferredNetworkType(obtainMessage(
MESSAGE_GET_PREFERRED_NETWORK_TYPE));
      }
}

A,如果ril库对RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE 消息处理没有出现异常,则再次将网络模式

写入到数据库中保存起来。

B,否则接着调用PhoneProxy的getPreferredNetworkType方法获取当前的网络模式。这个方法的调用流程和

setPreferredNetworkType方法调用流程完全一样,在此就不赘述了。

其实模式切换比打开还要复杂,首先会断开原来的连接,然后重新发起拨号,最后拨号完成。

5.2 RIL_UNSOL_DATA_CALL_LIST_CHANGED

一般情况下,打开数据网络并且设置网络模式之后,就可以正常的拨号上网了.一般的各大国内厂商的手机也都可以上网,

因为基于高通解决方案的reference-ril库比较稳定.但是一些模块厂商的reference-ril库很不稳定,存在或多或少的问题

导致模式切换的时候无法上网。一般情况下,有以下2种情况导致数据业务连接失败:

1, Modem未上报RIL_UNSOL_DATA_CALL_LIST_CHANGED消息,或者上报包含错误码或者链接中断;

2, 数据网络模式切换时,查询 RIL_REQUEST_DATA_REGISTRATION_STATE消息出错;

一般地,在模式切换时,中间会断开并且重新连接一次,而负责重新连接的就是根据modem上报的

RIL_UNSOL_DATA_CALL_LIST_CHANGED消息,RIL.java对的processUnsolicited方法该消息的处理如下,

首先获取并解析底层ril上传的数据,

case RIL_UNSOL_DATA_CALL_LIST_CHANGED: ret = responseDataCallList(p);break;

responseDataCallList方法如下,

private Object
    responseDataCallList(Parcel p) {
        ArrayList<DataCallResponse> response;
        int ver = p.readInt();
        int num = p.readInt();//读取socket数据
        riljLog("responseDataCallList ver=" + ver + " num=" + num);
        response = new ArrayList<DataCallResponse>(num);
        for (int i = 0; i < num; i++) {
            response.add(getDataCallResponse(p, ver));//解析
        }
        return response;
    }

解析完数据之后,将数据发送出去,进行回调.

case RIL_UNSOL_DATA_CALL_LIST_CHANGED:
    if (RILJ_LOGD) unsljLogRet(response, ret);
mDataNetworkStateRegistrants.notifyRegistrants(new AsyncResult(null, ret, null));
break;

RIL.java中的消息都是谁注册谁处理, mDataNetworkStateRegistrants是谁注册的呢?

RIL的父类BaseCommands中, registerForDataNetworkStateChanged方法如下,

@Override
public void registerForDataNetworkStateChanged(Handler h, int what, Object obj) {
Registrant r = new Registrant (h, what, obj);
mDataNetworkStateRegistrants.add(r);
}

DcController的内部类DccDefaultState调用registerForDataNetworkStateChanged方法进行注册的,

DccDefaultState是一个状态机,刚开始进入该状态时就会注册,

public void enter() {
   mPhone.mCi.registerForRilConnected(getHandler(),
                    DataConnection.EVENT_RIL_CONNECTED, null);
   mPhone.mCi.registerForDataNetworkStateChanged(getHandler(),
                    DataConnection.EVENT_DATA_STATE_CHANGED, null);
   if (Build.IS_DEBUGGABLE) {
         mDcTesterDeactivateAll =
                new DcTesterDeactivateAll(mPhone, DcController.this, getHandler());
    }
}

注册时handler类型是EVENT_DATA_STATE_CHANGED,因此, mDataNetworkStateRegistrants.notifyRegistrants(newAsyncResult(null, ret, null)) 

这句回调的是DccDefaultState的processMessage方法,有关EVENT_DATA_STATE_CHANGED消息处理的代码如下,

case DataConnection.EVENT_DATA_STATE_CHANGED:
      ar = (AsyncResult)msg.obj;
      if (ar.exception == null) {
          onDataStateChanged((ArrayList<DataCallResponse>)ar.result);
      } else {
           log("DccDefaultState: EVENT_DATA_STATE_CHANGED:" +
                                    " exception; likely radio not available, ignore");
      }
    break;

在onDataStateChanged方法中,首先读取上报的数据,然后根据状态做不同的处理.

一般数据网络模式切换时候出现问题大部分都是因为RIL_UNSOL_DATA_CALL_LIST_CHANGED消息,具体的问题可以

分析onDataStateChanged方法,该方法会打出大量的log。

RIL上报RIL_UNSOL_DATA_CALL_LIST_CHANGED消息时,一般会有2种结果,

1,网络从连接的状态转到断开状态;

2,网络从断开状态转到连接状态。

5.2.1 转到断开状态

如果当前状态是连接状态,在onDataStateChanged中关键代码如下,

for (DataConnection dc : dcsToRetry) {
     dc.sendMessage(DataConnection.EVENT_LOST_CONNECTION, dc.mTag);
}

然后DataConnection中的DcActiveState状态的processMessage方法就会处理EVENT_LOST_CONNECTION消息,

case EVENT_LOST_CONNECTION: {
    •••
    if (mRetryManager.isRetryNeeded()) {
         •••
        mDcRetryAlarmController.startRetryAlarm(EVENT_RETRY_CONNECTION, mTag,
                                delayMillis);
        transitionTo(mRetryingState);
    }
•••

跳转到DcRetryingState状态,就像在第三章中论述的那样,无论DcActiveState跳到哪种状态,最后都会调用exit方法进而

调用NetworkAgent的sendNetworkInfo方法更新网络状态。

如果是正常断开的话,DcRetryingState状态会立即转为DcInactiveState状态,

DcRetryingState的enter方法中对应的代码如下,

mInactiveState.setEnterNotificationParams(DcFailCause.LOST_CONNECTION);
transitionTo(mInactiveState);

5.2.2 转到连接状态

从DcInactiveState状态一直转换到DcActiveState状态的过程详见第2.3小节。

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

Android 电话系统框架介绍

在android系统中rild运行在AP上,AP上的应用通过rild发送AT指令给BP,BP接收到信息后又通过rild传送给AP。AP与BP之间有两种通信方式: 1.Solicited Resp...

[Android6.0] 数据业务重试机制

解析Android telephony对数据链接错误的重试机制。
  • lcr006
  • lcr006
  • 2016年12月26日 10:45
  • 1399

android 6.0 优先网络类型设置流程(Preferrred network type)

本文主要介绍在settings –> Mobile network –> Preferred network type 选择某个网络类型的流程整体流程图重点代码分析1、是否包含global选项最开始执...

Android 首选网络模式默认值的修改方法

修改系统属性:ro.telephony.default_network 修改说明: 可连续给两个值(如4,1),卡1用的是4,卡2用的是1。数字代表的意义见下方的相关代码片段。 相关源码位置: f...

Android RIL java 详解---------command interface

概括

Android RIL Java

RIL-Java在本质上就是一个RIL代理,起到一个转发的作用,是Android Java概念空间中的电话系统的起点。 在RIL-D的分析中,我们知道RILD建立了一个侦听套接口,等待RIL...
  • hgl868
  • hgl868
  • 2011年10月05日 08:05
  • 3187

Android核心分析(18)-----Android电话系统之RIL-Java

Android RIL-Java     RIL-Java在本质上就是一个RIL代理,起到一个转发的作用,是Android Java概念空间中的电话系统的起点。在RIL-D的分析中,我们知道RI...
  • maxleng
  • maxleng
  • 2010年05月14日 23:07
  • 54090

Android RIL的java框架

Android RIL的Java部分也被分为了两个模块,RIL模块与Phone模块。其中RIL模块负责进行请求以及相应的处理,它将直接与RIL的原声代码进行通信。而Phone模块则向应用程序开发者提供...

【Android架构Telephony篇】数据业务(3)RILC

Telephony数据业务的RILC层

Android——RIL 机制源码分析

Android 电话系统框架介绍在Android系统中rild运行在AP上,AP上的应用通过rild发送AT指令给BP,BP接收到信息后又通过rild传送给AP。AP与BP之间有两种通信方式:1.So...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:android 系统数据业务---模式切换分析(上)
举报原因:
原因补充:

(最多只允许输入30个字)