android 系统数据业务---模式切换分析(上)
2017-07-17 19:55
344 查看
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 系统数据业务---模式切换分析(下)
- 原因分析如下: 遇到这种情况,很有可能是把一个int型业务数据的 设置setText()或者类似的方法中, 这样Android系统就会主动去资源文件当中寻找, 但是它不是一个资源文件ID, 所
- android 系统上做GC双模的---数据业务的处理分析
- android 系统上做GC双模的---数据业务的处理分析
- android源码分析--MMS data 数据模型及业务逻辑transaction
- 研读《基于Hadoop的海量业务数据分析平台的设计与实现》----flume的数据收集系统的设计
- Android Audio 系统框架数据流分析
- 业务数据分析系统
- Android 数据业务框架分析<二>
- 【Android 数据业务解析】PreferredApn修改的源码分析
- 【案例实战】餐饮企业分店财务数据分析系统解决方案:业务需求
- android 系统数据业务---phone进程启动
- Android系统中视频电话中camera部分数据流分析
- Android 数据业务框架分析<三>
- android系统源码分析——binder基础数据结构
- 【案例实战】餐饮企业分店财务数据分析系统解决方案:业务需求
- Android系统中视频电话中camera部分数据流分析
- 商业智能系统--公司业务、系统执行统计数据和分析
- Android 5.0 Camera系统源码分析(4):Camera预览流程数据流
- 赵雅智_android系统联系人app分析并获取数据