1b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki/*
2b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki * Copyright (C) 2010 The Android Open Source Project
3b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki *
4b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki * Licensed under the Apache License, Version 2.0 (the "License");
5b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki * you may not use this file except in compliance with the License.
6b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki * You may obtain a copy of the License at
7b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki *
8b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki *      http://www.apache.org/licenses/LICENSE-2.0
9b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki *
10b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki * Unless required by applicable law or agreed to in writing, software
11b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki * distributed under the License is distributed on an "AS IS" BASIS,
12b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki * See the License for the specific language governing permissions and
14b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki * limitations under the License.
15b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki */
16b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki
17b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onukipackage com.android.email.activity;
18b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki
19b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onukiimport com.android.email.activity.ContactStatusLoader.Result;
207fdde9bb4a24e931618a7a64227e2194c89034daScott Kennedyimport com.android.mail.utils.MatrixCursorWithCachedColumns;
21b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki
22b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onukiimport android.content.Context;
23b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onukiimport android.content.pm.ProviderInfo;
24b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onukiimport android.database.Cursor;
25b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onukiimport android.database.MatrixCursor;
26b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onukiimport android.graphics.Bitmap;
27b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onukiimport android.net.Uri;
28b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onukiimport android.provider.ContactsContract;
29b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onukiimport android.provider.ContactsContract.StatusUpdates;
30b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onukiimport android.test.ProviderTestCase2;
31b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onukiimport android.test.mock.MockContentProvider;
323555dc03bf2243dc275c9c832702abbee3b64387Jerry Xieimport android.test.suitebuilder.annotation.SmallTest;
33b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki
34b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onukiimport java.io.ByteArrayOutputStream;
35b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onukiimport java.util.ArrayList;
36b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onukiimport java.util.Queue;
37b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onukiimport java.util.concurrent.LinkedBlockingQueue;
38b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki
39b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onukiimport junit.framework.Assert;
40b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki
41b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki/**
42b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki * Test for {@link ContactStatusLoader}
43b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki *
44b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki * Unfortunately this doesn't check {@link ContactStatusLoader.Result#mLookupUri}, because we don't
45b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki * (shouldn't) know how {@link android.provider.ContactsContract.Data#getContactLookupUri} is
46b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki * implemented.
47b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki */
483555dc03bf2243dc275c9c832702abbee3b64387Jerry Xie@SmallTest
49b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onukipublic class ContactStatusLoaderTest
50b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        extends ProviderTestCase2<ContactStatusLoaderTest.MockContactProvider> {
51b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki    private static final String EMAIL = "a@b.c";
52b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki
53b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki    private MockContactProvider mProvider;
54b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki
55b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki    public ContactStatusLoaderTest() {
56b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        super(MockContactProvider.class, ContactsContract.AUTHORITY);
57b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki    }
58b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki
59b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki    @Override
60b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki    protected void setUp() throws Exception {
61b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        super.setUp();
62b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        mProvider = getProvider();
63b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki    }
64b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki
65b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki    // Contact doesn't exist
667037a0bd3d8e925a9115f475f5c0d05ddae2eeeeJerry Xie    public void brokentestContactNotFound() {
67b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        // Insert empty cursor
687fdde9bb4a24e931618a7a64227e2194c89034daScott Kennedy        mProvider.mCursors.offer(new MatrixCursorWithCachedColumns(
697fdde9bb4a24e931618a7a64227e2194c89034daScott Kennedy                ContactStatusLoader.PROJECTION_PHOTO_ID_PRESENCE));
70b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki
71b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        // Load!
72b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        ContactStatusLoader l = new ContactStatusLoader(getMockContext(), EMAIL);
73b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        Result r = l.loadInBackground();
74b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki
75b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        // Check input to the provider
76b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        assertEquals(1, mProvider.mUris.size());
77b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        assertEquals("content://com.android.contacts/data/emails/lookup/a%40b.c",
78b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki                mProvider.mUris.get(0));
79b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki
80b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        // Check result
81b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        assertNull(r.mPhoto);
82b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        assertEquals(ContactStatusLoader.PRESENCE_UNKNOWN_RESOURCE_ID, r.mPresenceResId);
83b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki    }
84b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki
85b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki    // Contact doesn't exist -- provider returns null for the first query
867037a0bd3d8e925a9115f475f5c0d05ddae2eeeeJerry Xie    public void brokentestNull() {
87b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        // No cursor prepared. (Mock provider will return null)
88b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki
89b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        // Load!
90b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        ContactStatusLoader l = new ContactStatusLoader(getMockContext(), EMAIL);
91b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        Result r = l.loadInBackground();
92b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki
93b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        // Check result
94b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        assertNull(r.mPhoto);
95b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        assertEquals(ContactStatusLoader.PRESENCE_UNKNOWN_RESOURCE_ID, r.mPresenceResId);
96b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki    }
97b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki
98b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki    // Contact exists, but no photo
997037a0bd3d8e925a9115f475f5c0d05ddae2eeeeJerry Xie    public void brokentestNoPhoto() {
100b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        // Result for the first query (the one for photo-id)
1017fdde9bb4a24e931618a7a64227e2194c89034daScott Kennedy        MatrixCursor cursor1 =
1027fdde9bb4a24e931618a7a64227e2194c89034daScott Kennedy                new MatrixCursorWithCachedColumns(ContactStatusLoader.PROJECTION_PHOTO_ID_PRESENCE);
103b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        cursor1.addRow(new Object[]{12345, StatusUpdates.AWAY});
104b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        mProvider.mCursors.offer(cursor1);
105b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki
106b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        // Empty cursor for the second query
1077fdde9bb4a24e931618a7a64227e2194c89034daScott Kennedy        mProvider.mCursors.offer(
1087fdde9bb4a24e931618a7a64227e2194c89034daScott Kennedy                new MatrixCursorWithCachedColumns(ContactStatusLoader.PHOTO_PROJECTION));
109b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki
110b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        // Load!
111b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        ContactStatusLoader l = new ContactStatusLoader(getMockContext(), EMAIL);
112b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        Result r = l.loadInBackground();
113b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki
114b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        // Check input to the provider
115b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        // We should have had at least two queries from loadInBackground.
116b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        // There can be extra queries from getContactLookupUri(), but this test shouldn't know
117b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        // the details, so use ">= 2".
118b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        assertTrue(mProvider.mUris.size() >= 2);
119b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        assertEquals("content://com.android.contacts/data/emails/lookup/a%40b.c",
120b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki                mProvider.mUris.get(0));
1217093746dd5017b1dacb726eb7b083922de15612eMakoto Onuki        assertEquals("content://com.android.contacts/data/12345",
122b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki                mProvider.mUris.get(1));
123b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki
124b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        // Check result
125b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        assertNull(r.mPhoto); // no photo
126b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        assertEquals(android.R.drawable.presence_away, r.mPresenceResId);
127b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki    }
128b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki
129b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki    // Contact exists, but no photo (provider returns null for the second query)
1307037a0bd3d8e925a9115f475f5c0d05ddae2eeeeJerry Xie    public void brokentestNull2() {
131b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        // Result for the first query (the one for photo-id)
1327fdde9bb4a24e931618a7a64227e2194c89034daScott Kennedy        MatrixCursor cursor1 =
1337fdde9bb4a24e931618a7a64227e2194c89034daScott Kennedy                new MatrixCursorWithCachedColumns(ContactStatusLoader.PROJECTION_PHOTO_ID_PRESENCE);
134b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        cursor1.addRow(new Object[]{12345, StatusUpdates.AWAY});
135b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        mProvider.mCursors.offer(cursor1);
136b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki
137b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        // No cursor for the second query
138b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki
139b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        // Load!
140b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        ContactStatusLoader l = new ContactStatusLoader(getMockContext(), EMAIL);
141b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        Result r = l.loadInBackground();
142b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki
143b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        // Check result
144b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        assertNull(r.mPhoto); // no photo
145b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        assertEquals(android.R.drawable.presence_away, r.mPresenceResId);
146b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki    }
147b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki
148b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki    // Contact exists, with a photo
1497037a0bd3d8e925a9115f475f5c0d05ddae2eeeeJerry Xie    public void brokentestWithPhoto() {
150b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        // Result for the first query (the one for photo-id)
1517fdde9bb4a24e931618a7a64227e2194c89034daScott Kennedy        MatrixCursor cursor1 =
1527fdde9bb4a24e931618a7a64227e2194c89034daScott Kennedy                new MatrixCursorWithCachedColumns(ContactStatusLoader.PROJECTION_PHOTO_ID_PRESENCE);
153b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        cursor1.addRow(new Object[]{12345, StatusUpdates.AWAY});
154b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        mProvider.mCursors.offer(cursor1);
155b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki
156b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        // Prepare for the second query.
157b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        MatrixCursor cursor2 = new PhotoCursor(createJpegData(10, 20));
158b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        mProvider.mCursors.offer(cursor2);
159b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki
160b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        // Load!
161b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        ContactStatusLoader l = new ContactStatusLoader(getMockContext(), EMAIL);
162b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        Result r = l.loadInBackground();
163b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki
164b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        // Check result
165b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        assertNotNull(r.mPhoto);
166b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        assertEquals(10, r.mPhoto.getWidth());
167b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        assertEquals(android.R.drawable.presence_away, r.mPresenceResId);
168b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki    }
169b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki
170b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki    private static byte[] createJpegData(int width, int height) {
171b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
172b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        ByteArrayOutputStream out = new ByteArrayOutputStream();
173b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        bitmap.compress(Bitmap.CompressFormat.JPEG, 50, out);
174b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        return out.toByteArray();
175b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki    }
176b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki
177b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki    // MatrixCursor doesn't support getBlob, so use this...
1787fdde9bb4a24e931618a7a64227e2194c89034daScott Kennedy    private static class PhotoCursor extends MatrixCursorWithCachedColumns {
179b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        private final byte[] mBlob;
180b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki
181b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        public PhotoCursor(byte[] blob) {
182b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki            super(ContactStatusLoader.PHOTO_PROJECTION);
183b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki            mBlob = blob;
184b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki            addRow(new Object[] {null}); // Add dummy row
185b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        }
186b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki
187b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        @Override
188b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        public byte[] getBlob(int column) {
189b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki            Assert.assertEquals(0, column);
190b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki            return mBlob;
191b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        }
192b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki    }
193b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki
194b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki    public static class MockContactProvider extends MockContentProvider {
195b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        public ArrayList<String> mUris = new ArrayList<String>();
196b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki
197b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        public final Queue<Cursor> mCursors = new LinkedBlockingQueue<Cursor>();
198b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki
199b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        @Override
200b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
201b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki                String sortOrder) {
202b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki            mUris.add(uri.toString());
203b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki            return mCursors.poll();
204b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        }
205b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki
206b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        @Override
207b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        public void attachInfo(Context context, ProviderInfo info) {
208b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        }
209b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki    }
210b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki}
211