• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 = LogTag.TAG;
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 
init(Context context)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 
isSmsEnabled(Context context)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 
isSmsPromoDismissed(Context context)135     public static boolean isSmsPromoDismissed(Context context) {
136         SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
137         return preferences.getBoolean(SMS_PROMO_DISMISSED_KEY, false);
138     }
139 
setSmsPromoDismissed(Context context)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 
getRequestDefaultSmsAppActivity()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 
getSmsToMmsTextThreshold()153     public static int getSmsToMmsTextThreshold() {
154         return mSmsToMmsTextThreshold;
155     }
156 
getMmsEnabled()157     public static boolean getMmsEnabled() {
158         return mMmsEnabled == 1 ? true : false;
159     }
160 
getMaxMessageSize()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      */
getTransIdEnabled()173     public static boolean getTransIdEnabled() {
174         return mTransIdEnabled;
175     }
176 
getUserAgent()177     public static String getUserAgent() {
178         return mUserAgent;
179     }
180 
getUaProfTagName()181     public static String getUaProfTagName() {
182         return mUaProfTagName;
183     }
184 
getUaProfUrl()185     public static String getUaProfUrl() {
186         return mUaProfUrl;
187     }
188 
getHttpParams()189     public static String getHttpParams() {
190         return mHttpParams;
191     }
192 
getHttpParamsLine1Key()193     public static String getHttpParamsLine1Key() {
194         return mHttpParamsLine1Key;
195     }
196 
getEmailGateway()197     public static String getEmailGateway() {
198         return mEmailGateway;
199     }
200 
getMaxImageHeight()201     public static int getMaxImageHeight() {
202         return mMaxImageHeight;
203     }
204 
getMaxImageWidth()205     public static int getMaxImageWidth() {
206         return mMaxImageWidth;
207     }
208 
getRecipientLimit()209     public static int getRecipientLimit() {
210         return mRecipientLimit;
211     }
212 
getMaxTextLimit()213     public static int getMaxTextLimit() {
214         return mMaxTextLength > -1 ? mMaxTextLength : MAX_TEXT_LENGTH;
215     }
216 
getDefaultSMSMessagesPerThread()217     public static int getDefaultSMSMessagesPerThread() {
218         return mDefaultSMSMessagesPerThread;
219     }
220 
getDefaultMMSMessagesPerThread()221     public static int getDefaultMMSMessagesPerThread() {
222         return mDefaultMMSMessagesPerThread;
223     }
224 
getMinMessageCountPerThread()225     public static int getMinMessageCountPerThread() {
226         return mMinMessageCountPerThread;
227     }
228 
getMaxMessageCountPerThread()229     public static int getMaxMessageCountPerThread() {
230         return mMaxMessageCountPerThread;
231     }
232 
getHttpSocketTimeout()233     public static int getHttpSocketTimeout() {
234         return mHttpSocketTimeout;
235     }
236 
getMinimumSlideElementDuration()237     public static int getMinimumSlideElementDuration() {
238         return mMinimumSlideElementDuration;
239     }
240 
getMultipartSmsEnabled()241     public static boolean getMultipartSmsEnabled() {
242         return mEnableMultipartSMS;
243     }
244 
getSlideDurationEnabled()245     public static boolean getSlideDurationEnabled() {
246         return mEnableSlideDuration;
247     }
248 
getMMSReadReportsEnabled()249     public static boolean getMMSReadReportsEnabled() {
250         return mEnableMMSReadReports;
251     }
252 
getSMSDeliveryReportsEnabled()253     public static boolean getSMSDeliveryReportsEnabled() {
254         return mEnableSMSDeliveryReports;
255     }
256 
getMMSDeliveryReportsEnabled()257     public static boolean getMMSDeliveryReportsEnabled() {
258         return mEnableMMSDeliveryReports;
259     }
260 
getNotifyWapMMSC()261     public static boolean getNotifyWapMMSC() {
262         return mNotifyWapMMSC;
263     }
264 
getMaxSizeScaleForPendingMmsAllowed()265     public static int getMaxSizeScaleForPendingMmsAllowed() {
266         return mMaxSizeScaleForPendingMmsAllowed;
267     }
268 
isAliasEnabled()269     public static boolean isAliasEnabled() {
270         return mAliasEnabled;
271     }
272 
getAliasMinChars()273     public static int getAliasMinChars() {
274         return mAliasRuleMinChars;
275     }
276 
getAliasMaxChars()277     public static int getAliasMaxChars() {
278         return mAliasRuleMaxChars;
279     }
280 
getAllowAttachAudio()281     public static boolean getAllowAttachAudio() {
282         return mAllowAttachAudio;
283     }
284 
getMaxSubjectLength()285     public static int getMaxSubjectLength() {
286         return mMaxSubjectLength;
287     }
288 
getGroupMmsEnabled()289     public static boolean getGroupMmsEnabled() {
290         return mEnableGroupMms;
291     }
292 
beginDocument(XmlPullParser parser, String firstElementName)293     public static final void beginDocument(XmlPullParser parser, String firstElementName) throws XmlPullParserException, IOException
294     {
295         int type;
296         while ((type=parser.next()) != XmlPullParser.START_TAG
297                    && type != XmlPullParser.END_DOCUMENT) {
298             ;
299         }
300 
301         if (type != XmlPullParser.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 
nextElement(XmlPullParser parser)311     public static final void nextElement(XmlPullParser parser) throws XmlPullParserException, IOException
312     {
313         int type;
314         while ((type=parser.next()) != XmlPullParser.START_TAG
315                    && type != XmlPullParser.END_DOCUMENT) {
316             ;
317         }
318     }
319 
loadMmsSettings(Context context)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