Merge "Fix assertion failures caused by different instance type"
diff --git a/src/android/support/v7/mms/CarrierConfigValuesLoader.java b/src/android/support/v7/mms/CarrierConfigValuesLoader.java
index 150d92d..1cb5226 100644
--- a/src/android/support/v7/mms/CarrierConfigValuesLoader.java
+++ b/src/android/support/v7/mms/CarrierConfigValuesLoader.java
@@ -174,7 +174,7 @@
     /**
      * String value: name for the user agent profile HTTP header
      */
-    public static final String CONFIG_UA_PROF_TAG_NAME = "mUaProfTagName";
+    public static final String CONFIG_UA_PROF_TAG_NAME = "uaProfTagName";
     public static final String CONFIG_UA_PROF_TAG_NAME_DEFAULT = "x-wap-profile";
     /**
      * String value: additional HTTP headers for MMS HTTP requests.
@@ -195,4 +195,14 @@
      */
     public static final String CONFIG_NAI_SUFFIX = "naiSuffix";
     public static final String CONFIG_NAI_SUFFIX_DEFAULT = null;
+    /**
+     * String value: Url for user agent profile
+     */
+    public static final String CONFIG_UA_PROF_URL = "uaProfUrl";
+    public static final String CONFIG_UA_PROF_URL_DEFAULT = null;
+    /**
+     * String value: user agent
+     */
+    public static final String CONFIG_USER_AGENT = "userAgent";
+    public static final String CONFIG_USER_AGENT_DEFAULT = null;
 }
diff --git a/src/com/android/messaging/datamodel/action/DownloadMmsAction.java b/src/com/android/messaging/datamodel/action/DownloadMmsAction.java
index 7a8c907..2852a61 100644
--- a/src/com/android/messaging/datamodel/action/DownloadMmsAction.java
+++ b/src/com/android/messaging/datamodel/action/DownloadMmsAction.java
@@ -82,6 +82,7 @@
     private static final String KEY_SUB_PHONE_NUMBER = "sub_phone_number";
     private static final String KEY_AUTO_DOWNLOAD = "auto_download";
     private static final String KEY_FAILURE_STATUS = "failure_status";
+    private static final String KEY_EXPIRY = "expiry";
 
     // Values we attach to the pending intent that's fired when the message is downloaded.
     // Only applicable when downloading via the platform APIs on L+.
@@ -97,6 +98,7 @@
     public static final String EXTRA_CONVERSATION_ID = "conversation_id";
     public static final String EXTRA_PARTICIPANT_ID = "participant_id";
     public static final String EXTRA_STATUS_IF_FAILED = "status_if_failed";
+    public static final String EXTRA_EXPIRY = "expiry";
 
     private DownloadMmsAction() {
         super();
@@ -130,6 +132,7 @@
             actionParameters.putString(KEY_TRANSACTION_ID, message.getMmsTransactionId());
             actionParameters.putParcelable(KEY_NOTIFICATION_URI, notificationUri);
             actionParameters.putBoolean(KEY_AUTO_DOWNLOAD, isAutoDownload(status));
+            actionParameters.putLong(KEY_EXPIRY, message.getMmsExpiry());
 
             final long now = System.currentTimeMillis();
             if (message.getInDownloadWindow(now)) {
@@ -239,6 +242,7 @@
         final String conversationId = actionParameters.getString(KEY_CONVERSATION_ID);
         final String participantId = actionParameters.getString(KEY_PARTICIPANT_ID);
         final int statusIfFailed = actionParameters.getInt(KEY_FAILURE_STATUS);
+        final long expiry = actionParameters.getLong(KEY_EXPIRY);
 
         final long receivedTimestampRoundedToSecond =
                 1000 * ((System.currentTimeMillis() + 500) / 1000);
@@ -256,7 +260,7 @@
         // Start the download
         final MmsUtils.StatusPlusUri status = MmsUtils.downloadMmsMessage(context,
                 notificationUri, subId, subPhoneNumber, transactionId, contentLocation,
-                autoDownload, receivedTimestampRoundedToSecond / 1000L, extras);
+                autoDownload, receivedTimestampRoundedToSecond / 1000L, expiry / 1000L, extras);
         if (status == MmsUtils.STATUS_PENDING) {
             // Async download; no status yet
             if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
diff --git a/src/com/android/messaging/datamodel/action/ProcessDownloadedMmsAction.java b/src/com/android/messaging/datamodel/action/ProcessDownloadedMmsAction.java
index 757ea05..07e2cfb 100644
--- a/src/com/android/messaging/datamodel/action/ProcessDownloadedMmsAction.java
+++ b/src/com/android/messaging/datamodel/action/ProcessDownloadedMmsAction.java
@@ -78,6 +78,7 @@
     private static final String KEY_CONTENT_LOCATION = "content_location";
     private static final String KEY_AUTO_DOWNLOAD = "auto_download";
     private static final String KEY_RECEIVED_TIMESTAMP = "received_timestamp";
+    private static final String KEY_EXPIRY = "expiry";
 
     // Set when message downloaded by us (legacy)
     private static final String KEY_STATUS = "status";
@@ -130,6 +131,7 @@
         params.putString(KEY_PARTICIPANT_ID, participantId);
         params.putInt(KEY_STATUS_IF_FAILED,
                 extras.getInt(DownloadMmsAction.EXTRA_STATUS_IF_FAILED));
+        params.putLong(KEY_EXPIRY, extras.getLong(DownloadMmsAction.EXTRA_EXPIRY));
         action.start();
     }
 
@@ -279,6 +281,7 @@
                                 KEY_AUTO_DOWNLOAD);
                         final long receivedTimestampInSeconds =
                                 actionParameters.getLong(KEY_RECEIVED_TIMESTAMP);
