• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2011, Google Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.mail.providers.protos.mock;
18 
19 import android.content.ContentProvider;
20 import android.content.ContentValues;
21 import android.database.Cursor;
22 import android.database.MatrixCursor;
23 import android.net.Uri;
24 import android.provider.BaseColumns;
25 import android.text.Html;
26 
27 import com.android.mail.providers.ConversationInfo;
28 import com.android.mail.providers.Folder;
29 import com.android.mail.providers.FolderList;
30 import com.android.mail.providers.MessageInfo;
31 import com.android.mail.providers.ReplyFromAccount;
32 import com.android.mail.providers.UIProvider.AccountCapabilities;
33 import com.android.mail.providers.UIProvider.AccountColumns;
34 import com.android.mail.providers.UIProvider.AccountColumns.SettingsColumns;
35 import com.android.mail.providers.UIProvider.AttachmentColumns;
36 import com.android.mail.providers.UIProvider.ConversationColumns;
37 import com.android.mail.providers.UIProvider.ConversationCursorCommand;
38 import com.android.mail.providers.UIProvider.FolderCapabilities;
39 import com.android.mail.providers.UIProvider.FolderColumns;
40 import com.android.mail.providers.UIProvider.MessageColumns;
41 
42 import com.google.common.annotations.VisibleForTesting;
43 import com.google.common.collect.ImmutableList;
44 import com.google.common.collect.Lists;
45 import com.google.common.collect.Maps;
46 
47 import org.json.JSONArray;
48 
49 import java.util.ArrayList;
50 import java.util.Date;
51 import java.util.List;
52 import java.util.Map;
53 import java.util.Set;
54 
55 public final class MockUiProvider extends ContentProvider {
56 
57     public static final String AUTHORITY = "com.android.mail.mockprovider";
58 
59     private static final int NUM_ACCOUNTS = 5;
60 
61 
62     private static final Uri MOCK_ACCOUNTS_URI = Uri.parse("content://" + AUTHORITY + "/accounts");
63 
64     // A map of query result for uris
65     // TODO(pwestbro) read this map from an external file
66     private static Map<String, List<Map<String, Object>>> MOCK_QUERY_RESULTS = Maps.newHashMap();
67 
initializeAccount(int accountId, Map<String, List<Map<String, Object>>> resultMap)68     private static void initializeAccount(int accountId,
69             Map<String, List<Map<String, Object>>> resultMap) {
70         final Map<String, Object> inboxfolderDetailsMap =
71                 createFolderDetailsMap(0, accountId, "zero", true, 0, 2);
72         resultMap.put(inboxfolderDetailsMap.get(FolderColumns.URI).toString(),
73                 ImmutableList.of(inboxfolderDetailsMap));
74 
75         final Map<String, Object> accountDetailsMap = createAccountDetailsMap(accountId,
76                 (String)inboxfolderDetailsMap.get(FolderColumns.URI));
77         resultMap.put(((Uri) accountDetailsMap.get(AccountColumns.URI)).toString(),
78                 ImmutableList.of(accountDetailsMap));
79 
80         final Map<String, Object> secondFolderDetailsMap =
81                 createFolderDetailsMap(2, accountId, "two", 2, 2);
82         resultMap.put(secondFolderDetailsMap.get(FolderColumns.URI).toString(),
83                 ImmutableList.of(secondFolderDetailsMap));
84 
85         resultMap.put(
86                 inboxfolderDetailsMap.get(FolderColumns.CHILD_FOLDERS_LIST_URI).toString(),
87                 ImmutableList.of(createFolderDetailsMap(10, accountId, "zeroChild0", 0, 0),
88                         createFolderDetailsMap(11, accountId, "zeroChild1", 0, 0)));
89 
90         final ArrayList<Map<String, Object>> conversations = new ArrayList<Map<String, Object>>();
91         for (int i = 0; i < 100; i++) {
92             final String name = "zeroConv"+i;
93             conversations.add(createConversationDetailsMap(accountId, name.hashCode(),
94                     name, 1, 5, i % 2));
95         }
96         resultMap.put(inboxfolderDetailsMap.get(FolderColumns.CONVERSATION_LIST_URI).toString(),
97                 conversations);
98 
99         final Map<String, Object> message0 =
100                 createMessageDetailsMap(accountId, "zeroConv0".hashCode(), "zeroConv0", 1, false);
101         resultMap.put(message0.get(MessageColumns.URI).toString(), ImmutableList.of(message0));
102         resultMap.put(conversations.get(0).get(ConversationColumns.MESSAGE_LIST_URI).toString(),
103                 ImmutableList.of(message0));
104         resultMap.put(message0.get(MessageColumns.ATTACHMENT_LIST_URI).toString(),
105                 ImmutableList.of(createAttachmentDetailsMap(0, "zero")));
106         final Map<String, Object> message1 =
107                 createMessageDetailsMap(accountId, "zeroConv1".hashCode(), "zeroConv1", 1, false);
108         resultMap.put(message1.get(MessageColumns.URI).toString(), ImmutableList.of(message1));
109         final Map<String, Object> message1a =
110                 createMessageDetailsMap(accountId, "zeroConv1a".hashCode(), "zeroConv1a", 2, false);
111         resultMap.put(message1a.get(MessageColumns.URI).toString(), ImmutableList.of(message1a));
112         resultMap.put(conversations.get(1).get(ConversationColumns.MESSAGE_LIST_URI).toString(),
113                 ImmutableList.of(message1, message1a));
114         resultMap.put(message1.get(MessageColumns.ATTACHMENT_LIST_URI).toString(),
115                 ImmutableList.of(createAttachmentDetailsMap(1, "one")));
116 
117         final Map<String, Object> folderDetailsMap1 =
118                 createFolderDetailsMap(1, accountId,  "one", 0, 0);
119         resultMap.put(folderDetailsMap1.get(FolderColumns.URI).toString(),
120                 ImmutableList.of(folderDetailsMap1));
121 
122         // We currently have two configurations for accounts
123         if (accountId % 2 == 0) {
124             resultMap.put(accountDetailsMap.get(AccountColumns.FOLDER_LIST_URI).toString(),
125                     ImmutableList.of(inboxfolderDetailsMap, folderDetailsMap1));
126         } else {
127             resultMap.put(secondFolderDetailsMap.get(FolderColumns.URI).toString(),
128                     ImmutableList.of(secondFolderDetailsMap));
129             final Map<String, Object> folderDetailsMap3 =
130                     createFolderDetailsMap(3, accountId, "three", 0, 0);
131             resultMap.put(folderDetailsMap3.get(FolderColumns.URI).toString(),
132                     ImmutableList.of(folderDetailsMap3));
133 
134             resultMap.put(accountDetailsMap.get(AccountColumns.FOLDER_LIST_URI).toString(),
135                     ImmutableList.of(secondFolderDetailsMap, folderDetailsMap3));
136         }
137 
138         final Map<String, Object> conv3 =
139                 createConversationDetailsMap(accountId, "zeroConv3".hashCode(), "zeroConv3",
140                         0, 1, 0);
141         resultMap.put(conv3.get(ConversationColumns.URI).toString(),
142                 ImmutableList.of(conv3));
143         final Map<String, Object> conv4 =
144                 createConversationDetailsMap(accountId, "zeroConv4".hashCode(), "zeroConv4",
145                         0, 1, 0);
146         resultMap.put(conv4.get(ConversationColumns.URI).toString(),
147                 ImmutableList.of(conv4));
148         resultMap.put(secondFolderDetailsMap.get(FolderColumns.CONVERSATION_LIST_URI).toString(),
149                 ImmutableList.of(conv3, conv4));
150 
151         final Map<String, Object> message2 =
152                 createMessageDetailsMap(accountId, "zeroConv3".hashCode(), "zeroConv3", 0, true);
153         resultMap.put(message2.get(MessageColumns.URI).toString(), ImmutableList.of(message2));
154         resultMap.put(conv3.get(ConversationColumns.MESSAGE_LIST_URI).toString(),
155                 ImmutableList.of(message2));
156         final Map<String, Object> message3 =
157                 createMessageDetailsMap(accountId, "zeroConv4".hashCode(), "zeroConv4", 0, true);
158         resultMap.put(message3.get(MessageColumns.URI).toString(), ImmutableList.of(message3));
159         resultMap.put(conv4.get(ConversationColumns.MESSAGE_LIST_URI).toString(),
160                 ImmutableList.of(message3));
161 
162         // Add the account to the list of accounts
163         List<Map<String, Object>> accountList = resultMap.get(getAccountsUri().toString());
164         if (accountList == null) {
165             accountList = Lists.newArrayList();
166             resultMap.put(getAccountsUri().toString(), accountList);
167         }
168         accountList.add(accountDetailsMap);
169     }
170 
initializeMockProvider()171     public static void initializeMockProvider() {
172         MOCK_QUERY_RESULTS = Maps.newHashMap();
173 
174         for (int accountId = 0; accountId < NUM_ACCOUNTS; accountId++) {
175             initializeAccount(accountId, MOCK_QUERY_RESULTS);
176         }
177     }
178 
createConversationDetailsMap(int accountId, int conversationId, String subject, int hasAttachments, int messageCount, int draftCount)179     private static Map<String, Object> createConversationDetailsMap(int accountId,
180             int conversationId, String subject, int hasAttachments, int messageCount,
181             int draftCount) {
182         final String conversationUri = getMockConversationUri(accountId, conversationId);
183         Map<String, Object> conversationMap = Maps.newHashMap();
184         conversationMap.put(BaseColumns._ID, Long.valueOf(conversationId));
185         conversationMap.put(ConversationColumns.URI, conversationUri);
186         conversationMap.put(ConversationColumns.MESSAGE_LIST_URI, conversationUri + "/getMessages");
187         conversationMap.put(ConversationColumns.SUBJECT, "Conversation " + subject);
188         conversationMap.put(ConversationColumns.SNIPPET, "snippet");
189         conversationMap.put(ConversationColumns.SENDER_INFO,
190                 "account1@mock.com, account2@mock.com");
191         conversationMap.put(ConversationColumns.DATE_RECEIVED_MS, new Date().getTime());
192         conversationMap.put(ConversationColumns.HAS_ATTACHMENTS, hasAttachments);
193         conversationMap.put(ConversationColumns.NUM_MESSAGES, 1);
194         conversationMap.put(ConversationColumns.NUM_DRAFTS, 1);
195         conversationMap.put(ConversationColumns.SENDING_STATE, 1);
196         conversationMap.put(ConversationColumns.READ, 0);
197         conversationMap.put(ConversationColumns.SEEN, 0);
198         conversationMap.put(ConversationColumns.STARRED, 0);
199         conversationMap.put(ConversationColumns.CONVERSATION_INFO,
200                 generateConversationInfo(messageCount, draftCount));
201         final List<Folder> folders = new ArrayList<Folder>(3);
202         for (int i = 0; i < 3; i++) {
203             final Folder folder = Folder.newUnsafeInstance();
204             folder.name = "folder" + i;
205             switch (i) {
206                 case 0:
207                     folder.bgColor = "#fff000";
208                     break;
209                 case 1:
210                     folder.bgColor = "#0000FF";
211                     break;
212                 case 2:
213                     folder.bgColor = "#FFFF00";
214                     break;
215                 default:
216                     folder.bgColor = null;
217                     break;
218             }
219 
220             folders.add(folder);
221         }
222         final FolderList folderList = FolderList.copyOf(folders);
223         conversationMap.put(
224                 MockRespondMatrixCursor.MOCK_RESPOND_PREFIX +
225                         ConversationCursorCommand.COMMAND_GET_RAW_FOLDERS, folderList);
226         return conversationMap;
227     }
228 
generateConversationInfo(int messageCount, int draftCount)229     private static byte[] generateConversationInfo(int messageCount, int draftCount) {
230         ConversationInfo info = new ConversationInfo(messageCount, draftCount, "first",
231                 "firstUnread", "last");
232         for (int i = 0; i < messageCount; i++) {
233             if (i % 2 == 0) {
234                 info.addMessage(new MessageInfo(false, false,
235                         i + "Test <testsender@test.com>", -1, "testsender@test.com"));
236             } else if (i % 3 == 0) {
237                 info.addMessage(new MessageInfo(true, false, i + "sender@test.com", -1,
238                         "sender@test.com"));
239             } else {
240                 info.addMessage(new MessageInfo(false, false, MessageInfo.SENDER_LIST_TOKEN_ELIDED,
241                         -1, null));
242             }
243         }
244         return info.toBlob();
245     }
246 
createMessageDetailsMap(int accountId, int messageId, String subject, int hasAttachments, boolean addReplyTo)247     private static Map<String, Object> createMessageDetailsMap(int accountId, int messageId,
248             String subject, int hasAttachments, boolean addReplyTo) {
249         final String accountUri = getMockAccountUri(accountId);
250         final String messageUri = getMockMessageUri(accountId, messageId);
251         Map<String, Object> messageMap = Maps.newHashMap();
252         messageMap.put(BaseColumns._ID, Long.valueOf(messageId));
253         messageMap.put(MessageColumns.URI, messageUri);
254         messageMap.put(MessageColumns.SUBJECT, "Message " + subject);
255         messageMap.put(MessageColumns.SNIPPET, "SNIPPET");
256         String html = "<html><body><b><i>This is some html!!!</i></b></body></html>";
257         messageMap.put(MessageColumns.BODY_HTML, html);
258         messageMap.put(MessageColumns.BODY_TEXT, Html.fromHtml(html));
259         messageMap.put(MessageColumns.HAS_ATTACHMENTS, hasAttachments);
260         messageMap.put(MessageColumns.DATE_RECEIVED_MS, new Date().getTime());
261         messageMap.put(MessageColumns.ATTACHMENT_LIST_URI, messageUri + "/getAttachments");
262         messageMap.put(MessageColumns.TO, "account1@mock.com, account2@mock.com");
263         messageMap.put(MessageColumns.FROM, "fromaccount1@mock.com");
264         messageMap.put(MessageColumns.MESSAGE_ACCOUNT_URI, accountUri);
265         return messageMap;
266     }
267 
createAttachmentDetailsMap(int attachmentId, String name)268     private static Map<String, Object> createAttachmentDetailsMap(int attachmentId, String name) {
269         Map<String, Object> attachmentMap = Maps.newHashMap();
270         attachmentMap.put(BaseColumns._ID, Long.valueOf(attachmentId));
271         attachmentMap.put(AttachmentColumns.NAME, "Attachment " + name);
272         attachmentMap.put(AttachmentColumns.URI,
273                 "attachmentUri/" + attachmentMap.get(AttachmentColumns.NAME));
274         return attachmentMap;
275     }
276 
createFolderDetailsMap(int folderId, int accountId, String name, int unread, int total)277     private static Map<String, Object> createFolderDetailsMap(int folderId, int accountId,
278             String name, int unread, int total) {
279         return createFolderDetailsMap(folderId, accountId, name, false, unread, total);
280     }
281 
createFolderDetailsMap(int folderId, int accountId, String name, boolean hasChildren, int unread, int total)282     private static Map<String, Object> createFolderDetailsMap(int folderId, int accountId,
283             String name, boolean hasChildren, int unread, int total) {
284         final String folderUri = getMockAccountFolderUri(accountId, folderId);
285 
286         Map<String, Object> folderMap = Maps.newHashMap();
287         folderMap.put(BaseColumns._ID, Long.valueOf(folderId));
288         folderMap.put(FolderColumns.URI, folderUri);
289         folderMap.put(FolderColumns.NAME, "Folder " + name);
290         folderMap.put(FolderColumns.HAS_CHILDREN, new Integer(hasChildren ? 1 : 0));
291         folderMap.put(FolderColumns.CONVERSATION_LIST_URI, folderUri + "/getConversations");
292         folderMap.put(FolderColumns.CHILD_FOLDERS_LIST_URI, folderUri + "/getChildFolders");
293         folderMap.put(FolderColumns.CAPABILITIES,
294                 Long.valueOf(
295                         FolderCapabilities.SYNCABLE |
296                         FolderCapabilities.PARENT |
297                         FolderCapabilities.CAN_ACCEPT_MOVED_MESSAGES));
298         folderMap.put(FolderColumns.UNREAD_COUNT, unread);
299         folderMap.put(FolderColumns.TOTAL_COUNT, total);
300         folderMap.put(FolderColumns.SYNC_STATUS, 0);
301         folderMap.put(FolderColumns.LAST_SYNC_RESULT, 0);
302         return folderMap;
303     }
304 
305     // Temporarily made this public to allow the Gmail accounts to use the mock ui provider uris
createAccountDetailsMap(int accountId,String defaultInbox)306     public static Map<String, Object> createAccountDetailsMap(int accountId,String defaultInbox) {
307         final String accountUri = getMockAccountUri(accountId);
308         Map<String, Object> accountMap = Maps.newHashMap();
309         accountMap.put(BaseColumns._ID, Long.valueOf(accountId));
310         accountMap.put(AccountColumns.NAME, "account" + accountId + "@mockuiprovider.com");
311         accountMap.put(AccountColumns.TYPE, "com.android.mail.providers.protos.mock");
312         accountMap.put(AccountColumns.ACCOUNT_MANAGER_NAME,
313                 "account" + accountId + "@mockuiprovider.com");
314         accountMap.put(AccountColumns.PROVIDER_VERSION, Long.valueOf(1));
315         accountMap.put(AccountColumns.URI, Uri.parse(accountUri));
316         accountMap.put(AccountColumns.CAPABILITIES,
317                 Integer.valueOf(
318                         AccountCapabilities.SYNCABLE_FOLDERS |
319                         AccountCapabilities.REPORT_SPAM |
320                         AccountCapabilities.ARCHIVE |
321                         AccountCapabilities.MUTE |
322                         AccountCapabilities.SERVER_SEARCH |
323                         AccountCapabilities.FOLDER_SERVER_SEARCH |
324                         AccountCapabilities.SANITIZED_HTML |
325                         AccountCapabilities.DRAFT_SYNCHRONIZATION |
326                         AccountCapabilities.MULTIPLE_FROM_ADDRESSES |
327                         AccountCapabilities.SMART_REPLY |
328                         AccountCapabilities.LOCAL_SEARCH |
329                         AccountCapabilities.THREADED_CONVERSATIONS |
330                         AccountCapabilities.MULTIPLE_FOLDERS_PER_CONV));
331         JSONArray replyFroms = new JSONArray();
332         ArrayList<ReplyFromAccount> list = new ArrayList<ReplyFromAccount>();
333         list.add(new ReplyFromAccount(null, Uri.parse(accountUri), "customAddress1@custom.com",
334                 "customAddress2@custom.com", "Custom1", false, true));
335         list.add(new ReplyFromAccount(null, Uri.parse(accountUri), "customAddress2@custom.com",
336                 "customAddress2@custom.com", "Custom2", false, true));
337         for (ReplyFromAccount a : list) {
338             replyFroms.put(a.serialize());
339         }
340         accountMap.put(AccountColumns.ACCOUNT_FROM_ADDRESSES, replyFroms.toString());
341         accountMap.put(AccountColumns.FOLDER_LIST_URI, Uri.parse(accountUri + "/folders"));
342         accountMap.put(AccountColumns.FULL_FOLDER_LIST_URI, Uri.parse(accountUri + "/folders"));
343         accountMap.put(AccountColumns.ALL_FOLDER_LIST_URI, Uri.parse(accountUri + "/folders"));
344         accountMap.put(AccountColumns.SEARCH_URI, Uri.parse(accountUri + "/search"));
345         accountMap.put(AccountColumns.EXPUNGE_MESSAGE_URI,
346                 Uri.parse(accountUri + "/expungeMessage"));
347         accountMap.put(AccountColumns.UNDO_URI, Uri.parse(accountUri + "/undo"));
348         accountMap.put(AccountColumns.SETTINGS_INTENT_URI, Uri.EMPTY);
349         accountMap.put(AccountColumns.HELP_INTENT_URI, Uri.EMPTY);
350         accountMap.put(AccountColumns.SEND_FEEDBACK_INTENT_URI, Uri.EMPTY);
351         accountMap.put(AccountColumns.REAUTHENTICATION_INTENT_URI, Uri.EMPTY);
352         accountMap.put(AccountColumns.SYNC_STATUS, 0);
353         accountMap.put(AccountColumns.COMPOSE_URI, Uri.parse(accountUri + "/compose"));
354         accountMap.put(AccountColumns.RECENT_FOLDER_LIST_URI,
355                 Uri.parse(accountUri + "/recentFolderListUri"));
356         accountMap.put(AccountColumns.MIME_TYPE, "account/mock");
357         accountMap.put(AccountColumns.COLOR, 0);
358         accountMap.put(AccountColumns.RECENT_FOLDER_LIST_URI, Uri.EMPTY);
359         accountMap.put(AccountColumns.DEFAULT_RECENT_FOLDER_LIST_URI, Uri.EMPTY);
360         accountMap.put(AccountColumns.MANUAL_SYNC_URI, Uri.EMPTY);
361         accountMap.put(AccountColumns.VIEW_INTENT_PROXY_URI, Uri.EMPTY);
362         accountMap.put(AccountColumns.ACCOUNT_COOKIE_QUERY_URI, Uri.EMPTY);
363         accountMap.put(AccountColumns.UPDATE_SETTINGS_URI, Uri.EMPTY);
364         accountMap.put(AccountColumns.ENABLE_MESSAGE_TRANSFORMS, 1);
365 
366 
367         // Add settings columns
368         accountMap.put(SettingsColumns.SIGNATURE, "");
369         accountMap.put(SettingsColumns.AUTO_ADVANCE, 1);
370         accountMap.put(SettingsColumns.MESSAGE_TEXT_SIZE, 1);
371         accountMap.put(SettingsColumns.SNAP_HEADERS, 1);
372         accountMap.put(SettingsColumns.REPLY_BEHAVIOR, 1);
373         accountMap.put(SettingsColumns.CONV_LIST_ICON, 1);
374         accountMap.put(SettingsColumns.CONV_LIST_ATTACHMENT_PREVIEWS, 1);
375         accountMap.put(SettingsColumns.CONFIRM_DELETE, 1);
376         accountMap.put(SettingsColumns.CONFIRM_ARCHIVE, 1);
377         accountMap.put(SettingsColumns.CONFIRM_SEND, 1);
378         accountMap.put(SettingsColumns.DEFAULT_INBOX, defaultInbox);
379         accountMap.put(SettingsColumns.DEFAULT_INBOX_NAME, "Inbox");
380         accountMap.put(SettingsColumns.FORCE_REPLY_FROM_DEFAULT, 1);
381         accountMap.put(SettingsColumns.MAX_ATTACHMENT_SIZE, 25 * 1024 * 1024);
382         accountMap.put(SettingsColumns.SWIPE, 1);
383         accountMap.put(SettingsColumns.PRIORITY_ARROWS_ENABLED, 1);
384         accountMap.put(SettingsColumns.SETUP_INTENT_URI, Uri.EMPTY);
385         accountMap.put(SettingsColumns.CONVERSATION_VIEW_MODE, 1);
386         accountMap.put(SettingsColumns.VEILED_ADDRESS_PATTERN, null);
387         accountMap.put(SettingsColumns.MOVE_TO_INBOX, Uri.EMPTY);
388         return accountMap;
389     }
390 
getMockAccountUri(int accountId)391     public static String getMockAccountUri(int accountId) {
392         return "content://" + AUTHORITY + "/account/" + accountId;
393     }
394 
getMockAccountFolderUri(int accountId, int folderId)395     private static String getMockAccountFolderUri(int accountId, int folderId) {
396         return getMockAccountUri(accountId) + "/folder/" + folderId;
397     }
398 
getMockConversationUri(int accountId, int conversationId)399     private static String getMockConversationUri(int accountId, int conversationId) {
400         return getMockAccountUri(accountId) + "/conversation/" + conversationId;
401     }
402 
getMockMessageUri(int accountId, int messageId)403     private static String getMockMessageUri(int accountId, int messageId) {
404         return getMockAccountUri(accountId) + "/message/" + messageId;
405     }
406 
407     @Override
onCreate()408     public boolean onCreate() {
409         MockUiProvider.initializeMockProvider();
410         return true;
411     }
412 
413     @Override
query(Uri url, String[] projection, String selection, String[] selectionArgs, String sortOrder)414     public Cursor query(Uri url, String[] projection, String selection, String[] selectionArgs,
415             String sortOrder) {
416 
417         final List<Map<String, Object>> queryResults = MOCK_QUERY_RESULTS.get(url.toString());
418 
419         if (queryResults != null && queryResults.size() > 0) {
420             // Get the projection.  If there are rows in the result set, pick the first item to
421             // generate the projection
422             // TODO (pwestbro): handle the case where we want to return an empty result.\
423             if (projection == null) {
424                 Set<String> keys = queryResults.get(0).keySet();
425                 projection = keys.toArray(new String[keys.size()]);
426             }
427             final MatrixCursor matrixCursor =
428                     new MockRespondMatrixCursor(projection, queryResults.size(), queryResults);
429 
430             for (Map<String, Object> queryResult : queryResults) {
431                 MatrixCursor.RowBuilder rowBuilder = matrixCursor.newRow();
432 
433                 for (String key : projection) {
434                     rowBuilder.add(queryResult.get(key));
435                 }
436             }
437             return matrixCursor;
438         }
439 
440         return null;
441     }
442 
443     @Override
insert(Uri url, ContentValues values)444     public Uri insert(Uri url, ContentValues values) {
445         return url;
446     }
447 
448     @Override
update(Uri url, ContentValues values, String selection, String[] selectionArgs)449     public int update(Uri url, ContentValues values, String selection,
450             String[] selectionArgs) {
451         return 0;
452     }
453 
454     @Override
delete(Uri url, String selection, String[] selectionArgs)455     public int delete(Uri url, String selection, String[] selectionArgs) {
456         return 0;
457     }
458 
459     @Override
getType(Uri uri)460     public String getType(Uri uri) {
461         return null;
462     }
463 
464     @VisibleForTesting
getAccountsUri()465     static Uri getAccountsUri() {
466         return MOCK_ACCOUNTS_URI;
467     }
468 }
469 
470