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


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

<span style="background-color: rgb(255, 255, 255);"> 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);            }        }    }</span>



下面这个方法比较长,有很多条件的检查 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<ApnSetting> 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. 系出名门Android(9) - 数据库支持(SQLite), 内容提供器(ContentP
  2. android中的bundle传送数据
  3. Android隐藏状态栏、导航栏
  4. Android NetworkInfo.DetailedState 获取wifi连接状态详情
  5. Android Room联合AsyncListUtil实现RecyclerView分页加载ORM数据
  6. Android 状态栏通知Notification(转载)
  7. Android——SQLite数据库
  8. Android使用JDBC连接mysql数据库

随机推荐

  1. android image 压缩和解压 unyaffs与mkya
  2. Android(安卓)APK安装过程及原理详解
  3. Android学习——基础组件
  4. Android(安卓)LCD(三):Samsung LCD接口篇
  5. 使用Eclipse开发Android
  6. android init.rc详解
  7. Android(安卓)带有弹出收缩动画的扇形菜
  8. 从Android中Activity之间的通信说开来
  9. android——wifi系统架构
  10. [Android] AsyncTask使用实例---加载网络