• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.os.PersistableBundle;
21 import android.telephony.CarrierConfigManager;
22 import android.telephony.Rlog;
23 import android.telephony.ServiceState;
24 import android.text.TextUtils;
25 
26 import com.android.internal.telephony.PhoneConstants;
27 import com.android.internal.telephony.RILConstants;
28 import com.android.internal.telephony.uicc.IccRecords;
29 
30 import java.util.ArrayList;
31 import java.util.Arrays;
32 import java.util.HashMap;
33 import java.util.HashSet;
34 import java.util.List;
35 import java.util.Locale;
36 
37 /**
38  * This class represents a apn setting for create PDP link
39  */
40 public class ApnSetting {
41 
42     static final String LOG_TAG = "ApnSetting";
43 
44     private static final boolean DBG = false;
45 
46     static final String V2_FORMAT_REGEX = "^\\[ApnSettingV2\\]\\s*";
47     static final String V3_FORMAT_REGEX = "^\\[ApnSettingV3\\]\\s*";
48 
49     public final String carrier;
50     public final String apn;
51     public final String proxy;
52     public final String port;
53     public final String mmsc;
54     public final String mmsProxy;
55     public final String mmsPort;
56     public final String user;
57     public final String password;
58     public final int authType;
59     public final String[] types;
60     public final int id;
61     public final String numeric;
62     public final String protocol;
63     public final String roamingProtocol;
64     public final int mtu;
65 
66     /**
67       * Current status of APN
68       * true : enabled APN, false : disabled APN.
69       */
70     public final boolean carrierEnabled;
71     /**
72      * Radio Access Technology info
73      * To check what values can hold, refer to ServiceState.java.
74      * This should be spread to other technologies,
75      * but currently only used for LTE(14) and EHRPD(13).
76      */
77     private final int bearer;
78     /**
79       * Radio Access Technology info
80       * To check what values can hold, refer to ServiceState.java. This is a bitmask of radio
81       * technologies in ServiceState.
82       * This should be spread to other technologies,
83       * but currently only used for LTE(14) and EHRPD(13).
84       */
85     public final int bearerBitmask;
86 
87     /* ID of the profile in the modem */
88     public final int profileId;
89     public final boolean modemCognitive;
90     public final int maxConns;
91     public final int waitTime;
92     public final int maxConnsTime;
93 
94     /**
95       * MVNO match type. Possible values:
96       *   "spn": Service provider name.
97       *   "imsi": IMSI.
98       *   "gid": Group identifier level 1.
99       */
100     public final String mvnoType;
101     /**
102       * MVNO data. Examples:
103       *   "spn": A MOBILE, BEN NL
104       *   "imsi": 302720x94, 2060188
105       *   "gid": 4E, 33
106       */
107     public final String mvnoMatchData;
108 
109     /**
110      * Indicates this APN setting is permanently failed and cannot be
111      * retried by the retry manager anymore.
112      * */
113     public boolean permanentFailed = false;
114 
115     /**
116      * Metered APN types which would be accounted for in data usage. This is a map of subId ->
117      * set of metered apn strings for the carrier.
118      */
119     private static HashMap<Integer, HashSet<String>> sMeteredApnTypes = new HashMap<>();
120 
121     /**
122      * Metered Roaming APN types which would be accounted for in data usage. This is a map of
123      * subId -> set of metered roaming apn strings for the carrier.
124      */
125     private static HashMap<Integer, HashSet<String>> sMeteredRoamingApnTypes = new HashMap<>();
126 
ApnSetting(int id, String numeric, String carrier, String apn, String proxy, String port, String mmsc, String mmsProxy, String mmsPort, String user, String password, int authType, String[] types, String protocol, String roamingProtocol, boolean carrierEnabled, int bearer, int bearerBitmask, int profileId, boolean modemCognitive, int maxConns, int waitTime, int maxConnsTime, int mtu, String mvnoType, String mvnoMatchData)127     public ApnSetting(int id, String numeric, String carrier, String apn,
128             String proxy, String port,
129             String mmsc, String mmsProxy, String mmsPort,
130             String user, String password, int authType, String[] types,
131             String protocol, String roamingProtocol, boolean carrierEnabled, int bearer,
132             int bearerBitmask, int profileId, boolean modemCognitive, int maxConns, int waitTime,
133             int maxConnsTime, int mtu, String mvnoType, String mvnoMatchData) {
134         this.id = id;
135         this.numeric = numeric;
136         this.carrier = carrier;
137         this.apn = apn;
138         this.proxy = proxy;
139         this.port = port;
140         this.mmsc = mmsc;
141         this.mmsProxy = mmsProxy;
142         this.mmsPort = mmsPort;
143         this.user = user;
144         this.password = password;
145         this.authType = authType;
146         this.types = new String[types.length];
147         for (int i = 0; i < types.length; i++) {
148             this.types[i] = types[i].toLowerCase(Locale.ROOT);
149         }
150         this.protocol = protocol;
151         this.roamingProtocol = roamingProtocol;
152         this.carrierEnabled = carrierEnabled;
153         this.bearer = bearer;
154         this.bearerBitmask = (bearerBitmask | ServiceState.getBitmaskForTech(bearer));
155         this.profileId = profileId;
156         this.modemCognitive = modemCognitive;
157         this.maxConns = maxConns;
158         this.waitTime = waitTime;
159         this.maxConnsTime = maxConnsTime;
160         this.mtu = mtu;
161         this.mvnoType = mvnoType;
162         this.mvnoMatchData = mvnoMatchData;
163 
164     }
165 
ApnSetting(ApnSetting apn)166     public ApnSetting(ApnSetting apn) {
167         this(apn.id, apn.numeric, apn.carrier, apn.apn, apn.proxy, apn.port, apn.mmsc, apn.mmsProxy,
168                 apn.mmsPort, apn.user, apn.password, apn.authType, apn.types, apn.protocol,
169                 apn.roamingProtocol, apn.carrierEnabled, apn.bearer, apn.bearerBitmask,
170                 apn.profileId, apn.modemCognitive, apn.maxConns, apn.waitTime, apn.maxConnsTime,
171                 apn.mtu, apn.mvnoType, apn.mvnoMatchData);
172     }
173 
174     /**
175      * Creates an ApnSetting object from a string.
176      *
177      * @param data the string to read.
178      *
179      * The string must be in one of two formats (newlines added for clarity,
180      * spaces are optional):
181      *
182      * v1 format:
183      *   <carrier>, <apn>, <proxy>, <port>, <user>, <password>, <server>,
184      *   <mmsc>, <mmsproxy>, <mmsport>, <mcc>, <mnc>, <authtype>,
185      *   <type>[| <type>...],
186      *
187      * v2 format:
188      *   [ApnSettingV2] <carrier>, <apn>, <proxy>, <port>, <user>, <password>, <server>,
189      *   <mmsc>, <mmsproxy>, <mmsport>, <mcc>, <mnc>, <authtype>,
190      *   <type>[| <type>...], <protocol>, <roaming_protocol>, <carrierEnabled>, <bearerBitmask>,
191      *
192      * v3 format:
193      *   [ApnSettingV3] <carrier>, <apn>, <proxy>, <port>, <user>, <password>, <server>,
194      *   <mmsc>, <mmsproxy>, <mmsport>, <mcc>, <mnc>, <authtype>,
195      *   <type>[| <type>...], <protocol>, <roaming_protocol>, <carrierEnabled>, <bearerBitmask>,
196      *   <profileId>, <modemCognitive>, <maxConns>, <waitTime>, <maxConnsTime>, <mtu>,
197      *   <mvnoType>, <mvnoMatchData>
198      *
199      * Note that the strings generated by toString() do not contain the username
200      * and password and thus cannot be read by this method.
201      */
fromString(String data)202     public static ApnSetting fromString(String data) {
203         if (data == null) return null;
204 
205         int version;
206         // matches() operates on the whole string, so append .* to the regex.
207         if (data.matches(V3_FORMAT_REGEX + ".*")) {
208             version = 3;
209             data = data.replaceFirst(V3_FORMAT_REGEX, "");
210         } else if (data.matches(V2_FORMAT_REGEX + ".*")) {
211             version = 2;
212             data = data.replaceFirst(V2_FORMAT_REGEX, "");
213         } else {
214             version = 1;
215         }
216 
217         String[] a = data.split("\\s*,\\s*");
218         if (a.length < 14) {
219             return null;
220         }
221 
222         int authType;
223         try {
224             authType = Integer.parseInt(a[12]);
225         } catch (NumberFormatException e) {
226             authType = 0;
227         }
228 
229         String[] typeArray;
230         String protocol, roamingProtocol;
231         boolean carrierEnabled;
232         int bearerBitmask = 0;
233         int profileId = 0;
234         boolean modemCognitive = false;
235         int maxConns = 0;
236         int waitTime = 0;
237         int maxConnsTime = 0;
238         int mtu = PhoneConstants.UNSET_MTU;
239         String mvnoType = "";
240         String mvnoMatchData = "";
241         if (version == 1) {
242             typeArray = new String[a.length - 13];
243             System.arraycopy(a, 13, typeArray, 0, a.length - 13);
244             protocol = RILConstants.SETUP_DATA_PROTOCOL_IP;
245             roamingProtocol = RILConstants.SETUP_DATA_PROTOCOL_IP;
246             carrierEnabled = true;
247         } else {
248             if (a.length < 18) {
249                 return null;
250             }
251             typeArray = a[13].split("\\s*\\|\\s*");
252             protocol = a[14];
253             roamingProtocol = a[15];
254             carrierEnabled = Boolean.parseBoolean(a[16]);
255 
256             bearerBitmask = ServiceState.getBitmaskFromString(a[17]);
257 
258             if (a.length > 22) {
259                 modemCognitive = Boolean.parseBoolean(a[19]);
260                 try {
261                     profileId = Integer.parseInt(a[18]);
262                     maxConns = Integer.parseInt(a[20]);
263                     waitTime = Integer.parseInt(a[21]);
264                     maxConnsTime = Integer.parseInt(a[22]);
265                 } catch (NumberFormatException e) {
266                 }
267             }
268             if (a.length > 23) {
269                 try {
270                     mtu = Integer.parseInt(a[23]);
271                 } catch (NumberFormatException e) {
272                 }
273             }
274             if (a.length > 25) {
275                 mvnoType = a[24];
276                 mvnoMatchData = a[25];
277             }
278         }
279 
280         return new ApnSetting(-1,a[10]+a[11],a[0],a[1],a[2],a[3],a[7],a[8],
281                 a[9],a[4],a[5],authType,typeArray,protocol,roamingProtocol,carrierEnabled,0,
282                 bearerBitmask, profileId, modemCognitive, maxConns, waitTime, maxConnsTime, mtu,
283                 mvnoType, mvnoMatchData);
284     }
285 
286     /**
287      * Creates an array of ApnSetting objects from a string.
288      *
289      * @param data the string to read.
290      *
291      * Builds on top of the same format used by fromString, but allows for multiple entries
292      * separated by "; ".
293      */
arrayFromString(String data)294     public static List<ApnSetting> arrayFromString(String data) {
295         List<ApnSetting> retVal = new ArrayList<ApnSetting>();
296         if (TextUtils.isEmpty(data)) {
297             return retVal;
298         }
299         String[] apnStrings = data.split("\\s*;\\s*");
300         for (String apnString : apnStrings) {
301             ApnSetting apn = fromString(apnString);
302             if (apn != null) {
303                 retVal.add(apn);
304             }
305         }
306         return retVal;
307     }
308 
309     @Override
toString()310     public String toString() {
311         StringBuilder sb = new StringBuilder();
312         sb.append("[ApnSettingV3] ")
313         .append(carrier)
314         .append(", ").append(id)
315         .append(", ").append(numeric)
316         .append(", ").append(apn)
317         .append(", ").append(proxy)
318         .append(", ").append(mmsc)
319         .append(", ").append(mmsProxy)
320         .append(", ").append(mmsPort)
321         .append(", ").append(port)
322         .append(", ").append(authType).append(", ");
323         for (int i = 0; i < types.length; i++) {
324             sb.append(types[i]);
325             if (i < types.length - 1) {
326                 sb.append(" | ");
327             }
328         }
329         sb.append(", ").append(protocol);
330         sb.append(", ").append(roamingProtocol);
331         sb.append(", ").append(carrierEnabled);
332         sb.append(", ").append(bearer);
333         sb.append(", ").append(bearerBitmask);
334         sb.append(", ").append(profileId);
335         sb.append(", ").append(modemCognitive);
336         sb.append(", ").append(maxConns);
337         sb.append(", ").append(waitTime);
338         sb.append(", ").append(maxConnsTime);
339         sb.append(", ").append(mtu);
340         sb.append(", ").append(mvnoType);
341         sb.append(", ").append(mvnoMatchData);
342         sb.append(", ").append(permanentFailed);
343         return sb.toString();
344     }
345 
346     /**
347      * Returns true if there are MVNO params specified.
348      */
hasMvnoParams()349     public boolean hasMvnoParams() {
350         return !TextUtils.isEmpty(mvnoType) && !TextUtils.isEmpty(mvnoMatchData);
351     }
352 
canHandleType(String type)353     public boolean canHandleType(String type) {
354         if (!carrierEnabled) return false;
355         for (String t : types) {
356             // DEFAULT handles all, and HIPRI is handled by DEFAULT
357             if (t.equalsIgnoreCase(type) ||
358                     t.equalsIgnoreCase(PhoneConstants.APN_TYPE_ALL) ||
359                     (t.equalsIgnoreCase(PhoneConstants.APN_TYPE_DEFAULT) &&
360                     type.equalsIgnoreCase(PhoneConstants.APN_TYPE_HIPRI))) {
361                 return true;
362             }
363         }
364         return false;
365     }
366 
imsiMatches(String imsiDB, String imsiSIM)367     private static boolean imsiMatches(String imsiDB, String imsiSIM) {
368         // Note: imsiDB value has digit number or 'x' character for seperating USIM information
369         // for MVNO operator. And then digit number is matched at same order and 'x' character
370         // could replace by any digit number.
371         // ex) if imsiDB inserted '310260x10xxxxxx' for GG Operator,
372         //     that means first 6 digits, 8th and 9th digit
373         //     should be set in USIM for GG Operator.
374         int len = imsiDB.length();
375         int idxCompare = 0;
376 
377         if (len <= 0) return false;
378         if (len > imsiSIM.length()) return false;
379 
380         for (int idx=0; idx<len; idx++) {
381             char c = imsiDB.charAt(idx);
382             if ((c == 'x') || (c == 'X') || (c == imsiSIM.charAt(idx))) {
383                 continue;
384             } else {
385                 return false;
386             }
387         }
388         return true;
389     }
390 
mvnoMatches(IccRecords r, String mvnoType, String mvnoMatchData)391     public static boolean mvnoMatches(IccRecords r, String mvnoType, String mvnoMatchData) {
392         if (mvnoType.equalsIgnoreCase("spn")) {
393             if ((r.getServiceProviderName() != null) &&
394                     r.getServiceProviderName().equalsIgnoreCase(mvnoMatchData)) {
395                 return true;
396             }
397         } else if (mvnoType.equalsIgnoreCase("imsi")) {
398             String imsiSIM = r.getIMSI();
399             if ((imsiSIM != null) && imsiMatches(mvnoMatchData, imsiSIM)) {
400                 return true;
401             }
402         } else if (mvnoType.equalsIgnoreCase("gid")) {
403             String gid1 = r.getGid1();
404             int mvno_match_data_length = mvnoMatchData.length();
405             if ((gid1 != null) && (gid1.length() >= mvno_match_data_length) &&
406                     gid1.substring(0, mvno_match_data_length).equalsIgnoreCase(mvnoMatchData)) {
407                 return true;
408             }
409         }
410         return false;
411     }
412 
isMeteredApnType(String type, Context context, int subId, boolean isRoaming)413     public static boolean isMeteredApnType(String type, Context context, int subId,
414                                            boolean isRoaming) {
415 
416         HashMap<Integer, HashSet<String>> meteredApnTypesCache = (isRoaming) ?
417                 sMeteredApnTypes : sMeteredRoamingApnTypes;
418         String carrierConfig = (isRoaming) ?
419                 CarrierConfigManager.KEY_CARRIER_METERED_ROAMING_APN_TYPES_STRINGS :
420                 CarrierConfigManager.KEY_CARRIER_METERED_APN_TYPES_STRINGS;
421 
422         synchronized (meteredApnTypesCache) {
423             HashSet<String> meteredApnSet = meteredApnTypesCache.get(subId);
424 
425             // In case of cache miss, we need to look up the settings from carrier config.
426             if (meteredApnSet == null) {
427                 // Retrieve the metered APN types from carrier config
428                 CarrierConfigManager configManager = (CarrierConfigManager)
429                         context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
430                 if (configManager == null) {
431                     Rlog.e(LOG_TAG, "Carrier config service is not available");
432                     return true;
433                 }
434 
435                 PersistableBundle b = configManager.getConfigForSubId(subId);
436                 if (b == null) {
437                     Rlog.e(LOG_TAG, "Can't get the config. subId = " + subId);
438                     return true;
439                 }
440 
441                 String[] meteredApnTypes = b.getStringArray(carrierConfig);
442                 if (meteredApnTypes == null) {
443                     Rlog.e(LOG_TAG, carrierConfig +  " is not available. " + "subId = " + subId);
444                     return true;
445                 }
446 
447                 meteredApnSet = new HashSet<String>(Arrays.asList(meteredApnTypes));
448                 meteredApnTypesCache.put(subId, meteredApnSet);
449                 if (DBG) {
450                     Rlog.d(LOG_TAG, "For subId = " + subId + ", metered APN types are " +
451                             Arrays.toString(meteredApnSet.toArray()) +
452                             " isRoaming: " + isRoaming);
453                 }
454             }
455             // If all types of APN are metered, then this APN setting must be metered.
456             if (meteredApnSet.contains(PhoneConstants.APN_TYPE_ALL)) {
457                 if (DBG) Rlog.d(LOG_TAG, "All APN types are metered. isRoaming: " + isRoaming);
458                 return true;
459             }
460 
461             if (meteredApnSet.contains(type)) {
462                 if (DBG) Rlog.d(LOG_TAG, type + " is metered. isRoaming: " + isRoaming);
463                 return true;
464             } else if (type.equals(PhoneConstants.APN_TYPE_ALL)) {
465                 // Assuming no configuration error, if at least one APN type is
466                 // metered, then this APN setting is metered.
467                 if (meteredApnSet.size() > 0) {
468                     if (DBG) Rlog.d(LOG_TAG, "APN_TYPE_ALL APN is metered. isRoaming: " +
469                             isRoaming);
470                     return true;
471                 }
472             }
473         }
474         if (DBG) Rlog.d(LOG_TAG, type + " is not metered. isRoaming: " + isRoaming);
475         return false;
476     }
477 
isMetered(Context context, int subId, boolean isRoaming )478     public boolean isMetered(Context context, int subId, boolean isRoaming ) {
479         for (String type : types) {
480             // If one of the APN type is metered, then this APN setting is metered.
481             if (isMeteredApnType(type, context, subId, isRoaming)) {
482                 if (DBG) Rlog.d(LOG_TAG, "Metered. APN = " + toString() +
483                         "isRoaming: " + isRoaming);
484                 return true;
485             }
486         }
487         if (DBG) Rlog.d(LOG_TAG, "Not metered. APN = " + toString() + "isRoaming: " + isRoaming);
488         return false;
489     }
490 
491     // TODO - if we have this function we should also have hashCode.
492     // Also should handle changes in type order and perhaps case-insensitivity
493     @Override
equals(Object o)494     public boolean equals(Object o) {
495         if (o instanceof ApnSetting == false) {
496             return false;
497         }
498 
499         ApnSetting other = (ApnSetting) o;
500 
501         return carrier.equals(other.carrier) &&
502                 id == other.id &&
503                 numeric.equals(other.numeric) &&
504                 apn.equals(other.apn) &&
505                 proxy.equals(other.proxy) &&
506                 mmsc.equals(other.mmsc) &&
507                 mmsProxy.equals(other.mmsProxy) &&
508                 port.equals(other.port) &&
509                 authType == other.authType &&
510                 Arrays.deepEquals(types, other.types) &&
511                 protocol.equals(other.protocol) &&
512                 roamingProtocol.equals(other.roamingProtocol) &&
513                 carrierEnabled == other.carrierEnabled &&
514                 bearer == other.bearer &&
515                 bearerBitmask == other.bearerBitmask &&
516                 profileId == other.profileId &&
517                 modemCognitive == other.modemCognitive &&
518                 maxConns == other.maxConns &&
519                 waitTime == other.waitTime &&
520                 maxConnsTime == other.maxConnsTime &&
521                 mtu == other.mtu &&
522                 mvnoType.equals(other.mvnoType) &&
523                 mvnoMatchData.equals(other.mvnoMatchData);
524     }
525 }
526