一、DcTracker介绍
DcTracker是Telephony框架中负责数据业务的核心(类似于GsmCallTracker是通话业务核心,GsmServiceStateTracker是网络CS业务的核心),所有对数据网络的请求(打开关闭数据开关、切换数据卡、修改APN参数等)都会发送到该处理中心来处理。本节所涉及的大部分代码也都在该对象中。下面我们先来看该对象的初始化流程。
DcTracker是在Phone对象创建过程中被创建的,确切来说,如果当前使用的是GSMPhone,那么在GSMPhone创建过程中就会创建DcTracker对象:- @GSMPhone.java
- public GSMPhone (Context context, CommandsInterface ci, PhoneNotifier notifier, boolean unitTestMode) {
- //创建DcTracker对象,传递的参数就是当前的GSMPhone对象
- mDcTracker = new DcTracker(this);
- }
- public final class DcTracker extends DcTrackerBase {}
- public abstract class DcTrackerBase extends Handler {}
然后来看DcTracker的初始化过程:
- @DcTracker.java
- public DcTracker(PhoneBase p) {
- super(p);
- mDataConnectionTracker = this;
- //注册监听器
- update();
- //监听APN状态
- mApnObserver = new ApnChangeObserver();
- p.getContext().getContentResolver().registerContentObserver(Telephony.Carriers.CONTENT_URI, true, mApnObserver);
- //从networkAttributes数组中初始化APN参数
- initApnContexts();
- for (ApnContext apnContext : mApnContexts.values()) {
- IntentFilter filter = new IntentFilter();
- filter.addAction(INTENT_RECONNECT_ALARM + '.' + apnContext.getApnType());
- filter.addAction(INTENT_RESTART_TRYSETUP_ALARM + '.' + apnContext.getApnType());
- mPhone.getContext().registerReceiver(mIntentReceiver, filter, null, mPhone);
- }
- ConnectivityManager cm = (ConnectivityManager)p.getContext().getSystemService(Context.CONNECTIVITY_SERVICE);
- //添加各种网络请求过滤器,用于根据这些过滤器发起不同的数据连接
- mNetworkFilter = new NetworkCapabilities();
- mNetworkFilter.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
- mNetworkFilter.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
- mNetworkFilter.addCapability(NetworkCapabilities.NET_CAPABILITY_SUPL);
- mNetworkFilter.addCapability(NetworkCapabilities.NET_CAPABILITY_DUN);
- mNetworkFilter.addCapability(NetworkCapabilities.NET_CAPABILITY_FOTA);
- mNetworkFilter.addCapability(NetworkCapabilities.NET_CAPABILITY_IMS);
- mNetworkFilter.addCapability(NetworkCapabilities.NET_CAPABILITY_CBS);
- mNetworkFilter.addCapability(NetworkCapabilities.NET_CAPABILITY_IA);
- mNetworkFilter.addCapability(NetworkCapabilities.NET_CAPABILITY_RCS);
- mNetworkFilter.addCapability(NetworkCapabilities.NET_CAPABILITY_XCAP);
- mNetworkFilter.addCapability(NetworkCapabilities.NET_CAPABILITY_EIMS);
- mNetworkFilter.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
- mNetworkFilter.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
- //初始化数据网络的NetworkFactory,并设置数据网络的分值为50
- mNetworkFactory = new TelephonyNetworkFactory(this.getLooper(), p.getContext(), "TelephonyNetworkFactory", mNetworkFilter);
- mNetworkFactory.setScoreFilter(50);
- mNetworkFactoryMessenger = new Messenger(mNetworkFactory);
- cm.registerNetworkFactory(mNetworkFactoryMessenger, "Telephony");
- //初始化紧急APN
- initEmergencyApnSetting();
- addEmergencyApnSetting();
- mProvisionActionName = "com.android.internal.telephony.PROVISION" + p.getPhoneId();
- }
1、初始化各种监听器;
2、初始化TelephonyNetworkFactory对象;
3、初始化一些基本的APN参数;
下面我们分别详细介绍这三个过程。
二、DcTracker中监听器的初始化
- public void update() {
- if (isActiveDataSubscription()) {
- //注册各种监听器
- registerForAllEvents();
- //注册SIM卡状态监听器
- onUpdateIcc();
- //mUserDataEnabled就是用户是否打开网络开关的标志位,当为0时,表示当前数据流量被关闭
- mUserDataEnabled = Settings.Global.getInt(mPhone.getContext().getContentResolver(), Settings.Global.MOBILE_DATA, 1) == 1;
- if (mPhone instanceof CDMALTEPhone) {
- ((CDMALTEPhone)mPhone).updateCurrentCarrierInProvider();
- supplyMessenger();
- } else if (mPhone instanceof GSMPhone) {
- ((GSMPhone)mPhone).updateCurrentCarrierInProvider();
- supplyMessenger();
- } else {
- log("Phone object is not MultiSim. This should not hit!!!!");
- }
- } else {
- unregisterForAllEvents();
- log("update(): NOT the active DDS, unregister for all events!");
- }
- }
- protected boolean isActiveDataSubscription() {
- // FIXME This should have code like
- // return (mPhone.getSubId() == SubscriptionManager.getDefaultDataSubId());
- return true;
- }
对于双卡的手机,由于任意时刻只能有一个SIM卡在上网,因此就需要根据用户选择的上网卡来配置不同的APN参数,该方法的原始意图应该是在内部判断当前的DcTracker是否就是用户设置的上网SIM(用户当前使用哪张卡上网可以通过SubscriptionManager.getDefaultDataSubId()方法查询到SIM的SubID),如果是当前卡的话返回true,否则返回false。但是由于Google并未完善其双卡逻辑,因此这里直接返回了true。
接下来继续来看判断后的registerForAllEvents()的过程:
- protected void registerForAllEvents() {
- //监听射频是否打开,没有处理动作
- mPhone.mCi.registerForAvailable(this, DctConstants.EVENT_RADIO_AVAILABLE, null);
- //监听射频是否可用,没有处理动作
- mPhone.mCi.registerForOffOrNotAvailable(this, DctConstants.EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
- //监听当前连接状态,没有处理动作
- mPhone.mCi.registerForDataNetworkStateChanged(this, DctConstants.EVENT_DATA_STATE_CHANGED, null);
- //监听当前通话状态,没有处理动作
- mPhone.getCallTracker().registerForVoiceCallEnded (this, DctConstants.EVENT_VOICE_CALL_ENDED, null);
- //监听当前通话状态,没有处理动作
- mPhone.getCallTracker().registerForVoiceCallStarted (this, DctConstants.EVENT_VOICE_CALL_STARTED, null);
- //监听是否PS域Attach状态
- mPhone.getServiceStateTracker().registerForDataConnectionAttached(this, DctConstants.EVENT_DATA_CONNECTION_ATTACHED, null);
- //监听是否PS域Detach状态
- mPhone.getServiceStateTracker().registerForDataConnectionDetached(this, DctConstants.EVENT_DATA_CONNECTION_DETACHED, null);
- //监听漫游状态,没有处理动作
- mPhone.getServiceStateTracker().registerForRoamingOn(this, DctConstants.EVENT_ROAMING_ON, null);
- //监听漫游状态,没有处理动作
- mPhone.getServiceStateTracker().registerForRoamingOff(this, DctConstants.EVENT_ROAMING_OFF, null);
- mPhone.getServiceStateTracker().registerForPsRestrictedEnabled(this, DctConstants.EVENT_PS_RESTRICT_ENABLED, null);
- mPhone.getServiceStateTracker().registerForPsRestrictedDisabled(this, DctConstants.EVENT_PS_RESTRICT_DISABLED, null);
- //监听接入技术状态
- mPhone.getServiceStateTracker().registerForDataRegStateOrRatChanged(this, DctConstants.EVENT_DATA_RAT_CHANGED, null);
- }
EVENT_DATA_CONNECTION_ATTACHED
----监听PS的Attach事件,触发时将进入onDataConnectionAttached()
EVENT_DATA_RAT_CHANGED
----监听当前所注册的网络技术(LTE/UMTS/GSM)是否发生改变,触发时将进入setupDataOnConnectableApns()
然后在update()中还对SIM卡状态进行监听:
- protected void onUpdateIcc() {
- if (mUiccController == null ) {
- return;
- }
- IccRecords newIccRecords = getUiccRecords(UiccController.APP_FAM_3GPP);
- IccRecords r = mIccRecords.get();
- if (r != newIccRecords) {
- if (r != null) {
- r.unregisterForRecordsLoaded(this);
- mIccRecords.set(null);
- }
- if (newIccRecords != null) {
- mIccRecords.set(newIccRecords);
- //监听SIM各项数据是否载入完毕
- newIccRecords.registerForRecordsLoaded( this, DctConstants.EVENT_RECORDS_LOADED, null);
- }
- }
- }
除了以上的update()和onUpdateIcc()外,在DcTracker的构造方法里面还注册了对APN参数的监听器:
- public DcTracker(PhoneBase p) {
- update();
- mApnObserver = new ApnChangeObserver();
- p.getContext().getContentResolver().registerContentObserver( Telephony.Carriers.CONTENT_URI, true, mApnObserver);
- }
- private class ApnChangeObserver extends ContentObserver {
- public ApnChangeObserver () {
- super(mDataConnectionTracker);
- }
- @Override
- public void onChange(boolean selfChange) {
- sendMessage(obtainMessage(DctConstants.EVENT_APN_CHANGED));
- }
- }
至此,DcTracker中所有监听器准备就绪,其中比较重要的监听器被触发时所产生的影响我们会在稍后过程中介绍。
三、DcTracker中NetworkFactory的创建过程
- public DcTracker(PhoneBase p) {
- ConnectivityManager cm = (ConnectivityManager)p.getContext().getSystemService(Context.CONNECTIVITY_SERVICE);
- //初始化数据网络的NetworkFactory,并设置数据网络的分值为50
- mNetworkFactory = new TelephonyNetworkFactory(this.getLooper(), p.getContext(), "TelephonyNetworkFactory", mNetworkFilter);
- mNetworkFactory.setScoreFilter(50);
- mNetworkFactoryMessenger = new Messenger(mNetworkFactory);
- cm.registerNetworkFactory(mNetworkFactoryMessenger, "Telephony");
- }
- private class TelephonyNetworkFactory extends NetworkFactory {
- public TelephonyNetworkFactory(Looper l, Context c, String TAG, NetworkCapabilities nc) {
- super(l, c, TAG, nc);
- }
- @Override
- protected void needNetworkFor(NetworkRequest networkRequest, int score) {
- ApnContext apnContext = apnContextForNetworkRequest(networkRequest);
- if (apnContext != null) apnContext.incRefCount();
- }
- @Override
- protected void releaseNetworkFor(NetworkRequest networkRequest) {
- ApnContext apnContext = apnContextForNetworkRequest(networkRequest);
- if (apnContext != null) apnContext.decRefCount();
- }
- }
更多的NetworkFactory使用与原理请点击《连接管理中的评分机制》。
四、DcTracker中初始APN的创建过程
- public DcTracker(PhoneBase p) {
- //从networkAttributes数组中初始化APN参数
- initApnContexts();
- //初始化紧急APN
- initEmergencyApnSetting();
- addEmergencyApnSetting();
- }
4.1、初始化networkAttributes数组中的APN参数
- protected void initApnContexts() {
- //载入networkAttributes数组
- String[] networkConfigStrings = mPhone.getContext().getResources().getStringArray( com.android.internal.R.array.networkAttributes);
- for (String networkConfigString : networkConfigStrings) {
- NetworkConfig networkConfig = new NetworkConfig(networkConfigString);
- ApnContext apnContext = null;
- //根据不同类型创建不同APN参数
- switch (networkConfig.type) {
- case ConnectivityManager.TYPE_MOBILE:
- apnContext = addApnContext(PhoneConstants.APN_TYPE_DEFAULT, networkConfig);
- break;
- case ConnectivityManager.TYPE_MOBILE_MMS:
- apnContext = addApnContext(PhoneConstants.APN_TYPE_MMS, networkConfig);
- break;
- case ConnectivityManager.TYPE_MOBILE_EMERGENCY:
- apnContext = addApnContext(PhoneConstants.APN_TYPE_EMERGENCY, networkConfig);
- break;
- default:
- log("initApnContexts: skipping unknown type=" + networkConfig.type);
- continue;
- }
- }
- }
这个过程比较简单,就是从networkAttributes数组中获取所有APN字串,然后根据类型分别创建APN参数。
4.2、初始化紧急APN参数
1、通过initEmergencyApnSetting()载入紧急APN;
2、通过addEmergencyApnSetting()将紧急APN添加到APN列表中;
先来看载入过程:
- private void initEmergencyApnSetting() {
- String selection = "type=\"emergency\"";
- Cursor cursor = mPhone.getContext().getContentResolver().query( Telephony.Carriers.CONTENT_URI, null, selection, null, null);
- if (cursor != null) {
- if (cursor.getCount() > 0) {
- if (cursor.moveToFirst()) {
- mEmergencyApn = makeApnSetting(cursor);
- }
- }
- cursor.close();
- }
- }
这些参数是在TelephonyProvider被创建的时候被初始化,下面简单看一下初始化流程:
- @TelephonyProvider.java
- private void initDatabase(SQLiteDatabase db) {
- Resources r = mContext.getResources();
- //从apns文件读取APN参数
- XmlResourceParser parser = r.getXml(com.android.internal.R.xml.apns);
- int publicversion = -1;
- try {
- XmlUtils.beginDocument(parser, "apns");
- //解析该文件
- publicversion = Integer.parseInt(parser.getAttributeValue(null, "version"));
- loadApns(db, parser);
- } catch (Exception e) {
- } finally {
- parser.close();
- }
- XmlPullParser confparser = null;
- //从"etc/apns-conf.xml"配置文件读取APN参数
- File confFile = new File(Environment.getRootDirectory(), PARTNER_APNS_PATH);
- FileReader confreader = null;
- try {
- confreader = new FileReader(confFile);
- confparser = Xml.newPullParser();
- confparser.setInput(confreader);
- XmlUtils.beginDocument(confparser, "apns");
- int confversion = Integer.parseInt(confparser.getAttributeValue(null, "version"));
- if (publicversion != confversion) {
- throw new IllegalStateException("Internal APNS file version doesn't match " + confFile.getAbsolutePath());
- }
- //将配置文件解析后存入数据库
- loadApns(db, confparser);
- } catch (FileNotFoundException e) {
- } catch (Exception e) {
- } finally {
- try { if (confreader != null) confreader.close(); } catch (IOException e) { }
- }
- }
- @apns-conf.xml
- <?xml version="1.0" encoding="utf-8"?>
- <apns version="8">
- <apn carrier="T-Mobile US"
- mcc="310"
- mnc="260"
- apn="epc.tmobile.com"
- user="none"
- server="*"
- password="none"
- mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc"
- />
- <apn carrier="T-Mobile US 250"
- mcc="310"
- mnc="250"
- apn="epc.tmobile.com"
- user="none"
- server="*"
- password="none"
- mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc"
- />
- </apns>
上面是数据库初始化的过程,回到DcTracker的紧急APN初始化过程中来,当从数据库中搜索到"type="emergency""的紧急APN参数后,通过initEmergencyApnSetting()方法将这些参数放入mEmergencyApn中,接下来还需要通过addEmergencyApnSetting()方法把这些紧急APN存入统一的APN库中:
- private void addEmergencyApnSetting() {
- if(mEmergencyApn != null) {
- if(mAllApnSettings == null) {
- mAllApnSettings = new ArrayList<ApnSetting>();
- } else {
- boolean hasEmergencyApn = false;
- for (ApnSetting apn : mAllApnSettings) {
- if (ArrayUtils.contains(apn.types, PhoneConstants.APN_TYPE_EMERGENCY)) {
- //如果之前的SIM APN中已经包含了紧急APN,就无需再次添加
- hasEmergencyApn = true;
- break;
- }
- }
- if(hasEmergencyApn == false) {
- //将mEmergencyApn添加到APN列表中
- mAllApnSettings.add(mEmergencyApn);
- } else {
- log("addEmergencyApnSetting - E-APN setting is already present");
- }
- }
- }
- }
至此,DcTracker所有初始化工作全部完成,在这个过程中注册了监听器、创建了TelephonyNetworkFactory、初始化了紧急APN,接下来就是等待监听器被触发。