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 17package com.android.mms.service; 18 19import android.content.Context; 20import android.content.res.XmlResourceParser; 21import android.os.Bundle; 22import android.telephony.SubscriptionManager; 23import android.telephony.TelephonyManager; 24import android.text.TextUtils; 25import android.util.Base64; 26import android.util.Log; 27 28import java.io.UnsupportedEncodingException; 29import java.util.Iterator; 30import java.util.Map; 31import 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 */ 43public 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