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