merge in nyc-release history after reset to nyc-dev
diff --git a/src/com/android/providers/telephony/TelephonyBackupAgent.java b/src/com/android/providers/telephony/TelephonyBackupAgent.java
index 748a703..61796a2 100644
--- a/src/com/android/providers/telephony/TelephonyBackupAgent.java
+++ b/src/com/android/providers/telephony/TelephonyBackupAgent.java
@@ -194,7 +194,8 @@
             Telephony.Mms.MMS_VERSION,
             Telephony.Mms.MESSAGE_BOX,
             Telephony.Mms.CONTENT_LOCATION,
-            Telephony.Mms.THREAD_ID
+            Telephony.Mms.THREAD_ID,
+            Telephony.Mms.TRANSACTION_ID
     };
 
     // Columns from addr database for backup/restore. This database is used for fetching addresses
@@ -267,6 +268,7 @@
 
     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.
@@ -360,6 +362,8 @@
                 backupAll(data, mmsCursor, String.format(MMS_BACKUP_FILE_FORMAT, fileNum++));
             }
         }
+
+        mThreadArchived = new HashMap<>();
     }
 
     @VisibleForTesting
@@ -654,8 +658,7 @@
                     break;
                 case Telephony.Sms.THREAD_ID:
                     final long threadId = cursor.getLong(i);
-                    writeRecipientsToWriter(jsonWriter.name(RECIPIENTS),
-                            getRecipientsByThread(threadId));
+                    handleThreadId(jsonWriter, threadId);
                     break;
                 case Telephony.Sms._ID:
                     break;
@@ -668,6 +671,36 @@
 
     }
 
+    private void handleThreadId(JsonWriter jsonWriter, long threadId) throws IOException {
+        writeRecipientsToWriter(jsonWriter.name(RECIPIENTS),
+                getRecipientsByThread(threadId));
+        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.moveToFirst()) {
+                return cursor.getInt(THREAD_ARCHIVED_IDX) == 1;
+            }
+        }
+        return false;
+    }
+
     private static void writeRecipientsToWriter(JsonWriter jsonWriter, List<String> recipients)
             throws IOException {
         jsonWriter.beginArray();
@@ -683,6 +716,8 @@
             throws IOException {
         ContentValues values = new ContentValues(8+sDefaultValuesSms.size());
         values.putAll(sDefaultValuesSms);
+        long threadId = -1;
+        boolean isArchived = false;
         jsonReader.beginObject();
         while (jsonReader.hasNext()) {
             String name = jsonReader.nextName();
@@ -697,8 +732,11 @@
                     values.put(name, jsonReader.nextString());
                     break;
                 case RECIPIENTS:
-                    values.put(Telephony.Sms.THREAD_ID,
-                            getOrCreateThreadId(getRecipients(jsonReader)));
+                    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();
@@ -715,6 +753,7 @@
             }
         }
         jsonReader.endObject();
+        archiveThread(threadId, isArchived);
         return values;
     }
 
@@ -753,8 +792,7 @@
                     break;
                 case Telephony.Mms.THREAD_ID:
                     final long threadId = cursor.getLong(i);
-                    writeRecipientsToWriter(jsonWriter.name(RECIPIENTS),
-                            getRecipientsByThread(threadId));
+                    handleThreadId(jsonWriter, threadId);
                     break;
                 case Telephony.Mms._ID:
                 case Telephony.Mms.SUBJECT_CHARSET:
@@ -787,6 +825,8 @@
         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();
@@ -807,8 +847,11 @@
                     bodyCharset = jsonReader.nextInt();
                     break;
                 case RECIPIENTS:
-                    mms.values.put(Telephony.Sms.THREAD_ID,
-                            getOrCreateThreadId(getRecipients(jsonReader)));
+                    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:
@@ -818,6 +861,7 @@
                 case Telephony.Mms.MMS_VERSION:
                 case Telephony.Mms.MESSAGE_BOX:
                 case Telephony.Mms.CONTENT_LOCATION:
+                case Telephony.Mms.TRANSACTION_ID:
                     mms.values.put(name, jsonReader.nextString());
                     break;
                 default:
@@ -840,9 +884,30 @@
             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();
diff --git a/tests/src/com/android/providers/telephony/TelephonyBackupAgentTest.java b/tests/src/com/android/providers/telephony/TelephonyBackupAgentTest.java
index 8bf45c9..5869a84 100644
--- a/tests/src/com/android/providers/telephony/TelephonyBackupAgentTest.java
+++ b/tests/src/com/android/providers/telephony/TelephonyBackupAgentTest.java
@@ -48,6 +48,7 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -125,8 +126,9 @@
         mSmsJson[0] = "{\"self_phone\":\"+111111111111111\",\"address\":" +
                 "\"+1232132214124\",\"body\":\"sms 1\",\"subject\":\"sms subject\",\"date\":" +
                 "\"9087978987\",\"date_sent\":\"999999999\",\"status\":\"3\",\"type\":\"44\"," +