+                        final long expiry = actionParameters.getLong(KEY_EXPIRY);
 
                         // Inform sync we're adding a message to telephony
                         final SyncManager syncManager = DataModel.get().getSyncManager();
@@ -288,7 +291,7 @@
                                 MmsUtils.insertDownloadedMessageAndSendResponse(context,
                                         notificationUri, subId, subPhoneNumber, transactionId,
                                         contentLocation, autoDownload, receivedTimestampInSeconds,
-                                        retrieveConf);
+                                        expiry, retrieveConf);
                         status = result.status;
                         rawStatus = result.rawStatus;
                         mmsUri = result.uri;
diff --git a/src/com/android/messaging/datamodel/action/SyncMessageBatch.java b/src/com/android/messaging/datamodel/action/SyncMessageBatch.java
index 972d691..a623666 100644
--- a/src/com/android/messaging/datamodel/action/SyncMessageBatch.java
+++ b/src/com/android/messaging/datamodel/action/SyncMessageBatch.java
@@ -202,11 +202,11 @@
         // For a message we sync either
         if (isOutgoing) {
             // Outgoing message not yet been sent
-            if (type == Telephony.Sms.MESSAGE_TYPE_FAILED ||
-                    type == Telephony.Sms.MESSAGE_TYPE_OUTBOX ||
-                    type == Telephony.Sms.MESSAGE_TYPE_QUEUED ||
-                    (type == Telephony.Sms.MESSAGE_TYPE_SENT &&
-                     status == Telephony.Sms.STATUS_FAILED)) {
+            if (type == Telephony.Sms.MESSAGE_TYPE_FAILED
+                    || type == Telephony.Sms.MESSAGE_TYPE_OUTBOX
+                    || type == Telephony.Sms.MESSAGE_TYPE_QUEUED
+                    || (type == Telephony.Sms.MESSAGE_TYPE_SENT
+                            && status >= Telephony.Sms.STATUS_FAILED)) {
                 // Not sent counts as failed and available for manual resend
                 bugleStatus = MessageData.BUGLE_STATUS_OUTGOING_FAILED;
             } else if (status == Sms.STATUS_COMPLETE) {
diff --git a/src/com/android/messaging/datamodel/data/MessageData.java b/src/com/android/messaging/datamodel/data/MessageData.java
index a3698a9..cb5311e 100644
--- a/src/com/android/messaging/datamodel/data/MessageData.java
+++ b/src/com/android/messaging/datamodel/data/MessageData.java
@@ -540,6 +540,10 @@
         return mSeen;
     }
 
+    public final long getMmsExpiry() {
+        return mMmsExpiry;
+    }
+
     /**
      * For incoming MMS messages this returns the retrieve-status value
      * For sent MMS messages this returns the response-status value
diff --git a/src/com/android/messaging/receiver/SendStatusReceiver.java b/src/com/android/messaging/receiver/SendStatusReceiver.java
index fc0e8c9..3af65f2 100644
--- a/src/com/android/messaging/receiver/SendStatusReceiver.java
+++ b/src/com/android/messaging/receiver/SendStatusReceiver.java
@@ -20,6 +20,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.net.Uri;
+import android.provider.Telephony.Sms;
 import android.telephony.SmsMessage;
 
 import com.android.messaging.datamodel.action.ProcessDeliveryReportAction;
@@ -81,9 +82,32 @@
                 LogUtil.e(LogUtil.BUGLE_TAG, "SendStatusReceiver: empty report message");
                 return;
             }
-            int status = 0;
+            int status = Sms.STATUS_COMPLETE;
             try {
+                final String format = intent.getStringExtra("format");
                 status = smsMessage.getStatus();
+                // Simple matching up CDMA status with GSM status.
+                if (SmsMessage.FORMAT_3GPP2.equals(format)) {
+                    final int errorClass = (status >> 24) & 0x03;
+                    final int statusCode = (status >> 16) & 0x3f;
+                    switch (errorClass) {
+                        case 0: /*ERROR_NONE*/
+                            if (statusCode == 0x02 /*STATUS_DELIVERED*/) {
+                                status = Sms.STATUS_COMPLETE;
+                            } else status = Sms.STATUS_PENDING;
+                            break;
+                        case 2: /*ERROR_TEMPORARY*/
+                            // TODO: Need to check whether SC still trying to deliver the SMS to
+                            // destination and will send the report again?
+                            status = Sms.STATUS_PENDING;
+                            break;
+                        case 3: /*ERROR_PERMANENT*/
+                            status = Sms.STATUS_FAILED;
+                            break;
+                        default:
+                            status = Sms.STATUS_PENDING;
+                    }
+                }
             } catch (final NullPointerException e) {
                 // Sometimes, SmsMessage.mWrappedSmsMessage is null causing NPE when we access
                 // the methods on it although the SmsMessage itself is not null.
diff --git a/src/com/android/messaging/receiver/SmsReceiver.java b/src/com/android/messaging/receiver/SmsReceiver.java
index 859beff..b54359f 100644
--- a/src/com/android/messaging/receiver/SmsReceiver.java
+++ b/src/com/android/messaging/receiver/SmsReceiver.java
@@ -192,7 +192,7 @@
                 intent, EXTRA_SUB_ID);
         deliverSmsMessages(context, subId, errorCode, messages);
         if (MmsUtils.isDumpSmsEnabled()) {
-            final String format = null;
+            final String format = intent.getStringExtra("format");
             DebugUtils.dumpSms(messages[0].getTimestampMillis(), messages, format);
         }
     }
