/*
 * 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.app.AlarmManager;
import android.app.IntentService;
import android.app.backup.BackupAgent;
import android.app.backup.BackupDataInput;
import android.app.backup.BackupDataOutput;
import android.app.backup.FullBackupDataOutput;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.database.DatabaseUtils;
import android.net.Uri;
import android.os.Build;
import android.os.ParcelFileDescriptor;
import android.os.PowerManager;
import android.provider.BaseColumns;
import android.provider.Telephony;
import android.telephony.PhoneNumberUtils;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.text.TextUtils;
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 com.android.internal.annotations.VisibleForTesting;

import com.google.android.mms.ContentType;
import com.google.android.mms.pdu.CharacterSets;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
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",
 *  "attachments":[{"mime_type":"image/jpeg","filename":"image000000.jpg"}],
 *  "smil":"<smil><head><layout><root-layout/><region id='Image' fit='meet' top='0' left='0'
 *   height='100%' width='100%'/></layout></head><body><par dur='5000ms'><img src='image000000.jpg'
 *   region='Image' /></par></body></smil>",
 *  "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.
 *
 *   It stores how many bytes we are over the quota and don't backup the oldest messages.
 *
 *   NOTE: presently, only MMS's with text are backed up. However, MMS's with attachments are
 *   restored. In other words, this code can restore MMS attachments if the attachment data
 *   is in the json, but it doesn't currently backup the attachment data in the json.
 */

@TargetApi(Build.VERSION_CODES.M)
public class TelephonyBackupAgent extends BackupAgent {
    private static final String TAG = "TelephonyBackupAgent";
    private static final boolean DEBUG = false;
    private static volatile boolean sIsRestoring;


    // 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 list of attachments of MMS message.
    private static final String MMS_ATTACHMENTS_KEY = "attachments";
    // JSON key for SMIL part of the MMS.
    private static final String MMS_SMIL_KEY = "smil";
    // JSON key for list of recipients of the message.
    private static final String RECIPIENTS = "recipients";
    // 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";
    // JSON key for mime type.
    private static final String MMS_MIME_TYPE = "mime_type";
    // JSON key for attachment filename.
    private static final String MMS_ATTACHMENT_FILENAME = "filename";

    // File names suffixes for backup/restore.
    private static final String SMS_BACKUP_FILE_SUFFIX = "_sms_backup";
    private static final String MMS_BACKUP_FILE_SUFFIX = "_mms_backup";

    // File name formats for backup. It looks like 000000_sms_backup, 000001_sms_backup, etc.
    private static final String SMS_BACKUP_FILE_FORMAT = "%06d"+SMS_BACKUP_FILE_SUFFIX;
    private static final String MMS_BACKUP_FILE_FORMAT = "%06d"+MMS_BACKUP_FILE_SUFFIX;

    // 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";

    // Order by Date entries from database. We start backup from the oldest.
    private static final String ORDER_BY_DATE = "date ASC";

    // This is a hard coded string rather than a localized one because we don't want it to
    // change when you change locale.
    @VisibleForTesting
    static final String UNKNOWN_SENDER = "\u02BCUNKNOWN_SENDER!\u02BC";

    private static String ATTACHMENT_DATA_PATH = "/app_parts/";

    // Thread id for UNKNOWN_SENDER.
    private long mUnknownSenderThreadId;

    // 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,
            Telephony.Sms.THREAD_ID,
            Telephony.Sms.READ
    };

    // Columns to fetch recepients of SMS.
    private static final String[] SMS_RECIPIENTS_PROJECTION = {
            Telephony.Threads._ID,
            Telephony.Threads.RECIPIENT_IDS
    };

    // 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.MESSAGE_BOX,
            Telephony.Mms.CONTENT_LOCATION,
            Telephony.Mms.THREAD_ID,
            Telephony.Mms.TRANSACTION_ID,
            Telephony.Mms.READ
    };

    // 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.TEXT,
            Telephony.Mms.Part.CHARSET
    };
    static final int MMS_TEXT_IDX = 0;
    static final int MMS_TEXT_CHARSET_IDX = 1;

    // Buffer size for Json writer.
    public static final int WRITER_BUFFER_SIZE = 32*1024; //32Kb

    // We increase how many bytes backup size over quota by 10%, so we will fit into quota on next
    // backup
    public static final double BYTES_OVER_QUOTA_MULTIPLIER = 1.1;

    // 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.
    // Not final for the testing.
    @VisibleForTesting
    int mMaxMsgPerFile = 1000;

    // Default values for SMS, MMS, Addresses restore.
    private static ContentValues sDefaultValuesSms = new ContentValues(5);
    private static ContentValues sDefaultValuesMms = new ContentValues(6);
    private static final ContentValues sDefaultValuesAddr = new ContentValues(2);
    private static final ContentValues sDefaultValuesAttachments = new ContentValues(2);

    // Shared preferences for the backup agent.
    private static final String BACKUP_PREFS = "backup_shared_prefs";
    // Key for storing quota bytes.
    private static final String QUOTA_BYTES = "backup_quota_bytes";
    // Key for storing backup data size.
    private static final String BACKUP_DATA_BYTES = "backup_data_bytes";
    // Key for storing timestamp when backup agent resets quota. It does that to get onQuotaExceeded
    // call so it could get the new quota if it changed.
    private static final String QUOTA_RESET_TIME = "reset_quota_time";
    private static final long QUOTA_RESET_INTERVAL = 30 * AlarmManager.INTERVAL_DAY; // 30 days.


    static {
        // Consider restored messages read and seen by default. The actual data can override
        // these values.
        sDefaultValuesSms.put(Telephony.Sms.READ, 1);
        sDefaultValuesSms.put(Telephony.Sms.SEEN, 1);
        sDefaultValuesSms.put(Telephony.Sms.ADDRESS, UNKNOWN_SENDER);
        // If there is no sub_id with self phone number on restore set it to -1.
        sDefaultValuesSms.put(Telephony.Sms.SUBSCRIPTION_ID, -1);

        sDefaultValuesMms.put(Telephony.Mms.READ, 1);
        sDefaultValuesMms.put(Telephony.Mms.SEEN, 1);
        sDefaultValuesMms.put(Telephony.Mms.SUBSCRIPTION_ID, -1);
        sDefaultValuesMms.put(Telephony.Mms.MESSAGE_BOX, Telephony.Mms.MESSAGE_BOX_ALL);
        sDefaultValuesMms.put(Telephony.Mms.TEXT_ONLY, 1);

        sDefaultValuesAddr.put(Telephony.Mms.Addr.TYPE, 0);
        sDefaultValuesAddr.put(Telephony.Mms.Addr.CHARSET, CharacterSets.DEFAULT_CHARSET);
    }


    private SparseArray<String> mSubId2phone = new SparseArray<String>();
    private Map<String, Integer> mPhone2subId = new ArrayMap<String, Integer>();
    private Map<Long, Boolean> mThreadArchived = new HashMap<>();

    private ContentResolver mContentResolver;
    // How many bytes we can backup to fit into quota.
    private long mBytesOverQuota;

    // Cache list of recipients by threadId. It reduces db requests heavily. Used during backup.
    @VisibleForTesting
    Map<Long, List<String>> mCacheRecipientsByThread = null;
    // Cache threadId by list of recipients. Used during restore.
    @VisibleForTesting
    Map<Set<String>, Long> mCacheGetOrCreateThreadId = null;

    @Override
    public void onCreate() {
        super.onCreate();

        final SubscriptionManager subscriptionManager = SubscriptionManager.from(this);
        if (subscriptionManager != null) {
            final List<SubscriptionInfo> subInfo =
                    subscriptionManager.getActiveSubscriptionInfoList(/* userVisibleonly */false);
            if (subInfo != null) {
                for (SubscriptionInfo sub : subInfo) {
                    final String phoneNumber = getNormalizedNumber(sub);
                    mSubId2phone.append(sub.getSubscriptionId(), phoneNumber);
                    mPhone2subId.put(phoneNumber, sub.getSubscriptionId());
                }
            }
        }
        mContentResolver = getContentResolver();
        initUnknownSender();
    }

    @VisibleForTesting
    void setContentResolver(ContentResolver contentResolver) {
        mContentResolver = contentResolver;
    }
    @VisibleForTesting
    void setSubId(SparseArray<String> subId2Phone, Map<String, Integer> phone2subId) {
        mSubId2phone = subId2Phone;
        mPhone2subId = phone2subId;
    }

    @VisibleForTesting
    void initUnknownSender() {
        mUnknownSenderThreadId = getOrCreateThreadId(null);
        sDefaultValuesSms.put(Telephony.Sms.THREAD_ID, mUnknownSenderThreadId);
        sDefaultValuesMms.put(Telephony.Mms.THREAD_ID, mUnknownSenderThreadId);
    }

    @Override
    public void onFullBackup(FullBackupDataOutput data) throws IOException {
        SharedPreferences sharedPreferences = getSharedPreferences(BACKUP_PREFS, MODE_PRIVATE);
        if (sharedPreferences.getLong(QUOTA_RESET_TIME, Long.MAX_VALUE) <
                System.currentTimeMillis()) {
            clearSharedPreferences();
        }

        mBytesOverQuota = sharedPreferences.getLong(BACKUP_DATA_BYTES, 0) -
                sharedPreferences.getLong(QUOTA_BYTES, Long.MAX_VALUE);
        if (mBytesOverQuota > 0) {
            mBytesOverQuota *= BYTES_OVER_QUOTA_MULTIPLIER;
        }

        try (
                Cursor smsCursor = mContentResolver.query(Telephony.Sms.CONTENT_URI, SMS_PROJECTION,
                        null, null, ORDER_BY_DATE);
                Cursor mmsCursor = mContentResolver.query(Telephony.Mms.CONTENT_URI, MMS_PROJECTION,
                        null, null, ORDER_BY_DATE)) {

            if (smsCursor != null) {
                smsCursor.moveToFirst();
            }
            if (mmsCursor != null) {
                mmsCursor.moveToFirst();
            }

            // It backs up messages from the oldest to newest. First it looks at the timestamp of
            // the next SMS messages and MMS message. If the SMS is older it backs up 1000 SMS
            // messages, otherwise 1000 MMS messages. Repeat until out of SMS's or MMS's.
            // It ensures backups are incremental.
            int fileNum = 0;
            while (smsCursor != null && !smsCursor.isAfterLast() &&
                    mmsCursor != null && !mmsCursor.isAfterLast()) {
                final long smsDate = TimeUnit.MILLISECONDS.toSeconds(getMessageDate(smsCursor));
                final long mmsDate = getMessageDate(mmsCursor);
                if (smsDate < mmsDate) {
                    backupAll(data, smsCursor,
                            String.format(Locale.US, SMS_BACKUP_FILE_FORMAT, fileNum++));
                } else {
                    backupAll(data, mmsCursor, String.format(Locale.US,
                            MMS_BACKUP_FILE_FORMAT, fileNum++));
                }
            }

            while (smsCursor != null && !smsCursor.isAfterLast()) {
                backupAll(data, smsCursor,
                        String.format(Locale.US, SMS_BACKUP_FILE_FORMAT, fileNum++));
            }

            while (mmsCursor != null && !mmsCursor.isAfterLast()) {
                backupAll(data, mmsCursor,
                        String.format(Locale.US, MMS_BACKUP_FILE_FORMAT, fileNum++));
            }
        }

        mThreadArchived = new HashMap<>();
    }

    @VisibleForTesting
    void clearSharedPreferences() {
        getSharedPreferences(BACKUP_PREFS, MODE_PRIVATE).edit()
                .remove(BACKUP_DATA_BYTES)
                .remove(QUOTA_BYTES)
                .remove(QUOTA_RESET_TIME)
                .apply();
    }

    private static long getMessageDate(Cursor cursor) {
        return cursor.getLong(cursor.getColumnIndex(Telephony.Sms.DATE));
    }

    @Override
    public void onQuotaExceeded(long backupDataBytes, long quotaBytes) {
        SharedPreferences sharedPreferences = getSharedPreferences(BACKUP_PREFS, MODE_PRIVATE);
        if (sharedPreferences.contains(BACKUP_DATA_BYTES)
                && sharedPreferences.contains(QUOTA_BYTES)) {
            // Increase backup size by the size we skipped during previous backup.
            backupDataBytes += (sharedPreferences.getLong(BACKUP_DATA_BYTES, 0)
                    - sharedPreferences.getLong(QUOTA_BYTES, 0)) * BYTES_OVER_QUOTA_MULTIPLIER;
        }
        sharedPreferences.edit()
                .putLong(BACKUP_DATA_BYTES, backupDataBytes)
                .putLong(QUOTA_BYTES, quotaBytes)
                .putLong(QUOTA_RESET_TIME, System.currentTimeMillis() + QUOTA_RESET_INTERVAL)
                .apply();
    }

    private void backupAll(FullBackupDataOutput data, Cursor cursor, String fileName)
            throws IOException {
        if (cursor == null || cursor.isAfterLast()) {
            return;
        }

        int messagesWritten = 0;
        try (JsonWriter jsonWriter = getJsonWriter(fileName)) {
            if (fileName.endsWith(SMS_BACKUP_FILE_SUFFIX)) {
                messagesWritten = putSmsMessagesToJson(cursor, jsonWriter);
            } else {
                messagesWritten = putMmsMessagesToJson(cursor, jsonWriter);
            }
        }
        backupFile(messagesWritten, fileName, data);
    }

    @VisibleForTesting
    int putMmsMessagesToJson(Cursor cursor,
                             JsonWriter jsonWriter) throws IOException {
        jsonWriter.beginArray();
        int msgCount;
        for (msgCount = 0; msgCount < mMaxMsgPerFile && !cursor.isAfterLast();
                cursor.moveToNext()) {
            msgCount += writeMmsToWriter(jsonWriter, cursor);
        }
        jsonWriter.endArray();
        return msgCount;
    }

    @VisibleForTesting
    int putSmsMessagesToJson(Cursor cursor, JsonWriter jsonWriter) throws IOException {

        jsonWriter.beginArray();
        int msgCount;
        for (msgCount = 0; msgCount < mMaxMsgPerFile && !cursor.isAfterLast();
                ++msgCount, cursor.moveToNext()) {
            writeSmsToWriter(jsonWriter, cursor);
        }
        jsonWriter.endArray();
        return msgCount;
    }

    private void backupFile(int messagesWritten, String fileName, FullBackupDataOutput data)
            throws IOException {
        final File file = new File(getFilesDir().getPath() + "/" + fileName);
        try {
            if (messagesWritten > 0) {
                if (mBytesOverQuota > 0) {
                    mBytesOverQuota -= file.length();
                    return;
                }
                super.fullBackupFile(file, data);
            }
        } finally {
            file.delete();
        }
    }

    public static class DeferredSmsMmsRestoreService extends IntentService {
        private static final String TAG = "DeferredSmsMmsRestoreService";

        private final Comparator<File> mFileComparator = new Comparator<File>() {
            @Override
            public int compare(File lhs, File rhs) {
                return rhs.getName().compareTo(lhs.getName());
            }
        };

        public DeferredSmsMmsRestoreService() {
            super(TAG);
            setIntentRedelivery(true);
        }

        private TelephonyBackupAgent mTelephonyBackupAgent;
        private PowerManager.WakeLock mWakeLock;

        @Override
        protected void onHandleIntent(Intent intent) {
            try {
                mWakeLock.acquire();
                sIsRestoring = true;

                File[] files = getFilesToRestore(this);

                if (files == null || files.length == 0) {
                    return;
                }
                Arrays.sort(files, mFileComparator);

                boolean didRestore = false;

                for (File file : files) {
                    final String fileName = file.getName();
                    if (DEBUG) {
                        Log.d(TAG, "onHandleIntent restoring file " + fileName);
                    }
                    try (FileInputStream fileInputStream = new FileInputStream(file)) {
                        mTelephonyBackupAgent.doRestoreFile(fileName, fileInputStream.getFD());
                        didRestore = true;
                    } catch (Exception e) {
                        // Either IOException or RuntimeException.
                        Log.e(TAG, "onHandleIntent", e);
                    } finally {
                        file.delete();
                    }
                }
                if (didRestore) {
                  // Tell the default sms app to do a full sync now that the messages have been
                  // restored.
                  if (DEBUG) {
                    Log.d(TAG, "onHandleIntent done - notifying default sms app");
                  }
                  ProviderUtil.notifyIfNotDefaultSmsApp(null /*uri*/, null /*calling package*/,
                      this);
                }
           } finally {
                sIsRestoring = false;
                mWakeLock.release();
            }
        }

        @Override
        public void onCreate() {
            super.onCreate();
            mTelephonyBackupAgent = new TelephonyBackupAgent();
            mTelephonyBackupAgent.attach(this);
            mTelephonyBackupAgent.onCreate();

            PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
            mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
        }

        @Override
        public void onDestroy() {
            if (mTelephonyBackupAgent != null) {
                mTelephonyBackupAgent.onDestroy();
                mTelephonyBackupAgent = null;
            }
            super.onDestroy();
        }

        static void startIfFilesExist(Context context) {
            File[] files = getFilesToRestore(context);
            if (files == null || files.length == 0) {
                return;
            }
            context.startService(new Intent(context, DeferredSmsMmsRestoreService.class));
        }

        private static File[] getFilesToRestore(Context context) {
            return context.getFilesDir().listFiles(new FileFilter() {
                @Override
                public boolean accept(File file) {
                    return file.getName().endsWith(SMS_BACKUP_FILE_SUFFIX) ||
                            file.getName().endsWith(MMS_BACKUP_FILE_SUFFIX);
                }
            });
        }
    }

    @Override
    public void onRestoreFinished() {
        super.onRestoreFinished();
        DeferredSmsMmsRestoreService.startIfFilesExist(this);
    }

    private void doRestoreFile(String fileName, FileDescriptor fd) throws IOException {
        if (DEBUG) {
            Log.d(TAG, "Restoring file " + fileName);
        }

        try (JsonReader jsonReader = getJsonReader(fd)) {
            if (fileName.endsWith(SMS_BACKUP_FILE_SUFFIX)) {
                if (DEBUG) {
                    Log.d(TAG, "Restoring SMS");
                }
                putSmsMessagesToProvider(jsonReader);
            } else if (fileName.endsWith(MMS_BACKUP_FILE_SUFFIX)) {
                if (DEBUG) {
                    Log.d(TAG, "Restoring text MMS");
                }
                putMmsMessagesToProvider(jsonReader);
            } else {
                if (DEBUG) {
                    Log.e(TAG, "Unknown file to restore:" + fileName);
                }
            }
        }
    }

    @VisibleForTesting
    void putSmsMessagesToProvider(JsonReader jsonReader) throws IOException {
        jsonReader.beginArray();
        int msgCount = 0;
        final int bulkInsertSize = mMaxMsgPerFile;
        ContentValues[] values = new ContentValues[bulkInsertSize];
        while (jsonReader.hasNext()) {
            ContentValues cv = readSmsValuesFromReader(jsonReader);
            if (doesSmsExist(cv)) {
                continue;
            }
            values[(msgCount++) % bulkInsertSize] = cv;
            if (msgCount % bulkInsertSize == 0) {
                mContentResolver.bulkInsert(Telephony.Sms.CONTENT_URI, values);
            }
        }
        if (msgCount % bulkInsertSize > 0) {
            mContentResolver.bulkInsert(Telephony.Sms.CONTENT_URI,
                    Arrays.copyOf(values, msgCount % bulkInsertSize));
        }
        jsonReader.endArray();
    }

    @VisibleForTesting
    void putMmsMessagesToProvider(JsonReader jsonReader) throws IOException {
        jsonReader.beginArray();
        while (jsonReader.hasNext()) {
            final Mms mms = readMmsFromReader(jsonReader);
            if (DEBUG) {
                Log.d(TAG, "putMmsMessagesToProvider " + mms);
            }
            if (doesMmsExist(mms)) {
                if (DEBUG) {
                    Log.e(TAG, String.format("Mms: %s already exists", mms.toString()));
                }
                continue;
            }
            addMmsMessage(mms);
        }
    }

    @VisibleForTesting
    static final String[] PROJECTION_ID = {BaseColumns._ID};
    private static final int ID_IDX = 0;

    private boolean doesSmsExist(ContentValues smsValues) {
        final String where = String.format(Locale.US, "%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 = mContentResolver.query(Telephony.Sms.CONTENT_URI, PROJECTION_ID, where,
                null, null)) {
            return cursor != null && cursor.getCount() > 0;
        }
    }

    private boolean doesMmsExist(Mms mms) {
        final String where = String.format(Locale.US, "%s = %d",
                Telephony.Sms.DATE, mms.values.getAsLong(Telephony.Mms.DATE));
        try (Cursor cursor = mContentResolver.query(Telephony.Mms.CONTENT_URI, PROJECTION_ID, where,
                null, null)) {
            if (cursor != null && cursor.moveToFirst()) {
                do {
                    final int mmsId = cursor.getInt(ID_IDX);
                    final MmsBody body = getMmsBody(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 void writeSmsToWriter(JsonWriter jsonWriter, Cursor cursor) 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 = mSubId2phone.get(subId);
                    if (selfNumber != null) {
                        jsonWriter.name(SELF_PHONE_KEY).value(selfNumber);
                    }
                    break;
                case Telephony.Sms.THREAD_ID:
                    final long threadId = cursor.getLong(i);
                    handleThreadId(jsonWriter, threadId);
                    break;
                case Telephony.Sms._ID:
                    break;
                default:
                    jsonWriter.name(name).value(value);
                    break;
            }
        }
        jsonWriter.endObject();

    }

    private void handleThreadId(JsonWriter jsonWriter, long threadId) throws IOException {
        final List<String> recipients = getRecipientsByThread(threadId);
        if (recipients == null || recipients.isEmpty()) {
            return;
        }

        writeRecipientsToWriter(jsonWriter.name(RECIPIENTS), recipients);
        if (!mThreadArchived.containsKey(threadId)) {
            boolean isArchived = isThreadArchived(threadId);
            if (isArchived) {
                jsonWriter.name(Telephony.Threads.ARCHIVED).value(true);
            }
            mThreadArchived.put(threadId, isArchived);
        }
    }

    private static String[] THREAD_ARCHIVED_PROJECTION =
            new String[] { Telephony.Threads.ARCHIVED };
    private static int THREAD_ARCHIVED_IDX = 0;

    private boolean isThreadArchived(long threadId) {
        Uri.Builder builder = Telephony.Threads.CONTENT_URI.buildUpon();
        builder.appendPath(String.valueOf(threadId)).appendPath("recipients");
        Uri uri = builder.build();

        try (Cursor cursor = getContentResolver().query(uri, THREAD_ARCHIVED_PROJECTION, null, null,
                null)) {
            if (cursor != null && cursor.moveToFirst()) {
                return cursor.getInt(THREAD_ARCHIVED_IDX) == 1;
            }
        }
        return false;
    }

    private static void writeRecipientsToWriter(JsonWriter jsonWriter, List<String> recipients)
            throws IOException {
        jsonWriter.beginArray();
        if (recipients != null) {
            for (String s : recipients) {
                jsonWriter.value(s);
            }
        }
        jsonWriter.endArray();
    }

    private ContentValues readSmsValuesFromReader(JsonReader jsonReader)
            throws IOException {
        ContentValues values = new ContentValues(6+sDefaultValuesSms.size());
        values.putAll(sDefaultValuesSms);
        long threadId = -1;
        boolean isArchived = false;
        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:
                case Telephony.Sms.ADDRESS:
                case Telephony.Sms.READ:
                    values.put(name, jsonReader.nextString());
                    break;
                case RECIPIENTS:
                    threadId = getOrCreateThreadId(getRecipients(jsonReader));
                    values.put(Telephony.Sms.THREAD_ID, threadId);
                    break;
                case Telephony.Threads.ARCHIVED:
                    isArchived = jsonReader.nextBoolean();
                    break;
                case SELF_PHONE_KEY:
                    final String selfPhone = jsonReader.nextString();
                    if (mPhone2subId.containsKey(selfPhone)) {
                        values.put(Telephony.Sms.SUBSCRIPTION_ID, mPhone2subId.get(selfPhone));
                    }
                    break;
                default:
                    if (DEBUG) {
                        Log.w(TAG, "readSmsValuesFromReader Unknown name:" + name);
                    }
                    jsonReader.skipValue();
                    break;
            }
        }
        jsonReader.endObject();
        archiveThread(threadId, isArchived);
        return values;
    }

    private static Set<String> getRecipients(JsonReader jsonReader) throws IOException {
        Set<String> recipients = new ArraySet<String>();
        jsonReader.beginArray();
        while (jsonReader.hasNext()) {
            recipients.add(jsonReader.nextString());
        }
        jsonReader.endArray();
        return recipients;
    }

    private int writeMmsToWriter(JsonWriter jsonWriter, Cursor cursor) throws IOException {
        final int mmsId = cursor.getInt(ID_IDX);
        final MmsBody body = getMmsBody(mmsId);
        // We backup any message that contains text, but only backup the text part.
        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 (DEBUG) {
                Log.d(TAG, "writeMmsToWriter name: " + name + " value: " + value);
            }
            if (value == null) {
                continue;
            }
            switch (name) {
                case Telephony.Mms.SUBSCRIPTION_ID:
                    final int subId = cursor.getInt(i);
                    final String selfNumber = mSubId2phone.get(subId);
                    if (selfNumber != null) {
                        jsonWriter.name(SELF_PHONE_KEY).value(selfNumber);
                    }
                    break;
                case Telephony.Mms.THREAD_ID:
                    final long threadId = cursor.getLong(i);
                    handleThreadId(jsonWriter, threadId);
                    break;
                case Telephony.Mms._ID:
                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), 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 Mms readMmsFromReader(JsonReader jsonReader) throws IOException {
        Mms mms = new Mms();
        mms.values = new ContentValues(5+sDefaultValuesMms.size());
        mms.values.putAll(sDefaultValuesMms);
        jsonReader.beginObject();
        String bodyText = null;
        long threadId = -1;
        boolean isArchived = false;
        int bodyCharset = CharacterSets.DEFAULT_CHARSET;
        while (jsonReader.hasNext()) {
            String name = jsonReader.nextName();
            if (DEBUG) {
                Log.d(TAG, "readMmsFromReader " + name);
            }
            switch (name) {
                case SELF_PHONE_KEY:
                    final String selfPhone = jsonReader.nextString();
                    if (mPhone2subId.containsKey(selfPhone)) {
                        mms.values.put(Telephony.Mms.SUBSCRIPTION_ID, mPhone2subId.get(selfPhone));
                    }
                    break;
                case MMS_ADDRESSES_KEY:
                    getMmsAddressesFromReader(jsonReader, mms);
                    break;
                case MMS_ATTACHMENTS_KEY:
                    getMmsAttachmentsFromReader(jsonReader, mms);
                    break;
                case MMS_SMIL_KEY:
                    mms.smil = jsonReader.nextString();
                    break;
                case MMS_BODY_KEY:
                    bodyText = jsonReader.nextString();
                    break;
                case MMS_BODY_CHARSET_KEY:
                    bodyCharset = jsonReader.nextInt();
                    break;
                case RECIPIENTS:
                    threadId = getOrCreateThreadId(getRecipients(jsonReader));
                    mms.values.put(Telephony.Sms.THREAD_ID, threadId);
                    break;
                case Telephony.Threads.ARCHIVED:
                    isArchived = jsonReader.nextBoolean();
                    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:
                case Telephony.Mms.TRANSACTION_ID:
                case Telephony.Mms.READ:
                    mms.values.put(name, jsonReader.nextString());
                    break;
                default:
                    if (DEBUG) {
                        Log.d(TAG, "Unknown name:" + name);
                    }
                    jsonReader.skipValue();
                    break;
            }
        }
        jsonReader.endObject();

        if (bodyText != null) {
            mms.body = new MmsBody(bodyText, bodyCharset);
        }
        // Set the text_only flag
        mms.values.put(Telephony.Mms.TEXT_ONLY, (mms.attachments == null
                || mms.attachments.size() == 0) && bodyText != null ? 1 : 0);

        // 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);
        }

        archiveThread(threadId, isArchived);

        return mms;
    }

    private static final String ARCHIVE_THREAD_SELECTION = Telephony.Threads._ID + "=?";

    private void archiveThread(long threadId, boolean isArchived) {
        if (threadId < 0 || !isArchived) {
            return;
        }
        final ContentValues values = new ContentValues(1);
        values.put(Telephony.Threads.ARCHIVED, 1);
        if (mContentResolver.update(
                Telephony.Threads.CONTENT_URI,
                values,
                ARCHIVE_THREAD_SELECTION,
                new String[] { Long.toString(threadId)}) != 1) {
            if (DEBUG) {
                Log.e(TAG, "archiveThread: failed to update database");
            }
        }
    }

    private MmsBody getMmsBody(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 = mContentResolver.query(MMS_PART_CONTENT_URI, MMS_TEXT_PROJECTION,
                Telephony.Mms.Part.CONTENT_TYPE + "=?", new String[]{ContentType.TEXT_PLAIN},
                ORDER_BY_ID)) {
            if (cursor != null && cursor.moveToFirst()) {
                do {
                    String text = cursor.getString(MMS_TEXT_IDX);
                    if (text != null) {
                        body = (body == null ? text : body.concat(text));
                        charSet = cursor.getInt(MMS_TEXT_CHARSET_IDX);
                    }
                } while (cursor.moveToNext());
            }
        }
        return (body == null ? null : new MmsBody(body, charSet));
    }

    private void writeMmsAddresses(JsonWriter jsonWriter, 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 = mContentResolver.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(sDefaultValuesAddr);
            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.d(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 getMmsAttachmentsFromReader(JsonReader jsonReader, Mms mms)
            throws IOException {
        if (DEBUG) {
            Log.d(TAG, "Add getMmsAttachmentsFromReader");
        }
        mms.attachments = new ArrayList<ContentValues>();
        jsonReader.beginArray();
        while (jsonReader.hasNext()) {
            jsonReader.beginObject();
            ContentValues attachmentValues = new ContentValues(sDefaultValuesAttachments);
            while (jsonReader.hasNext()) {
                final String name = jsonReader.nextName();
                switch (name) {
                    case MMS_MIME_TYPE:
                    case MMS_ATTACHMENT_FILENAME:
                        attachmentValues.put(name, jsonReader.nextString());
                        break;
                    default:
                        if (DEBUG) {
                            Log.d(TAG, "getMmsAttachmentsFromReader Unknown name:" + name);
                        }
                        jsonReader.skipValue();
                        break;
                }
            }
            jsonReader.endObject();
            if (attachmentValues.containsKey(MMS_ATTACHMENT_FILENAME)) {
                mms.attachments.add(attachmentValues);
            } else {
                if (DEBUG) {
                    Log.d(TAG, "Attachment json with no filenames");
                }
            }
        }
        jsonReader.endArray();
    }

    private void addMmsMessage(Mms mms) {
        if (DEBUG) {
            Log.d(TAG, "Add mms:\n" + mms);
        }
        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(Locale.US, "text.%06d.txt", 0);
        { // Insert SMIL part.
            final String smilBody = String.format(sSmilTextPart, srcName);
            final String smil = TextUtils.isEmpty(mms.smil) ?
                    String.format(sSmilTextOnly, smilBody) : mms.smil;
            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 (mContentResolver.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 == null ? CharacterSets.DEFAULT_CHARSET : mms.body.charSet);
            values.put(Telephony.Mms.Part.TEXT, mms.body == null ? "" : mms.body.text);

            if (mContentResolver.insert(partUri, values) == null) {
                if (DEBUG) {
                    Log.e(TAG, "Could not insert body part");
                }
                return;
            }
        }

        if (mms.attachments != null) {
            // Insert the attachment parts.
            for (ContentValues mmsAttachment : mms.attachments) {
                final ContentValues values = new ContentValues(6);
                values.put(Telephony.Mms.Part.MSG_ID, dummyId);
                values.put(Telephony.Mms.Part.SEQ, 0);
                values.put(Telephony.Mms.Part.CONTENT_TYPE,
                        mmsAttachment.getAsString(MMS_MIME_TYPE));
                String filename = mmsAttachment.getAsString(MMS_ATTACHMENT_FILENAME);
                values.put(Telephony.Mms.Part.CONTENT_ID, "<"+filename+">");
                values.put(Telephony.Mms.Part.CONTENT_LOCATION, filename);
                values.put(Telephony.Mms.Part._DATA,
                        getDataDir() + ATTACHMENT_DATA_PATH + filename);
                Uri newPartUri = mContentResolver.insert(partUri, values);
                if (newPartUri == null) {
                    if (DEBUG) {
                        Log.e(TAG, "Could not insert attachment part");
                    }
                    return;
                }
            }
        }

        // Insert mms.
        final Uri mmsUri = mContentResolver.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);
            mContentResolver.update(partUri, values, null, null);
        }

        { // Insert addresses 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);
                mContentResolver.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 List<ContentValues> attachments;
        public String smil;
        public MmsBody body;
        @Override
        public String toString() {
            return "Values:" + values.toString() + "\nRecipients:" + addresses.toString()
                    + "\nAttachments:" + (attachments == null ? "none" : attachments.toString())
                    + "\nBody:" + body;
        }
    }

    private JsonWriter getJsonWriter(final String fileName) throws IOException {
        return new JsonWriter(new BufferedWriter(new OutputStreamWriter(new DeflaterOutputStream(
                openFileOutput(fileName, MODE_PRIVATE)), CHARSET_UTF8), WRITER_BUFFER_SIZE));
    }

    private static 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);
        }
    }

    private long getOrCreateThreadId(Set<String> recipients) {
        if (recipients == null) {
            recipients = new ArraySet<String>();
        }

        if (recipients.isEmpty()) {
            recipients.add(UNKNOWN_SENDER);
        }

        if (mCacheGetOrCreateThreadId == null) {
            mCacheGetOrCreateThreadId = new HashMap<>();
        }

        if (!mCacheGetOrCreateThreadId.containsKey(recipients)) {
            long threadId = mUnknownSenderThreadId;
            try {
                threadId = Telephony.Threads.getOrCreateThreadId(this, recipients);
            } catch (RuntimeException e) {
                if (DEBUG) {
                    Log.e(TAG, e.toString());
                }
            }
            mCacheGetOrCreateThreadId.put(recipients, threadId);
            return threadId;
        }

        return mCacheGetOrCreateThreadId.get(recipients);
    }

    @VisibleForTesting
    static final Uri THREAD_ID_CONTENT_URI = Uri.parse("content://mms-sms/threadID");

    // Mostly copied from packages/apps/Messaging/src/com/android/messaging/sms/MmsUtils.java.
    private List<String> getRecipientsByThread(final long threadId) {
        if (mCacheRecipientsByThread == null) {
            mCacheRecipientsByThread = new HashMap<>();
        }

        if (!mCacheRecipientsByThread.containsKey(threadId)) {
            final String spaceSepIds = getRawRecipientIdsForThread(threadId);
            if (!TextUtils.isEmpty(spaceSepIds)) {
                mCacheRecipientsByThread.put(threadId, getAddresses(spaceSepIds));
            } else {
                mCacheRecipientsByThread.put(threadId, new ArrayList<String>());
            }
        }

        return mCacheRecipientsByThread.get(threadId);
    }

    @VisibleForTesting
    static final Uri ALL_THREADS_URI =
            Telephony.Threads.CONTENT_URI.buildUpon().
                    appendQueryParameter("simple", "true").build();
    private static final int RECIPIENT_IDS  = 1;

    // Copied from packages/apps/Messaging/src/com/android/messaging/sms/MmsUtils.java.
    // NOTE: There are phones on which you can't get the recipients from the thread id for SMS
    // until you have a message in the conversation!
    private String getRawRecipientIdsForThread(final long threadId) {
        if (threadId <= 0) {
            return null;
        }
        final Cursor thread = mContentResolver.query(
                ALL_THREADS_URI,
                SMS_RECIPIENTS_PROJECTION, "_id=?", new String[]{String.valueOf(threadId)}, null);
        if (thread != null) {
            try {
                if (thread.moveToFirst()) {
                    // recipientIds will be a space-separated list of ids into the
                    // canonical addresses table.
                    return thread.getString(RECIPIENT_IDS);
                }
            } finally {
                thread.close();
            }
        }
        return null;
    }

    @VisibleForTesting
    static final Uri SINGLE_CANONICAL_ADDRESS_URI =
            Uri.parse("content://mms-sms/canonical-address");

    // Copied from packages/apps/Messaging/src/com/android/messaging/sms/MmsUtils.java.
    private List<String> getAddresses(final String spaceSepIds) {
        final List<String> numbers = new ArrayList<String>();
        final String[] ids = spaceSepIds.split(" ");
        for (final String id : ids) {
            long longId;

            try {
                longId = Long.parseLong(id);
                if (longId < 0) {
                    if (DEBUG) {
                        Log.e(TAG, "getAddresses: invalid id " + longId);
                    }
                    continue;
                }
            } catch (final NumberFormatException ex) {
                if (DEBUG) {
                    Log.e(TAG, "getAddresses: invalid id. " + ex, ex);
                }
                // skip this id
                continue;
            }

            // TODO: build a single query where we get all the addresses at once.
            Cursor c = null;
            try {
                c = mContentResolver.query(
                        ContentUris.withAppendedId(SINGLE_CANONICAL_ADDRESS_URI, longId),
                        null, null, null, null);
            } catch (final Exception e) {
                if (DEBUG) {
                    Log.e(TAG, "getAddresses: query failed for id " + longId, e);
                }
            }
            if (c != null) {
                try {
                    if (c.moveToFirst()) {
                        final String number = c.getString(0);
                        if (!TextUtils.isEmpty(number)) {
                            numbers.add(number);
                        } else {
                            if (DEBUG) {
                                Log.d(TAG, "Canonical MMS/SMS address is empty for id: " + longId);
                            }
                        }
                    }
                } finally {
                    c.close();
                }
            }
        }
        if (numbers.isEmpty()) {
            if (DEBUG) {
                Log.d(TAG, "No MMS addresses found from ids string [" + spaceSepIds + "]");
            }
        }
        return numbers;
    }

    @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.
    }

    public static boolean getIsRestoring() {
        return sIsRestoring;
    }
}