-                "\"recipients\":[\"+123 (213) 2214124\"]}";
-        mThreadProvider.getOrCreateThreadId(new String[]{"+123 (213) 2214124"});
+                "\"recipients\":[\"+123 (213) 2214124\"],\"archived\":true}";
+        mThreadProvider.setArchived(
+                mThreadProvider.getOrCreateThreadId(new String[]{"+123 (213) 2214124"}));
 
         mSmsRows[1] = createSmsRow(2, 2, "+1232132214124", "sms 2", null, 9087978987l, 999999999,
                 0, 4, 1);
@@ -198,7 +200,7 @@
         mMmsJson[2] = "{\"self_phone\":\"+333333333333333\",\"sub\":\"Subject 10\"," +
                 "\"date\":\"111133\",\"date_sent\":\"1111132\",\"m_type\":\"5\",\"v\":\"19\"," +
                 "\"msg_box\":\"333\"," +
-                "\"recipients\":[\"+123 (213) 2214124\"]," +
+                "\"recipients\":[\"+123 (213) 2214124\"],\"archived\":true," +
                 "\"mms_addresses\":" +
                 "[{\"type\":10,\"address\":\"333 333333333333\",\"charset\":100}," +
                 "{\"type\":11,\"address\":\"+1232132214124\",\"charset\":101}]," +
@@ -488,6 +490,7 @@
         mMockContentResolver.addProvider("sms", smsProvider);
         mTelephonyBackupAgent.putSmsMessagesToProvider(jsonReader);
         assertEquals(mSmsRows.length, smsProvider.getRowsAdded());
+        assertEquals(mThreadProvider.mIsThreadArchived, mThreadProvider.mUpdateThreadsArchived);
     }
 
     /**
@@ -512,6 +515,7 @@
         mMockContentResolver.addProvider("mms", mmsProvider);
         mTelephonyBackupAgent.putMmsMessagesToProvider(jsonReader);
         assertEquals(18, mmsProvider.getRowsAdded());
+        assertEquals(mThreadProvider.mIsThreadArchived, mThreadProvider.mUpdateThreadsArchived);
     }
 
     /**
@@ -703,6 +707,9 @@
     private static class ThreadProvider extends MockContentProvider {
         ArrayList<Set<Integer> > id2Thread = new ArrayList<>();
         ArrayList<String> id2Recipient = new ArrayList<>();
+        Set<Integer> mIsThreadArchived = new HashSet<>();
+        Set<Integer> mUpdateThreadsArchived = new HashSet<>();
+
 
         public int getOrCreateThreadId(final String[] recipients) {
             Set<Integer> ids = new ArraySet<>();
@@ -718,6 +725,10 @@
             return id2Thread.indexOf(ids)+1;
         }
 
+        public void setArchived(int threadId) {
+            mIsThreadArchived.add(threadId);
+        }
+
         private String getSpaceSepIds(int threadId) {
             String spaceSepIds = null;
             for (Integer id : id2Thread.get(threadId-1)) {
@@ -741,6 +752,16 @@
                 row.put(Telephony.Threads.RECIPIENT_IDS, spaceSepIds);
                 table.add(row);
                 return new FakeCursor(table, projection);
+            } else if (uri.toString().startsWith(Telephony.Threads.CONTENT_URI.toString())) {
+                assertEquals(1, projection.length);
+                assertEquals(Telephony.Threads.ARCHIVED, projection[0]);
+                List<String> segments = uri.getPathSegments();
+                final int threadId = Integer.parseInt(segments.get(segments.size() - 2));
+                List<ContentValues> table = new ArrayList<>();
+                ContentValues row = new ContentValues();
+                row.put(Telephony.Threads.ARCHIVED, mIsThreadArchived.contains(threadId) ? 1 : 0);
+                table.add(row);
+                return new FakeCursor(table, projection);
             } else if (uri.toString().startsWith(
                     TelephonyBackupAgent.SINGLE_CANONICAL_ADDRESS_URI.toString())) {
                 final int recipientId = (int)ContentUris.parseId(uri);
@@ -765,9 +786,20 @@
                 row.put(BaseColumns._ID, String.valueOf(threadId));
                 table.add(row);
                 return new FakeCursor(table, projection);
-            };
+            } else {
+                fail("Unknown URI");
+            }
             return null;
         }
+
+        @Override
+        public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
+            assertEquals(uri, Telephony.Threads.CONTENT_URI);
+            assertEquals(values.getAsInteger(Telephony.Threads.ARCHIVED).intValue(), 1);
+            final int threadId = Integer.parseInt(selectionArgs[0]);
+            mUpdateThreadsArchived.add(threadId);
+            return 1;
+        }
     }
 
     /**