APN
Definition:
APN (access point name) can be simply understood as the access point name for data access to the Internet, which is a parameter that must be configured to access data. The configuration of this parameter directly determines the access mode of accessing data.
Parameters:
<apn carrier="China Mobile (China Mobile) WAP"
mcc="460"
mnc="00"
apn="cmwap"
proxy="10.0.0.172"
port="80"
type="default,supl"
/>
Name | Explain |
---|---|
carrier | The name of the APN (you can see it on your phone) |
mccmnc | mccmnc for mobile phones |
apn | Access point |
proxy | agent |
port | port |
type | The type of apn accessible to the network |
To configure:
apn is defined by google as a set of default configurations that can be used by operators. The default location of apn is device/sample/etc/apns-full-conf.xml. After compilation, it will copy to system/etc/apns-conf.xml. For different operators, it can be changed in apns-full-conf.xml.
In mobile phones, APNs exist in telephony.db. Specific location: content://telephony/carriers
Load:
After device detects the completion of simcard load, it undergoes a series of calls:
protected void onRecordsLoadedOrSubIdChanged() {
...
createAllApnList();//Get all standard APNs from the database
setInitialAttachApn();//Setting the apn of the initial accach
...
}
/**
* Based on the sim operator numeric, create a list for all possible
* Data Connections and setup the preferredApn.
*/
protected void createAllApnList() {
mMvnoMatched = false;//Virtual operators are related, not yet encountered
mAllApnSettings = new ArrayList<ApnSetting>();
IccRecords r = mIccRecords.get();
String operator = mPhone.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);
//Screening apn set by mccmnc
Cursor cursor = mPhone.getContext().getContentResolver().query(
Telephony.Carriers.CONTENT_URI, null, selection, null, orderBy);
if (cursor != null) {
if (cursor.getCount() > 0) {
//Get all the appropriate APNs
mAllApnSettings = createApnList(cursor);
}
cursor.close();
}
}
//Add Emergency APN settings
addEmergencyApnSetting();
//Remove duplicate apn
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();
}
ApnSetting
ApnSetting can be simply regarded as the constructor of APN. When querying the database, it is mainly stored in the form of ApnSetting. The parameters correspond to each item in the telephony.db carrier table.
Constructor:
public ApnSetting(int id, String numeric, String carrier, String apn,
String proxy, String port,
String mmsc, String mmsProxy, String mmsPort,
String user, String password, int authType, String[] types,
String protocol, String roamingProtocol, boolean carrierEnabled, int bearer,
int bearerBitmask, int profileId, boolean modemCognitive, int maxConns, int waitTime,
int maxConnsTime, int mtu, String mvnoType, String mvnoMatchData) {
this.id = id; //Identity ID in the database
this.numeric = numeric; // mccmnc
this.carrier = carrier; //The name of the apn (shown in settings)
this.apn = apn; //Access point
this.proxy = proxy; //Agent of apn
this.port = port; //Port number of apn
this.mmsc = mmsc; //Address of MMS Center
this.mmsProxy = mmsProxy; //MMS Proxy
this.mmsPort = mmsPort; //mms port
this.user = user; //To be updated
this.password = password; //To be updated
this.authType = authType; //To be updated
this.types = new String[types.length]; //The data type applicable to the apn
for (int i = 0; i < types.length; i++) {
this.types[i] = types[i].toLowerCase(Locale.ROOT);
}
this.protocol = protocol;
this.roamingProtocol = roamingProtocol;
this.carrierEnabled = carrierEnabled;
this.bearer = bearer;//The type of network that can be processed (?)
this.bearerBitmask = (bearerBitmask | ServiceState.getBitmaskForTech(bearer));
this.profileId = profileId;
this.modemCognitive = modemCognitive;
this.maxConns = maxConns;
this.waitTime = waitTime;
this.maxConnsTime = maxConnsTime;
this.mtu = mtu;
this.mvnoType = mvnoType;
this.mvnoMatchData = mvnoMatchData;
}
Key interface:
/**
* Determine whether the passed type can be processed.
* Usually different operators have different needs, which need special treatment.
*/
public boolean canHandleType(String type) {
if (!carrierEnabled) return false;
for (String t : types) {
// DEFAULT handles all, and HIPRI is handled by DEFAULT
if (t.equalsIgnoreCase(type) ||
t.equalsIgnoreCase(PhoneConstants.APN_TYPE_ALL) ||
(t.equalsIgnoreCase(PhoneConstants.APN_TYPE_DEFAULT) &&
type.equalsIgnoreCase(PhoneConstants.APN_TYPE_HIPRI))) {
return true;
}
}
return false;
}
ApnContext
APN & ApnSetting are configuration parameters, while ApnContext is the operation of APN or ApnSetting. In Dctracker or Data Connection and other major data-related classes, the main operation is ApnContext to read or set APN-related information.
Common interface:
Interface | Return value | Explain |
---|---|---|
getApnSetting | ApnSetting | Returns all current APN s |
getApnType | String | Returns the current APN type |
getState | DctConstants.State | Returns the status of the corresponding network for the apn |
isConnectedOrConnecting | boolean | Returns whether the network corresponding to the current apn is connected |
… | … | … |
System calls:
/**
* Determine whether the type passed in allows access to data
*/
public boolean isDataPossible(String apnType) {
ApnContext apnContext = mApnContexts.get(apnType);
if (apnContext == null) {
return false;
}
boolean apnContextIsEnabled = apnContext.isEnabled();
DctConstants.State apnContextState = apnContext.getState();
boolean apnTypePossible = !(apnContextIsEnabled &&
(apnContextState == DctConstants.State.FAILED));
boolean isEmergencyApn = apnContext.getApnType().equals(PhoneConstants.APN_TYPE_EMERGENCY);
// Set the emergency APN availability status as TRUE irrespective of conditions checked in
// isDataAllowed() like IN_SERVICE, MOBILE DATA status etc.
boolean dataAllowed = isEmergencyApn || isDataAllowed(null);
boolean possible = dataAllowed && apnTypePossible;
if ((apnContext.getApnType().equals(PhoneConstants.APN_TYPE_DEFAULT)
|| apnContext.getApnType().equals(PhoneConstants.APN_TYPE_IA))
&& (mPhone.getServiceState().getRilDataRadioTechnology()
== ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN)) {
log("Default data call activation not possible in iwlan.");
possible = false;
}
if (VDBG) {
log(String.format("isDataPossible(%s): possible=%b isDataAllowed=%b " +
"apnTypePossible=%b apnContextisEnabled=%b apnContextState()=%s",
apnType, possible, dataAllowed, apnTypePossible,
apnContextIsEnabled, apnContextState));
}
return possible;
}