/*
 * 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.NonNull;
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.preference.PreferenceManager;
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.android.internal.telephony.PhoneFactory;

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;

    // SharedPreferences keys
    private static final String NUM_SMS_RESTORED = "num_sms_restored";
    private static final String NUM_SMS_EXCEPTIONS = "num_sms_exceptions";
    private static final String NUM_SMS_FILES_STORED = "num_sms_files_restored";
    private static final String NUM_SMS_FILES_WITH_EXCEPTIONS = "num_sms_files_with_exceptions";
    private static final String NUM_MMS_RESTORED = "num_mms_restored";
    private static final String NUM_MMS_EXCEPTIONS = "num_mms_exceptions";
    private static final String NUM_MMS_FILES_STORED = "num_mms_files_restored";
    private static final String NUM_MMS_FILES_WITH_EXCEPTIONS = "num_mms_files_with_exceptions";

    // 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();
        Log.d(TAG, "onCreate");
        final SubscriptionManager subscriptionManager = SubscriptionManager.from(this);
        if (subscriptionManager != null) {
            final List<SubscriptionInfo> subInfo =
                    subscriptionManager.getCompleteActiveSubscriptionInfoList();
            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;
        }

        // Backups consist of multiple chunks; each chunk consists of a set of messages
        // of the same type in a chronological order.
        BackupChunkInformation chunk;
        try (JsonWriter jsonWriter = getJsonWriter(fileName)) {
            if (fileName.endsWith(SMS_BACKUP_FILE_SUFFIX)) {
                chunk = putSmsMessagesToJson(cursor, jsonWriter);
            } else {
                chunk = putMmsMessagesToJson(cursor, jsonWriter);
            }
        }
        backupFile(chunk, fileName, data);
    }

    @VisibleForTesting
    @NonNull
    BackupChunkInformation putMmsMessagesToJson(Cursor cursor,
                             JsonWriter jsonWriter) throws IOException {
        BackupChunkInformation results = new BackupChunkInformation();
        jsonWriter.beginArray();
        for (; results.count < mMaxMsgPerFile && !cursor.isAfterLast();
                cursor.moveToNext()) {
            writeMmsToWriter(jsonWriter, cursor, results);
        }
        jsonWriter.endArray();
        return results;
    }

    @VisibleForTesting
    @NonNull
    BackupChunkInformation putSmsMessagesToJson(Cursor cursor, JsonWriter jsonWriter)
      throws IOException {
        BackupChunkInformation results = new BackupChunkInformation();
        jsonWriter.beginArray();
        for (; results.count < mMaxMsgPerFile && !cursor.isAfterLast();
                ++results.count, cursor.moveToNext()) {
            writeSmsToWriter(jsonWriter, cursor, results);
        }
        jsonWriter.endArray();
        return results;
    }

    private void backupFile(BackupChunkInformation chunkInformation, String fileName,
        FullBackupDataOutput data)
            throws IOException {
        final File file = new File(getFilesDir().getPath() + "/" + fileName);
        file.setLastModified(chunkInformation.timestamp);
        try {
            if (chunkInformation.count > 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 static boolean sSharedPrefsAddedToLocalLogs = false;

        public static void addAllSharedPrefToLocalLog(Context context) {
            if (sSharedPrefsAddedToLocalLogs) return;
            localLog("addAllSharedPrefToLocalLog");
            SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
            Map<String, ?> allPref = sp.getAll();
            if (allPref.keySet() == null || allPref.keySet().size() == 0) return;
            for (String key : allPref.keySet()) {
                try {
                    localLog(key + ":" + allPref.get(key).toString());
                } catch (Exception e) {
                    localLog("Skipping over key " + key + " due to exception " + e);
                }
            }
            sSharedPrefsAddedToLocalLogs = true;
        }

        public static void localLog(String logMsg) {
            Log.d(TAG, logMsg);
            PhoneFactory.localLog(TAG, logMsg);
        }

        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);
            Log.d(TAG, "DeferredSmsMmsRestoreService");
            setIntentRedelivery(true);
        }

        private TelephonyBackupAgent mTelephonyBackupAgent;
        private PowerManager.WakeLock mWakeLock;

        @Override
        protected void onHandleIntent(Intent intent) {
            Log.d(TAG, "onHandleIntent");
            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();
                    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);
                        localLog("onHandleIntent: Exception " + e);
                    } finally {
                        file.delete();
                    }
                }
                if (didRestore) {
                  // Tell the default sms app to do a full sync now that the messages have been
                  // restored.
                  localLog("onHandleIntent: done - notifying default sms app");
                  ProviderUtil.notifyIfNotDefaultSmsApp(null /*uri*/, null /*calling package*/,
                      this);
                }
           } finally {
                addAllSharedPrefToLocalLog(this);
                sIsRestoring = false;
                mWakeLock.release();
            }
        }

        @Override
        public void onCreate() {
            super.onCreate();
            Log.d(TAG, "onCreate");
            try {
                PhoneFactory.addLocalLog(TAG, 32);
            } catch (IllegalArgumentException e) {
                // ignore
            }
            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) {
            try {
                PhoneFactory.addLocalLog(TAG, 32);
            } catch (IllegalArgumentException e) {
                // ignore
            }
            File[] files = getFilesToRestore(context);
            if (files == null || files.length == 0) {
                Log.d(TAG, "startIfFilesExist: no files to restore");
                addAllSharedPrefToLocalLog(context);
                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 {
        Log.d(TAG, "Restoring file " + fileName);

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

    @VisibleForTesting
    void putSmsMessagesToProvider(JsonReader jsonReader) throws IOException {
        jsonReader.beginArray();
        int msgCount = 0;
        int numExceptions = 0;
        final int bulkInsertSize = mMaxMsgPerFile;
        ContentValues[] values = new ContentValues[bulkInsertSize];
        while (jsonReader.hasNext()) {
            ContentValues cv = readSmsValuesFromReader(jsonReader);
            try {
                if (mSmsProviderQuery.doesSmsExist(cv)) {
                    continue;
                }
                values[(msgCount++) % bulkInsertSize] = cv;
                if (msgCount % bulkInsertSize == 0) {
                    mContentResolver.bulkInsert(Telephony.Sms.CONTENT_URI, values);
                }
            } catch (RuntimeException e) {
                Log.e(TAG, "putSmsMessagesToProvider", e);
                DeferredSmsMmsRestoreService.localLog("putSmsMessagesToProvider: Exception " + e);
                numExceptions++;
            }
        }
        if (msgCount % bulkInsertSize > 0) {
            mContentResolver.bulkInsert(Telephony.Sms.CONTENT_URI,
                    Arrays.copyOf(values, msgCount % bulkInsertSize));
        }
        jsonReader.endArray();
        incremenentSharedPref(true, msgCount, numExceptions);
    }

    void incremenentSharedPref(boolean sms, int msgCount, int numExceptions) {
        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
        SharedPreferences.Editor editor = sp.edit();
        if (sms) {
            editor.putInt(NUM_SMS_RESTORED, sp.getInt(NUM_SMS_RESTORED, 0) + msgCount);
            editor.putInt(NUM_SMS_EXCEPTIONS, sp.getInt(NUM_SMS_EXCEPTIONS, 0) + numExceptions);
            editor.putInt(NUM_SMS_FILES_STORED, sp.getInt(NUM_SMS_FILES_STORED, 0) + 1);
            if (numExceptions > 0) {
                editor.putInt(NUM_SMS_FILES_WITH_EXCEPTIONS,
                        sp.getInt(NUM_SMS_FILES_WITH_EXCEPTIONS, 0) + 1);
            }
        } else {
            editor.putInt(NUM_MMS_RESTORED, sp.getInt(NUM_MMS_RESTORED, 0) + msgCount);
            editor.putInt(NUM_MMS_EXCEPTIONS, sp.getInt(NUM_MMS_EXCEPTIONS, 0) + numExceptions);
            editor.putInt(NUM_MMS_FILES_STORED, sp.getInt(NUM_MMS_FILES_STORED, 0) + 1);
            if (numExceptions > 0) {
                editor.putInt(NUM_MMS_FILES_WITH_EXCEPTIONS,
                        sp.getInt(NUM_MMS_FILES_WITH_EXCEPTIONS, 0) + 1);
            }
        }
        editor.commit();
    }

    @VisibleForTesting
    void putMmsMessagesToProvider(JsonReader jsonReader) throws IOException {
        jsonReader.beginArray();
        int total = 0;
        int numExceptions = 0;
        while (jsonReader.hasNext()) {
            final Mms mms = readMmsFromReader(jsonReader);
            if (DEBUG) {
                Log.d(TAG, "putMmsMessagesToProvider " + mms);
            }
            try {
                if (doesMmsExist(mms)) {
                    if (DEBUG) {
                        Log.e(TAG, String.format("Mms: %s already exists", mms.toString()));
                    } else {
                        Log.w(TAG, "Mms: Found duplicate MMS");
                    }
                    continue;
                }
                total++;
                addMmsMessage(mms);
            } catch (Exception e) {
                Log.e(TAG, "putMmsMessagesToProvider", e);
                numExceptions++;
                DeferredSmsMmsRestoreService.localLog("putMmsMessagesToProvider: Exception " + e);
            }
        }
        Log.d(TAG, "putMmsMessagesToProvider handled " + total + " new messages.");
        incremenentSharedPref(false, total, numExceptions);
    }

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

    /**
     * Interface to allow mocking method for testing.
     */
    public interface SmsProviderQuery {
        boolean doesSmsExist(ContentValues smsValues);
    }

    private SmsProviderQuery mSmsProviderQuery = new SmsProviderQuery() {
        @Override
        public boolean doesSmsExist(ContentValues smsValues) {
            // The SMS body might contain '\0' characters (U+0000) such as in the case of
            // http://b/160801497 . SQLite does not allow '\0' in String literals, but as of SQLite
            // version 3.32.2 2020-06-04, it does allow them as selectionArgs; therefore, we're
            // using the latter approach here.
            final String selection = String.format(Locale.US, "%s=%d AND %s=?",
                    Telephony.Sms.DATE, smsValues.getAsLong(Telephony.Sms.DATE),
                    Telephony.Sms.BODY);
            String[] selectionArgs = new String[] { smsValues.getAsString(Telephony.Sms.BODY)};
            try (Cursor cursor = mContentResolver.query(Telephony.Sms.CONTENT_URI, PROJECTION_ID,
                    selection, selectionArgs, null)) {
                return cursor != null && cursor.getCount() > 0;
            }
        }
    };

    /**
     * Sets a temporary {@code SmsProviderQuery} for testing; note that this method
     * is not thread safe.
     *
     * @return the previous {@code SmsProviderQuery}
     */
    @VisibleForTesting
    public SmsProviderQuery getAndSetSmsProviderQuery(SmsProviderQuery smsProviderQuery) {
        SmsProviderQuery result = mSmsProviderQuery;
        mSmsProviderQuery = smsProviderQuery;
        return result;
    }

    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;
        }
        // country iso might not be always available in some corner cases (e.g. mis-configured SIM,
        // carrier config, or test SIM has incorrect IMSI, etc...). In that case, just return the
        // unformatted number.
        if (!TextUtils.isEmpty(subscriptionInfo.getCountryIso())) {
            return PhoneNumberUtils.formatNumberToE164(subscriptionInfo.getNumber(),
                    subscriptionInfo.getCountryIso().toUpperCase(Locale.US));
        } else {
            return subscriptionInfo.getNumber();
        }
    }

    private void writeSmsToWriter(JsonWriter jsonWriter, Cursor cursor,
            BackupChunkInformation chunk) 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;
                case Telephony.Sms.DATE:
                case Telephony.Sms.DATE_SENT:
                    chunk.timestamp = findNewestValue(chunk.timestamp, value);
                    jsonWriter.name(name).value(value);
                    break;
                default:
                    jsonWriter.name(name).value(value);
                    break;
            }
        }
        jsonWriter.endObject();
    }

    private long findNewestValue(long current, String latest) {
        if(latest == null) {
            return current;
        }

        try {
            long latestLong = Long.valueOf(latest);
            return Math.max(current, latestLong);
        } catch (NumberFormatException e) {
            Log.d(TAG, "Unable to parse value "+latest);
            return current;
        }

    }

    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);
                    } else {
                        Log.w(TAG, "readSmsValuesFromReader encountered unknown 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 void writeMmsToWriter(JsonWriter jsonWriter, Cursor cursor,
            BackupChunkInformation chunk) 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;
        }

        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.DATE:
                case Telephony.Mms.DATE_SENT:
                    chunk.timestamp = findNewestValue(chunk.timestamp, value);
                    jsonWriter.name(name).value(value);
                    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();
        chunk.count++;
    }

    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:
                    Log.d(TAG, "Unknown JSON element 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) {
            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:
                        Log.d(TAG, "Unknown JSON Element 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:
                        Log.d(TAG, "getMmsAttachmentsFromReader Unknown name:" + name);
                        jsonReader.skipValue();
                        break;
                }
            }
            jsonReader.endObject();
            if (attachmentValues.containsKey(MMS_ATTACHMENT_FILENAME)) {
                mms.attachments.add(attachmentValues);
            } else {
                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 placeholderId = System.currentTimeMillis(); // Placeholder ID of the msg.
        final Uri partUri = Telephony.Mms.CONTENT_URI.buildUpon()
                .appendPath(String.valueOf(placeholderId)).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, placeholderId);
            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) {
                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, placeholderId);
            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) {
                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, placeholderId);
                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) {
                    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) {
            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) {
                Log.e(TAG, "Problem obtaining thread.", e);
            }
            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) {
                    Log.e(TAG, "getAddresses: invalid id " + longId);
                    continue;
                }
            } catch (final NumberFormatException ex) {
                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) {
                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 {
                            Log.d(TAG, "Canonical MMS/SMS address is empty for id: " + longId);
                        }
                    }
                } finally {
                    c.close();
                }
            }
        }
        if (numbers.isEmpty()) {
            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;
    }

    private static class BackupChunkInformation {
        // Timestamp of the recent message in the file
        private long timestamp;

        // The number of messages in the backup file
        private int count = 0;
    }
}
