一、DcTracker介绍
DcTracker是Telephony框架中负责数据业务的核心.
所有对数据网络的请求(打开关闭数据开关、切换数据卡、修改APN参数等)都会发送到该处理中心来处理。
DcTracker是在Phone对象创建过程中被创建的,确切来说,如果当前使用的是GsmCdmaPhone,那么在GsmCdmaPhone创建过程中就会创建DcTracker对象:
GsmCdmaPhone.java
public GsmCdmaPhone(Context context, CommandsInterface ci, PhoneNotifier notifier,
boolean unitTestMode, int phoneId, int precisePhoneType,
TelephonyComponentFactory telephonyComponentFactory) {
mSST = mTelephonyComponentFactory.makeServiceStateTracker(this, this.mCi);
// DcTracker uses SST so needs to be created after it is instantiated
mDcTracker = mTelephonyComponentFactory.makeDcTracker(this);
}
TelephonyComponentFactory.java
public DcTracker makeDcTracker(Phone phone) {
Rlog.d(LOG_TAG, "makeDcTracker");
return new DcTracker(phone);
}
DcTracker本质是什么:
public class DcTracker extends Handler
DcTracker的初始化过程:
public DcTracker(Phone phone) {
super();
//初始化几个全局的成员变量
mPhone = phone;
if (DBG) log("DCT.constructor");
mResolver = mPhone.getContext().getContentResolver();
mUiccController = UiccController.getInstance();
mUiccController.registerForIccChanged(this, DctConstants.EVENT_ICC_CHANGED, null);
mAlarmManager =
(AlarmManager) mPhone.getContext().getSystemService(Context.ALARM_SERVICE);
mCm = (ConnectivityManager) mPhone.getContext().getSystemService(
Context.CONNECTIVITY_SERVICE);
//注册一个广播监听器,监听屏幕开关,WIFI变化的广播
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
filter.addAction(INTENT_DATA_STALL_ALARM);
filter.addAction(INTENT_PROVISIONING_APN_ALARM);
filter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
mPhone.getContext().registerReceiver(mIntentReceiver, filter, null, mPhone);
//向SubscriptionManager添加监听器,猜测是用于双卡切换处理的
mSubscriptionManager = SubscriptionManager.from(mPhone.getContext());
mSubscriptionManager.addOnSubscriptionsChangedListener(mOnSubscriptionsChangedListener);
//创建并启动一个HandlerThread,暂时不清楚具体作用
HandlerThread dcHandlerThread = new HandlerThread("DcHandlerThread");
dcHandlerThread.start();
Handler dcHandler = new Handler(dcHandlerThread.getLooper());
mDcc = DcController.makeDcc(mPhone, this, dcHandler);
mDcTesterFailBringUpAll = new DcTesterFailBringUpAll(mPhone, dcHandler);
//赋值DcTracker自身给mDataConnectionTracker
mDataConnectionTracker = this;
//方法内部通过当前Phone对象分别向RIL ,CallTracker以及ServiceStateTracker注册监听器
registerForAllEvents();
//方法内部已通过mPhone.getIccRecords()获取IccRecords实例后做相关处理
update();
//监听APN数据库的状态,比如在Settings下新增APN
mApnObserver = new ApnChangeObserver();
phone.getContext().getContentResolver().registerContentObserver(
Telephony.Carriers.CONTENT_URI, true, mApnObserver);
//初始化ApnContexts
initApnContexts();
//对每个ApnContext注册广播监听器,应该是跟retry data相关,具体流程暂时不清楚
for (ApnContext apnContext : mApnContexts.values()) {
// Register the reconnect and restart actions.
filter = new IntentFilter();
filter.addAction(INTENT_RECONNECT_ALARM + '.' + apnContext.getApnType());
mPhone.getContext().registerReceiver(mIntentReceiver, filter, null, mPhone);
}
// Add Emergency APN to APN setting list by default to support EPDN in sim absent cases
initEmergencyApnSetting();
addEmergencyApnSetting();
mProvisionActionName = "com.android.internal.telephony.PROVISION" + phone.getPhoneId();
//通过SettingsObserver监听Setting下面漫游的情况,在前面的ServiceStateTracker有相似的监听,目前不清楚这两者的区别
mSettingsObserver = new SettingsObserver(mPhone.getContext(), this);
registerSettingsObserver();
}
在上面这个初始化过程中,主要完成了三个任务:
1、初始化一些成员变量;
2、注册监听,包括广播监听器,Listener,Observer;
3、初始化一些基本的APN参数;
二、DcTracker中监听器的初始化
1,registerForAllEvents():
Listener主要是通过当前Phone对象分别向RIL ,CallTracker以及ServiceStateTracker注册监听器
private void registerForAllEvents() {
//向RIL注册监听器
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.mCi.registerForPcoData(this, DctConstants.EVENT_PCO_DATA_RECEIVED, null);
//向CallTracker注册监听器
mPhone.getCallTracker().registerForVoiceCallEnded(this,
DctConstants.EVENT_VOICE_CALL_ENDED, null);
mPhone.getCallTracker().registerForVoiceCallStarted(this,
DctConstants.EVENT_VOICE_CALL_STARTED, null);
//向ServiceStateTracker注册监听器
registerServiceStateTrackerEvents()
}
public void registerServiceStateTrackerEvents() {
mPhone.getServiceStateTracker().registerForDataConnectionAttached(this,
DctConstants.EVENT_DATA_CONNECTION_ATTACHED, null);
mPhone.getServiceStateTracker().registerForDataConnectionDetached(this,
DctConstants.EVENT_DATA_CONNECTION_DETACHED, null);
mPhone.getServiceStateTracker().registerForDataRoamingOn(this,
DctConstants.EVENT_ROAMING_ON, null);
mPhone.getServiceStateTracker().registerForDataRoamingOff(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);
}
这些监听器包括:
RIL:
DctConstants.EVENT_RADIO_AVAILABLE
DctConstants.EVENT_RADIO_OFF_OR_NOT_AVAILABLE
DctConstants.EVENT_DATA_STATE_CHANGED
DctConstants.EVENT_PCO_DATA_RECEIVED
CallTracker:
DctConstants.EVENT_VOICE_CALL_ENDED
DctConstants.EVENT_VOICE_CALL_STARTED
ServiceStateTracker:
DctConstants.EVENT_DATA_CONNECTION_ATTACHED
DctConstants.EVENT_DATA_CONNECTION_DETACHED
DctConstants.EVENT_ROAMING_ON
DctConstants.EVENT_ROAMING_OFF
DctConstants.EVENT_PS_RESTRICT_ENABLED
DctConstants.EVENT_PS_RESTRICT_DISABLED
DctConstants.EVENT_DATA_RAT_CHANGED
与dataCall流程关系紧密,会回调 handleMessage ()来处理.
2,update()
public void update() {
log("update sub = " + mPhone.getSubId());
log("update(): Active DDS, register for all events now!");
//更新ICC,y与UICC框架相关,暂时说不清楚
onUpdateIcc();
mDataEnabledSettings.setUserDataEnabled(getDataEnabled());
mAutoAttachOnCreation.set(false);
//使用当前Sim卡更新数据库的operatorNumeric
((GsmCdmaPhone)mPhone).updateCurrentCarrierInProvider();
}
private void onUpdateIcc() {
if (mUiccController == null ) {
return;
}
IccRecords newIccRecords = mPhone.getIccRecords();
IccRecords r = mIccRecords.get();
if (r != newIccRecords) {
if (r != null) {
log("Removing stale icc objects.");
r.unregisterForRecordsLoaded(this);
mIccRecords.set(null);
}
if (newIccRecords != null) {
/* [PSN]Telephony FEATURE_PSN_TEL_00069 add Start */
// if (mSubscriptionManager.isActiveSubId(mPhone.getSubId())) {
log("onUpdateIcc: isValidDefaultFallbackSubId= " + SubscriptionController.getInstance().isValidDefaultFallbackSubId());
if (SubscriptionController.getInstance().isValidDefaultFallbackSubId()) {
/* [PSN]Telephony FEATURE_PSN_TEL_00069 add End */
log("New records found.");
mIccRecords.set(newIccRecords);
////监听SIM各项数据是否载入完毕
newIccRecords.registerForRecordsLoaded(
this, DctConstants.EVENT_RECORDS_LOADED, null);
// reset carrier actions on sim loaded
final ServiceStateTracker sst = mPhone.getServiceStateTracker();
//重新开启Radio
sst.setRadioPowerFromCarrier(true);
mDataEnabledSettings.setCarrierDataEnabled(true);
mPhone.getCarrierSignalAgent().reset();
}
} else {
onSimNotReady();
}
}
}
3,initApnContexts()
initApnContexts()的主要作用就是载入networkAttributes数组中预置的APN参数:
private void initApnContexts() {
log("initApnContexts: E");
//载入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;
//根据不同类型创建不同ApnContext
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_SUPL:
apnContext = addApnContext(PhoneConstants.APN_TYPE_SUPL, networkConfig);
break;
case ConnectivityManager.TYPE_MOBILE_DUN:
apnContext = addApnContext(PhoneConstants.APN_TYPE_DUN, networkConfig);
break;
case ConnectivityManager.TYPE_MOBILE_HIPRI:
apnContext = addApnContext(PhoneConstants.APN_TYPE_HIPRI, networkConfig);
break;
case ConnectivityManager.TYPE_MOBILE_FOTA:
apnContext = addApnContext(PhoneConstants.APN_TYPE_FOTA, networkConfig);
break;
case ConnectivityManager.TYPE_MOBILE_IMS:
apnContext = addApnContext(PhoneConstants.APN_TYPE_IMS, networkConfig);
break;
case ConnectivityManager.TYPE_MOBILE_CBS:
apnContext = addApnContext(PhoneConstants.APN_TYPE_CBS, networkConfig);
break;
case ConnectivityManager.TYPE_MOBILE_IA:
apnContext = addApnContext(PhoneConstants.APN_TYPE_IA, networkConfig);
break;
case ConnectivityManager.TYPE_MOBILE_EMERGENCY:
apnContext = addApnContext(PhoneConstants.APN_TYPE_EMERGENCY, networkConfig);
break;
default:
log("initApnContexts: skipping unknown type=" + networkConfig.type);
continue;
}
log("initApnContexts: apnContext=" + apnContext);
}
if (VDBG) log("initApnContexts: X mApnContexts=" + mApnContexts);
}
4,initEmergencyApnSetting()和addEmergencyApnSetting()
通过initEmergencyApnSetting()载入紧急APN;
通过addEmergencyApnSetting()将紧急APN添加到APN列表中;
private void initEmergencyApnSetting() {
// Operator Numeric is not available when sim records are not loaded.
// Query Telephony.db with APN type as EPDN request does not
// require APN name, plmn and all operators support same APN config.
// DB will contain only one entry for Emergency APN
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();
}
}
这个载入过程其实就是从数据库中搜索条件为"type="emergency""的APN参数,那么这个数据库中的内容是哪里来的呢?
这些参数是在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) { }
}
}
从上面可以看到,从com.android.internal.R.xml.apns和"etc/apns-conf.xml"两个路径下读取了APN的配置文件并解析,然后存入了数据库,这些配置文件的配置内容如下:
@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>
从这个配置文件中可以看到,其每一项数据都包含了某个运营商的PLMN name、MCC、MNC、apn、user、server、password、mmsc等信息。
上面是数据库初始化的过程,回到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");
}
}
}
}
通过以上步骤,紧急APN的创建过程就完成了。
至此,DcTracker所有初始化工作全部完成,在这个过程中注册了监听器、广播接收器,初始化了紧急APN,接下来就是等待监听器被触发。
Telephony基础之DataCall业务(DcTracker创建过程)
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/cornerOfHeart/article/details/79895995
猜你喜欢
转载自blog.csdn.net/cornerOfHeart/article/details/79895995
今日推荐
周排行