您的位置:首页 > 移动开发 > Android开发

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);

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

--------------
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: