diff --git a/Android.mk b/Android.mk
index 7b63072..c824fff 100644
--- a/Android.mk
+++ b/Android.mk
@@ -5,7 +5,7 @@
 
 LOCAL_PRIVILEGED_MODULE := true
 
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
+LOCAL_SRC_FILES := $(call all-java-files-under,src)
 
 LOCAL_PACKAGE_NAME := TelephonyProvider
 LOCAL_CERTIFICATE := platform
@@ -14,3 +14,5 @@
 LOCAL_STATIC_JAVA_LIBRARIES += android-common
 
 include $(BUILD_PACKAGE)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 49c71eb..256c347 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -29,7 +29,9 @@
 
     <application android:process="com.android.phone"
                  android:allowClearUserData="false"
-                 android:allowBackup="false"
+                 android:fullBackupOnly="true"
+                 android:backupAgent="TelephonyBackupAgent"
+                 android:restoreAnyVersion="true"
                  android:label="@string/app_label"
                  android:icon="@mipmap/ic_launcher_phone"
                  android:usesCleartextTraffic="true"
diff --git a/src/com/android/providers/telephony/TelephonyBackupAgent.java b/src/com/android/providers/telephony/TelephonyBackupAgent.java
new file mode 100644
index 0000000..50a7c8e
--- /dev/null
+++ b/src/com/android/providers/telephony/TelephonyBackupAgent.java
@@ -0,0 +1,922 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.providers.telephony;
+
+import com.google.android.mms.ContentType;
+import com.google.android.mms.pdu.CharacterSets;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import android.annotation.TargetApi;
+import android.app.backup.BackupAgent;
+import android.app.backup.BackupDataInput;
+import android.app.backup.BackupDataOutput;
+import android.app.backup.FullBackupDataOutput;
+import android.content.ContentProvider;
+import android.content.ContentUris;
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.database.DatabaseUtils;
+import android.net.Uri;
+import android.os.Build;
+import android.os.ParcelFileDescriptor;
+import android.provider.BaseColumns;
+import android.provider.Telephony;
+import android.telephony.PhoneNumberUtils;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+import android.util.ArrayMap;
+import android.util.ArraySet;
+import android.util.JsonReader;
+import android.util.JsonWriter;
+import android.util.Log;
+import android.util.SparseArray;
+
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+import java.util.zip.DeflaterOutputStream;
+import java.util.zip.InflaterInputStream;
+
+/***
+ * Backup agent for backup and restore SMS's and text MMS's.
+ *
+ * This backup agent stores SMS's into "sms_backup" file as a JSON array. Example below.
+ *  [{"self_phone":"+1234567891011","address":"+1234567891012","body":"Example sms",
+ *  "date":"1450893518140","date_sent":"1450893514000","status":"-1","type":"1"},
+ *  {"self_phone":"+1234567891011","address":"12345","body":"Example 2","date":"1451328022316",
+ *  "date_sent":"1451328018000","status":"-1","type":"1"}]
+ *
+ * Text MMS's are stored into "mms_backup" file as a JSON array. Example below.
+ *  [{"self_phone":"+1234567891011","date":"1451322716","date_sent":"0","m_type":"128","v":"18",
+ *  "msg_box":"2","mms_addresses":[{"type":137,"address":"+1234567891011","charset":106},
+ *  {"type":151,"address":"example@example.com","charset":106}],"mms_body":"Mms to email",
+ *  "mms_charset":106},
+ *  {"self_phone":"+1234567891011","sub":"MMS subject","date":"1451322955","date_sent":"0",
+ *  "m_type":"132","v":"17","msg_box":"1","ct_l":"http://promms/servlets/NOK5BBqgUHAqugrQNM",
+ *  "mms_addresses":[{"type":151,"address":"+1234567891011","charset":106}],
+ *  "mms_body":"Mms\nBody\r\n",
+ *  "mms_charset":106,"sub_cs":"106"}]
+ *
+ *   It deflates the files on the flight.
+ *   Every 1000 messages it backs up file, deletes it and creates a new one with the same name.
+ */
+
+@TargetApi(Build.VERSION_CODES.M)
+public class TelephonyBackupAgent extends BackupAgent {
+    private static final String TAG = "TelephonyBackupAgent";
+    private static final boolean DEBUG = false;
+
+
+    // Copied from packages/apps/Messaging/src/com/android/messaging/sms/MmsUtils.java.
+    private static final int DEFAULT_DURATION = 5000; //ms
+
+    // Copied from packages/apps/Messaging/src/com/android/messaging/sms/MmsUtils.java.
+    @VisibleForTesting
+    static final String sSmilTextOnly =
+            "<smil>" +
+                "<head>" +
+                    "<layout>" +
+                        "<root-layout/>" +
+                        "<region id=\"Text\" top=\"0\" left=\"0\" "
+                        + "height=\"100%%\" width=\"100%%\"/>" +
+                    "</layout>" +
+                "</head>" +
+                "<body>" +
+                       "%s" +  // constructed body goes here
+                "</body>" +
+            "</smil>";
+
+    // Copied from packages/apps/Messaging/src/com/android/messaging/sms/MmsUtils.java.
+    @VisibleForTesting
+    static final String sSmilTextPart =
+            "<par dur=\"" + DEFAULT_DURATION + "ms\">" +
+                "<text src=\"%s\" region=\"Text\" />" +
+            "</par>";
+
+
+    // JSON key for phone number a message was sent from or received to.
+    private static final String SELF_PHONE_KEY = "self_phone";
+    // JSON key for list of addresses of MMS message.
+    private static final String MMS_ADDRESSES_KEY = "mms_addresses";
+    // JSON key for MMS body.
+    private static final String MMS_BODY_KEY = "mms_body";
+    // JSON key for MMS charset.
+    private static final String MMS_BODY_CHARSET_KEY = "mms_charset";
+
+    // File names for backup/restore.
+    private static final String SMS_BACKUP_FILE = "sms_backup";
+    private static final String MMS_BACKUP_FILE = "mms_backup";
+
+    // Charset being used for reading/writing backup files.
+    private static final String CHARSET_UTF8 = "UTF-8";
+
+    // Order by ID entries from database.
+    private static final String ORDER_BY_ID = BaseColumns._ID + " ASC";
+
+    // Columns from SMS database for backup/restore.
+    @VisibleForTesting
+    static final String[] SMS_PROJECTION = new String[] {
+            Telephony.Sms._ID,
+            Telephony.Sms.SUBSCRIPTION_ID,
+            Telephony.Sms.ADDRESS,
+            Telephony.Sms.BODY,
+            Telephony.Sms.SUBJECT,
+            Telephony.Sms.DATE,
+            Telephony.Sms.DATE_SENT,
+            Telephony.Sms.STATUS,
+            Telephony.Sms.TYPE
+    };
+
+    // Columns from MMS database for backup/restore.
+    @VisibleForTesting
+    static final String[] MMS_PROJECTION = new String[] {
+            Telephony.Mms._ID,
+            Telephony.Mms.SUBSCRIPTION_ID,
+            Telephony.Mms.SUBJECT,
+            Telephony.Mms.SUBJECT_CHARSET,
+            Telephony.Mms.DATE,
+            Telephony.Mms.DATE_SENT,
+            Telephony.Mms.MESSAGE_TYPE,
+            Telephony.Mms.MMS_VERSION,
+            Telephony.Mms.TEXT_ONLY,
+            Telephony.Mms.MESSAGE_BOX,
+            Telephony.Mms.CONTENT_LOCATION
+    };
+
+    // Columns from addr database for backup/restore. This database is used for fetching addresses
+    // for MMS message.
+    @VisibleForTesting
+    static final String[] MMS_ADDR_PROJECTION = new String[] {
+            Telephony.Mms.Addr.TYPE,
+            Telephony.Mms.Addr.ADDRESS,
+            Telephony.Mms.Addr.CHARSET
+    };
+
+    // Columns from part database for backup/restore. This database is used for fetching body text
+    // and charset for MMS message.
+    @VisibleForTesting
+    static final String[] MMS_TEXT_PROJECTION = new String[] {
+            Telephony.Mms.Part.CONTENT_TYPE,
+            Telephony.Mms.Part.TEXT,
+            Telephony.Mms.Part.CHARSET
+    };
+
+    // Maximum messages for one backup file. After reaching the limit the agent backs up the file,
+    // deletes it and creates a new one with the same name.
+    private static final int MAX_MSG_PER_FILE = 1000;
+
+
+    // Default values for SMS, MMS, Addresses restore.
+    private static final ContentValues defaultValuesSms = new ContentValues(3);
+    private static final ContentValues defaultValuesMms = new ContentValues(5);
+    private static final ContentValues defaultValuesAddr = new ContentValues(2);
+
+    static {
+        // Consider restored messages read and seen.
+        defaultValuesSms.put(Telephony.Sms.READ, 1);
+        defaultValuesSms.put(Telephony.Sms.SEEN, 1);
+        // If there is no sub_id with self phone number on restore set it to -1.
+        defaultValuesSms.put(Telephony.Sms.SUBSCRIPTION_ID, -1);
+
+        defaultValuesMms.put(Telephony.Mms.READ, 1);
+        defaultValuesMms.put(Telephony.Mms.SEEN, 1);
+        defaultValuesMms.put(Telephony.Mms.SUBSCRIPTION_ID, -1);
+        defaultValuesMms.put(Telephony.Mms.MESSAGE_BOX, Telephony.Mms.MESSAGE_BOX_ALL);
+        defaultValuesMms.put(Telephony.Mms.TEXT_ONLY, 1);
+
+        defaultValuesAddr.put(Telephony.Mms.Addr.TYPE, 0);
+        defaultValuesAddr.put(Telephony.Mms.Addr.CHARSET, CharacterSets.DEFAULT_CHARSET);
+    }
+
+
+    private SparseArray<String> subId2phone;
+    private Map<String, Integer> phone2subId;
+    private SmsProvider mSmsProvider;
+    private MmsProvider mMmsProvider;
+    private MmsSmsProvider mMmsSmsProvider;
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+
+        subId2phone = new SparseArray<String>();
+        phone2subId = new ArrayMap<String, Integer>();
+        final SubscriptionManager subscriptionManager = SubscriptionManager.from(this);
+        if (subscriptionManager != null) {
+            final List<SubscriptionInfo> subInfo =
+                    subscriptionManager.getActiveSubscriptionInfoList();
+            if (subInfo != null) {
+                for (SubscriptionInfo sub : subInfo) {
+                    final String phoneNumber = getNormalizedNumber(sub);
+                    subId2phone.append(sub.getSubscriptionId(), phoneNumber);
+                    phone2subId.put(phoneNumber, sub.getSubscriptionId());
+                }
+            }
+        }
+
+        mSmsProvider = new SmsProvider();
+        mSmsProvider.attachInfo(this, null);
+        mSmsProvider.onCreate();
+
+        mMmsProvider = new MmsProvider();
+        mMmsProvider.attachInfo(this, null);
+        mMmsProvider.onCreate();
+
+        mMmsSmsProvider = new MmsSmsProvider();
+        mMmsSmsProvider.attachInfo(this, null);
+        mMmsSmsProvider.onCreate();
+    }
+
+
+    @Override
+    public void onFullBackup(FullBackupDataOutput data) throws IOException {
+        try (Cursor cursor = mSmsProvider.query(Telephony.Sms.CONTENT_URI, SMS_PROJECTION, null,
+                null, ORDER_BY_ID)) {
+            if (DEBUG) {
+                Log.i(TAG, "Backing up SMS");
+            }
+            if (cursor != null) {
+                while (!cursor.isLast() && !cursor.isAfterLast()) {
+                    try (JsonWriter jsonWriter = getJsonWriter(SMS_BACKUP_FILE)) {
+                        putSmsMessagesToJson(cursor, subId2phone, jsonWriter, MAX_MSG_PER_FILE);
+                    }
+                    backupFile(SMS_BACKUP_FILE, data);
+                }
+            }
+        }
+
+        try (Cursor cursor = mMmsProvider.query(Telephony.Mms.CONTENT_URI, MMS_PROJECTION, null,
+                null, ORDER_BY_ID)) {
+            if (DEBUG) {
+                Log.i(TAG, "Backing up text MMS");
+            }
+            if (cursor != null) {
+                while (!cursor.isLast() && !cursor.isAfterLast()) {
+                    try (JsonWriter jsonWriter = getJsonWriter(MMS_BACKUP_FILE)) {
+                        putMmsMessagesToJson(cursor, mMmsProvider, subId2phone, jsonWriter,
+                                MAX_MSG_PER_FILE);
+                    }
+                    backupFile(MMS_BACKUP_FILE, data);
+                }
+            }
+        }
+    }
+
+    @VisibleForTesting
+    static void putMmsMessagesToJson(Cursor cursor, ContentProvider mmsProvider,
+                                     SparseArray<String> subId2phone, JsonWriter jsonWriter,
+                                     int maxMsgPerFile) throws IOException {
+        jsonWriter.beginArray();
+        for (int msgCount=0; msgCount<maxMsgPerFile && cursor.moveToNext();) {
+            msgCount += writeMmsToWriter(jsonWriter, cursor, subId2phone, mmsProvider);
+        }
+        jsonWriter.endArray();
+    }
+
+    @VisibleForTesting
+    static void putSmsMessagesToJson(Cursor cursor, SparseArray<String> subId2phone,
+                             JsonWriter jsonWriter, int maxMsgPerFile) throws IOException {
+
+        jsonWriter.beginArray();
+        for (int msgCount=0; msgCount<maxMsgPerFile && cursor.moveToNext(); ++msgCount) {
+            writeSmsToWriter(jsonWriter, cursor, subId2phone);
+        }
+        jsonWriter.endArray();
+    }
+
+    private void backupFile(String fileName, FullBackupDataOutput data) {
+        final File file = new File(getFilesDir().getPath() + "/" + fileName);
+        super.fullBackupFile(file, data);
+        file.delete();
+    }
+
+    @Override
+    public void onRestoreFile(ParcelFileDescriptor data, long size, File destination, int type,
+                              long mode, long mtime) throws IOException {
+        if (DEBUG) {
+            Log.i(TAG, "Restoring file " + destination.getName());
+        }
+
+        if (destination.getName().equals(SMS_BACKUP_FILE)) {
+            if (DEBUG) {
+                Log.i(TAG, "Restoring SMS");
+            }
+            try (JsonReader jsonReader = getJsonReader(data.getFileDescriptor())) {
+                putSmsMessagesToProvider(jsonReader, mSmsProvider, mMmsSmsProvider, phone2subId);
+            }
+        } else if (destination.getName().equals(MMS_BACKUP_FILE)) {
+            if (DEBUG) {
+                Log.i(TAG, "Restoring text MMS");
+            }
+            try (JsonReader jsonReader = getJsonReader(data.getFileDescriptor())) {
+                putMmsMessagesToProvider(jsonReader, mMmsProvider, mMmsSmsProvider, phone2subId);
+            }
+        } else {
+            super.onRestoreFile(data, size, destination, type, mode, mtime);
+        }
+        if (DEBUG) {
+            Log.i(TAG, "Finished restore");
+        }
+    }
+
+    @VisibleForTesting
+    static void putSmsMessagesToProvider(JsonReader jsonReader, ContentProvider smsProvider,
+                                         ContentProvider threadProvider,
+                                         Map<String, Integer> phone2subId) throws IOException {
+        jsonReader.beginArray();
+        while (jsonReader.hasNext()) {
+            ContentValues smsValues =
+                    readSmsValuesFromReader(jsonReader, threadProvider, phone2subId);
+            if (doesSmsExist(smsProvider, smsValues)) {
+                if (DEBUG) {
+                    Log.e(TAG, String.format("Sms: %s already exists", smsValues.toString()));
+                }
+                continue;
+            }
+            smsProvider.insert(Telephony.Sms.CONTENT_URI, smsValues);
+        }
+        jsonReader.endArray();
+    }
+
+    @VisibleForTesting
+    static void putMmsMessagesToProvider(JsonReader jsonReader, ContentProvider mmsProvider,
+                                         ContentProvider threadProvider,
+                                         Map<String, Integer> phone2subId) throws IOException {
+        jsonReader.beginArray();
+        while (jsonReader.hasNext()) {
+            final Mms mms = readMmsFromReader(jsonReader, threadProvider, phone2subId);
+            if (doesMmsExist(mmsProvider, mms)) {
+                if (DEBUG) {
+                    Log.e(TAG, String.format("Mms: %s already exists", mms.toString()));
+                }
+                continue;
+            }
+            addMmsMessage(mmsProvider, mms);
+        }
+    }
+
+    @VisibleForTesting
+    static final String[] PROJECTION_ID = {BaseColumns._ID};
+
+    private static boolean doesSmsExist(ContentProvider smsProvider, ContentValues smsValues) {
+        final String where = String.format("%s = %d and %s = %s",
+                Telephony.Sms.DATE, smsValues.getAsLong(Telephony.Sms.DATE),
+                Telephony.Sms.BODY,
+                DatabaseUtils.sqlEscapeString(smsValues.getAsString(Telephony.Sms.BODY)));
+        try (Cursor cursor = smsProvider.query(Telephony.Sms.CONTENT_URI, PROJECTION_ID, where,
+                null, null)) {
+            return cursor != null && cursor.getCount() > 0;
+        }
+    }
+
+    private static boolean doesMmsExist(ContentProvider mmsProvider, Mms mms) {
+        final String where = String.format("%s = %d",
+                Telephony.Sms.DATE, mms.values.getAsLong(Telephony.Mms.DATE));
+        try (Cursor cursor = mmsProvider.query(Telephony.Mms.CONTENT_URI, PROJECTION_ID, where,
+                null, null)) {
+            if (cursor != null && cursor.moveToFirst()) {
+                do {
+                    final int mmsId = cursor.getInt(0);
+                    final MmsBody body = getMmsBody(mmsProvider, mmsId);
+                    if (body != null && body.equals(mms.body)) {
+                        return true;
+                    }
+                } while (cursor.moveToNext());
+            }
+        }
+        return false;
+    }
+
+    private static String getNormalizedNumber(SubscriptionInfo subscriptionInfo) {
+        if (subscriptionInfo == null) {
+            return null;
+        }
+        return PhoneNumberUtils.formatNumberToE164(subscriptionInfo.getNumber(),
+                subscriptionInfo.getCountryIso().toUpperCase(Locale.US));
+    }
+
+    private static void writeSmsToWriter(JsonWriter jsonWriter, Cursor cursor,
+                                         SparseArray<String> subId2phone) throws IOException {
+        jsonWriter.beginObject();
+
+        for (int i=0; i<cursor.getColumnCount(); ++i) {
+            final String name = cursor.getColumnName(i);
+            final String value = cursor.getString(i);
+            if (value == null) {
+                continue;
+            }
+            switch (name) {
+                case Telephony.Sms.SUBSCRIPTION_ID:
+                    final int subId = cursor.getInt(i);
+                    final String selfNumber = subId2phone.get(subId);
+                    if (selfNumber != null) {
+                        jsonWriter.name(SELF_PHONE_KEY).value(selfNumber);
+                    }
+                    break;
+                case Telephony.Sms._ID:
+                    break;
+                default:
+                    jsonWriter.name(name).value(value);
+                    break;
+            }
+        }
+        jsonWriter.endObject();
+    }
+
+    @VisibleForTesting
+    static ContentValues readSmsValuesFromReader(JsonReader jsonReader,
+                                                 ContentProvider threadProvider,
+                                                 Map<String, Integer> phone2id)
+            throws IOException {
+        ContentValues values = new ContentValues(8+defaultValuesSms.size());
+        values.putAll(defaultValuesSms);
+        jsonReader.beginObject();
+        while (jsonReader.hasNext()) {
+            String name = jsonReader.nextName();
+            switch (name) {
+                case Telephony.Sms.BODY:
+                case Telephony.Sms.DATE:
+                case Telephony.Sms.DATE_SENT:
+                case Telephony.Sms.STATUS:
+                case Telephony.Sms.TYPE:
+                case Telephony.Sms.SUBJECT:
+                    values.put(name, jsonReader.nextString());
+                    break;
+                case Telephony.Sms.ADDRESS:
+                    final String address = jsonReader.nextString();
+                    values.put(name, address);
+                    values.put(Telephony.Sms.THREAD_ID,
+                            getOrCreateThreadId(threadProvider, getSmsRecipients(address)));
+                    break;
+                case SELF_PHONE_KEY:
+                    final String selfPhone = jsonReader.nextString();
+                    if (phone2id.containsKey(selfPhone)) {
+                        values.put(Telephony.Sms.SUBSCRIPTION_ID, phone2id.get(selfPhone));
+                    }
+                    break;
+                default:
+                    if (DEBUG) {
+                        Log.w(TAG, "Unknown name:" + name);
+                    }
+                    jsonReader.skipValue();
+                    break;
+            }
+        }
+        jsonReader.endObject();
+        return values;
+    }
+
+    private static Set<String> getSmsRecipients(String address) {
+        Set<String> recipients = new ArraySet<String>();
+        recipients.addAll(Arrays.asList(address.split("[\\s,;]+")));
+        return recipients;
+    }
+
+    private static int writeMmsToWriter(JsonWriter jsonWriter, Cursor cursor,
+                                        SparseArray<String> subId2phone,
+                                        ContentProvider mmsProvider) throws IOException {
+        // Do not backup non text-only MMS's.
+        if (cursor.getInt(cursor.getColumnIndex(Telephony.Mms.TEXT_ONLY)) != 1) {
+            return 0;
+        }
+        final int mmsId = cursor.getInt(0);
+        final MmsBody body = getMmsBody(mmsProvider, mmsId);
+        if (body == null || body.text == null) {
+            return 0;
+        }
+
+        boolean subjectNull = true;
+        jsonWriter.beginObject();
+        for (int i=0; i<cursor.getColumnCount(); ++i) {
+            final String name = cursor.getColumnName(i);
+            final String value = cursor.getString(i);
+            if (value == null) {
+                continue;
+            }
+            switch (name) {
+                case Telephony.Sms.SUBSCRIPTION_ID:
+                    final int subId = cursor.getInt(i);
+                    final String selfNumber = subId2phone.get(subId);
+                    if (selfNumber != null) {
+                        jsonWriter.name(SELF_PHONE_KEY).value(selfNumber);
+                    }
+                    break;
+                case Telephony.Mms._ID:
+                case Telephony.Mms.TEXT_ONLY:
+                case Telephony.Mms.SUBJECT_CHARSET:
+                    break;
+                case Telephony.Mms.SUBJECT:
+                    subjectNull = false;
+                default:
+                    jsonWriter.name(name).value(value);
+                    break;
+            }
+        }
+        // Addresses.
+        writeMmsAddresses(jsonWriter.name(MMS_ADDRESSES_KEY), mmsProvider, mmsId);
+        // Body (text of the message).
+        jsonWriter.name(MMS_BODY_KEY).value(body.text);
+        // Charset of the body text.
+        jsonWriter.name(MMS_BODY_CHARSET_KEY).value(body.charSet);
+
+        if (!subjectNull) {
+            // Subject charset.
+            writeStringToWriter(jsonWriter, cursor, Telephony.Mms.SUBJECT_CHARSET);
+        }
+        jsonWriter.endObject();
+        return 1;
+    }
+
+    private static Mms readMmsFromReader(JsonReader jsonReader, ContentProvider threadProvider,
+                                         Map<String, Integer> phone2id) throws IOException {
+        Mms mms = new Mms();
+        mms.values = new ContentValues(6+defaultValuesMms.size());
+        mms.values.putAll(defaultValuesMms);
+        jsonReader.beginObject();
+        String selfPhone = null;
+        String bodyText = null;
+        int bodyCharset = CharacterSets.DEFAULT_CHARSET;
+        while (jsonReader.hasNext()) {
+            String name = jsonReader.nextName();
+            switch (name) {
+                case SELF_PHONE_KEY:
+                    selfPhone = jsonReader.nextString();
+                    if (phone2id.containsKey(selfPhone)) {
+                        mms.values.put(Telephony.Mms.SUBSCRIPTION_ID, phone2id.get(selfPhone));
+                    }
+                    break;
+                case MMS_ADDRESSES_KEY:
+                    getMmsAddressesFromReader(jsonReader, mms);
+                    break;
+                case MMS_BODY_KEY:
+                    bodyText = jsonReader.nextString();
+                    break;
+                case MMS_BODY_CHARSET_KEY:
+                    bodyCharset = jsonReader.nextInt();
+                    break;
+                case Telephony.Mms.SUBJECT:
+                case Telephony.Mms.SUBJECT_CHARSET:
+                case Telephony.Mms.DATE:
+                case Telephony.Mms.DATE_SENT:
+                case Telephony.Mms.MESSAGE_TYPE:
+                case Telephony.Mms.MMS_VERSION:
+                case Telephony.Mms.MESSAGE_BOX:
+                case Telephony.Mms.CONTENT_LOCATION:
+                    mms.values.put(name, jsonReader.nextString());
+                    break;
+                default:
+                    if (DEBUG) {
+                        Log.w(TAG, "Unknown name:" + name);
+                    }
+                    jsonReader.skipValue();
+                    break;
+            }
+        }
+        jsonReader.endObject();
+
+        if (bodyText != null) {
+            mms.body = new MmsBody(bodyText, bodyCharset);
+        }
+
+        { // Get ThreadId.
+            Set<String> recipients = new ArraySet<String>();
+            for (ContentValues mmsAddress : mms.addresses) {
+                String address = getDecodedString(
+                        getStringBytes(mmsAddress.getAsString(Telephony.Mms.Addr.ADDRESS),
+                                CharacterSets.ISO_8859_1),
+                        mmsAddress.getAsInteger(Telephony.Mms.Addr.CHARSET));
+                if (selfPhone != null && selfPhone.equals(address))
+                    continue;
+                recipients.add(address);
+            }
+            mms.values.put(Telephony.Mms.THREAD_ID,
+                    getOrCreateThreadId(threadProvider, recipients));
+        }
+
+        // Set default charset for subject.
+        if (mms.values.get(Telephony.Mms.SUBJECT) != null &&
+                mms.values.get(Telephony.Mms.SUBJECT_CHARSET) == null) {
+            mms.values.put(Telephony.Mms.SUBJECT_CHARSET, CharacterSets.DEFAULT_CHARSET);
+        }
+
+        return mms;
+    }
+
+    private static MmsBody getMmsBody(ContentProvider mmsProvider, int mmsId) {
+        Uri MMS_PART_CONTENT_URI = Telephony.Mms.CONTENT_URI.buildUpon()
+                .appendPath(String.valueOf(mmsId)).appendPath("part").build();
+
+        String body = null;
+        int charSet = 0;
+
+        try (Cursor cursor = mmsProvider.query(MMS_PART_CONTENT_URI, MMS_TEXT_PROJECTION,
+                null, null/*selectionArgs*/, ORDER_BY_ID)) {
+            if (cursor != null && cursor.moveToFirst()) {
+                do {
+                    if (ContentType.TEXT_PLAIN.equals(cursor.getString(0))) {
+                        body = (body == null ? cursor.getString(1)
+                                             : body.concat(cursor.getString(1)));
+                        charSet = cursor.getInt(2);
+                    }
+                } while (cursor.moveToNext());
+            }
+        }
+        return (body == null ? null : new MmsBody(body, charSet));
+    }
+
+    private static void writeMmsAddresses(JsonWriter jsonWriter, ContentProvider mmsProvider,
+                                          int mmsId) throws IOException {
+        Uri.Builder builder = Telephony.Mms.CONTENT_URI.buildUpon();
+        builder.appendPath(String.valueOf(mmsId)).appendPath("addr");
+        Uri uriAddrPart = builder.build();
+
+        jsonWriter.beginArray();
+        try (Cursor cursor = mmsProvider.query(uriAddrPart, MMS_ADDR_PROJECTION,
+                null/*selection*/, null/*selectionArgs*/, ORDER_BY_ID)) {
+            if (cursor != null && cursor.moveToFirst()) {
+                do {
+                    if (cursor.getString(cursor.getColumnIndex(Telephony.Mms.Addr.ADDRESS))
+                            != null) {
+                        jsonWriter.beginObject();
+                        writeIntToWriter(jsonWriter, cursor, Telephony.Mms.Addr.TYPE);
+                        writeStringToWriter(jsonWriter, cursor, Telephony.Mms.Addr.ADDRESS);
+                        writeIntToWriter(jsonWriter, cursor, Telephony.Mms.Addr.CHARSET);
+                        jsonWriter.endObject();
+                    }
+                } while (cursor.moveToNext());
+            }
+        }
+        jsonWriter.endArray();
+    }
+
+    private static void getMmsAddressesFromReader(JsonReader jsonReader, Mms mms)
+            throws IOException {
+        mms.addresses = new ArrayList<ContentValues>();
+        jsonReader.beginArray();
+        while (jsonReader.hasNext()) {
+            jsonReader.beginObject();
+            ContentValues addrValues = new ContentValues(defaultValuesAddr);
+            while (jsonReader.hasNext()) {
+                final String name = jsonReader.nextName();
+                switch (name) {
+                    case Telephony.Mms.Addr.TYPE:
+                    case Telephony.Mms.Addr.CHARSET:
+                        addrValues.put(name, jsonReader.nextInt());
+                        break;
+                    case Telephony.Mms.Addr.ADDRESS:
+                        addrValues.put(name, jsonReader.nextString());
+                        break;
+                    default:
+                        if (DEBUG) {
+                            Log.w(TAG, "Unknown name:" + name);
+                        }
+                        jsonReader.skipValue();
+                        break;
+                }
+            }
+            jsonReader.endObject();
+            if (addrValues.containsKey(Telephony.Mms.Addr.ADDRESS)) {
+                mms.addresses.add(addrValues);
+            }
+        }
+        jsonReader.endArray();
+    }
+
+    private static void addMmsMessage(ContentProvider mmsProvider, Mms mms) {
+        if (DEBUG) {
+            Log.e(TAG, "Add mms:\n" + mms.toString());
+        }
+        final long dummyId = System.currentTimeMillis(); // Dummy ID of the msg.
+        final Uri partUri = Telephony.Mms.CONTENT_URI.buildUpon()
+                .appendPath(String.valueOf(dummyId)).appendPath("part").build();
+
+        final String srcName = String.format("text.%06d.txt", 0);
+        { // Insert SMIL part.
+            final String smilBody = String.format(sSmilTextPart, srcName);
+            final String smil = String.format(sSmilTextOnly, smilBody);
+            final ContentValues values = new ContentValues(7);
+            values.put(Telephony.Mms.Part.MSG_ID, dummyId);
+            values.put(Telephony.Mms.Part.SEQ, -1);
+            values.put(Telephony.Mms.Part.CONTENT_TYPE, ContentType.APP_SMIL);
+            values.put(Telephony.Mms.Part.NAME, "smil.xml");
+            values.put(Telephony.Mms.Part.CONTENT_ID, "<smil>");
+            values.put(Telephony.Mms.Part.CONTENT_LOCATION, "smil.xml");
+            values.put(Telephony.Mms.Part.TEXT, smil);
+            if (mmsProvider.insert(partUri, values) == null) {
+                if (DEBUG) {
+                    Log.e(TAG, "Could not insert SMIL part");
+                }
+                return;
+            }
+        }
+
+        { // Insert body part.
+            final ContentValues values = new ContentValues(8);
+            values.put(Telephony.Mms.Part.MSG_ID, dummyId);
+            values.put(Telephony.Mms.Part.SEQ, 0);
+            values.put(Telephony.Mms.Part.CONTENT_TYPE, ContentType.TEXT_PLAIN);
+            values.put(Telephony.Mms.Part.NAME, srcName);
+            values.put(Telephony.Mms.Part.CONTENT_ID, "<"+srcName+">");
+            values.put(Telephony.Mms.Part.CONTENT_LOCATION, srcName);
+            values.put(Telephony.Mms.Part.CHARSET, mms.body.charSet);
+            values.put(Telephony.Mms.Part.TEXT, mms.body.text);
+            if (mmsProvider.insert(partUri, values) == null) {
+                if (DEBUG) {
+                    Log.e(TAG, "Could not insert body part");
+                }
+                return;
+            }
+        }
+
+        // Insert mms.
+        final Uri mmsUri = mmsProvider.insert(Telephony.Mms.CONTENT_URI, mms.values);
+        if (mmsUri == null) {
+            if (DEBUG) {
+                Log.e(TAG, "Could not insert mms");
+            }
+            return;
+        }
+
+        final long mmsId = ContentUris.parseId(mmsUri);
+        { // Update parts with the right mms id.
+            ContentValues values = new ContentValues(1);
+            values.put(Telephony.Mms.Part.MSG_ID, mmsId);
+            mmsProvider.update(partUri, values, null, null);
+        }
+
+        { // Insert adderesses into "addr".
+            final Uri addrUri = Uri.withAppendedPath(mmsUri, "addr");
+            for (ContentValues mmsAddress : mms.addresses) {
+                ContentValues values = new ContentValues(mmsAddress);
+                values.put(Telephony.Mms.Addr.MSG_ID, mmsId);
+                mmsProvider.insert(addrUri, values);
+            }
+        }
+    }
+
+    private static final class MmsBody {
+        public String text;
+        public int charSet;
+
+        public MmsBody(String text, int charSet) {
+            this.text = text;
+            this.charSet = charSet;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj == null || !(obj instanceof MmsBody)) {
+                return false;
+            }
+            MmsBody typedObj = (MmsBody) obj;
+            return this.text.equals(typedObj.text) && this.charSet == typedObj.charSet;
+        }
+
+        @Override
+        public String toString() {
+            return "Text:" + text + " charSet:" + charSet;
+        }
+    }
+
+    private static final class Mms {
+        public ContentValues values;
+        public List<ContentValues> addresses;
+        public MmsBody body;
+        @Override
+        public String toString() {
+            return "Values:" + values.toString() + "\nRecipients:"+addresses.toString()
+                    + "\nBody:" + body;
+        }
+    }
+
+    private JsonWriter getJsonWriter(final String fileName) throws IOException {
+        return new JsonWriter(new OutputStreamWriter(new DeflaterOutputStream(
+                openFileOutput(fileName, MODE_PRIVATE)), CHARSET_UTF8));
+    }
+
+    private JsonReader getJsonReader(final FileDescriptor fileDescriptor) throws IOException {
+        return new JsonReader(new InputStreamReader(new InflaterInputStream(
+                new FileInputStream(fileDescriptor)), CHARSET_UTF8));
+    }
+
+    private static void writeStringToWriter(JsonWriter jsonWriter, Cursor cursor, String name)
+            throws IOException {
+        final String value = cursor.getString(cursor.getColumnIndex(name));
+        if (value != null) {
+            jsonWriter.name(name).value(value);
+        }
+    }
+
+    private static void writeIntToWriter(JsonWriter jsonWriter, Cursor cursor, String name)
+            throws IOException {
+        final int value = cursor.getInt(cursor.getColumnIndex(name));
+        if (value != 0) {
+            jsonWriter.name(name).value(value);
+        }
+    }
+
+    // Copied from packages/apps/Messaging/src/com/android/messaging/sms/DatabaseMessages.java.
+    /**
+     * Decoded string by character set
+     */
+    private static String getDecodedString(final byte[] data, final int charset)  {
+        if (CharacterSets.ANY_CHARSET == charset) {
+            return new String(data); // system default encoding.
+        } else {
+            try {
+                final String name = CharacterSets.getMimeName(charset);
+                return new String(data, name);
+            } catch (final UnsupportedEncodingException e) {
+                try {
+                    return new String(data, CharacterSets.MIMENAME_ISO_8859_1);
+                } catch (final UnsupportedEncodingException exception) {
+                    return new String(data); // system default encoding.
+                }
+            }
+        }
+    }
+
+    // Copied from packages/apps/Messaging/src/com/android/messaging/sms/DatabaseMessages.java.
+    /**
+     * Unpack a given String into a byte[].
+     */
+    private static byte[] getStringBytes(final String data, final int charset) {
+        if (CharacterSets.ANY_CHARSET == charset) {
+            return data.getBytes();
+        } else {
+            try {
+                final String name = CharacterSets.getMimeName(charset);
+                return data.getBytes(name);
+            } catch (final UnsupportedEncodingException e) {
+                return data.getBytes();
+            }
+        }
+    }
+
+    private static final Uri THREAD_ID_CONTENT_URI = Uri.parse("content://mms-sms/threadID");
+    // Copied from frameworks/opt/telephony/src/java/android/provider/Telephony.java because we
+    // can't use ContentResolver during backup/restore.
+    private static long getOrCreateThreadId(
+            ContentProvider contentProvider, Set<String> recipients) {
+        Uri.Builder uriBuilder = THREAD_ID_CONTENT_URI.buildUpon();
+
+        for (String recipient : recipients) {
+            if (Telephony.Mms.isEmailAddress(recipient)) {
+                recipient = Telephony.Mms.extractAddrSpec(recipient);
+            }
+
+            uriBuilder.appendQueryParameter("recipient", recipient);
+        }
+
+        Uri uri = uriBuilder.build();
+
+        try (Cursor cursor = contentProvider.query(uri, PROJECTION_ID, null, null, null)) {
+            if (cursor != null) {
+                if (cursor.moveToFirst()) {
+                    return cursor.getLong(0);
+                } else {
+                    Log.e(TAG, "getOrCreateThreadId returned no rows!");
+                }
+            }
+        }
+
+        Log.e(TAG, "getOrCreateThreadId failed with " + recipients.size() + " recipients");
+        throw new IllegalArgumentException("Unable to find or allocate a thread ID.");
+    }
+    @Override
+    public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
+                         ParcelFileDescriptor newState) throws IOException {
+        // Empty because is not used during full backup.
+    }
+
+    @Override
+    public void onRestore(BackupDataInput data, int appVersionCode,
+                          ParcelFileDescriptor newState) throws IOException {
+        // Empty because is not used during full restore.
+    }
+}
diff --git a/tests/Android.mk b/tests/Android.mk
new file mode 100644
index 0000000..1041716
--- /dev/null
+++ b/tests/Android.mk
@@ -0,0 +1,19 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_STATIC_JAVA_LIBRARIES := mockito-target
+
+LOCAL_JAVA_LIBRARIES := android.test.runner
+
+LOCAL_SRC_FILES := $(call all-java-files-under,src)
+
+LOCAL_PACKAGE_NAME := TelephonyProviderTests
+LOCAL_CERTIFICATE := platform
+
+LOCAL_INSTRUMENTATION_FOR := TelephonyProvider
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_PACKAGE)
diff --git a/tests/AndroidManifest.xml b/tests/AndroidManifest.xml
new file mode 100644
index 0000000..7a273fc
--- /dev/null
+++ b/tests/AndroidManifest.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.providers.telephony.tests">
+
+    <application>
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <instrumentation android:name="android.test.InstrumentationTestRunner"
+        android:targetPackage="com.android.providers.telephony"
+        android:label="Tests for TelephonyProvider">
+    </instrumentation>
+</manifest>
diff --git a/tests/src/com/android/providers/telephony/TelephonyBackupAgentTest.java b/tests/src/com/android/providers/telephony/TelephonyBackupAgentTest.java
new file mode 100644
index 0000000..5ce7a47
--- /dev/null
+++ b/tests/src/com/android/providers/telephony/TelephonyBackupAgentTest.java
@@ -0,0 +1,704 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.providers.telephony;
+
+import android.annotation.TargetApi;
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Build;
+import android.provider.BaseColumns;
+import android.provider.Telephony;
+import android.test.AndroidTestCase;
+import android.test.mock.MockContentProvider;
+import android.test.mock.MockCursor;
+import android.util.ArrayMap;
+import android.util.JsonReader;
+import android.util.JsonWriter;
+import android.util.SparseArray;
+
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+
+/**
+ * Tests for testing backup/restore of SMS and text MMS messages.
+ * For backup it creates fake provider and checks resulting json array.
+ * For restore provides json array and checks inserts of the messages into provider.
+ */
+@TargetApi(Build.VERSION_CODES.M)
+public class TelephonyBackupAgentTest extends AndroidTestCase {
+    private SparseArray<String> mSubId2Phone;
+    private ArrayMap<String, Integer> mPhone2SubId;
+    private final List<ContentValues> mSmsTable = new ArrayList<>();
+    private final List<ContentValues> mMmsTable = new ArrayList<>();
+    private final List<ContentValues> mMmsAllContentValues = new ArrayList<>();
+    private FakeCursor mSmsCursor, mMmsCursor;
+    private ContentValues[] mSmsRows, mMmsRows;
+    private ContentValues mMmsNonText;
+    private String[] mSmsJson, mMmsJson;
+    private String mAllSmsJson, mAllMmsJson;
+
+
+    private StringWriter mStringWriter;
+    private Map<Uri, FakeCursor> mCursors;
+    private MockContentProvider mContentProvider;
+
+    private static final String EMPTY_JSON_ARRAY = "[]";
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mStringWriter = new StringWriter();
+        mSubId2Phone = new SparseArray<String>();
+        mSubId2Phone.append(1, "+111111111111111");
+        mSubId2Phone.append(3, "+333333333333333");
+
+        mPhone2SubId = new ArrayMap<>();
+        for (int i=0; i<mSubId2Phone.size(); ++i) {
+            mPhone2SubId.put(mSubId2Phone.valueAt(i), mSubId2Phone.keyAt(i));
+        }
+
+        mSmsCursor = new FakeCursor(mSmsTable, TelephonyBackupAgent.SMS_PROJECTION);
+        mMmsCursor = new FakeCursor(mMmsTable, TelephonyBackupAgent.MMS_PROJECTION);
+        mCursors = new HashMap<Uri, FakeCursor>();
+
+        mSmsRows = new ContentValues[3];
+        mSmsJson = new String[3];
+        mSmsRows[0] = createSmsRow(1, 1, "+1232132214124", "sms 1", "sms subject", 9087978987l,
+                999999999, 3, 44, 1);
+        mSmsJson[0] = "{\"self_phone\":\"+111111111111111\",\"address\":" +
+                "\"+1232132214124\",\"body\":\"sms 1\",\"subject\":\"sms subject\",\"date\":" +
+                "\"9087978987\",\"date_sent\":\"999999999\",\"status\":\"3\",\"type\":\"44\"}";
+
+        mSmsRows[1] = createSmsRow(2, 2, "+1232132214124", "sms 2", null, 9087978987l, 999999999,
+                0, 4, 1);
+        mSmsJson[1] = "{\"address\":\"+1232132214124\",\"body\":\"sms 2\",\"date\":" +
+                "\"9087978987\",\"date_sent\":\"999999999\",\"status\":\"0\",\"type\":\"4\"}";
+
+        mSmsRows[2] = createSmsRow(4, 3, "+1232221412433 +1232221412444", "sms 3", null,
+                111111111111l, 999999999, 2, 3, 2);
+        mSmsJson[2] =  "{\"self_phone\":\"+333333333333333\",\"address\":" +
+                "\"+1232221412433 +1232221412444\",\"body\":\"sms 3\",\"date\":\"111111111111\"," +
+                "\"date_sent\":" +
+                "\"999999999\",\"status\":\"2\",\"type\":\"3\"}";
+
+        mAllSmsJson = concatJson(mSmsJson);
+
+
+
+        mMmsRows = new ContentValues[3];
+        mMmsJson = new String[3];
+        mMmsRows[0] = createMmsRow(1 /*id*/, 1 /*subid*/, "Subject 1" /*subject*/,
+                100 /*subcharset*/, 111111 /*date*/, 111112 /*datesent*/, 3 /*type*/,
+                17 /*version*/, 1 /*textonly*/,
+                11 /*msgBox*/, "location 1" /*contentLocation*/, "MMs body 1" /*body*/,
+                111 /*body charset*/,
+                new String[]{"+11121212", "example@example.com", "+999999999"} /*addresses*/,
+                1 /*threadId*/);
+
+        mMmsJson[0] = "{\"self_phone\":\"+111111111111111\",\"sub\":\"Subject 1\"," +
+                "\"date\":\"111111\",\"date_sent\":\"111112\",\"m_type\":\"3\",\"v\":\"17\"," +
+                "\"msg_box\":\"11\",\"ct_l\":\"location 1\",\"mms_addresses\":[{\"type\":10," +
+                "\"address\":\"+11121212\",\"charset\":100},{\"type\":11,\"address\":" +
+                "\"example@example.com\",\"charset\":101},{\"type\":12,\"address\":\"+999999999\"" +
+                ",\"charset\":102}],\"mms_body\":\"MMs body 1\",\"mms_charset\":111,\"" +
+                "sub_cs\":\"100\"}";
+
+        mMmsRows[1] = createMmsRow(2 /*id*/, 2 /*subid*/, null /*subject*/, 100 /*subcharset*/,
+                111122 /*date*/, 1111112 /*datesent*/, 4 /*type*/, 18 /*version*/, 1 /*textonly*/,
+                222 /*msgBox*/, "location 2" /*contentLocation*/, "MMs body 2" /*body*/,
+                121 /*body charset*/,
+                new String[]{"example@example.com", "+999999999"} /*addresses*/, 2 /*threadId*/);
+
+        mMmsJson[1] = "{\"date\":\"111122\",\"date_sent\":\"1111112\",\"m_type\":\"4\"," +
+                "\"v\":\"18\",\"msg_box\":\"222\",\"ct_l\":\"location 2\",\"mms_addresses\":" +
+                "[{\"type\":10,\"address\":\"example@example.com\",\"charset\":100}," +
+                "{\"type\":11,\"address\":\"+999999999\",\"charset\":101}]," +
+                "\"mms_body\":\"MMs body 2\",\"mms_charset\":121}";
+
+        mMmsRows[2] = createMmsRow(10 /*id*/, 3 /*subid*/, "Subject 10" /*subject*/,
+                10 /*subcharset*/, 111133 /*date*/, 1111132 /*datesent*/, 5 /*type*/,
+                19 /*version*/, 1 /*textonly*/,
+                333 /*msgBox*/, null /*contentLocation*/, "MMs body 3" /*body*/,
+                131 /*body charset*/, new String[]{"+8888888888"} /*addresses*/, 3 /*threadId*/);
+
+        mMmsJson[2] = "{\"self_phone\":\"+333333333333333\",\"sub\":\"Subject 10\"," +
+                "\"date\":\"111133\",\"date_sent\":\"1111132\",\"m_type\":\"5\",\"v\":\"19\"," +
+                "\"msg_box\":\"333\",\"mms_addresses\":[{\"type\":10,\"address\":\"+8888888888\"," +
+                "\"charset\":100}],\"mms_body\":\"MMs body 3\",\"mms_charset\":131," +
+                "\"sub_cs\":\"10\"}";
+        mAllMmsJson = concatJson(mMmsJson);
+
+
+        // Should not be backed up. Cause flag text_only is false.
+        mMmsNonText = createMmsRow(10 /*id*/, 3 /*subid*/, "Subject 10" /*subject*/,
+                10 /*subcharset*/,
+                111133 /*date*/, 1111132 /*datesent*/, 5 /*type*/, 19 /*version*/, 0 /*textonly*/,
+                333 /*msgBox*/, null /*contentLocation*/, "MMs body 3" /*body*/,
+                131 /*body charset*/, new String[]{"+8888888888"} /*addresses*/, 3 /*threadId*/);
+
+        mContentProvider = new MockContentProvider() {
+            @Override
+            public Cursor query(Uri uri, String[] projection, String selection,
+                                String[] selectionArgs, String sortOrder) {
+                if (mCursors.containsKey(uri)) {
+                    FakeCursor fakeCursor = mCursors.get(uri);
+                    if (projection != null) {
+                        fakeCursor.setProjection(projection);
+                    }
+                    return fakeCursor;
+                }
+                return super.query(uri, projection, selection, selectionArgs, sortOrder);
+            }
+        };
+
+    }
+
+    private static String concatJson(String[] json) {
+        StringBuilder stringBuilder = new StringBuilder("[");
+        for (int i=0; i<json.length; ++i) {
+            if (i > 0) {
+                stringBuilder.append(",");
+            }
+            stringBuilder.append(json[i]);
+        }
+        stringBuilder.append("]");
+        return stringBuilder.toString();
+    }
+
+    private static ContentValues createSmsRow(int id, int subId, String address, String body,
+                                              String subj, long date, long dateSent,
+                                              int status, int type, long threadId) {
+        ContentValues smsRow = new ContentValues();
+        smsRow.put(Telephony.Sms._ID, id);
+        smsRow.put(Telephony.Sms.SUBSCRIPTION_ID, subId);
+        if (address != null) {
+            smsRow.put(Telephony.Sms.ADDRESS, address);
+        }
+        if (body != null) {
+            smsRow.put(Telephony.Sms.BODY, body);
+        }
+        if (subj != null) {
+            smsRow.put(Telephony.Sms.SUBJECT, subj);
+        }
+        smsRow.put(Telephony.Sms.DATE, String.valueOf(date));
+        smsRow.put(Telephony.Sms.DATE_SENT, String.valueOf(dateSent));
+        smsRow.put(Telephony.Sms.STATUS, String.valueOf(status));
+        smsRow.put(Telephony.Sms.TYPE, String.valueOf(type));
+        smsRow.put(Telephony.Sms.THREAD_ID, threadId);
+
+        return smsRow;
+    }
+
+    private ContentValues createMmsRow(int id, int subId, String subj, int subCharset,
+                                       long date, long dateSent, int type, int version,
+                                       int textOnly, int msgBox,
+                                       String contentLocation, String body,
+                                       int bodyCharset, String[] addresses, long threadId) {
+        ContentValues mmsRow = new ContentValues();
+        mmsRow.put(Telephony.Mms._ID, id);
+        mmsRow.put(Telephony.Mms.SUBSCRIPTION_ID, subId);
+        if (subj != null) {
+            mmsRow.put(Telephony.Mms.SUBJECT, subj);
+            mmsRow.put(Telephony.Mms.SUBJECT_CHARSET, String.valueOf(subCharset));
+        }
+        mmsRow.put(Telephony.Mms.DATE, String.valueOf(date));
+        mmsRow.put(Telephony.Mms.DATE_SENT, String.valueOf(dateSent));
+        mmsRow.put(Telephony.Mms.MESSAGE_TYPE, String.valueOf(type));
+        mmsRow.put(Telephony.Mms.MMS_VERSION, String.valueOf(version));
+        mmsRow.put(Telephony.Mms.TEXT_ONLY, textOnly);
+        mmsRow.put(Telephony.Mms.MESSAGE_BOX, String.valueOf(msgBox));
+        if (contentLocation != null) {
+            mmsRow.put(Telephony.Mms.CONTENT_LOCATION, contentLocation);
+        }
+        mmsRow.put(Telephony.Mms.THREAD_ID, threadId);
+
+        final Uri partUri = Telephony.Mms.CONTENT_URI.buildUpon().appendPath(String.valueOf(id)).
+                appendPath("part").build();
+        mCursors.put(partUri, createBodyCursor(body, bodyCharset));
+        mMmsAllContentValues.add(mmsRow);
+
+        final Uri addrUri = Telephony.Mms.CONTENT_URI.buildUpon().appendPath(String.valueOf(id)).
+                appendPath("addr").build();
+        mCursors.put(addrUri, createAddrCursor(addresses));
+
+        return mmsRow;
+    }
+
+    private static final String APP_SMIL = "application/smil";
+    private static final String TEXT_PLAIN = "text/plain";
+
+    // Cursor with parts of Mms.
+    private FakeCursor createBodyCursor(String body, int charset) {
+        List<ContentValues> table = new ArrayList<>();
+
+        final String srcName = String.format("text.%06d.txt", 0);
+        final String smilBody = String.format(TelephonyBackupAgent.sSmilTextPart, srcName);
+        final String smil = String.format(TelephonyBackupAgent.sSmilTextOnly, smilBody);
+
+        final ContentValues smilPart = new ContentValues();
+        smilPart.put(Telephony.Mms.Part.SEQ, -1);
+        smilPart.put(Telephony.Mms.Part.CONTENT_TYPE, APP_SMIL);
+        smilPart.put(Telephony.Mms.Part.NAME, "smil.xml");
+        smilPart.put(Telephony.Mms.Part.CONTENT_ID, "<smil>");
+        smilPart.put(Telephony.Mms.Part.CONTENT_LOCATION, "smil.xml");
+        smilPart.put(Telephony.Mms.Part.TEXT, smil);
+        table.add(smilPart); // This part should not be backed up.
+        mMmsAllContentValues.add(smilPart);
+
+        final ContentValues bodyPart = new ContentValues();
+        bodyPart.put(Telephony.Mms.Part.SEQ, 0);
+        bodyPart.put(Telephony.Mms.Part.CONTENT_TYPE, TEXT_PLAIN);
+        bodyPart.put(Telephony.Mms.Part.NAME, srcName);
+        bodyPart.put(Telephony.Mms.Part.CONTENT_ID, "<"+srcName+">");
+        bodyPart.put(Telephony.Mms.Part.CONTENT_LOCATION, srcName);
+        bodyPart.put(Telephony.Mms.Part.CHARSET, charset);
+        bodyPart.put(Telephony.Mms.Part.TEXT, body);
+        table.add(bodyPart);
+        mMmsAllContentValues.add(bodyPart);
+
+        return new FakeCursor(table, TelephonyBackupAgent.MMS_TEXT_PROJECTION);
+    }
+
+    // Cursor with addresses of Mms.
+    private FakeCursor createAddrCursor(String[] addresses) {
+        List<ContentValues> table = new ArrayList<>();
+        for (int i=0; i<addresses.length; ++i) {
+            ContentValues addr = new ContentValues();
+            addr.put(Telephony.Mms.Addr.TYPE, 10+i);
+            addr.put(Telephony.Mms.Addr.ADDRESS, addresses[i]);
+            addr.put(Telephony.Mms.Addr.CHARSET, 100 + i);
+            mMmsAllContentValues.add(addr);
+            table.add(addr);
+        }
+        return new FakeCursor(table, TelephonyBackupAgent.MMS_ADDR_PROJECTION);
+    }
+
+    /**
+     * Test with no sms in the provider.
+     * @throws Exception
+     */
+    public void testBackupSms_NoSms() throws Exception {
+        TelephonyBackupAgent.putSmsMessagesToJson(mSmsCursor, mSubId2Phone,
+                new JsonWriter(mStringWriter), 1);
+        assertEquals(EMPTY_JSON_ARRAY, mStringWriter.toString());
+    }
+
+    /**
+     * Test with 3 sms in the provider with the limit per file 4.
+     * @throws Exception
+     */
+    public void testBackupSms_AllSms() throws Exception {
+        mSmsTable.addAll(Arrays.asList(mSmsRows));
+        TelephonyBackupAgent.putSmsMessagesToJson(mSmsCursor, mSubId2Phone,
+                new JsonWriter(mStringWriter), 4);
+        final String expected =
+                "[" + mSmsJson[0] + "," + mSmsJson[1] + "," + mSmsJson[2] + "]";
+        assertEquals(expected, mStringWriter.toString());
+    }
+
+    /**
+     * Test with 3 sms in the provider with the limit per file 3.
+     * @throws Exception
+     */
+    public void testBackupSms_AllSmsWithExactFileLimit() throws Exception {
+        mSmsTable.addAll(Arrays.asList(mSmsRows));
+        TelephonyBackupAgent.putSmsMessagesToJson(mSmsCursor, mSubId2Phone,
+                new JsonWriter(mStringWriter), 3);
+        final String expected =
+                "[" + mSmsJson[0] + "," + mSmsJson[1] + "," + mSmsJson[2] + "]";
+        assertEquals(expected, mStringWriter.toString());
+    }
+
+    /**
+     * Test with 3 sms in the provider with the limit per file 1.
+     * @throws Exception
+     */
+    public void testBackupSms_AllSmsOneMessagePerFile() throws Exception {
+        mSmsTable.addAll(Arrays.asList(mSmsRows));
+        TelephonyBackupAgent.putSmsMessagesToJson(mSmsCursor, mSubId2Phone,
+                new JsonWriter(mStringWriter), 1);
+        assertEquals("[" + mSmsJson[0] + "]", mStringWriter.toString());
+
+        mStringWriter = new StringWriter();
+        TelephonyBackupAgent.putSmsMessagesToJson(mSmsCursor, mSubId2Phone,
+                new JsonWriter(mStringWriter), 1);
+        assertEquals("[" + mSmsJson[1] + "]", mStringWriter.toString());
+
+        mStringWriter = new StringWriter();
+        TelephonyBackupAgent.putSmsMessagesToJson(mSmsCursor, mSubId2Phone,
+                new JsonWriter(mStringWriter), 1);
+        assertEquals("[" + mSmsJson[2] + "]", mStringWriter.toString());
+    }
+
+    /**
+     * Test with no mms in the pvovider.
+     * @throws Exception
+     */
+    public void testBackupMms_NoMms() throws Exception {
+        TelephonyBackupAgent.putMmsMessagesToJson(mMmsCursor, mContentProvider, mSubId2Phone,
+                new JsonWriter(mStringWriter), 4);
+        assertEquals(EMPTY_JSON_ARRAY, mStringWriter.toString());
+    }
+
+    /**
+     * Test with all mms.
+     * @throws Exception
+     */
+    public void testBackupMms_AllMms() throws Exception {
+        mMmsTable.addAll(Arrays.asList(mMmsRows));
+        mMmsTable.add(mMmsNonText);
+        TelephonyBackupAgent.putMmsMessagesToJson(mMmsCursor, mContentProvider, mSubId2Phone,
+                new JsonWriter(mStringWriter), 4);
+        final String expected =
+                "[" + mMmsJson[0] + "," + mMmsJson[1] + "," + mMmsJson[2] + "]";
+        assertEquals(expected, mStringWriter.toString());
+    }
+
+    /**
+     * Test with 3 mms in the provider with the limit per file 1.
+     * @throws Exception
+     */
+    public void testBackupMms_OneMessagePerFile() throws Exception {
+        mMmsTable.addAll(Arrays.asList(mMmsRows));
+        TelephonyBackupAgent.putMmsMessagesToJson(mMmsCursor, mContentProvider, mSubId2Phone,
+                new JsonWriter(mStringWriter), 1);
+        assertEquals("[" + mMmsJson[0] + "]", mStringWriter.toString());
+
+        mStringWriter = new StringWriter();
+        TelephonyBackupAgent.putMmsMessagesToJson(mMmsCursor, mContentProvider, mSubId2Phone,
+                new JsonWriter(mStringWriter), 1);
+        assertEquals("[" + mMmsJson[1] + "]", mStringWriter.toString());
+
+        mStringWriter = new StringWriter();
+        TelephonyBackupAgent.putMmsMessagesToJson(mMmsCursor, mContentProvider, mSubId2Phone,
+                new JsonWriter(mStringWriter), 2);
+        assertEquals("[" + mMmsJson[2] + "]", mStringWriter.toString());
+    }
+
+    /**
+     * Test with 3 mms in the provider with the limit per file 3.
+     * @throws Exception
+     */
+    public void testBackupMms_WithExactFileLimit() throws Exception {
+        mMmsTable.addAll(Arrays.asList(mMmsRows));
+        TelephonyBackupAgent.putMmsMessagesToJson(mMmsCursor, mContentProvider, mSubId2Phone,
+                new JsonWriter(mStringWriter), 3);
+        final String expected =
+                "[" + mMmsJson[0] + "," + mMmsJson[1] + "," + mMmsJson[2] + "]";
+        assertEquals(expected, mStringWriter.toString());
+    }
+
+    /**
+     * Test restore sms with the empty json array "[]".
+     * @throws Exception
+     */
+    public void testRestoreSms_NoSms() throws Exception {
+        JsonReader jsonReader = new JsonReader(new StringReader(EMPTY_JSON_ARRAY));
+        FakeSmsProvider smsProvider = new FakeSmsProvider(null);
+        TelephonyBackupAgent.putSmsMessagesToProvider(jsonReader, smsProvider,
+                new ThreadProvider(), mPhone2SubId);
+        assertEquals(0, smsProvider.getRowsAdded());
+    }
+
+    /**
+     * Test restore sms with three sms json object in the array.
+     * @throws Exception
+     */
+    public void testRestoreSms_AllSms() throws Exception {
+        JsonReader jsonReader = new JsonReader(new StringReader(mAllSmsJson));
+        FakeSmsProvider smsProvider = new FakeSmsProvider(mSmsRows);
+        TelephonyBackupAgent.putSmsMessagesToProvider(jsonReader, smsProvider,
+                new ThreadProvider(), mPhone2SubId);
+        assertEquals(mSmsRows.length, smsProvider.getRowsAdded());
+    }
+
+    /**
+     * Test restore mms with the empty json array "[]".
+     * @throws Exception
+     */
+    public void testRestoreMms_NoMms() throws Exception {
+        JsonReader jsonReader = new JsonReader(new StringReader(EMPTY_JSON_ARRAY));
+        FakeMmsProvider mmsProvider = new FakeMmsProvider(null);
+        TelephonyBackupAgent.putMmsMessagesToProvider(jsonReader, mmsProvider,
+                new ThreadProvider(), mPhone2SubId);
+        assertEquals(0, mmsProvider.getRowsAdded());
+    }
+
+    /**
+     * Test restore sms with three mms json object in the array.
+     * @throws Exception
+     */
+    public void testRestoreMms_AllMms() throws Exception {
+        JsonReader jsonReader = new JsonReader(new StringReader(mAllMmsJson));
+        FakeMmsProvider mmsProvider = new FakeMmsProvider(mMmsAllContentValues);
+        TelephonyBackupAgent.putMmsMessagesToProvider(jsonReader, mmsProvider,
+                new ThreadProvider(), mPhone2SubId);
+        assertEquals(15, mmsProvider.getRowsAdded());
+    }
+
+    /**
+     * class for checking sms insertion into the provider on restore.
+     */
+    private class FakeSmsProvider extends MockContentProvider {
+        private int nextRow = 0;
+        private ContentValues[] mSms;
+
+        public FakeSmsProvider(ContentValues[] sms) {
+            this.mSms = sms;
+        }
+
+        @Override
+        public Uri insert(Uri uri, ContentValues values) {
+            assertEquals(Telephony.Sms.CONTENT_URI, uri);
+            ContentValues modifiedValues = new ContentValues(mSms[nextRow++]);
+            modifiedValues.remove(Telephony.Sms._ID);
+            modifiedValues.put(Telephony.Sms.READ, 1);
+            modifiedValues.put(Telephony.Sms.SEEN, 1);
+            if (mSubId2Phone.get(modifiedValues.getAsInteger(Telephony.Sms.SUBSCRIPTION_ID))
+                    == null) {
+                modifiedValues.put(Telephony.Sms.SUBSCRIPTION_ID, -1);
+            }
+
+            assertEquals(modifiedValues, values);
+            return null;
+        }
+
+        @Override
+        public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
+                            String sortOrder) {
+            return null;
+        }
+
+        public int getRowsAdded() {
+            return nextRow;
+        }
+    }
+
+    /**
+     * class for checking mms insertion into the provider on restore.
+     */
+    private class FakeMmsProvider extends MockContentProvider {
+        private int nextRow = 0;
+        private List<ContentValues> mValues;
+        private long mDummyMsgId = -1;
+        private long mMsgId = -1;
+
+        public FakeMmsProvider(List<ContentValues> values) {
+            this.mValues = values;
+        }
+
+        @Override
+        public Uri insert(Uri uri, ContentValues values) {
+            Uri retUri = Uri.parse("dummy_uri");
+            ContentValues modifiedValues = new ContentValues(mValues.get(nextRow++));
+            if (APP_SMIL.equals(values.get(Telephony.Mms.Part.CONTENT_TYPE))) {
+                // Smil part.
+                assertEquals(-1, mDummyMsgId);
+                mDummyMsgId = values.getAsLong(Telephony.Mms.Part.MSG_ID);
+            }
+
+            if (values.get(Telephony.Mms.Part.SEQ) != null) {
+                // Part of mms.
+                final Uri expectedUri = Telephony.Mms.CONTENT_URI.buildUpon()
+                        .appendPath(String.valueOf(mDummyMsgId))
+                        .appendPath("part")
+                        .build();
+                assertEquals(expectedUri, uri);
+            }
+
+            if (values.get(Telephony.Mms.Part.MSG_ID) != null) {
+                modifiedValues.put(Telephony.Mms.Part.MSG_ID, mDummyMsgId);
+            }
+
+
+            if (values.get(Telephony.Mms.SUBSCRIPTION_ID) != null) {
+                assertEquals(Telephony.Mms.CONTENT_URI, uri);
+                if (mSubId2Phone.get(modifiedValues.getAsInteger(Telephony.Sms.SUBSCRIPTION_ID))
+                        == null) {
+                    modifiedValues.put(Telephony.Sms.SUBSCRIPTION_ID, -1);
+                }
+                // Mms.
+                modifiedValues.put(Telephony.Mms.READ, 1);
+                modifiedValues.put(Telephony.Mms.SEEN, 1);
+                mMsgId = modifiedValues.getAsInteger(BaseColumns._ID);
+                retUri = Uri.withAppendedPath(Telephony.Mms.CONTENT_URI, String.valueOf(mMsgId));
+                modifiedValues.remove(BaseColumns._ID);
+            }
+
+            if (values.get(Telephony.Mms.Addr.ADDRESS) != null) {
+                // Address.
+                final Uri expectedUri = Telephony.Mms.CONTENT_URI.buildUpon()
+                        .appendPath(String.valueOf(mMsgId))
+                        .appendPath("addr")
+                        .build();
+                assertEquals(expectedUri, uri);
+                assertNotSame(-1, mMsgId);
+                modifiedValues.put(Telephony.Mms.Addr.MSG_ID, mMsgId);
+                mDummyMsgId = -1;
+            }
+
+            for (String key : modifiedValues.keySet()) {
+                assertEquals(modifiedValues.get(key), values.get(key));
+            }
+            assertEquals(modifiedValues.size(), values.size());
+            return retUri;
+        }
+
+        @Override
+        public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
+            final Uri expectedUri = Telephony.Mms.CONTENT_URI.buildUpon()
+                    .appendPath(String.valueOf(mDummyMsgId))
+                    .appendPath("part")
+                    .build();
+            assertEquals(expectedUri, uri);
+            ContentValues expected = new ContentValues();
+            expected.put(Telephony.Mms.Part.MSG_ID, mMsgId);
+            assertEquals(expected, values);
+            return 2;
+        }
+
+        @Override
+        public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
+                            String sortOrder) {
+            return null;
+        }
+
+        public int getRowsAdded() {
+            return nextRow;
+        }
+    }
+
+    /**
+     * class that implements MmsSms provider for thread ids.
+     */
+    private static class ThreadProvider extends MockContentProvider {
+
+        Map<List<String>, Integer> threadIds;
+
+        public ThreadProvider() {
+            threadIds = new ArrayMap<>();
+        }
+
+        @Override
+        public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
+                            String sortOrder) {
+            List<String> recipients = uri.getQueryParameters("recipient");
+            int threadId = threadIds.size() + 1;
+            if (threadIds.containsKey(recipients)) {
+                threadId = threadIds.get(recipients);
+            } else {
+                threadIds.put(recipients, threadId);
+            }
+
+            List<ContentValues> table = new ArrayList<>();
+            ContentValues row = new ContentValues();
+            row.put(BaseColumns._ID, String.valueOf(threadId));
+            table.add(row);
+            return new FakeCursor(table, projection);
+        }
+    }
+
+    /**
+     * general cursor for serving queries.
+     */
+    private static class FakeCursor extends MockCursor {
+        String[] projection;
+        List<ContentValues> rows;
+        int nextRow = -1;
+
+        public FakeCursor(List<ContentValues> rows, String[] projection) {
+            this.projection = projection;
+            this.rows = rows;
+        }
+
+        public void setProjection(String[] projection) {
+            this.projection = projection;
+        }
+
+        @Override
+        public int getColumnCount() {
+            return projection.length;
+        }
+
+        @Override
+        public String getColumnName(int columnIndex) {
+            return projection[columnIndex];
+        }
+
+        @Override
+        public String getString(int columnIndex) {
+            return rows.get(nextRow).getAsString(projection[columnIndex]);
+        }
+
+        @Override
+        public int getInt(int columnIndex) {
+            return rows.get(nextRow).getAsInteger(projection[columnIndex]);
+        }
+
+        @Override
+        public long getLong(int columnIndex) {
+            return rows.get(nextRow).getAsLong(projection[columnIndex]);
+        }
+
+        @Override
+        public boolean isAfterLast() {
+            return nextRow >= getCount();
+        }
+
+        @Override
+        public boolean isLast() {
+            return nextRow == getCount() - 1;
+        }
+
+        @Override
+        public boolean moveToFirst() {
+            nextRow = 0;
+            return getCount() > 0;
+        }
+
+        @Override
+        public boolean moveToNext() {
+            return getCount() > ++nextRow;
+        }
+
+        @Override
+        public int getCount() {
+            return rows.size();
+        }
+
+        @Override
+        public int getColumnIndex(String columnName) {
+            for (int i=0; i<projection.length; ++i) {
+                if (columnName.equals(projection[i])) {
+                    return i;
+                }
+            }
+            return -1;
+        }
+
+        @Override
+        public void close() {
+        }
+    }
+}
