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.telephony.ServiceState;
     20 import android.text.TextUtils;
     21 
     22 import com.android.internal.telephony.PhoneConstants;
     23 import com.android.internal.telephony.RILConstants;
     24 import com.android.internal.telephony.uicc.IccRecords;
     25 
     26 import java.util.ArrayList;
     27 import java.util.List;
     28 import java.util.Locale;
     29 
     30 /**
     31  * This class represents a apn setting for create PDP link
     32  */
     33 public class ApnSetting {
     34 
     35     static final String V2_FORMAT_REGEX = "^\\[ApnSettingV2\\]\\s*";
     36     static final String V3_FORMAT_REGEX = "^\\[ApnSettingV3\\]\\s*";
     37 
     38     public final String carrier;
     39     public final String apn;
     40     public final String proxy;
     41     public final String port;
     42     public final String mmsc;
     43     public final String mmsProxy;
     44     public final String mmsPort;
     45     public final String user;
     46     public final String password;
     47     public final int authType;
     48     public final String[] types;
     49     public final int id;
     50     public final String numeric;
     51     public final String protocol;
     52     public final String roamingProtocol;
     53     public final int mtu;
     54 
     55     /**
     56       * Current status of APN
     57       * true : enabled APN, false : disabled APN.
     58       */
     59     public final boolean carrierEnabled;
     60     /**
     61      * Radio Access Technology info
     62      * To check what values can hold, refer to ServiceState.java.
     63      * This should be spread to other technologies,
     64      * but currently only used for LTE(14) and EHRPD(13).
     65      */
     66     private final int bearer;
     67     /**
     68       * Radio Access Technology info
     69       * To check what values can hold, refer to ServiceState.java. This is a bitmask of radio
     70       * technologies in ServiceState.
     71       * This should be spread to other technologies,
     72       * but currently only used for LTE(14) and EHRPD(13).
     73       */
     74     public final int bearerBitmask;
     75 
     76     /* ID of the profile in the modem */
     77     public final int profileId;
     78     public final boolean modemCognitive;
     79     public final int maxConns;
     80     public final int waitTime;
     81     public final int maxConnsTime;
     82 
     83     /**
     84       * MVNO match type. Possible values:
     85       *   "spn": Service provider name.
     86       *   "imsi": IMSI.
     87       *   "gid": Group identifier level 1.
     88       */
     89     public final String mvnoType;
     90     /**
     91       * MVNO data. Examples:
     92       *   "spn": A MOBILE, BEN NL
     93       *   "imsi": 302720x94, 2060188
     94       *   "gid": 4E, 33
     95       */
     96     public final String mvnoMatchData;
     97 
     98     public ApnSetting(int id, String numeric, String carrier, String apn,
     99             String proxy, String port,
    100             String mmsc, String mmsProxy, String mmsPort,
    101             String user, String password, int authType, String[] types,
    102             String protocol, String roamingProtocol, boolean carrierEnabled, int bearer,
    103             int bearerBitmask, int profileId, boolean modemCognitive, int maxConns, int waitTime,
    104             int maxConnsTime, int mtu, String mvnoType, String mvnoMatchData) {
    105         this.id = id;
    106         this.numeric = numeric;
    107         this.carrier = carrier;
    108         this.apn = apn;
    109         this.proxy = proxy;
    110         this.port = port;
    111         this.mmsc = mmsc;
    112         this.mmsProxy = mmsProxy;
    113         this.mmsPort = mmsPort;
    114         this.user = user;
    115         this.password = password;
    116         this.authType = authType;
    117         this.types = new String[types.length];
    118         for (int i = 0; i < types.length; i++) {
    119             this.types[i] = types[i].toLowerCase(Locale.ROOT);
    120         }
    121         this.protocol = protocol;
    122         this.roamingProtocol = roamingProtocol;
    123         this.carrierEnabled = carrierEnabled;
    124         this.bearer = bearer;
    125         this.bearerBitmask = (bearerBitmask | ServiceState.getBitmaskForTech(bearer));
    126         this.profileId = profileId;
    127         this.modemCognitive = modemCognitive;
    128         this.maxConns = maxConns;
    129         this.waitTime = waitTime;
    130         this.maxConnsTime = maxConnsTime;
    131         this.mtu = mtu;
    132         this.mvnoType = mvnoType;
    133         this.mvnoMatchData = mvnoMatchData;
    134 
    135     }
    136 
    137     /**
    138      * Creates an ApnSetting object from a string.
    139      *
    140      * @param data the string to read.
    141      *
    142      * The string must be in one of two formats (newlines added for clarity,
    143      * spaces are optional):
    144      *
    145      * v1 format:
    146      *   <carrier>, <apn>, <proxy>, <port>, <user>, <password>, <server>,
    147      *   <mmsc>, <mmsproxy>, <mmsport>, <mcc>, <mnc>, <authtype>,
    148      *   <type>[| <type>...],
    149      *
    150      * v2 format:
    151      *   [ApnSettingV2] <carrier>, <apn>, <proxy>, <port>, <user>, <password>, <server>,
    152      *   <mmsc>, <mmsproxy>, <mmsport>, <mcc>, <mnc>, <authtype>,
    153      *   <type>[| <type>...], <protocol>, <roaming_protocol>, <carrierEnabled>, <bearerBitmask>,
    154      *
    155      * v3 format:
    156      *   [ApnSettingV3] <carrier>, <apn>, <proxy>, <port>, <user>, <password>, <server>,
    157      *   <mmsc>, <mmsproxy>, <mmsport>, <mcc>, <mnc>, <authtype>,
    158      *   <type>[| <type>...], <protocol>, <roaming_protocol>, <carrierEnabled>, <bearerBitmask>,
    159      *   <profileId>, <modemCognitive>, <maxConns>, <waitTime>, <maxConnsTime>, <mtu>,
    160      *   <mvnoType>, <mvnoMatchData>
    161      *
    162      * Note that the strings generated by toString() do not contain the username
    163      * and password and thus cannot be read by this method.
    164      */
    165     public static ApnSetting fromString(String data) {
    166         if (data == null) return null;
    167 
    168         int version;
    169         // matches() operates on the whole string, so append .* to the regex.
    170         if (data.matches(V3_FORMAT_REGEX + ".*")) {
    171             version = 3;
    172             data = data.replaceFirst(V3_FORMAT_REGEX, "");
    173         } else if (data.matches(V2_FORMAT_REGEX + ".*")) {
    174             version = 2;
    175             data = data.replaceFirst(V2_FORMAT_REGEX, "");
    176         } else {
    177             version = 1;
    178         }
    179 
    180         String[] a = data.split("\\s*,\\s*");
    181         if (a.length < 14) {
    182             return null;
    183         }
    184 
    185         int authType;
    186         try {
    187             authType = Integer.parseInt(a[12]);
    188         } catch (NumberFormatException e) {
    189             authType = 0;
    190         }
    191 
    192         String[] typeArray;
    193         String protocol, roamingProtocol;
    194         boolean carrierEnabled;
    195         int bearerBitmask = 0;
    196         int profileId = 0;
    197         boolean modemCognitive = false;
    198         int maxConns = 0;
    199         int waitTime = 0;
    200         int maxConnsTime = 0;
    201         int mtu = PhoneConstants.UNSET_MTU;
    202         String mvnoType = "";
    203         String mvnoMatchData = "";
    204         if (version == 1) {
    205             typeArray = new String[a.length - 13];
    206             System.arraycopy(a, 13, typeArray, 0, a.length - 13);
    207             protocol = RILConstants.SETUP_DATA_PROTOCOL_IP;
    208             roamingProtocol = RILConstants.SETUP_DATA_PROTOCOL_IP;
    209             carrierEnabled = true;
    210         } else {
    211             if (a.length < 18) {
    212                 return null;
    213             }
    214             typeArray = a[13].split("\\s*\\|\\s*");
    215             protocol = a[14];
    216             roamingProtocol = a[15];
    217             carrierEnabled = Boolean.parseBoolean(a[16]);
    218 
    219             bearerBitmask = ServiceState.getBitmaskFromString(a[17]);
    220 
    221             if (a.length > 22) {
    222                 modemCognitive = Boolean.parseBoolean(a[19]);
    223                 try {
    224                     profileId = Integer.parseInt(a[18]);
    225                     maxConns = Integer.parseInt(a[20]);
    226                     waitTime = Integer.parseInt(a[21]);
    227                     maxConnsTime = Integer.parseInt(a[22]);
    228                 } catch (NumberFormatException e) {
    229                 }
    230             }
    231             if (a.length > 23) {
    232                 try {
    233                     mtu = Integer.parseInt(a[23]);
    234                 } catch (NumberFormatException e) {
    235                 }
    236             }
    237             if (a.length > 25) {
    238                 mvnoType = a[24];
    239                 mvnoMatchData = a[25];
    240             }
    241         }
    242 
    243         return new ApnSetting(-1,a[10]+a[11],a[0],a[1],a[2],a[3],a[7],a[8],
    244                 a[9],a[4],a[5],authType,typeArray,protocol,roamingProtocol,carrierEnabled,0,
    245                 bearerBitmask, profileId, modemCognitive, maxConns, waitTime, maxConnsTime, mtu,
    246                 mvnoType, mvnoMatchData);
    247     }
    248 
    249     /**
    250      * Creates an array of ApnSetting objects from a string.
    251      *
    252      * @param data the string to read.
    253      *
    254      * Builds on top of the same format used by fromString, but allows for multiple entries
    255      * separated by "; ".
    256      */
    257     public static List<ApnSetting> arrayFromString(String data) {
    258         List<ApnSetting> retVal = new ArrayList<ApnSetting>();
    259         if (TextUtils.isEmpty(data)) {
    260             return retVal;
    261         }
    262         String[] apnStrings = data.split("\\s*;\\s*");
    263         for (String apnString : apnStrings) {
    264             ApnSetting apn = fromString(apnString);
    265             if (apn != null) {
    266                 retVal.add(apn);
    267             }
    268         }
    269         return retVal;
    270     }
    271 
    272     @Override
    273     public String toString() {
    274         StringBuilder sb = new StringBuilder();
    275         sb.append("[ApnSettingV3] ")
    276         .append(carrier)
    277         .append(", ").append(id)
    278         .append(", ").append(numeric)
    279         .append(", ").append(apn)
    280         .append(", ").append(proxy)
    281         .append(", ").append(mmsc)
    282         .append(", ").append(mmsProxy)
    283         .append(", ").append(mmsPort)
    284         .append(", ").append(port)
    285         .append(", ").append(authType).append(", ");
    286         for (int i = 0; i < types.length; i++) {
    287             sb.append(types[i]);
    288             if (i < types.length - 1) {
    289                 sb.append(" | ");
    290             }
    291         }
    292         sb.append(", ").append(protocol);
    293         sb.append(", ").append(roamingProtocol);
    294         sb.append(", ").append(carrierEnabled);
    295         sb.append(", ").append(bearer);
    296         sb.append(", ").append(bearerBitmask);
    297         sb.append(", ").append(profileId);
    298         sb.append(", ").append(modemCognitive);
    299         sb.append(", ").append(maxConns);
    300         sb.append(", ").append(waitTime);
    301         sb.append(", ").append(maxConnsTime);
    302         sb.append(", ").append(mtu);
    303         sb.append(", ").append(mvnoType);
    304         sb.append(", ").append(mvnoMatchData);
    305         return sb.toString();
    306     }
    307 
    308     /**
    309      * Returns true if there are MVNO params specified.
    310      */
    311     public boolean hasMvnoParams() {
    312         return !TextUtils.isEmpty(mvnoType) && !TextUtils.isEmpty(mvnoMatchData);
    313     }
    314 
    315     public boolean canHandleType(String type) {
    316         if (!carrierEnabled) return false;
    317         for (String t : types) {
    318             // DEFAULT handles all, and HIPRI is handled by DEFAULT
    319             if (t.equalsIgnoreCase(type) ||
    320                     t.equalsIgnoreCase(PhoneConstants.APN_TYPE_ALL) ||
    321                     (t.equalsIgnoreCase(PhoneConstants.APN_TYPE_DEFAULT) &&
    322                     type.equalsIgnoreCase(PhoneConstants.APN_TYPE_HIPRI))) {
    323                 return true;
    324             }
    325         }
    326         return false;
    327     }
    328 
    329     private static boolean imsiMatches(String imsiDB, String imsiSIM) {
    330         // Note: imsiDB value has digit number or 'x' character for seperating USIM information
    331         // for MVNO operator. And then digit number is matched at same order and 'x' character
    332         // could replace by any digit number.
    333         // ex) if imsiDB inserted '310260x10xxxxxx' for GG Operator,
    334         //     that means first 6 digits, 8th and 9th digit
    335         //     should be set in USIM for GG Operator.
    336         int len = imsiDB.length();
    337         int idxCompare = 0;
    338 
    339         if (len <= 0) return false;
    340         if (len > imsiSIM.length()) return false;
    341 
    342         for (int idx=0; idx<len; idx++) {
    343             char c = imsiDB.charAt(idx);
    344             if ((c == 'x') || (c == 'X') || (c == imsiSIM.charAt(idx))) {
    345                 continue;
    346             } else {
    347                 return false;
    348             }
    349         }
    350         return true;
    351     }
    352 
    353     public static boolean mvnoMatches(IccRecords r, String mvnoType, String mvnoMatchData) {
    354         if (mvnoType.equalsIgnoreCase("spn")) {
    355             if ((r.getServiceProviderName() != null) &&
    356                     r.getServiceProviderName().equalsIgnoreCase(mvnoMatchData)) {
    357                 return true;
    358             }
    359         } else if (mvnoType.equalsIgnoreCase("imsi")) {
    360             String imsiSIM = r.getIMSI();
    361             if ((imsiSIM != null) && imsiMatches(mvnoMatchData, imsiSIM)) {
    362                 return true;
    363             }
    364         } else if (mvnoType.equalsIgnoreCase("gid")) {
    365             String gid1 = r.getGid1();
    366             int mvno_match_data_length = mvnoMatchData.length();
    367             if ((gid1 != null) && (gid1.length() >= mvno_match_data_length) &&
    368                     gid1.substring(0, mvno_match_data_length).equalsIgnoreCase(mvnoMatchData)) {
    369                 return true;
    370             }
    371         }
    372         return false;
    373     }
    374 
    375     // TODO - if we have this function we should also have hashCode.
    376     // Also should handle changes in type order and perhaps case-insensitivity
    377     @Override
    378     public boolean equals(Object o) {
    379         if (o instanceof ApnSetting == false) return false;
    380         return (toString().equals(o.toString()));
    381     }
    382 }
    383