首先,SIM卡的开机流程中,我们知道,是从PhoneFactory.java文件的makeDefaultPhone方法中开始的,而在其中,我们可以看到如下段
for (int i = 0; i < numPhones; i++) {
PhoneBase phone = null;
int phoneType = TelephonyManager.getPhoneType(networkModes[i]);
if (phoneType == PhoneConstants.PHONE_TYPE_GSM) {
phone = new GSMPhone(context,
sCommandsInterfaces[i], sPhoneNotifier, i);
} else if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) {
phone = new CDMALTEPhone(context,
sCommandsInterfaces[i], sPhoneNotifier, i);
}
Rlog.i(LOG_TAG, "Creating Phone with type = " + phoneType + " sub = " + i);
sProxyPhones[i] = new PhoneProxy(phone);
}
创建Phone对象,今天我们就以GSMPhone对象来分析这个默认APN的流程
public
GSMPhone(Context context, CommandsInterface ci, PhoneNotifier notifier, int phoneId) {
this(context, ci, notifier, false, phoneId);
}
public
GSMPhone(Context context, CommandsInterface ci,
PhoneNotifier notifier, boolean unitTestMode, int phoneId) {
super("GSM", notifier, context, ci, unitTestMode, phoneId);
if (ci instanceof SimulatedRadioControl) {
mSimulatedRadioControl = (SimulatedRadioControl) ci;
}
mCi.setPhoneType(PhoneConstants.PHONE_TYPE_GSM);
mCT = new GsmCallTracker(this);
mSST = new GsmServiceStateTracker(this);
mDcTracker = new DcTracker(this);
if (!unitTestMode) {
mSimPhoneBookIntManager = new SimPhoneBookInterfaceManager(this);
mSubInfo = new PhoneSubInfo(this);
}
mCi.registerForAvailable(this, EVENT_RADIO_AVAILABLE, null);
mCi.registerForOffOrNotAvailable(this, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
mCi.registerForOn(this, EVENT_RADIO_ON, null);
mCi.setOnUSSD(this, EVENT_USSD, null);
mCi.setOnSuppServiceNotification(this, EVENT_SSN, null);
mSST.registerForNetworkAttached(this, EVENT_REGISTERED_TO_NETWORK, null);
mCi.setOnSs(this, EVENT_SS, null);
setProperties();
log("GSMPhone: constructor: sub = " + mPhoneId);
setProperties();
}
其中,有创建DcTracker对象,查看这个类的构造方法
//***** Constructor
public DcTracker(PhoneBase p) {
super(p);
......
update();
......
}
首先,先调用了其父类的构造方法
/**
* Default constructor
*/
protected DcTrackerBase(PhoneBase phone) {
super();
mPhone = phone;
......
mUiccController = UiccController.getInstance();
mUiccController.registerForIccChanged(this, DctConstants.EVENT_ICC_CHANGED, null);
......
}
再继续回到DcTracker的构造方法中,可以看到还调用了update方法,进入update方法中查看
public void update() {
......
registerForAllEvents();
onUpdateIcc();
......
}
进入onUpdateIcc方法
@Override
protected void onUpdateIcc() {
......
IccRecords newIccRecords = getUiccRecords(UiccController.APP_FAM_3GPP);
IccRecords r = mIccRecords.get();
if (r != newIccRecords) {
......
if (newIccRecords != null) {
if (mPhone.getSubId() >= 0) {
......
mIccRecords.set(newIccRecords);
newIccRecords.registerForRecordsLoaded(
this, DctConstants.EVENT_RECORDS_LOADED, null);
}
}
......
}
}
通过IccRecords注册DctConstants.EVENT_RECORDS_LOADED消息,当全部加载完成后,发出EVENT_RECORDS_LOADED消息,在DcTracker中接收,并处理
@Override
public void handleMessage (Message msg) {
......
switch (msg.what) {
case DctConstants.EVENT_RECORDS_LOADED:
onRecordsLoaded();
break;
}
}
private void onRecordsLoaded() {
......
createAllApnList();
setInitialAttachApn();
if (mPhone.mCi.getRadioState().isOn()) {
if (DBG) log("onRecordsLoaded: notifying data availability");
notifyOffApnsOfAvailability(Phone.REASON_SIM_LOADED);
}
setupDataOnConnectableApns(Phone.REASON_SIM_LOADED);
}
再查看createAllApnList方法
/**
* Based on the sim operator numeric, create a list for all possible
* Data Connections and setup the preferredApn.
*/
private void createAllApnList() {
mAllApnSettings = new ArrayList();
IccRecords r = mIccRecords.get();
String operator = (r != null) ? r.getOperatorNumeric() : "";
if (operator != null) {
String selection = "numeric = '" + operator + "'";
String orderBy = "_id";
// query only enabled apn.
// carrier_enabled : 1 means enabled apn, 0 disabled apn.
// selection += " and carrier_enabled = 1";
if (DBG) log("createAllApnList: selection=" + selection);
Cursor cursor = mPhone.getContext().getContentResolver().query(
Telephony.Carriers.CONTENT_URI, null, selection, null, orderBy);
if (cursor != null) {
if (cursor.getCount() > 0) {
mAllApnSettings = createApnList(cursor);
}
cursor.close();
}
}
addEmergencyApnSetting();
dedupeApnSettings();
if (mAllApnSettings.isEmpty()) {
if (DBG) log("createAllApnList: No APN found for carrier: " + operator);
mPreferredApn = null;
// TODO: What is the right behavior?
//notifyNoData(DataConnection.FailCause.MISSING_UNKNOWN_APN);
} else {
mPreferredApn = getPreferredApn();
if (mPreferredApn != null && !mPreferredApn.numeric.equals(operator)) {
mPreferredApn = null;
setPreferredApn(-1);
}
if (DBG) log("createAllApnList: mPreferredApn=" + mPreferredApn);
}
if (DBG) log("createAllApnList: X mAllApnSettings=" + mAllApnSettings);
setDataProfilesAsNeeded();
}
可以看到,在这个方法中,主要是通过当前SIM卡的numeric字段,从content://telephony/carriers数据库中获取所有numeric字段对应的APN信息(数据库信息是从哪儿来的,请查看TelephonyProvider.java文件),并且将所有的数据均插入mAllApnSettings中,在这段代码下方可以看到,还有获取preferred apn的数据,由于此前并未设定,因此此处无法获取到
private void setupDataOnConnectableApns(String reason) {
setupDataOnConnectableApns(reason, RetryFailures.ALWAYS);
}
private void setupDataOnConnectableApns(String reason, RetryFailures retryFailures) {
......
for (ApnContext apnContext : mPrioritySortedApnContexts) {
ArrayList waitingApns = null;
......
if (apnContext.getState() == DctConstants.State.FAILED
|| apnContext.getState() == DctConstants.State.RETRYING) {
......
// RetryFailures.ONLY_ON_CHANGE - check if the apns have changed
int radioTech = mPhone.getServiceState().getRilDataRadioTechnology();
ArrayList originalApns = apnContext.getOriginalWaitingApns();
if (originalApns != null && originalApns.isEmpty() == false) {
waitingApns = buildWaitingApns(apnContext.getApnType(), radioTech);
if (originalApns.size() != waitingApns.size() ||
originalApns.containsAll(waitingApns) == false) {
apnContext.releaseDataConnection(reason);
} else {
continue;
}
} else {
continue;
}
......
}
if (apnContext.isConnectable()) {
log("setupDataOnConnectableApns: isConnectable() call trySetupData");
apnContext.setReason(reason);
trySetupData(apnContext, waitingApns);
}
}
}
这边有一个buildWaitingApns方法和trySetupData方法比较重要,我们继续分析这段
/**
* Build a list of APNs to be used to create PDP's.
*
* @param requestedApnType
* @return waitingApns list to be used to create PDP
* error when waitingApns.isEmpty()
*/
private ArrayList buildWaitingApns(String requestedApnType, int radioTech) {
......
ArrayList apnList = new ArrayList();
......
IccRecords r = mIccRecords.get();
String operator = (r != null) ? r.getOperatorNumeric() : "";
......
boolean usePreferred = true;
try {
// 返回usePreferred的值为true
usePreferred = ! mPhone.getContext().getResources().getBoolean(com.android.
internal.R.bool.config_dontPreferApn);
} catch (Resources.NotFoundException e) {
if (DBG) log("buildWaitingApns: usePreferred NotFoundException set to true");
usePreferred = true;
}
// 我们知道此地,一样,无法取得值,返回mPreferredApn的值为null
if (usePreferred) {
mPreferredApn = getPreferredApn();
}
if (DBG) {
log("buildWaitingApns: usePreferred=" + usePreferred
+ " canSetPreferApn=" + mCanSetPreferApn
+ " mPreferredApn=" + mPreferredApn
+ " operator=" + operator + " radioTech=" + radioTech
+ " IccRecords r=" + r);
}
......
if (mAllApnSettings != null) {
......
// 刚刚通过createAllApnList方法获取到的值
for (ApnSetting apn : mAllApnSettings) {
if (apn.canHandleType(requestedApnType)) {
if (ServiceState.bitmaskHasTech(apn.bearerBitmask, radioTech)) {
if (DBG) log("buildWaitingApns: adding apn=" + apn);
apnList.add(apn);
} else {
if (DBG) {
log("buildWaitingApns: bearerBitmask:" + apn.bearerBitmask + " does " +
"not include radioTech:" + radioTech);
}
}
} else if (DBG) {
log("buildWaitingApns: couldn't handle requesedApnType="
+ requestedApnType);
}
}
} else {
loge("mAllApnSettings is null!");
}
if (DBG) log("buildWaitingApns: X apnList=" + apnList);
return apnList;
}
返回一个apnList,这个list是从mAllApnSettings中取到的,而其判断条件为该ApnSetting中是否包含需要的apnType,和是否符合我们的需要
private boolean trySetupData(ApnContext apnContext, ArrayList waitingApns) {
......
apnContext.setWaitingApns(waitingApns);
......
boolean retValue = setupData(apnContext, radioTech);
notifyOffApnsOfAvailability(apnContext.getReason());
......
}
再看setupData方法
private boolean setupData(ApnContext apnContext, int radioTech) {
......
ApnSetting apnSetting;
DcAsyncChannel dcac = null;
// 直接获取mWaitingApn List中的第一个ApnSetting
apnSetting = apnContext.getNextWaitingApn();
......
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 = new Pair(apnContext, generation);
dcac.bringUp(apnContext, getInitialMaxRetry(), profileId, radioTech,
mAutoAttachOnCreation.get(), msg, generation);
if (DBG) log("setupData: initing!");
return true;
}
创建DataConnection,并设置其参数,设置完成后发送EVENT_DATA_SETUP_COMPLETE消息,在其父类DcTrackerBase.java文件中接收,并处理
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
......
case DctConstants.EVENT_DATA_SETUP_COMPLETE:
onDataSetupComplete((AsyncResult) msg.obj);
break;
}
}
在DcTracker的onDataSetupComplete方法中进行处理
/**
* A SETUP (aka bringUp) has completed, possibly with an error. If
* there is an error this method will call {@link #onDataSetupCompleteError}.
*/
@Override
protected void onDataSetupComplete(AsyncResult ar) {
DcFailCause cause = DcFailCause.UNKNOWN;
boolean handleError = false;
ApnContext apnContext = getValidApnContext(ar, "onDataSetupComplete");
......
if (ar.exception == null) {
DcAsyncChannel dcac = apnContext.getDcAc();
......
ApnSetting apn = apnContext.getApnSetting();
......
// everything is setup
if(TextUtils.equals(apnContext.getApnType(),PhoneConstants.APN_TYPE_DEFAULT)) {
SystemProperties.set(PUPPET_MASTER_RADIO_STRESS_TEST, "true");
if (mCanSetPreferApn && mPreferredApn == null) {
if (DBG) log("onDataSetupComplete: PREFERED APN is null");
mPreferredApn = apn;
if (mPreferredApn != null) {
setPreferredApn(mPreferredApn.id);
}
}
}
......
}
......
}