Android 5.1 close data flow 数据关闭流程
2015-11-26 18:59
471 查看
惯例流程图先
流程是入口是Settings->DataUsage的开关,后面会看一下从下拉快速设置的入口进入。
android/packages/apps/Settings/src/com/android/settings/DataUsageSummary.java
关闭数据开关时,会弹出确认窗口
ConfirmDataDisableFragment.show(DataUsageSummary.this);
点击确认后即开始关闭数据的后续流程
target.setMobileDataEnabled(false);
获得当前TAB对应的SIM卡subId
mTelephonyManager.setDataEnabled(subId[0],
enabled);
android/frameworks/base/telephony/java/android/telephony/TelephonyManager.java
getITelephony().setDataEnabled(subId,
enable);
android/packages/services/Telephony/src/com/android/phone/PhoneInterfaceManager.java
phone.setDataEnabled(enable);
android/frameworks/opt/telephony/src/java/com/android/internal/telephony/gsm/GSMPhone.java
mDcTracker.setDataEnabled(enable);
android/frameworks/opt/telephony/src/java/com/android/internal/telephony/dataconnection/DcTrackerBase.java
onSetUserDataEnabled(enabled);
onCleanUpAllConnections
android/frameworks/opt/telephony/src/java/com/android/internal/telephony/dataconnection/DcTracker.java
这个类比较复杂,我们只看本次重点。
cleanUpAllConnections(true,
cause);
下面这里会循环多次。for(ApnContext
apnContext:
mApnContexts.values())
每一次进来后if(apnContext.isDisconnected())的判断结果是不一样的,apnContext={mApnType=default
mState=CONNECTEDmApnType为其他时,其mState一般是IDLE的
android/frameworks/opt/telephony/src/java/com/android/internal/telephony/dataconnection/DcAsyncChannel.java
sendMessage
android/frameworks/opt/telephony/src/java/com/android/internal/telephony/dataconnection/DataConnection.java
这个也挺复杂的维护了一个状态机StateMachine
tearDownData(dp);
mPhone.mCi.deactivateDataCall
调用到RIL.java中的方法
android/frameworks/opt/telephony/src/java/com/android/internal/telephony/RIL.java
--------------
流程是入口是Settings->DataUsage的开关,后面会看一下从下拉快速设置的入口进入。
android/packages/apps/Settings/src/com/android/settings/DataUsageSummary.java
关闭数据开关时,会弹出确认窗口
ConfirmDataDisableFragment.show(DataUsageSummary.this);
privateView.OnClickListenermDataEnabledListener=newView.OnClickListener(){
@Override
publicvoidonClick(Viewv){
if(mBinding)return;
finalbooleandataEnabled=!mDataEnabled.isChecked();
finalStringcurrentTab=mCurrentTab;
if(TAB_MOBILE.equals(currentTab)||currentTab.startsWith(TAB_SIM)){
if(dataEnabled){
setMobileDataEnabled(true);
if(mPolicyEditor.getPolicyWarningBytes(mTemplate)==WARNING_DISABLED){
mPolicyEditor.setPolicyWarningBytes(mTemplate,2*GB_IN_BYTES);
}
}else{
//disablingdata;showconfirmationdialogwhicheventually
//callssetMobileDataEnabled()onceuserconfirms.
ConfirmDataDisableFragment.show(DataUsageSummary.this);
}
}
updatePolicy(false);
}
};[/code]
点击确认后即开始关闭数据的后续流程
target.setMobileDataEnabled(false);
/**
*Dialogtorequestuserconfirmationbeforedisablingdata.
*/
publicstaticclassConfirmDataDisableFragmentextendsDialogFragment{
publicstaticvoidshow(DataUsageSummaryparent){
if(!parent.isAdded())return;
finalConfirmDataDisableFragmentdialog=newConfirmDataDisableFragment();
dialog.setTargetFragment(parent,0);
dialog.show(parent.getFragmentManager(),TAG_CONFIRM_DATA_DISABLE);
}
@Override
publicDialogonCreateDialog(BundlesavedInstanceState){
finalContextcontext=getActivity();
finalAlertDialog.Builderbuilder=newAlertDialog.Builder(context);
builder.setMessage(R.string.data_usage_disable_mobile);
builder.setPositiveButton(android.R.string.ok,newDialogInterface.OnClickListener(){
@Override
publicvoidonClick(DialogInterfacedialog,intwhich){
finalDataUsageSummarytarget=(DataUsageSummary)getTargetFragment();
if(target!=null){
//TODO:extendtomodifypolicyenabledflag.
target.setMobileDataEnabled(false);
}
}
});
builder.setNegativeButton(android.R.string.cancel,null);
returnbuilder.create();
}
}[/code]
获得当前TAB对应的SIM卡subId
mTelephonyManager.setDataEnabled(subId[0],
enabled);
privatevoidsetMobileDataEnabled(booleanenabled){
if(LOGD)Log.d(TAG,"setMobileDataEnabled()");
//HowaboutexposingsubbasedAPIlikeTelephonyManager.setDataEnabled(intsubId);
if(mCurrentTab.startsWith(TAB_SIM)){
intphoneId=multiSimGetCurrentSub();
//asperphone,settheindividualflag
android.provider.Settings.Global.putInt(getActivity().getContentResolver(),
android.provider.Settings.Global.MOBILE_DATA+phoneId,enabled?1:0);
int[]subId=SubscriptionManager.getSubId(phoneId);
mTelephonyManager.setDataEnabled(subId[0],enabled);
}else{
mTelephonyManager.setDataEnabled(enabled);
mMobileDataEnabled=enabled;
}
updatePolicy(false);
}[/code]
android/frameworks/base/telephony/java/android/telephony/TelephonyManager.java
getITelephony().setDataEnabled(subId,
enable);
/**@hide*/
@SystemApi
publicvoidsetDataEnabled(intsubId,booleanenable){
try{
AppOpsManagerappOps=(AppOpsManager)mContext.getSystemService(Context.APP_OPS_SERVICE);
if(enable){
if(appOps.noteOp(AppOpsManager.OP_DATA_CONNECT_CHANGE)!=AppOpsManager.MODE_ALLOWED){
Log.w(TAG,"Permissiondeniedbyuser.");
return;
}
}
Log.d(TAG,"setDataEnabled:enabled="+enable);
getITelephony().setDataEnabled(subId,enable);
}catch(RemoteExceptione){
Log.e(TAG,"ErrorcallingsetDataEnabled",e);
}
}[/code]
android/packages/services/Telephony/src/com/android/phone/PhoneInterfaceManager.java
phone.setDataEnabled(enable);
/**
*Setmobiledataenabled
*Usedbytheuserthroughsettingsetctoturnon/offmobiledata
*
*@paramenable{@codetrue}turnturndataon,else{@codefalse}
*/
@Override
publicvoidsetDataEnabled(intsubId,booleanenable){
enforceModifyPermission();
intphoneId=mSubscriptionController.getPhoneId(subId);
log("getDataEnabled:subId="+subId+"phoneId="+phoneId);
Phonephone=PhoneFactory.getPhone(phoneId);
if(phone!=null){
log("setDataEnabled:subId="+subId+"enable="+enable);
phone.setDataEnabled(enable);
}else{
loge("setDataEnabled:nophoneforsubId="+subId);
}
}[/code]
android/frameworks/opt/telephony/src/java/com/android/internal/telephony/gsm/GSMPhone.java
mDcTracker.setDataEnabled(enable);
@Override
publicvoidsetDataEnabled(booleanenable){
mDcTracker.setDataEnabled(enable);
}[/code]
android/frameworks/opt/telephony/src/java/com/android/internal/telephony/dataconnection/DcTrackerBase.java
/**
*Modify{@linkandroid.provider.Settings.Global#MOBILE_DATA}value.
*/
publicvoidsetDataEnabled(booleanenable){
Messagemsg=obtainMessage(DctConstants.CMD_SET_USER_DATA_ENABLE);
msg.arg1=enable?1:0;
sendMessage(msg);
}[/code]
onSetUserDataEnabled(enabled);
@Override
publicvoidhandleMessage(Messagemsg){
switch(msg.what){
caseAsyncChannel.CMD_CHANNEL_DISCONNECTED:{
log("DISCONNECTED_CONNECTED:msg="+msg);
DcAsyncChanneldcac=(DcAsyncChannel)msg.obj;
mDataConnectionAcHashMap.remove(dcac.getDataConnectionIdSync());
dcac.disconnected();
break;
}
...
caseDctConstants.CMD_SET_USER_DATA_ENABLE:{
finalbooleanenabled=(msg.arg1==DctConstants.ENABLED)?true:false;
if(DBG)log("CMD_SET_USER_DATA_ENABLEenabled="+enabled);
onSetUserDataEnabled(enabled);
break;
}
...[/code]
onCleanUpAllConnections
protectedvoidonSetUserDataEnabled(booleanenabled){
synchronized(mDataEnabledLock){
if(mUserDataEnabled!=enabled){
mUserDataEnabled=enabled;
Settings.Global.putInt(mPhone.getContext().getContentResolver(),
Settings.Global.MOBILE_DATA+mPhone.getPhoneId(),enabled?1:0);
if(getDataOnRoamingEnabled()==false&&
mPhone.getServiceState().getRoaming()==true){
if(enabled){
notifyOffApnsOfAvailability(Phone.REASON_ROAMING_ON);
}else{
notifyOffApnsOfAvailability(Phone.REASON_DATA_DISABLED);
}
}
if(enabled){
onTrySetupData(Phone.REASON_DATA_ENABLED);
}else{
onCleanUpAllConnections(Phone.REASON_DATA_SPECIFIC_DISABLED);//1
}
}
}
}[/code]
android/frameworks/opt/telephony/src/java/com/android/internal/telephony/dataconnection/DcTracker.java
这个类比较复杂,我们只看本次重点。
cleanUpAllConnections(true,
cause);
/**
*Cleanupallconnections.
*
*TODO:Cleanuponlyaspecifiedconnectionpassedasaparameter.
*Also,makesurewhenyoucleanupaconn,ifitislastapply
*logicasthoughitiscleanupAllConnections
*
*@paramcauseforthecleanup.
*/
@Override
protectedvoidonCleanUpAllConnections(Stringcause){
cleanUpAllConnections(true,cause);
}[/code]
下面这里会循环多次。for(ApnContext
apnContext:
mApnContexts.values())
/**
*IftearDownistrue,thisonlytearsdownaCONNECTEDsession.Presently,
*thereisnomechanismforabandoninganCONNECTINGsession,
*butwouldlikelyinvolvecancellingpendingasyncrequestsor
*settingaflagornewstatetoignorethemwhentheycamein
*@paramtearDowntrueiftheunderlyingDataConnectionshouldbe
*disconnected.
*@paramreasonreasonforthecleanup.
*@returnboolean-trueifwedidcleanupanyconnections,falseifthey
*werealreadyalldisconnected.
*/
protectedbooleancleanUpAllConnections(booleantearDown,Stringreason){
if(DBG)log("cleanUpAllConnections:tearDown="+tearDown+"reason="+reason);
booleandidDisconnect=false;
booleanspecificdisable=false;
if(!TextUtils.isEmpty(reason)){
specificdisable=reason.equals(Phone.REASON_DATA_SPECIFIC_DISABLED);
}
for(ApnContextapnContext:mApnContexts.values()){
if(apnContext.isDisconnected()==false)didDisconnect=true;
if(specificdisable){
if(!apnContext.getApnType().equals(PhoneConstants.APN_TYPE_IMS)){
if(DBG)log("ApnConextType:"+apnContext.getApnType());
apnContext.setReason(reason);
cleanUpConnection(tearDown,apnContext);//2
}
}else{
//TODO-onlydocleanupifnotdisconnected
apnContext.setReason(reason);
cleanUpConnection(tearDown,apnContext);
}
}
stopNetStatPoll();
stopDataStallAlarm();
//TODO:DoweneedmRequestedApnType?
mRequestedApnType=PhoneConstants.APN_TYPE_DEFAULT;
log("cleanUpConnection:mDisconnectPendingCount="+mDisconnectPendingCount);
if(tearDown&&mDisconnectPendingCount==0){
notifyDataDisconnectComplete();
notifyAllDataDisconnected();
}
returndidDisconnect;
}[/code]
每一次进来后if(apnContext.isDisconnected())的判断结果是不一样的,apnContext={mApnType=default
mState=CONNECTEDmApnType为其他时,其mState一般是IDLE的
protectedvoidcleanUpConnection(booleantearDown,ApnContextapnContext){
if(apnContext==null){
if(DBG)log("cleanUpConnection:apncontextisnull");
return;
}
DcAsyncChanneldcac=apnContext.getDcAc();
if(DBG){
log("cleanUpConnection:EtearDown="+tearDown+"reason="+apnContext.getReason()+
"apnContext="+apnContext);
}
if(tearDown){//3
if(apnContext.isDisconnected()){
//TherequestistearDownandbutApnContextisnotconnected.
//IfapnContextisnotenabledanymore,breakthelinkagetotheDCAC/DC.
apnContext.setState(DctConstants.State.IDLE);
if(!apnContext.isReady()){
if(dcac!=null){
dcac.tearDown(apnContext,"",null);
}
apnContext.setDataConnectionAc(null);
}
}else{
//Connectionisstillthere.Trytocleanup.
if(dcac!=null){//4
if(apnContext.getState()!=DctConstants.State.DISCONNECTING){
booleandisconnectAll=false;
if(PhoneConstants.APN_TYPE_DUN.equals(apnContext.getApnType())){
//CAF_MSIMisthisbelowconditionrequired.
//if(PhoneConstants.APN_TYPE_DUN.equals(PhoneConstants.APN_TYPE_DEFAULT)){
if(teardownForDun()){
if(DBG)log("tearingdowndedicatedDUNconnection");
//weneedtotearitdown-webroughtitupjustfordunand
//otherpeoplearecampedonitandnowdunisdone.Weneed
//tostopusingitandletthenormalapnlistgetusedtofind
//connectionsfortheremainingdesiredconnections
disconnectAll=true;
}
}
if(DBG){
log("cleanUpConnection:tearingdown"+(disconnectAll?"all":""));
}
Messagemsg=obtainMessage(DctConstants.EVENT_DISCONNECT_DONE,apnContext);//4
if(disconnectAll){
apnContext.getDcAc().tearDownAll(apnContext.getReason(),msg);
}else{
apnContext.getDcAc()
.tearDown(apnContext,apnContext.getReason(),msg);
}
apnContext.setState(DctConstants.State.DISCONNECTING);
mDisconnectPendingCount++;
}
}else{
//apnisconnectedbutnoreferencetodcac.
//Shouldnotbehappen,butresetthestateincase.
apnContext.setState(DctConstants.State.IDLE);
mPhone.notifyDataConnection(apnContext.getReason(),
apnContext.getApnType());
}
}
}else{
//forcecleanupthedataconnection.
if(dcac!=null)dcac.reqReset();
apnContext.setState(DctConstants.State.IDLE);
mPhone.notifyDataConnection(apnContext.getReason(),apnContext.getApnType());
apnContext.setDataConnectionAc(null);
}
if(mOmhApt!=null){
mOmhApt.clearActiveApnProfile();
}
//MakesurereconnectionalarmiscleanedupifthereisnoApnContext
//associatedtotheconnection.
if(dcac!=null){
cancelReconnectAlarm(apnContext);
}
setupDataForSinglePdnArbitration(apnContext.getReason());
if(DBG){
log("cleanUpConnection:XtearDown="+tearDown+"reason="+apnContext.getReason()+
"apnContext="+apnContext+"dcac="+apnContext.getDcAc());
}
}[/code]
android/frameworks/opt/telephony/src/java/com/android/internal/telephony/dataconnection/DcAsyncChannel.java
sendMessage
/**
*Teardowntheconnectionthroughtheapnonthenetwork.
*
*@paramonCompletedMsgissentwithitsmsg.objasanAsyncResultobject.
*WithAsyncResult.userObjsettotheoriginalmsg.obj.
*/
publicvoidtearDown(ApnContextapnContext,Stringreason,MessageonCompletedMsg){
if(DBG){
log("tearDown:apnContext="+apnContext
+"reason="+reason+"onCompletedMsg="+onCompletedMsg);
}
sendMessage(DataConnection.EVENT_DISCONNECT,//7
newDisconnectParams(apnContext,reason,onCompletedMsg));
}[/code]
android/frameworks/opt/telephony/src/java/com/android/internal/telephony/dataconnection/DataConnection.java
这个也挺复杂的维护了一个状态机StateMachine
tearDownData(dp);
/**
*Thestatemachineisconnected,expectinganEVENT_DISCONNECT.
*/
privateclassDcActiveStateextendsState{
...
@Override
publicbooleanprocessMessage(Messagemsg){
...
caseEVENT_DISCONNECT:{
DisconnectParamsdp=(DisconnectParams)msg.obj;
if(DBG){
log("DcActiveState:EVENT_DISCONNECTdp="+dp
+"dc="+DataConnection.this);
}
if(mApnContexts.contains(dp.mApnContext)){
if(DBG){
log("DcActiveStatemsg.what=EVENT_DISCONNECTRefCount="
+mApnContexts.size());
}
if(mApnContexts.size()==1){
mApnContexts.clear();
mDisconnectParams=dp;
mConnectionParams=null;
dp.mTag=mTag;
tearDownData(dp);
transitionTo(mDisconnectingState);
}else{
mApnContexts.remove(dp.mApnContext);
notifyDisconnectCompleted(dp,false);
}
}else{
log("DcActiveStateERRORnosuchapnContext="+dp.mApnContext
+"inthisdc="+DataConnection.this);
notifyDisconnectCompleted(dp,false);
}
retVal=HANDLED;
break;
}[/code]
mPhone.mCi.deactivateDataCall
/**
*TearDownthedataconnectionwhenthedeactivationiscompleteaMessagewith
*msg.what==EVENT_DEACTIVATE_DONEandmsg.obj==AsyncResultwithAsyncResult.obj
*containingtheparametero.
*
*@paramoistheobjectreturnedintheAsyncResult.obj.
*/
privatevoidtearDownData(Objecto){
intdiscReason=RILConstants.DEACTIVATE_REASON_NONE;
if((o!=null)&&(oinstanceofDisconnectParams)){
DisconnectParamsdp=(DisconnectParams)o;
if(TextUtils.equals(dp.mReason,Phone.REASON_RADIO_TURNED_OFF)){
discReason=RILConstants.DEACTIVATE_REASON_RADIO_OFF;
}elseif(TextUtils.equals(dp.mReason,Phone.REASON_PDP_RESET)){
discReason=RILConstants.DEACTIVATE_REASON_PDP_RESET;
}
}
if(mPhone.mCi.getRadioState().isOn()
||(mPhone.getServiceState().getRilDataRadioTechnology()
==ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN)){
if(DBG)log("tearDownDataradioison,calldeactivateDataCall");
mPhone.mCi.deactivateDataCall(mCid,discReason,
obtainMessage(EVENT_DEACTIVATE_DONE,mTag,0,o));
}else{
if(DBG)log("tearDownDataradioisoffsendMessageEVENT_DEACTIVATE_DONEimmediately");
AsyncResultar=newAsyncResult(o,null,null);
sendMessage(obtainMessage(EVENT_DEACTIVATE_DONE,mTag,0,ar));
}
}[/code]
调用到RIL.java中的方法
android/frameworks/opt/telephony/src/java/com/android/internal/telephony/RIL.java
--------------
相关文章推荐
- Android 5.1 open data flow 数据开启流程
- Android平台的音视频多媒体
- Android中Activity启动模式详解
- android Sql Login
- Android VideoView播放视频控制:开始、暂停、快进(3)
- Android模拟多线程下载
- Android编程之LayoutInflater的inflate方法详解及其中参数的作用
- Android 自定义CheckBox RadioButton中的button,且设置与文字的间距
- android dialog的圆角不显示问题
- Android汉字转拼音HanziToPinyin
- activity中fragment不能全屏的问题
- Android ListView性能提升小技巧
- android ndk 笔记
- 学习Android开发相关站点汇总
- Android 关于上文中第三方开源PinnedSectionListView异常崩溃报错问题解决方案
- Android Activity 详述
- Android学习笔记(三):关于像素的一些知识
- Android GreenDao介绍和Generator生成表对象代码
- Android Studio如何发布APK
- Android之drawable state各个属性详解