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;
20b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki
21b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onukiimport android.content.Context;
22b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onukiimport android.content.pm.ProviderInfo;
23b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onukiimport android.database.Cursor;
24b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onukiimport android.database.MatrixCursor;
25b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onukiimport android.graphics.Bitmap;
26b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onukiimport android.net.Uri;
27b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onukiimport android.provider.ContactsContract;
28b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onukiimport android.provider.ContactsContract.StatusUpdates;
29b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onukiimport android.test.ProviderTestCase2;
30b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onukiimport android.test.mock.MockContentProvider;
31b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki
32b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onukiimport java.io.ByteArrayOutputStream;
33b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onukiimport java.util.ArrayList;
34b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onukiimport java.util.Queue;
35b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onukiimport java.util.concurrent.LinkedBlockingQueue;
36b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki
37b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onukiimport junit.framework.Assert;
38b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki
39b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki/**
40b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki * Test for {@link ContactStatusLoader}
41b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki *
42b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki * Unfortunately this doesn't check {@link ContactStatusLoader.Result#mLookupUri}, because we don't
43b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki * (shouldn't) know how {@link android.provider.ContactsContract.Data#getContactLookupUri} is
44b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki * implemented.
45b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki */
46b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onukipublic class ContactStatusLoaderTest
47b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        extends ProviderTestCase2<ContactStatusLoaderTest.MockContactProvider> {
48b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki    private static final String EMAIL = "a@b.c";
49b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki
50b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki    private MockContactProvider mProvider;
51b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki
52b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki    public ContactStatusLoaderTest() {
53b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        super(MockContactProvider.class, ContactsContract.AUTHORITY);
54b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki    }
55b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki
56b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki    @Override
57b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki    protected void setUp() throws Exception {
58b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        super.setUp();
59b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        mProvider = getProvider();
60b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki    }
61b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki
62b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki    // Contact doesn't exist
63b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki    public void testContactNotFound() {
64b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        // Insert empty cursor
65b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        mProvider.mCursors.offer(
66b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki                new MatrixCursor(ContactStatusLoader.PROJECTION_PHOTO_ID_PRESENCE));
67b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki
68b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        // Load!
69b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        ContactStatusLoader l = new ContactStatusLoader(getMockContext(), EMAIL);
70b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        Result r = l.loadInBackground();
71b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki
72b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        // Check input to the provider
73b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        assertEquals(1, mProvider.mUris.size());
74b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        assertEquals("content://com.android.contacts/data/emails/lookup/a%40b.c",
75b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki                mProvider.mUris.get(0));
76b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki
77b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        // Check result
78b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        assertNull(r.mPhoto);
79b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        assertEquals(ContactStatusLoader.PRESENCE_UNKNOWN_RESOURCE_ID, r.mPresenceResId);
80b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki    }
81b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki
82b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki    // Contact doesn't exist -- provider returns null for the first query
83b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki    public void testNull() {
84b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        // No cursor prepared. (Mock provider will return null)
85b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki
86b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        // Load!
87b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        ContactStatusLoader l = new ContactStatusLoader(getMockContext(), EMAIL);
88b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        Result r = l.loadInBackground();
89b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki
90b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        // Check result
91b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        assertNull(r.mPhoto);
92b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        assertEquals(ContactStatusLoader.PRESENCE_UNKNOWN_RESOURCE_ID, r.mPresenceResId);
93b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki    }
94b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki
95b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki    // Contact exists, but no photo
96b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki    public void testNoPhoto() {
97b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        // Result for the first query (the one for photo-id)
98b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        MatrixCursor cursor1 = new MatrixCursor(ContactStatusLoader.PROJECTION_PHOTO_ID_PRESENCE);
99b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        cursor1.addRow(new Object[]{12345, StatusUpdates.AWAY});
100b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        mProvider.mCursors.offer(cursor1);
101b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki
102b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        // Empty cursor for the second query
103b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        mProvider.mCursors.offer(new MatrixCursor(ContactStatusLoader.PHOTO_PROJECTION));
104b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki
105b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        // Load!
106b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        ContactStatusLoader l = new ContactStatusLoader(getMockContext(), EMAIL);
107b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        Result r = l.loadInBackground();
108b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki
109b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        // Check input to the provider
110b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        // We should have had at least two queries from loadInBackground.
111b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        // There can be extra queries from getContactLookupUri(), but this test shouldn't know
112b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        // the details, so use ">= 2".
113b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        assertTrue(mProvider.mUris.size() >= 2);
114b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        assertEquals("content://com.android.contacts/data/emails/lookup/a%40b.c",
115b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki                mProvider.mUris.get(0));
1167093746dd5017b1dacb726eb7b083922de15612eMakoto Onuki        assertEquals("content://com.android.contacts/data/12345",
117b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki                mProvider.mUris.get(1));
118b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki
119b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        // Check result
120b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        assertNull(r.mPhoto); // no photo
121b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        assertEquals(android.R.drawable.presence_away, r.mPresenceResId);
122b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki    }
123b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki
124b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki    // Contact exists, but no photo (provider returns null for the second query)
125b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki    public void testNull2() {
126b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        // Result for the first query (the one for photo-id)
127b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        MatrixCursor cursor1 = new MatrixCursor(ContactStatusLoader.PROJECTION_PHOTO_ID_PRESENCE);
128b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        cursor1.addRow(new Object[]{12345, StatusUpdates.AWAY});
129b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        mProvider.mCursors.offer(cursor1);
130b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki
131b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        // No cursor for the second query
132b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki
133b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        // Load!
134b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        ContactStatusLoader l = new ContactStatusLoader(getMockContext(), EMAIL);
135b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        Result r = l.loadInBackground();
136b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki
137b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        // Check result
138b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        assertNull(r.mPhoto); // no photo
139b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        assertEquals(android.R.drawable.presence_away, r.mPresenceResId);
140b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki    }
141b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki
142b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki    // Contact exists, with a photo
143b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki    public void testWithPhoto() {
144b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        // Result for the first query (the one for photo-id)
145b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        MatrixCursor cursor1 = new MatrixCursor(ContactStatusLoader.PROJECTION_PHOTO_ID_PRESENCE);
146b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        cursor1.addRow(new Object[]{12345, StatusUpdates.AWAY});
147b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        mProvider.mCursors.offer(cursor1);
148b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki
149b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        // Prepare for the second query.
150b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        MatrixCursor cursor2 = new PhotoCursor(createJpegData(10, 20));
151b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        mProvider.mCursors.offer(cursor2);
152b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki
153b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        // Load!
154b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        ContactStatusLoader l = new ContactStatusLoader(getMockContext(), EMAIL);
155b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        Result r = l.loadInBackground();
156b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki
157b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        // Check result
158b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        assertNotNull(r.mPhoto);
159b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        assertEquals(10, r.mPhoto.getWidth());
160b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        assertEquals(android.R.drawable.presence_away, r.mPresenceResId);
161b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki    }
162b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki
163b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki    private static byte[] createJpegData(int width, int height) {
164b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
165b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        ByteArrayOutputStream out = new ByteArrayOutputStream();
166b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        bitmap.compress(Bitmap.CompressFormat.JPEG, 50, out);
167b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        return out.toByteArray();
168b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki    }
169b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki
170b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki    // MatrixCursor doesn't support getBlob, so use this...
171b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki    private static class PhotoCursor extends MatrixCursor {
172b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        private final byte[] mBlob;
173b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki
174b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        public PhotoCursor(byte[] blob) {
175b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki            super(ContactStatusLoader.PHOTO_PROJECTION);
176b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki            mBlob = blob;
177b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki            addRow(new Object[] {null}); // Add dummy row
178b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        }
179b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki
180b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        @Override
181b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        public byte[] getBlob(int column) {
182b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki            Assert.assertEquals(0, column);
183b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki            return mBlob;
184b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        }
185b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki    }
186b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki
187b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki    public static class MockContactProvider extends MockContentProvider {
188b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        public ArrayList<String> mUris = new ArrayList<String>();
189b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki
190b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        public final Queue<Cursor> mCursors = new LinkedBlockingQueue<Cursor>();
191b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki
192b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        @Override
193b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
194b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki                String sortOrder) {
195b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki            mUris.add(uri.toString());
196b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki            return mCursors.poll();
197b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        }
198b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki
199b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        @Override
200b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        public void attachInfo(Context context, ProviderInfo info) {
201b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki        }
202b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki    }
203b1ea9c3c12d8d9da5c1e49a8752076ce60861e9fMakoto Onuki}
204