diff --git a/src/com/android/messaging/sms/MmsConfig.java b/src/com/android/messaging/sms/MmsConfig.java
index 5649be4..187e677 100755
--- a/src/com/android/messaging/sms/MmsConfig.java
+++ b/src/com/android/messaging/sms/MmsConfig.java
@@ -90,6 +90,8 @@
         sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_HTTP_PARAMS, KEY_TYPE_STRING);
         sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_EMAIL_GATEWAY_NUMBER, KEY_TYPE_STRING);
         sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_NAI_SUFFIX, KEY_TYPE_STRING);
+        sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_UA_PROF_URL, KEY_TYPE_STRING);
+        sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_USER_AGENT, KEY_TYPE_STRING);
     }
 
     // A map that stores all MmsConfigs, one per active subscription. For pre-LMSim, this will
diff --git a/src/com/android/messaging/sms/MmsUtils.java b/src/com/android/messaging/sms/MmsUtils.java
index 9c4c2d5..fbecd8b 100644
--- a/src/com/android/messaging/sms/MmsUtils.java
+++ b/src/com/android/messaging/sms/MmsUtils.java
@@ -952,7 +952,7 @@
     // Persist a received MMS message in telephony
     public static Uri insertReceivedMmsMessage(final Context context,
             final RetrieveConf retrieveConf, final int subId, final String subPhoneNumber,
-            final long receivedTimestampInSeconds, final String contentLocation) {
+            final long receivedTimestampInSeconds, final long expiry, final String transactionId) {
         final PduPersister persister = PduPersister.getPduPersister(context);
         Uri uri = null;
         try {
@@ -963,12 +963,13 @@
                     subPhoneNumber,
                     null/*preOpenedFiles*/);
 
-            final ContentValues values = new ContentValues(2);
+            final ContentValues values = new ContentValues(3);
             // Update mms table with local time instead of PDU time
             values.put(Mms.DATE, receivedTimestampInSeconds);
-            // Also update the content location field from NotificationInd so that
-            // wap push dedup would work even after the wap push is deleted
-            values.put(Mms.CONTENT_LOCATION, contentLocation);
+            // Also update the transaction id and the expiry from NotificationInd so that
+            // wap push dedup would work even after the wap push is deleted.
+            values.put(Mms.TRANSACTION_ID, transactionId);
+            values.put(Mms.EXPIRY, expiry);
             SqliteWrapper.update(context, context.getContentResolver(), uri, values, null, null);
             if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
                 LogUtil.d(TAG, "MmsUtils: Inserted MMS message into telephony, uri: " + uri);
@@ -1194,7 +1195,8 @@
 
     public static SmsMessage getSmsMessageFromDeliveryReport(final Intent intent) {
         final byte[] pdu = intent.getByteArrayExtra("pdu");
-        return SmsMessage.createFromPdu(pdu);
+        final String format = intent.getStringExtra("format");
+        return SmsMessage.createFromPdu(pdu, format);
     }
 
     /**
@@ -1842,7 +1844,7 @@
     public static StatusPlusUri downloadMmsMessage(final Context context, final Uri notificationUri,
             final int subId, final String subPhoneNumber, final String transactionId,
             final String contentLocation, final boolean autoDownload,
-            final long receivedTimestampInSeconds, Bundle extras) {
+            final long receivedTimestampInSeconds, final long expiry, Bundle extras) {
         if (TextUtils.isEmpty(contentLocation)) {
             LogUtil.e(TAG, "MmsUtils: Download from empty content location URL");
             return new StatusPlusUri(
@@ -1893,13 +1895,14 @@
                 extras.putBoolean(DownloadMmsAction.EXTRA_AUTO_DOWNLOAD, autoDownload);
                 extras.putLong(DownloadMmsAction.EXTRA_RECEIVED_TIMESTAMP,
                         receivedTimestampInSeconds);
+                extras.putLong(DownloadMmsAction.EXTRA_EXPIRY, expiry);
 
                 MmsSender.downloadMms(context, subId, contentLocation, extras);
                 return STATUS_PENDING; // Download happens asynchronously; no status to return
             }
             return insertDownloadedMessageAndSendResponse(context, notificationUri, subId,
                     subPhoneNumber, transactionId, contentLocation, autoDownload,
-                    receivedTimestampInSeconds, retrieveConf);
+                    receivedTimestampInSeconds, expiry, retrieveConf);
 
         } catch (final MmsFailureException e) {
             LogUtil.e(TAG, "MmsUtils: failed to download message " + notificationUri, e);
@@ -1914,8 +1917,8 @@
             final Uri notificationUri, final int subId, final String subPhoneNumber,
             final String transactionId, final String contentLocation,
             final boolean autoDownload, final long receivedTimestampInSeconds,
-            final RetrieveConf retrieveConf) {
-        final byte[] transactionIdBytes = stringToBytes(transactionId, "UTF-8");
+            final long expiry, final RetrieveConf retrieveConf) {
+        final byte[] notificationTransactionId = stringToBytes(transactionId, "UTF-8");
         Uri messageUri = null;
         int status = MMS_REQUEST_MANUAL_RETRY;
         int retrieveStatus = PDU_HEADER_VALUE_UNDEFINED;
@@ -1940,22 +1943,31 @@
         if (status == MMS_REQUEST_SUCCEEDED) {
             // Send response of the notification
             if (autoDownload) {
-                sendNotifyResponseForMmsDownload(context, subId, transactionIdBytes,
-                        contentLocation, PduHeaders.STATUS_RETRIEVED);
+                sendNotifyResponseForMmsDownload(
+                        context,
+                        subId,
+                        notificationTransactionId,
+                        contentLocation,
+                        PduHeaders.STATUS_RETRIEVED);
             } else {
-                sendAcknowledgeForMmsDownload(context, subId, transactionIdBytes, contentLocation);
+                sendAcknowledgeForMmsDownload(
+                        context, subId, retrieveConf.getTransactionId(), contentLocation);
             }
 
             // Insert downloaded message into telephony
             final Uri inboxUri = MmsUtils.insertReceivedMmsMessage(context, retrieveConf, subId,
-                    subPhoneNumber, receivedTimestampInSeconds, contentLocation);
+                    subPhoneNumber, receivedTimestampInSeconds, expiry, transactionId);
             messageUri = ContentUris.withAppendedId(Mms.CONTENT_URI, ContentUris.parseId(inboxUri));
         } else if (status == MMS_REQUEST_AUTO_RETRY) {
             // For a retry do nothing
         } else if (status == MMS_REQUEST_MANUAL_RETRY && autoDownload) {
             // Failure from autodownload - just treat like manual download
-            sendNotifyResponseForMmsDownload(context, subId, transactionIdBytes,
-                    contentLocation, PduHeaders.STATUS_DEFERRED);
+            sendNotifyResponseForMmsDownload(
+                    context,
+                    subId,
+                    notificationTransactionId,
+                    contentLocation,
+                    PduHeaders.STATUS_DEFERRED);
         }
         return new StatusPlusUri(status, retrieveStatus, messageUri);
     }
@@ -2161,57 +2173,28 @@
                     uri, values, null, null);
     }
 
-    // Selection for new dedup algorithm:
-    // ((m_type<>130) OR (exp>NOW)) AND (date>NOW-7d) AND (date<NOW+7d) AND (ct_l=xxxxxx)
-    // i.e. If it is NotificationInd and not expired or not NotificationInd
-    //      AND message is received with +/- 7 days from now
-    //      AND content location is the input URL
+    // Selection for dedup algorithm:
+    // ((m_type=NOTIFICATION_IND) OR (m_type=RETRIEVE_CONF)) AND (exp>NOW)) AND (t_id=xxxxxx)
+    // i.e. If it is NotificationInd or RetrieveConf and not expired
+    //      AND transaction id is the input id
     private static final String DUP_NOTIFICATION_QUERY_SELECTION =
-            "((" + Mms.MESSAGE_TYPE + "<>?) OR (" + Mms.EXPIRY + ">?)) AND ("
-                    + Mms.DATE + ">?) AND (" + Mms.DATE + "<?) AND (" + Mms.CONTENT_LOCATION +
-                    "=?)";
-    // Selection for old behavior: only checks NotificationInd and its content location
-    private static final String DUP_NOTIFICATION_QUERY_SELECTION_OLD =
-            "(" + Mms.MESSAGE_TYPE + "=?) AND (" + Mms.CONTENT_LOCATION + "=?)";
+            "((" + Mms.MESSAGE_TYPE + "=?) OR (" + Mms.MESSAGE_TYPE + "=?)) AND ("
+                    + Mms.EXPIRY + ">?) AND (" + Mms.TRANSACTION_ID + "=?)";
 
     private static final int MAX_RETURN = 32;
     private static String[] getDupNotifications(final Context context, final NotificationInd nInd) {
-        final byte[] rawLocation = nInd.getContentLocation();
-        if (rawLocation != null) {
-            final String location = new String(rawLocation);
-            // We can not be sure if the content location of an MMS is globally and historically
-            // unique. So we limit the dedup time within the last 7 days
-            // (or configured by gservices remotely). If the same content location shows up after
-            // that, we will download regardless. Duplicated message is better than no message.
-            String selection;
-            String[] selectionArgs;
-            final long timeLimit = BugleGservices.get().getLong(
-                    BugleGservicesKeys.MMS_WAP_PUSH_DEDUP_TIME_LIMIT_SECS,
-                    BugleGservicesKeys.MMS_WAP_PUSH_DEDUP_TIME_LIMIT_SECS_DEFAULT);
-            if (timeLimit > 0) {
-                // New dedup algorithm
-                selection = DUP_NOTIFICATION_QUERY_SELECTION;
-                final long nowSecs = System.currentTimeMillis() / 1000;
-                final long timeLowerBoundSecs = nowSecs - timeLimit;
-                // Need upper bound to protect against clock change so that a message has a time
-                // stamp in the future
-                final long timeUpperBoundSecs = nowSecs + timeLimit;
-                selectionArgs = new String[] {
-                        Integer.toString(PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND),
-                        Long.toString(nowSecs),
-                        Long.toString(timeLowerBoundSecs),
-                        Long.toString(timeUpperBoundSecs),
-                        location
-                };
-            } else {
-                // If time limit is 0, we revert back to old behavior in case the new
-                // dedup algorithm behaves badly
-                selection = DUP_NOTIFICATION_QUERY_SELECTION_OLD;
-                selectionArgs = new String[] {
-                        Integer.toString(PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND),
-                        location
-                };
-            }
+        final byte[] rawTransactionId = nInd.getTransactionId();
+        if (rawTransactionId != null) {
+            // dedup algorithm
+            String selection = DUP_NOTIFICATION_QUERY_SELECTION;
+            final long nowSecs = System.currentTimeMillis() / 1000;
+            String[] selectionArgs = new String[] {
+                    Integer.toString(PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND),
+                    Integer.toString(PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF),
+                    Long.toString(nowSecs),
+                    new String(rawTransactionId)
+            };
+
             Cursor cursor = null;
             try {
                 cursor = SqliteWrapper.query(
@@ -2348,7 +2331,7 @@
                 } else {
                     LogUtil.w(TAG, "Received WAP Push is a dup: " + Joiner.on(',').join(dups));
                     if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
-                        LogUtil.w(TAG, "Dup WAP Push url=" + new String(nInd.getContentLocation()));
+                        LogUtil.w(TAG, "Dup Transaction Id=" + new String(nInd.getTransactionId()));
                     }
                 }
                 break;
diff --git a/src/com/android/messaging/ui/appsettings/PerSubscriptionSettingsActivity.java b/src/com/android/messaging/ui/appsettings/PerSubscriptionSettingsActivity.java
index 623bc91..7ab5dc7 100644
--- a/src/com/android/messaging/ui/appsettings/PerSubscriptionSettingsActivity.java
+++ b/src/com/android/messaging/ui/appsettings/PerSubscriptionSettingsActivity.java
@@ -134,7 +134,7 @@
             if (!MmsConfig.get(mSubId).getSMSDeliveryReportsEnabled()) {
                 final Preference deliveryReportsPref = findPreference(
                         getString(R.string.delivery_reports_pref_key));
-                mmsCategory.removePreference(deliveryReportsPref);
+                advancedCategory.removePreference(deliveryReportsPref);
             }
             final Preference wirelessAlertPref = findPreference(getString(
                     R.string.wireless_alerts_key));
diff --git a/src/com/android/messaging/ui/debug/DebugMmsConfigFragment.java b/src/com/android/messaging/ui/debug/DebugMmsConfigFragment.java
index 7c54db5..f7da331 100644
--- a/src/com/android/messaging/ui/debug/DebugMmsConfigFragment.java
+++ b/src/com/android/messaging/ui/debug/DebugMmsConfigFragment.java
@@ -39,6 +39,7 @@
 
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.Iterator;
 import java.util.List;
 
 /**
@@ -103,6 +104,13 @@
             mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
             mMmsConfig = MmsConfig.get(subId);
             mKeys = new ArrayList<>(mMmsConfig.keySet());
+            Iterator<String> it = mKeys.iterator();
+            while (it.hasNext()) {
+                // Remove a config if the MmsConfig.sKeyTypeMap doesn't have it.
+                if (MmsConfig.getKeyType(it.next()) == null) {
+                    it.remove();
+                }
+            }
             Collections.sort(mKeys);
         }
 
@@ -125,7 +133,7 @@
 
         @Override
         public void onValueChanged(String key, String keyType, String value) {
-            mMmsConfig.update(key, value, keyType);
+            mMmsConfig.update(keyType, key, value);
             notifyDataSetChanged();
         }
 
diff --git a/src/com/android/messaging/util/DebugUtils.java b/src/com/android/messaging/util/DebugUtils.java
index 1362f83..0d689fe 100644
--- a/src/com/android/messaging/util/DebugUtils.java
+++ b/src/com/android/messaging/util/DebugUtils.java
@@ -291,9 +291,10 @@
                 dis = new DataInputStream(fis);
 
                 // SMS dump
+                String format = null;
                 final int chars = dis.readInt();
                 if (chars > 0) {
-                    final String format = dis.readUTF();
+                    format = dis.readUTF();
                 }
                 final int count = dis.readInt();
                 final SmsMessage[] messagesTemp = new SmsMessage[count];
@@ -301,7 +302,11 @@
                     final int length = dis.readInt();
                     final byte[] pdu = new byte[length];
                     dis.read(pdu, 0, length);
-                    messagesTemp[i] = SmsMessage.createFromPdu(pdu);
+                    if (format == null) {
+                        messagesTemp[i] = SmsMessage.createFromPdu(pdu);
+                    } else {
+                        messagesTemp[i] = SmsMessage.createFromPdu(pdu, format);
+                    }
                 }
                 messages = messagesTemp;
             } catch (final FileNotFoundException e) {