惯例流程图先


流程是入口是Settings->Data Usage 的开关,后面会看一下从下拉快速设置的入口进入。
android/packages/apps/Settings/src/com/android/settings/DataUsageSummary.java
关闭数据开关时,会弹出确认窗口 ConfirmDataDisableFragment . show ( DataUsageSummary . this );

                                                    private View.OnClickListener mDataEnabledListener = new View.OnClickListener() {                                        @Override                                        public void onClick(View v) {                                        if (mBinding) return;                                                                               final boolean dataEnabled = !mDataEnabled.isChecked();                                        final String currentTab = 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 {                                        // disabling data; show confirmation dialog which eventually                                        // calls setMobileDataEnabled() once user confirms.                                        ConfirmDataDisableFragment.show(DataUsageSummary.this);                                        }                                        }                                                                               updatePolicy(false);                                        }                                        };                           

点击确认后即开始关闭数据的后续流程 target . setMobileDataEnabled ( false );

                                                     /**                                        * Dialog to request user confirmation before disabling data.                                        */                                        public static class ConfirmDataDisableFragment extends DialogFragment {                                        public static void show(DataUsageSummary parent) {                                        if (!parent.isAdded()) return;                                                                               final ConfirmDataDisableFragment dialog = new ConfirmDataDisableFragment();                                        dialog.setTargetFragment(parent, 0);                                        dialog.show(parent.getFragmentManager(), TAG_CONFIRM_DATA_DISABLE);                                        }                                                                               @Override                                        public Dialog onCreateDialog(Bundle savedInstanceState) {                                        final Context context = getActivity();                                                                               final AlertDialog.Builder builder = new AlertDialog.Builder(context);                                        builder.setMessage(R.string.data_usage_disable_mobile);                                                                               builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {                                        @Override                                        public void onClick(DialogInterface dialog, int which) {                                        final DataUsageSummary target = (DataUsageSummary) getTargetFragment();                                        if (target != null) {                                        // TODO: extend to modify policy enabled flag.                                        target.setMobileDataEnabled(false);                                        }                                        }                                        });                                        builder.setNegativeButton(android.R.string.cancel, null);                                                                               return builder.create();                                        }                                        }                           

获得当前TAB对应的SIM卡subId mTelephonyManager . setDataEnabled ( subId [ 0 ], enabled );
                                                                                            private void setMobileDataEnabled(boolean enabled) {                                        if (LOGD) Log.d(TAG, "setMobileDataEnabled()");                                        // How about exposing sub based API like TelephonyManager.setDataEnabled(int subId);                                        if (mCurrentTab.startsWith(TAB_SIM)) {                                        int phoneId = multiSimGetCurrentSub();                                                                               // as per phone, set the individual flag                                        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);                                        }                           

android/frameworks/base/telephony/java/android/telephony/TelephonyManager.java
getITelephony (). setDataEnabled ( subId , enable );
                                                     /** @hide */                                        @SystemApi                                        public void setDataEnabled(int subId, boolean enable) {                                        try {                                        AppOpsManager appOps = (AppOpsManager)mContext.getSystemService(Context.APP_OPS_SERVICE);                                        if (enable) {                                        if (appOps.noteOp(AppOpsManager.OP_DATA_CONNECT_CHANGE) != AppOpsManager.MODE_ALLOWED) {                                        Log.w(TAG, "Permission denied by user.");                                        return;                                        }                                        }                                        Log.d(TAG, "setDataEnabled: enabled=" + enable);                                        getITelephony().setDataEnabled(subId, enable);                                        } catch (RemoteException e) {                                        Log.e(TAG, "Error calling setDataEnabled", e);                                        }                                        }                           

android/packages/services/Telephony/src/com/android/phone/PhoneInterfaceManager.java
phone . setDataEnabled ( enable );
                                                                                            /**                                        * Set mobile data enabled                                        * Used by the user through settings etc to turn on/off mobile data                                        *                                        * @param enable {@code true} turn turn data on, else {@code false}                                        */                                        @Override                                        public void setDataEnabled(int subId, boolean enable) {                                        enforceModifyPermission();                                        int phoneId = mSubscriptionController.getPhoneId(subId);                                        log("getDataEnabled: subId=" + subId + " phoneId=" + phoneId);                                        Phone phone = PhoneFactory.getPhone(phoneId);                                        if (phone != null) {                                        log("setDataEnabled: subId=" + subId + " enable=" + enable);                                        phone.setDataEnabled(enable);                                        } else {                                        loge("setDataEnabled: no phone for subId=" + subId);                                        }                                        }                           

android/frameworks/opt/telephony/src/java/com/android/internal/telephony/gsm/GSMPhone.java
mDcTracker . setDataEnabled ( enable );
                                                     @Override                                        public void setDataEnabled(boolean enable) {                                        mDcTracker.setDataEnabled(enable);                                        }                           
android/frameworks/opt/telephony/src/java/com/android/internal/telephony/dataconnection/DcTrackerBase.java

                                                     /**                                        * Modify {@link android.provider.Settings.Global#MOBILE_DATA} value.                                        */                                        public void setDataEnabled(boolean enable) {                                        Message msg = obtainMessage(DctConstants.CMD_SET_USER_DATA_ENABLE);                                        msg.arg1 = enable ? 1 : 0;                                        sendMessage(msg);                                        }                           
onSetUserDataEnabled ( enabled );
                                                     @Override                                        public void handleMessage(Message msg) {                                        switch (msg.what) {                                        case AsyncChannel.CMD_CHANNEL_DISCONNECTED: {                                        log("DISCONNECTED_CONNECTED: msg=" + msg);                                        DcAsyncChannel dcac = (DcAsyncChannel) msg.obj;                                        mDataConnectionAcHashMap.remove(dcac.getDataConnectionIdSync());                                        dcac.disconnected();                                        break;                                        }                                        ...                                        case DctConstants.CMD_SET_USER_DATA_ENABLE: {                                        final boolean enabled = (msg.arg1 == DctConstants.ENABLED) ? true : false;                                        if (DBG) log("CMD_SET_USER_DATA_ENABLE enabled=" + enabled);                                        onSetUserDataEnabled(enabled);                                        break;                                        }                                       ...                           
onCleanUpAllConnections
                                                     protected void onSetUserDataEnabled(boolean enabled) {                                        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                                        }                                        }                                        }                                        }                           

android/frameworks/opt/telephony/src/java/com/android/internal/telephony/dataconnection/DcTracker.java 这个类比较复杂,我们只看本次重点。 cleanUpAllConnections ( true , cause );
                                            /**                                  * Cleanup all connections.                                  *                                  * TODO: Cleanup only a specified connection passed as a parameter.                                  * Also, make sure when you clean up a conn, if it is last apply                                  * logic as though it is cleanupAllConnections                                  *                                  * @param cause for the clean up.                                  */                                                                   @Override                                  protected void onCleanUpAllConnections(String cause) {                                  cleanUpAllConnections(true, cause);                                  }                              

下面这里会循环多次。 for ( ApnContext apnContext : mApnContexts . values ())
                                                     /**                                        * If tearDown is true, this only tears down a CONNECTED session. Presently,                                        * there is no mechanism for abandoning an CONNECTING session,                                        * but would likely involve cancelling pending async requests or                                        * setting a flag or new state to ignore them when they came in                                        * @param tearDown true if the underlying DataConnection should be                                        * disconnected.                                        * @param reason reason for the clean up.                                        * @return boolean - true if we did cleanup any connections, false if they                                        * were already all disconnected.                                        */                                        protected boolean cleanUpAllConnections(boolean tearDown, String reason) {                                        if (DBG) log("cleanUpAllConnections: tearDown=" + tearDown + " reason=" + reason);                                        boolean didDisconnect = false;                                        boolean specificdisable = false;                                                                               if (!TextUtils.isEmpty(reason)) {                                        specificdisable = reason.equals(Phone.REASON_DATA_SPECIFIC_DISABLED);                                        }                                                                               for (ApnContext apnContext : 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 - only do cleanup if not disconnected                                        apnContext.setReason(reason);                                        cleanUpConnection(tearDown, apnContext);                                        }                                        }                                                                               stopNetStatPoll();                                        stopDataStallAlarm();                                                                               // TODO: Do we need mRequestedApnType?                                        mRequestedApnType = PhoneConstants.APN_TYPE_DEFAULT;                                                                               log("cleanUpConnection: mDisconnectPendingCount = " + mDisconnectPendingCount);                                        if (tearDown && mDisconnectPendingCount == 0) {                                        notifyDataDisconnectComplete();                                        notifyAllDataDisconnected();                                        }                                                                               return didDisconnect;                                        }                           

每一次进来后 if ( apnContext . isDisconnected ()) 的判断结果是不一样的,apnContext={mApnType=default mState=CONNECTED mApnType为其他时,其mState一般是IDLE的
                                                    protected void cleanUpConnection(boolean tearDown, ApnContext apnContext) {                                                                               if (apnContext == null) {                                        if (DBG) log("cleanUpConnection: apn context is null");                                        return;                                        }                                                                               DcAsyncChannel dcac = apnContext.getDcAc();                                        if (DBG) {                                        log("cleanUpConnection: E tearDown=" + tearDown + " reason=" + apnContext.getReason() +                                        " apnContext=" + apnContext);                                        }                                        if (tearDown) {//3                                        if (apnContext.isDisconnected()) {                                        // The request is tearDown and but ApnContext is not connected.                                        // If apnContext is not enabled anymore, break the linkage to the DCAC/DC.                                        apnContext.setState(DctConstants.State.IDLE);                                        if (!apnContext.isReady()) {                                        if (dcac != null) {                                        dcac.tearDown(apnContext, "", null);                                        }                                        apnContext.setDataConnectionAc(null);                                        }                                        } else {                                        // Connection is still there. Try to clean up.                                        if (dcac != null) {//4                                        if (apnContext.getState() != DctConstants.State.DISCONNECTING) {                                        boolean disconnectAll = false;                                        if (PhoneConstants.APN_TYPE_DUN.equals(apnContext.getApnType())) {                                        // CAF_MSIM is this below condition required.                                        // if (PhoneConstants.APN_TYPE_DUN.equals(PhoneConstants.APN_TYPE_DEFAULT)) {                                        if (teardownForDun()) {                                        if (DBG) log("tearing down dedicated DUN connection");                                        // we need to tear it down - we brought it up just for dun and                                        // other people are camped on it and now dun is done. We need                                        // to stop using it and let the normal apn list get used to find                                        // connections for the remaining desired connections                                        disconnectAll = true;                                        }                                        }                                        if (DBG) {                                        log("cleanUpConnection: tearing down" + (disconnectAll ? " all" :""));                                        }                                        Message msg = 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 {                                        // apn is connected but no reference to dcac.                                        // Should not be happen, but reset the state in case.                                        apnContext.setState(DctConstants.State.IDLE);                                        mPhone.notifyDataConnection(apnContext.getReason(),                                        apnContext.getApnType());                                        }                                        }                                        } else {                                        // force clean up the data connection.                                        if (dcac != null) dcac.reqReset();                                        apnContext.setState(DctConstants.State.IDLE);                                        mPhone.notifyDataConnection(apnContext.getReason(), apnContext.getApnType());                                        apnContext.setDataConnectionAc(null);                                        }                                                                               if (mOmhApt != null) {                                        mOmhApt.clearActiveApnProfile();                                        }                                                                               // Make sure reconnection alarm is cleaned up if there is no ApnContext                                        // associated to the connection.                                        if (dcac != null) {                                        cancelReconnectAlarm(apnContext);                                        }                                                                               setupDataForSinglePdnArbitration(apnContext.getReason());                                                                               if (DBG) {                                        log("cleanUpConnection: X tearDown=" + tearDown + " reason=" + apnContext.getReason() +                                        " apnContext=" + apnContext + " dcac=" + apnContext.getDcAc());                                        }                                        }                           

android/frameworks/opt/telephony/src/java/com/android/internal/telephony/dataconnection/DcAsyncChannel.java sendMessage
                                                    /**                                        * Tear down the connection through the apn on the network.                                        *                                        * @param onCompletedMsg is sent with its msg.obj as an AsyncResult object.                                        * With AsyncResult.userObj set to the original msg.obj.                                        */                                        public void tearDown(ApnContext apnContext, String reason, Message onCompletedMsg) {                                        if (DBG) {                                        log("tearDown: apnContext=" + apnContext                                        + " reason=" + reason + " onCompletedMsg=" + onCompletedMsg);                                        }                                        sendMessage(DataConnection.EVENT_DISCONNECT,//7                                        new DisconnectParams(apnContext, reason, onCompletedMsg));                                        }                           
android/frameworks/opt/telephony/src/java/com/android/internal/telephony/dataconnection/DataConnection.java 这个也挺复杂的 维护了一个状态机StateMachine tearDownData ( dp );
                                                     /**                                        * The state machine is connected, expecting an EVENT_DISCONNECT.                                        */                                        private class DcActiveState extends State {                                        ...                                                                               @Override                                        public boolean processMessage(Message msg) {                                        ...                                         case EVENT_DISCONNECT: {                                        DisconnectParams dp = (DisconnectParams) msg.obj;                                        if (DBG) {                                        log("DcActiveState: EVENT_DISCONNECT dp=" + dp                                        + " dc=" + DataConnection.this);                                        }                                        if (mApnContexts.contains(dp.mApnContext)) {                                        if (DBG) {                                        log("DcActiveState msg.what=EVENT_DISCONNECT RefCount="                                        + 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("DcActiveState ERROR no such apnContext=" + dp.mApnContext                                        + " in this dc=" + DataConnection.this);                                        notifyDisconnectCompleted(dp, false);                                        }                                        retVal = HANDLED;                                        break;                                        }                           

mPhone . mCi . deactivateDataCall
                                                    /**                                        * TearDown the data connection when the deactivation is complete a Message with                                        * msg.what == EVENT_DEACTIVATE_DONE and msg.obj == AsyncResult with AsyncResult.obj                                        * containing the parameter o.                                        *                                        * @param o is the object returned in the AsyncResult.obj.                                        */                                        private void tearDownData(Object o) {                                        int discReason = RILConstants.DEACTIVATE_REASON_NONE;                                        if ((o != null) && (o instanceof DisconnectParams)) {                                        DisconnectParams dp = (DisconnectParams)o;                                                                               if (TextUtils.equals(dp.mReason, Phone.REASON_RADIO_TURNED_OFF)) {                                        discReason = RILConstants.DEACTIVATE_REASON_RADIO_OFF;                                        } else if (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("tearDownData radio is on, call deactivateDataCall");                                        mPhone.mCi.deactivateDataCall(mCid, discReason,                                        obtainMessage(EVENT_DEACTIVATE_DONE, mTag, 0, o));                                        } else {                                        if (DBG) log("tearDownData radio is off sendMessage EVENT_DEACTIVATE_DONE immediately");                                        AsyncResult ar = new AsyncResult(o, null, null);                                        sendMessage(obtainMessage(EVENT_DEACTIVATE_DONE, mTag, 0, ar));                                        }                                        }                           
调用到RIL.java中的方法 android/frameworks/opt/telephony/src/java/com/android/internal/telephony/RIL.java



--------------

更多相关文章

  1. Android(安卓)USB通信弹出权限确认框
  2. Android(安卓)通过代码实现控制数据网络的开关(仅适用于5.0以上)
  3. Evernote Android(安卓)版更新,给您超便捷笔记入口
  4. Android(安卓)8.0 SystemUI下拉状态栏快捷开关
  5. 谈Android下一个apk安装多个程序入口图标
  6. 如何编程实现开启或者关闭GPS
  7. Android自动开关机实现
  8. 最完美的android仿ios开关按钮源码
  9. Android(安卓)之 发送短信

随机推荐

  1. Android数据库编程教程
  2. android Handler导致内存泄露分析
  3. Android中贪吃蛇游戏的学习(三)
  4. Android拖拽详解
  5. Android(安卓)am命令
  6. android ViewPager 竖向滑动
  7. js 中判断手机是iphone,ipad还是Android、
  8. [android]Context 上下文
  9. android TextView ellipsize 只显示一个
  10. 2013.12.23 ——— android assents文件