diff options
Diffstat (limited to 'src/com/android')
-rw-r--r-- | src/com/android/mms/service/DownloadRequest.java | 13 | ||||
-rwxr-xr-x | src/com/android/mms/service/MmsConfig.java | 571 | ||||
-rw-r--r-- | src/com/android/mms/service/MmsConfigManager.java | 61 | ||||
-rw-r--r-- | src/com/android/mms/service/MmsConfigXmlProcessor.java | 197 | ||||
-rw-r--r-- | src/com/android/mms/service/MmsHttpClient.java | 171 | ||||
-rw-r--r-- | src/com/android/mms/service/MmsRequest.java | 31 | ||||
-rw-r--r-- | src/com/android/mms/service/MmsService.java | 10 | ||||
-rw-r--r-- | src/com/android/mms/service/SendRequest.java | 12 |
8 files changed, 207 insertions, 859 deletions
diff --git a/src/com/android/mms/service/DownloadRequest.java b/src/com/android/mms/service/DownloadRequest.java index c9f6789..5e4d0a4 100644 --- a/src/com/android/mms/service/DownloadRequest.java +++ b/src/com/android/mms/service/DownloadRequest.java @@ -36,6 +36,7 @@ import android.service.carrier.CarrierMessagingService; import android.service.carrier.ICarrierMessagingCallback; import android.service.carrier.ICarrierMessagingService; import android.telephony.CarrierMessagingServiceManager; +import android.telephony.SmsManager; import android.telephony.TelephonyManager; import android.text.TextUtils; import android.util.Log; @@ -65,8 +66,8 @@ public class DownloadRequest extends MmsRequest { public DownloadRequest(RequestManager manager, int subId, String locationUrl, Uri contentUri, PendingIntent downloadedIntent, String creator, - Bundle configOverrides) { - super(manager, subId, creator, configOverrides); + Bundle configOverrides, Context context) { + super(manager, subId, creator, configOverrides, context); mLocationUrl = locationUrl; mDownloadedIntent = downloadedIntent; mContentUri = contentUri; @@ -87,7 +88,8 @@ public class DownloadRequest extends MmsRequest { apn.isProxySet(), apn.getProxyAddress(), apn.getProxyPort(), - mMmsConfig); + mMmsConfig, + mSubId); } @Override @@ -115,8 +117,9 @@ public class DownloadRequest extends MmsRequest { } final long identity = Binder.clearCallingIdentity(); try { - final GenericPdu pdu = - (new PduParser(response, mMmsConfig.getSupportMmsContentDisposition())).parse(); + final boolean supportMmsContentDisposition = + mMmsConfig.getBoolean(SmsManager.MMS_CONFIG_SUPPORT_MMS_CONTENT_DISPOSITION); + final GenericPdu pdu = (new PduParser(response, supportMmsContentDisposition)).parse(); if (pdu == null || !(pdu instanceof RetrieveConf)) { Log.e(MmsService.TAG, "DownloadRequest.persistIfRequired: invalid parsed PDU"); return null; diff --git a/src/com/android/mms/service/MmsConfig.java b/src/com/android/mms/service/MmsConfig.java deleted file mode 100755 index c5505aa..0000000 --- a/src/com/android/mms/service/MmsConfig.java +++ /dev/null @@ -1,571 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.mms.service; - -import android.content.Context; -import android.content.res.XmlResourceParser; -import android.os.Bundle; -import android.telephony.SubscriptionManager; -import android.telephony.TelephonyManager; -import android.text.TextUtils; -import android.util.Base64; -import android.util.Log; - -import java.io.UnsupportedEncodingException; -import java.util.Iterator; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -/** - * This class manages a cached copy of current MMS configuration key values - * - * The steps to add a key - * 1. Add a String constant for the key - * 2. Add a default value for the key by putting a typed value to DEFAULTS - * (null means String type only) - * 3. Add a getter for the key - * 4. Add key/value for relevant mms_config.xml of a specific carrier (mcc/mnc) - */ -public class MmsConfig { - private static final String TAG = MmsService.TAG; - - private static final String DEFAULT_HTTP_KEY_X_WAP_PROFILE = "x-wap-profile"; - - private static final int MAX_IMAGE_HEIGHT = 480; - private static final int MAX_IMAGE_WIDTH = 640; - private static final int MAX_TEXT_LENGTH = 2000; - - /* - * MmsConfig keys. These have to stay in sync with the MMS_CONFIG_* values defined in - * SmsManager. - */ - public static final String CONFIG_ENABLED_MMS = "enabledMMS"; - // In case of single segment wap push message, this CONFIG_ENABLED_TRANS_ID indicates whether - // TransactionID should be appended to URI or not. - public static final String CONFIG_ENABLED_TRANS_ID = "enabledTransID"; - public static final String CONFIG_ENABLED_NOTIFY_WAP_MMSC = "enabledNotifyWapMMSC"; - public static final String CONFIG_ALIAS_ENABLED = "aliasEnabled"; - public static final String CONFIG_ALLOW_ATTACH_AUDIO = "allowAttachAudio"; - // If CONFIG_ENABLE_MULTIPART_SMS is true, long sms messages are always sent as multi-part sms - // messages, with no checked limit on the number of segments. - // If CONFIG_ENABLE_MULTIPART_SMS is false, then as soon as the user types a message longer - // than a single segment (i.e. 140 chars), then the message will turn into and be sent - // as an mms message or separate, independent SMS messages - // (which is dependent on CONFIG_SEND_MULTIPART_SMS_AS_SEPARATE_MESSAGES flag). - // This feature exists for carriers that don't support multi-part sms's. - public static final String CONFIG_ENABLE_MULTIPART_SMS = "enableMultipartSMS"; - public static final String CONFIG_ENABLE_SMS_DELIVERY_REPORTS = "enableSMSDeliveryReports"; - // If CONFIG_ENABLE_GROUP_MMS is true, a message with multiple recipients, - // regardless of contents, will be sent as a single MMS message with multiple "TO" fields set - // for each recipient. - // If CONFIG_ENABLE_GROUP_MMS is false, the group MMS setting/preference will be hidden - // in the settings activity. - public static final String CONFIG_ENABLE_GROUP_MMS = "enableGroupMms"; - // If this is true, then we should read the content_disposition field of an MMS part - // Check wap-230-wsp-20010705-a.pdf, chapter 8.4.2.21 - // Most carriers support it except Sprint. - // There is a system resource defining it: - // com.android.internal.R.bool.config_mms_content_disposition_support. - // But Shem can not read it. Add here so that we can configure for different carriers. - public static final String CONFIG_SUPPORT_MMS_CONTENT_DISPOSITION = - "supportMmsContentDisposition"; - // if true, show the cell broadcast (amber alert) in the SMS settings. Some carriers - // don't want this shown. - public static final String CONFIG_CELL_BROADCAST_APP_LINKS = "config_cellBroadcastAppLinks"; - // If this is true, we will send multipart SMS as separate SMS messages - public static final String CONFIG_SEND_MULTIPART_SMS_AS_SEPARATE_MESSAGES = - "sendMultipartSmsAsSeparateMessages"; - // FLAG(ywen): the following two is not supported yet. - public static final String CONFIG_ENABLE_MMS_READ_REPORTS = "enableMMSReadReports"; - public static final String CONFIG_ENABLE_MMS_DELIVERY_REPORTS = "enableMMSDeliveryReports"; - // Bouygues Telecom (20820) MMSC does not support "charset" with "Content-Type" header - // It would fail and return 500. See b/18604507 - // If this is false, then we don't add "charset" to "Content-Type" - public static final String CONFIG_SUPPORT_HTTP_CHARSET_HEADER = "supportHttpCharsetHeader"; - public static final String CONFIG_MAX_MESSAGE_SIZE = "maxMessageSize"; // in bytes - public static final String CONFIG_MAX_IMAGE_HEIGHT = "maxImageHeight"; // in pixels - public static final String CONFIG_MAX_IMAGE_WIDTH = "maxImageWidth"; // in pixels - public static final String CONFIG_RECIPIENT_LIMIT = "recipientLimit"; - public static final String CONFIG_HTTP_SOCKET_TIMEOUT = "httpSocketTimeout"; - public static final String CONFIG_ALIAS_MIN_CHARS = "aliasMinChars"; - public static final String CONFIG_ALIAS_MAX_CHARS = "aliasMaxChars"; - // If CONFIG_ENABLE_MULTIPART_SMS is true and CONFIG_SMS_TO_MMS_TEXT_THRESHOLD > 1, - // then multi-part SMS messages will be converted into a single mms message. - // For example, if the mms_config.xml file specifies <int name="smsToMmsTextThreshold">4</int>, - // then on the 5th sms segment, the message will be converted to an mms. - public static final String CONFIG_SMS_TO_MMS_TEXT_THRESHOLD = "smsToMmsTextThreshold"; - // LGU+ temporarily requires any SMS message longer than 80 bytes to be sent as MMS - // see b/12122333 - public static final String CONFIG_SMS_TO_MMS_TEXT_LENGTH_THRESHOLD = - "smsToMmsTextLengthThreshold"; - public static final String CONFIG_MAX_MESSAGE_TEXT_SIZE = "maxMessageTextSize"; - // maximum number of characters allowed for mms subject - public static final String CONFIG_MAX_SUBJECT_LENGTH = "maxSubjectLength"; - public static final String CONFIG_UA_PROF_TAG_NAME = "uaProfTagName"; - public static final String CONFIG_USER_AGENT = "userAgent"; - public static final String CONFIG_UA_PROF_URL = "uaProfUrl"; - public static final String CONFIG_HTTP_PARAMS = "httpParams"; - // Email gateway alias support, including the master switch and different rules - public static final String CONFIG_EMAIL_GATEWAY_NUMBER = "emailGatewayNumber"; - // String to append to the NAI header, e.g. ":pcs" - public static final String CONFIG_NAI_SUFFIX = "naiSuffix"; - - /* - * Key types - */ - public static final String KEY_TYPE_INT = "int"; - public static final String KEY_TYPE_BOOL = "bool"; - public static final String KEY_TYPE_STRING = "string"; - - /* - * Macro names - */ - // The raw phone number from TelephonyManager.getLine1Number - public static final String MACRO_LINE1 = "LINE1"; - // The phone number without country code - public static final String MACRO_LINE1NOCOUNTRYCODE = "LINE1NOCOUNTRYCODE"; - // NAI (Network Access Identifier), used by Sprint for authentication - public static final String MACRO_NAI = "NAI"; - - // Default values. This is read-only. Don't write into it. - // This provides the info on valid keys, their types and default values - private static final Map<String, Object> DEFAULTS = new ConcurrentHashMap<String, Object>(); - static { - DEFAULTS.put(CONFIG_ENABLED_MMS, Boolean.valueOf(true)); - DEFAULTS.put(CONFIG_ENABLED_TRANS_ID, Boolean.valueOf(false)); - DEFAULTS.put(CONFIG_ENABLED_NOTIFY_WAP_MMSC, Boolean.valueOf(false)); - DEFAULTS.put(CONFIG_ALIAS_ENABLED, Boolean.valueOf(false)); - DEFAULTS.put(CONFIG_ALLOW_ATTACH_AUDIO, Boolean.valueOf(true)); - DEFAULTS.put(CONFIG_ENABLE_MULTIPART_SMS, Boolean.valueOf(true)); - DEFAULTS.put(CONFIG_ENABLE_SMS_DELIVERY_REPORTS, Boolean.valueOf(true)); - DEFAULTS.put(CONFIG_ENABLE_GROUP_MMS, Boolean.valueOf(true)); - DEFAULTS.put(CONFIG_SUPPORT_MMS_CONTENT_DISPOSITION, Boolean.valueOf(true)); - DEFAULTS.put(CONFIG_CELL_BROADCAST_APP_LINKS, Boolean.valueOf(true)); - DEFAULTS.put(CONFIG_SEND_MULTIPART_SMS_AS_SEPARATE_MESSAGES, Boolean.valueOf(false)); - DEFAULTS.put(CONFIG_ENABLE_MMS_READ_REPORTS, Boolean.valueOf(false)); - DEFAULTS.put(CONFIG_ENABLE_MMS_DELIVERY_REPORTS, Boolean.valueOf(false)); - DEFAULTS.put(CONFIG_SUPPORT_HTTP_CHARSET_HEADER, Boolean.valueOf(false)); - DEFAULTS.put(CONFIG_MAX_MESSAGE_SIZE, Integer.valueOf(300 * 1024)); - DEFAULTS.put(CONFIG_MAX_IMAGE_HEIGHT, Integer.valueOf(MAX_IMAGE_HEIGHT)); - DEFAULTS.put(CONFIG_MAX_IMAGE_WIDTH, Integer.valueOf(MAX_IMAGE_WIDTH)); - DEFAULTS.put(CONFIG_RECIPIENT_LIMIT, Integer.valueOf(Integer.MAX_VALUE)); - DEFAULTS.put(CONFIG_HTTP_SOCKET_TIMEOUT, Integer.valueOf(60 * 1000)); - DEFAULTS.put(CONFIG_ALIAS_MIN_CHARS, Integer.valueOf(2)); - DEFAULTS.put(CONFIG_ALIAS_MAX_CHARS, Integer.valueOf(48)); - DEFAULTS.put(CONFIG_SMS_TO_MMS_TEXT_THRESHOLD, Integer.valueOf(-1)); - DEFAULTS.put(CONFIG_SMS_TO_MMS_TEXT_LENGTH_THRESHOLD, Integer.valueOf(-1)); - DEFAULTS.put(CONFIG_MAX_MESSAGE_TEXT_SIZE, Integer.valueOf(-1)); - DEFAULTS.put(CONFIG_MAX_SUBJECT_LENGTH, Integer.valueOf(40)); - DEFAULTS.put(CONFIG_UA_PROF_TAG_NAME, DEFAULT_HTTP_KEY_X_WAP_PROFILE); - DEFAULTS.put(CONFIG_USER_AGENT, ""); - DEFAULTS.put(CONFIG_UA_PROF_URL, ""); - DEFAULTS.put(CONFIG_HTTP_PARAMS, ""); - DEFAULTS.put(CONFIG_EMAIL_GATEWAY_NUMBER, ""); - DEFAULTS.put(CONFIG_NAI_SUFFIX, ""); - } - - private final int mSubId; - - /** - * This class manages a cached copy of current MMS configuration key values for a particular - * subscription id. (See the {@link android.telephony.SubscriptionManager}). - * - * @param context Context of the particular subscription to load. The context's mcc/mnc - * should be set to that of the subscription id - * @param subId Subscription id of the mcc/mnc in the context - */ - public MmsConfig(Context context, int subId) { - mSubId = subId; - // Load defaults - mKeyValues.clear(); - mKeyValues.putAll(DEFAULTS); - // Load User-Agent and UA profile URL settings - loadDeviceUaSettings(context); - Log.v(TAG, "MmsConfig: mUserAgent=" + mUserAgent + ", mUaProfUrl=" + mUaProfUrl); - // Load mms_config.xml resource overlays - loadFromResources(context); - Log.v(TAG, "MmsConfig: all settings -- " + mKeyValues); - } - - /** - * Return the subscription ID associated with this MmsConfig - * - * @return subId the subId associated with this MmsConfig - */ - public int getSubId() { - return mSubId; - } - - /** - * Check a key and its type match the predefined keys and corresponding types - * - * @param key - * @param type Including "int" "bool" and "string" - * @return True if key and type both matches and false otherwise - */ - public static boolean isValidKey(String key, String type) { - if (!TextUtils.isEmpty(key) && DEFAULTS.containsKey(key)) { - Object defVal = DEFAULTS.get(key); - Class<?> valueType = defVal != null ? defVal.getClass() : String.class; - if (KEY_TYPE_INT.equals(type)) { - return valueType == Integer.class; - } else if (KEY_TYPE_BOOL.equals(type)) { - return valueType == Boolean.class; - } else if (KEY_TYPE_STRING.equals(type)) { - return valueType == String.class; - } - } - return false; - } - - /** - * Check a key and its type match the predefined keys and corresponding types - * - * @param key The key of the config - * @param value The value of the config - * @return True if key and type both matches and false otherwise - */ - public static boolean isValidValue(String key, Object value) { - if (!TextUtils.isEmpty(key) && DEFAULTS.containsKey(key)) { - Object defVal = DEFAULTS.get(key); - Class<?> valueType = defVal != null ? defVal.getClass() : String.class; - return value.getClass().equals(valueType); - } - return false; - } - - private String mUserAgent = null; - private String mUaProfUrl = null; - - // The current values - private final Map<String, Object> mKeyValues = new ConcurrentHashMap<String, Object>(); - - /** - * Get a config value by its type - * - * @param key The key of the config - * @param type The type of the config value - * @return The expected typed value or null if no match - */ - public Object getValueAsType(String key, String type) { - if (isValidKey(key, type)) { - return mKeyValues.get(key); - } - return null; - } - - public Bundle getCarrierConfigValues() { - final Bundle bundle = new Bundle(); - final Iterator<Map.Entry<String, Object>> iter = mKeyValues.entrySet().iterator(); - while(iter.hasNext()) { - final Map.Entry<String, Object> entry = iter.next(); - final String key = entry.getKey(); - final Object val = entry.getValue(); - Class<?> valueType = val != null ? val.getClass() : String.class; - if (valueType == Integer.class) { - bundle.putInt(key, (Integer)val); - } else if (valueType == Boolean.class) { - bundle.putBoolean(key, (Boolean)val); - } else if (valueType == String.class) { - bundle.putString(key, (String)val); - } - } - return bundle; - } - - private String getNullableStringValue(String key) { - final Object value = mKeyValues.get(key); - if (value != null) { - return (String) value; - } - return null; - } - - private void update(String key, String value, String type) { - try { - if (KEY_TYPE_INT.equals(type)) { - mKeyValues.put(key, Integer.parseInt(value)); - } else if (KEY_TYPE_BOOL.equals(type)) { - mKeyValues.put(key, Boolean.parseBoolean(value)); - } else if (KEY_TYPE_STRING.equals(type)){ - mKeyValues.put(key, value); - } - } catch (NumberFormatException e) { - Log.e(TAG, "MmsConfig.update: invalid " + key + "," + value + "," + type); - } - } - - private void loadDeviceUaSettings(Context context) { - // load the MMS User agent and UaProfUrl from TelephonyManager APIs - final TelephonyManager telephonyManager = - (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); - mUserAgent = telephonyManager.getMmsUserAgent(); - mUaProfUrl = telephonyManager.getMmsUAProfUrl(); - } - - private void loadFromResources(Context context) { - Log.d(TAG, "MmsConfig.loadFromResources"); - final XmlResourceParser parser = context.getResources().getXml(R.xml.mms_config); - final MmsConfigXmlProcessor processor = MmsConfigXmlProcessor.get(parser); - processor.setMmsConfigHandler(new MmsConfigXmlProcessor.MmsConfigHandler() { - @Override - public void process(String key, String value, String type) { - update(key, value, type); - } - }); - try { - processor.process(); - } finally { - parser.close(); - } - } - - /** - * This class returns corresponding MmsConfig values which can be overridden by - * externally provided values. - */ - public static class Overridden { - // The base MmsConfig - private final MmsConfig mBase; - // The overridden values - private final Bundle mOverrides; - - public Overridden(MmsConfig base, Bundle overrides) { - mBase = base; - mOverrides = overrides; - } - - private int getInt(String key) { - final Integer def = (Integer) mBase.mKeyValues.get(key); - return mOverrides != null ? mOverrides.getInt(key, def) : def; - } - - private boolean getBoolean(String key) { - final Boolean def = (Boolean) mBase.mKeyValues.get(key); - return mOverrides != null ? mOverrides.getBoolean(key, def) : def; - } - - private String getString(String key) { - if (mOverrides != null && mOverrides.containsKey(key)) { - return mOverrides.getString(key); - } - return mBase.getNullableStringValue(key); - } - - public int getSmsToMmsTextThreshold() { - return getInt(CONFIG_SMS_TO_MMS_TEXT_THRESHOLD); - } - - public int getSmsToMmsTextLengthThreshold() { - return getInt(CONFIG_SMS_TO_MMS_TEXT_LENGTH_THRESHOLD); - } - - public boolean getMmsEnabled() { - return getBoolean(CONFIG_ENABLED_MMS); - } - - public int getMaxMessageSize() { - return getInt(CONFIG_MAX_MESSAGE_SIZE); - } - - public boolean getTransIdEnabled() { - return getBoolean(CONFIG_ENABLED_TRANS_ID); - } - - public String getUserAgent() { - if (mOverrides != null && mOverrides.containsKey(CONFIG_USER_AGENT)) { - return mOverrides.getString(CONFIG_USER_AGENT); - } - return !TextUtils.isEmpty(mBase.mUserAgent) ? - mBase.mUserAgent : mBase.getNullableStringValue(CONFIG_USER_AGENT); - } - - public String getUaProfTagName() { - return getString(CONFIG_UA_PROF_TAG_NAME); - } - - public String getUaProfUrl() { - if (mOverrides != null && mOverrides.containsKey(CONFIG_UA_PROF_URL)) { - return mOverrides.getString(CONFIG_UA_PROF_URL); - } - return !TextUtils.isEmpty(mBase.mUaProfUrl) ? - mBase.mUaProfUrl : mBase.getNullableStringValue(CONFIG_UA_PROF_URL); - } - - public String getHttpParams() { - return getString(CONFIG_HTTP_PARAMS); - } - - public String getEmailGateway() { - return getString(CONFIG_EMAIL_GATEWAY_NUMBER); - } - - public int getMaxImageHeight() { - return getInt(CONFIG_MAX_IMAGE_HEIGHT); - } - - public int getMaxImageWidth() { - return getInt(CONFIG_MAX_IMAGE_WIDTH); - } - - public int getRecipientLimit() { - final int limit = getInt(CONFIG_RECIPIENT_LIMIT); - return limit < 0 ? Integer.MAX_VALUE : limit; - } - - public int getMaxTextLimit() { - final int max = getInt(CONFIG_MAX_MESSAGE_TEXT_SIZE); - return max > -1 ? max : MAX_TEXT_LENGTH; - } - - public int getHttpSocketTimeout() { - return getInt(CONFIG_HTTP_SOCKET_TIMEOUT); - } - - public boolean getMultipartSmsEnabled() { - return getBoolean(CONFIG_ENABLE_MULTIPART_SMS); - } - - public boolean getSendMultipartSmsAsSeparateMessages() { - return getBoolean(CONFIG_SEND_MULTIPART_SMS_AS_SEPARATE_MESSAGES); - } - - public boolean getSMSDeliveryReportsEnabled() { - return getBoolean(CONFIG_ENABLE_SMS_DELIVERY_REPORTS); - } - - public boolean getNotifyWapMMSC() { - return getBoolean(CONFIG_ENABLED_NOTIFY_WAP_MMSC); - } - - public boolean isAliasEnabled() { - return getBoolean(CONFIG_ALIAS_ENABLED); - } - - public int getAliasMinChars() { - return getInt(CONFIG_ALIAS_MIN_CHARS); - } - - public int getAliasMaxChars() { - return getInt(CONFIG_ALIAS_MAX_CHARS); - } - - public boolean getAllowAttachAudio() { - return getBoolean(CONFIG_ALLOW_ATTACH_AUDIO); - } - - public int getMaxSubjectLength() { - return getInt(CONFIG_MAX_SUBJECT_LENGTH); - } - - public boolean getGroupMmsEnabled() { - return getBoolean(CONFIG_ENABLE_GROUP_MMS); - } - - public boolean getSupportMmsContentDisposition() { - return getBoolean(CONFIG_SUPPORT_MMS_CONTENT_DISPOSITION); - } - - public boolean getShowCellBroadcast() { - return getBoolean(CONFIG_CELL_BROADCAST_APP_LINKS); - } - - public String getNaiSuffix() { - return getString(CONFIG_NAI_SUFFIX); - } - - public boolean isMmsReadReportsEnabled() { - return getBoolean(CONFIG_ENABLE_MMS_READ_REPORTS); - } - - public boolean isMmsDeliveryReportsEnabled() { - return getBoolean(CONFIG_ENABLE_MMS_DELIVERY_REPORTS); - } - - public boolean getSupportHttpCharsetHeader() { - return getBoolean(CONFIG_SUPPORT_HTTP_CHARSET_HEADER); - } - - /** - * Return the HTTP param macro value. - * Example: LINE1 returns the phone number, etc. - * - * @param macro The macro name - * @return The value of the defined macro - */ - public String getHttpParamMacro(Context context, String macro) { - if (MACRO_LINE1.equals(macro)) { - return getLine1(context, mBase.getSubId()); - } else if (MACRO_LINE1NOCOUNTRYCODE.equals(macro)) { - return getLine1NoCountryCode(context, mBase.getSubId()); - } else if (MACRO_NAI.equals(macro)) { - return getNai(context, mBase.getSubId()); - } - Log.e(MmsService.TAG, "MmsConfig: invalid macro " + macro); - return null; - } - - /** - * @return the phone number - */ - private static String getLine1(Context context, int subId) { - final TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService( - Context.TELEPHONY_SERVICE); - return telephonyManager.getLine1NumberForSubscriber(subId); - } - - private static String getLine1NoCountryCode(Context context, int subId) { - final TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService( - Context.TELEPHONY_SERVICE); - return PhoneUtils.getNationalNumber( - telephonyManager, - subId, - telephonyManager.getLine1NumberForSubscriber(subId)); - } - - /** - * @return the NAI (Network Access Identifier) from SystemProperties - */ - private String getNai(Context context, int subId) { - final TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService( - Context.TELEPHONY_SERVICE); - String nai = telephonyManager.getNai(SubscriptionManager.getSlotId(subId)); - if (Log.isLoggable(TAG, Log.VERBOSE)) { - Log.v(TAG, "MmsConfig.getNai: nai=" + nai); - } - - if (!TextUtils.isEmpty(nai)) { - String naiSuffix = getNaiSuffix(); - if (!TextUtils.isEmpty(naiSuffix)) { - nai = nai + naiSuffix; - } - byte[] encoded = null; - try { - encoded = Base64.encode(nai.getBytes("UTF-8"), Base64.NO_WRAP); - } catch (UnsupportedEncodingException e) { - encoded = Base64.encode(nai.getBytes(), Base64.NO_WRAP); - } - try { - nai = new String(encoded, "UTF-8"); - } catch (UnsupportedEncodingException e) { - nai = new String(encoded); - } - } - return nai; - } - } -} diff --git a/src/com/android/mms/service/MmsConfigManager.java b/src/com/android/mms/service/MmsConfigManager.java index de1522c..7aa60f6 100644 --- a/src/com/android/mms/service/MmsConfigManager.java +++ b/src/com/android/mms/service/MmsConfigManager.java @@ -21,9 +21,13 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.res.Configuration; +import android.os.Bundle; +import android.os.PersistableBundle; +import android.telephony.CarrierConfigManager; +import android.telephony.SmsManager; import android.telephony.SubscriptionInfo; -import android.telephony.SubscriptionManager; import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener; +import android.telephony.SubscriptionManager; import android.util.ArrayMap; import android.util.Log; @@ -48,7 +52,7 @@ public class MmsConfigManager { } // Map the various subIds to their corresponding MmsConfigs. - private final Map<Integer, MmsConfig> mSubIdConfigMap = new ArrayMap<Integer, MmsConfig>(); + private final Map<Integer, Bundle> mSubIdConfigMap = new ArrayMap<Integer, Bundle>(); private Context mContext; private SubscriptionManager mSubscriptionManager; @@ -114,28 +118,32 @@ public class MmsConfigManager { } /** - * Find and return the MmsConfig for a particular subscription id. + * Find and return the MMS config for a particular subscription id. * - * @param subId Subscription id of the desired MmsConfig - * @return MmsConfig for the particular subscription id. This function can return null if - * the MmsConfig cannot be found or if this function is called before the - * TelephonyManager has setup the SIMs or if loadInBackground is still spawning a + * @param subId Subscription id of the desired MMS config bundle + * @return MMS config bundle for the particular subscription id. This function can return null + * if the MMS config cannot be found or if this function is called before the + * TelephonyManager has set up the SIMs, or if loadInBackground is still spawning a * thread after a recent LISTEN_SUBSCRIPTION_INFO_LIST_CHANGED event. */ - public MmsConfig getMmsConfigBySubId(int subId) { - MmsConfig mmsConfig; + public Bundle getMmsConfigBySubId(int subId) { + Bundle mmsConfig; synchronized(mSubIdConfigMap) { mmsConfig = mSubIdConfigMap.get(subId); } Log.i(TAG, "getMmsConfigBySubId -- for sub: " + subId + " mmsConfig: " + mmsConfig); - return mmsConfig; + // Return a copy so that callers can mutate it. + if (mmsConfig != null) { + return new Bundle(mmsConfig); + } + return null; } /** - * This function goes through all the activated subscription ids (the actual SIMs in the - * device), builds a context with that SIM's mcc/mnc and loads the appropriate mms_config.xml - * file via the ResourceManager. With single-SIM devices, there will be a single subId. + * This loads the MMS config for each active subscription. * + * MMS config is fetched from CarrierConfigManager and filtered to only include MMS config + * variables. The resulting bundles are stored in mSubIdConfigMap. */ private void load(Context context) { List<SubscriptionInfo> subs = mSubscriptionManager.getActiveSubscriptionInfoList(); @@ -143,28 +151,15 @@ public class MmsConfigManager { Log.e(TAG, "MmsConfigManager.load -- empty getActiveSubInfoList"); return; } - // Load all the mms_config.xml files in a separate map and then swap with the - // real map at the end so we don't block anyone sync'd on the real map. - final Map<Integer, MmsConfig> newConfigMap = new ArrayMap<Integer, MmsConfig>(); + // Load all the config bundles into a new map and then swap it with the real map to avoid + // blocking. + final Map<Integer, Bundle> newConfigMap = new ArrayMap<Integer, Bundle>(); + CarrierConfigManager configManager = + (CarrierConfigManager) context.getSystemService(Context.CARRIER_CONFIG_SERVICE); for (SubscriptionInfo sub : subs) { - Configuration configuration = new Configuration(); - if (sub.getMcc() == 0 && sub.getMnc() == 0) { - Configuration config = mContext.getResources().getConfiguration(); - configuration.mcc = config.mcc; - configuration.mnc = config.mnc; - Log.i(TAG, "MmsConfigManager.load -- no mcc/mnc for sub: " + sub + - " using mcc/mnc from main context: " + configuration.mcc + "/" + - configuration.mnc); - } else { - Log.i(TAG, "MmsConfigManager.load -- mcc/mnc for sub: " + sub); - - configuration.mcc = sub.getMcc(); - configuration.mnc = sub.getMnc(); - } - Context subContext = context.createConfigurationContext(configuration); - int subId = sub.getSubscriptionId(); - newConfigMap.put(subId, new MmsConfig(subContext, subId)); + PersistableBundle config = configManager.getConfigForSubId(subId); + newConfigMap.put(subId, SmsManager.getMmsConfig(config)); } synchronized(mSubIdConfigMap) { mSubIdConfigMap.clear(); diff --git a/src/com/android/mms/service/MmsConfigXmlProcessor.java b/src/com/android/mms/service/MmsConfigXmlProcessor.java deleted file mode 100644 index 9eaebcd..0000000 --- a/src/com/android/mms/service/MmsConfigXmlProcessor.java +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.mms.service; - -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; - -import android.content.ContentValues; -import android.util.Log; - -import java.io.IOException; - -/* - * XML processor for mms_config.xml - */ -public class MmsConfigXmlProcessor { - private static final String TAG = MmsService.TAG; - - public interface MmsConfigHandler { - public void process(String key, String value, String type); - } - - private static final String TAG_MMS_CONFIG = "mms_config"; - - // Handler to process one mms_config key/value pair - private MmsConfigHandler mMmsConfigHandler; - - private final StringBuilder mLogStringBuilder = new StringBuilder(); - - private final XmlPullParser mInputParser; - - private MmsConfigXmlProcessor(XmlPullParser parser) { - mInputParser = parser; - mMmsConfigHandler = null; - } - - public static MmsConfigXmlProcessor get(XmlPullParser parser) { - return new MmsConfigXmlProcessor(parser); - } - - public MmsConfigXmlProcessor setMmsConfigHandler(MmsConfigHandler handler) { - mMmsConfigHandler = handler; - return this; - } - - /** - * Move XML parser forward to next event type or the end of doc - * - * @param eventType - * @return The final event type we meet - * @throws org.xmlpull.v1.XmlPullParserException - * @throws java.io.IOException - */ - private int advanceToNextEvent(int eventType) throws XmlPullParserException, IOException { - for (;;) { - int nextEvent = mInputParser.next(); - if (nextEvent == eventType - || nextEvent == XmlPullParser.END_DOCUMENT) { - return nextEvent; - } - } - } - - public void process() { - try { - // Find the first element - if (advanceToNextEvent(XmlPullParser.START_TAG) != XmlPullParser.START_TAG) { - throw new XmlPullParserException("MmsConfigXmlProcessor: expecting start tag @" - + xmlParserDebugContext()); - } - // A single ContentValues object for holding the parsing result of - // an apn element - final ContentValues values = new ContentValues(); - String tagName = mInputParser.getName(); - // Top level tag can be "apns" (apns.xml, or APN OTA XML) - // or "mms_config" (mms_config.xml) - if (TAG_MMS_CONFIG.equals(tagName)) { - // mms_config.xml resource - processMmsConfig(); - } - } catch (IOException e) { - Log.e(TAG, "MmsConfigXmlProcessor: I/O failure " + e, e); - } catch (XmlPullParserException e) { - Log.e(TAG, "MmsConfigXmlProcessor: parsing failure " + e, e); - } - } - - private static String xmlParserEventString(int event) { - switch (event) { - case XmlPullParser.START_DOCUMENT: return "START_DOCUMENT"; - case XmlPullParser.END_DOCUMENT: return "END_DOCUMENT"; - case XmlPullParser.START_TAG: return "START_TAG"; - case XmlPullParser.END_TAG: return "END_TAG"; - case XmlPullParser.TEXT: return "TEXT"; - } - return Integer.toString(event); - } - - /** - * @return The debugging information of the parser's current position - */ - private String xmlParserDebugContext() { - mLogStringBuilder.setLength(0); - if (mInputParser != null) { - try { - final int eventType = mInputParser.getEventType(); - mLogStringBuilder.append(xmlParserEventString(eventType)); - if (eventType == XmlPullParser.START_TAG - || eventType == XmlPullParser.END_TAG - || eventType == XmlPullParser.TEXT) { - mLogStringBuilder.append('<').append(mInputParser.getName()); - for (int i = 0; i < mInputParser.getAttributeCount(); i++) { - mLogStringBuilder.append(' ') - .append(mInputParser.getAttributeName(i)) - .append('=') - .append(mInputParser.getAttributeValue(i)); - } - mLogStringBuilder.append("/>"); - } - return mLogStringBuilder.toString(); - } catch (XmlPullParserException e) { - Log.e(TAG, "xmlParserDebugContext: " + e, e); - } - } - return "Unknown"; - } - - /** - * Process one mms_config. - * - * @throws java.io.IOException - * @throws org.xmlpull.v1.XmlPullParserException - */ - private void processMmsConfig() - throws IOException, XmlPullParserException { - // We are at the start tag - for (;;) { - int nextEvent; - // Skipping spaces - while ((nextEvent = mInputParser.next()) == XmlPullParser.TEXT); - if (nextEvent == XmlPullParser.START_TAG) { - // Parse one mms config key/value - processMmsConfigKeyValue(); - } else if (nextEvent == XmlPullParser.END_TAG) { - break; - } else { - throw new XmlPullParserException("MmsConfig: expecting start or end tag @" - + xmlParserDebugContext()); - } - } - } - - /** - * Process one mms_config key/value pair - * - * @throws java.io.IOException - * @throws org.xmlpull.v1.XmlPullParserException - */ - private void processMmsConfigKeyValue() throws IOException, XmlPullParserException { - final String key = mInputParser.getAttributeValue(null, "name"); - // We are at the start tag, the name of the tag is the type - // e.g. <int name="key">value</int> - final String type = mInputParser.getName(); - int nextEvent = mInputParser.next(); - String value = null; - if (nextEvent == XmlPullParser.TEXT) { - value = mInputParser.getText(); - nextEvent = mInputParser.next(); - } - if (nextEvent != XmlPullParser.END_TAG) { - throw new XmlPullParserException("MmsConfigXmlProcessor: expecting end tag @" - + xmlParserDebugContext()); - } - if (MmsConfig.isValidKey(key, type)) { - // We are done parsing one mms_config key/value, call the handler - if (mMmsConfigHandler != null) { - mMmsConfigHandler.process(key, value, type); - } - } else { - Log.w(TAG, "MmsConfig: invalid key=" + key + " or type=" + type); - } - } -} diff --git a/src/com/android/mms/service/MmsHttpClient.java b/src/com/android/mms/service/MmsHttpClient.java index 10b8aa2..da36f26 100644 --- a/src/com/android/mms/service/MmsHttpClient.java +++ b/src/com/android/mms/service/MmsHttpClient.java @@ -18,7 +18,12 @@ package com.android.mms.service; import android.content.Context; import android.net.Network; +import android.os.Bundle; +import android.telephony.SmsManager; +import android.telephony.SubscriptionManager; +import android.telephony.TelephonyManager; import android.text.TextUtils; +import android.util.Base64; import android.util.Log; import com.android.mms.service.exception.MmsHttpException; @@ -29,6 +34,7 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.io.UnsupportedEncodingException; import java.net.HttpURLConnection; import java.net.InetSocketAddress; import java.net.MalformedURLException; @@ -87,11 +93,12 @@ public class MmsHttpClient { * @param proxyHost The proxy host * @param proxyPort The proxy port * @param mmsConfig The MMS config to use + * @param subId The subscription ID used to get line number, etc. * @return The HTTP response body * @throws MmsHttpException For any failures */ public byte[] execute(String urlString, byte[] pdu, String method, boolean isProxySet, - String proxyHost, int proxyPort, MmsConfig.Overridden mmsConfig) + String proxyHost, int proxyPort, Bundle mmsConfig, int subId) throws MmsHttpException { Log.d(MmsService.TAG, "HTTP: " + method + " " + redactUrlForNonVerbose(urlString) + (isProxySet ? (", proxy=" + proxyHost + ":" + proxyPort) : "") @@ -107,7 +114,8 @@ public class MmsHttpClient { // Now get the connection connection = (HttpURLConnection) mNetwork.openConnection(url, proxy); connection.setDoInput(true); - connection.setConnectTimeout(mmsConfig.getHttpSocketTimeout()); + connection.setConnectTimeout( + mmsConfig.getInt(SmsManager.MMS_CONFIG_HTTP_SOCKET_TIMEOUT)); // ------- COMMON HEADERS --------- // Header: Accept connection.setRequestProperty(HEADER_ACCEPT, HEADER_VALUE_ACCEPT); @@ -115,18 +123,19 @@ public class MmsHttpClient { connection.setRequestProperty( HEADER_ACCEPT_LANGUAGE, getCurrentAcceptLanguage(Locale.getDefault())); // Header: User-Agent - final String userAgent = mmsConfig.getUserAgent(); + final String userAgent = mmsConfig.getString(SmsManager.MMS_CONFIG_USER_AGENT); Log.i(MmsService.TAG, "HTTP: User-Agent=" + userAgent); connection.setRequestProperty(HEADER_USER_AGENT, userAgent); // Header: x-wap-profile - final String uaProfUrlTagName = mmsConfig.getUaProfTagName(); - final String uaProfUrl = mmsConfig.getUaProfUrl(); + final String uaProfUrlTagName = + mmsConfig.getString(SmsManager.MMS_CONFIG_UA_PROF_TAG_NAME); + final String uaProfUrl = mmsConfig.getString(SmsManager.MMS_CONFIG_UA_PROF_URL); if (uaProfUrl != null) { Log.i(MmsService.TAG, "HTTP: UaProfUrl=" + uaProfUrl); connection.setRequestProperty(uaProfUrlTagName, uaProfUrl); } // Add extra headers specified by mms_config.xml's httpparams - addExtraHeaders(connection, mmsConfig); + addExtraHeaders(connection, mmsConfig, subId); // Different stuff for GET and POST if (METHOD_POST.equals(method)) { if (pdu == null || pdu.length < 1) { @@ -135,7 +144,7 @@ public class MmsHttpClient { } connection.setDoOutput(true); connection.setRequestMethod(METHOD_POST); - if (mmsConfig.getSupportHttpCharsetHeader()) { + if (mmsConfig.getBoolean(SmsManager.MMS_CONFIG_SUPPORT_HTTP_CHARSET_HEADER)) { connection.setRequestProperty(HEADER_CONTENT_TYPE, HEADER_VALUE_CONTENT_TYPE_WITH_CHARSET); } else { @@ -276,16 +285,45 @@ public class MmsHttpClient { } } + /** + * Add extra HTTP headers from mms_config.xml's httpParams, which is a list of key/value + * pairs separated by "|". Each key/value pair is separated by ":". Value may contain + * macros like "##LINE1##" or "##NAI##" which is resolved with methods in this class + * + * @param connection The HttpURLConnection that we add headers to + * @param mmsConfig The MmsConfig object + * @param subId The subscription ID used to get line number, etc. + */ + private void addExtraHeaders(HttpURLConnection connection, Bundle mmsConfig, int subId) { + final String extraHttpParams = mmsConfig.getString(SmsManager.MMS_CONFIG_HTTP_PARAMS); + if (!TextUtils.isEmpty(extraHttpParams)) { + // Parse the parameter list + String paramList[] = extraHttpParams.split("\\|"); + for (String paramPair : paramList) { + String splitPair[] = paramPair.split(":", 2); + if (splitPair.length == 2) { + final String name = splitPair[0].trim(); + final String value = + resolveMacro(mContext, splitPair[1].trim(), mmsConfig, subId); + if (!TextUtils.isEmpty(name) && !TextUtils.isEmpty(value)) { + // Add the header if the param is valid + connection.setRequestProperty(name, value); + } + } + } + } + } + private static final Pattern MACRO_P = Pattern.compile("##(\\S+)##"); /** * Resolve the macro in HTTP param value text * For example, "something##LINE1##something" is resolved to "something9139531419something" * * @param value The HTTP param value possibly containing macros - * @return The HTTP param with macro resolved to real value + * @param subId The subscription ID used to get line number, etc. + * @return The HTTP param with macros resolved to real value */ - private static String resolveMacro(Context context, String value, - MmsConfig.Overridden mmsConfig) { + private static String resolveMacro(Context context, String value, Bundle mmsConfig, int subId) { if (TextUtils.isEmpty(value)) { return value; } @@ -301,7 +339,7 @@ public class MmsHttpClient { replaced.append(value.substring(nextStart, matchedStart)); } final String macro = matcher.group(1); - final String macroValue = mmsConfig.getHttpParamMacro(context, macro); + final String macroValue = getMacroValue(context, macro, mmsConfig, subId); if (macroValue != null) { replaced.append(macroValue); } @@ -314,33 +352,6 @@ public class MmsHttpClient { } /** - * Add extra HTTP headers from mms_config.xml's httpParams, which is a list of key/value - * pairs separated by "|". Each key/value pair is separated by ":". Value may contain - * macros like "##LINE1##" or "##NAI##" which is resolved with methods in this class - * - * @param connection The HttpURLConnection that we add headers to - * @param mmsConfig The MmsConfig object - */ - private void addExtraHeaders(HttpURLConnection connection, MmsConfig.Overridden mmsConfig) { - final String extraHttpParams = mmsConfig.getHttpParams(); - if (!TextUtils.isEmpty(extraHttpParams)) { - // Parse the parameter list - String paramList[] = extraHttpParams.split("\\|"); - for (String paramPair : paramList) { - String splitPair[] = paramPair.split(":", 2); - if (splitPair.length == 2) { - final String name = splitPair[0].trim(); - final String value = resolveMacro(mContext, splitPair[1].trim(), mmsConfig); - if (!TextUtils.isEmpty(name) && !TextUtils.isEmpty(value)) { - // Add the header if the param is valid - connection.setRequestProperty(name, value); - } - } - } - } - } - - /** * Redact the URL for non-VERBOSE logging. Replace url with only the host part and the length * of the input URL string. * @@ -370,4 +381,88 @@ public class MmsHttpClient { .append("[").append(urlString.length()).append("]"); return sb.toString(); } + + /* + * Macro names + */ + // The raw phone number from TelephonyManager.getLine1Number + private static final String MACRO_LINE1 = "LINE1"; + // The phone number without country code + private static final String MACRO_LINE1NOCOUNTRYCODE = "LINE1NOCOUNTRYCODE"; + // NAI (Network Access Identifier), used by Sprint for authentication + private static final String MACRO_NAI = "NAI"; + /** + * Return the HTTP param macro value. + * Example: "LINE1" returns the phone number, etc. + * + * @param macro The macro name + * @param mmsConfig The MMS config which contains NAI suffix. + * @param subId The subscription ID used to get line number, etc. + * @return The value of the defined macro + */ + private static String getMacroValue(Context context, String macro, Bundle mmsConfig, + int subId) { + if (MACRO_LINE1.equals(macro)) { + return getLine1(context, subId); + } else if (MACRO_LINE1NOCOUNTRYCODE.equals(macro)) { + return getLine1NoCountryCode(context, subId); + } else if (MACRO_NAI.equals(macro)) { + return getNai(context, mmsConfig, subId); + } + Log.e(MmsService.TAG, "invalid macro " + macro); + return null; + } + + /** + * Returns the phone number for the given subscription ID. + */ + private static String getLine1(Context context, int subId) { + final TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService( + Context.TELEPHONY_SERVICE); + return telephonyManager.getLine1NumberForSubscriber(subId); + } + + /** + * Returns the phone number (without country code) for the given subscription ID. + */ + private static String getLine1NoCountryCode(Context context, int subId) { + final TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService( + Context.TELEPHONY_SERVICE); + return PhoneUtils.getNationalNumber( + telephonyManager, + subId, + telephonyManager.getLine1NumberForSubscriber(subId)); + } + + /** + * Returns the NAI (Network Access Identifier) from SystemProperties for the given subscription + * ID. + */ + private static String getNai(Context context, Bundle mmsConfig, int subId) { + final TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService( + Context.TELEPHONY_SERVICE); + String nai = telephonyManager.getNai(SubscriptionManager.getSlotId(subId)); + if (Log.isLoggable(MmsService.TAG, Log.VERBOSE)) { + Log.v(MmsService.TAG, "getNai: nai=" + nai); + } + + if (!TextUtils.isEmpty(nai)) { + String naiSuffix = mmsConfig.getString(SmsManager.MMS_CONFIG_NAI_SUFFIX); + if (!TextUtils.isEmpty(naiSuffix)) { + nai = nai + naiSuffix; + } + byte[] encoded = null; + try { + encoded = Base64.encode(nai.getBytes("UTF-8"), Base64.NO_WRAP); + } catch (UnsupportedEncodingException e) { + encoded = Base64.encode(nai.getBytes(), Base64.NO_WRAP); + } + try { + nai = new String(encoded, "UTF-8"); + } catch (UnsupportedEncodingException e) { + nai = new String(encoded); + } + } + return nai; + } } diff --git a/src/com/android/mms/service/MmsRequest.java b/src/com/android/mms/service/MmsRequest.java index f43f1b4..9255c16 100644 --- a/src/com/android/mms/service/MmsRequest.java +++ b/src/com/android/mms/service/MmsRequest.java @@ -25,6 +25,8 @@ import android.os.Bundle; import android.service.carrier.CarrierMessagingService; import android.service.carrier.ICarrierMessagingCallback; import android.telephony.SmsManager; +import android.telephony.TelephonyManager; +import android.text.TextUtils; import android.util.Log; import com.android.mms.service.exception.ApnException; @@ -77,17 +79,20 @@ public abstract class MmsRequest { // The creator app protected String mCreator; // MMS config - protected MmsConfig.Overridden mMmsConfig; - // MMS config overrides + protected Bundle mMmsConfig; + // MMS config overrides that will be applied to mMmsConfig when we eventually load it. protected Bundle mMmsConfigOverrides; + // Context used to get TelephonyManager. + protected Context mContext; public MmsRequest(RequestManager requestManager, int subId, String creator, - Bundle configOverrides) { + Bundle configOverrides, Context context) { mRequestManager = requestManager; mSubId = subId; mCreator = creator; mMmsConfigOverrides = configOverrides; mMmsConfig = null; + mContext = context; } public int getSubId() { @@ -97,9 +102,25 @@ public abstract class MmsRequest { private boolean ensureMmsConfigLoaded() { if (mMmsConfig == null) { // Not yet retrieved from mms config manager. Try getting it. - final MmsConfig config = MmsConfigManager.getInstance().getMmsConfigBySubId(mSubId); + final Bundle config = MmsConfigManager.getInstance().getMmsConfigBySubId(mSubId); if (config != null) { - mMmsConfig = new MmsConfig.Overridden(config, mMmsConfigOverrides); + mMmsConfig = config; + // TODO: Make MmsConfigManager authoritative for user agent and don't consult + // TelephonyManager. + TelephonyManager telephonyManager = + (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE); + String userAgent = telephonyManager.getMmsUserAgent(); + if (!TextUtils.isEmpty(userAgent)) { + config.putString(SmsManager.MMS_CONFIG_USER_AGENT, userAgent); + } + String userAgentProfileUrl = telephonyManager.getMmsUAProfUrl(); + if (!TextUtils.isEmpty(userAgentProfileUrl)) { + config.putString(SmsManager.MMS_CONFIG_UA_PROF_URL, userAgentProfileUrl); + } + // Apply overrides + if (mMmsConfigOverrides != null) { + mMmsConfig.putAll(mMmsConfigOverrides); + } } } return mMmsConfig != null; diff --git a/src/com/android/mms/service/MmsService.java b/src/com/android/mms/service/MmsService.java index b6058c9..c6a3b8f 100644 --- a/src/com/android/mms/service/MmsService.java +++ b/src/com/android/mms/service/MmsService.java @@ -172,7 +172,7 @@ public class MmsService extends Service implements MmsRequest.RequestManager { } final SendRequest request = new SendRequest(MmsService.this, subId, contentUri, - locationUrl, sentIntent, callingPkg, configOverrides); + locationUrl, sentIntent, callingPkg, configOverrides, MmsService.this); final String carrierMessagingServicePackage = getCarrierMessagingServicePackageIfExists(); @@ -199,8 +199,8 @@ public class MmsService extends Service implements MmsRequest.RequestManager { // download anyway. // TODO: Fail fast when downloading will fail (i.e. SIM swapped) - final DownloadRequest request = new DownloadRequest(MmsService.this, subId, - locationUrl, contentUri, downloadedIntent, callingPkg, configOverrides); + final DownloadRequest request = new DownloadRequest(MmsService.this, subId, locationUrl, + contentUri, downloadedIntent, callingPkg, configOverrides, MmsService.this); final String carrierMessagingServicePackage = getCarrierMessagingServicePackageIfExists(); if (carrierMessagingServicePackage != null) { @@ -215,11 +215,11 @@ public class MmsService extends Service implements MmsRequest.RequestManager { Log.d(TAG, "getCarrierConfigValues"); // Make sure the subId is correct subId = checkSubId(subId); - final MmsConfig mmsConfig = MmsConfigManager.getInstance().getMmsConfigBySubId(subId); + final Bundle mmsConfig = MmsConfigManager.getInstance().getMmsConfigBySubId(subId); if (mmsConfig == null) { return new Bundle(); } - return mmsConfig.getCarrierConfigValues(); + return mmsConfig; } @Override diff --git a/src/com/android/mms/service/SendRequest.java b/src/com/android/mms/service/SendRequest.java index 70d19b1..d1781b1 100644 --- a/src/com/android/mms/service/SendRequest.java +++ b/src/com/android/mms/service/SendRequest.java @@ -60,8 +60,8 @@ public class SendRequest extends MmsRequest { private final PendingIntent mSentIntent; public SendRequest(RequestManager manager, int subId, Uri contentUri, String locationUrl, - PendingIntent sentIntent, String creator, Bundle configOverrides) { - super(manager, subId, creator, configOverrides); + PendingIntent sentIntent, String creator, Bundle configOverrides, Context context) { + super(manager, subId, creator, configOverrides, context); mPduUri = contentUri; mPduData = null; mLocationUrl = locationUrl; @@ -83,7 +83,8 @@ public class SendRequest extends MmsRequest { apn.isProxySet(), apn.getProxyAddress(), apn.getProxyPort(), - mMmsConfig); + mMmsConfig, + mSubId); } @Override @@ -109,7 +110,8 @@ public class SendRequest extends MmsRequest { } final long identity = Binder.clearCallingIdentity(); try { - final boolean supportContentDisposition = mMmsConfig.getSupportMmsContentDisposition(); + final boolean supportContentDisposition = + mMmsConfig.getBoolean(SmsManager.MMS_CONFIG_SUPPORT_MMS_CONTENT_DISPOSITION); // Persist the request PDU first GenericPdu pdu = (new PduParser(mPduData, supportContentDisposition)).parse(); if (pdu == null) { @@ -185,7 +187,7 @@ public class SendRequest extends MmsRequest { if (mPduData != null) { return true; } - final int bytesTobeRead = mMmsConfig.getMaxMessageSize(); + final int bytesTobeRead = mMmsConfig.getInt(SmsManager.MMS_CONFIG_MAX_MESSAGE_SIZE); mPduData = mRequestManager.readPduFromContentUri(mPduUri, bytesTobeRead); return (mPduData != null); } |