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