Home | History | Annotate | Download | only in service
      1 /*
      2  * Copyright (C) 2014 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.mms.service;
     18 
     19 import android.content.Context;
     20 import android.content.res.XmlResourceParser;
     21 import android.os.Bundle;
     22 import android.telephony.SubscriptionManager;
     23 import android.telephony.TelephonyManager;
     24 import android.text.TextUtils;
     25 import android.util.Base64;
     26 import android.util.Log;
     27 
     28 import java.io.UnsupportedEncodingException;
     29 import java.util.Iterator;
     30 import java.util.Map;
     31 import java.util.concurrent.ConcurrentHashMap;
     32 
     33 /**
     34  * This class manages a cached copy of current MMS configuration key values
     35  *
     36  * The steps to add a key
     37  * 1. Add a String constant for the key
     38  * 2. Add a default value for the key by putting a typed value to DEFAULTS
     39  *    (null means String type only)
     40  * 3. Add a getter for the key
     41  * 4. Add key/value for relevant mms_config.xml of a specific carrier (mcc/mnc)
     42  */
     43 public class MmsConfig {
     44     private static final String TAG = MmsService.TAG;
     45 
     46     private static final String DEFAULT_HTTP_KEY_X_WAP_PROFILE = "x-wap-profile";
     47 
     48     private static final int MAX_IMAGE_HEIGHT = 480;
     49     private static final int MAX_IMAGE_WIDTH = 640;
     50     private static final int MAX_TEXT_LENGTH = 2000;
     51 
     52     /*
     53      * MmsConfig keys. These have to stay in sync with the MMS_CONFIG_* values defined in
     54      * SmsManager.
     55      */
     56     public static final String CONFIG_ENABLED_MMS = "enabledMMS";
     57     // In case of single segment wap push message, this CONFIG_ENABLED_TRANS_ID indicates whether
     58     // TransactionID should be appended to URI or not.
     59     public static final String CONFIG_ENABLED_TRANS_ID = "enabledTransID";
     60     public static final String CONFIG_ENABLED_NOTIFY_WAP_MMSC = "enabledNotifyWapMMSC";
     61     public static final String CONFIG_ALIAS_ENABLED = "aliasEnabled";
     62     public static final String CONFIG_ALLOW_ATTACH_AUDIO = "allowAttachAudio";
     63     // If CONFIG_ENABLE_MULTIPART_SMS is true, long sms messages are always sent as multi-part sms
     64     // messages, with no checked limit on the number of segments.
     65     // If CONFIG_ENABLE_MULTIPART_SMS is false, then as soon as the user types a message longer
     66     // than a single segment (i.e. 140 chars), then the message will turn into and be sent
     67     // as an mms message or separate, independent SMS messages
     68     // (which is dependent on CONFIG_SEND_MULTIPART_SMS_AS_SEPARATE_MESSAGES flag).
     69     // This feature exists for carriers that don't support multi-part sms's.
     70     public static final String CONFIG_ENABLE_MULTIPART_SMS = "enableMultipartSMS";
     71     public static final String CONFIG_ENABLE_SMS_DELIVERY_REPORTS = "enableSMSDeliveryReports";
     72     // If CONFIG_ENABLE_GROUP_MMS is true, a message with multiple recipients,
     73     // regardless of contents, will be sent as a single MMS message with multiple "TO" fields set
     74     // for each recipient.
     75     // If CONFIG_ENABLE_GROUP_MMS is false, the group MMS setting/preference will be hidden
     76     // in the settings activity.
     77     public static final String CONFIG_ENABLE_GROUP_MMS = "enableGroupMms";
     78     // If this is true, then we should read the content_disposition field of an MMS part
     79     // Check wap-230-wsp-20010705-a.pdf, chapter 8.4.2.21
     80     // Most carriers support it except Sprint.
     81     // There is a system resource defining it:
     82     // com.android.internal.R.bool.config_mms_content_disposition_support.
     83     // But Shem can not read it. Add here so that we can configure for different carriers.
     84     public static final String CONFIG_SUPPORT_MMS_CONTENT_DISPOSITION =
     85             "supportMmsContentDisposition";
     86     // if true, show the cell broadcast (amber alert) in the SMS settings. Some carriers
     87     // don't want this shown.
     88     public static final String CONFIG_CELL_BROADCAST_APP_LINKS = "config_cellBroadcastAppLinks";
     89     // If this is true, we will send multipart SMS as separate SMS messages
     90     public static final String CONFIG_SEND_MULTIPART_SMS_AS_SEPARATE_MESSAGES =
     91             "sendMultipartSmsAsSeparateMessages";
     92     // FLAG(ywen): the following two is not supported yet.
     93     public static final String CONFIG_ENABLE_MMS_READ_REPORTS = "enableMMSReadReports";
     94     public static final String CONFIG_ENABLE_MMS_DELIVERY_REPORTS = "enableMMSDeliveryReports";
     95     // Bouygues Telecom (20820) MMSC does not support "charset" with "Content-Type" header
     96     // It would fail and return 500. See b/18604507
     97     // If this is false, then we don't add "charset" to "Content-Type"
     98     public static final String CONFIG_SUPPORT_HTTP_CHARSET_HEADER = "supportHttpCharsetHeader";
     99     public static final String CONFIG_MAX_MESSAGE_SIZE = "maxMessageSize"; // in bytes
    100     public static final String CONFIG_MAX_IMAGE_HEIGHT = "maxImageHeight"; // in pixels
    101     public static final String CONFIG_MAX_IMAGE_WIDTH = "maxImageWidth"; // in pixels
    102     public static final String CONFIG_RECIPIENT_LIMIT = "recipientLimit";
    103     public static final String CONFIG_HTTP_SOCKET_TIMEOUT = "httpSocketTimeout";
    104     public static final String CONFIG_ALIAS_MIN_CHARS = "aliasMinChars";
    105     public static final String CONFIG_ALIAS_MAX_CHARS = "aliasMaxChars";
    106     // If CONFIG_ENABLE_MULTIPART_SMS is true and CONFIG_SMS_TO_MMS_TEXT_THRESHOLD > 1,
    107     // then multi-part SMS messages will be converted into a single mms message.
    108     // For example, if the mms_config.xml file specifies <int name="smsToMmsTextThreshold">4</int>,
    109     // then on the 5th sms segment, the message will be converted to an mms.
    110     public static final String CONFIG_SMS_TO_MMS_TEXT_THRESHOLD = "smsToMmsTextThreshold";
    111     // LGU+ temporarily requires any SMS message longer than 80 bytes to be sent as MMS
    112     // see b/12122333
    113     public static final String CONFIG_SMS_TO_MMS_TEXT_LENGTH_THRESHOLD =
    114             "smsToMmsTextLengthThreshold";
    115     public static final String CONFIG_MAX_MESSAGE_TEXT_SIZE = "maxMessageTextSize";
    116     // maximum number of characters allowed for mms subject
    117     public static final String CONFIG_MAX_SUBJECT_LENGTH = "maxSubjectLength";
    118     public static final String CONFIG_UA_PROF_TAG_NAME = "uaProfTagName";
    119     public static final String CONFIG_USER_AGENT = "userAgent";
    120     public static final String CONFIG_UA_PROF_URL = "uaProfUrl";
    121     public static final String CONFIG_HTTP_PARAMS = "httpParams";
    122     // Email gateway alias support, including the master switch and different rules
    123     public static final String CONFIG_EMAIL_GATEWAY_NUMBER = "emailGatewayNumber";
    124     // String to append to the NAI header, e.g. ":pcs"
    125     public static final String CONFIG_NAI_SUFFIX = "naiSuffix";
    126 
    127     /*
    128      * Key types
    129      */
    130     public static final String KEY_TYPE_INT = "int";
    131     public static final String KEY_TYPE_BOOL = "bool";
    132     public static final String KEY_TYPE_STRING = "string";
    133 
    134     /*
    135      * Macro names
    136      */
    137     // The raw phone number from TelephonyManager.getLine1Number
    138     public static final String MACRO_LINE1 = "LINE1";
    139     // The phone number without country code
    140     public static final String MACRO_LINE1NOCOUNTRYCODE = "LINE1NOCOUNTRYCODE";
    141     // NAI (Network Access Identifier), used by Sprint for authentication
    142     public static final String MACRO_NAI = "NAI";
    143 
    144     // Default values. This is read-only. Don't write into it.
    145     // This provides the info on valid keys, their types and default values
    146     private static final Map<String, Object> DEFAULTS = new ConcurrentHashMap<String, Object>();
    147     static {
    148         DEFAULTS.put(CONFIG_ENABLED_MMS, Boolean.valueOf(true));
    149         DEFAULTS.put(CONFIG_ENABLED_TRANS_ID, Boolean.valueOf(false));
    150         DEFAULTS.put(CONFIG_ENABLED_NOTIFY_WAP_MMSC, Boolean.valueOf(false));
    151         DEFAULTS.put(CONFIG_ALIAS_ENABLED, Boolean.valueOf(false));
    152         DEFAULTS.put(CONFIG_ALLOW_ATTACH_AUDIO, Boolean.valueOf(true));
    153         DEFAULTS.put(CONFIG_ENABLE_MULTIPART_SMS, Boolean.valueOf(true));
    154         DEFAULTS.put(CONFIG_ENABLE_SMS_DELIVERY_REPORTS, Boolean.valueOf(true));
    155         DEFAULTS.put(CONFIG_ENABLE_GROUP_MMS, Boolean.valueOf(true));
    156         DEFAULTS.put(CONFIG_SUPPORT_MMS_CONTENT_DISPOSITION, Boolean.valueOf(true));
    157         DEFAULTS.put(CONFIG_CELL_BROADCAST_APP_LINKS, Boolean.valueOf(true));
    158         DEFAULTS.put(CONFIG_SEND_MULTIPART_SMS_AS_SEPARATE_MESSAGES, Boolean.valueOf(false));
    159         DEFAULTS.put(CONFIG_ENABLE_MMS_READ_REPORTS, Boolean.valueOf(false));
    160         DEFAULTS.put(CONFIG_ENABLE_MMS_DELIVERY_REPORTS, Boolean.valueOf(false));
    161         DEFAULTS.put(CONFIG_SUPPORT_HTTP_CHARSET_HEADER, Boolean.valueOf(false));
    162         DEFAULTS.put(CONFIG_MAX_MESSAGE_SIZE, Integer.valueOf(300 * 1024));
    163         DEFAULTS.put(CONFIG_MAX_IMAGE_HEIGHT, Integer.valueOf(MAX_IMAGE_HEIGHT));
    164         DEFAULTS.put(CONFIG_MAX_IMAGE_WIDTH, Integer.valueOf(MAX_IMAGE_WIDTH));
    165         DEFAULTS.put(CONFIG_RECIPIENT_LIMIT, Integer.valueOf(Integer.MAX_VALUE));
    166         DEFAULTS.put(CONFIG_HTTP_SOCKET_TIMEOUT, Integer.valueOf(60 * 1000));
    167         DEFAULTS.put(CONFIG_ALIAS_MIN_CHARS, Integer.valueOf(2));
    168         DEFAULTS.put(CONFIG_ALIAS_MAX_CHARS, Integer.valueOf(48));
    169         DEFAULTS.put(CONFIG_SMS_TO_MMS_TEXT_THRESHOLD, Integer.valueOf(-1));
    170         DEFAULTS.put(CONFIG_SMS_TO_MMS_TEXT_LENGTH_THRESHOLD, Integer.valueOf(-1));
    171         DEFAULTS.put(CONFIG_MAX_MESSAGE_TEXT_SIZE, Integer.valueOf(-1));
    172         DEFAULTS.put(CONFIG_MAX_SUBJECT_LENGTH, Integer.valueOf(40));
    173         DEFAULTS.put(CONFIG_UA_PROF_TAG_NAME, DEFAULT_HTTP_KEY_X_WAP_PROFILE);
    174         DEFAULTS.put(CONFIG_USER_AGENT, "");
    175         DEFAULTS.put(CONFIG_UA_PROF_URL, "");
    176         DEFAULTS.put(CONFIG_HTTP_PARAMS, "");
    177         DEFAULTS.put(CONFIG_EMAIL_GATEWAY_NUMBER, "");
    178         DEFAULTS.put(CONFIG_NAI_SUFFIX, "");
    179     }
    180 
    181     private final int mSubId;
    182 
    183     /**
    184      * This class manages a cached copy of current MMS configuration key values for a particular
    185      * subscription id. (See the {@link android.telephony.SubscriptionManager}).
    186      *
    187      * @param context Context of the particular subscription to load. The context's mcc/mnc
    188      * should be set to that of the subscription id
    189      * @param subId Subscription id of the mcc/mnc in the context
    190      */
    191     public MmsConfig(Context context, int subId) {
    192         mSubId = subId;
    193         // Load defaults
    194         mKeyValues.clear();
    195         mKeyValues.putAll(DEFAULTS);
    196         // Load User-Agent and UA profile URL settings
    197         loadDeviceUaSettings(context);
    198         Log.v(TAG, "MmsConfig: mUserAgent=" + mUserAgent + ", mUaProfUrl=" + mUaProfUrl);
    199         // Load mms_config.xml resource overlays
    200         loadFromResources(context);
    201         Log.v(TAG, "MmsConfig: all settings -- " + mKeyValues);
    202     }
    203 
    204     /**
    205      * Return the subscription ID associated with this MmsConfig
    206      *
    207      * @return subId the subId associated with this MmsConfig
    208      */
    209     public int getSubId() {
    210         return mSubId;
    211     }
    212 
    213     /**
    214      * Check a key and its type match the predefined keys and corresponding types
    215      *
    216      * @param key
    217      * @param type Including "int" "bool" and "string"
    218      * @return True if key and type both matches and false otherwise
    219      */
    220     public static boolean isValidKey(String key, String type) {
    221         if (!TextUtils.isEmpty(key) && DEFAULTS.containsKey(key)) {
    222             Object defVal = DEFAULTS.get(key);
    223             Class<?> valueType = defVal != null ? defVal.getClass() : String.class;
    224             if (KEY_TYPE_INT.equals(type)) {
    225                 return valueType == Integer.class;
    226             } else if (KEY_TYPE_BOOL.equals(type)) {
    227                 return valueType == Boolean.class;
    228             } else if (KEY_TYPE_STRING.equals(type)) {
    229                 return valueType == String.class;
    230             }
    231         }
    232         return false;
    233     }
    234 
    235     /**
    236      * Check a key and its type match the predefined keys and corresponding types
    237      *
    238      * @param key The key of the config
    239      * @param value The value of the config
    240      * @return True if key and type both matches and false otherwise
    241      */
    242     public static boolean isValidValue(String key, Object value) {
    243         if (!TextUtils.isEmpty(key) && DEFAULTS.containsKey(key)) {
    244             Object defVal = DEFAULTS.get(key);
    245             Class<?> valueType = defVal != null ? defVal.getClass() : String.class;
    246             return value.getClass().equals(valueType);
    247         }
    248         return false;
    249     }
    250 
    251     private String mUserAgent = null;
    252     private String mUaProfUrl = null;
    253 
    254     // The current values
    255     private final Map<String, Object> mKeyValues = new ConcurrentHashMap<String, Object>();
    256 
    257     /**
    258      * Get a config value by its type
    259      *
    260      * @param key The key of the config
    261      * @param type The type of the config value
    262      * @return The expected typed value or null if no match
    263      */
    264     public Object getValueAsType(String key, String type) {
    265         if (isValidKey(key, type)) {
    266             return mKeyValues.get(key);
    267         }
    268         return null;
    269     }
    270 
    271     public Bundle getCarrierConfigValues() {
    272         final Bundle bundle = new Bundle();
    273         final Iterator<Map.Entry<String, Object>> iter = mKeyValues.entrySet().iterator();
    274         while(iter.hasNext()) {
    275             final Map.Entry<String, Object> entry = iter.next();
    276             final String key = entry.getKey();
    277             final Object val = entry.getValue();
    278             Class<?> valueType =  val != null ? val.getClass() : String.class;
    279             if (valueType == Integer.class) {
    280                 bundle.putInt(key, (Integer)val);
    281             } else if (valueType == Boolean.class) {
    282                 bundle.putBoolean(key, (Boolean)val);
    283             } else if (valueType == String.class) {
    284                 bundle.putString(key, (String)val);
    285             }
    286         }
    287         return bundle;
    288     }
    289 
    290     private String getNullableStringValue(String key) {
    291         final Object value = mKeyValues.get(key);
    292         if (value != null) {
    293             return (String) value;
    294         }
    295         return null;
    296     }
    297 
    298     private void update(String key, String value, String type) {
    299         try {
    300             if (KEY_TYPE_INT.equals(type)) {
    301                 mKeyValues.put(key, Integer.parseInt(value));
    302             } else if (KEY_TYPE_BOOL.equals(type)) {
    303                 mKeyValues.put(key, Boolean.parseBoolean(value));
    304             } else if (KEY_TYPE_STRING.equals(type)){
    305                 mKeyValues.put(key, value);
    306             }
    307         } catch (NumberFormatException e) {
    308             Log.e(TAG, "MmsConfig.update: invalid " + key + "," + value + "," + type);
    309         }
    310     }
    311 
    312     private void loadDeviceUaSettings(Context context) {
    313         // load the MMS User agent and UaProfUrl from TelephonyManager APIs
    314         final TelephonyManager telephonyManager =
    315                 (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
    316         mUserAgent = telephonyManager.getMmsUserAgent();
    317         mUaProfUrl = telephonyManager.getMmsUAProfUrl();
    318     }
    319 
    320     private void loadFromResources(Context context) {
    321         Log.d(TAG, "MmsConfig.loadFromResources");
    322         final XmlResourceParser parser = context.getResources().getXml(R.xml.mms_config);
    323         final MmsConfigXmlProcessor processor = MmsConfigXmlProcessor.get(parser);
    324         processor.setMmsConfigHandler(new MmsConfigXmlProcessor.MmsConfigHandler() {
    325             @Override
    326             public void process(String key, String value, String type) {
    327                 update(key, value, type);
    328             }
    329         });
    330         try {
    331             processor.process();
    332         } finally {
    333             parser.close();
    334         }
    335     }
    336 
    337     /**
    338      * This class returns corresponding MmsConfig values which can be overridden by
    339      * externally provided values.
    340      */
    341     public static class Overridden {
    342         // The base MmsConfig
    343         private final MmsConfig mBase;
    344         // The overridden values
    345         private final Bundle mOverrides;
    346 
    347         public Overridden(MmsConfig base, Bundle overrides) {
    348             mBase = base;
    349             mOverrides = overrides;
    350         }
    351 
    352         private int getInt(String key) {
    353             final Integer def = (Integer) mBase.mKeyValues.get(key);
    354             return mOverrides != null ? mOverrides.getInt(key, def) : def;
    355         }
    356 
    357         private boolean getBoolean(String key) {
    358             final Boolean def = (Boolean) mBase.mKeyValues.get(key);
    359             return mOverrides != null ? mOverrides.getBoolean(key, def) : def;
    360         }
    361 
    362         private String getString(String key) {
    363             if (mOverrides != null && mOverrides.containsKey(key)) {
    364                 return mOverrides.getString(key);
    365             }
    366             return mBase.getNullableStringValue(key);
    367         }
    368 
    369         public int getSmsToMmsTextThreshold() {
    370             return getInt(CONFIG_SMS_TO_MMS_TEXT_THRESHOLD);
    371         }
    372 
    373         public int getSmsToMmsTextLengthThreshold() {
    374             return getInt(CONFIG_SMS_TO_MMS_TEXT_LENGTH_THRESHOLD);
    375         }
    376 
    377         public boolean getMmsEnabled() {
    378             return getBoolean(CONFIG_ENABLED_MMS);
    379         }
    380 
    381         public int getMaxMessageSize() {
    382             return getInt(CONFIG_MAX_MESSAGE_SIZE);
    383         }
    384 
    385         public boolean getTransIdEnabled() {
    386             return getBoolean(CONFIG_ENABLED_TRANS_ID);
    387         }
    388 
    389         public String getUserAgent() {
    390             if (mOverrides != null && mOverrides.containsKey(CONFIG_USER_AGENT)) {
    391                 return mOverrides.getString(CONFIG_USER_AGENT);
    392             }
    393             return !TextUtils.isEmpty(mBase.mUserAgent) ?
    394                     mBase.mUserAgent : mBase.getNullableStringValue(CONFIG_USER_AGENT);
    395         }
    396 
    397         public String getUaProfTagName() {
    398             return getString(CONFIG_UA_PROF_TAG_NAME);
    399         }
    400 
    401         public String getUaProfUrl() {
    402             if (mOverrides != null && mOverrides.containsKey(CONFIG_UA_PROF_URL)) {
    403                 return mOverrides.getString(CONFIG_UA_PROF_URL);
    404             }
    405             return !TextUtils.isEmpty(mBase.mUaProfUrl) ?
    406                     mBase.mUaProfUrl : mBase.getNullableStringValue(CONFIG_UA_PROF_URL);
    407         }
    408 
    409         public String getHttpParams() {
    410             return getString(CONFIG_HTTP_PARAMS);
    411         }
    412 
    413         public String getEmailGateway() {
    414             return getString(CONFIG_EMAIL_GATEWAY_NUMBER);
    415         }
    416 
    417         public int getMaxImageHeight() {
    418             return getInt(CONFIG_MAX_IMAGE_HEIGHT);
    419         }
    420 
    421         public int getMaxImageWidth() {
    422             return getInt(CONFIG_MAX_IMAGE_WIDTH);
    423         }
    424 
    425         public int getRecipientLimit() {
    426             final int limit = getInt(CONFIG_RECIPIENT_LIMIT);
    427             return limit < 0 ? Integer.MAX_VALUE : limit;
    428         }
    429 
    430         public int getMaxTextLimit() {
    431             final int max = getInt(CONFIG_MAX_MESSAGE_TEXT_SIZE);
    432             return max > -1 ? max : MAX_TEXT_LENGTH;
    433         }
    434 
    435         public int getHttpSocketTimeout() {
    436             return getInt(CONFIG_HTTP_SOCKET_TIMEOUT);
    437         }
    438 
    439         public boolean getMultipartSmsEnabled() {
    440             return getBoolean(CONFIG_ENABLE_MULTIPART_SMS);
    441         }
    442 
    443         public boolean getSendMultipartSmsAsSeparateMessages() {
    444             return getBoolean(CONFIG_SEND_MULTIPART_SMS_AS_SEPARATE_MESSAGES);
    445         }
    446 
    447         public boolean getSMSDeliveryReportsEnabled() {
    448             return getBoolean(CONFIG_ENABLE_SMS_DELIVERY_REPORTS);
    449         }
    450 
    451         public boolean getNotifyWapMMSC() {
    452             return getBoolean(CONFIG_ENABLED_NOTIFY_WAP_MMSC);
    453         }
    454 
    455         public boolean isAliasEnabled() {
    456             return getBoolean(CONFIG_ALIAS_ENABLED);
    457         }
    458 
    459         public int getAliasMinChars() {
    460             return getInt(CONFIG_ALIAS_MIN_CHARS);
    461         }
    462 
    463         public int getAliasMaxChars() {
    464             return getInt(CONFIG_ALIAS_MAX_CHARS);
    465         }
    466 
    467         public boolean getAllowAttachAudio() {
    468             return getBoolean(CONFIG_ALLOW_ATTACH_AUDIO);
    469         }
    470 
    471         public int getMaxSubjectLength() {
    472             return getInt(CONFIG_MAX_SUBJECT_LENGTH);
    473         }
    474 
    475         public boolean getGroupMmsEnabled() {
    476             return getBoolean(CONFIG_ENABLE_GROUP_MMS);
    477         }
    478 
    479         public boolean getSupportMmsContentDisposition() {
    480             return getBoolean(CONFIG_SUPPORT_MMS_CONTENT_DISPOSITION);
    481         }
    482 
    483         public boolean getShowCellBroadcast() {
    484             return getBoolean(CONFIG_CELL_BROADCAST_APP_LINKS);
    485         }
    486 
    487         public String getNaiSuffix() {
    488             return getString(CONFIG_NAI_SUFFIX);
    489         }
    490 
    491         public boolean isMmsReadReportsEnabled() {
    492             return getBoolean(CONFIG_ENABLE_MMS_READ_REPORTS);
    493         }
    494 
    495         public boolean isMmsDeliveryReportsEnabled() {
    496             return getBoolean(CONFIG_ENABLE_MMS_DELIVERY_REPORTS);
    497         }
    498 
    499         public boolean getSupportHttpCharsetHeader() {
    500             return getBoolean(CONFIG_SUPPORT_HTTP_CHARSET_HEADER);
    501         }
    502 
    503         /**
    504          * Return the HTTP param macro value.
    505          * Example: LINE1 returns the phone number, etc.
    506          *
    507          * @param macro The macro name
    508          * @return The value of the defined macro
    509          */
    510         public String getHttpParamMacro(Context context, String macro) {
    511             if (MACRO_LINE1.equals(macro)) {
    512                 return getLine1(context, mBase.getSubId());
    513             } else if (MACRO_LINE1NOCOUNTRYCODE.equals(macro)) {
    514                 return getLine1NoCountryCode(context, mBase.getSubId());
    515             } else if (MACRO_NAI.equals(macro)) {
    516                 return getNai(context, mBase.getSubId());
    517             }
    518             return null;
    519         }
    520 
    521         /**
    522          * @return the phone number
    523          */
    524         private static String getLine1(Context context, int subId) {
    525             final TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(
    526                     Context.TELEPHONY_SERVICE);
    527             return telephonyManager.getLine1NumberForSubscriber(subId);
    528         }
    529 
    530         private static String getLine1NoCountryCode(Context context, int subId) {
    531             final TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(
    532                     Context.TELEPHONY_SERVICE);
    533             return PhoneUtils.getNationalNumber(
    534                     telephonyManager,
    535                     subId,
    536                     telephonyManager.getLine1NumberForSubscriber(subId));
    537         }
    538 
    539         /**
    540          * @return the NAI (Network Access Identifier) from SystemProperties
    541          */
    542         private String getNai(Context context, int subId) {
    543             final TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(
    544                     Context.TELEPHONY_SERVICE);
    545             String nai = telephonyManager.getNai(SubscriptionManager.getSlotId(subId));
    546             if (Log.isLoggable(TAG, Log.VERBOSE)) {
    547                 Log.v(TAG, "MmsConfig.getNai: nai=" + nai);
    548             }
    549 
    550             if (!TextUtils.isEmpty(nai)) {
    551                 String naiSuffix = getNaiSuffix();
    552                 if (!TextUtils.isEmpty(naiSuffix)) {
    553                     nai = nai + naiSuffix;
    554                 }
    555                 byte[] encoded = null;
    556                 try {
    557                     encoded = Base64.encode(nai.getBytes("UTF-8"), Base64.NO_WRAP);
    558                 } catch (UnsupportedEncodingException e) {
    559                     encoded = Base64.encode(nai.getBytes(), Base64.NO_WRAP);
    560                 }
    561                 try {
    562                     nai = new String(encoded, "UTF-8");
    563                 } catch (UnsupportedEncodingException e) {
    564                     nai = new String(encoded);
    565                 }
    566             }
    567             return nai;
    568         }
    569     }
    570 }
    571