Home | History | Annotate | Download | only in dataconnection
      1 /*
      2  * Copyright (C) 2006 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.internal.telephony.dataconnection;
     18 
     19 import android.content.Context;
     20 import android.hardware.radio.V1_0.ApnTypes;
     21 import android.os.PersistableBundle;
     22 import android.provider.Telephony.Carriers;
     23 import android.telephony.CarrierConfigManager;
     24 import android.telephony.Rlog;
     25 import android.telephony.ServiceState;
     26 import android.text.TextUtils;
     27 import android.util.Log;
     28 
     29 import com.android.internal.annotations.VisibleForTesting;
     30 import com.android.internal.telephony.Phone;
     31 import com.android.internal.telephony.PhoneConstants;
     32 import com.android.internal.telephony.RILConstants;
     33 import com.android.internal.telephony.uicc.IccRecords;
     34 
     35 import java.util.ArrayList;
     36 import java.util.Arrays;
     37 import java.util.HashSet;
     38 import java.util.List;
     39 import java.util.Objects;
     40 
     41 /**
     42  * This class represents a apn setting for create PDP link
     43  */
     44 public class ApnSetting {
     45 
     46     static final String LOG_TAG = "ApnSetting";
     47 
     48     private static final boolean DBG = false;
     49     private static final boolean VDBG = false;
     50 
     51     static final String V2_FORMAT_REGEX = "^\\[ApnSettingV2\\]\\s*";
     52     static final String V3_FORMAT_REGEX = "^\\[ApnSettingV3\\]\\s*";
     53     static final String V4_FORMAT_REGEX = "^\\[ApnSettingV4\\]\\s*";
     54     static final String V5_FORMAT_REGEX = "^\\[ApnSettingV5\\]\\s*";
     55     static final String TAG = "ApnSetting";
     56 
     57     public final String carrier;
     58     public final String apn;
     59     public final String proxy;
     60     public final String port;
     61     public final String mmsc;
     62     public final String mmsProxy;
     63     public final String mmsPort;
     64     public final String user;
     65     public final String password;
     66     public final int authType;
     67     public final String[] types;
     68     public final int typesBitmap;
     69     public final int id;
     70     public final String numeric;
     71     public final String protocol;
     72     public final String roamingProtocol;
     73     public final int mtu;
     74 
     75     /**
     76       * Current status of APN
     77       * true : enabled APN, false : disabled APN.
     78       */
     79     public final boolean carrierEnabled;
     80     /**
     81      * Radio Access Technology info
     82      * To check what values can hold, refer to ServiceState.java.
     83      * This should be spread to other technologies,
     84      * but currently only used for LTE(14) and EHRPD(13).
     85      *
     86      * @deprecated use {@code networkTypeBitmask} instead
     87      */
     88     @Deprecated
     89     private final int bearer;
     90     /**
     91       * Radio Access Technology info
     92       * To check what values can hold, refer to ServiceState.java. This is a bitmask of radio
     93       * technologies in ServiceState.
     94       * This should be spread to other technologies,
     95       * but currently only used for LTE(14) and EHRPD(13).
     96       *
     97       * @deprecated use {@code networkTypeBitmask} instead
     98       */
     99     @Deprecated
    100     public final int bearerBitmask;
    101 
    102     /**
    103      * Radio Technology (Network Type) info
    104      * To check what values can hold, refer to TelephonyManager.java. This is a bitmask of radio
    105      * technologies ({@code NETWORK_TYPE_} constants) in {@link TelephonyManager}.
    106      */
    107     public final int networkTypeBitmask;
    108 
    109     /* ID of the profile in the modem */
    110     public final int profileId;
    111     public final boolean modemCognitive;
    112     public final int maxConns;
    113     public final int waitTime;
    114     public final int maxConnsTime;
    115 
    116     /**
    117       * MVNO match type. Possible values:
    118       *   "spn": Service provider name.
    119       *   "imsi": IMSI.
    120       *   "gid": Group identifier level 1.
    121       *   "iccid": ICCID
    122       */
    123     public final String mvnoType;
    124     /**
    125       * MVNO data. Examples:
    126       *   "spn": A MOBILE, BEN NL
    127       *   "imsi": 302720x94, 2060188
    128       *   "gid": 4E, 33
    129       *   "iccid": 898603 etc.
    130       */
    131     public final String mvnoMatchData;
    132 
    133     /**
    134      * The APN set id.
    135      *
    136      * APNs that are part of the same set should be preferred together, e.g. if the
    137      * user selects a default APN with apnSetId=1, then we will prefer all APNs with apnSetId=1.
    138      *
    139      * If the apnSetId=Carriers.NO_SET_SET (=0) then the APN is not part of a set.
    140      */
    141     public final int apnSetId;
    142 
    143     /**
    144      * Indicates this APN setting is permanently failed and cannot be
    145      * retried by the retry manager anymore.
    146      * */
    147     public boolean permanentFailed = false;
    148 
    149     /**
    150      * @deprecated this constructor is no longer supported. Use the other constructor which takes
    151      * a network type bitmask instead of the deprecated bearer bitmask and bearer field.
    152      * */
    153     @Deprecated
    154     public ApnSetting(int id, String numeric, String carrier, String apn,
    155                       String proxy, String port,
    156                       String mmsc, String mmsProxy, String mmsPort,
    157                       String user, String password, int authType, String[] types,
    158                       String protocol, String roamingProtocol, boolean carrierEnabled, int bearer,
    159                       int bearerBitmask, int profileId, boolean modemCognitive, int maxConns,
    160                       int waitTime, int maxConnsTime, int mtu, String mvnoType,
    161                       String mvnoMatchData) {
    162         this.id = id;
    163         this.numeric = numeric;
    164         this.carrier = carrier;
    165         this.apn = apn;
    166         this.proxy = proxy;
    167         this.port = port;
    168         this.mmsc = mmsc;
    169         this.mmsProxy = mmsProxy;
    170         this.mmsPort = mmsPort;
    171         this.user = user;
    172         this.password = password;
    173         this.authType = authType;
    174         this.types = new String[types.length];
    175         int apnBitmap = 0;
    176         for (int i = 0; i < types.length; i++) {
    177             this.types[i] = types[i].toLowerCase();
    178             apnBitmap |= getApnBitmask(this.types[i]);
    179         }
    180         this.typesBitmap = apnBitmap;
    181         this.protocol = protocol;
    182         this.roamingProtocol = roamingProtocol;
    183         this.carrierEnabled = carrierEnabled;
    184         this.bearer = bearer;
    185         this.bearerBitmask = (bearerBitmask | ServiceState.getBitmaskForTech(bearer));
    186         this.profileId = profileId;
    187         this.modemCognitive = modemCognitive;
    188         this.maxConns = maxConns;
    189         this.waitTime = waitTime;
    190         this.maxConnsTime = maxConnsTime;
    191         this.mtu = mtu;
    192         this.mvnoType = mvnoType;
    193         this.mvnoMatchData = mvnoMatchData;
    194         this.apnSetId = Carriers.NO_SET_SET;
    195         this.networkTypeBitmask = ServiceState.convertBearerBitmaskToNetworkTypeBitmask(
    196                 this.bearerBitmask);
    197     }
    198 
    199     // Constructor with default apn set id
    200     public ApnSetting(int id, String numeric, String carrier, String apn,
    201                       String proxy, String port,
    202                       String mmsc, String mmsProxy, String mmsPort,
    203                       String user, String password, int authType, String[] types,
    204                       String protocol, String roamingProtocol, boolean carrierEnabled,
    205                       int networkTypeBitmask, int profileId, boolean modemCognitive, int maxConns,
    206                       int waitTime, int maxConnsTime, int mtu, String mvnoType,
    207                       String mvnoMatchData) {
    208         this(id, numeric, carrier, apn, proxy, port, mmsc, mmsProxy, mmsPort, user, password,
    209                 authType, types, protocol, roamingProtocol, carrierEnabled, networkTypeBitmask,
    210                 profileId, modemCognitive, maxConns, waitTime, maxConnsTime, mtu, mvnoType,
    211                 mvnoMatchData, Carriers.NO_SET_SET);
    212     }
    213 
    214     public ApnSetting(int id, String numeric, String carrier, String apn,
    215                       String proxy, String port,
    216                       String mmsc, String mmsProxy, String mmsPort,
    217                       String user, String password, int authType, String[] types,
    218                       String protocol, String roamingProtocol, boolean carrierEnabled,
    219                       int networkTypeBitmask, int profileId, boolean modemCognitive, int maxConns,
    220                       int waitTime, int maxConnsTime, int mtu, String mvnoType,
    221                       String mvnoMatchData, int apnSetId) {
    222         this.id = id;
    223         this.numeric = numeric;
    224         this.carrier = carrier;
    225         this.apn = apn;
    226         this.proxy = proxy;
    227         this.port = port;
    228         this.mmsc = mmsc;
    229         this.mmsProxy = mmsProxy;
    230         this.mmsPort = mmsPort;
    231         this.user = user;
    232         this.password = password;
    233         this.authType = authType;
    234         this.types = new String[types.length];
    235         int apnBitmap = 0;
    236         for (int i = 0; i < types.length; i++) {
    237             this.types[i] = types[i].toLowerCase();
    238             apnBitmap |= getApnBitmask(this.types[i]);
    239         }
    240         this.typesBitmap = apnBitmap;
    241         this.protocol = protocol;
    242         this.roamingProtocol = roamingProtocol;
    243         this.carrierEnabled = carrierEnabled;
    244         this.bearer = 0;
    245         this.bearerBitmask =
    246                 ServiceState.convertNetworkTypeBitmaskToBearerBitmask(networkTypeBitmask);
    247         this.networkTypeBitmask = networkTypeBitmask;
    248         this.profileId = profileId;
    249         this.modemCognitive = modemCognitive;
    250         this.maxConns = maxConns;
    251         this.waitTime = waitTime;
    252         this.maxConnsTime = maxConnsTime;
    253         this.mtu = mtu;
    254         this.mvnoType = mvnoType;
    255         this.mvnoMatchData = mvnoMatchData;
    256         this.apnSetId = apnSetId;
    257     }
    258 
    259     public ApnSetting(ApnSetting apn) {
    260         this(apn.id, apn.numeric, apn.carrier, apn.apn, apn.proxy, apn.port, apn.mmsc, apn.mmsProxy,
    261                 apn.mmsPort, apn.user, apn.password, apn.authType, apn.types, apn.protocol,
    262                 apn.roamingProtocol, apn.carrierEnabled, apn.networkTypeBitmask, apn.profileId,
    263                 apn.modemCognitive, apn.maxConns, apn.waitTime, apn.maxConnsTime,
    264                 apn.mtu, apn.mvnoType, apn.mvnoMatchData, apn.apnSetId);
    265     }
    266 
    267     /**
    268      * Creates an ApnSetting object from a string.
    269      *
    270      * @param data the string to read.
    271      *
    272      * The string must be in one of two formats (newlines added for clarity,
    273      * spaces are optional):
    274      *
    275      * v1 format:
    276      *   <carrier>, <apn>, <proxy>, <port>, <user>, <password>, <server>,
    277      *   <mmsc>, <mmsproxy>, <mmsport>, <mcc>, <mnc>, <authtype>,
    278      *   <type>[| <type>...],
    279      *
    280      * v2 format:
    281      *   [ApnSettingV2] <carrier>, <apn>, <proxy>, <port>, <user>, <password>, <server>,
    282      *   <mmsc>, <mmsproxy>, <mmsport>, <mcc>, <mnc>, <authtype>,
    283      *   <type>[| <type>...], <protocol>, <roaming_protocol>, <carrierEnabled>, <bearerBitmask>,
    284      *
    285      * v3 format:
    286      *   [ApnSettingV3] <carrier>, <apn>, <proxy>, <port>, <user>, <password>, <server>,
    287      *   <mmsc>, <mmsproxy>, <mmsport>, <mcc>, <mnc>, <authtype>,
    288      *   <type>[| <type>...], <protocol>, <roaming_protocol>, <carrierEnabled>, <bearerBitmask>,
    289      *   <profileId>, <modemCognitive>, <maxConns>, <waitTime>, <maxConnsTime>, <mtu>,
    290      *   <mvnoType>, <mvnoMatchData>
    291      *
    292      * v4 format:
    293      *   [ApnSettingV4] <carrier>, <apn>, <proxy>, <port>, <user>, <password>, <server>,
    294      *   <mmsc>, <mmsproxy>, <mmsport>, <mcc>, <mnc>, <authtype>,
    295      *   <type>[| <type>...], <protocol>, <roaming_protocol>, <carrierEnabled>, <bearerBitmask>,
    296      *   <profileId>, <modemCognitive>, <maxConns>, <waitTime>, <maxConnsTime>, <mtu>,
    297      *   <mvnoType>, <mvnoMatchData>, <networkTypeBitmask>
    298      *
    299      * v5 format:
    300      *   [ApnSettingV5] <carrier>, <apn>, <proxy>, <port>, <user>, <password>, <server>,
    301      *   <mmsc>, <mmsproxy>, <mmsport>, <mcc>, <mnc>, <authtype>,
    302      *   <type>[| <type>...], <protocol>, <roaming_protocol>, <carrierEnabled>, <bearerBitmask>,
    303      *   <profileId>, <modemCognitive>, <maxConns>, <waitTime>, <maxConnsTime>, <mtu>,
    304      *   <mvnoType>, <mvnoMatchData>, <networkTypeBitmask>, <apnSetId>
    305      *
    306      * Note that the strings generated by toString() do not contain the username
    307      * and password and thus cannot be read by this method.
    308      */
    309     public static ApnSetting fromString(String data) {
    310         if (data == null) return null;
    311 
    312         int version;
    313         // matches() operates on the whole string, so append .* to the regex.
    314         if (data.matches(V5_FORMAT_REGEX + ".*")) {
    315             version = 5;
    316             data = data.replaceFirst(V5_FORMAT_REGEX, "");
    317         } else if (data.matches(V4_FORMAT_REGEX + ".*")) {
    318             version = 4;
    319             data = data.replaceFirst(V4_FORMAT_REGEX, "");
    320         } else if (data.matches(V3_FORMAT_REGEX + ".*")) {
    321             version = 3;
    322             data = data.replaceFirst(V3_FORMAT_REGEX, "");
    323         } else if (data.matches(V2_FORMAT_REGEX + ".*")) {
    324             version = 2;
    325             data = data.replaceFirst(V2_FORMAT_REGEX, "");
    326         } else {
    327             version = 1;
    328         }
    329 
    330         String[] a = data.split("\\s*,\\s*");
    331         if (a.length < 14) {
    332             return null;
    333         }
    334 
    335         int authType;
    336         try {
    337             authType = Integer.parseInt(a[12]);
    338         } catch (NumberFormatException e) {
    339             authType = 0;
    340         }
    341 
    342         String[] typeArray;
    343         String protocol, roamingProtocol;
    344         boolean carrierEnabled;
    345         int bearerBitmask = 0;
    346         int networkTypeBitmask = 0;
    347         int profileId = 0;
    348         boolean modemCognitive = false;
    349         int maxConns = 0;
    350         int waitTime = 0;
    351         int maxConnsTime = 0;
    352         int mtu = PhoneConstants.UNSET_MTU;
    353         String mvnoType = "";
    354         String mvnoMatchData = "";
    355         int apnSetId = Carriers.NO_SET_SET;
    356         if (version == 1) {
    357             typeArray = new String[a.length - 13];
    358             System.arraycopy(a, 13, typeArray, 0, a.length - 13);
    359             protocol = RILConstants.SETUP_DATA_PROTOCOL_IP;
    360             roamingProtocol = RILConstants.SETUP_DATA_PROTOCOL_IP;
    361             carrierEnabled = true;
    362         } else {
    363             if (a.length < 18) {
    364                 return null;
    365             }
    366             typeArray = a[13].split("\\s*\\|\\s*");
    367             protocol = a[14];
    368             roamingProtocol = a[15];
    369             carrierEnabled = Boolean.parseBoolean(a[16]);
    370 
    371             bearerBitmask = ServiceState.getBitmaskFromString(a[17]);
    372 
    373             if (a.length > 22) {
    374                 modemCognitive = Boolean.parseBoolean(a[19]);
    375                 try {
    376                     profileId = Integer.parseInt(a[18]);
    377                     maxConns = Integer.parseInt(a[20]);
    378                     waitTime = Integer.parseInt(a[21]);
    379                     maxConnsTime = Integer.parseInt(a[22]);
    380                 } catch (NumberFormatException e) {
    381                 }
    382             }
    383             if (a.length > 23) {
    384                 try {
    385                     mtu = Integer.parseInt(a[23]);
    386                 } catch (NumberFormatException e) {
    387                 }
    388             }
    389             if (a.length > 25) {
    390                 mvnoType = a[24];
    391                 mvnoMatchData = a[25];
    392             }
    393             if (a.length > 26) {
    394                 networkTypeBitmask = ServiceState.getBitmaskFromString(a[26]);
    395             }
    396             if (a.length > 27) {
    397                 apnSetId = Integer.parseInt(a[27]);
    398             }
    399         }
    400 
    401         // If both bearerBitmask and networkTypeBitmask were specified, bearerBitmask would be
    402         // ignored.
    403         if (networkTypeBitmask == 0) {
    404             networkTypeBitmask =
    405                     ServiceState.convertBearerBitmaskToNetworkTypeBitmask(bearerBitmask);
    406         }
    407         return new ApnSetting(-1, a[10] + a[11], a[0], a[1], a[2], a[3], a[7], a[8], a[9], a[4],
    408                 a[5], authType, typeArray, protocol, roamingProtocol, carrierEnabled,
    409                 networkTypeBitmask, profileId, modemCognitive, maxConns, waitTime, maxConnsTime,
    410                 mtu, mvnoType, mvnoMatchData, apnSetId);
    411     }
    412 
    413     /**
    414      * Creates an array of ApnSetting objects from a string.
    415      *
    416      * @param data the string to read.
    417      *
    418      * Builds on top of the same format used by fromString, but allows for multiple entries
    419      * separated by "; ".
    420      */
    421     public static List<ApnSetting> arrayFromString(String data) {
    422         List<ApnSetting> retVal = new ArrayList<ApnSetting>();
    423         if (TextUtils.isEmpty(data)) {
    424             return retVal;
    425         }
    426         String[] apnStrings = data.split("\\s*;\\s*");
    427         for (String apnString : apnStrings) {
    428             ApnSetting apn = fromString(apnString);
    429             if (apn != null) {
    430                 retVal.add(apn);
    431             }
    432         }
    433         return retVal;
    434     }
    435 
    436     @Override
    437     public String toString() {
    438         StringBuilder sb = new StringBuilder();
    439         sb.append("[ApnSettingV5] ")
    440         .append(carrier)
    441         .append(", ").append(id)
    442         .append(", ").append(numeric)
    443         .append(", ").append(apn)
    444         .append(", ").append(proxy)
    445         .append(", ").append(mmsc)
    446         .append(", ").append(mmsProxy)
    447         .append(", ").append(mmsPort)
    448         .append(", ").append(port)
    449         .append(", ").append(authType).append(", ");
    450         for (int i = 0; i < types.length; i++) {
    451             sb.append(types[i]);
    452             if (i < types.length - 1) {
    453                 sb.append(" | ");
    454             }
    455         }
    456         sb.append(", ").append(protocol);
    457         sb.append(", ").append(roamingProtocol);
    458         sb.append(", ").append(carrierEnabled);
    459         sb.append(", ").append(bearer);
    460         sb.append(", ").append(bearerBitmask);
    461         sb.append(", ").append(profileId);
    462         sb.append(", ").append(modemCognitive);
    463         sb.append(", ").append(maxConns);
    464         sb.append(", ").append(waitTime);
    465         sb.append(", ").append(maxConnsTime);
    466         sb.append(", ").append(mtu);
    467         sb.append(", ").append(mvnoType);
    468         sb.append(", ").append(mvnoMatchData);
    469         sb.append(", ").append(permanentFailed);
    470         sb.append(", ").append(networkTypeBitmask);
    471         sb.append(", ").append(apnSetId);
    472         return sb.toString();
    473     }
    474 
    475     /**
    476      * Returns true if there are MVNO params specified.
    477      */
    478     public boolean hasMvnoParams() {
    479         return !TextUtils.isEmpty(mvnoType) && !TextUtils.isEmpty(mvnoMatchData);
    480     }
    481 
    482     public boolean canHandleType(String type) {
    483         if (!carrierEnabled) return false;
    484         boolean wildcardable = true;
    485         if (PhoneConstants.APN_TYPE_IA.equalsIgnoreCase(type)) wildcardable = false;
    486         for (String t : types) {
    487             // DEFAULT handles all, and HIPRI is handled by DEFAULT
    488             if (t.equalsIgnoreCase(type) ||
    489                     (wildcardable && t.equalsIgnoreCase(PhoneConstants.APN_TYPE_ALL)) ||
    490                     (t.equalsIgnoreCase(PhoneConstants.APN_TYPE_DEFAULT) &&
    491                     type.equalsIgnoreCase(PhoneConstants.APN_TYPE_HIPRI))) {
    492                 return true;
    493             }
    494         }
    495         return false;
    496     }
    497 
    498     private static boolean iccidMatches(String mvnoData, String iccId) {
    499         String[] mvnoIccidList = mvnoData.split(",");
    500         for (String mvnoIccid : mvnoIccidList) {
    501             if (iccId.startsWith(mvnoIccid)) {
    502                 Log.d(TAG, "mvno icc id match found");
    503                 return true;
    504             }
    505         }
    506         return false;
    507     }
    508 
    509     private static boolean imsiMatches(String imsiDB, String imsiSIM) {
    510         // Note: imsiDB value has digit number or 'x' character for seperating USIM information
    511         // for MVNO operator. And then digit number is matched at same order and 'x' character
    512         // could replace by any digit number.
    513         // ex) if imsiDB inserted '310260x10xxxxxx' for GG Operator,
    514         //     that means first 6 digits, 8th and 9th digit
    515         //     should be set in USIM for GG Operator.
    516         int len = imsiDB.length();
    517         int idxCompare = 0;
    518 
    519         if (len <= 0) return false;
    520         if (len > imsiSIM.length()) return false;
    521 
    522         for (int idx=0; idx<len; idx++) {
    523             char c = imsiDB.charAt(idx);
    524             if ((c == 'x') || (c == 'X') || (c == imsiSIM.charAt(idx))) {
    525                 continue;
    526             } else {
    527                 return false;
    528             }
    529         }
    530         return true;
    531     }
    532 
    533     public static boolean mvnoMatches(IccRecords r, String mvnoType, String mvnoMatchData) {
    534         if (mvnoType.equalsIgnoreCase("spn")) {
    535             if ((r.getServiceProviderName() != null) &&
    536                     r.getServiceProviderName().equalsIgnoreCase(mvnoMatchData)) {
    537                 return true;
    538             }
    539         } else if (mvnoType.equalsIgnoreCase("imsi")) {
    540             String imsiSIM = r.getIMSI();
    541             if ((imsiSIM != null) && imsiMatches(mvnoMatchData, imsiSIM)) {
    542                 return true;
    543             }
    544         } else if (mvnoType.equalsIgnoreCase("gid")) {
    545             String gid1 = r.getGid1();
    546             int mvno_match_data_length = mvnoMatchData.length();
    547             if ((gid1 != null) && (gid1.length() >= mvno_match_data_length) &&
    548                     gid1.substring(0, mvno_match_data_length).equalsIgnoreCase(mvnoMatchData)) {
    549                 return true;
    550             }
    551         } else if (mvnoType.equalsIgnoreCase("iccid")) {
    552             String iccId = r.getIccId();
    553             if ((iccId != null) && iccidMatches(mvnoMatchData, iccId)) {
    554                 return true;
    555             }
    556         }
    557 
    558         return false;
    559     }
    560 
    561     /**
    562      * Check if this APN type is metered.
    563      *
    564      * @param type The APN type
    565      * @param phone The phone object
    566      * @return True if the APN type is metered, otherwise false.
    567      */
    568     public static boolean isMeteredApnType(String type, Phone phone) {
    569         if (phone == null) {
    570             return true;
    571         }
    572 
    573         boolean isRoaming = phone.getServiceState().getDataRoaming();
    574         boolean isIwlan = phone.getServiceState().getRilDataRadioTechnology()
    575                 == ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN;
    576         int subId = phone.getSubId();
    577 
    578         String carrierConfig;
    579         // First check if the device is in IWLAN mode. If yes, use the IWLAN metered APN list. Then
    580         // check if the device is roaming. If yes, use the roaming metered APN list. Otherwise, use
    581         // the normal metered APN list.
    582         if (isIwlan) {
    583             carrierConfig = CarrierConfigManager.KEY_CARRIER_METERED_IWLAN_APN_TYPES_STRINGS;
    584         } else if (isRoaming) {
    585             carrierConfig = CarrierConfigManager.KEY_CARRIER_METERED_ROAMING_APN_TYPES_STRINGS;
    586         } else {
    587             carrierConfig = CarrierConfigManager.KEY_CARRIER_METERED_APN_TYPES_STRINGS;
    588         }
    589 
    590         if (DBG) {
    591             Rlog.d(LOG_TAG, "isMeteredApnType: isRoaming=" + isRoaming + ", isIwlan=" + isIwlan);
    592         }
    593 
    594         CarrierConfigManager configManager = (CarrierConfigManager)
    595                 phone.getContext().getSystemService(Context.CARRIER_CONFIG_SERVICE);
    596         if (configManager == null) {
    597             Rlog.e(LOG_TAG, "Carrier config service is not available");
    598             return true;
    599         }
    600 
    601         PersistableBundle b = configManager.getConfigForSubId(subId);
    602         if (b == null) {
    603             Rlog.e(LOG_TAG, "Can't get the config. subId = " + subId);
    604             return true;
    605         }
    606 
    607         String[] meteredApnTypes = b.getStringArray(carrierConfig);
    608         if (meteredApnTypes == null) {
    609             Rlog.e(LOG_TAG, carrierConfig +  " is not available. " + "subId = " + subId);
    610             return true;
    611         }
    612 
    613         HashSet<String> meteredApnSet = new HashSet<>(Arrays.asList(meteredApnTypes));
    614         if (DBG) {
    615             Rlog.d(LOG_TAG, "For subId = " + subId + ", metered APN types are "
    616                     + Arrays.toString(meteredApnSet.toArray()));
    617         }
    618 
    619         // If all types of APN are metered, then this APN setting must be metered.
    620         if (meteredApnSet.contains(PhoneConstants.APN_TYPE_ALL)) {
    621             if (DBG) Rlog.d(LOG_TAG, "All APN types are metered.");
    622             return true;
    623         }
    624 
    625         if (meteredApnSet.contains(type)) {
    626             if (DBG) Rlog.d(LOG_TAG, type + " is metered.");
    627             return true;
    628         } else if (type.equals(PhoneConstants.APN_TYPE_ALL)) {
    629             // Assuming no configuration error, if at least one APN type is
    630             // metered, then this APN setting is metered.
    631             if (meteredApnSet.size() > 0) {
    632                 if (DBG) Rlog.d(LOG_TAG, "APN_TYPE_ALL APN is metered.");
    633                 return true;
    634             }
    635         }
    636 
    637         if (DBG) Rlog.d(LOG_TAG, type + " is not metered.");
    638         return false;
    639     }
    640 
    641     /**
    642      * Check if this APN setting is metered.
    643      *
    644      * @param phone The phone object
    645      * @return True if this APN setting is metered, otherwise false.
    646      */
    647     public boolean isMetered(Phone phone) {
    648         if (phone == null) {
    649             return true;
    650         }
    651 
    652         for (String type : types) {
    653             // If one of the APN type is metered, then this APN setting is metered.
    654             if (isMeteredApnType(type, phone)) {
    655                 return true;
    656             }
    657         }
    658         return false;
    659     }
    660 
    661     // TODO - if we have this function we should also have hashCode.
    662     // Also should handle changes in type order and perhaps case-insensitivity
    663     @Override
    664     public boolean equals(Object o) {
    665         if (o instanceof ApnSetting == false) {
    666             return false;
    667         }
    668 
    669         ApnSetting other = (ApnSetting) o;
    670 
    671         return carrier.equals(other.carrier)
    672                 && id == other.id
    673                 && numeric.equals(other.numeric)
    674                 && apn.equals(other.apn)
    675                 && proxy.equals(other.proxy)
    676                 && mmsc.equals(other.mmsc)
    677                 && mmsProxy.equals(other.mmsProxy)
    678                 && TextUtils.equals(mmsPort, other.mmsPort)
    679                 && port.equals(other.port)
    680                 && TextUtils.equals(user, other.user)
    681                 && TextUtils.equals(password, other.password)
    682                 && authType == other.authType
    683                 && Arrays.deepEquals(types, other.types)
    684                 && typesBitmap == other.typesBitmap
    685                 && protocol.equals(other.protocol)
    686                 && roamingProtocol.equals(other.roamingProtocol)
    687                 && carrierEnabled == other.carrierEnabled
    688                 && bearer == other.bearer
    689                 && bearerBitmask == other.bearerBitmask
    690                 && profileId == other.profileId
    691                 && modemCognitive == other.modemCognitive
    692                 && maxConns == other.maxConns
    693                 && waitTime == other.waitTime
    694                 && maxConnsTime == other.maxConnsTime
    695                 && mtu == other.mtu
    696                 && mvnoType.equals(other.mvnoType)
    697                 && mvnoMatchData.equals(other.mvnoMatchData)
    698                 && networkTypeBitmask == other.networkTypeBitmask
    699                 && apnSetId == other.apnSetId;
    700     }
    701 
    702     /**
    703      * Compare two APN settings
    704      *
    705      * Note: This method does not compare 'id', 'bearer', 'bearerBitmask', 'networkTypeBitmask'.
    706      * We only use this for determining if tearing a data call is needed when conditions change. See
    707      * cleanUpConnectionsOnUpdatedApns in DcTracker.
    708      *
    709      * @param o the other object to compare
    710      * @param isDataRoaming True if the device is on data roaming
    711      * @return True if the two APN settings are same
    712      */
    713     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
    714     public boolean equals(Object o, boolean isDataRoaming) {
    715         if (!(o instanceof ApnSetting)) {
    716             return false;
    717         }
    718 
    719         ApnSetting other = (ApnSetting) o;
    720 
    721         return carrier.equals(other.carrier)
    722                 && numeric.equals(other.numeric)
    723                 && apn.equals(other.apn)
    724                 && proxy.equals(other.proxy)
    725                 && mmsc.equals(other.mmsc)
    726                 && mmsProxy.equals(other.mmsProxy)
    727                 && TextUtils.equals(mmsPort, other.mmsPort)
    728                 && port.equals(other.port)
    729                 && TextUtils.equals(user, other.user)
    730                 && TextUtils.equals(password, other.password)
    731                 && authType == other.authType
    732                 && Arrays.deepEquals(types, other.types)
    733                 && typesBitmap == other.typesBitmap
    734                 && (isDataRoaming || protocol.equals(other.protocol))
    735                 && (!isDataRoaming || roamingProtocol.equals(other.roamingProtocol))
    736                 && carrierEnabled == other.carrierEnabled
    737                 && profileId == other.profileId
    738                 && modemCognitive == other.modemCognitive
    739                 && maxConns == other.maxConns
    740                 && waitTime == other.waitTime
    741                 && maxConnsTime == other.maxConnsTime
    742                 && mtu == other.mtu
    743                 && mvnoType.equals(other.mvnoType)
    744                 && mvnoMatchData.equals(other.mvnoMatchData)
    745                 && apnSetId == other.apnSetId;
    746     }
    747 
    748     /**
    749      * Check if neither mention DUN and are substantially similar
    750      *
    751      * @param other The other APN settings to compare
    752      * @return True if two APN settings are similar
    753      */
    754     public boolean similar(ApnSetting other) {
    755         return (!this.canHandleType(PhoneConstants.APN_TYPE_DUN)
    756                 && !other.canHandleType(PhoneConstants.APN_TYPE_DUN)
    757                 && Objects.equals(this.apn, other.apn)
    758                 && !typeSameAny(this, other)
    759                 && xorEquals(this.proxy, other.proxy)
    760                 && xorEquals(this.port, other.port)
    761                 && xorEquals(this.protocol, other.protocol)
    762                 && xorEquals(this.roamingProtocol, other.roamingProtocol)
    763                 && this.carrierEnabled == other.carrierEnabled
    764                 && this.bearerBitmask == other.bearerBitmask
    765                 && this.profileId == other.profileId
    766                 && Objects.equals(this.mvnoType, other.mvnoType)
    767                 && Objects.equals(this.mvnoMatchData, other.mvnoMatchData)
    768                 && xorEquals(this.mmsc, other.mmsc)
    769                 && xorEquals(this.mmsProxy, other.mmsProxy)
    770                 && xorEquals(this.mmsPort, other.mmsPort))
    771                 && this.networkTypeBitmask == other.networkTypeBitmask
    772                 && this.apnSetId == other.apnSetId;
    773     }
    774 
    775     // check whether the types of two APN same (even only one type of each APN is same)
    776     private boolean typeSameAny(ApnSetting first, ApnSetting second) {
    777         if (VDBG) {
    778             StringBuilder apnType1 = new StringBuilder(first.apn + ": ");
    779             for (int index1 = 0; index1 < first.types.length; index1++) {
    780                 apnType1.append(first.types[index1]);
    781                 apnType1.append(",");
    782             }
    783 
    784             StringBuilder apnType2 = new StringBuilder(second.apn + ": ");
    785             for (int index1 = 0; index1 < second.types.length; index1++) {
    786                 apnType2.append(second.types[index1]);
    787                 apnType2.append(",");
    788             }
    789             Rlog.d(LOG_TAG, "APN1: is " + apnType1);
    790             Rlog.d(LOG_TAG, "APN2: is " + apnType2);
    791         }
    792 
    793         for (int index1 = 0; index1 < first.types.length; index1++) {
    794             for (int index2 = 0; index2 < second.types.length; index2++) {
    795                 if (first.types[index1].equals(PhoneConstants.APN_TYPE_ALL)
    796                         || second.types[index2].equals(PhoneConstants.APN_TYPE_ALL)
    797                         || first.types[index1].equals(second.types[index2])) {
    798                     if (VDBG) Rlog.d(LOG_TAG, "typeSameAny: return true");
    799                     return true;
    800                 }
    801             }
    802         }
    803 
    804         if (VDBG) Rlog.d(LOG_TAG, "typeSameAny: return false");
    805         return false;
    806     }
    807 
    808     // equal or one is not specified
    809     private boolean xorEquals(String first, String second) {
    810         return (Objects.equals(first, second)
    811                 || TextUtils.isEmpty(first)
    812                 || TextUtils.isEmpty(second));
    813     }
    814 
    815     // Helper function to convert APN string into a 32-bit bitmask.
    816     private static int getApnBitmask(String apn) {
    817         switch (apn) {
    818             case PhoneConstants.APN_TYPE_DEFAULT: return ApnTypes.DEFAULT;
    819             case PhoneConstants.APN_TYPE_MMS: return ApnTypes.MMS;
    820             case PhoneConstants.APN_TYPE_SUPL: return ApnTypes.SUPL;
    821             case PhoneConstants.APN_TYPE_DUN: return ApnTypes.DUN;
    822             case PhoneConstants.APN_TYPE_HIPRI: return ApnTypes.HIPRI;
    823             case PhoneConstants.APN_TYPE_FOTA: return ApnTypes.FOTA;
    824             case PhoneConstants.APN_TYPE_IMS: return ApnTypes.IMS;
    825             case PhoneConstants.APN_TYPE_CBS: return ApnTypes.CBS;
    826             case PhoneConstants.APN_TYPE_IA: return ApnTypes.IA;
    827             case PhoneConstants.APN_TYPE_EMERGENCY: return ApnTypes.EMERGENCY;
    828             case PhoneConstants.APN_TYPE_ALL: return ApnTypes.ALL;
    829             default: return ApnTypes.NONE;
    830         }
    831     }
    832 }
    833