惯例流程图先 dataconnection disconnect.jpg


流程是入口是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 图文数据JSON解析,金山词霸每日一句API的调用
  2. Android数据库SQLite使用详解一 : SQLiteOpenHelper详解
  3. android sqlite数据库封装 实现crud
  4. Android 与 JS 交互数据上限问题【Refusing to load URL as it e
  5. 在 Android 应用中使用数据库
  6. android 数据传输之JSON
  7. Android P 以及之后版本不支持同时从多个进程使用具有相同数据目

随机推荐

  1. Gallery 画廊
  2. Android学习资源网站
  3. android 学习之---Android之SurfaceView
  4. Android获取机器显示屏幕的分辨率
  5. Android(安卓)helloword demo程序不能运
  6. android 自定义ListView中的单项选择
  7. android 去除ScrollVIew拉到尽头时再拉的
  8. MTK Android(安卓)Driver :sound
  9. 新添的Activity 要在 manifest 中注册 否
  10. android 设置 源码 修改默认主题为白底黑