博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android 5.1 open data flow 数据开启流程
阅读量:5036 次
发布时间:2019-06-12

本文共 17967 字,大约阅读时间需要 59 分钟。

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

底层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
这个类是通讯中的使用类。

转载于:https://www.cnblogs.com/new0801/p/6175787.html

你可能感兴趣的文章
Python模块之pickle(列表,字典等复杂数据类型与二进制文件的转化)
查看>>
通过数据库表反向生成pojo类
查看>>
css_去掉默认样式
查看>>
TensorFlow2.0矩阵与向量的加减乘
查看>>
NOIP 2010题解
查看>>
javascript中的each遍历
查看>>
String中各方法多数情况下返回新的String对象
查看>>
浅谈tcp粘包问题
查看>>
UVA11524构造系数数组+高斯消元解异或方程组
查看>>
排序系列之——冒泡排序、插入排序、选择排序
查看>>
爬虫基础
查看>>
jquery.lazyload延迟加载图片第一屏问题
查看>>
HDU 1011 Starship Troopers (树形DP)
查看>>
手把手教你写DI_1_DI框架有什么?
查看>>
.net常见的一些面试题
查看>>
OGRE 源码编译方法
查看>>
上周热点回顾(10.20-10.26)
查看>>
C#正则表达式引发的CPU跑高问题以及解决方法
查看>>
云计算之路-阿里云上:“黑色30秒”走了,“黑色1秒”来了,真相也许大白了...
查看>>
APScheduler调度器
查看>>