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