Home | History | Annotate | Download | only in mms
      1 /*
      2  * Copyright (C) 2009 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;
     18 
     19 import java.io.IOException;
     20 
     21 import org.xmlpull.v1.XmlPullParser;
     22 import org.xmlpull.v1.XmlPullParserException;
     23 
     24 import android.content.Context;
     25 import android.content.Intent;
     26 import android.content.SharedPreferences;
     27 import android.content.res.XmlResourceParser;
     28 import android.preference.PreferenceManager;
     29 import android.provider.Telephony;
     30 import android.text.TextUtils;
     31 import android.util.Log;
     32 
     33 import com.android.internal.telephony.TelephonyProperties;
     34 import com.android.mms.ui.MessageUtils;
     35 import com.android.mms.ui.MessagingPreferenceActivity;
     36 
     37 public class MmsConfig {
     38     private static final String TAG = "MmsConfig";
     39     private static final boolean DEBUG = true;
     40     private static final boolean LOCAL_LOGV = false;
     41 
     42     private static final String DEFAULT_HTTP_KEY_X_WAP_PROFILE = "x-wap-profile";
     43     private static final String DEFAULT_USER_AGENT = "Android-Mms/2.0";
     44 
     45     private static final String MMS_APP_PACKAGE = "com.android.mms";
     46 
     47     private static final String SMS_PROMO_DISMISSED_KEY = "sms_promo_dismissed_key";
     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      * Whether to hide MMS functionality from the user (i.e. SMS only).
     55      */
     56     private static boolean mTransIdEnabled = false;
     57     private static int mMmsEnabled = 1;                         // default to true
     58     private static int mMaxMessageSize = 300 * 1024;            // default to 300k max size
     59     private static String mUserAgent = DEFAULT_USER_AGENT;
     60     private static String mUaProfTagName = DEFAULT_HTTP_KEY_X_WAP_PROFILE;
     61     private static String mUaProfUrl = null;
     62     private static String mHttpParams = null;
     63     private static String mHttpParamsLine1Key = null;
     64     private static String mEmailGateway = null;
     65     private static int mMaxImageHeight = MAX_IMAGE_HEIGHT;      // default value
     66     private static int mMaxImageWidth = MAX_IMAGE_WIDTH;        // default value
     67     private static int mRecipientLimit = Integer.MAX_VALUE;     // default value
     68     private static int mDefaultSMSMessagesPerThread = 10000;    // default value
     69     private static int mDefaultMMSMessagesPerThread = 1000;     // default value
     70     private static int mMinMessageCountPerThread = 2;           // default value
     71     private static int mMaxMessageCountPerThread = 5000;        // default value
     72     private static int mHttpSocketTimeout = 60*1000;            // default to 1 min
     73     private static int mMinimumSlideElementDuration = 7;        // default to 7 sec
     74     private static boolean mNotifyWapMMSC = false;
     75     private static boolean mAllowAttachAudio = true;
     76 
     77     // If mEnableMultipartSMS is true, long sms messages are always sent as multi-part sms
     78     // messages, with no checked limit on the number of segments.
     79     // If mEnableMultipartSMS is false, then as soon as the user types a message longer
     80     // than a single segment (i.e. 140 chars), then the message will turn into and be sent
     81     // as an mms message. This feature exists for carriers that don't support multi-part sms's.
     82     private static boolean mEnableMultipartSMS = true;
     83 
     84     // If mEnableMultipartSMS is true and mSmsToMmsTextThreshold > 1, then multi-part SMS messages
     85     // will be converted into a single mms message. For example, if the mms_config.xml file
     86     // specifies <int name="smsToMmsTextThreshold">4</int>, then on the 5th sms segment, the
     87     // message will be converted to an mms.
     88     private static int mSmsToMmsTextThreshold = -1;
     89 
     90     private static boolean mEnableSlideDuration = true;
     91     private static boolean mEnableMMSReadReports = true;        // key: "enableMMSReadReports"
     92     private static boolean mEnableSMSDeliveryReports = true;    // key: "enableSMSDeliveryReports"
     93     private static boolean mEnableMMSDeliveryReports = true;    // key: "enableMMSDeliveryReports"
     94     private static int mMaxTextLength = -1;
     95 
     96     // This is the max amount of storage multiplied by mMaxMessageSize that we
     97     // allow of unsent messages before blocking the user from sending any more
     98     // MMS's.
     99     private static int mMaxSizeScaleForPendingMmsAllowed = 4;       // default value
    100 
    101     // Email gateway alias support, including the master switch and different rules
    102     private static boolean mAliasEnabled = false;
    103     private static int mAliasRuleMinChars = 2;
    104     private static int mAliasRuleMaxChars = 48;
    105 
    106     private static int mMaxSubjectLength = 40;  // maximum number of characters allowed for mms
    107                                                 // subject
    108 
    109     // If mEnableGroupMms is true, a message with multiple recipients, regardless of contents,
    110     // will be sent as a single MMS message with multiple "TO" fields set for each recipient.
    111     // If mEnableGroupMms is false, the group MMS setting/preference will be hidden in the settings
    112     // activity.
    113     private static boolean mEnableGroupMms = true;
    114 
    115     public static void init(Context context) {
    116         if (LOCAL_LOGV) {
    117             Log.v(TAG, "MmsConfig.init()");
    118         }
    119         // Always put the mnc/mcc in the log so we can tell which mms_config.xml was loaded.
    120         Log.v(TAG, "mnc/mcc: " +
    121                 android.os.SystemProperties.get(TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC));
    122 
    123         loadMmsSettings(context);
    124     }
    125 
    126     public static boolean isSmsEnabled(Context context) {
    127         String defaultSmsApplication = Telephony.Sms.getDefaultSmsPackage(context);
    128 
    129         if (defaultSmsApplication != null && defaultSmsApplication.equals(MMS_APP_PACKAGE)) {
    130             return true;
    131         }
    132         return false;
    133     }
    134 
    135     public static boolean isSmsPromoDismissed(Context context) {
    136         SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
    137         return preferences.getBoolean(SMS_PROMO_DISMISSED_KEY, false);
    138     }
    139 
    140     public static void setSmsPromoDismissed(Context context) {
    141         SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
    142         SharedPreferences.Editor editor = preferences.edit();
    143         editor.putBoolean(SMS_PROMO_DISMISSED_KEY, true);
    144         editor.apply();
    145     }
    146 
    147     public static Intent getRequestDefaultSmsAppActivity() {
    148         final Intent intent = new Intent(Telephony.Sms.Intents.ACTION_CHANGE_DEFAULT);
    149         intent.putExtra(Telephony.Sms.Intents.EXTRA_PACKAGE_NAME, MMS_APP_PACKAGE);
    150         return intent;
    151     }
    152 
    153     public static int getSmsToMmsTextThreshold() {
    154         return mSmsToMmsTextThreshold;
    155     }
    156 
    157     public static boolean getMmsEnabled() {
    158         return mMmsEnabled == 1 ? true : false;
    159     }
    160 
    161     public static int getMaxMessageSize() {
    162         if (LOCAL_LOGV) {
    163             Log.v(TAG, "MmsConfig.getMaxMessageSize(): " + mMaxMessageSize);
    164         }
    165        return mMaxMessageSize;
    166     }
    167 
    168     /**
    169      * This function returns the value of "enabledTransID" present in mms_config file.
    170      * In case of single segment wap push message, this "enabledTransID" indicates whether
    171      * TransactionID should be appended to URI or not.
    172      */
    173     public static boolean getTransIdEnabled() {
    174         return mTransIdEnabled;
    175     }
    176 
    177     public static String getUserAgent() {
    178         return mUserAgent;
    179     }
    180 
    181     public static String getUaProfTagName() {
    182         return mUaProfTagName;
    183     }
    184 
    185     public static String getUaProfUrl() {
    186         return mUaProfUrl;
    187     }
    188 
    189     public static String getHttpParams() {
    190         return mHttpParams;
    191     }
    192 
    193     public static String getHttpParamsLine1Key() {
    194         return mHttpParamsLine1Key;
    195     }
    196 
    197     public static String getEmailGateway() {
    198         return mEmailGateway;
    199     }
    200 
    201     public static int getMaxImageHeight() {
    202         return mMaxImageHeight;
    203     }
    204 
    205     public static int getMaxImageWidth() {
    206         return mMaxImageWidth;
    207     }
    208 
    209     public static int getRecipientLimit() {
    210         return mRecipientLimit;
    211     }
    212 
    213     public static int getMaxTextLimit() {
    214         return mMaxTextLength > -1 ? mMaxTextLength : MAX_TEXT_LENGTH;
    215     }
    216 
    217     public static int getDefaultSMSMessagesPerThread() {
    218         return mDefaultSMSMessagesPerThread;
    219     }
    220 
    221     public static int getDefaultMMSMessagesPerThread() {
    222         return mDefaultMMSMessagesPerThread;
    223     }
    224 
    225     public static int getMinMessageCountPerThread() {
    226         return mMinMessageCountPerThread;
    227     }
    228 
    229     public static int getMaxMessageCountPerThread() {
    230         return mMaxMessageCountPerThread;
    231     }
    232 
    233     public static int getHttpSocketTimeout() {
    234         return mHttpSocketTimeout;
    235     }
    236 
    237     public static int getMinimumSlideElementDuration() {
    238         return mMinimumSlideElementDuration;
    239     }
    240 
    241     public static boolean getMultipartSmsEnabled() {
    242         return mEnableMultipartSMS;
    243     }
    244 
    245     public static boolean getSlideDurationEnabled() {
    246         return mEnableSlideDuration;
    247     }
    248 
    249     public static boolean getMMSReadReportsEnabled() {
    250         return mEnableMMSReadReports;
    251     }
    252 
    253     public static boolean getSMSDeliveryReportsEnabled() {
    254         return mEnableSMSDeliveryReports;
    255     }
    256 
    257     public static boolean getMMSDeliveryReportsEnabled() {
    258         return mEnableMMSDeliveryReports;
    259     }
    260 
    261     public static boolean getNotifyWapMMSC() {
    262         return mNotifyWapMMSC;
    263     }
    264 
    265     public static int getMaxSizeScaleForPendingMmsAllowed() {
    266         return mMaxSizeScaleForPendingMmsAllowed;
    267     }
    268 
    269     public static boolean isAliasEnabled() {
    270         return mAliasEnabled;
    271     }
    272 
    273     public static int getAliasMinChars() {
    274         return mAliasRuleMinChars;
    275     }
    276 
    277     public static int getAliasMaxChars() {
    278         return mAliasRuleMaxChars;
    279     }
    280 
    281     public static boolean getAllowAttachAudio() {
    282         return mAllowAttachAudio;
    283     }
    284 
    285     public static int getMaxSubjectLength() {
    286         return mMaxSubjectLength;
    287     }
    288 
    289     public static boolean getGroupMmsEnabled() {
    290         return mEnableGroupMms;
    291     }
    292 
    293     public static final void beginDocument(XmlPullParser parser, String firstElementName) throws XmlPullParserException, IOException
    294     {
    295         int type;
    296         while ((type=parser.next()) != parser.START_TAG
    297                    && type != parser.END_DOCUMENT) {
    298             ;
    299         }
    300 
    301         if (type != parser.START_TAG) {
    302             throw new XmlPullParserException("No start tag found");
    303         }
    304 
    305         if (!parser.getName().equals(firstElementName)) {
    306             throw new XmlPullParserException("Unexpected start tag: found " + parser.getName() +
    307                     ", expected " + firstElementName);
    308         }
    309     }
    310 
    311     public static final void nextElement(XmlPullParser parser) throws XmlPullParserException, IOException
    312     {
    313         int type;
    314         while ((type=parser.next()) != parser.START_TAG
    315                    && type != parser.END_DOCUMENT) {
    316             ;
    317         }
    318     }
    319 
    320     private static void loadMmsSettings(Context context) {
    321         XmlResourceParser parser = context.getResources().getXml(R.xml.mms_config);
    322 
    323         try {
    324             beginDocument(parser, "mms_config");
    325 
    326             while (true) {
    327                 nextElement(parser);
    328                 String tag = parser.getName();
    329                 if (tag == null) {
    330                     break;
    331                 }
    332                 String name = parser.getAttributeName(0);
    333                 String value = parser.getAttributeValue(0);
    334                 String text = null;
    335                 if (parser.next() == XmlPullParser.TEXT) {
    336                     text = parser.getText();
    337                 }
    338 
    339                 if (DEBUG) {
    340                     Log.v(TAG, "tag: " + tag + " value: " + value + " - " +
    341                             text);
    342                 }
    343                 if ("name".equalsIgnoreCase(name)) {
    344                     if ("bool".equals(tag)) {
    345                         // bool config tags go here
    346                         if ("enabledMMS".equalsIgnoreCase(value)) {
    347                             mMmsEnabled = "true".equalsIgnoreCase(text) ? 1 : 0;
    348                         } else if ("enabledTransID".equalsIgnoreCase(value)) {
    349                             mTransIdEnabled = "true".equalsIgnoreCase(text);
    350                         } else if ("enabledNotifyWapMMSC".equalsIgnoreCase(value)) {
    351                             mNotifyWapMMSC = "true".equalsIgnoreCase(text);
    352                         } else if ("aliasEnabled".equalsIgnoreCase(value)) {
    353                             mAliasEnabled = "true".equalsIgnoreCase(text);
    354                         } else if ("allowAttachAudio".equalsIgnoreCase(value)) {
    355                             mAllowAttachAudio = "true".equalsIgnoreCase(text);
    356                         } else if ("enableMultipartSMS".equalsIgnoreCase(value)) {
    357                             mEnableMultipartSMS = "true".equalsIgnoreCase(text);
    358                         } else if ("enableSlideDuration".equalsIgnoreCase(value)) {
    359                             mEnableSlideDuration = "true".equalsIgnoreCase(text);
    360                         } else if ("enableMMSReadReports".equalsIgnoreCase(value)) {
    361                             mEnableMMSReadReports = "true".equalsIgnoreCase(text);
    362                         } else if ("enableSMSDeliveryReports".equalsIgnoreCase(value)) {
    363                             mEnableSMSDeliveryReports = "true".equalsIgnoreCase(text);
    364                         } else if ("enableMMSDeliveryReports".equalsIgnoreCase(value)) {
    365                             mEnableMMSDeliveryReports = "true".equalsIgnoreCase(text);
    366                         } else if ("enableGroupMms".equalsIgnoreCase(value)) {
    367                             mEnableGroupMms = "true".equalsIgnoreCase(text);
    368                         }
    369                     } else if ("int".equals(tag)) {
    370                         // int config tags go here
    371                         if ("maxMessageSize".equalsIgnoreCase(value)) {
    372                             mMaxMessageSize = Integer.parseInt(text);
    373                         } else if ("maxImageHeight".equalsIgnoreCase(value)) {
    374                             mMaxImageHeight = Integer.parseInt(text);
    375                         } else if ("maxImageWidth".equalsIgnoreCase(value)) {
    376                             mMaxImageWidth = Integer.parseInt(text);
    377                         } else if ("defaultSMSMessagesPerThread".equalsIgnoreCase(value)) {
    378                             mDefaultSMSMessagesPerThread = Integer.parseInt(text);
    379                         } else if ("defaultMMSMessagesPerThread".equalsIgnoreCase(value)) {
    380                             mDefaultMMSMessagesPerThread = Integer.parseInt(text);
    381                         } else if ("minMessageCountPerThread".equalsIgnoreCase(value)) {
    382                             mMinMessageCountPerThread = Integer.parseInt(text);
    383                         } else if ("maxMessageCountPerThread".equalsIgnoreCase(value)) {
    384                             mMaxMessageCountPerThread = Integer.parseInt(text);
    385                         } else if ("recipientLimit".equalsIgnoreCase(value)) {
    386                             mRecipientLimit = Integer.parseInt(text);
    387                             if (mRecipientLimit < 0) {
    388                                 mRecipientLimit = Integer.MAX_VALUE;
    389                             }
    390                         } else if ("httpSocketTimeout".equalsIgnoreCase(value)) {
    391                             mHttpSocketTimeout = Integer.parseInt(text);
    392                         } else if ("minimumSlideElementDuration".equalsIgnoreCase(value)) {
    393                             mMinimumSlideElementDuration = Integer.parseInt(text);
    394                         } else if ("maxSizeScaleForPendingMmsAllowed".equalsIgnoreCase(value)) {
    395                             mMaxSizeScaleForPendingMmsAllowed = Integer.parseInt(text);
    396                         } else if ("aliasMinChars".equalsIgnoreCase(value)) {
    397                             mAliasRuleMinChars = Integer.parseInt(text);
    398                         } else if ("aliasMaxChars".equalsIgnoreCase(value)) {
    399                             mAliasRuleMaxChars = Integer.parseInt(text);
    400                         } else if ("smsToMmsTextThreshold".equalsIgnoreCase(value)) {
    401                             mSmsToMmsTextThreshold = Integer.parseInt(text);
    402                         } else if ("maxMessageTextSize".equalsIgnoreCase(value)) {
    403                             mMaxTextLength = Integer.parseInt(text);
    404                         } else if ("maxSubjectLength".equalsIgnoreCase(value)) {
    405                             mMaxSubjectLength = Integer.parseInt(text);
    406                         }
    407                     } else if ("string".equals(tag)) {
    408                         // string config tags go here
    409                         if ("userAgent".equalsIgnoreCase(value)) {
    410                             mUserAgent = text;
    411                         } else if ("uaProfTagName".equalsIgnoreCase(value)) {
    412                             mUaProfTagName = text;
    413                         } else if ("uaProfUrl".equalsIgnoreCase(value)) {
    414                             mUaProfUrl = text;
    415                         } else if ("httpParams".equalsIgnoreCase(value)) {
    416                             mHttpParams = text;
    417                         } else if ("httpParamsLine1Key".equalsIgnoreCase(value)) {
    418                             mHttpParamsLine1Key = text;
    419                         } else if ("emailGatewayNumber".equalsIgnoreCase(value)) {
    420                             mEmailGateway = text;
    421                         }
    422                     }
    423                 }
    424             }
    425         } catch (XmlPullParserException e) {
    426             Log.e(TAG, "loadMmsSettings caught ", e);
    427         } catch (NumberFormatException e) {
    428             Log.e(TAG, "loadMmsSettings caught ", e);
    429         } catch (IOException e) {
    430             Log.e(TAG, "loadMmsSettings caught ", e);
    431         } finally {
    432             parser.close();
    433         }
    434 
    435         String errorStr = null;
    436 
    437         if (getMmsEnabled() && mUaProfUrl == null) {
    438             errorStr = "uaProfUrl";
    439         }
    440 
    441         if (errorStr != null) {
    442             String err =
    443                 String.format("MmsConfig.loadMmsSettings mms_config.xml missing %s setting",
    444                         errorStr);
    445             Log.e(TAG, err);
    446         }
    447     }
    448 
    449 }
    450