首先我们来看看下面的关系图:


底层Settings.apk 在Settings -> Data Usage Summary中的某个SIM tab下开启数据开关 android/packages/apps/Settings/src/com/android/settings/DataUsageSummary.java
setMobileDataEnabled(true);

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);        }    };
下面这部根据phoneId获得了当前获得了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);    }


frameworks/base
数据开关都会调用到TelephonyManager.setDataEnabled(),不管是从流量使用情况还是从下拉的“快速设置”(Quick Setting)里打开(这里会在后面补充说明)
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的数据开启 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/rameworks/opt/telephony/src/java/com/android/internal/telephony/dataconnection/DcTrackerBase.java   
发送打开数据开关的消息CMD_SET_USER_DATA_ENABLE Message msg = obtainMessage(DctConstants.CMD_SET_USER_DATA_ENABLE);

 /**     * 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;            }...


onTrySetupData(Phone.REASON_DATA_ENABLED);

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

android/frameworks/opt/telephony/src/java/com/android/internal/telephony/dataconnection/DcTracker.java setupDataOnConnectableApns(reason);
 @Override    // TODO: We shouldnt need this.    protected boolean onTrySetupData(String reason) {        if (DBG) log("onTrySetupData: reason=" + reason);        setupDataOnConnectableApns(reason);        return true;    }



trySetupData(apnContext);

 private void setupDataOnConnectableApns(String reason) {        if (DBG) log("setupDataOnConnectableApns: " + reason);         for (ApnContext apnContext : mPrioritySortedApnContexts) {            if (DBG) log("setupDataOnConnectableApns: apnContext " + apnContext);            if (apnContext.getState() == DctConstants.State.FAILED) {                apnContext.setState(DctConstants.State.IDLE);            }            if (apnContext.isConnectable()) {                log("setupDataOnConnectableApns: isConnectable() call trySetupData");                apnContext.setReason(reason);                trySetupData(apnContext);            }        }    }



下面这个方法比较长,有很多条件的检查 boolean retValue =setupData(apnContext, radioTech);
  private boolean trySetupData(ApnContext apnContext) {        ...                if (apnContext.isConnectable() && (isEmergencyApn ||                 (isDataAllowed(apnContext) &&                getAnyDataEnabled(checkUserDataEnabled) && !isEmergency()))) {            if (apnContext.getState() == DctConstants.State.FAILED) {                if (DBG) log("trySetupData: make a FAILED ApnContext IDLE so its reusable");                apnContext.setState(DctConstants.State.IDLE);            }            int radioTech = mPhone.getServiceState().getRilDataRadioTechnology();            if (apnContext.getState() == DctConstants.State.IDLE) {                 ArrayList waitingApns = buildWaitingApns(apnContext.getApnType(),                        radioTech);                if (waitingApns.isEmpty()) {                    notifyNoData(DcFailCause.MISSING_UNKNOWN_APN, apnContext);                    notifyOffApnsOfAvailability(apnContext.getReason());                    if (DBG) log("trySetupData: X No APN found retValue=false");                    return false;                } else {                    apnContext.setWaitingApns(waitingApns);                    if (DBG) {                        log ("trySetupData: Create from mAllApnSettings : "                                    + apnListToString(mAllApnSettings));                    }                }            }             if (DBG) {                log("trySetupData: call setupData, waitingApns : "                        + apnListToString(apnContext.getWaitingApns()));            }            boolean retValue = setupData(apnContext, radioTech);//7            notifyOffApnsOfAvailability(apnContext.getReason());             if (DBG) log("trySetupData: X retValue=" + retValue);            return retValue;        } else {            if (!apnContext.getApnType().equals(PhoneConstants.APN_TYPE_DEFAULT)                    && apnContext.isConnectable()) {                mPhone.notifyDataConnectionFailed(apnContext.getReason(), apnContext.getApnType());            }            notifyOffApnsOfAvailability(apnContext.getReason());            if (DBG) log ("trySetupData: X apnContext not 'ready' retValue=false");            return false;        }    }


dcac.bringUp(apnContext, getInitialMaxRetry(), profileId, radioTech, mAutoAttachOnCreation,msg);


 private boolean setupData(ApnContext apnContext, int radioTech) {        if (DBG) log("setupData: apnContext=" + apnContext);        ApnSetting apnSetting;        DcAsyncChannel dcac = null;         apnSetting = apnContext.getNextWaitingApn();        if (apnSetting == null) {            if (DBG) log("setupData: return for no apn found!");            return false;        }         int profileId = apnSetting.profileId;        if (profileId == 0) {            profileId = getApnProfileID(apnContext.getApnType());        }         // On CDMA, if we're explicitly asking for DUN, we need have        // a dun-profiled connection so we can't share an existing one        // On GSM/LTE we can share existing apn connections provided they support        // this type.        if (apnContext.getApnType() != PhoneConstants.APN_TYPE_DUN ||                teardownForDun() == false) {            dcac = checkForCompatibleConnectedApnContext(apnContext);            if (dcac != null) {                // Get the dcacApnSetting for the connection we want to share.                ApnSetting dcacApnSetting = dcac.getApnSettingSync();                if (dcacApnSetting != null) {                    // Setting is good, so use it.                    apnSetting = dcacApnSetting;                }            }        }        if (dcac == null) {            if (isOnlySingleDcAllowed(radioTech)) {                if (isHigherPriorityApnContextActive(apnContext)) {                    if (DBG) {                        log("setupData: Higher priority ApnContext active.  Ignoring call");                    }                    return false;                }                 // Only lower priority calls left.  Disconnect them all in this single PDP case                // so that we can bring up the requested higher priority call (once we receive                // repsonse for deactivate request for the calls we are about to disconnect                if (cleanUpAllConnections(true, Phone.REASON_SINGLE_PDN_ARBITRATION)) {                    // If any call actually requested to be disconnected, means we can't                    // bring up this connection yet as we need to wait for those data calls                    // to be disconnected.                    if (DBG) log("setupData: Some calls are disconnecting first.  Wait and retry");                    return false;                }                 // No other calls are active, so proceed                if (DBG) log("setupData: Single pdp. Continue setting up data call.");            }             dcac = findFreeDataConnection();             if (dcac == null) {                dcac = createDataConnection();            }             if (dcac == null) {                if (DBG) log("setupData: No free DataConnection and couldn't create one, WEIRD");                return false;            }        }        if (DBG) log("setupData: dcac=" + dcac + " apnSetting=" + apnSetting);         apnContext.setDataConnectionAc(dcac);        apnContext.setApnSetting(apnSetting);        apnContext.setState(DctConstants.State.CONNECTING);        mPhone.notifyDataConnection(apnContext.getReason(), apnContext.getApnType());         Message msg = obtainMessage();        msg.what = DctConstants.EVENT_DATA_SETUP_COMPLETE;        msg.obj = apnContext;        dcac.bringUp(apnContext, getInitialMaxRetry(), profileId, radioTech, mAutoAttachOnCreation,                msg);//8         if (DBG) log("setupData: initing!");        return true;    }


android/frameworks/opt/telephony/src/java/com/android/internal/telephony/dataconnection/DcAsyncChannel.java
sendMessage

 /**     * Bring up a connection to the apn and return an AsyncResult in onCompletedMsg.     * Used for cellular networks that use Acesss Point Names (APN) such     * as GSM networks.     *     * @param apnContext is the Access Point Name to bring up a connection to     * @param initialMaxRetry the number of retires for initial bringup.     * @param profileId for the conneciton     * @param onCompletedMsg is sent with its msg.obj as an AsyncResult object.     *        With AsyncResult.userObj set to the original msg.obj,     *        AsyncResult.result = FailCause and AsyncResult.exception = Exception().     */    public void bringUp(ApnContext apnContext, int initialMaxRetry, int profileId,            int rilRadioTechnology, boolean retryWhenSSChange, Message onCompletedMsg) {        if (DBG) {            log("bringUp: apnContext=" + apnContext + " initialMaxRetry=" + initialMaxRetry                + " onCompletedMsg=" + onCompletedMsg);        }        sendMessage(DataConnection.EVENT_CONNECT,//9                    new ConnectionParams(apnContext, initialMaxRetry, profileId,                            rilRadioTechnology, retryWhenSSChange, onCompletedMsg));    }


android/frameworks/opt/telephony/src/java/com/android/internal/telephony/dataconnection/DataConnection.java 这其实是个状态即机 StateMachine,这个类或者或机制,本身也比较复杂,以后看明白了以后会单独在写一篇文章 现在是进入其中一个状态DcInactiveState。 DcInactiveState processmesssage
onConnect(mConnectionParams);
   /**     * The state machine is inactive and expects a EVENT_CONNECT.     */    private class DcInactiveState extends State {       ...         @Override        public boolean processMessage(Message msg) {       ...                                        case EVENT_CONNECT:                    if (DBG) log("DcInactiveState: mag.what=EVENT_CONNECT");                    ConnectionParams cp = (ConnectionParams) msg.obj;                    if (initConnection(cp)) {                        onConnect(mConnectionParams);//10                        transitionTo(mActivatingState);                    } else {                        if (DBG) {                            log("DcInactiveState: msg.what=EVENT_CONNECT initConnection failed");                        }                        notifyConnectCompleted(cp, DcFailCause.UNACCEPTABLE_NETWORK_PARAMETER,                                false);                    }                    retVal = HANDLED;                    break;

mPhone.mCi.setupDataCall


    /**     * Begin setting up a data connection, calls setupDataCall     * and the ConnectionParams will be returned with the     * EVENT_SETUP_DATA_CONNECTION_DONE AsyncResul.userObj.     *     * @param cp is the connection parameters     */    private void onConnect(ConnectionParams cp) {        if (DBG) log("onConnect: carrier='" + mApnSetting.carrier                + "' APN='" + mApnSetting.apn                + "' proxy='" + mApnSetting.proxy + "' port='" + mApnSetting.port + "'");         // Check if we should fake an error.        if (mDcTesterFailBringUpAll.getDcFailBringUp().mCounter  > 0) {           ...        }         mCreateTime = -1;        mLastFailTime = -1;        mLastFailCause = DcFailCause.NONE;         // The data profile's profile ID must be set when it is created.        int dataProfileId;        if (mApnSetting.getApnProfileType() == ApnProfileType.PROFILE_TYPE_OMH) {            dataProfileId = mApnSetting.getProfileId() + RILConstants.DATA_PROFILE_OEM_BASE;            log("OMH profile, dataProfile id = " + dataProfileId);        } else {            dataProfileId = cp.mProfileId;        }         // msg.obj will be returned in AsyncResult.userObj;        Message msg = obtainMessage(EVENT_SETUP_DATA_CONNECTION_DONE, cp);        msg.obj = cp;         int authType = mApnSetting.authType;        if (authType == -1) {            authType = TextUtils.isEmpty(mApnSetting.user) ? RILConstants.SETUP_DATA_AUTH_NONE                    : RILConstants.SETUP_DATA_AUTH_PAP_CHAP;        }         String protocol;        if (mPhone.getServiceState().getRoaming()) {            protocol = mApnSetting.roamingProtocol;        } else {            protocol = mApnSetting.protocol;        }         mPhone.mCi.setupDataCall(//11                Integer.toString(cp.mRilRat + 2),                Integer.toString(dataProfileId),                mApnSetting.apn, mApnSetting.user, mApnSetting.password,                Integer.toString(authType),                protocol, msg);    }

android/frameworks/opt/telephony/src/java/com/android/internal/telephony/RIL.java 这个类是通讯中的使用类。


更多相关文章

  1. ContentProvider数据共享
  2. android root后数据安全
  3. 有关XML的点击状态背景图的设置
  4. Android基础笔记(四)-数据存储和界面展现
  5. Android中数据存储的5种方法
  6. Android数据加密之Des加密
  7. Android 数据库之 SQLiteConnectionPool 源码分析
  8. android button 正常状态,按下状态
  9. android 去掉顶部状态栏

随机推荐

  1. Java面试题全集(12)
  2. 面试官:什么是CSRF?(你的钱为什么被转走,这篇
  3. 2020年5A PMP 经验分享
  4. 静态链表
  5. 栈和队列就是这么简单
  6. 解读容器的 2020:寻找云原生的下一站
  7. JVM中一个小知识点:深堆和浅堆的认识
  8. Linux网络基础概念
  9. 十道简单算法题
  10. HashMap的负载因子初始值为什么是0.75?这