18b39acf181c547e87161873112d6c52a581fc778Roman Sorokin/*
28b39acf181c547e87161873112d6c52a581fc778Roman Sorokin * Copyright (C) 2016 The Android Open Source Project
38b39acf181c547e87161873112d6c52a581fc778Roman Sorokin *
48b39acf181c547e87161873112d6c52a581fc778Roman Sorokin * Licensed under the Apache License, Version 2.0 (the "License");
58b39acf181c547e87161873112d6c52a581fc778Roman Sorokin * you may not use this file except in compliance with the License.
68b39acf181c547e87161873112d6c52a581fc778Roman Sorokin * You may obtain a copy of the License at
78b39acf181c547e87161873112d6c52a581fc778Roman Sorokin *
88b39acf181c547e87161873112d6c52a581fc778Roman Sorokin *      http://www.apache.org/licenses/LICENSE-2.0
98b39acf181c547e87161873112d6c52a581fc778Roman Sorokin *
108b39acf181c547e87161873112d6c52a581fc778Roman Sorokin * Unless required by applicable law or agreed to in writing, software
118b39acf181c547e87161873112d6c52a581fc778Roman Sorokin * distributed under the License is distributed on an "AS IS" BASIS,
128b39acf181c547e87161873112d6c52a581fc778Roman Sorokin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138b39acf181c547e87161873112d6c52a581fc778Roman Sorokin * See the License for the specific language governing permissions and
148b39acf181c547e87161873112d6c52a581fc778Roman Sorokin * limitations under the License
158b39acf181c547e87161873112d6c52a581fc778Roman Sorokin */
168b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
178b39acf181c547e87161873112d6c52a581fc778Roman Sorokinpackage com.android.providers.telephony;
188b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
198b39acf181c547e87161873112d6c52a581fc778Roman Sorokinimport android.annotation.TargetApi;
2021736c3871d5c4cd3a6322d65d635057d0a61937Roman Sorokinimport android.app.backup.FullBackupDataOutput;
219037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokinimport android.content.ContentProvider;
229037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokinimport android.content.ContentResolver;
231d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokinimport android.content.ContentUris;
248b39acf181c547e87161873112d6c52a581fc778Roman Sorokinimport android.content.ContentValues;
259037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokinimport android.content.ContextWrapper;
268b39acf181c547e87161873112d6c52a581fc778Roman Sorokinimport android.database.Cursor;
278b39acf181c547e87161873112d6c52a581fc778Roman Sorokinimport android.net.Uri;
288b39acf181c547e87161873112d6c52a581fc778Roman Sorokinimport android.os.Build;
298b39acf181c547e87161873112d6c52a581fc778Roman Sorokinimport android.provider.BaseColumns;
308b39acf181c547e87161873112d6c52a581fc778Roman Sorokinimport android.provider.Telephony;
318b39acf181c547e87161873112d6c52a581fc778Roman Sorokinimport android.test.AndroidTestCase;
328b39acf181c547e87161873112d6c52a581fc778Roman Sorokinimport android.test.mock.MockContentProvider;
339037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokinimport android.test.mock.MockContentResolver;
348b39acf181c547e87161873112d6c52a581fc778Roman Sorokinimport android.test.mock.MockCursor;
358b39acf181c547e87161873112d6c52a581fc778Roman Sorokinimport android.util.ArrayMap;
361d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokinimport android.util.ArraySet;
378b39acf181c547e87161873112d6c52a581fc778Roman Sorokinimport android.util.JsonReader;
388b39acf181c547e87161873112d6c52a581fc778Roman Sorokinimport android.util.JsonWriter;
398b39acf181c547e87161873112d6c52a581fc778Roman Sorokinimport android.util.SparseArray;
408b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
419037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokinimport org.json.JSONArray;
429037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokinimport org.json.JSONException;
439037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokinimport org.json.JSONObject;
449037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokin
458b39acf181c547e87161873112d6c52a581fc778Roman Sorokinimport java.io.StringReader;
468b39acf181c547e87161873112d6c52a581fc778Roman Sorokinimport java.io.StringWriter;
478b39acf181c547e87161873112d6c52a581fc778Roman Sorokinimport java.util.ArrayList;
488b39acf181c547e87161873112d6c52a581fc778Roman Sorokinimport java.util.Arrays;
498b39acf181c547e87161873112d6c52a581fc778Roman Sorokinimport java.util.HashMap;
503aa281731a6f25cd36b88bca809b13d3f581d05fRoman Sorokinimport java.util.HashSet;
518b39acf181c547e87161873112d6c52a581fc778Roman Sorokinimport java.util.List;
528b39acf181c547e87161873112d6c52a581fc778Roman Sorokinimport java.util.Map;
531d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokinimport java.util.Set;
549037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokinimport java.util.UUID;
558b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
568b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
578b39acf181c547e87161873112d6c52a581fc778Roman Sorokin/**
588b39acf181c547e87161873112d6c52a581fc778Roman Sorokin * Tests for testing backup/restore of SMS and text MMS messages.
598b39acf181c547e87161873112d6c52a581fc778Roman Sorokin * For backup it creates fake provider and checks resulting json array.
608b39acf181c547e87161873112d6c52a581fc778Roman Sorokin * For restore provides json array and checks inserts of the messages into provider.
618b39acf181c547e87161873112d6c52a581fc778Roman Sorokin */
628b39acf181c547e87161873112d6c52a581fc778Roman Sorokin@TargetApi(Build.VERSION_CODES.M)
638b39acf181c547e87161873112d6c52a581fc778Roman Sorokinpublic class TelephonyBackupAgentTest extends AndroidTestCase {
641d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin    /* Map subscriptionId -> phone number */
658b39acf181c547e87161873112d6c52a581fc778Roman Sorokin    private SparseArray<String> mSubId2Phone;
661d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin    /* Map phone number -> subscriptionId */
678b39acf181c547e87161873112d6c52a581fc778Roman Sorokin    private ArrayMap<String, Integer> mPhone2SubId;
681d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin    /* Table being used for sms cursor */
698b39acf181c547e87161873112d6c52a581fc778Roman Sorokin    private final List<ContentValues> mSmsTable = new ArrayList<>();
701d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin    /* Table begin used for mms cursor */
718b39acf181c547e87161873112d6c52a581fc778Roman Sorokin    private final List<ContentValues> mMmsTable = new ArrayList<>();
721d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin    /* Table contains parts, addresses of mms */
738b39acf181c547e87161873112d6c52a581fc778Roman Sorokin    private final List<ContentValues> mMmsAllContentValues = new ArrayList<>();
741d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin    /* Cursors being used to access sms, mms tables */
758b39acf181c547e87161873112d6c52a581fc778Roman Sorokin    private FakeCursor mSmsCursor, mMmsCursor;
761d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin    /* Test data with sms and mms */
778b39acf181c547e87161873112d6c52a581fc778Roman Sorokin    private ContentValues[] mSmsRows, mMmsRows;
781d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin    /* Json representation for the test data */
798b39acf181c547e87161873112d6c52a581fc778Roman Sorokin    private String[] mSmsJson, mMmsJson;
801d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin    /* sms, mms json concatenated as json array */
818b39acf181c547e87161873112d6c52a581fc778Roman Sorokin    private String mAllSmsJson, mAllMmsJson;
828b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
838b39acf181c547e87161873112d6c52a581fc778Roman Sorokin    private StringWriter mStringWriter;
841d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin
859037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokin    /* Content resolver passed to the backupAgent */
869037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokin    private MockContentResolver mMockContentResolver = new MockContentResolver();
879037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokin
881d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin    /* Map uri -> cursors. Being used for contentprovider. */
898b39acf181c547e87161873112d6c52a581fc778Roman Sorokin    private Map<Uri, FakeCursor> mCursors;
9076422e0ed1bc5b68f857094a05b5fec8b507f36eRoman Sorokin    /* Content provider with threadIds.*/
9176422e0ed1bc5b68f857094a05b5fec8b507f36eRoman Sorokin    private ThreadProvider mThreadProvider = new ThreadProvider();
928b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
938b39acf181c547e87161873112d6c52a581fc778Roman Sorokin    private static final String EMPTY_JSON_ARRAY = "[]";
9421736c3871d5c4cd3a6322d65d635057d0a61937Roman Sorokin
9521736c3871d5c4cd3a6322d65d635057d0a61937Roman Sorokin    TelephonyBackupAgent mTelephonyBackupAgent;
9621736c3871d5c4cd3a6322d65d635057d0a61937Roman Sorokin
978b39acf181c547e87161873112d6c52a581fc778Roman Sorokin    @Override
988b39acf181c547e87161873112d6c52a581fc778Roman Sorokin    protected void setUp() throws Exception {
998b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        super.setUp();
1001d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin
1011d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin        /* Filling up subscription maps */
1028b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        mStringWriter = new StringWriter();
1038b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        mSubId2Phone = new SparseArray<String>();
1048b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        mSubId2Phone.append(1, "+111111111111111");
1058b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        mSubId2Phone.append(3, "+333333333333333");
1068b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
1078b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        mPhone2SubId = new ArrayMap<>();
1088b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        for (int i=0; i<mSubId2Phone.size(); ++i) {
1098b39acf181c547e87161873112d6c52a581fc778Roman Sorokin            mPhone2SubId.put(mSubId2Phone.valueAt(i), mSubId2Phone.keyAt(i));
1108b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        }
1118b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
11221736c3871d5c4cd3a6322d65d635057d0a61937Roman Sorokin        mCursors = new HashMap<Uri, FakeCursor>();
1131d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin        /* Bind tables to the cursors */
1148b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        mSmsCursor = new FakeCursor(mSmsTable, TelephonyBackupAgent.SMS_PROJECTION);
11521736c3871d5c4cd3a6322d65d635057d0a61937Roman Sorokin        mCursors.put(Telephony.Sms.CONTENT_URI, mSmsCursor);
1168b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        mMmsCursor = new FakeCursor(mMmsTable, TelephonyBackupAgent.MMS_PROJECTION);
11721736c3871d5c4cd3a6322d65d635057d0a61937Roman Sorokin        mCursors.put(Telephony.Mms.CONTENT_URI, mMmsCursor);
1181d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin
1198b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
1201d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin        /* Generating test data */
12156117b955dda1c134473a4fed4b0a73fb1c6cea2Roman Sorokin        mSmsRows = new ContentValues[4];
12256117b955dda1c134473a4fed4b0a73fb1c6cea2Roman Sorokin        mSmsJson = new String[4];
1238b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        mSmsRows[0] = createSmsRow(1, 1, "+1232132214124", "sms 1", "sms subject", 9087978987l,
1248b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                999999999, 3, 44, 1);
1258b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        mSmsJson[0] = "{\"self_phone\":\"+111111111111111\",\"address\":" +
1268b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                "\"+1232132214124\",\"body\":\"sms 1\",\"subject\":\"sms subject\",\"date\":" +
1271d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin                "\"9087978987\",\"date_sent\":\"999999999\",\"status\":\"3\",\"type\":\"44\"," +
1283aa281731a6f25cd36b88bca809b13d3f581d05fRoman Sorokin                "\"recipients\":[\"+123 (213) 2214124\"],\"archived\":true}";
1293aa281731a6f25cd36b88bca809b13d3f581d05fRoman Sorokin        mThreadProvider.setArchived(
1303aa281731a6f25cd36b88bca809b13d3f581d05fRoman Sorokin                mThreadProvider.getOrCreateThreadId(new String[]{"+123 (213) 2214124"}));
1318b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
1328b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        mSmsRows[1] = createSmsRow(2, 2, "+1232132214124", "sms 2", null, 9087978987l, 999999999,
1338b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                0, 4, 1);
1348b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        mSmsJson[1] = "{\"address\":\"+1232132214124\",\"body\":\"sms 2\",\"date\":" +
1351d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin                "\"9087978987\",\"date_sent\":\"999999999\",\"status\":\"0\",\"type\":\"4\"," +
13676422e0ed1bc5b68f857094a05b5fec8b507f36eRoman Sorokin                "\"recipients\":[\"+123 (213) 2214124\"]}";
1378b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
1388b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        mSmsRows[2] = createSmsRow(4, 3, "+1232221412433 +1232221412444", "sms 3", null,
1398b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                111111111111l, 999999999, 2, 3, 2);
1408b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        mSmsJson[2] =  "{\"self_phone\":\"+333333333333333\",\"address\":" +
1418b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                "\"+1232221412433 +1232221412444\",\"body\":\"sms 3\",\"date\":\"111111111111\"," +
1428b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                "\"date_sent\":" +
1431d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin                "\"999999999\",\"status\":\"2\",\"type\":\"3\"," +
14476422e0ed1bc5b68f857094a05b5fec8b507f36eRoman Sorokin                "\"recipients\":[\"+1232221412433\",\"+1232221412444\"]}";
14576422e0ed1bc5b68f857094a05b5fec8b507f36eRoman Sorokin        mThreadProvider.getOrCreateThreadId(new String[]{"+1232221412433", "+1232221412444"});
1468b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
14756117b955dda1c134473a4fed4b0a73fb1c6cea2Roman Sorokin
14856117b955dda1c134473a4fed4b0a73fb1c6cea2Roman Sorokin        mSmsRows[3] = createSmsRow(5, 3, null, "sms 4", null,
14956117b955dda1c134473a4fed4b0a73fb1c6cea2Roman Sorokin                111111111111l, 999999999, 2, 3, 5);
15056117b955dda1c134473a4fed4b0a73fb1c6cea2Roman Sorokin        mSmsJson[3] = "{\"self_phone\":\"+333333333333333\"," +
15156117b955dda1c134473a4fed4b0a73fb1c6cea2Roman Sorokin                "\"body\":\"sms 4\",\"date\":\"111111111111\"," +
15256117b955dda1c134473a4fed4b0a73fb1c6cea2Roman Sorokin                "\"date_sent\":" +
15356117b955dda1c134473a4fed4b0a73fb1c6cea2Roman Sorokin                "\"999999999\",\"status\":\"2\",\"type\":\"3\"}";
15456117b955dda1c134473a4fed4b0a73fb1c6cea2Roman Sorokin
1551d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin        mAllSmsJson = makeJsonArray(mSmsJson);
1568b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
1578b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
1588b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
1598b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        mMmsRows = new ContentValues[3];
1608b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        mMmsJson = new String[3];
1618b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        mMmsRows[0] = createMmsRow(1 /*id*/, 1 /*subid*/, "Subject 1" /*subject*/,
1628b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                100 /*subcharset*/, 111111 /*date*/, 111112 /*datesent*/, 3 /*type*/,
1638b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                17 /*version*/, 1 /*textonly*/,
1648b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                11 /*msgBox*/, "location 1" /*contentLocation*/, "MMs body 1" /*body*/,
1658b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                111 /*body charset*/,
16676422e0ed1bc5b68f857094a05b5fec8b507f36eRoman Sorokin                new String[]{"+111 (111) 11111111", "+11121212", "example@example.com",
16776422e0ed1bc5b68f857094a05b5fec8b507f36eRoman Sorokin                        "+999999999"} /*addresses*/,
16876422e0ed1bc5b68f857094a05b5fec8b507f36eRoman Sorokin                3 /*threadId*/);
1698b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
1708b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        mMmsJson[0] = "{\"self_phone\":\"+111111111111111\",\"sub\":\"Subject 1\"," +
1718b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                "\"date\":\"111111\",\"date_sent\":\"111112\",\"m_type\":\"3\",\"v\":\"17\"," +
17276422e0ed1bc5b68f857094a05b5fec8b507f36eRoman Sorokin                "\"msg_box\":\"11\",\"ct_l\":\"location 1\"," +
17376422e0ed1bc5b68f857094a05b5fec8b507f36eRoman Sorokin                "\"recipients\":[\"+11121212\",\"example@example.com\",\"+999999999\"]," +
17476422e0ed1bc5b68f857094a05b5fec8b507f36eRoman Sorokin                "\"mms_addresses\":" +
17576422e0ed1bc5b68f857094a05b5fec8b507f36eRoman Sorokin                "[{\"type\":10,\"address\":\"+111 (111) 11111111\",\"charset\":100}," +
17676422e0ed1bc5b68f857094a05b5fec8b507f36eRoman Sorokin                "{\"type\":11,\"address\":\"+11121212\",\"charset\":101},{\"type\":12,\"address\":"+
17776422e0ed1bc5b68f857094a05b5fec8b507f36eRoman Sorokin                "\"example@example.com\",\"charset\":102},{\"type\":13,\"address\":\"+999999999\"" +
17876422e0ed1bc5b68f857094a05b5fec8b507f36eRoman Sorokin                ",\"charset\":103}],\"mms_body\":\"MMs body 1\",\"mms_charset\":111,\"" +
1798b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                "sub_cs\":\"100\"}";
18076422e0ed1bc5b68f857094a05b5fec8b507f36eRoman Sorokin        mThreadProvider.getOrCreateThreadId(new String[]{"+11121212", "example@example.com",
18176422e0ed1bc5b68f857094a05b5fec8b507f36eRoman Sorokin                "+999999999"});
1828b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
1838b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        mMmsRows[1] = createMmsRow(2 /*id*/, 2 /*subid*/, null /*subject*/, 100 /*subcharset*/,
1848b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                111122 /*date*/, 1111112 /*datesent*/, 4 /*type*/, 18 /*version*/, 1 /*textonly*/,
1858b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                222 /*msgBox*/, "location 2" /*contentLocation*/, "MMs body 2" /*body*/,
1868b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                121 /*body charset*/,
18776422e0ed1bc5b68f857094a05b5fec8b507f36eRoman Sorokin                new String[]{"+7 (333) ", "example@example.com", "+999999999"} /*addresses*/,
18876422e0ed1bc5b68f857094a05b5fec8b507f36eRoman Sorokin                4 /*threadId*/);
1898b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        mMmsJson[1] = "{\"date\":\"111122\",\"date_sent\":\"1111112\",\"m_type\":\"4\"," +
19076422e0ed1bc5b68f857094a05b5fec8b507f36eRoman Sorokin                "\"v\":\"18\",\"msg_box\":\"222\",\"ct_l\":\"location 2\"," +
19176422e0ed1bc5b68f857094a05b5fec8b507f36eRoman Sorokin                "\"recipients\":[\"example@example.com\",\"+999999999\"]," +
19276422e0ed1bc5b68f857094a05b5fec8b507f36eRoman Sorokin                "\"mms_addresses\":" +
19376422e0ed1bc5b68f857094a05b5fec8b507f36eRoman Sorokin                "[{\"type\":10,\"address\":\"+7 (333) \",\"charset\":100}," +
19476422e0ed1bc5b68f857094a05b5fec8b507f36eRoman Sorokin                "{\"type\":11,\"address\":\"example@example.com\",\"charset\":101}," +
19576422e0ed1bc5b68f857094a05b5fec8b507f36eRoman Sorokin                "{\"type\":12,\"address\":\"+999999999\",\"charset\":102}]," +
1968b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                "\"mms_body\":\"MMs body 2\",\"mms_charset\":121}";
19776422e0ed1bc5b68f857094a05b5fec8b507f36eRoman Sorokin        mThreadProvider.getOrCreateThreadId(new String[]{"example@example.com", "+999999999"});
1988b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
19976422e0ed1bc5b68f857094a05b5fec8b507f36eRoman Sorokin        mMmsRows[2] = createMmsRow(9 /*id*/, 3 /*subid*/, "Subject 10" /*subject*/,
2008b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                10 /*subcharset*/, 111133 /*date*/, 1111132 /*datesent*/, 5 /*type*/,
2018b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                19 /*version*/, 1 /*textonly*/,
2028b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                333 /*msgBox*/, null /*contentLocation*/, "MMs body 3" /*body*/,
20376422e0ed1bc5b68f857094a05b5fec8b507f36eRoman Sorokin                131 /*body charset*/,
20476422e0ed1bc5b68f857094a05b5fec8b507f36eRoman Sorokin                new String[]{"333 333333333333", "+1232132214124"} /*addresses*/,
20576422e0ed1bc5b68f857094a05b5fec8b507f36eRoman Sorokin                1 /*threadId*/);
2068b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
2078b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        mMmsJson[2] = "{\"self_phone\":\"+333333333333333\",\"sub\":\"Subject 10\"," +
2088b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                "\"date\":\"111133\",\"date_sent\":\"1111132\",\"m_type\":\"5\",\"v\":\"19\"," +
20976422e0ed1bc5b68f857094a05b5fec8b507f36eRoman Sorokin                "\"msg_box\":\"333\"," +
2103aa281731a6f25cd36b88bca809b13d3f581d05fRoman Sorokin                "\"recipients\":[\"+123 (213) 2214124\"],\"archived\":true," +
21176422e0ed1bc5b68f857094a05b5fec8b507f36eRoman Sorokin                "\"mms_addresses\":" +
21276422e0ed1bc5b68f857094a05b5fec8b507f36eRoman Sorokin                "[{\"type\":10,\"address\":\"333 333333333333\",\"charset\":100}," +
21376422e0ed1bc5b68f857094a05b5fec8b507f36eRoman Sorokin                "{\"type\":11,\"address\":\"+1232132214124\",\"charset\":101}]," +
21476422e0ed1bc5b68f857094a05b5fec8b507f36eRoman Sorokin                "\"mms_body\":\"MMs body 3\",\"mms_charset\":131," +
2158b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                "\"sub_cs\":\"10\"}";
2161d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin        mAllMmsJson = makeJsonArray(mMmsJson);
2178b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
2189037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokin        ContentProvider contentProvider = new MockContentProvider() {
2198b39acf181c547e87161873112d6c52a581fc778Roman Sorokin            @Override
2208b39acf181c547e87161873112d6c52a581fc778Roman Sorokin            public Cursor query(Uri uri, String[] projection, String selection,
2218b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                                String[] selectionArgs, String sortOrder) {
2228b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                if (mCursors.containsKey(uri)) {
2238b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                    FakeCursor fakeCursor = mCursors.get(uri);
2248b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                    if (projection != null) {
2258b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                        fakeCursor.setProjection(projection);
2268b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                    }
22721736c3871d5c4cd3a6322d65d635057d0a61937Roman Sorokin                    fakeCursor.nextRow = 0;
2288b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                    return fakeCursor;
2298b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                }
2309037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokin                fail("No cursor for " + uri.toString());
2319037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokin                return null;
2328b39acf181c547e87161873112d6c52a581fc778Roman Sorokin            }
2338b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        };
2348b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
2359037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokin        mMockContentResolver.addProvider("sms", contentProvider);
2369037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokin        mMockContentResolver.addProvider("mms", contentProvider);
2379037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokin        mMockContentResolver.addProvider("mms-sms", mThreadProvider);
2389037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokin
2399037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokin        mTelephonyBackupAgent = new TelephonyBackupAgent();
2409037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokin        mTelephonyBackupAgent.attach(new ContextWrapper(getContext()) {
2419037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokin            @Override
2429037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokin            public ContentResolver getContentResolver() {
2439037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokin                return mMockContentResolver;
2449037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokin            }
2459037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokin        });
2469037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokin
2479037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokin
24821736c3871d5c4cd3a6322d65d635057d0a61937Roman Sorokin        mTelephonyBackupAgent.clearSharedPreferences();
2499037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokin        mTelephonyBackupAgent.setContentResolver(mMockContentResolver);
2509037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokin        mTelephonyBackupAgent.setSubId(mSubId2Phone, mPhone2SubId);
25121736c3871d5c4cd3a6322d65d635057d0a61937Roman Sorokin    }
25221736c3871d5c4cd3a6322d65d635057d0a61937Roman Sorokin
25321736c3871d5c4cd3a6322d65d635057d0a61937Roman Sorokin    @Override
25421736c3871d5c4cd3a6322d65d635057d0a61937Roman Sorokin    protected void tearDown() throws Exception {
25521736c3871d5c4cd3a6322d65d635057d0a61937Roman Sorokin        mTelephonyBackupAgent.clearSharedPreferences();
25621736c3871d5c4cd3a6322d65d635057d0a61937Roman Sorokin        super.tearDown();
2578b39acf181c547e87161873112d6c52a581fc778Roman Sorokin    }
2588b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
2591d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin    private static String makeJsonArray(String[] json) {
2608b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        StringBuilder stringBuilder = new StringBuilder("[");
2618b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        for (int i=0; i<json.length; ++i) {
2628b39acf181c547e87161873112d6c52a581fc778Roman Sorokin            if (i > 0) {
2638b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                stringBuilder.append(",");
2648b39acf181c547e87161873112d6c52a581fc778Roman Sorokin            }
2658b39acf181c547e87161873112d6c52a581fc778Roman Sorokin            stringBuilder.append(json[i]);
2668b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        }
2678b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        stringBuilder.append("]");
2688b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        return stringBuilder.toString();
2698b39acf181c547e87161873112d6c52a581fc778Roman Sorokin    }
2708b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
2718b39acf181c547e87161873112d6c52a581fc778Roman Sorokin    private static ContentValues createSmsRow(int id, int subId, String address, String body,
2728b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                                              String subj, long date, long dateSent,
2738b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                                              int status, int type, long threadId) {
2748b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        ContentValues smsRow = new ContentValues();
2758b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        smsRow.put(Telephony.Sms._ID, id);
2768b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        smsRow.put(Telephony.Sms.SUBSCRIPTION_ID, subId);
2778b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        if (address != null) {
2788b39acf181c547e87161873112d6c52a581fc778Roman Sorokin            smsRow.put(Telephony.Sms.ADDRESS, address);
2798b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        }
2808b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        if (body != null) {
2818b39acf181c547e87161873112d6c52a581fc778Roman Sorokin            smsRow.put(Telephony.Sms.BODY, body);
2828b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        }
2838b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        if (subj != null) {
2848b39acf181c547e87161873112d6c52a581fc778Roman Sorokin            smsRow.put(Telephony.Sms.SUBJECT, subj);
2858b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        }
2868b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        smsRow.put(Telephony.Sms.DATE, String.valueOf(date));
2878b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        smsRow.put(Telephony.Sms.DATE_SENT, String.valueOf(dateSent));
2888b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        smsRow.put(Telephony.Sms.STATUS, String.valueOf(status));
2898b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        smsRow.put(Telephony.Sms.TYPE, String.valueOf(type));
2908b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        smsRow.put(Telephony.Sms.THREAD_ID, threadId);
2918b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
2928b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        return smsRow;
2938b39acf181c547e87161873112d6c52a581fc778Roman Sorokin    }
2948b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
2958b39acf181c547e87161873112d6c52a581fc778Roman Sorokin    private ContentValues createMmsRow(int id, int subId, String subj, int subCharset,
2968b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                                       long date, long dateSent, int type, int version,
2978b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                                       int textOnly, int msgBox,
2988b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                                       String contentLocation, String body,
2998b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                                       int bodyCharset, String[] addresses, long threadId) {
3008b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        ContentValues mmsRow = new ContentValues();
3018b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        mmsRow.put(Telephony.Mms._ID, id);
3028b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        mmsRow.put(Telephony.Mms.SUBSCRIPTION_ID, subId);
3038b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        if (subj != null) {
3048b39acf181c547e87161873112d6c52a581fc778Roman Sorokin            mmsRow.put(Telephony.Mms.SUBJECT, subj);
3058b39acf181c547e87161873112d6c52a581fc778Roman Sorokin            mmsRow.put(Telephony.Mms.SUBJECT_CHARSET, String.valueOf(subCharset));
3068b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        }
3078b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        mmsRow.put(Telephony.Mms.DATE, String.valueOf(date));
3088b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        mmsRow.put(Telephony.Mms.DATE_SENT, String.valueOf(dateSent));
3098b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        mmsRow.put(Telephony.Mms.MESSAGE_TYPE, String.valueOf(type));
3108b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        mmsRow.put(Telephony.Mms.MMS_VERSION, String.valueOf(version));
3118b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        mmsRow.put(Telephony.Mms.TEXT_ONLY, textOnly);
3128b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        mmsRow.put(Telephony.Mms.MESSAGE_BOX, String.valueOf(msgBox));
3138b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        if (contentLocation != null) {
3148b39acf181c547e87161873112d6c52a581fc778Roman Sorokin            mmsRow.put(Telephony.Mms.CONTENT_LOCATION, contentLocation);
3158b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        }
3168b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        mmsRow.put(Telephony.Mms.THREAD_ID, threadId);
3178b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
3188b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        final Uri partUri = Telephony.Mms.CONTENT_URI.buildUpon().appendPath(String.valueOf(id)).
3198b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                appendPath("part").build();
3208b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        mCursors.put(partUri, createBodyCursor(body, bodyCharset));
3218b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        mMmsAllContentValues.add(mmsRow);
3228b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
3238b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        final Uri addrUri = Telephony.Mms.CONTENT_URI.buildUpon().appendPath(String.valueOf(id)).
3248b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                appendPath("addr").build();
3258b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        mCursors.put(addrUri, createAddrCursor(addresses));
3268b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
3278b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        return mmsRow;
3288b39acf181c547e87161873112d6c52a581fc778Roman Sorokin    }
3298b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
3308b39acf181c547e87161873112d6c52a581fc778Roman Sorokin    private static final String APP_SMIL = "application/smil";
3318b39acf181c547e87161873112d6c52a581fc778Roman Sorokin    private static final String TEXT_PLAIN = "text/plain";
3328b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
3338b39acf181c547e87161873112d6c52a581fc778Roman Sorokin    // Cursor with parts of Mms.
3348b39acf181c547e87161873112d6c52a581fc778Roman Sorokin    private FakeCursor createBodyCursor(String body, int charset) {
3358b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        List<ContentValues> table = new ArrayList<>();
3368b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        final String srcName = String.format("text.%06d.txt", 0);
3378b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        final String smilBody = String.format(TelephonyBackupAgent.sSmilTextPart, srcName);
3388b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        final String smil = String.format(TelephonyBackupAgent.sSmilTextOnly, smilBody);
3398b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
3408b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        final ContentValues smilPart = new ContentValues();
3418b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        smilPart.put(Telephony.Mms.Part.SEQ, -1);
3428b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        smilPart.put(Telephony.Mms.Part.CONTENT_TYPE, APP_SMIL);
3438b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        smilPart.put(Telephony.Mms.Part.NAME, "smil.xml");
3448b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        smilPart.put(Telephony.Mms.Part.CONTENT_ID, "<smil>");
3458b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        smilPart.put(Telephony.Mms.Part.CONTENT_LOCATION, "smil.xml");
3468b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        smilPart.put(Telephony.Mms.Part.TEXT, smil);
3478b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        mMmsAllContentValues.add(smilPart);
3488b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
3498b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        final ContentValues bodyPart = new ContentValues();
3508b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        bodyPart.put(Telephony.Mms.Part.SEQ, 0);
3518b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        bodyPart.put(Telephony.Mms.Part.CONTENT_TYPE, TEXT_PLAIN);
3528b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        bodyPart.put(Telephony.Mms.Part.NAME, srcName);
3538b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        bodyPart.put(Telephony.Mms.Part.CONTENT_ID, "<"+srcName+">");
3548b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        bodyPart.put(Telephony.Mms.Part.CONTENT_LOCATION, srcName);
3558b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        bodyPart.put(Telephony.Mms.Part.CHARSET, charset);
3568b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        bodyPart.put(Telephony.Mms.Part.TEXT, body);
3578b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        table.add(bodyPart);
3588b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        mMmsAllContentValues.add(bodyPart);
3598b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
3608b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        return new FakeCursor(table, TelephonyBackupAgent.MMS_TEXT_PROJECTION);
3618b39acf181c547e87161873112d6c52a581fc778Roman Sorokin    }
3628b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
3638b39acf181c547e87161873112d6c52a581fc778Roman Sorokin    // Cursor with addresses of Mms.
3648b39acf181c547e87161873112d6c52a581fc778Roman Sorokin    private FakeCursor createAddrCursor(String[] addresses) {
3658b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        List<ContentValues> table = new ArrayList<>();
3668b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        for (int i=0; i<addresses.length; ++i) {
3678b39acf181c547e87161873112d6c52a581fc778Roman Sorokin            ContentValues addr = new ContentValues();
3688b39acf181c547e87161873112d6c52a581fc778Roman Sorokin            addr.put(Telephony.Mms.Addr.TYPE, 10+i);
3698b39acf181c547e87161873112d6c52a581fc778Roman Sorokin            addr.put(Telephony.Mms.Addr.ADDRESS, addresses[i]);
370a632476534b877cdad602a27fe8ba01892d0bd83Roman Sorokin            addr.put(Telephony.Mms.Addr.CHARSET, 100+i);
3718b39acf181c547e87161873112d6c52a581fc778Roman Sorokin            mMmsAllContentValues.add(addr);
3728b39acf181c547e87161873112d6c52a581fc778Roman Sorokin            table.add(addr);
3738b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        }
3748b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        return new FakeCursor(table, TelephonyBackupAgent.MMS_ADDR_PROJECTION);
3758b39acf181c547e87161873112d6c52a581fc778Roman Sorokin    }
3768b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
3778b39acf181c547e87161873112d6c52a581fc778Roman Sorokin    /**
3788b39acf181c547e87161873112d6c52a581fc778Roman Sorokin     * Test with no sms in the provider.
3798b39acf181c547e87161873112d6c52a581fc778Roman Sorokin     * @throws Exception
3808b39acf181c547e87161873112d6c52a581fc778Roman Sorokin     */
3818b39acf181c547e87161873112d6c52a581fc778Roman Sorokin    public void testBackupSms_NoSms() throws Exception {
3829037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokin        mTelephonyBackupAgent.putSmsMessagesToJson(mSmsCursor, new JsonWriter(mStringWriter));
3838b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        assertEquals(EMPTY_JSON_ARRAY, mStringWriter.toString());
3848b39acf181c547e87161873112d6c52a581fc778Roman Sorokin    }
3858b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
3868b39acf181c547e87161873112d6c52a581fc778Roman Sorokin    /**
3878b39acf181c547e87161873112d6c52a581fc778Roman Sorokin     * Test with 3 sms in the provider with the limit per file 4.
3888b39acf181c547e87161873112d6c52a581fc778Roman Sorokin     * @throws Exception
3898b39acf181c547e87161873112d6c52a581fc778Roman Sorokin     */
3901d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin    public void testBackupSms_AllSms() throws Exception {
3919037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokin        mTelephonyBackupAgent.mMaxMsgPerFile = 4;
3928b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        mSmsTable.addAll(Arrays.asList(mSmsRows));
3939037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokin        mTelephonyBackupAgent.putSmsMessagesToJson(mSmsCursor, new JsonWriter(mStringWriter));
3941d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin        assertEquals(mAllSmsJson, mStringWriter.toString());
3958b39acf181c547e87161873112d6c52a581fc778Roman Sorokin    }
3968b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
3978b39acf181c547e87161873112d6c52a581fc778Roman Sorokin    /**
3988b39acf181c547e87161873112d6c52a581fc778Roman Sorokin     * Test with 3 sms in the provider with the limit per file 3.
3998b39acf181c547e87161873112d6c52a581fc778Roman Sorokin     * @throws Exception
4008b39acf181c547e87161873112d6c52a581fc778Roman Sorokin     */
4011d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin    public void testBackupSms_AllSmsWithExactFileLimit() throws Exception {
40256117b955dda1c134473a4fed4b0a73fb1c6cea2Roman Sorokin        mTelephonyBackupAgent.mMaxMsgPerFile = 4;
4038b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        mSmsTable.addAll(Arrays.asList(mSmsRows));
4049037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokin        mTelephonyBackupAgent.putSmsMessagesToJson(mSmsCursor, new JsonWriter(mStringWriter));
4051d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin        assertEquals(mAllSmsJson, mStringWriter.toString());
4068b39acf181c547e87161873112d6c52a581fc778Roman Sorokin    }
4078b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
4088b39acf181c547e87161873112d6c52a581fc778Roman Sorokin    /**
4098b39acf181c547e87161873112d6c52a581fc778Roman Sorokin     * Test with 3 sms in the provider with the limit per file 1.
4108b39acf181c547e87161873112d6c52a581fc778Roman Sorokin     * @throws Exception
4118b39acf181c547e87161873112d6c52a581fc778Roman Sorokin     */
4121d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin    public void testBackupSms_AllSmsOneMessagePerFile() throws Exception {
4139037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokin        mTelephonyBackupAgent.mMaxMsgPerFile = 1;
4148b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        mSmsTable.addAll(Arrays.asList(mSmsRows));
4151d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin
4169037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokin        mTelephonyBackupAgent.putSmsMessagesToJson(mSmsCursor, new JsonWriter(mStringWriter));
4178b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        assertEquals("[" + mSmsJson[0] + "]", mStringWriter.toString());
4188b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
4198b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        mStringWriter = new StringWriter();
4209037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokin        mTelephonyBackupAgent.putSmsMessagesToJson(mSmsCursor, new JsonWriter(mStringWriter));
4218b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        assertEquals("[" + mSmsJson[1] + "]", mStringWriter.toString());
4228b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
4238b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        mStringWriter = new StringWriter();
4249037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokin        mTelephonyBackupAgent.putSmsMessagesToJson(mSmsCursor, new JsonWriter(mStringWriter));
4258b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        assertEquals("[" + mSmsJson[2] + "]", mStringWriter.toString());
42656117b955dda1c134473a4fed4b0a73fb1c6cea2Roman Sorokin
42756117b955dda1c134473a4fed4b0a73fb1c6cea2Roman Sorokin        mStringWriter = new StringWriter();
42856117b955dda1c134473a4fed4b0a73fb1c6cea2Roman Sorokin        mTelephonyBackupAgent.putSmsMessagesToJson(mSmsCursor, new JsonWriter(mStringWriter));
42956117b955dda1c134473a4fed4b0a73fb1c6cea2Roman Sorokin        assertEquals("[" + mSmsJson[3] + "]", mStringWriter.toString());
4308b39acf181c547e87161873112d6c52a581fc778Roman Sorokin    }
4318b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
4328b39acf181c547e87161873112d6c52a581fc778Roman Sorokin    /**
4338b39acf181c547e87161873112d6c52a581fc778Roman Sorokin     * Test with no mms in the pvovider.
4348b39acf181c547e87161873112d6c52a581fc778Roman Sorokin     * @throws Exception
4358b39acf181c547e87161873112d6c52a581fc778Roman Sorokin     */
4368b39acf181c547e87161873112d6c52a581fc778Roman Sorokin    public void testBackupMms_NoMms() throws Exception {
4379037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokin        mTelephonyBackupAgent.putMmsMessagesToJson(mMmsCursor, new JsonWriter(mStringWriter));
4388b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        assertEquals(EMPTY_JSON_ARRAY, mStringWriter.toString());
4398b39acf181c547e87161873112d6c52a581fc778Roman Sorokin    }
4408b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
4418b39acf181c547e87161873112d6c52a581fc778Roman Sorokin    /**
4428b39acf181c547e87161873112d6c52a581fc778Roman Sorokin     * Test with all mms.
4438b39acf181c547e87161873112d6c52a581fc778Roman Sorokin     * @throws Exception
4448b39acf181c547e87161873112d6c52a581fc778Roman Sorokin     */
4458b39acf181c547e87161873112d6c52a581fc778Roman Sorokin    public void testBackupMms_AllMms() throws Exception {
4469037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokin        mTelephonyBackupAgent.mMaxMsgPerFile = 4;
4478b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        mMmsTable.addAll(Arrays.asList(mMmsRows));
4489037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokin        mTelephonyBackupAgent.putMmsMessagesToJson(mMmsCursor, new JsonWriter(mStringWriter));
4491d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin        assertEquals(mAllMmsJson, mStringWriter.toString());
4508b39acf181c547e87161873112d6c52a581fc778Roman Sorokin    }
4518b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
4528b39acf181c547e87161873112d6c52a581fc778Roman Sorokin    /**
4538b39acf181c547e87161873112d6c52a581fc778Roman Sorokin     * Test with 3 mms in the provider with the limit per file 1.
4548b39acf181c547e87161873112d6c52a581fc778Roman Sorokin     * @throws Exception
4558b39acf181c547e87161873112d6c52a581fc778Roman Sorokin     */
4568b39acf181c547e87161873112d6c52a581fc778Roman Sorokin    public void testBackupMms_OneMessagePerFile() throws Exception {
4579037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokin        mTelephonyBackupAgent.mMaxMsgPerFile = 1;
4588b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        mMmsTable.addAll(Arrays.asList(mMmsRows));
4599037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokin        mTelephonyBackupAgent.putMmsMessagesToJson(mMmsCursor, new JsonWriter(mStringWriter));
4608b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        assertEquals("[" + mMmsJson[0] + "]", mStringWriter.toString());
4618b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
4628b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        mStringWriter = new StringWriter();
4639037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokin        mTelephonyBackupAgent.putMmsMessagesToJson(mMmsCursor, new JsonWriter(mStringWriter));
4648b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        assertEquals("[" + mMmsJson[1] + "]", mStringWriter.toString());
4658b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
4668b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        mStringWriter = new StringWriter();
4679037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokin        mTelephonyBackupAgent.putMmsMessagesToJson(mMmsCursor, new JsonWriter(mStringWriter));
4688b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        assertEquals("[" + mMmsJson[2] + "]", mStringWriter.toString());
4698b39acf181c547e87161873112d6c52a581fc778Roman Sorokin    }
4708b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
4718b39acf181c547e87161873112d6c52a581fc778Roman Sorokin    /**
4728b39acf181c547e87161873112d6c52a581fc778Roman Sorokin     * Test with 3 mms in the provider with the limit per file 3.
4738b39acf181c547e87161873112d6c52a581fc778Roman Sorokin     * @throws Exception
4748b39acf181c547e87161873112d6c52a581fc778Roman Sorokin     */
4758b39acf181c547e87161873112d6c52a581fc778Roman Sorokin    public void testBackupMms_WithExactFileLimit() throws Exception {
4768b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        mMmsTable.addAll(Arrays.asList(mMmsRows));
4779037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokin        mTelephonyBackupAgent.mMaxMsgPerFile = 3;
4789037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokin        mTelephonyBackupAgent.putMmsMessagesToJson(mMmsCursor, new JsonWriter(mStringWriter));
4791d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin        assertEquals(mAllMmsJson, mStringWriter.toString());
4808b39acf181c547e87161873112d6c52a581fc778Roman Sorokin    }
4818b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
4828b39acf181c547e87161873112d6c52a581fc778Roman Sorokin    /**
4838b39acf181c547e87161873112d6c52a581fc778Roman Sorokin     * Test restore sms with the empty json array "[]".
4848b39acf181c547e87161873112d6c52a581fc778Roman Sorokin     * @throws Exception
4858b39acf181c547e87161873112d6c52a581fc778Roman Sorokin     */
4868b39acf181c547e87161873112d6c52a581fc778Roman Sorokin    public void testRestoreSms_NoSms() throws Exception {
4878b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        JsonReader jsonReader = new JsonReader(new StringReader(EMPTY_JSON_ARRAY));
4888b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        FakeSmsProvider smsProvider = new FakeSmsProvider(null);
4899037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokin        mMockContentResolver.addProvider("sms", smsProvider);
4909037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokin        mTelephonyBackupAgent.putSmsMessagesToProvider(jsonReader);
4918b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        assertEquals(0, smsProvider.getRowsAdded());
4928b39acf181c547e87161873112d6c52a581fc778Roman Sorokin    }
4938b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
4948b39acf181c547e87161873112d6c52a581fc778Roman Sorokin    /**
4958b39acf181c547e87161873112d6c52a581fc778Roman Sorokin     * Test restore sms with three sms json object in the array.
4968b39acf181c547e87161873112d6c52a581fc778Roman Sorokin     * @throws Exception
4978b39acf181c547e87161873112d6c52a581fc778Roman Sorokin     */
4981d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin    public void testRestoreSms_AllSms() throws Exception {
49956117b955dda1c134473a4fed4b0a73fb1c6cea2Roman Sorokin        mTelephonyBackupAgent.initUnknownSender();
5009037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokin        JsonReader jsonReader = new JsonReader(new StringReader(addRandomDataToJson(mAllSmsJson)));
5018b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        FakeSmsProvider smsProvider = new FakeSmsProvider(mSmsRows);
5029037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokin        mMockContentResolver.addProvider("sms", smsProvider);
5039037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokin        mTelephonyBackupAgent.putSmsMessagesToProvider(jsonReader);
5048b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        assertEquals(mSmsRows.length, smsProvider.getRowsAdded());
5053aa281731a6f25cd36b88bca809b13d3f581d05fRoman Sorokin        assertEquals(mThreadProvider.mIsThreadArchived, mThreadProvider.mUpdateThreadsArchived);
5068b39acf181c547e87161873112d6c52a581fc778Roman Sorokin    }
5078b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
5088b39acf181c547e87161873112d6c52a581fc778Roman Sorokin    /**
5098b39acf181c547e87161873112d6c52a581fc778Roman Sorokin     * Test restore mms with the empty json array "[]".
5108b39acf181c547e87161873112d6c52a581fc778Roman Sorokin     * @throws Exception
5118b39acf181c547e87161873112d6c52a581fc778Roman Sorokin     */
5128b39acf181c547e87161873112d6c52a581fc778Roman Sorokin    public void testRestoreMms_NoMms() throws Exception {
5138b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        JsonReader jsonReader = new JsonReader(new StringReader(EMPTY_JSON_ARRAY));
5148b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        FakeMmsProvider mmsProvider = new FakeMmsProvider(null);
5159037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokin        mMockContentResolver.addProvider("mms", mmsProvider);
5169037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokin        mTelephonyBackupAgent.putMmsMessagesToProvider(jsonReader);
5178b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        assertEquals(0, mmsProvider.getRowsAdded());
5188b39acf181c547e87161873112d6c52a581fc778Roman Sorokin    }
5198b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
5208b39acf181c547e87161873112d6c52a581fc778Roman Sorokin    /**
5219037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokin     * Test restore sms with three mms json object in the array.
5229037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokin     * @throws Exception
5239037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokin     */
5249037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokin    public void testRestoreMms_AllMms() throws Exception {
5259037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokin        JsonReader jsonReader = new JsonReader(new StringReader(addRandomDataToJson(mAllMmsJson)));
5269037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokin        FakeMmsProvider mmsProvider = new FakeMmsProvider(mMmsAllContentValues);
5279037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokin        mMockContentResolver.addProvider("mms", mmsProvider);
5289037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokin        mTelephonyBackupAgent.putMmsMessagesToProvider(jsonReader);
5299037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokin        assertEquals(18, mmsProvider.getRowsAdded());
5303aa281731a6f25cd36b88bca809b13d3f581d05fRoman Sorokin        assertEquals(mThreadProvider.mIsThreadArchived, mThreadProvider.mUpdateThreadsArchived);
5319037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokin    }
5329037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokin
5339037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokin    /**
53421736c3871d5c4cd3a6322d65d635057d0a61937Roman Sorokin     * Test with quota exceeded. Checking size of the backup before it hits quota and after.
53521736c3871d5c4cd3a6322d65d635057d0a61937Roman Sorokin     * It still backs up more than a quota since there is meta-info which matters with small amounts
53621736c3871d5c4cd3a6322d65d635057d0a61937Roman Sorokin     * of data. The agent does not take backup meta-info into consideration.
53721736c3871d5c4cd3a6322d65d635057d0a61937Roman Sorokin     * @throws Exception
53821736c3871d5c4cd3a6322d65d635057d0a61937Roman Sorokin     */
53921736c3871d5c4cd3a6322d65d635057d0a61937Roman Sorokin    public void testBackup_WithQuotaExceeded() throws Exception {
5409037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokin        mTelephonyBackupAgent.mMaxMsgPerFile = 1;
54156117b955dda1c134473a4fed4b0a73fb1c6cea2Roman Sorokin        final int backupSize = 7168;
54256117b955dda1c134473a4fed4b0a73fb1c6cea2Roman Sorokin        final int backupSizeAfterFirstQuotaHit = 6144;
54356117b955dda1c134473a4fed4b0a73fb1c6cea2Roman Sorokin        final int backupSizeAfterSecondQuotaHit = 5120;
54421736c3871d5c4cd3a6322d65d635057d0a61937Roman Sorokin
54521736c3871d5c4cd3a6322d65d635057d0a61937Roman Sorokin        mSmsTable.addAll(Arrays.asList(mSmsRows));
54621736c3871d5c4cd3a6322d65d635057d0a61937Roman Sorokin        mMmsTable.addAll(Arrays.asList(mMmsRows));
54721736c3871d5c4cd3a6322d65d635057d0a61937Roman Sorokin
54821736c3871d5c4cd3a6322d65d635057d0a61937Roman Sorokin        FullBackupDataOutput fullBackupDataOutput = new FullBackupDataOutput();
54921736c3871d5c4cd3a6322d65d635057d0a61937Roman Sorokin        mTelephonyBackupAgent.onFullBackup(fullBackupDataOutput);
55021736c3871d5c4cd3a6322d65d635057d0a61937Roman Sorokin        assertEquals(backupSize, fullBackupDataOutput.getSize());
55121736c3871d5c4cd3a6322d65d635057d0a61937Roman Sorokin
55221736c3871d5c4cd3a6322d65d635057d0a61937Roman Sorokin        mTelephonyBackupAgent.onQuotaExceeded(backupSize, backupSize - 100);
55321736c3871d5c4cd3a6322d65d635057d0a61937Roman Sorokin        fullBackupDataOutput = new FullBackupDataOutput();
55421736c3871d5c4cd3a6322d65d635057d0a61937Roman Sorokin        mTelephonyBackupAgent.onFullBackup(fullBackupDataOutput);
55521736c3871d5c4cd3a6322d65d635057d0a61937Roman Sorokin        assertEquals(backupSizeAfterFirstQuotaHit, fullBackupDataOutput.getSize());
55621736c3871d5c4cd3a6322d65d635057d0a61937Roman Sorokin
55721736c3871d5c4cd3a6322d65d635057d0a61937Roman Sorokin        mTelephonyBackupAgent.onQuotaExceeded(backupSizeAfterFirstQuotaHit,
55821736c3871d5c4cd3a6322d65d635057d0a61937Roman Sorokin                backupSizeAfterFirstQuotaHit - 200);
55921736c3871d5c4cd3a6322d65d635057d0a61937Roman Sorokin        fullBackupDataOutput = new FullBackupDataOutput();
56021736c3871d5c4cd3a6322d65d635057d0a61937Roman Sorokin        mTelephonyBackupAgent.onFullBackup(fullBackupDataOutput);
56121736c3871d5c4cd3a6322d65d635057d0a61937Roman Sorokin        assertEquals(backupSizeAfterSecondQuotaHit, fullBackupDataOutput.getSize());
56221736c3871d5c4cd3a6322d65d635057d0a61937Roman Sorokin    }
56321736c3871d5c4cd3a6322d65d635057d0a61937Roman Sorokin
5649037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokin    // Adding random keys to JSON to test handling it by the BackupAgent on restore.
5659037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokin    private String addRandomDataToJson(String jsonString) throws JSONException {
5669037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokin        JSONArray jsonArray = new JSONArray(jsonString);
5679037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokin        JSONArray res = new JSONArray();
5689037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokin        for (int i = 0; i < jsonArray.length(); ++i) {
5699037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokin            JSONObject jsonObject = jsonArray.getJSONObject(i);
5709037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokin            jsonObject.put(UUID.randomUUID().toString(), UUID.randomUUID().toString());
5719037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokin            res = res.put(jsonObject);
5729037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokin        }
5739037d648d61f3d90726e43296f0b12c532e1f934Roman Sorokin        return res.toString();
5741d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin    }
5751d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin
5768b39acf181c547e87161873112d6c52a581fc778Roman Sorokin    /**
5778b39acf181c547e87161873112d6c52a581fc778Roman Sorokin     * class for checking sms insertion into the provider on restore.
5788b39acf181c547e87161873112d6c52a581fc778Roman Sorokin     */
5798b39acf181c547e87161873112d6c52a581fc778Roman Sorokin    private class FakeSmsProvider extends MockContentProvider {
5808b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        private int nextRow = 0;
5818b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        private ContentValues[] mSms;
5828b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
5838b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        public FakeSmsProvider(ContentValues[] sms) {
5848b39acf181c547e87161873112d6c52a581fc778Roman Sorokin            this.mSms = sms;
5858b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        }
5868b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
5878b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        @Override
5888b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        public Uri insert(Uri uri, ContentValues values) {
5898b39acf181c547e87161873112d6c52a581fc778Roman Sorokin            assertEquals(Telephony.Sms.CONTENT_URI, uri);
5908b39acf181c547e87161873112d6c52a581fc778Roman Sorokin            ContentValues modifiedValues = new ContentValues(mSms[nextRow++]);
5918b39acf181c547e87161873112d6c52a581fc778Roman Sorokin            modifiedValues.remove(Telephony.Sms._ID);
5928b39acf181c547e87161873112d6c52a581fc778Roman Sorokin            modifiedValues.put(Telephony.Sms.READ, 1);
5938b39acf181c547e87161873112d6c52a581fc778Roman Sorokin            modifiedValues.put(Telephony.Sms.SEEN, 1);
5948b39acf181c547e87161873112d6c52a581fc778Roman Sorokin            if (mSubId2Phone.get(modifiedValues.getAsInteger(Telephony.Sms.SUBSCRIPTION_ID))
5958b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                    == null) {
5968b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                modifiedValues.put(Telephony.Sms.SUBSCRIPTION_ID, -1);
5978b39acf181c547e87161873112d6c52a581fc778Roman Sorokin            }
5988b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
59956117b955dda1c134473a4fed4b0a73fb1c6cea2Roman Sorokin            if (modifiedValues.get(Telephony.Sms.ADDRESS) == null) {
60056117b955dda1c134473a4fed4b0a73fb1c6cea2Roman Sorokin                modifiedValues.put(Telephony.Sms.ADDRESS, TelephonyBackupAgent.UNKNOWN_SENDER);
60156117b955dda1c134473a4fed4b0a73fb1c6cea2Roman Sorokin            }
60256117b955dda1c134473a4fed4b0a73fb1c6cea2Roman Sorokin
6038b39acf181c547e87161873112d6c52a581fc778Roman Sorokin            assertEquals(modifiedValues, values);
6048b39acf181c547e87161873112d6c52a581fc778Roman Sorokin            return null;
6058b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        }
6068b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
6078b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        @Override
60821736c3871d5c4cd3a6322d65d635057d0a61937Roman Sorokin        public int bulkInsert(Uri uri, ContentValues[] values) {
60921736c3871d5c4cd3a6322d65d635057d0a61937Roman Sorokin            for (ContentValues cv : values) {
61021736c3871d5c4cd3a6322d65d635057d0a61937Roman Sorokin                insert(uri, cv);
61121736c3871d5c4cd3a6322d65d635057d0a61937Roman Sorokin            }
61221736c3871d5c4cd3a6322d65d635057d0a61937Roman Sorokin            return values.length;
61321736c3871d5c4cd3a6322d65d635057d0a61937Roman Sorokin        }
61421736c3871d5c4cd3a6322d65d635057d0a61937Roman Sorokin
61521736c3871d5c4cd3a6322d65d635057d0a61937Roman Sorokin        @Override
6168b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
6178b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                            String sortOrder) {
6188b39acf181c547e87161873112d6c52a581fc778Roman Sorokin            return null;
6198b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        }
6208b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
6218b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        public int getRowsAdded() {
6228b39acf181c547e87161873112d6c52a581fc778Roman Sorokin            return nextRow;
6238b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        }
6248b39acf181c547e87161873112d6c52a581fc778Roman Sorokin    }
6258b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
6268b39acf181c547e87161873112d6c52a581fc778Roman Sorokin    /**
6278b39acf181c547e87161873112d6c52a581fc778Roman Sorokin     * class for checking mms insertion into the provider on restore.
6288b39acf181c547e87161873112d6c52a581fc778Roman Sorokin     */
6298b39acf181c547e87161873112d6c52a581fc778Roman Sorokin    private class FakeMmsProvider extends MockContentProvider {
6308b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        private int nextRow = 0;
6318b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        private List<ContentValues> mValues;
6328b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        private long mDummyMsgId = -1;
6338b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        private long mMsgId = -1;
6348b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
6358b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        public FakeMmsProvider(List<ContentValues> values) {
6368b39acf181c547e87161873112d6c52a581fc778Roman Sorokin            this.mValues = values;
6378b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        }
6388b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
6398b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        @Override
6408b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        public Uri insert(Uri uri, ContentValues values) {
6418b39acf181c547e87161873112d6c52a581fc778Roman Sorokin            Uri retUri = Uri.parse("dummy_uri");
6428b39acf181c547e87161873112d6c52a581fc778Roman Sorokin            ContentValues modifiedValues = new ContentValues(mValues.get(nextRow++));
6438b39acf181c547e87161873112d6c52a581fc778Roman Sorokin            if (APP_SMIL.equals(values.get(Telephony.Mms.Part.CONTENT_TYPE))) {
6448b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                // Smil part.
6458b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                assertEquals(-1, mDummyMsgId);
6468b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                mDummyMsgId = values.getAsLong(Telephony.Mms.Part.MSG_ID);
6478b39acf181c547e87161873112d6c52a581fc778Roman Sorokin            }
6488b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
6498b39acf181c547e87161873112d6c52a581fc778Roman Sorokin            if (values.get(Telephony.Mms.Part.SEQ) != null) {
6508b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                // Part of mms.
6518b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                final Uri expectedUri = Telephony.Mms.CONTENT_URI.buildUpon()
6528b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                        .appendPath(String.valueOf(mDummyMsgId))
6538b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                        .appendPath("part")
6548b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                        .build();
6558b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                assertEquals(expectedUri, uri);
6568b39acf181c547e87161873112d6c52a581fc778Roman Sorokin            }
6578b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
6588b39acf181c547e87161873112d6c52a581fc778Roman Sorokin            if (values.get(Telephony.Mms.Part.MSG_ID) != null) {
6598b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                modifiedValues.put(Telephony.Mms.Part.MSG_ID, mDummyMsgId);
6608b39acf181c547e87161873112d6c52a581fc778Roman Sorokin            }
6618b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
6628b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
6638b39acf181c547e87161873112d6c52a581fc778Roman Sorokin            if (values.get(Telephony.Mms.SUBSCRIPTION_ID) != null) {
6648b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                assertEquals(Telephony.Mms.CONTENT_URI, uri);
6658b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                if (mSubId2Phone.get(modifiedValues.getAsInteger(Telephony.Sms.SUBSCRIPTION_ID))
6668b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                        == null) {
6678b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                    modifiedValues.put(Telephony.Sms.SUBSCRIPTION_ID, -1);
6688b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                }
6698b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                // Mms.
6708b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                modifiedValues.put(Telephony.Mms.READ, 1);
6718b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                modifiedValues.put(Telephony.Mms.SEEN, 1);
6728b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                mMsgId = modifiedValues.getAsInteger(BaseColumns._ID);
6738b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                retUri = Uri.withAppendedPath(Telephony.Mms.CONTENT_URI, String.valueOf(mMsgId));
6748b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                modifiedValues.remove(BaseColumns._ID);
6758b39acf181c547e87161873112d6c52a581fc778Roman Sorokin            }
6768b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
6778b39acf181c547e87161873112d6c52a581fc778Roman Sorokin            if (values.get(Telephony.Mms.Addr.ADDRESS) != null) {
6788b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                // Address.
6798b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                final Uri expectedUri = Telephony.Mms.CONTENT_URI.buildUpon()
6808b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                        .appendPath(String.valueOf(mMsgId))
6818b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                        .appendPath("addr")
6828b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                        .build();
6838b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                assertEquals(expectedUri, uri);
6848b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                assertNotSame(-1, mMsgId);
6858b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                modifiedValues.put(Telephony.Mms.Addr.MSG_ID, mMsgId);
6868b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                mDummyMsgId = -1;
6878b39acf181c547e87161873112d6c52a581fc778Roman Sorokin            }
6888b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
6898b39acf181c547e87161873112d6c52a581fc778Roman Sorokin            for (String key : modifiedValues.keySet()) {
69076422e0ed1bc5b68f857094a05b5fec8b507f36eRoman Sorokin                assertEquals("Key:"+key, modifiedValues.get(key), values.get(key));
6918b39acf181c547e87161873112d6c52a581fc778Roman Sorokin            }
6928b39acf181c547e87161873112d6c52a581fc778Roman Sorokin            assertEquals(modifiedValues.size(), values.size());
6938b39acf181c547e87161873112d6c52a581fc778Roman Sorokin            return retUri;
6948b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        }
6958b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
6968b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        @Override
6978b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
6988b39acf181c547e87161873112d6c52a581fc778Roman Sorokin            final Uri expectedUri = Telephony.Mms.CONTENT_URI.buildUpon()
6998b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                    .appendPath(String.valueOf(mDummyMsgId))
7008b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                    .appendPath("part")
7018b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                    .build();
7028b39acf181c547e87161873112d6c52a581fc778Roman Sorokin            assertEquals(expectedUri, uri);
7038b39acf181c547e87161873112d6c52a581fc778Roman Sorokin            ContentValues expected = new ContentValues();
7048b39acf181c547e87161873112d6c52a581fc778Roman Sorokin            expected.put(Telephony.Mms.Part.MSG_ID, mMsgId);
7058b39acf181c547e87161873112d6c52a581fc778Roman Sorokin            assertEquals(expected, values);
7068b39acf181c547e87161873112d6c52a581fc778Roman Sorokin            return 2;
7078b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        }
7088b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
7098b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        @Override
7108b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
7118b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                            String sortOrder) {
7128b39acf181c547e87161873112d6c52a581fc778Roman Sorokin            return null;
7138b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        }
7148b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
7158b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        public int getRowsAdded() {
7168b39acf181c547e87161873112d6c52a581fc778Roman Sorokin            return nextRow;
7178b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        }
7188b39acf181c547e87161873112d6c52a581fc778Roman Sorokin    }
7198b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
7208b39acf181c547e87161873112d6c52a581fc778Roman Sorokin    /**
7218b39acf181c547e87161873112d6c52a581fc778Roman Sorokin     * class that implements MmsSms provider for thread ids.
7228b39acf181c547e87161873112d6c52a581fc778Roman Sorokin     */
7238b39acf181c547e87161873112d6c52a581fc778Roman Sorokin    private static class ThreadProvider extends MockContentProvider {
7241d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin        ArrayList<Set<Integer> > id2Thread = new ArrayList<>();
7251d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin        ArrayList<String> id2Recipient = new ArrayList<>();
7263aa281731a6f25cd36b88bca809b13d3f581d05fRoman Sorokin        Set<Integer> mIsThreadArchived = new HashSet<>();
7273aa281731a6f25cd36b88bca809b13d3f581d05fRoman Sorokin        Set<Integer> mUpdateThreadsArchived = new HashSet<>();
7283aa281731a6f25cd36b88bca809b13d3f581d05fRoman Sorokin
7291d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin
7301d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin        public int getOrCreateThreadId(final String[] recipients) {
73156117b955dda1c134473a4fed4b0a73fb1c6cea2Roman Sorokin            if (recipients == null || recipients.length == 0) {
73256117b955dda1c134473a4fed4b0a73fb1c6cea2Roman Sorokin                throw new IllegalArgumentException("Unable to find or allocate a thread ID.");
73356117b955dda1c134473a4fed4b0a73fb1c6cea2Roman Sorokin            }
73456117b955dda1c134473a4fed4b0a73fb1c6cea2Roman Sorokin
7351d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin            Set<Integer> ids = new ArraySet<>();
7361d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin            for (String rec : recipients) {
7371d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin                if (!id2Recipient.contains(rec)) {
7381d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin                    id2Recipient.add(rec);
7391d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin                }
7401d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin                ids.add(id2Recipient.indexOf(rec)+1);
7411d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin            }
7421d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin            if (!id2Thread.contains(ids)) {
7431d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin                id2Thread.add(ids);
7441d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin            }
7451d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin            return id2Thread.indexOf(ids)+1;
7461d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin        }
7478b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
7483aa281731a6f25cd36b88bca809b13d3f581d05fRoman Sorokin        public void setArchived(int threadId) {
7493aa281731a6f25cd36b88bca809b13d3f581d05fRoman Sorokin            mIsThreadArchived.add(threadId);
7503aa281731a6f25cd36b88bca809b13d3f581d05fRoman Sorokin        }
7513aa281731a6f25cd36b88bca809b13d3f581d05fRoman Sorokin
7521d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin        private String getSpaceSepIds(int threadId) {
75356117b955dda1c134473a4fed4b0a73fb1c6cea2Roman Sorokin            if (id2Thread.size() < threadId) {
75456117b955dda1c134473a4fed4b0a73fb1c6cea2Roman Sorokin                return null;
75556117b955dda1c134473a4fed4b0a73fb1c6cea2Roman Sorokin            }
75656117b955dda1c134473a4fed4b0a73fb1c6cea2Roman Sorokin
7571d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin            String spaceSepIds = null;
7581d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin            for (Integer id : id2Thread.get(threadId-1)) {
7591d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin                spaceSepIds = (spaceSepIds == null ? "" : spaceSepIds + " ") + String.valueOf(id);
7601d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin            }
7611d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin            return spaceSepIds;
7621d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin        }
7638b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
7641d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin        private String getRecipient(int recipientId) {
7651d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin            return id2Recipient.get(recipientId-1);
7668b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        }
7678b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
7688b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        @Override
7698b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
7708b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                            String sortOrder) {
7711d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin            if (uri.equals(TelephonyBackupAgent.ALL_THREADS_URI)) {
7721d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin                final int threadId = Integer.parseInt(selectionArgs[0]);
7731d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin                final String spaceSepIds = getSpaceSepIds(threadId);
7741d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin                List<ContentValues> table = new ArrayList<>();
7751d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin                ContentValues row = new ContentValues();
7761d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin                row.put(Telephony.Threads.RECIPIENT_IDS, spaceSepIds);
7771d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin                table.add(row);
7781d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin                return new FakeCursor(table, projection);
7793aa281731a6f25cd36b88bca809b13d3f581d05fRoman Sorokin            } else if (uri.toString().startsWith(Telephony.Threads.CONTENT_URI.toString())) {
7803aa281731a6f25cd36b88bca809b13d3f581d05fRoman Sorokin                assertEquals(1, projection.length);
7813aa281731a6f25cd36b88bca809b13d3f581d05fRoman Sorokin                assertEquals(Telephony.Threads.ARCHIVED, projection[0]);
7823aa281731a6f25cd36b88bca809b13d3f581d05fRoman Sorokin                List<String> segments = uri.getPathSegments();
7833aa281731a6f25cd36b88bca809b13d3f581d05fRoman Sorokin                final int threadId = Integer.parseInt(segments.get(segments.size() - 2));
7843aa281731a6f25cd36b88bca809b13d3f581d05fRoman Sorokin                List<ContentValues> table = new ArrayList<>();
7853aa281731a6f25cd36b88bca809b13d3f581d05fRoman Sorokin                ContentValues row = new ContentValues();
7863aa281731a6f25cd36b88bca809b13d3f581d05fRoman Sorokin                row.put(Telephony.Threads.ARCHIVED, mIsThreadArchived.contains(threadId) ? 1 : 0);
7873aa281731a6f25cd36b88bca809b13d3f581d05fRoman Sorokin                table.add(row);
7883aa281731a6f25cd36b88bca809b13d3f581d05fRoman Sorokin                return new FakeCursor(table, projection);
7891d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin            } else if (uri.toString().startsWith(
7901d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin                    TelephonyBackupAgent.SINGLE_CANONICAL_ADDRESS_URI.toString())) {
7911d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin                final int recipientId = (int)ContentUris.parseId(uri);
7921d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin                final String recipient = getRecipient(recipientId);
7931d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin                List<ContentValues> table = new ArrayList<>();
7941d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin                ContentValues row = new ContentValues();
7951d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin                row.put(Telephony.CanonicalAddressesColumns.ADDRESS, recipient);
7961d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin                table.add(row);
7971d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin
7981d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin                return new FakeCursor(table,
7991d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin                        projection != null
8001d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin                                ? projection
8011d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin                                : new String[] { Telephony.CanonicalAddressesColumns.ADDRESS });
8021d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin            } else if (uri.toString().startsWith(
8031d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin                    TelephonyBackupAgent.THREAD_ID_CONTENT_URI.toString())) {
8041d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin                List<String> recipients = uri.getQueryParameters("recipient");
8051d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin
8061d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin                final int threadId =
8071d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin                        getOrCreateThreadId(recipients.toArray(new String[recipients.size()]));
8081d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin                List<ContentValues> table = new ArrayList<>();
8091d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin                ContentValues row = new ContentValues();
8101d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin                row.put(BaseColumns._ID, String.valueOf(threadId));
8111d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin                table.add(row);
8121d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin                return new FakeCursor(table, projection);
8133aa281731a6f25cd36b88bca809b13d3f581d05fRoman Sorokin            } else {
8143aa281731a6f25cd36b88bca809b13d3f581d05fRoman Sorokin                fail("Unknown URI");
8153aa281731a6f25cd36b88bca809b13d3f581d05fRoman Sorokin            }
8161d42223c7e497b5513fa0cc5e65ffc405b432989Roman Sorokin            return null;
8178b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        }
8183aa281731a6f25cd36b88bca809b13d3f581d05fRoman Sorokin
8193aa281731a6f25cd36b88bca809b13d3f581d05fRoman Sorokin        @Override
8203aa281731a6f25cd36b88bca809b13d3f581d05fRoman Sorokin        public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
8213aa281731a6f25cd36b88bca809b13d3f581d05fRoman Sorokin            assertEquals(uri, Telephony.Threads.CONTENT_URI);
8223aa281731a6f25cd36b88bca809b13d3f581d05fRoman Sorokin            assertEquals(values.getAsInteger(Telephony.Threads.ARCHIVED).intValue(), 1);
8233aa281731a6f25cd36b88bca809b13d3f581d05fRoman Sorokin            final int threadId = Integer.parseInt(selectionArgs[0]);
8243aa281731a6f25cd36b88bca809b13d3f581d05fRoman Sorokin            mUpdateThreadsArchived.add(threadId);
8253aa281731a6f25cd36b88bca809b13d3f581d05fRoman Sorokin            return 1;
8263aa281731a6f25cd36b88bca809b13d3f581d05fRoman Sorokin        }
8278b39acf181c547e87161873112d6c52a581fc778Roman Sorokin    }
8288b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
8298b39acf181c547e87161873112d6c52a581fc778Roman Sorokin    /**
8308b39acf181c547e87161873112d6c52a581fc778Roman Sorokin     * general cursor for serving queries.
8318b39acf181c547e87161873112d6c52a581fc778Roman Sorokin     */
8328b39acf181c547e87161873112d6c52a581fc778Roman Sorokin    private static class FakeCursor extends MockCursor {
8338b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        String[] projection;
8348b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        List<ContentValues> rows;
83521736c3871d5c4cd3a6322d65d635057d0a61937Roman Sorokin        int nextRow = 0;
8368b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
8378b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        public FakeCursor(List<ContentValues> rows, String[] projection) {
8388b39acf181c547e87161873112d6c52a581fc778Roman Sorokin            this.projection = projection;
8398b39acf181c547e87161873112d6c52a581fc778Roman Sorokin            this.rows = rows;
8408b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        }
8418b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
8428b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        public void setProjection(String[] projection) {
8438b39acf181c547e87161873112d6c52a581fc778Roman Sorokin            this.projection = projection;
8448b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        }
8458b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
8468b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        @Override
8478b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        public int getColumnCount() {
8488b39acf181c547e87161873112d6c52a581fc778Roman Sorokin            return projection.length;
8498b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        }
8508b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
8518b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        @Override
8528b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        public String getColumnName(int columnIndex) {
8538b39acf181c547e87161873112d6c52a581fc778Roman Sorokin            return projection[columnIndex];
8548b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        }
8558b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
8568b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        @Override
8578b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        public String getString(int columnIndex) {
8588b39acf181c547e87161873112d6c52a581fc778Roman Sorokin            return rows.get(nextRow).getAsString(projection[columnIndex]);
8598b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        }
8608b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
8618b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        @Override
8628b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        public int getInt(int columnIndex) {
8638b39acf181c547e87161873112d6c52a581fc778Roman Sorokin            return rows.get(nextRow).getAsInteger(projection[columnIndex]);
8648b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        }
8658b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
8668b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        @Override
8678b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        public long getLong(int columnIndex) {
8688b39acf181c547e87161873112d6c52a581fc778Roman Sorokin            return rows.get(nextRow).getAsLong(projection[columnIndex]);
8698b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        }
8708b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
8718b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        @Override
8728b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        public boolean isAfterLast() {
8738b39acf181c547e87161873112d6c52a581fc778Roman Sorokin            return nextRow >= getCount();
8748b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        }
8758b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
8768b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        @Override
8778b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        public boolean isLast() {
8788b39acf181c547e87161873112d6c52a581fc778Roman Sorokin            return nextRow == getCount() - 1;
8798b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        }
8808b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
8818b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        @Override
8828b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        public boolean moveToFirst() {
8838b39acf181c547e87161873112d6c52a581fc778Roman Sorokin            nextRow = 0;
8848b39acf181c547e87161873112d6c52a581fc778Roman Sorokin            return getCount() > 0;
8858b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        }
8868b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
8878b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        @Override
8888b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        public boolean moveToNext() {
8898b39acf181c547e87161873112d6c52a581fc778Roman Sorokin            return getCount() > ++nextRow;
8908b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        }
8918b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
8928b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        @Override
8938b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        public int getCount() {
8948b39acf181c547e87161873112d6c52a581fc778Roman Sorokin            return rows.size();
8958b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        }
8968b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
8978b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        @Override
8988b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        public int getColumnIndex(String columnName) {
8998b39acf181c547e87161873112d6c52a581fc778Roman Sorokin            for (int i=0; i<projection.length; ++i) {
9008b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                if (columnName.equals(projection[i])) {
9018b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                    return i;
9028b39acf181c547e87161873112d6c52a581fc778Roman Sorokin                }
9038b39acf181c547e87161873112d6c52a581fc778Roman Sorokin            }
9048b39acf181c547e87161873112d6c52a581fc778Roman Sorokin            return -1;
9058b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        }
9068b39acf181c547e87161873112d6c52a581fc778Roman Sorokin
9078b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        @Override
9088b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        public void close() {
9098b39acf181c547e87161873112d6c52a581fc778Roman Sorokin        }
9108b39acf181c547e87161873112d6c52a581fc778Roman Sorokin    }
9118b39acf181c547e87161873112d6c52a581fc778Roman Sorokin}
912