1 /* 2 * Copyright (C) 2015 The Android Open Source Project 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.calllogbackup; 18 19 import static org.mockito.ArgumentMatchers.any; 20 import static org.mockito.ArgumentMatchers.anyInt; 21 import static org.mockito.Mockito.verify; 22 import static org.mockito.Mockito.when; 23 import static org.mockito.Mockito.eq; 24 25 import android.app.backup.BackupDataOutput; 26 import android.content.Context; 27 import android.database.Cursor; 28 import android.provider.CallLog; 29 import android.test.AndroidTestCase; 30 import android.test.suitebuilder.annotation.SmallTest; 31 32 import androidx.test.InstrumentationRegistry; 33 34 import com.android.calllogbackup.CallLogBackupAgent.Call; 35 import com.android.calllogbackup.CallLogBackupAgent.CallLogBackupState; 36 37 import org.mockito.InOrder; 38 import org.mockito.Matchers; 39 import org.mockito.Mock; 40 import org.mockito.Mockito; 41 import org.mockito.MockitoAnnotations; 42 43 import java.io.DataInput; 44 import java.io.DataOutput; 45 import java.io.EOFException; 46 import java.io.IOException; 47 import java.util.HashMap; 48 import java.util.LinkedList; 49 import java.util.List; 50 import java.util.Map; 51 import java.util.TreeSet; 52 53 /** 54 * Test cases for {@link com.android.providers.contacts.CallLogBackupAgent} 55 */ 56 @SmallTest 57 public class CallLogBackupAgentTest extends AndroidTestCase { 58 static final String TELEPHONY_COMPONENT 59 = "com.android.phone/com.android.services.telephony.TelephonyConnectionService"; 60 static final String TEST_PHONE_ACCOUNT_HANDLE_SUB_ID = "666"; 61 static final int TEST_PHONE_ACCOUNT_HANDLE_SUB_ID_INT = 666; 62 static final String TEST_PHONE_ACCOUNT_HANDLE_ICC_ID = "891004234814455936F"; 63 64 public int backupRestoreLoggerSuccessCount = 0; 65 public int backupRestoreLoggerFailCount = 0; 66 67 @Mock DataInput mDataInput; 68 @Mock DataOutput mDataOutput; 69 @Mock BackupDataOutput mBackupDataOutput; 70 @Mock Cursor mCursor; 71 72 private CallLogBackupAgent.BackupRestoreEventLoggerProxy mBackupRestoreEventLoggerProxy = 73 new CallLogBackupAgent.BackupRestoreEventLoggerProxy() { 74 @Override 75 public void logItemsBackedUp(String dataType, int count) { 76 backupRestoreLoggerSuccessCount += count; 77 } 78 79 @Override 80 public void logItemsBackupFailed(String dataType, int count, String error) { 81 backupRestoreLoggerFailCount += count; 82 } 83 84 @Override 85 public void logItemsRestored(String dataType, int count) { 86 backupRestoreLoggerSuccessCount += count; 87 } 88 89 @Override 90 public void logItemsRestoreFailed(String dataType, int count, String error) { 91 backupRestoreLoggerFailCount += count; 92 } 93 }; 94 95 CallLogBackupAgent mCallLogBackupAgent; 96 97 MockitoHelper mMockitoHelper = new MockitoHelper(); 98 99 @Override setUp()100 public void setUp() throws Exception { 101 super.setUp(); 102 103 mMockitoHelper.setUp(getClass()); 104 // Since we're testing a system app, AppDataDirGuesser doesn't find our 105 // cache dir, so set it explicitly. 106 System.setProperty("dexmaker.dexcache", getContext().getCacheDir().toString()); 107 MockitoAnnotations.initMocks(this); 108 109 mCallLogBackupAgent = new CallLogBackupAgent(); 110 mCallLogBackupAgent.setBackupRestoreEventLoggerProxy(mBackupRestoreEventLoggerProxy); 111 } 112 113 @Override tearDown()114 public void tearDown() throws Exception { 115 mMockitoHelper.tearDown(); 116 } 117 118 @Override getTestContext()119 public Context getTestContext() { 120 return InstrumentationRegistry.getContext(); 121 } 122 testReadState_NoCall()123 public void testReadState_NoCall() throws Exception { 124 when(mDataInput.readInt()).thenThrow(new EOFException()); 125 126 CallLogBackupState state = mCallLogBackupAgent.readState(mDataInput); 127 128 assertEquals(state.version, CallLogBackupAgent.VERSION_NO_PREVIOUS_STATE); 129 assertEquals(state.callIds.size(), 0); 130 } 131 testReadState_OneCall()132 public void testReadState_OneCall() throws Exception { 133 when(mDataInput.readInt()).thenReturn( 134 1 /* version */, 135 1 /* size */, 136 101 /* call-ID */ ); 137 138 CallLogBackupState state = mCallLogBackupAgent.readState(mDataInput); 139 140 assertEquals(1, state.version); 141 assertEquals(1, state.callIds.size()); 142 assertTrue(state.callIds.contains(101)); 143 } 144 testReadState_MultipleCalls()145 public void testReadState_MultipleCalls() throws Exception { 146 when(mDataInput.readInt()).thenReturn( 147 1 /* version */, 148 2 /* size */, 149 101 /* call-ID */, 150 102 /* call-ID */); 151 152 CallLogBackupState state = mCallLogBackupAgent.readState(mDataInput); 153 154 assertEquals(1, state.version); 155 assertEquals(2, state.callIds.size()); 156 assertTrue(state.callIds.contains(101)); 157 assertTrue(state.callIds.contains(102)); 158 } 159 testWriteState_NoCalls()160 public void testWriteState_NoCalls() throws Exception { 161 CallLogBackupState state = new CallLogBackupState(); 162 state.version = CallLogBackupAgent.VERSION; 163 state.callIds = new TreeSet<>(); 164 165 mCallLogBackupAgent.writeState(mDataOutput, state); 166 167 InOrder inOrder = Mockito.inOrder(mDataOutput); 168 inOrder.verify(mDataOutput).writeInt(CallLogBackupAgent.VERSION); 169 inOrder.verify(mDataOutput).writeInt(0 /* size */); 170 } 171 testWriteState_OneCall()172 public void testWriteState_OneCall() throws Exception { 173 CallLogBackupState state = new CallLogBackupState(); 174 state.version = CallLogBackupAgent.VERSION; 175 state.callIds = new TreeSet<>(); 176 state.callIds.add(101); 177 178 mCallLogBackupAgent.writeState(mDataOutput, state); 179 180 InOrder inOrder = Mockito.inOrder(mDataOutput); 181 inOrder.verify(mDataOutput).writeInt(CallLogBackupAgent.VERSION); 182 inOrder.verify(mDataOutput).writeInt(1); 183 inOrder.verify(mDataOutput).writeInt(101 /* call-ID */); 184 } 185 testWriteState_MultipleCalls()186 public void testWriteState_MultipleCalls() throws Exception { 187 CallLogBackupState state = new CallLogBackupState(); 188 state.version = CallLogBackupAgent.VERSION; 189 state.callIds = new TreeSet<>(); 190 state.callIds.add(101); 191 state.callIds.add(102); 192 state.callIds.add(103); 193 194 mCallLogBackupAgent.writeState(mDataOutput, state); 195 196 InOrder inOrder = Mockito.inOrder(mDataOutput); 197 inOrder.verify(mDataOutput).writeInt(CallLogBackupAgent.VERSION); 198 inOrder.verify(mDataOutput).writeInt(3 /* size */); 199 inOrder.verify(mDataOutput).writeInt(101 /* call-ID */); 200 inOrder.verify(mDataOutput).writeInt(102 /* call-ID */); 201 inOrder.verify(mDataOutput).writeInt(103 /* call-ID */); 202 } 203 testRunBackup_NoCalls()204 public void testRunBackup_NoCalls() throws Exception { 205 CallLogBackupState state = new CallLogBackupState(); 206 state.version = CallLogBackupAgent.VERSION; 207 state.callIds = new TreeSet<>(); 208 List<Call> calls = new LinkedList<>(); 209 210 mCallLogBackupAgent.runBackup(state, mBackupDataOutput, calls); 211 212 // Ensure the {@link BackupRestoreEventLogger} is not notified as no calls were backed up: 213 assertEquals(backupRestoreLoggerSuccessCount, 0); 214 assertEquals(backupRestoreLoggerFailCount, 0); 215 216 Mockito.verifyNoMoreInteractions(mBackupDataOutput); 217 } 218 testRunBackup_OneNewCall_ErrorAddingCall()219 public void testRunBackup_OneNewCall_ErrorAddingCall() throws Exception { 220 CallLogBackupState state = new CallLogBackupState(); 221 state.version = CallLogBackupAgent.VERSION; 222 state.callIds = new TreeSet<>(); 223 List<Call> calls = new LinkedList<>(); 224 calls.add(makeCall(101, 0L, 0L, "555-5555")); 225 226 // Throw an exception when the call is added to the backup: 227 when(mBackupDataOutput.writeEntityData(any(byte[].class), anyInt())) 228 .thenThrow(IOException.class); 229 mCallLogBackupAgent.runBackup(state, mBackupDataOutput, calls); 230 231 // Ensure the {@link BackupRestoreEventLogger} is informed of the failed backed up call: 232 assertEquals(backupRestoreLoggerSuccessCount, 0); 233 assertEquals(backupRestoreLoggerFailCount, 1); 234 } 235 testRunBackup_OneNewCall_NullBackupDataOutput()236 public void testRunBackup_OneNewCall_NullBackupDataOutput() throws Exception { 237 CallLogBackupState state = new CallLogBackupState(); 238 state.version = CallLogBackupAgent.VERSION; 239 state.callIds = new TreeSet<>(); 240 List<Call> calls = new LinkedList<>(); 241 calls.add(makeCall(101, 0L, 0L, "555-5555")); 242 243 // Invoke runBackup() with a null value for BackupDataOutput causing an exception: 244 mCallLogBackupAgent.runBackup(state, null, calls); 245 246 // Ensure the {@link BackupRestoreEventLogger} is informed of the failed backed up call: 247 assertEquals(backupRestoreLoggerSuccessCount, 0); 248 assertEquals(backupRestoreLoggerFailCount, 1); 249 } 250 testRunBackup_OneNewCall()251 public void testRunBackup_OneNewCall() throws Exception { 252 CallLogBackupState state = new CallLogBackupState(); 253 state.version = CallLogBackupAgent.VERSION; 254 state.callIds = new TreeSet<>(); 255 List<Call> calls = new LinkedList<>(); 256 calls.add(makeCall(101, 0L, 0L, "555-5555")); 257 mCallLogBackupAgent.runBackup(state, mBackupDataOutput, calls); 258 259 // Ensure the {@link BackupRestoreEventLogger} is informed of the backed up call: 260 assertEquals(backupRestoreLoggerSuccessCount, 1); 261 assertEquals(backupRestoreLoggerFailCount, 0); 262 263 verify(mBackupDataOutput).writeEntityHeader(eq("101"), Matchers.anyInt()); 264 verify(mBackupDataOutput).writeEntityData((byte[]) Matchers.any(), Matchers.anyInt()); 265 } 266 267 /* 268 Test PhoneAccountHandle Migration process during back up 269 */ testReadCallFromCursorForPhoneAccountMigrationBackup()270 public void testReadCallFromCursorForPhoneAccountMigrationBackup() throws Exception { 271 Map<Integer, String> subscriptionInfoMap = new HashMap<>(); 272 subscriptionInfoMap.put(TEST_PHONE_ACCOUNT_HANDLE_SUB_ID_INT, 273 TEST_PHONE_ACCOUNT_HANDLE_ICC_ID); 274 mCallLogBackupAgent.mSubscriptionInfoMap = subscriptionInfoMap; 275 276 // Mock telephony component name and expect the Sub ID is converted to Icc ID 277 // and the pending status is 1 when backup 278 mockCursor(mCursor, true); 279 Call call = mCallLogBackupAgent.readCallFromCursor(mCursor); 280 assertEquals(TEST_PHONE_ACCOUNT_HANDLE_ICC_ID, call.accountId); 281 assertEquals(1, call.isPhoneAccountMigrationPending); 282 283 // Mock non-telephony component name and expect the Sub ID not converted to Icc ID 284 // and pending status is 0 when backup. 285 mockCursor(mCursor, false); 286 call = mCallLogBackupAgent.readCallFromCursor(mCursor); 287 assertEquals(TEST_PHONE_ACCOUNT_HANDLE_SUB_ID, call.accountId); 288 assertEquals(0, call.isPhoneAccountMigrationPending); 289 } 290 testReadCallFromCursor_WithNullAccountComponentName()291 public void testReadCallFromCursor_WithNullAccountComponentName() throws Exception { 292 testReadCallFromCursor_WithNullField(CallLog.Calls.PHONE_ACCOUNT_COMPONENT_NAME); 293 } 294 testReadCallFromCursor_WithNullNumber()295 public void testReadCallFromCursor_WithNullNumber() throws Exception { 296 testReadCallFromCursor_WithNullField(CallLog.Calls.NUMBER); 297 } 298 testReadCallFromCursor_WithNullPostDialDigits()299 public void testReadCallFromCursor_WithNullPostDialDigits() throws Exception { 300 testReadCallFromCursor_WithNullField(CallLog.Calls.POST_DIAL_DIGITS); 301 } 302 testReadCallFromCursor_WithNullViaNumber()303 public void testReadCallFromCursor_WithNullViaNumber() throws Exception { 304 testReadCallFromCursor_WithNullField(CallLog.Calls.VIA_NUMBER); 305 } 306 testReadCallFromCursor_WithNullPhoneAccountId()307 public void testReadCallFromCursor_WithNullPhoneAccountId() throws Exception { 308 testReadCallFromCursor_WithNullField(CallLog.Calls.PHONE_ACCOUNT_ID); 309 } 310 testReadCallFromCursor_WithNullCallAccountAddress()311 public void testReadCallFromCursor_WithNullCallAccountAddress() throws Exception { 312 testReadCallFromCursor_WithNullField(CallLog.Calls.PHONE_ACCOUNT_ADDRESS); 313 } 314 testReadCallFromCursor_WithNullCallScreeningAppName()315 public void testReadCallFromCursor_WithNullCallScreeningAppName() throws Exception { 316 testReadCallFromCursor_WithNullField(CallLog.Calls.CALL_SCREENING_APP_NAME); 317 } 318 testReadCallFromCursor_WithNullCallScreeningComponentName()319 public void testReadCallFromCursor_WithNullCallScreeningComponentName() throws Exception { 320 testReadCallFromCursor_WithNullField(CallLog.Calls.CALL_SCREENING_COMPONENT_NAME); 321 } 322 testReadCallFromCursor_WithNullMissedReason()323 public void testReadCallFromCursor_WithNullMissedReason() throws Exception { 324 testReadCallFromCursor_WithNullField(CallLog.Calls.MISSED_REASON); 325 } 326 testReadCallFromCursor_WithNullField(String field)327 private void testReadCallFromCursor_WithNullField(String field) throws Exception { 328 Map<Integer, String> subscriptionInfoMap = new HashMap<>(); 329 subscriptionInfoMap.put(TEST_PHONE_ACCOUNT_HANDLE_SUB_ID_INT, 330 TEST_PHONE_ACCOUNT_HANDLE_ICC_ID); 331 mCallLogBackupAgent.mSubscriptionInfoMap = subscriptionInfoMap; 332 333 //read from cursor and not throw exception 334 mockCursorWithNullFields(mCursor, field); 335 Call call = mCallLogBackupAgent.readCallFromCursor(mCursor); 336 } 337 testRunBackup_MultipleCall()338 public void testRunBackup_MultipleCall() throws Exception { 339 CallLogBackupState state = new CallLogBackupState(); 340 state.version = CallLogBackupAgent.VERSION; 341 state.callIds = new TreeSet<>(); 342 List<Call> calls = new LinkedList<>(); 343 calls.add(makeCall(101, 0L, 0L, "555-1234")); 344 calls.add(makeCall(102, 0L, 0L, "555-5555")); 345 346 mCallLogBackupAgent.runBackup(state, mBackupDataOutput, calls); 347 348 // Ensure the {@link BackupRestoreEventLogger} is informed of the 2 backed up calls: 349 assertEquals(backupRestoreLoggerSuccessCount, 2); 350 assertEquals(backupRestoreLoggerFailCount, 0); 351 352 InOrder inOrder = Mockito.inOrder(mBackupDataOutput); 353 inOrder.verify(mBackupDataOutput).writeEntityHeader(eq("101"), Matchers.anyInt()); 354 inOrder.verify(mBackupDataOutput). 355 writeEntityData((byte[]) Matchers.any(), Matchers.anyInt()); 356 inOrder.verify(mBackupDataOutput).writeEntityHeader(eq("102"), Matchers.anyInt()); 357 inOrder.verify(mBackupDataOutput). 358 writeEntityData((byte[]) Matchers.any(), Matchers.anyInt()); 359 } 360 testRunBackup_PartialMultipleCall()361 public void testRunBackup_PartialMultipleCall() throws Exception { 362 CallLogBackupState state = new CallLogBackupState(); 363 364 state.version = CallLogBackupAgent.VERSION; 365 state.callIds = new TreeSet<>(); 366 state.callIds.add(101); 367 368 List<Call> calls = new LinkedList<>(); 369 calls.add(makeCall(101, 0L, 0L, "555-1234")); 370 calls.add(makeCall(102, 0L, 0L, "555-5555")); 371 372 mCallLogBackupAgent.runBackup(state, mBackupDataOutput, calls); 373 374 // Ensure the {@link BackupRestoreEventLogger} is informed of the 2 backed up calls: 375 assertEquals(backupRestoreLoggerSuccessCount, 2); 376 assertEquals(backupRestoreLoggerFailCount, 0); 377 378 InOrder inOrder = Mockito.inOrder(mBackupDataOutput); 379 inOrder.verify(mBackupDataOutput).writeEntityHeader(eq("102"), Matchers.anyInt()); 380 inOrder.verify(mBackupDataOutput). 381 writeEntityData((byte[]) Matchers.any(), Matchers.anyInt()); 382 } 383 mockCursor(Cursor cursor, boolean isTelephonyComponentName)384 private static void mockCursor(Cursor cursor, boolean isTelephonyComponentName) { 385 when(cursor.moveToNext()).thenReturn(true).thenReturn(false); 386 387 int CALLS_ID_COLUMN_INDEX = 1; 388 int CALL_ID = 9; 389 when(cursor.getColumnIndex(CallLog.Calls._ID)).thenReturn(CALLS_ID_COLUMN_INDEX); 390 when(cursor.getInt(CALLS_ID_COLUMN_INDEX)).thenReturn(CALL_ID); 391 392 int CALLS_DATE_COLUMN_INDEX = 2; 393 long CALL_DATE = 20991231; 394 when(cursor.getColumnIndex(CallLog.Calls.DATE)).thenReturn(CALLS_DATE_COLUMN_INDEX); 395 when(cursor.getLong(CALLS_DATE_COLUMN_INDEX)).thenReturn(CALL_DATE); 396 397 int CALLS_DURATION_COLUMN_INDEX = 3; 398 long CALL_DURATION = 987654321; 399 when(cursor.getColumnIndex(CallLog.Calls.DURATION)).thenReturn( 400 CALLS_DURATION_COLUMN_INDEX); 401 when(cursor.getLong(CALLS_DURATION_COLUMN_INDEX)).thenReturn(CALL_DURATION); 402 403 int CALLS_NUMBER_COLUMN_INDEX = 4; 404 String CALL_NUMBER = "6316056461"; 405 when(cursor.getColumnIndex(CallLog.Calls.NUMBER)).thenReturn( 406 CALLS_NUMBER_COLUMN_INDEX); 407 when(cursor.getString(CALLS_NUMBER_COLUMN_INDEX)).thenReturn(CALL_NUMBER); 408 409 int CALLS_POST_DIAL_DIGITS_COLUMN_INDEX = 5; 410 String CALL_POST_DIAL_DIGITS = "54321"; 411 when(cursor.getColumnIndex(CallLog.Calls.POST_DIAL_DIGITS)).thenReturn( 412 CALLS_POST_DIAL_DIGITS_COLUMN_INDEX); 413 when(cursor.getString(CALLS_POST_DIAL_DIGITS_COLUMN_INDEX)).thenReturn( 414 CALL_POST_DIAL_DIGITS); 415 416 int CALLS_VIA_NUMBER_COLUMN_INDEX = 6; 417 String CALL_VIA_NUMBER = "via_number"; 418 when(cursor.getColumnIndex(CallLog.Calls.VIA_NUMBER)).thenReturn( 419 CALLS_VIA_NUMBER_COLUMN_INDEX); 420 when(cursor.getString(CALLS_VIA_NUMBER_COLUMN_INDEX)).thenReturn( 421 CALL_VIA_NUMBER); 422 423 int CALLS_TYPE_COLUMN_INDEX = 7; 424 int CALL_TYPE = CallLog.Calls.OUTGOING_TYPE; 425 when(cursor.getColumnIndex(CallLog.Calls.TYPE)).thenReturn(CALLS_TYPE_COLUMN_INDEX); 426 when(cursor.getInt(CALLS_TYPE_COLUMN_INDEX)).thenReturn(CALL_TYPE); 427 428 int CALLS_NUMBER_PRESENTATION_COLUMN_INDEX = 8; 429 int CALL_NUMBER_PRESENTATION = CallLog.Calls.PRESENTATION_ALLOWED; 430 when(cursor.getColumnIndex(CallLog.Calls.NUMBER_PRESENTATION)).thenReturn( 431 CALLS_NUMBER_PRESENTATION_COLUMN_INDEX); 432 when(cursor.getInt(CALLS_NUMBER_PRESENTATION_COLUMN_INDEX)).thenReturn( 433 CALL_NUMBER_PRESENTATION); 434 435 int CALLS_ACCOUNT_COMPONENT_NAME_COLUMN_INDEX = 9; 436 String CALL_ACCOUNT_COMPONENT_NAME = "NON_TELEPHONY_COMPONENT_NAME"; 437 if (isTelephonyComponentName) { 438 CALL_ACCOUNT_COMPONENT_NAME = TELEPHONY_COMPONENT; 439 } 440 when(cursor.getColumnIndex(CallLog.Calls.PHONE_ACCOUNT_COMPONENT_NAME)).thenReturn( 441 CALLS_ACCOUNT_COMPONENT_NAME_COLUMN_INDEX); 442 when(cursor.getString(CALLS_ACCOUNT_COMPONENT_NAME_COLUMN_INDEX)).thenReturn( 443 CALL_ACCOUNT_COMPONENT_NAME); 444 445 int CALLS_ACCOUNT_ID_COLUMN_INDEX = 10; 446 String CALL_ACCOUNT_ID = TEST_PHONE_ACCOUNT_HANDLE_SUB_ID; 447 when(cursor.getColumnIndex(CallLog.Calls.PHONE_ACCOUNT_ID)).thenReturn( 448 CALLS_ACCOUNT_ID_COLUMN_INDEX); 449 when(cursor.getString(CALLS_ACCOUNT_ID_COLUMN_INDEX)).thenReturn( 450 CALL_ACCOUNT_ID); 451 452 int CALLS_ACCOUNT_ADDRESS_COLUMN_INDEX = 11; 453 String CALL_ACCOUNT_ADDRESS = "CALL_ACCOUNT_ADDRESS"; 454 when(cursor.getColumnIndex(CallLog.Calls.PHONE_ACCOUNT_ADDRESS)).thenReturn( 455 CALLS_ACCOUNT_ADDRESS_COLUMN_INDEX); 456 when(cursor.getString(CALLS_ACCOUNT_ADDRESS_COLUMN_INDEX)).thenReturn( 457 CALL_ACCOUNT_ADDRESS); 458 459 int CALLS_DATA_USAGE_COLUMN_INDEX = 12; 460 long CALL_DATA_USAGE = 987654321; 461 when(cursor.getColumnIndex(CallLog.Calls.DATA_USAGE)).thenReturn( 462 CALLS_DATA_USAGE_COLUMN_INDEX); 463 when(cursor.getLong(CALLS_DATA_USAGE_COLUMN_INDEX)).thenReturn(CALL_DATA_USAGE); 464 465 int CALLS_FEATURES_COLUMN_INDEX = 13; 466 int CALL_FEATURES = 777; 467 when(cursor.getColumnIndex(CallLog.Calls.FEATURES)).thenReturn( 468 CALLS_FEATURES_COLUMN_INDEX); 469 when(cursor.getInt(CALLS_FEATURES_COLUMN_INDEX)).thenReturn(CALL_FEATURES); 470 471 int CALLS_ADD_FOR_ALL_USERS_COLUMN_INDEX = 14; 472 int CALL_ADD_FOR_ALL_USERS = 1; 473 when(cursor.getColumnIndex(CallLog.Calls.ADD_FOR_ALL_USERS)).thenReturn( 474 CALLS_ADD_FOR_ALL_USERS_COLUMN_INDEX); 475 when(cursor.getInt(CALLS_ADD_FOR_ALL_USERS_COLUMN_INDEX)).thenReturn( 476 CALL_ADD_FOR_ALL_USERS); 477 478 int CALLS_BLOCK_REASON_COLUMN_INDEX = 15; 479 int CALL_BLOCK_REASON = CallLog.Calls.BLOCK_REASON_NOT_BLOCKED; 480 when(cursor.getColumnIndex(CallLog.Calls.BLOCK_REASON)).thenReturn( 481 CALLS_BLOCK_REASON_COLUMN_INDEX); 482 when(cursor.getInt(CALLS_BLOCK_REASON_COLUMN_INDEX)).thenReturn( 483 CALL_BLOCK_REASON); 484 485 int CALLS_CALL_SCREENING_APP_NAME_COLUMN_INDEX = 16; 486 String CALL_CALL_SCREENING_APP_NAME = "CALL_CALL_SCREENING_APP_NAME"; 487 when(cursor.getColumnIndex(CallLog.Calls.CALL_SCREENING_APP_NAME)).thenReturn( 488 CALLS_CALL_SCREENING_APP_NAME_COLUMN_INDEX); 489 when(cursor.getString(CALLS_CALL_SCREENING_APP_NAME_COLUMN_INDEX)).thenReturn( 490 CALL_CALL_SCREENING_APP_NAME); 491 492 int CALLS_CALL_SCREENING_COMPONENT_NAME_COLUMN_INDEX = 17; 493 String CALL_CALL_SCREENING_COMPONENT_NAME = "CALL_CALL_SCREENING_COMPONENT_NAME"; 494 when(cursor.getColumnIndex(CallLog.Calls.CALL_SCREENING_COMPONENT_NAME)).thenReturn( 495 CALLS_CALL_SCREENING_COMPONENT_NAME_COLUMN_INDEX); 496 when(cursor.getString(CALLS_CALL_SCREENING_COMPONENT_NAME_COLUMN_INDEX)).thenReturn( 497 CALL_CALL_SCREENING_COMPONENT_NAME); 498 499 int CALLS_MISSED_REASON_COLUMN_INDEX = 18; 500 String CALL_MISSED_REASON = "CALL_MISSED_REASON"; 501 when(cursor.getColumnIndex(CallLog.Calls.MISSED_REASON)).thenReturn( 502 CALLS_MISSED_REASON_COLUMN_INDEX); 503 when(cursor.getString(CALLS_MISSED_REASON_COLUMN_INDEX)).thenReturn( 504 CALL_MISSED_REASON); 505 506 int CALLS_IS_PHONE_ACCOUNT_MIGRATION_PENDING_COLUMN_INDEX = 19; 507 int CALL_IS_PHONE_ACCOUNT_MIGRATION_PENDING = 0; 508 when(cursor.getColumnIndex(CallLog.Calls.IS_PHONE_ACCOUNT_MIGRATION_PENDING)).thenReturn( 509 CALLS_IS_PHONE_ACCOUNT_MIGRATION_PENDING_COLUMN_INDEX); 510 when(cursor.getInt(CALLS_IS_PHONE_ACCOUNT_MIGRATION_PENDING_COLUMN_INDEX)).thenReturn( 511 CALL_IS_PHONE_ACCOUNT_MIGRATION_PENDING); 512 } 513 514 //sets up the mock cursor with specified column data (string) set to null mockCursorWithNullFields(Cursor cursor, String columnToNullify)515 private static void mockCursorWithNullFields(Cursor cursor, String columnToNullify) { 516 when(cursor.moveToNext()).thenReturn(true).thenReturn(false); 517 518 int CALLS_ID_COLUMN_INDEX = 1; 519 int CALL_ID = 9; 520 when(cursor.getColumnIndex(CallLog.Calls._ID)).thenReturn(CALLS_ID_COLUMN_INDEX); 521 when(cursor.getInt(CALLS_ID_COLUMN_INDEX)).thenReturn(CALL_ID); 522 523 int CALLS_DATE_COLUMN_INDEX = 2; 524 long CALL_DATE = 20991231; 525 when(cursor.getColumnIndex(CallLog.Calls.DATE)).thenReturn(CALLS_DATE_COLUMN_INDEX); 526 when(cursor.getLong(CALLS_DATE_COLUMN_INDEX)).thenReturn(CALL_DATE); 527 528 int CALLS_DURATION_COLUMN_INDEX = 3; 529 long CALL_DURATION = 987654321; 530 when(cursor.getColumnIndex(CallLog.Calls.DURATION)).thenReturn( 531 CALLS_DURATION_COLUMN_INDEX); 532 when(cursor.getLong(CALLS_DURATION_COLUMN_INDEX)).thenReturn(CALL_DURATION); 533 534 int CALLS_NUMBER_COLUMN_INDEX = 4; 535 String CALL_NUMBER = "6316056461"; 536 when(cursor.getColumnIndex(CallLog.Calls.NUMBER)).thenReturn( 537 CALLS_NUMBER_COLUMN_INDEX); 538 if (CallLog.Calls.NUMBER.equals(columnToNullify)) { 539 when(cursor.getString(CALLS_NUMBER_COLUMN_INDEX)).thenReturn(null); 540 } else { 541 when(cursor.getString(CALLS_NUMBER_COLUMN_INDEX)).thenReturn(CALL_NUMBER); 542 } 543 544 int CALLS_POST_DIAL_DIGITS_COLUMN_INDEX = 5; 545 String CALL_POST_DIAL_DIGITS = "54321"; 546 when(cursor.getColumnIndex(CallLog.Calls.POST_DIAL_DIGITS)).thenReturn( 547 CALLS_POST_DIAL_DIGITS_COLUMN_INDEX); 548 if (CallLog.Calls.POST_DIAL_DIGITS.equals(columnToNullify)) { 549 when(cursor.getString(CALLS_POST_DIAL_DIGITS_COLUMN_INDEX)).thenReturn( 550 null); 551 } else { 552 when(cursor.getString(CALLS_POST_DIAL_DIGITS_COLUMN_INDEX)).thenReturn( 553 CALL_POST_DIAL_DIGITS); 554 } 555 556 int CALLS_VIA_NUMBER_COLUMN_INDEX = 6; 557 String CALL_VIA_NUMBER = "via_number"; 558 when(cursor.getColumnIndex(CallLog.Calls.VIA_NUMBER)).thenReturn( 559 CALLS_VIA_NUMBER_COLUMN_INDEX); 560 if (CallLog.Calls.VIA_NUMBER.equals(columnToNullify)) { 561 when(cursor.getString(CALLS_VIA_NUMBER_COLUMN_INDEX)).thenReturn( 562 null); 563 } else { 564 when(cursor.getString(CALLS_VIA_NUMBER_COLUMN_INDEX)).thenReturn( 565 CALL_VIA_NUMBER); 566 } 567 568 int CALLS_TYPE_COLUMN_INDEX = 7; 569 int CALL_TYPE = CallLog.Calls.OUTGOING_TYPE; 570 when(cursor.getColumnIndex(CallLog.Calls.TYPE)).thenReturn(CALLS_TYPE_COLUMN_INDEX); 571 when(cursor.getInt(CALLS_TYPE_COLUMN_INDEX)).thenReturn(CALL_TYPE); 572 573 int CALLS_NUMBER_PRESENTATION_COLUMN_INDEX = 8; 574 int CALL_NUMBER_PRESENTATION = CallLog.Calls.PRESENTATION_ALLOWED; 575 when(cursor.getColumnIndex(CallLog.Calls.NUMBER_PRESENTATION)).thenReturn( 576 CALLS_NUMBER_PRESENTATION_COLUMN_INDEX); 577 when(cursor.getInt(CALLS_NUMBER_PRESENTATION_COLUMN_INDEX)).thenReturn( 578 CALL_NUMBER_PRESENTATION); 579 580 int CALLS_ACCOUNT_COMPONENT_NAME_COLUMN_INDEX = 9; 581 String CALL_ACCOUNT_COMPONENT_NAME = TELEPHONY_COMPONENT; 582 when(cursor.getColumnIndex(CallLog.Calls.PHONE_ACCOUNT_COMPONENT_NAME)).thenReturn( 583 CALLS_ACCOUNT_COMPONENT_NAME_COLUMN_INDEX); 584 if (CallLog.Calls.PHONE_ACCOUNT_COMPONENT_NAME.equals(columnToNullify)) { 585 when(cursor.getString(CALLS_ACCOUNT_COMPONENT_NAME_COLUMN_INDEX)).thenReturn( 586 null); 587 } else { 588 when(cursor.getString(CALLS_ACCOUNT_COMPONENT_NAME_COLUMN_INDEX)).thenReturn( 589 CALL_ACCOUNT_COMPONENT_NAME); 590 } 591 592 int CALLS_ACCOUNT_ID_COLUMN_INDEX = 10; 593 String CALL_ACCOUNT_ID = TEST_PHONE_ACCOUNT_HANDLE_SUB_ID; 594 when(cursor.getColumnIndex(CallLog.Calls.PHONE_ACCOUNT_ID)).thenReturn( 595 CALLS_ACCOUNT_ID_COLUMN_INDEX); 596 if (CallLog.Calls.PHONE_ACCOUNT_ID.equals(columnToNullify)) { 597 when(cursor.getString(CALLS_ACCOUNT_ID_COLUMN_INDEX)).thenReturn( 598 null); 599 } else { 600 when(cursor.getString(CALLS_ACCOUNT_ID_COLUMN_INDEX)).thenReturn( 601 CALL_ACCOUNT_ID); 602 } 603 604 int CALLS_ACCOUNT_ADDRESS_COLUMN_INDEX = 11; 605 String CALL_ACCOUNT_ADDRESS = "CALL_ACCOUNT_ADDRESS"; 606 when(cursor.getColumnIndex(CallLog.Calls.PHONE_ACCOUNT_ADDRESS)).thenReturn( 607 CALLS_ACCOUNT_ADDRESS_COLUMN_INDEX); 608 if (CallLog.Calls.PHONE_ACCOUNT_ADDRESS.equals(columnToNullify)) { 609 when(cursor.getString(CALLS_ACCOUNT_ADDRESS_COLUMN_INDEX)).thenReturn( 610 null); 611 } else { 612 when(cursor.getString(CALLS_ACCOUNT_ADDRESS_COLUMN_INDEX)).thenReturn( 613 CALL_ACCOUNT_ADDRESS); 614 } 615 616 int CALLS_DATA_USAGE_COLUMN_INDEX = 12; 617 long CALL_DATA_USAGE = 987654321; 618 when(cursor.getColumnIndex(CallLog.Calls.DATA_USAGE)).thenReturn( 619 CALLS_DATA_USAGE_COLUMN_INDEX); 620 when(cursor.getLong(CALLS_DATA_USAGE_COLUMN_INDEX)).thenReturn(CALL_DATA_USAGE); 621 622 int CALLS_FEATURES_COLUMN_INDEX = 13; 623 int CALL_FEATURES = 777; 624 when(cursor.getColumnIndex(CallLog.Calls.FEATURES)).thenReturn( 625 CALLS_FEATURES_COLUMN_INDEX); 626 when(cursor.getInt(CALLS_FEATURES_COLUMN_INDEX)).thenReturn(CALL_FEATURES); 627 628 int CALLS_ADD_FOR_ALL_USERS_COLUMN_INDEX = 14; 629 int CALL_ADD_FOR_ALL_USERS = 1; 630 when(cursor.getColumnIndex(CallLog.Calls.ADD_FOR_ALL_USERS)).thenReturn( 631 CALLS_ADD_FOR_ALL_USERS_COLUMN_INDEX); 632 when(cursor.getInt(CALLS_ADD_FOR_ALL_USERS_COLUMN_INDEX)).thenReturn( 633 CALL_ADD_FOR_ALL_USERS); 634 635 int CALLS_BLOCK_REASON_COLUMN_INDEX = 15; 636 int CALL_BLOCK_REASON = CallLog.Calls.BLOCK_REASON_NOT_BLOCKED; 637 when(cursor.getColumnIndex(CallLog.Calls.BLOCK_REASON)).thenReturn( 638 CALLS_BLOCK_REASON_COLUMN_INDEX); 639 when(cursor.getInt(CALLS_BLOCK_REASON_COLUMN_INDEX)).thenReturn( 640 CALL_BLOCK_REASON); 641 642 int CALLS_CALL_SCREENING_APP_NAME_COLUMN_INDEX = 16; 643 String CALL_CALL_SCREENING_APP_NAME = "CALL_CALL_SCREENING_APP_NAME"; 644 when(cursor.getColumnIndex(CallLog.Calls.CALL_SCREENING_APP_NAME)).thenReturn( 645 CALLS_CALL_SCREENING_APP_NAME_COLUMN_INDEX); 646 if (CallLog.Calls.CALL_SCREENING_APP_NAME.equals(columnToNullify)) { 647 when(cursor.getString(CALLS_CALL_SCREENING_APP_NAME_COLUMN_INDEX)).thenReturn( 648 null); 649 } else { 650 when(cursor.getString(CALLS_CALL_SCREENING_APP_NAME_COLUMN_INDEX)).thenReturn( 651 CALL_CALL_SCREENING_APP_NAME); 652 } 653 654 int CALLS_CALL_SCREENING_COMPONENT_NAME_COLUMN_INDEX = 17; 655 String CALL_CALL_SCREENING_COMPONENT_NAME = "CALL_CALL_SCREENING_COMPONENT_NAME"; 656 when(cursor.getColumnIndex(CallLog.Calls.CALL_SCREENING_COMPONENT_NAME)).thenReturn( 657 CALLS_CALL_SCREENING_COMPONENT_NAME_COLUMN_INDEX); 658 if (CallLog.Calls.CALL_SCREENING_COMPONENT_NAME.equals(columnToNullify)) { 659 when(cursor.getString(CALLS_CALL_SCREENING_COMPONENT_NAME_COLUMN_INDEX)).thenReturn( 660 null); 661 } else { 662 when(cursor.getString(CALLS_CALL_SCREENING_COMPONENT_NAME_COLUMN_INDEX)).thenReturn( 663 CALL_CALL_SCREENING_COMPONENT_NAME); 664 } 665 666 int CALLS_MISSED_REASON_COLUMN_INDEX = 18; 667 String CALL_MISSED_REASON = "CALL_MISSED_REASON"; 668 when(cursor.getColumnIndex(CallLog.Calls.MISSED_REASON)).thenReturn( 669 CALLS_MISSED_REASON_COLUMN_INDEX); 670 if (CallLog.Calls.MISSED_REASON.equals(columnToNullify)) { 671 when(cursor.getString(CALLS_MISSED_REASON_COLUMN_INDEX)).thenReturn( 672 null); 673 } else { 674 when(cursor.getString(CALLS_MISSED_REASON_COLUMN_INDEX)).thenReturn( 675 CALL_MISSED_REASON); 676 } 677 678 int CALLS_IS_PHONE_ACCOUNT_MIGRATION_PENDING_COLUMN_INDEX = 19; 679 int CALL_IS_PHONE_ACCOUNT_MIGRATION_PENDING = 0; 680 when(cursor.getColumnIndex(CallLog.Calls.IS_PHONE_ACCOUNT_MIGRATION_PENDING)).thenReturn( 681 CALLS_IS_PHONE_ACCOUNT_MIGRATION_PENDING_COLUMN_INDEX); 682 when(cursor.getInt(CALLS_IS_PHONE_ACCOUNT_MIGRATION_PENDING_COLUMN_INDEX)).thenReturn( 683 CALL_IS_PHONE_ACCOUNT_MIGRATION_PENDING); 684 } 685 makeCall(int id, long date, long duration, String number)686 private static Call makeCall(int id, long date, long duration, String number) { 687 Call c = new Call(); 688 c.id = id; 689 c.date = date; 690 c.duration = duration; 691 c.number = number; 692 c.accountComponentName = "account-component"; 693 c.accountId = "account-id"; 694 return c; 695 } 696 697 } 698