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.res.XmlResourceParser; 26 import android.util.Log; 27 28 import com.android.internal.telephony.TelephonyProperties; 29 30 public 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 // If mEnableMultipartSMS is true, long sms messages are always sent as multi-part sms 67 // messages, with no checked limit on the number of segments. 68 // If mEnableMultipartSMS is false, then as soon as the user types a message longer 69 // than a single segment (i.e. 140 chars), then the message will turn into and be sent 70 // as an mms message. This feature exists for carriers that don't support multi-part sms's. 71 private static boolean mEnableMultipartSMS = true; 72 73 // If mEnableMultipartSMS is true and mSmsToMmsTextThreshold > 1, then multi-part SMS messages 74 // will be converted into a single mms message. For example, if the mms_config.xml file 75 // specifies <int name="smsToMmsTextThreshold">4</int>, then on the 5th sms segment, the 76 // message will be converted to an mms. 77 private static int mSmsToMmsTextThreshold = -1; 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 // If mEnableGroupMms is true, a message with multiple recipients, regardless of contents, 99 // will be sent as a single MMS message with multiple "TO" fields set for each recipient. 100 // If mEnableGroupMms is false, the group MMS setting/preference will be hidden in the settings 101 // activity. 102 private static boolean mEnableGroupMms = true; 103 104 public static void init(Context context) { 105 if (LOCAL_LOGV) { 106 Log.v(TAG, "MmsConfig.init()"); 107 } 108 // Always put the mnc/mcc in the log so we can tell which mms_config.xml was loaded. 109 Log.v(TAG, "mnc/mcc: " + 110 android.os.SystemProperties.get(TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC)); 111 112 loadMmsSettings(context); 113 } 114 115 public static int getSmsToMmsTextThreshold() { 116 return mSmsToMmsTextThreshold; 117 } 118 119 public static boolean getMmsEnabled() { 120 return mMmsEnabled == 1 ? true : false; 121 } 122 123 public static int getMaxMessageSize() { 124 if (LOCAL_LOGV) { 125 Log.v(TAG, "MmsConfig.getMaxMessageSize(): " + mMaxMessageSize); 126 } 127 return mMaxMessageSize; 128 } 129 130 /** 131 * This function returns the value of "enabledTransID" present in mms_config file. 132 * In case of single segment wap push message, this "enabledTransID" indicates whether 133 * TransactionID should be appended to URI or not. 134 */ 135 public static boolean getTransIdEnabled() { 136 return mTransIdEnabled; 137 } 138 139 public static String getUserAgent() { 140 return mUserAgent; 141 } 142 143 public static String getUaProfTagName() { 144 return mUaProfTagName; 145 } 146 147 public static String getUaProfUrl() { 148 return mUaProfUrl; 149 } 150 151 public static String getHttpParams() { 152 return mHttpParams; 153 } 154 155 public static String getHttpParamsLine1Key() { 156 return mHttpParamsLine1Key; 157 } 158 159 public static String getEmailGateway() { 160 return mEmailGateway; 161 } 162 163 public static int getMaxImageHeight() { 164 return mMaxImageHeight; 165 } 166 167 public static int getMaxImageWidth() { 168 return mMaxImageWidth; 169 } 170 171 public static int getRecipientLimit() { 172 return mRecipientLimit; 173 } 174 175 public static int getMaxTextLimit() { 176 return mMaxTextLength > -1 ? mMaxTextLength : MAX_TEXT_LENGTH; 177 } 178 179 public static int getDefaultSMSMessagesPerThread() { 180 return mDefaultSMSMessagesPerThread; 181 } 182 183 public static int getDefaultMMSMessagesPerThread() { 184 return mDefaultMMSMessagesPerThread; 185 } 186 187 public static int getMinMessageCountPerThread() { 188 return mMinMessageCountPerThread; 189 } 190 191 public static int getMaxMessageCountPerThread() { 192 return mMaxMessageCountPerThread; 193 } 194 195 public static int getHttpSocketTimeout() { 196 return mHttpSocketTimeout; 197 } 198 199 public static int getMinimumSlideElementDuration() { 200 return mMinimumSlideElementDuration; 201 } 202 203 public static boolean getMultipartSmsEnabled() { 204 return mEnableMultipartSMS; 205 } 206 207 public static boolean getSlideDurationEnabled() { 208 return mEnableSlideDuration; 209 } 210 211 public static boolean getMMSReadReportsEnabled() { 212 return mEnableMMSReadReports; 213 } 214 215 public static boolean getSMSDeliveryReportsEnabled() { 216 return mEnableSMSDeliveryReports; 217 } 218 219 public static boolean getMMSDeliveryReportsEnabled() { 220 return mEnableMMSDeliveryReports; 221 } 222 223 public static boolean getNotifyWapMMSC() { 224 return mNotifyWapMMSC; 225 } 226 227 public static int getMaxSizeScaleForPendingMmsAllowed() { 228 return mMaxSizeScaleForPendingMmsAllowed; 229 } 230 231 public static boolean isAliasEnabled() { 232 return mAliasEnabled; 233 } 234 235 public static int getAliasMinChars() { 236 return mAliasRuleMinChars; 237 } 238 239 public static int getAliasMaxChars() { 240 return mAliasRuleMaxChars; 241 } 242 243 public static boolean getAllowAttachAudio() { 244 return mAllowAttachAudio; 245 } 246 247 public static int getMaxSubjectLength() { 248 return mMaxSubjectLength; 249 } 250 251 public static boolean getGroupMmsEnabled() { 252 return mEnableGroupMms; 253 } 254 255 public static final void beginDocument(XmlPullParser parser, String firstElementName) throws XmlPullParserException, IOException 256 { 257 int type; 258 while ((type=parser.next()) != parser.START_TAG 259 && type != parser.END_DOCUMENT) { 260 ; 261 } 262 263 if (type != parser.START_TAG) { 264 throw new XmlPullParserException("No start tag found"); 265 } 266 267 if (!parser.getName().equals(firstElementName)) { 268 throw new XmlPullParserException("Unexpected start tag: found " + parser.getName() + 269 ", expected " + firstElementName); 270 } 271 } 272 273 public static final void nextElement(XmlPullParser parser) throws XmlPullParserException, IOException 274 { 275 int type; 276 while ((type=parser.next()) != parser.START_TAG 277 && type != parser.END_DOCUMENT) { 278 ; 279 } 280 } 281 282 private static void loadMmsSettings(Context context) { 283 XmlResourceParser parser = context.getResources().getXml(R.xml.mms_config); 284 285 try { 286 beginDocument(parser, "mms_config"); 287 288 while (true) { 289 nextElement(parser); 290 String tag = parser.getName(); 291 if (tag == null) { 292 break; 293 } 294 String name = parser.getAttributeName(0); 295 String value = parser.getAttributeValue(0); 296 String text = null; 297 if (parser.next() == XmlPullParser.TEXT) { 298 text = parser.getText(); 299 } 300 301 if (DEBUG) { 302 Log.v(TAG, "tag: " + tag + " value: " + value + " - " + 303 text); 304 } 305 if ("name".equalsIgnoreCase(name)) { 306 if ("bool".equals(tag)) { 307 // bool config tags go here 308 if ("enabledMMS".equalsIgnoreCase(value)) { 309 mMmsEnabled = "true".equalsIgnoreCase(text) ? 1 : 0; 310 } else if ("enabledTransID".equalsIgnoreCase(value)) { 311 mTransIdEnabled = "true".equalsIgnoreCase(text); 312 } else if ("enabledNotifyWapMMSC".equalsIgnoreCase(value)) { 313 mNotifyWapMMSC = "true".equalsIgnoreCase(text); 314 } else if ("aliasEnabled".equalsIgnoreCase(value)) { 315 mAliasEnabled = "true".equalsIgnoreCase(text); 316 } else if ("allowAttachAudio".equalsIgnoreCase(value)) { 317 mAllowAttachAudio = "true".equalsIgnoreCase(text); 318 } else if ("enableMultipartSMS".equalsIgnoreCase(value)) { 319 mEnableMultipartSMS = "true".equalsIgnoreCase(text); 320 } else if ("enableSlideDuration".equalsIgnoreCase(value)) { 321 mEnableSlideDuration = "true".equalsIgnoreCase(text); 322 } else if ("enableMMSReadReports".equalsIgnoreCase(value)) { 323 mEnableMMSReadReports = "true".equalsIgnoreCase(text); 324 } else if ("enableSMSDeliveryReports".equalsIgnoreCase(value)) { 325 mEnableSMSDeliveryReports = "true".equalsIgnoreCase(text); 326 } else if ("enableMMSDeliveryReports".equalsIgnoreCase(value)) { 327 mEnableMMSDeliveryReports = "true".equalsIgnoreCase(text); 328 } else if ("enableGroupMms".equalsIgnoreCase(value)) { 329 mEnableGroupMms = "true".equalsIgnoreCase(text); 330 } 331 } else if ("int".equals(tag)) { 332 // int config tags go here 333 if ("maxMessageSize".equalsIgnoreCase(value)) { 334 mMaxMessageSize = Integer.parseInt(text); 335 } else if ("maxImageHeight".equalsIgnoreCase(value)) { 336 mMaxImageHeight = Integer.parseInt(text); 337 } else if ("maxImageWidth".equalsIgnoreCase(value)) { 338 mMaxImageWidth = Integer.parseInt(text); 339 } else if ("defaultSMSMessagesPerThread".equalsIgnoreCase(value)) { 340 mDefaultSMSMessagesPerThread = Integer.parseInt(text); 341 } else if ("defaultMMSMessagesPerThread".equalsIgnoreCase(value)) { 342 mDefaultMMSMessagesPerThread = Integer.parseInt(text); 343 } else if ("minMessageCountPerThread".equalsIgnoreCase(value)) { 344 mMinMessageCountPerThread = Integer.parseInt(text); 345 } else if ("maxMessageCountPerThread".equalsIgnoreCase(value)) { 346 mMaxMessageCountPerThread = Integer.parseInt(text); 347 } else if ("recipientLimit".equalsIgnoreCase(value)) { 348 mRecipientLimit = Integer.parseInt(text); 349 if (mRecipientLimit < 0) { 350 mRecipientLimit = Integer.MAX_VALUE; 351 } 352 } else if ("httpSocketTimeout".equalsIgnoreCase(value)) { 353 mHttpSocketTimeout = Integer.parseInt(text); 354 } else if ("minimumSlideElementDuration".equalsIgnoreCase(value)) { 355 mMinimumSlideElementDuration = Integer.parseInt(text); 356 } else if ("maxSizeScaleForPendingMmsAllowed".equalsIgnoreCase(value)) { 357 mMaxSizeScaleForPendingMmsAllowed = Integer.parseInt(text); 358 } else if ("aliasMinChars".equalsIgnoreCase(value)) { 359 mAliasRuleMinChars = Integer.parseInt(text); 360 } else if ("aliasMaxChars".equalsIgnoreCase(value)) { 361 mAliasRuleMaxChars = Integer.parseInt(text); 362 } else if ("smsToMmsTextThreshold".equalsIgnoreCase(value)) { 363 mSmsToMmsTextThreshold = Integer.parseInt(text); 364 } else if ("maxMessageTextSize".equalsIgnoreCase(value)) { 365 mMaxTextLength = Integer.parseInt(text); 366 } else if ("maxSubjectLength".equalsIgnoreCase(value)) { 367 mMaxSubjectLength = Integer.parseInt(text); 368 } 369 } else if ("string".equals(tag)) { 370 // string config tags go here 371 if ("userAgent".equalsIgnoreCase(value)) { 372 mUserAgent = text; 373 } else if ("uaProfTagName".equalsIgnoreCase(value)) { 374 mUaProfTagName = text; 375 } else if ("uaProfUrl".equalsIgnoreCase(value)) { 376 mUaProfUrl = text; 377 } else if ("httpParams".equalsIgnoreCase(value)) { 378 mHttpParams = text; 379 } else if ("httpParamsLine1Key".equalsIgnoreCase(value)) { 380 mHttpParamsLine1Key = text; 381 } else if ("emailGatewayNumber".equalsIgnoreCase(value)) { 382 mEmailGateway = text; 383 } 384 } 385 } 386 } 387 } catch (XmlPullParserException e) { 388 Log.e(TAG, "loadMmsSettings caught ", e); 389 } catch (NumberFormatException e) { 390 Log.e(TAG, "loadMmsSettings caught ", e); 391 } catch (IOException e) { 392 Log.e(TAG, "loadMmsSettings caught ", e); 393 } finally { 394 parser.close(); 395 } 396 397 String errorStr = null; 398 399 if (getMmsEnabled() && mUaProfUrl == null) { 400 errorStr = "uaProfUrl"; 401 } 402 403 if (errorStr != null) { 404 String err = 405 String.format("MmsConfig.loadMmsSettings mms_config.xml missing %s setting", 406 errorStr); 407 Log.e(TAG, err); 408 } 409 } 410 411 } 412