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.ParticipantInfo; 31 import com.android.mail.providers.ReplyFromAccount; 32 import com.android.mail.providers.Settings; 33 import com.android.mail.providers.UIProvider.AccountCapabilities; 34 import com.android.mail.providers.UIProvider.AccountColumns; 35 import com.android.mail.providers.UIProvider.AccountColumns.SettingsColumns; 36 import com.android.mail.providers.UIProvider.AttachmentColumns; 37 import com.android.mail.providers.UIProvider.ConversationColumns; 38 import com.android.mail.providers.UIProvider.ConversationCursorCommand; 39 import com.android.mail.providers.UIProvider.FolderCapabilities; 40 import com.android.mail.providers.UIProvider.FolderColumns; 41 import com.android.mail.providers.UIProvider.MessageColumns; 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.addParticipant(new ParticipantInfo(i + "Test", "testsender@test.com", -1, 235 false)); 236 } else if (i % 3 == 0) { 237 info.addParticipant(new ParticipantInfo(i + "sender@test.com", "sender@test.com", 238 -1, false)); 239 } else { 240 info.addParticipant(new ParticipantInfo(" .. ", null, -1, false)); 241 } 242 } 243 return info.toBlob(); 244 } 245 createMessageDetailsMap(int accountId, int messageId, String subject, int hasAttachments, boolean addReplyTo)246 private static Map<String, Object> createMessageDetailsMap(int accountId, int messageId, 247 String subject, int hasAttachments, boolean addReplyTo) { 248 final String accountUri = getMockAccountUri(accountId); 249 final String messageUri = getMockMessageUri(accountId, messageId); 250 Map<String, Object> messageMap = Maps.newHashMap(); 251 messageMap.put(BaseColumns._ID, Long.valueOf(messageId)); 252 messageMap.put(MessageColumns.URI, messageUri); 253 messageMap.put(MessageColumns.SUBJECT, "Message " + subject); 254 messageMap.put(MessageColumns.SNIPPET, "SNIPPET"); 255 String html = "<html><body><b><i>This is some html!!!</i></b></body></html>"; 256 messageMap.put(MessageColumns.BODY_HTML, html); 257 messageMap.put(MessageColumns.BODY_TEXT, Html.fromHtml(html)); 258 messageMap.put(MessageColumns.HAS_ATTACHMENTS, hasAttachments); 259 messageMap.put(MessageColumns.DATE_RECEIVED_MS, new Date().getTime()); 260 messageMap.put(MessageColumns.ATTACHMENT_LIST_URI, messageUri + "/getAttachments"); 261 messageMap.put(MessageColumns.TO, "account1@mock.com, account2@mock.com"); 262 messageMap.put(MessageColumns.FROM, "fromaccount1@mock.com"); 263 messageMap.put(MessageColumns.MESSAGE_ACCOUNT_URI, accountUri); 264 return messageMap; 265 } 266 createAttachmentDetailsMap(int attachmentId, String name)267 private static Map<String, Object> createAttachmentDetailsMap(int attachmentId, String name) { 268 Map<String, Object> attachmentMap = Maps.newHashMap(); 269 attachmentMap.put(BaseColumns._ID, Long.valueOf(attachmentId)); 270 attachmentMap.put(AttachmentColumns.NAME, "Attachment " + name); 271 attachmentMap.put(AttachmentColumns.URI, 272 "attachmentUri/" + attachmentMap.get(AttachmentColumns.NAME)); 273 return attachmentMap; 274 } 275 createFolderDetailsMap(int folderId, int accountId, String name, int unread, int total)276 private static Map<String, Object> createFolderDetailsMap(int folderId, int accountId, 277 String name, int unread, int total) { 278 return createFolderDetailsMap(folderId, accountId, name, false, unread, total); 279 } 280 createFolderDetailsMap(int folderId, int accountId, String name, boolean hasChildren, int unread, int total)281 private static Map<String, Object> createFolderDetailsMap(int folderId, int accountId, 282 String name, boolean hasChildren, int unread, int total) { 283 final String folderUri = getMockAccountFolderUri(accountId, folderId); 284 285 Map<String, Object> folderMap = Maps.newHashMap(); 286 folderMap.put(BaseColumns._ID, folderId); 287 folderMap.put(FolderColumns.URI, folderUri); 288 folderMap.put(FolderColumns.NAME, "Folder " + name); 289 folderMap.put(FolderColumns.HAS_CHILDREN, hasChildren ? 1 : 0); 290 folderMap.put(FolderColumns.CONVERSATION_LIST_URI, folderUri + "/getConversations"); 291 folderMap.put(FolderColumns.CHILD_FOLDERS_LIST_URI, folderUri + "/getChildFolders"); 292 folderMap.put(FolderColumns.CAPABILITIES, FolderCapabilities.CAN_ACCEPT_MOVED_MESSAGES); 293 folderMap.put(FolderColumns.UNREAD_COUNT, unread); 294 folderMap.put(FolderColumns.TOTAL_COUNT, total); 295 folderMap.put(FolderColumns.SYNC_STATUS, 0); 296 folderMap.put(FolderColumns.LAST_SYNC_RESULT, 0); 297 return folderMap; 298 } 299 300 // Temporarily made this public to allow the Gmail accounts to use the mock ui provider uris createAccountDetailsMap(int accountId,String defaultInbox)301 public static Map<String, Object> createAccountDetailsMap(int accountId,String defaultInbox) { 302 final String accountUri = getMockAccountUri(accountId); 303 Map<String, Object> accountMap = Maps.newHashMap(); 304 accountMap.put(BaseColumns._ID, Long.valueOf(accountId)); 305 accountMap.put(AccountColumns.NAME, "account" + accountId + "@mockuiprovider.com"); 306 accountMap.put(AccountColumns.TYPE, "com.android.mail.providers.protos.mock"); 307 accountMap.put(AccountColumns.ACCOUNT_MANAGER_NAME, 308 "account" + accountId + "@mockuiprovider.com"); 309 accountMap.put(AccountColumns.ACCOUNT_ID, 310 "account" + accountId + "@mockuiprovider.com"); 311 accountMap.put(AccountColumns.PROVIDER_VERSION, Long.valueOf(1)); 312 accountMap.put(AccountColumns.URI, Uri.parse(accountUri)); 313 accountMap.put(AccountColumns.CAPABILITIES, 314 Integer.valueOf( 315 AccountCapabilities.SYNCABLE_FOLDERS | 316 AccountCapabilities.REPORT_SPAM | 317 AccountCapabilities.ARCHIVE | 318 AccountCapabilities.MUTE | 319 AccountCapabilities.SERVER_SEARCH | 320 AccountCapabilities.FOLDER_SERVER_SEARCH | 321 AccountCapabilities.SERVER_SANITIZED_HTML | 322 AccountCapabilities.DRAFT_SYNCHRONIZATION | 323 AccountCapabilities.MULTIPLE_FROM_ADDRESSES | 324 AccountCapabilities.SMART_REPLY | 325 AccountCapabilities.LOCAL_SEARCH | 326 AccountCapabilities.THREADED_CONVERSATIONS | 327 AccountCapabilities.MULTIPLE_FOLDERS_PER_CONV)); 328 JSONArray replyFroms = new JSONArray(); 329 ArrayList<ReplyFromAccount> list = new ArrayList<ReplyFromAccount>(); 330 list.add(new ReplyFromAccount(null, Uri.parse(accountUri), "customAddress1@custom.com", 331 "customAddress2@custom.com", "Custom1", false, true)); 332 list.add(new ReplyFromAccount(null, Uri.parse(accountUri), "customAddress2@custom.com", 333 "customAddress2@custom.com", "Custom2", false, true)); 334 for (ReplyFromAccount a : list) { 335 replyFroms.put(a.serialize()); 336 } 337 accountMap.put(AccountColumns.ACCOUNT_FROM_ADDRESSES, replyFroms.toString()); 338 accountMap.put(AccountColumns.FOLDER_LIST_URI, Uri.parse(accountUri + "/folders")); 339 accountMap.put(AccountColumns.FULL_FOLDER_LIST_URI, Uri.parse(accountUri + "/folders")); 340 accountMap.put(AccountColumns.ALL_FOLDER_LIST_URI, Uri.parse(accountUri + "/folders")); 341 accountMap.put(AccountColumns.SEARCH_URI, Uri.parse(accountUri + "/search")); 342 accountMap.put(AccountColumns.EXPUNGE_MESSAGE_URI, 343 Uri.parse(accountUri + "/expungeMessage")); 344 accountMap.put(AccountColumns.UNDO_URI, Uri.parse(accountUri + "/undo")); 345 accountMap.put(AccountColumns.SETTINGS_INTENT_URI, Uri.EMPTY); 346 accountMap.put(AccountColumns.HELP_INTENT_URI, Uri.EMPTY); 347 accountMap.put(AccountColumns.SEND_FEEDBACK_INTENT_URI, Uri.EMPTY); 348 accountMap.put(AccountColumns.REAUTHENTICATION_INTENT_URI, Uri.EMPTY); 349 accountMap.put(AccountColumns.SYNC_STATUS, 0); 350 accountMap.put(AccountColumns.COMPOSE_URI, Uri.parse(accountUri + "/compose")); 351 accountMap.put(AccountColumns.RECENT_FOLDER_LIST_URI, 352 Uri.parse(accountUri + "/recentFolderListUri")); 353 accountMap.put(AccountColumns.MIME_TYPE, "account/mock"); 354 accountMap.put(AccountColumns.COLOR, 0); 355 accountMap.put(AccountColumns.RECENT_FOLDER_LIST_URI, Uri.EMPTY); 356 accountMap.put(AccountColumns.DEFAULT_RECENT_FOLDER_LIST_URI, Uri.EMPTY); 357 accountMap.put(AccountColumns.MANUAL_SYNC_URI, Uri.EMPTY); 358 accountMap.put(AccountColumns.VIEW_INTENT_PROXY_URI, Uri.EMPTY); 359 accountMap.put(AccountColumns.ACCOUNT_COOKIE_QUERY_URI, Uri.EMPTY); 360 accountMap.put(AccountColumns.UPDATE_SETTINGS_URI, Uri.EMPTY); 361 accountMap.put(AccountColumns.ENABLE_MESSAGE_TRANSFORMS, 1); 362 363 364 // Add settings columns 365 accountMap.put(SettingsColumns.SIGNATURE, ""); 366 accountMap.put(SettingsColumns.AUTO_ADVANCE, 1); 367 accountMap.put(SettingsColumns.SNAP_HEADERS, 1); 368 accountMap.put(SettingsColumns.REPLY_BEHAVIOR, 1); 369 accountMap.put(SettingsColumns.CONV_LIST_ICON, 1); 370 accountMap.put(SettingsColumns.CONFIRM_DELETE, 1); 371 accountMap.put(SettingsColumns.CONFIRM_ARCHIVE, 1); 372 accountMap.put(SettingsColumns.CONFIRM_SEND, 1); 373 accountMap.put(SettingsColumns.DEFAULT_INBOX, defaultInbox); 374 accountMap.put(SettingsColumns.DEFAULT_INBOX_NAME, "Inbox"); 375 accountMap.put(SettingsColumns.FORCE_REPLY_FROM_DEFAULT, 1); 376 accountMap.put(SettingsColumns.MAX_ATTACHMENT_SIZE, 25 * 1024 * 1024); 377 accountMap.put(SettingsColumns.SWIPE, 1); 378 accountMap.put(SettingsColumns.IMPORTANCE_MARKERS_ENABLED, 1); 379 accountMap.put(SettingsColumns.SHOW_CHEVRONS_ENABLED, 0); 380 accountMap.put(SettingsColumns.SETUP_INTENT_URI, Uri.EMPTY); 381 accountMap.put(SettingsColumns.CONVERSATION_VIEW_MODE, 1); 382 accountMap.put(SettingsColumns.VEILED_ADDRESS_PATTERN, null); 383 accountMap.put(SettingsColumns.MOVE_TO_INBOX, Uri.EMPTY); 384 accountMap.put(SettingsColumns.SHOW_IMAGES, Settings.ShowImages.ASK_FIRST); 385 return accountMap; 386 } 387 getMockAccountUri(int accountId)388 public static String getMockAccountUri(int accountId) { 389 return "content://" + AUTHORITY + "/account/" + accountId; 390 } 391 getMockAccountFolderUri(int accountId, int folderId)392 private static String getMockAccountFolderUri(int accountId, int folderId) { 393 return getMockAccountUri(accountId) + "/folder/" + folderId; 394 } 395 getMockConversationUri(int accountId, int conversationId)396 private static String getMockConversationUri(int accountId, int conversationId) { 397 return getMockAccountUri(accountId) + "/conversation/" + conversationId; 398 } 399 getMockMessageUri(int accountId, int messageId)400 private static String getMockMessageUri(int accountId, int messageId) { 401 return getMockAccountUri(accountId) + "/message/" + messageId; 402 } 403 404 @Override onCreate()405 public boolean onCreate() { 406 MockUiProvider.initializeMockProvider(); 407 return true; 408 } 409 410 @Override query(Uri url, String[] projection, String selection, String[] selectionArgs, String sortOrder)411 public Cursor query(Uri url, String[] projection, String selection, String[] selectionArgs, 412 String sortOrder) { 413 414 final List<Map<String, Object>> queryResults = MOCK_QUERY_RESULTS.get(url.toString()); 415 416 if (queryResults != null && queryResults.size() > 0) { 417 // Get the projection. If there are rows in the result set, pick the first item to 418 // generate the projection 419 // TODO (pwestbro): handle the case where we want to return an empty result.\ 420 if (projection == null) { 421 Set<String> keys = queryResults.get(0).keySet(); 422 projection = keys.toArray(new String[keys.size()]); 423 } 424 final MatrixCursor matrixCursor = 425 new MockRespondMatrixCursor(projection, queryResults.size(), queryResults); 426 427 for (Map<String, Object> queryResult : queryResults) { 428 MatrixCursor.RowBuilder rowBuilder = matrixCursor.newRow(); 429 430 for (String key : projection) { 431 rowBuilder.add(queryResult.get(key)); 432 } 433 } 434 return matrixCursor; 435 } 436 437 return null; 438 } 439 440 @Override insert(Uri url, ContentValues values)441 public Uri insert(Uri url, ContentValues values) { 442 return url; 443 } 444 445 @Override update(Uri url, ContentValues values, String selection, String[] selectionArgs)446 public int update(Uri url, ContentValues values, String selection, 447 String[] selectionArgs) { 448 return 0; 449 } 450 451 @Override delete(Uri url, String selection, String[] selectionArgs)452 public int delete(Uri url, String selection, String[] selectionArgs) { 453 return 0; 454 } 455 456 @Override getType(Uri uri)457 public String getType(Uri uri) { 458 return null; 459 } 460 461 @VisibleForTesting getAccountsUri()462 static Uri getAccountsUri() { 463 return MOCK_ACCOUNTS_URI; 464 } 465 } 466 467