blob: 2ab8d4fb900e96df643dcf42c463879032523821 [file] [log] [blame]
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.telephony.data;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.StringDef;
import android.content.ContentValues;
import android.database.Cursor;
import android.hardware.radio.V1_0.ApnTypes;
import android.net.NetworkUtils;
import android.os.Parcel;
import android.os.Parcelable;
import android.provider.Telephony;
import android.telephony.Rlog;
import android.text.TextUtils;
import android.util.Log;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.net.MalformedURLException;
import java.net.UnknownHostException;
import java.net.URL;
import java.net.InetAddress;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
/**
* A class representing an APN configuration.
*/
public class ApnSetting implements Parcelable {
static final String LOG_TAG = "ApnSetting";
private static final boolean VDBG = false;
private final String mEntryName;
private final String mApnName;
private final InetAddress mProxy;
private final int mPort;
private final URL mMmsc;
private final InetAddress mMmsProxy;
private final int mMmsPort;
private final String mUser;
private final String mPassword;
private final int mAuthType;
private final List<String> mTypes;
private final int mTypesBitmap;
private final int mId;
private final String mOperatorNumeric;
private final String mProtocol;
private final String mRoamingProtocol;
private final int mMtu;
private final boolean mCarrierEnabled;
private final int mBearer;
private final int mBearerBitmask;
private final int mProfileId;
private final boolean mModemCognitive;
private final int mMaxConns;
private final int mWaitTime;
private final int mMaxConnsTime;
private final String mMvnoType;
private final String mMvnoMatchData;
private boolean mPermanentFailed = false;
/**
* Returns the types bitmap of the APN.
*
* @return types bitmap of the APN
* @hide
*/
public int getTypesBitmap() {
return mTypesBitmap;
}
/**
* Returns the MTU size of the mobile interface to which the APN connected.
*
* @return the MTU size of the APN
* @hide
*/
public int getMtu() {
return mMtu;
}
/**
* Radio Access Technology info.
* To check what values can hold, refer to ServiceState.java.
* This should be spread to other technologies,
* but currently only used for LTE(14) and EHRPD(13).
*
* @return the bearer info of the APN
* @hide
*/
public int getBearer() {
return mBearer;
}
/**
* Returns the radio access technology bitmask for this APN.
*
* To check what values can hold, refer to ServiceState.java. This is a bitmask of radio
* technologies in ServiceState.
* This should be spread to other technologies,
* but currently only used for LTE(14) and EHRPD(13).
*
* @return the radio access technology bitmask
* @hide
*/
public int getBearerBitmask() {
return mBearerBitmask;
}
/**
* Returns the profile id to which the APN saved in modem.
*
* @return the profile id of the APN
* @hide
*/
public int getProfileId() {
return mProfileId;
}
/**
* Returns if the APN setting is to be set in modem.
*
* @return is the APN setting to be set in modem
* @hide
*/
public boolean getModemCognitive() {
return mModemCognitive;
}
/**
* Returns the max connections of this APN.
*
* @return the max connections of this APN
* @hide
*/
public int getMaxConns() {
return mMaxConns;
}
/**
* Returns the wait time for retry of the APN.
*
* @return the wait time for retry of the APN
* @hide
*/
public int getWaitTime() {
return mWaitTime;
}
/**
* Returns the time to limit max connection for the APN.
*
* @return the time to limit max connection for the APN
* @hide
*/
public int getMaxConnsTime() {
return mMaxConnsTime;
}
/**
* Returns the MVNO data. Examples:
* "spn": A MOBILE, BEN NL
* "imsi": 302720x94, 2060188
* "gid": 4E, 33
* "iccid": 898603 etc..
*
* @return the mvno match data
* @hide
*/
public String getMvnoMatchData() {
return mMvnoMatchData;
}
/**
* Indicates this APN setting is permanently failed and cannot be
* retried by the retry manager anymore.
*
* @return if this APN setting is permanently failed
* @hide
*/
public boolean getPermanentFailed() {
return mPermanentFailed;
}
/**
* Sets if this APN setting is permanently failed.
*
* @param permanentFailed if this APN setting is permanently failed
* @hide
*/
public void setPermanentFailed(boolean permanentFailed) {
mPermanentFailed = permanentFailed;
}
/**
* Returns the entry name of the APN.
*
* @return the entry name for the APN
*/
public String getEntryName() {
return mEntryName;
}
/**
* Returns the name of the APN.
*
* @return APN name
*/
public String getApnName() {
return mApnName;
}
/**
* Returns the proxy address of the APN.
*
* @return proxy address.
*/
public InetAddress getProxy() {
return mProxy;
}
/**
* Returns the proxy port of the APN.
*
* @return proxy port
*/
public int getPort() {
return mPort;
}
/**
* Returns the MMSC URL of the APN.
*
* @return MMSC URL.
*/
public URL getMmsc() {
return mMmsc;
}
/**
* Returns the MMS proxy address of the APN.
*
* @return MMS proxy address.
*/
public InetAddress getMmsProxy() {
return mMmsProxy;
}
/**
* Returns the MMS proxy port of the APN.
*
* @return MMS proxy port
*/
public int getMmsPort() {
return mMmsPort;
}
/**
* Returns the APN username of the APN.
*
* @return APN username
*/
public String getUser() {
return mUser;
}
/**
* Returns the APN password of the APN.
*
* @return APN password
*/
public String getPassword() {
return mPassword;
}
/** @hide */
@IntDef({
AUTH_TYPE_NONE,
AUTH_TYPE_PAP,
AUTH_TYPE_CHAP,
AUTH_TYPE_PAP_OR_CHAP,
})
@Retention(RetentionPolicy.SOURCE)
public @interface AuthType {}
/**
* Returns the authentication type of the APN.
*
* Example of possible values: {@link #AUTH_TYPE_NONE}, {@link #AUTH_TYPE_PAP}.
*
* @return authentication type
*/
@AuthType
public int getAuthType() {
return mAuthType;
}
/** @hide */
@StringDef({
TYPE_DEFAULT,
TYPE_MMS,
TYPE_SUPL,
TYPE_DUN,
TYPE_HIPRI,
TYPE_FOTA,
TYPE_IMS,
TYPE_CBS,
TYPE_IA,
TYPE_EMERGENCY
})
@Retention(RetentionPolicy.SOURCE)
public @interface ApnType {}
/**
* Returns the list of APN types of the APN.
*
* Example of possible values: {@link #TYPE_DEFAULT}, {@link #TYPE_MMS}.
*
* @return the list of APN types
*/
@ApnType
public List<String> getTypes() {
return mTypes;
}
/**
* Returns the unique database id for this entry.
*
* @return the unique database id
*/
public int getId() {
return mId;
}
/**
* Returns the numeric operator ID for the APN. Usually
* {@link android.provider.Telephony.Carriers#MCC} +
* {@link android.provider.Telephony.Carriers#MNC}.
*
* @return the numeric operator ID
*/
public String getOperatorNumeric() {
return mOperatorNumeric;
}
/** @hide */
@StringDef({
PROTOCOL_IP,
PROTOCOL_IPV6,
PROTOCOL_IPV4V6,
PROTOCOL_PPP,
})
@Retention(RetentionPolicy.SOURCE)
public @interface ProtocolType {}
/**
* Returns the protocol to use to connect to this APN.
*
* One of the {@code PDP_type} values in TS 27.007 section 10.1.1.
* Example of possible values: {@link #PROTOCOL_IP}, {@link #PROTOCOL_IPV6}.
*
* @return the protocol
*/
@ProtocolType
public String getProtocol() {
return mProtocol;
}
/**
* Returns the protocol to use to connect to this APN when roaming.
*
* The syntax is the same as {@link android.provider.Telephony.Carriers#PROTOCOL}.
*
* @return the roaming protocol
*/
public String getRoamingProtocol() {
return mRoamingProtocol;
}
/**
* Returns the current status of APN.
*
* {@code true} : enabled APN.
* {@code false} : disabled APN.
*
* @return the current status
*/
public boolean isEnabled() {
return mCarrierEnabled;
}
/** @hide */
@StringDef({
MVNO_TYPE_SPN,
MVNO_TYPE_IMSI,
MVNO_TYPE_GID,
MVNO_TYPE_ICCID,
})
@Retention(RetentionPolicy.SOURCE)
public @interface MvnoType {}
/**
* Returns the MVNO match type for this APN.
*
* Example of possible values: {@link #MVNO_TYPE_SPN}, {@link #MVNO_TYPE_IMSI}.
*
* @return the MVNO match type
*/
@MvnoType
public String getMvnoType() {
return mMvnoType;
}
private ApnSetting(Builder builder) {
this.mEntryName = builder.mEntryName;
this.mApnName = builder.mApnName;
this.mProxy = builder.mProxy;
this.mPort = builder.mPort;
this.mMmsc = builder.mMmsc;
this.mMmsProxy = builder.mMmsProxy;
this.mMmsPort = builder.mMmsPort;
this.mUser = builder.mUser;
this.mPassword = builder.mPassword;
this.mAuthType = builder.mAuthType;
this.mTypes = (builder.mTypes == null ? new ArrayList<String>() : builder.mTypes);
this.mTypesBitmap = builder.mTypesBitmap;
this.mId = builder.mId;
this.mOperatorNumeric = builder.mOperatorNumeric;
this.mProtocol = builder.mProtocol;
this.mRoamingProtocol = builder.mRoamingProtocol;
this.mMtu = builder.mMtu;
this.mCarrierEnabled = builder.mCarrierEnabled;
this.mBearer = builder.mBearer;
this.mBearerBitmask = builder.mBearerBitmask;
this.mProfileId = builder.mProfileId;
this.mModemCognitive = builder.mModemCognitive;
this.mMaxConns = builder.mMaxConns;
this.mWaitTime = builder.mWaitTime;
this.mMaxConnsTime = builder.mMaxConnsTime;
this.mMvnoType = builder.mMvnoType;
this.mMvnoMatchData = builder.mMvnoMatchData;
}
/** @hide */
public static ApnSetting makeApnSetting(int id, String operatorNumeric, String entryName,
String apnName, InetAddress proxy, int port, URL mmsc, InetAddress mmsProxy,
int mmsPort, String user, String password, int authType, List<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) {
return new Builder()
.setId(id)
.setOperatorNumeric(operatorNumeric)
.setEntryName(entryName)
.setApnName(apnName)
.setProxy(proxy)
.setPort(port)
.setMmsc(mmsc)
.setMmsProxy(mmsProxy)
.setMmsPort(mmsPort)
.setUser(user)
.setPassword(password)
.setAuthType(authType)
.setTypes(types)
.setProtocol(protocol)
.setRoamingProtocol(roamingProtocol)
.setCarrierEnabled(carrierEnabled)
.setBearer(bearer)
.setBearerBitmask(bearerBitmask)
.setProfileId(profileId)
.setModemCognitive(modemCognitive)
.setMaxConns(maxConns)
.setWaitTime(waitTime)
.setMaxConnsTime(maxConnsTime)
.setMtu(mtu)
.setMvnoType(mvnoType)
.setMvnoMatchData(mvnoMatchData)
.build();
}
/** @hide */
public static ApnSetting makeApnSetting(Cursor cursor) {
String[] types = parseTypes(
cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.TYPE)));
return makeApnSetting(
cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers._ID)),
cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.NUMERIC)),
cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.NAME)),
cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.APN)),
inetAddressFromString(cursor.getString(
cursor.getColumnIndexOrThrow(Telephony.Carriers.PROXY))),
portFromString(cursor.getString(
cursor.getColumnIndexOrThrow(Telephony.Carriers.PORT))),
URLFromString(cursor.getString(
cursor.getColumnIndexOrThrow(Telephony.Carriers.MMSC))),
inetAddressFromString(cursor.getString(
cursor.getColumnIndexOrThrow(Telephony.Carriers.MMSPROXY))),
portFromString(cursor.getString(
cursor.getColumnIndexOrThrow(Telephony.Carriers.MMSPORT))),
cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.USER)),
cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.PASSWORD)),
cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.AUTH_TYPE)),
Arrays.asList(types),
cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.PROTOCOL)),
cursor.getString(cursor.getColumnIndexOrThrow(
Telephony.Carriers.ROAMING_PROTOCOL)),
cursor.getInt(cursor.getColumnIndexOrThrow(
Telephony.Carriers.CARRIER_ENABLED)) == 1,
cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.BEARER)),
cursor.getInt(cursor.getColumnIndexOrThrow(
Telephony.Carriers.BEARER_BITMASK)),
cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.PROFILE_ID)),
cursor.getInt(cursor.getColumnIndexOrThrow(
Telephony.Carriers.MODEM_COGNITIVE)) == 1,
cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.MAX_CONNS)),
cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.WAIT_TIME)),
cursor.getInt(cursor.getColumnIndexOrThrow(
Telephony.Carriers.MAX_CONNS_TIME)),
cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.MTU)),
cursor.getString(cursor.getColumnIndexOrThrow(
Telephony.Carriers.MVNO_TYPE)),
cursor.getString(cursor.getColumnIndexOrThrow(
Telephony.Carriers.MVNO_MATCH_DATA)));
}
/** @hide */
public static ApnSetting makeApnSetting(ApnSetting apn) {
return makeApnSetting(apn.mId, apn.mOperatorNumeric, apn.mEntryName, apn.mApnName,
apn.mProxy, apn.mPort, apn.mMmsc, apn.mMmsProxy, apn.mMmsPort, apn.mUser,
apn.mPassword, apn.mAuthType, apn.mTypes, apn.mProtocol, apn.mRoamingProtocol,
apn.mCarrierEnabled, apn.mBearer, apn.mBearerBitmask, apn.mProfileId,
apn.mModemCognitive, apn.mMaxConns, apn.mWaitTime, apn.mMaxConnsTime, apn.mMtu,
apn.mMvnoType, apn.mMvnoMatchData);
}
/** @hide */
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("[ApnSettingV3] ")
.append(mEntryName)
.append(", ").append(mId)
.append(", ").append(mOperatorNumeric)
.append(", ").append(mApnName)
.append(", ").append(inetAddressToString(mProxy))
.append(", ").append(URLToString(mMmsc))
.append(", ").append(inetAddressToString(mMmsProxy))
.append(", ").append(portToString(mMmsPort))
.append(", ").append(portToString(mPort))
.append(", ").append(mAuthType).append(", ");
for (int i = 0; i < mTypes.size(); i++) {
sb.append(mTypes.get(i));
if (i < mTypes.size() - 1) {
sb.append(" | ");
}
}
sb.append(", ").append(mProtocol);
sb.append(", ").append(mRoamingProtocol);
sb.append(", ").append(mCarrierEnabled);
sb.append(", ").append(mBearer);
sb.append(", ").append(mBearerBitmask);
sb.append(", ").append(mProfileId);
sb.append(", ").append(mModemCognitive);
sb.append(", ").append(mMaxConns);
sb.append(", ").append(mWaitTime);
sb.append(", ").append(mMaxConnsTime);
sb.append(", ").append(mMtu);
sb.append(", ").append(mMvnoType);
sb.append(", ").append(mMvnoMatchData);
sb.append(", ").append(mPermanentFailed);
return sb.toString();
}
/**
* Returns true if there are MVNO params specified.
* @hide
*/
public boolean hasMvnoParams() {
return !TextUtils.isEmpty(mMvnoType) && !TextUtils.isEmpty(mMvnoMatchData);
}
/** @hide */
public boolean canHandleType(String type) {
if (!mCarrierEnabled) return false;
boolean wildcardable = true;
if (TYPE_IA.equalsIgnoreCase(type)) wildcardable = false;
for (String t : mTypes) {
// DEFAULT handles all, and HIPRI is handled by DEFAULT
if (t.equalsIgnoreCase(type)
|| (wildcardable && t.equalsIgnoreCase(TYPE_ALL))
|| (t.equalsIgnoreCase(TYPE_DEFAULT)
&& type.equalsIgnoreCase(TYPE_HIPRI))) {
return true;
}
}
return false;
}
// check whether the types of two APN same (even only one type of each APN is same)
private boolean typeSameAny(ApnSetting first, ApnSetting second) {
if (VDBG) {
StringBuilder apnType1 = new StringBuilder(first.mApnName + ": ");
for (int index1 = 0; index1 < first.mTypes.size(); index1++) {
apnType1.append(first.mTypes.get(index1));
apnType1.append(",");
}
StringBuilder apnType2 = new StringBuilder(second.mApnName + ": ");
for (int index1 = 0; index1 < second.mTypes.size(); index1++) {
apnType2.append(second.mTypes.get(index1));
apnType2.append(",");
}
Rlog.d(LOG_TAG, "APN1: is " + apnType1);
Rlog.d(LOG_TAG, "APN2: is " + apnType2);
}
for (int index1 = 0; index1 < first.mTypes.size(); index1++) {
for (int index2 = 0; index2 < second.mTypes.size(); index2++) {
if (first.mTypes.get(index1).equals(ApnSetting.TYPE_ALL)
|| second.mTypes.get(index2).equals(ApnSetting.TYPE_ALL)
|| first.mTypes.get(index1).equals(second.mTypes.get(index2))) {
if (VDBG) Rlog.d(LOG_TAG, "typeSameAny: return true");
return true;
}
}
}
if (VDBG) Rlog.d(LOG_TAG, "typeSameAny: return false");
return false;
}
// TODO - if we have this function we should also have hashCode.
// Also should handle changes in type order and perhaps case-insensitivity
/** @hide */
public boolean equals(Object o) {
if (o instanceof ApnSetting == false) {
return false;
}
ApnSetting other = (ApnSetting) o;
return mEntryName.equals(other.mEntryName)
&& Objects.equals(mId, other.mId)
&& Objects.equals(mOperatorNumeric, other.mOperatorNumeric)
&& Objects.equals(mApnName, other.mApnName)
&& Objects.equals(mProxy, other.mProxy)
&& Objects.equals(mMmsc, other.mMmsc)
&& Objects.equals(mMmsProxy, other.mMmsProxy)
&& Objects.equals(mMmsPort, other.mMmsPort)
&& Objects.equals(mPort,other.mPort)
&& Objects.equals(mUser, other.mUser)
&& Objects.equals(mPassword, other.mPassword)
&& Objects.equals(mAuthType, other.mAuthType)
&& Objects.equals(mTypes, other.mTypes)
&& Objects.equals(mTypesBitmap, other.mTypesBitmap)
&& Objects.equals(mProtocol, other.mProtocol)
&& Objects.equals(mRoamingProtocol, other.mRoamingProtocol)
&& Objects.equals(mCarrierEnabled, other.mCarrierEnabled)
&& Objects.equals(mBearer, other.mBearer)
&& Objects.equals(mBearerBitmask, other.mBearerBitmask)
&& Objects.equals(mProfileId, other.mProfileId)
&& Objects.equals(mModemCognitive, other.mModemCognitive)
&& Objects.equals(mMaxConns, other.mMaxConns)
&& Objects.equals(mWaitTime, other.mWaitTime)
&& Objects.equals(mMaxConnsTime, other.mMaxConnsTime)
&& Objects.equals(mMtu, other.mMtu)
&& Objects.equals(mMvnoType, other.mMvnoType)
&& Objects.equals(mMvnoMatchData, other.mMvnoMatchData);
}
/**
* Compare two APN settings
*
* Note: This method does not compare 'id', 'bearer', 'bearerBitmask'. We only use this for
* determining if tearing a data call is needed when conditions change. See
* cleanUpConnectionsOnUpdatedApns in DcTracker.
*
* @param o the other object to compare
* @param isDataRoaming True if the device is on data roaming
* @return True if the two APN settings are same
* @hide
*/
public boolean equals(Object o, boolean isDataRoaming) {
if (!(o instanceof ApnSetting)) {
return false;
}
ApnSetting other = (ApnSetting) o;
return mEntryName.equals(other.mEntryName)
&& Objects.equals(mOperatorNumeric, other.mOperatorNumeric)
&& Objects.equals(mApnName, other.mApnName)
&& Objects.equals(mProxy, other.mProxy)
&& Objects.equals(mMmsc, other.mMmsc)
&& Objects.equals(mMmsProxy, other.mMmsProxy)
&& Objects.equals(mMmsPort, other.mMmsPort)
&& Objects.equals(mPort, other.mPort)
&& Objects.equals(mUser, other.mUser)
&& Objects.equals(mPassword, other.mPassword)
&& Objects.equals(mAuthType, other.mAuthType)
&& Objects.equals(mTypes, other.mTypes)
&& Objects.equals(mTypesBitmap, other.mTypesBitmap)
&& (isDataRoaming || Objects.equals(mProtocol,other.mProtocol))
&& (!isDataRoaming || Objects.equals(mRoamingProtocol, other.mRoamingProtocol))
&& Objects.equals(mCarrierEnabled, other.mCarrierEnabled)
&& Objects.equals(mProfileId, other.mProfileId)
&& Objects.equals(mModemCognitive, other.mModemCognitive)
&& Objects.equals(mMaxConns, other.mMaxConns)
&& Objects.equals(mWaitTime, other.mWaitTime)
&& Objects.equals(mMaxConnsTime, other.mMaxConnsTime)
&& Objects.equals(mMtu, other.mMtu)
&& Objects.equals(mMvnoType, other.mMvnoType)
&& Objects.equals(mMvnoMatchData, other.mMvnoMatchData);
}
/**
* Check if neither mention DUN and are substantially similar
*
* @param other The other APN settings to compare
* @return True if two APN settings are similar
* @hide
*/
public boolean similar(ApnSetting other) {
return (!this.canHandleType(TYPE_DUN)
&& !other.canHandleType(TYPE_DUN)
&& Objects.equals(this.mApnName, other.mApnName)
&& !typeSameAny(this, other)
&& xorEqualsInetAddress(this.mProxy, other.mProxy)
&& xorEqualsPort(this.mPort, other.mPort)
&& xorEquals(this.mProtocol, other.mProtocol)
&& xorEquals(this.mRoamingProtocol, other.mRoamingProtocol)
&& Objects.equals(this.mCarrierEnabled, other.mCarrierEnabled)
&& Objects.equals(this.mBearerBitmask, other.mBearerBitmask)
&& Objects.equals(this.mProfileId, other.mProfileId)
&& Objects.equals(this.mMvnoType, other.mMvnoType)
&& Objects.equals(this.mMvnoMatchData, other.mMvnoMatchData)
&& xorEqualsURL(this.mMmsc, other.mMmsc)
&& xorEqualsInetAddress(this.mMmsProxy, other.mMmsProxy)
&& xorEqualsPort(this.mMmsPort, other.mMmsPort));
}
// Equal or one is not specified.
private boolean xorEquals(String first, String second) {
return (Objects.equals(first, second)
|| TextUtils.isEmpty(first)
|| TextUtils.isEmpty(second));
}
// Equal or one is not specified.
private boolean xorEqualsInetAddress(InetAddress first, InetAddress second) {
return first == null || second == null || first.equals(second);
}
// Equal or one is not specified.
private boolean xorEqualsURL(URL first, URL second) {
return first == null || second == null || first.equals(second);
}
// Equal or one is not specified.
private boolean xorEqualsPort(int first, int second) {
return first == -1 || second == -1 || Objects.equals(first, second);
}
// Helper function to convert APN string into a 32-bit bitmask.
private static int getApnBitmask(String apn) {
switch (apn) {
case TYPE_DEFAULT: return ApnTypes.DEFAULT;
case TYPE_MMS: return ApnTypes.MMS;
case TYPE_SUPL: return ApnTypes.SUPL;
case TYPE_DUN: return ApnTypes.DUN;
case TYPE_HIPRI: return ApnTypes.HIPRI;
case TYPE_FOTA: return ApnTypes.FOTA;
case TYPE_IMS: return ApnTypes.IMS;
case TYPE_CBS: return ApnTypes.CBS;
case TYPE_IA: return ApnTypes.IA;
case TYPE_EMERGENCY: return ApnTypes.EMERGENCY;
case TYPE_ALL: return ApnTypes.ALL;
default: return ApnTypes.NONE;
}
}
private String deParseTypes(List<String> types) {
if (types == null) {
return null;
}
return TextUtils.join(",", types);
}
/** @hide */
// Called by DPM.
public ContentValues toContentValues() {
ContentValues apnValue = new ContentValues();
if (mOperatorNumeric != null) {
apnValue.put(Telephony.Carriers.NUMERIC, mOperatorNumeric);
}
if (mEntryName != null) {
apnValue.put(Telephony.Carriers.NAME, mEntryName);
}
if (mApnName != null) {
apnValue.put(Telephony.Carriers.APN, mApnName);
}
if (mProxy != null) {
apnValue.put(Telephony.Carriers.PROXY, inetAddressToString(mProxy));
}
apnValue.put(Telephony.Carriers.PORT, portToString(mPort));
if (mMmsc != null) {
apnValue.put(Telephony.Carriers.MMSC, URLToString(mMmsc));
}
apnValue.put(Telephony.Carriers.MMSPORT, portToString(mMmsPort));
if (mMmsProxy != null) {
apnValue.put(Telephony.Carriers.MMSPROXY, inetAddressToString(mMmsProxy));
}
if (mUser != null) {
apnValue.put(Telephony.Carriers.USER, mUser);
}
if (mPassword != null) {
apnValue.put(Telephony.Carriers.PASSWORD, mPassword);
}
apnValue.put(Telephony.Carriers.AUTH_TYPE, mAuthType);
String apnType = deParseTypes(mTypes);
if (apnType != null) {
apnValue.put(Telephony.Carriers.TYPE, apnType);
}
if (mProtocol != null) {
apnValue.put(Telephony.Carriers.PROTOCOL, mProtocol);
}
if (mRoamingProtocol != null) {
apnValue.put(Telephony.Carriers.ROAMING_PROTOCOL, mRoamingProtocol);
}
apnValue.put(Telephony.Carriers.CARRIER_ENABLED, mCarrierEnabled);
// networkTypeBit.
apnValue.put(Telephony.Carriers.BEARER_BITMASK, mBearerBitmask);
if (mMvnoType != null) {
apnValue.put(Telephony.Carriers.MVNO_TYPE, mMvnoType);
}
return apnValue;
}
/**
* @param types comma delimited list of APN types
* @return array of APN types
* @hide
*/
public static String[] parseTypes(String types) {
String[] result;
// If unset, set to DEFAULT.
if (TextUtils.isEmpty(types)) {
result = new String[1];
result[0] = TYPE_ALL;
} else {
result = types.split(",");
}
return result;
}
private static URL URLFromString(String url) {
try {
return TextUtils.isEmpty(url) ? null : new URL(url);
} catch (MalformedURLException e) {
Log.e(LOG_TAG, "Can't parse URL from string.");
return null;
}
}
private static String URLToString(URL url) {
return url == null ? "" : url.toString();
}
private static InetAddress inetAddressFromString(String inetAddress) {
if (TextUtils.isEmpty(inetAddress)) {
return null;
}
try {
return InetAddress.getByName(inetAddress);
} catch (UnknownHostException e) {
Log.e(LOG_TAG, "Can't parse InetAddress from string: unknown host.");
return null;
}
}
private static String inetAddressToString(InetAddress inetAddress) {
if (inetAddress == null) {
return null;
}
return TextUtils.isEmpty(inetAddress.getHostName())
? inetAddress.getHostAddress() : inetAddress.getHostName();
}
private static int portFromString(String strPort) {
int port = -1;
if (!TextUtils.isEmpty(strPort)) {
try {
port = Integer.parseInt(strPort);
} catch (NumberFormatException e) {
Log.e(LOG_TAG, "Can't parse port from String");
}
}
return port;
}
private static String portToString(int port) {
return port == -1 ? "" : Integer.toString(port);
}
// Implement Parcelable.
@Override
/** @hide */
public int describeContents() {
return 0;
}
@Override
/** @hide */
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeInt(mId);
dest.writeString(mOperatorNumeric);
dest.writeString(mEntryName);
dest.writeString(mApnName);
dest.writeValue(mProxy);
dest.writeInt(mPort);
dest.writeValue(mMmsc);
dest.writeValue(mMmsProxy);
dest.writeInt(mMmsPort);
dest.writeString(mUser);
dest.writeString(mPassword);
dest.writeInt(mAuthType);
dest.writeStringArray(mTypes.toArray(new String[0]));
dest.writeString(mProtocol);
dest.writeString(mRoamingProtocol);
dest.writeInt(mCarrierEnabled ? 1: 0);
dest.writeString(mMvnoType);
}
private static ApnSetting readFromParcel(Parcel in) {
return makeApnSetting(in.readInt(), in.readString(), in.readString(), in.readString(),
(InetAddress)in.readValue(InetAddress.class.getClassLoader()),
in.readInt(), (URL)in.readValue(URL.class.getClassLoader()),
(InetAddress)in.readValue(InetAddress.class.getClassLoader()),
in.readInt(), in.readString(), in.readString(), in.readInt(),
Arrays.asList(in.readStringArray()), in.readString(), in.readString(),
in.readInt() > 0, 0, 0, 0, false, 0, 0, 0, 0, in.readString(), null);
}
public static final Parcelable.Creator<ApnSetting> CREATOR =
new Parcelable.Creator<ApnSetting>() {
@Override
public ApnSetting createFromParcel(Parcel in) {
return readFromParcel(in);
}
@Override
public ApnSetting[] newArray(int size) {
return new ApnSetting[size];
}
};
/**
* APN types for data connections. These are usage categories for an APN
* entry. One APN entry may support multiple APN types, eg, a single APN
* may service regular internet traffic ("default") as well as MMS-specific
* connections.<br/>
* ALL is a special type to indicate that this APN entry can
* service all data connections.
*/
public static final String TYPE_ALL = "*";
/** APN type for default data traffic */
public static final String TYPE_DEFAULT = "default";
/** APN type for MMS traffic */
public static final String TYPE_MMS = "mms";
/** APN type for SUPL assisted GPS */
public static final String TYPE_SUPL = "supl";
/** APN type for DUN traffic */
public static final String TYPE_DUN = "dun";
/** APN type for HiPri traffic */
public static final String TYPE_HIPRI = "hipri";
/** APN type for FOTA */
public static final String TYPE_FOTA = "fota";
/** APN type for IMS */
public static final String TYPE_IMS = "ims";
/** APN type for CBS */
public static final String TYPE_CBS = "cbs";
/** APN type for IA Initial Attach APN */
public static final String TYPE_IA = "ia";
/** APN type for Emergency PDN. This is not an IA apn, but is used
* for access to carrier services in an emergency call situation. */
public static final String TYPE_EMERGENCY = "emergency";
/**
* Array of all APN types
*
* @hide
*/
public static final String[] ALL_TYPES = {
TYPE_DEFAULT,
TYPE_MMS,
TYPE_SUPL,
TYPE_DUN,
TYPE_HIPRI,
TYPE_FOTA,
TYPE_IMS,
TYPE_CBS,
TYPE_IA,
TYPE_EMERGENCY
};
// Possible values for authentication types.
public static final int AUTH_TYPE_NONE = 0;
public static final int AUTH_TYPE_PAP = 1;
public static final int AUTH_TYPE_CHAP = 2;
public static final int AUTH_TYPE_PAP_OR_CHAP = 3;
// Possible values for protocol.
public static final String PROTOCOL_IP = "IP";
public static final String PROTOCOL_IPV6 = "IPV6";
public static final String PROTOCOL_IPV4V6 = "IPV4V6";
public static final String PROTOCOL_PPP = "PPP";
// Possible values for MVNO type.
public static final String MVNO_TYPE_SPN = "spn";
public static final String MVNO_TYPE_IMSI = "imsi";
public static final String MVNO_TYPE_GID = "gid";
public static final String MVNO_TYPE_ICCID = "iccid";
public static class Builder{
private String mEntryName;
private String mApnName;
private InetAddress mProxy;
private int mPort = -1;
private URL mMmsc;
private InetAddress mMmsProxy;
private int mMmsPort = -1;
private String mUser;
private String mPassword;
private int mAuthType;
private List<String> mTypes;
private int mTypesBitmap;
private int mId;
private String mOperatorNumeric;
private String mProtocol;
private String mRoamingProtocol;
private int mMtu;
private boolean mCarrierEnabled;
private int mBearer;
private int mBearerBitmask;
private int mProfileId;
private boolean mModemCognitive;
private int mMaxConns;
private int mWaitTime;
private int mMaxConnsTime;
private String mMvnoType;
private String mMvnoMatchData;
/**
* Default constructor for Builder.
*/
public Builder() {}
/**
* Set the MTU size of the mobile interface to which the APN connected.
*
* @param mtu the MTU size to set for the APN
* @hide
*/
public Builder setMtu(int mtu) {
this.mMtu = mtu;
return this;
}
/**
* Sets bearer info.
*
* @param bearer the bearer info to set for the APN
* @hide
*/
public Builder setBearer(int bearer) {
this.mBearer = bearer;
return this;
}
/**
* Sets the radio access technology bitmask for this APN.
*
* @param bearerBitmask the radio access technology bitmask to set for this APN
* @hide
*/
public Builder setBearerBitmask(int bearerBitmask) {
this.mBearerBitmask = bearerBitmask;
return this;
}
/**
* Sets the profile id to which the APN saved in modem.
*
* @param profileId the profile id to set for the APN
* @hide
*/
public Builder setProfileId(int profileId) {
this.mProfileId = profileId;
return this;
}
/**
* Sets if the APN setting is to be set in modem.
*
* @param modemCognitive if the APN setting is to be set in modem
* @hide
*/
public Builder setModemCognitive(boolean modemCognitive) {
this.mModemCognitive = modemCognitive;
return this;
}
/**
* Sets the max connections of this APN.
*
* @param maxConns the max connections of this APN
* @hide
*/
public Builder setMaxConns(int maxConns) {
this.mMaxConns = maxConns;
return this;
}
/**
* Sets the wait time for retry of the APN.
*
* @param waitTime the wait time for retry of the APN
* @hide
*/
public Builder setWaitTime(int waitTime) {
this.mWaitTime = waitTime;
return this;
}
/**
* Sets the time to limit max connection for the APN.
*
* @param maxConnsTime the time to limit max connection for the APN
* @hide
*/
public Builder setMaxConnsTime(int maxConnsTime) {
this.mMaxConnsTime = maxConnsTime;
return this;
}
/**
* Sets the MVNO match data for the APN.
*
* @param mvnoMatchData the MVNO match data for the APN
* @hide
*/
public Builder setMvnoMatchData(String mvnoMatchData) {
this.mMvnoMatchData = mvnoMatchData;
return this;
}
/**
* Sets the entry name of the APN.
*
* @param entryName the entry name to set for the APN
*/
public Builder setEntryName(String entryName) {
this.mEntryName = entryName;
return this;
}
/**
* Sets the name of the APN.
*
* @param apnName the name to set for the APN
*/
public Builder setApnName(String apnName) {
this.mApnName = apnName;
return this;
}
/**
* Sets the proxy address of the APN.
*
* @param proxy the proxy address to set for the APN
*/
public Builder setProxy(InetAddress proxy) {
this.mProxy = proxy;
return this;
}
/**
* Sets the proxy port of the APN.
*
* @param port the proxy port to set for the APN
*/
public Builder setPort(int port) {
this.mPort = port;
return this;
}
/**
* Sets the MMSC URL of the APN.
*
* @param mmsc the MMSC URL to set for the APN
*/
public Builder setMmsc(URL mmsc) {
this.mMmsc = mmsc;
return this;
}
/**
* Sets the MMS proxy address of the APN.
*
* @param mmsProxy the MMS proxy address to set for the APN
*/
public Builder setMmsProxy(InetAddress mmsProxy) {
this.mMmsProxy = mmsProxy;
return this;
}
/**
* Sets the MMS proxy port of the APN.
*
* @param mmsPort the MMS proxy port to set for the APN
*/
public Builder setMmsPort(int mmsPort) {
this.mMmsPort = mmsPort;
return this;
}
/**
* Sets the APN username of the APN.
*
* @param user the APN username to set for the APN
*/
public Builder setUser(String user) {
this.mUser = user;
return this;
}
/**
* Sets the APN password of the APN.
*
* @see android.provider.Telephony.Carriers#PASSWORD
* @param password the APN password to set for the APN
*/
public Builder setPassword(String password) {
this.mPassword = password;
return this;
}
/**
* Sets the authentication type of the APN.
*
* Example of possible values: {@link #AUTH_TYPE_NONE}, {@link #AUTH_TYPE_PAP}.
*
* @param authType the authentication type to set for the APN
*/
public Builder setAuthType(@AuthType int authType) {
this.mAuthType = authType;
return this;
}
/**
* Sets the list of APN types of the APN.
*
* Example of possible values: {@link #TYPE_DEFAULT}, {@link #TYPE_MMS}.
*
* @param types the list of APN types to set for the APN
*/
public Builder setTypes(@ApnType List<String> types) {
this.mTypes = types;
int apnBitmap = 0;
for (int i = 0; i < mTypes.size(); i++) {
mTypes.set(i, mTypes.get(i).toLowerCase());
apnBitmap |= getApnBitmask(mTypes.get(i));
}
this.mTypesBitmap = apnBitmap;
return this;
}
/**
* Sets the unique database id for this entry.
*
* @param id the unique database id to set for this entry
*/
public Builder setId(int id) {
this.mId = id;
return this;
}
/**
* Set the numeric operator ID for the APN.
*
* @param operatorNumeric the numeric operator ID to set for this entry
*/
public Builder setOperatorNumeric(String operatorNumeric) {
this.mOperatorNumeric = operatorNumeric;
return this;
}
/**
* Sets the protocol to use to connect to this APN.
*
* One of the {@code PDP_type} values in TS 27.007 section 10.1.1.
* Example of possible values: {@link #PROTOCOL_IP}, {@link #PROTOCOL_IPV6}.
*
* @param protocol the protocol to set to use to connect to this APN
*/
public Builder setProtocol(@ProtocolType String protocol) {
this.mProtocol = protocol;
return this;
}
/**
* Sets the protocol to use to connect to this APN when roaming.
*
* @param roamingProtocol the protocol to set to use to connect to this APN when roaming
*/
public Builder setRoamingProtocol(String roamingProtocol) {
this.mRoamingProtocol = roamingProtocol;
return this;
}
/**
* Sets the current status of APN.
*
* @param carrierEnabled the current status to set for this APN
*/
public Builder setCarrierEnabled(boolean carrierEnabled) {
this.mCarrierEnabled = carrierEnabled;
return this;
}
/**
* Sets the MVNO match type for this APN.
*
* Example of possible values: {@link #MVNO_TYPE_SPN}, {@link #MVNO_TYPE_IMSI}.
*
* @param mvnoType the MVNO match type to set for this APN
*/
public Builder setMvnoType(@MvnoType String mvnoType) {
this.mMvnoType = mvnoType;
return this;
}
public ApnSetting build() {
return new ApnSetting(this);
}
}
}