CallLogManagerTest.java revision c9bb95616469ae02cc43a57ea827b45261d49e26
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 17package com.android.server.telecom.tests; 18 19 20import android.content.ComponentName; 21import android.content.ContentProvider; 22import android.content.ContentValues; 23import android.content.Context; 24import android.content.IContentProvider; 25import android.content.pm.UserInfo; 26import android.net.Uri; 27import android.os.UserHandle; 28import android.os.UserManager; 29import android.provider.CallLog; 30import android.provider.CallLog.Calls; 31import android.telecom.DisconnectCause; 32import android.telecom.PhoneAccount; 33import android.telecom.PhoneAccountHandle; 34import android.telecom.VideoProfile; 35 36import com.android.server.telecom.Call; 37import com.android.server.telecom.CallLogManager; 38import com.android.server.telecom.CallState; 39import com.android.server.telecom.PhoneAccountRegistrar; 40import com.android.server.telecom.TelephonyUtil; 41 42import static org.mockito.Matchers.any; 43import static org.mockito.Matchers.anyString; 44import static org.mockito.Matchers.eq; 45import static org.mockito.Mockito.doAnswer; 46import static org.mockito.Mockito.mock; 47import static org.mockito.Mockito.timeout; 48import static org.mockito.Mockito.verify; 49import static org.mockito.Mockito.when; 50 51import org.mockito.ArgumentCaptor; 52import org.mockito.Mock; 53import org.mockito.invocation.InvocationOnMock; 54import org.mockito.stubbing.Answer; 55 56import java.util.Arrays; 57 58public class CallLogManagerTest extends TelecomTestCase { 59 60 private CallLogManager mCallLogManager; 61 private IContentProvider mContentProvider; 62 private PhoneAccountHandle mDefaultAccountHandle; 63 private PhoneAccountHandle mOtherUserAccountHandle; 64 private PhoneAccountHandle mManagedProfileAccountHandle; 65 66 private static final Uri TEL_PHONEHANDLE = Uri.parse("tel:5555551234"); 67 68 private static final PhoneAccountHandle EMERGENCY_ACCT_HANDLE = TelephonyUtil 69 .getDefaultEmergencyPhoneAccount() 70 .getAccountHandle(); 71 72 private static final int NO_VIDEO_STATE = VideoProfile.STATE_AUDIO_ONLY; 73 private static final int BIDIRECTIONAL_VIDEO_STATE = VideoProfile.STATE_BIDIRECTIONAL; 74 private static final String POST_DIAL_STRING = ";12345"; 75 private static final String TEST_PHONE_ACCOUNT_ID= "testPhoneAccountId"; 76 77 private static final int TEST_TIMEOUT_MILLIS = 200; 78 private static final int CURRENT_USER_ID = 0; 79 private static final int OTHER_USER_ID = 10; 80 private static final int MANAGED_USER_ID = 11; 81 82 @Mock 83 PhoneAccountRegistrar mMockPhoneAccountRegistrar; 84 85 86 @Override 87 public void setUp() throws Exception { 88 super.setUp(); 89 mContext = mComponentContextFixture.getTestDouble().getApplicationContext(); 90 mCallLogManager = new CallLogManager(mContext, mMockPhoneAccountRegistrar); 91 mContentProvider = mContext.getContentResolver().acquireProvider("test"); 92 mDefaultAccountHandle = new PhoneAccountHandle( 93 new ComponentName("com.android.server.telecom.tests", "CallLogManagerTest"), 94 TEST_PHONE_ACCOUNT_ID, 95 UserHandle.of(CURRENT_USER_ID) 96 ); 97 98 mOtherUserAccountHandle = new PhoneAccountHandle( 99 new ComponentName("com.android.server.telecom.tests", "CallLogManagerTest"), 100 TEST_PHONE_ACCOUNT_ID, 101 UserHandle.of(OTHER_USER_ID) 102 ); 103 104 mManagedProfileAccountHandle = new PhoneAccountHandle( 105 new ComponentName("com.android.server.telecom.tests", "CallLogManagerTest"), 106 TEST_PHONE_ACCOUNT_ID, 107 UserHandle.of(MANAGED_USER_ID) 108 ); 109 110 UserManager userManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); 111 UserInfo userInfo = new UserInfo(CURRENT_USER_ID, "test", 0); 112 UserInfo otherUserInfo = new UserInfo(OTHER_USER_ID, "test2", 0); 113 UserInfo managedProfileUserInfo = new UserInfo(OTHER_USER_ID, "test3", 114 UserInfo.FLAG_MANAGED_PROFILE); 115 116 doAnswer(new Answer<Uri>() { 117 @Override 118 public Uri answer(InvocationOnMock invocation) throws Throwable { 119 return (Uri) invocation.getArguments()[1]; 120 } 121 }).when(mContentProvider).insert(anyString(), any(Uri.class), any(ContentValues.class)); 122 123 when(userManager.isUserRunning(any(UserHandle.class))).thenReturn(true); 124 when(userManager.isUserUnlocked(any(UserHandle.class))).thenReturn(true); 125 when(userManager.hasUserRestriction(any(String.class), any(UserHandle.class))) 126 .thenReturn(false); 127 when(userManager.getUsers(any(Boolean.class))) 128 .thenReturn(Arrays.asList(userInfo, otherUserInfo, managedProfileUserInfo)); 129 when(userManager.getUserInfo(eq(CURRENT_USER_ID))).thenReturn(userInfo); 130 when(userManager.getUserInfo(eq(OTHER_USER_ID))).thenReturn(otherUserInfo); 131 when(userManager.getUserInfo(eq(MANAGED_USER_ID))).thenReturn(managedProfileUserInfo); 132 } 133 134 public void testDontLogCancelledCall() { 135 Call fakeCall = makeFakeCall( 136 DisconnectCause.CANCELED, 137 false, // isConference 138 false, // isIncoming 139 1L, // creationTimeMillis 140 1000L, // ageMillis 141 TEL_PHONEHANDLE, // callHandle 142 mDefaultAccountHandle, // phoneAccountHandle 143 NO_VIDEO_STATE, // callVideoState 144 POST_DIAL_STRING, // postDialDigits, 145 UserHandle.of(CURRENT_USER_ID) 146 ); 147 mCallLogManager.onCallStateChanged(fakeCall, CallState.DIALING, CallState.DISCONNECTED); 148 verifyNoInsertion(); 149 mCallLogManager.onCallStateChanged(fakeCall, CallState.DIALING, CallState.ABORTED); 150 verifyNoInsertion(); 151 } 152 153 public void testDontLogChoosingAccountCall() { 154 when(mMockPhoneAccountRegistrar.getPhoneAccountUnchecked(any(PhoneAccountHandle.class))) 155 .thenReturn(makeFakePhoneAccount(mDefaultAccountHandle, CURRENT_USER_ID)); 156 Call fakeCall = makeFakeCall( 157 DisconnectCause.OTHER, // disconnectCauseCode 158 false, // isConference 159 false, // isIncoming 160 1L, // creationTimeMillis 161 1000L, // ageMillis 162 TEL_PHONEHANDLE, // callHandle 163 mDefaultAccountHandle, // phoneAccountHandle 164 NO_VIDEO_STATE, // callVideoState 165 POST_DIAL_STRING, // postDialDigits 166 UserHandle.of(CURRENT_USER_ID) 167 ); 168 mCallLogManager.onCallStateChanged(fakeCall, CallState.SELECT_PHONE_ACCOUNT, 169 CallState.DISCONNECTED); 170 verifyNoInsertion(); 171 } 172 173 public void testDontLogCallsFromEmergencyAccount() { 174 when(mMockPhoneAccountRegistrar.getPhoneAccountUnchecked(any(PhoneAccountHandle.class))) 175 .thenReturn(makeFakePhoneAccount(EMERGENCY_ACCT_HANDLE, 0)); 176 mComponentContextFixture.putBooleanResource(R.bool.allow_emergency_numbers_in_call_log, 177 false); 178 Call fakeCall = makeFakeCall( 179 DisconnectCause.OTHER, // disconnectCauseCode 180 false, // isConference 181 false, // isIncoming 182 1L, // creationTimeMillis 183 1000L, // ageMillis 184 TEL_PHONEHANDLE, // callHandle 185 EMERGENCY_ACCT_HANDLE, // phoneAccountHandle 186 NO_VIDEO_STATE, // callVideoState 187 POST_DIAL_STRING, // postDialDigits, 188 UserHandle.of(CURRENT_USER_ID) 189 ); 190 mCallLogManager.onCallStateChanged(fakeCall, CallState.ACTIVE, CallState.DISCONNECTED); 191 verifyNoInsertion(); 192 } 193 194 public void testLogCallDirectionOutgoing() { 195 when(mMockPhoneAccountRegistrar.getPhoneAccountUnchecked(any(PhoneAccountHandle.class))) 196 .thenReturn(makeFakePhoneAccount(mDefaultAccountHandle, CURRENT_USER_ID)); 197 Call fakeOutgoingCall = makeFakeCall( 198 DisconnectCause.OTHER, // disconnectCauseCode 199 false, // isConference 200 false, // isIncoming 201 1L, // creationTimeMillis 202 1000L, // ageMillis 203 TEL_PHONEHANDLE, // callHandle 204 mDefaultAccountHandle, // phoneAccountHandle 205 NO_VIDEO_STATE, // callVideoState 206 POST_DIAL_STRING, // postDialDigits 207 UserHandle.of(CURRENT_USER_ID) 208 ); 209 mCallLogManager.onCallStateChanged(fakeOutgoingCall, CallState.ACTIVE, 210 CallState.DISCONNECTED); 211 ContentValues insertedValues = verifyInsertionWithCapture(CURRENT_USER_ID); 212 assertEquals(insertedValues.getAsInteger(CallLog.Calls.TYPE), 213 Integer.valueOf(CallLog.Calls.OUTGOING_TYPE)); 214 } 215 216 public void testLogCallDirectionIncoming() { 217 when(mMockPhoneAccountRegistrar.getPhoneAccountUnchecked(any(PhoneAccountHandle.class))) 218 .thenReturn(makeFakePhoneAccount(mDefaultAccountHandle, CURRENT_USER_ID)); 219 Call fakeIncomingCall = makeFakeCall( 220 DisconnectCause.OTHER, // disconnectCauseCode 221 false, // isConference 222 true, // isIncoming 223 1L, // creationTimeMillis 224 1000L, // ageMillis 225 TEL_PHONEHANDLE, // callHandle 226 mDefaultAccountHandle, // phoneAccountHandle 227 NO_VIDEO_STATE, // callVideoState 228 POST_DIAL_STRING, // postDialDigits 229 null 230 ); 231 mCallLogManager.onCallStateChanged(fakeIncomingCall, CallState.ACTIVE, 232 CallState.DISCONNECTED); 233 ContentValues insertedValues = verifyInsertionWithCapture(CURRENT_USER_ID); 234 assertEquals(insertedValues.getAsInteger(CallLog.Calls.TYPE), 235 Integer.valueOf(CallLog.Calls.INCOMING_TYPE)); 236 } 237 238 public void testLogCallDirectionMissed() { 239 when(mMockPhoneAccountRegistrar.getPhoneAccountUnchecked(any(PhoneAccountHandle.class))) 240 .thenReturn(makeFakePhoneAccount(mDefaultAccountHandle, CURRENT_USER_ID)); 241 Call fakeMissedCall = makeFakeCall( 242 DisconnectCause.MISSED, // disconnectCauseCode 243 false, // isConference 244 true, // isIncoming 245 1L, // creationTimeMillis 246 1000L, // ageMillis 247 TEL_PHONEHANDLE, // callHandle 248 mDefaultAccountHandle, // phoneAccountHandle 249 NO_VIDEO_STATE, // callVideoState 250 POST_DIAL_STRING, // postDialDigits 251 null 252 ); 253 254 mCallLogManager.onCallStateChanged(fakeMissedCall, CallState.ACTIVE, 255 CallState.DISCONNECTED); 256 ContentValues insertedValues = verifyInsertionWithCapture(CURRENT_USER_ID); 257 assertEquals(insertedValues.getAsInteger(CallLog.Calls.TYPE), 258 Integer.valueOf(CallLog.Calls.MISSED_TYPE)); 259 } 260 261 public void testCreationTimeAndAge() { 262 when(mMockPhoneAccountRegistrar.getPhoneAccountUnchecked(any(PhoneAccountHandle.class))) 263 .thenReturn(makeFakePhoneAccount(mDefaultAccountHandle, CURRENT_USER_ID)); 264 long currentTime = System.currentTimeMillis(); 265 long duration = 1000L; 266 Call fakeCall = makeFakeCall( 267 DisconnectCause.OTHER, // disconnectCauseCode 268 false, // isConference 269 false, // isIncoming 270 currentTime, // creationTimeMillis 271 duration, // ageMillis 272 TEL_PHONEHANDLE, // callHandle 273 mDefaultAccountHandle, // phoneAccountHandle 274 NO_VIDEO_STATE, // callVideoState 275 POST_DIAL_STRING, // postDialDigits 276 UserHandle.of(CURRENT_USER_ID) 277 ); 278 mCallLogManager.onCallStateChanged(fakeCall, CallState.ACTIVE, CallState.DISCONNECTED); 279 ContentValues insertedValues = verifyInsertionWithCapture(CURRENT_USER_ID); 280 assertEquals(insertedValues.getAsLong(CallLog.Calls.DATE), 281 Long.valueOf(currentTime)); 282 assertEquals(insertedValues.getAsLong(CallLog.Calls.DURATION), 283 Long.valueOf(duration / 1000)); 284 } 285 286 public void testLogPhoneAccountId() { 287 when(mMockPhoneAccountRegistrar.getPhoneAccountUnchecked(any(PhoneAccountHandle.class))) 288 .thenReturn(makeFakePhoneAccount(mDefaultAccountHandle, CURRENT_USER_ID)); 289 Call fakeCall = makeFakeCall( 290 DisconnectCause.OTHER, // disconnectCauseCode 291 false, // isConference 292 true, // isIncoming 293 1L, // creationTimeMillis 294 1000L, // ageMillis 295 TEL_PHONEHANDLE, // callHandle 296 mDefaultAccountHandle, // phoneAccountHandle 297 NO_VIDEO_STATE, // callVideoState 298 POST_DIAL_STRING, // postDialDigits 299 UserHandle.of(CURRENT_USER_ID) 300 ); 301 mCallLogManager.onCallStateChanged(fakeCall, CallState.ACTIVE, CallState.DISCONNECTED); 302 ContentValues insertedValues = verifyInsertionWithCapture(CURRENT_USER_ID); 303 assertEquals(insertedValues.getAsString(CallLog.Calls.PHONE_ACCOUNT_ID), 304 TEST_PHONE_ACCOUNT_ID); 305 } 306 307 public void testLogCorrectPhoneNumber() { 308 when(mMockPhoneAccountRegistrar.getPhoneAccountUnchecked(any(PhoneAccountHandle.class))) 309 .thenReturn(makeFakePhoneAccount(mDefaultAccountHandle, CURRENT_USER_ID)); 310 Call fakeCall = makeFakeCall( 311 DisconnectCause.OTHER, // disconnectCauseCode 312 false, // isConference 313 true, // isIncoming 314 1L, // creationTimeMillis 315 1000L, // ageMillis 316 TEL_PHONEHANDLE, // callHandle 317 mDefaultAccountHandle, // phoneAccountHandle 318 NO_VIDEO_STATE, // callVideoState 319 POST_DIAL_STRING, // postDialDigits 320 UserHandle.of(CURRENT_USER_ID) 321 ); 322 mCallLogManager.onCallStateChanged(fakeCall, CallState.ACTIVE, CallState.DISCONNECTED); 323 ContentValues insertedValues = verifyInsertionWithCapture(CURRENT_USER_ID); 324 assertEquals(insertedValues.getAsString(CallLog.Calls.NUMBER), 325 TEL_PHONEHANDLE.getSchemeSpecificPart()); 326 assertEquals(insertedValues.getAsString(CallLog.Calls.POST_DIAL_DIGITS), POST_DIAL_STRING); 327 } 328 329 public void testLogCallVideoFeatures() { 330 when(mMockPhoneAccountRegistrar.getPhoneAccountUnchecked(any(PhoneAccountHandle.class))) 331 .thenReturn(makeFakePhoneAccount(mDefaultAccountHandle, CURRENT_USER_ID)); 332 Call fakeVideoCall = makeFakeCall( 333 DisconnectCause.OTHER, // disconnectCauseCode 334 false, // isConference 335 true, // isIncoming 336 1L, // creationTimeMillis 337 1000L, // ageMillis 338 TEL_PHONEHANDLE, // callHandle 339 mDefaultAccountHandle, // phoneAccountHandle 340 BIDIRECTIONAL_VIDEO_STATE, // callVideoState 341 POST_DIAL_STRING, // postDialDigits 342 UserHandle.of(CURRENT_USER_ID) 343 ); 344 mCallLogManager.onCallStateChanged(fakeVideoCall, CallState.ACTIVE, CallState.DISCONNECTED); 345 ContentValues insertedValues = verifyInsertionWithCapture(CURRENT_USER_ID); 346 assertTrue((insertedValues.getAsInteger(CallLog.Calls.FEATURES) 347 & CallLog.Calls.FEATURES_VIDEO) == CallLog.Calls.FEATURES_VIDEO); 348 } 349 350 public void testLogCallDirectionOutgoingWithMultiUserCapability() { 351 when(mMockPhoneAccountRegistrar.getPhoneAccountUnchecked(any(PhoneAccountHandle.class))) 352 .thenReturn(makeFakePhoneAccount(mOtherUserAccountHandle, 353 PhoneAccount.CAPABILITY_MULTI_USER)); 354 Call fakeOutgoingCall = makeFakeCall( 355 DisconnectCause.OTHER, // disconnectCauseCode 356 false, // isConference 357 false, // isIncoming 358 1L, // creationTimeMillis 359 1000L, // ageMillis 360 TEL_PHONEHANDLE, // callHandle 361 mDefaultAccountHandle, // phoneAccountHandle 362 NO_VIDEO_STATE, // callVideoState 363 POST_DIAL_STRING, // postDialDigits 364 UserHandle.of(CURRENT_USER_ID) 365 ); 366 mCallLogManager.onCallStateChanged(fakeOutgoingCall, CallState.ACTIVE, 367 CallState.DISCONNECTED); 368 369 // Outgoing call placed through a phone account with multi user capability is inserted to 370 // all users except managed profile. 371 ContentValues insertedValues = verifyInsertionWithCapture(CURRENT_USER_ID); 372 assertEquals(insertedValues.getAsInteger(CallLog.Calls.TYPE), 373 Integer.valueOf(CallLog.Calls.OUTGOING_TYPE)); 374 insertedValues = verifyInsertionWithCapture(OTHER_USER_ID); 375 assertEquals(insertedValues.getAsInteger(CallLog.Calls.TYPE), 376 Integer.valueOf(CallLog.Calls.OUTGOING_TYPE)); 377 verifyNoInsertionInUser(MANAGED_USER_ID); 378 } 379 380 public void testLogCallDirectionIncomingWithMultiUserCapability() { 381 when(mMockPhoneAccountRegistrar.getPhoneAccountUnchecked(any(PhoneAccountHandle.class))) 382 .thenReturn(makeFakePhoneAccount(mOtherUserAccountHandle, 383 PhoneAccount.CAPABILITY_MULTI_USER)); 384 Call fakeIncomingCall = makeFakeCall( 385 DisconnectCause.OTHER, // disconnectCauseCode 386 false, // isConference 387 true, // isIncoming 388 1L, // creationTimeMillis 389 1000L, // ageMillis 390 TEL_PHONEHANDLE, // callHandle 391 mDefaultAccountHandle, // phoneAccountHandle 392 NO_VIDEO_STATE, // callVideoState 393 POST_DIAL_STRING, // postDialDigits 394 null 395 ); 396 mCallLogManager.onCallStateChanged(fakeIncomingCall, CallState.ACTIVE, 397 CallState.DISCONNECTED); 398 399 // Incoming call using a phone account with multi user capability is inserted to all users 400 // except managed profile. 401 ContentValues insertedValues = verifyInsertionWithCapture(CURRENT_USER_ID); 402 assertEquals(insertedValues.getAsInteger(CallLog.Calls.TYPE), 403 Integer.valueOf(CallLog.Calls.INCOMING_TYPE)); 404 insertedValues = verifyInsertionWithCapture(OTHER_USER_ID); 405 assertEquals(insertedValues.getAsInteger(CallLog.Calls.TYPE), 406 Integer.valueOf(CallLog.Calls.INCOMING_TYPE)); 407 verifyNoInsertionInUser(MANAGED_USER_ID); 408 } 409 410 411 public void testLogCallDirectionOutgoingWithMultiUserCapabilityFromManagedProfile() { 412 when(mMockPhoneAccountRegistrar.getPhoneAccountUnchecked(any(PhoneAccountHandle.class))) 413 .thenReturn(makeFakePhoneAccount(mManagedProfileAccountHandle, 414 PhoneAccount.CAPABILITY_MULTI_USER)); 415 Call fakeOutgoingCall = makeFakeCall( 416 DisconnectCause.OTHER, // disconnectCauseCode 417 false, // isConference 418 false, // isIncoming 419 1L, // creationTimeMillis 420 1000L, // ageMillis 421 TEL_PHONEHANDLE, // callHandle 422 mManagedProfileAccountHandle, // phoneAccountHandle 423 NO_VIDEO_STATE, // callVideoState 424 POST_DIAL_STRING, // postDialDigits 425 UserHandle.of(MANAGED_USER_ID) 426 ); 427 mCallLogManager.onCallStateChanged(fakeOutgoingCall, CallState.ACTIVE, 428 CallState.DISCONNECTED); 429 430 // Outgoing call placed through work dialer should be inserted to managed profile only. 431 verifyNoInsertionInUser(CURRENT_USER_ID); 432 verifyNoInsertionInUser(OTHER_USER_ID); 433 ContentValues insertedValues = verifyInsertionWithCapture(MANAGED_USER_ID); 434 assertEquals(insertedValues.getAsInteger(CallLog.Calls.TYPE), 435 Integer.valueOf(CallLog.Calls.OUTGOING_TYPE)); 436 } 437 438 public void testLogCallDirectionOutgoingFromManagedProfile() { 439 when(mMockPhoneAccountRegistrar.getPhoneAccountUnchecked(any(PhoneAccountHandle.class))) 440 .thenReturn(makeFakePhoneAccount(mManagedProfileAccountHandle, 0)); 441 Call fakeOutgoingCall = makeFakeCall( 442 DisconnectCause.OTHER, // disconnectCauseCode 443 false, // isConference 444 false, // isIncoming 445 1L, // creationTimeMillis 446 1000L, // ageMillis 447 TEL_PHONEHANDLE, // callHandle 448 mManagedProfileAccountHandle, // phoneAccountHandle 449 NO_VIDEO_STATE, // callVideoState 450 POST_DIAL_STRING, // postDialDigits 451 UserHandle.of(MANAGED_USER_ID) 452 ); 453 mCallLogManager.onCallStateChanged(fakeOutgoingCall, CallState.ACTIVE, 454 CallState.DISCONNECTED); 455 456 // Outgoing call using phone account in managed profile should be inserted to managed 457 // profile only. 458 verifyNoInsertionInUser(CURRENT_USER_ID); 459 verifyNoInsertionInUser(OTHER_USER_ID); 460 ContentValues insertedValues = verifyInsertionWithCapture(MANAGED_USER_ID); 461 assertEquals(insertedValues.getAsInteger(CallLog.Calls.TYPE), 462 Integer.valueOf(CallLog.Calls.OUTGOING_TYPE)); 463 } 464 465 public void testLogCallDirectionIngoingFromManagedProfile() { 466 when(mMockPhoneAccountRegistrar.getPhoneAccountUnchecked(any(PhoneAccountHandle.class))) 467 .thenReturn(makeFakePhoneAccount(mManagedProfileAccountHandle, 0)); 468 Call fakeOutgoingCall = makeFakeCall( 469 DisconnectCause.OTHER, // disconnectCauseCode 470 false, // isConference 471 true, // isIncoming 472 1L, // creationTimeMillis 473 1000L, // ageMillis 474 TEL_PHONEHANDLE, // callHandle 475 mManagedProfileAccountHandle, // phoneAccountHandle 476 NO_VIDEO_STATE, // callVideoState 477 POST_DIAL_STRING, // postDialDigits 478 null 479 ); 480 mCallLogManager.onCallStateChanged(fakeOutgoingCall, CallState.ACTIVE, 481 CallState.DISCONNECTED); 482 483 // Incoming call using phone account in managed profile should be inserted to managed 484 // profile only. 485 verifyNoInsertionInUser(CURRENT_USER_ID); 486 verifyNoInsertionInUser(OTHER_USER_ID); 487 ContentValues insertedValues = verifyInsertionWithCapture(MANAGED_USER_ID); 488 assertEquals(insertedValues.getAsInteger(CallLog.Calls.TYPE), 489 Integer.valueOf(Calls.INCOMING_TYPE)); 490 } 491 492 /** 493 * Ensure call data usage is persisted to the call log when present in the call. 494 */ 495 public void testLogCallDataUsageSet() { 496 when(mMockPhoneAccountRegistrar.getPhoneAccountUnchecked(any(PhoneAccountHandle.class))) 497 .thenReturn(makeFakePhoneAccount(mDefaultAccountHandle, CURRENT_USER_ID)); 498 Call fakeVideoCall = makeFakeCall( 499 DisconnectCause.OTHER, // disconnectCauseCode 500 false, // isConference 501 true, // isIncoming 502 1L, // creationTimeMillis 503 1000L, // ageMillis 504 TEL_PHONEHANDLE, // callHandle 505 mDefaultAccountHandle, // phoneAccountHandle 506 BIDIRECTIONAL_VIDEO_STATE, // callVideoState 507 POST_DIAL_STRING, // postDialDigits 508 UserHandle.of(CURRENT_USER_ID), // initiatingUser 509 1000 // callDataUsage 510 ); 511 mCallLogManager.onCallStateChanged(fakeVideoCall, CallState.ACTIVE, CallState.DISCONNECTED); 512 ContentValues insertedValues = verifyInsertionWithCapture(CURRENT_USER_ID); 513 assertEquals(Long.valueOf(1000), insertedValues.getAsLong(CallLog.Calls.DATA_USAGE)); 514 } 515 516 /** 517 * Ensures call data usage is null in the call log when not set on the call. 518 */ 519 public void testLogCallDataUsageNotSet() { 520 when(mMockPhoneAccountRegistrar.getPhoneAccountUnchecked(any(PhoneAccountHandle.class))) 521 .thenReturn(makeFakePhoneAccount(mDefaultAccountHandle, CURRENT_USER_ID)); 522 Call fakeVideoCall = makeFakeCall( 523 DisconnectCause.OTHER, // disconnectCauseCode 524 false, // isConference 525 true, // isIncoming 526 1L, // creationTimeMillis 527 1000L, // ageMillis 528 TEL_PHONEHANDLE, // callHandle 529 mDefaultAccountHandle, // phoneAccountHandle 530 BIDIRECTIONAL_VIDEO_STATE, // callVideoState 531 POST_DIAL_STRING, // postDialDigits 532 UserHandle.of(CURRENT_USER_ID), // initiatingUser 533 Call.DATA_USAGE_NOT_SET // callDataUsage 534 ); 535 mCallLogManager.onCallStateChanged(fakeVideoCall, CallState.ACTIVE, CallState.DISCONNECTED); 536 ContentValues insertedValues = verifyInsertionWithCapture(CURRENT_USER_ID); 537 assertNull(insertedValues.getAsLong(CallLog.Calls.DATA_USAGE)); 538 } 539 540 private void verifyNoInsertion() { 541 try { 542 verify(mContentProvider, timeout(TEST_TIMEOUT_MILLIS).never()).insert(any(String.class), 543 any(Uri.class), any(ContentValues.class)); 544 } catch (android.os.RemoteException e) { 545 fail("Remote exception occurred during test execution"); 546 } 547 } 548 549 550 private void verifyNoInsertionInUser(int userId) { 551 try { 552 Uri uri = ContentProvider.maybeAddUserId(CallLog.Calls.CONTENT_URI, userId); 553 verify(mContentProvider, timeout(TEST_TIMEOUT_MILLIS).never()).insert(any(String.class), 554 eq(uri), any(ContentValues.class)); 555 } catch (android.os.RemoteException e) { 556 fail("Remote exception occurred during test execution"); 557 } 558 } 559 560 private ContentValues verifyInsertionWithCapture(int userId) { 561 ArgumentCaptor<ContentValues> captor = ArgumentCaptor.forClass(ContentValues.class); 562 try { 563 Uri uri = ContentProvider.maybeAddUserId(CallLog.Calls.CONTENT_URI, userId); 564 verify(mContentProvider, timeout(TEST_TIMEOUT_MILLIS).atLeastOnce()) 565 .insert(any(String.class), eq(uri), captor.capture()); 566 } catch (android.os.RemoteException e) { 567 fail("Remote exception occurred during test execution"); 568 } 569 570 return captor.getValue(); 571 } 572 573 private Call makeFakeCall(int disconnectCauseCode, boolean isConference, boolean isIncoming, 574 long creationTimeMillis, long ageMillis, Uri callHandle, 575 PhoneAccountHandle phoneAccountHandle, int callVideoState, 576 String postDialDigits, UserHandle initiatingUser) { 577 return makeFakeCall(disconnectCauseCode, isConference, isIncoming, creationTimeMillis, 578 ageMillis, 579 callHandle, phoneAccountHandle, callVideoState, postDialDigits, initiatingUser, 580 Call.DATA_USAGE_NOT_SET); 581 } 582 583 private Call makeFakeCall(int disconnectCauseCode, boolean isConference, boolean isIncoming, 584 long creationTimeMillis, long ageMillis, Uri callHandle, 585 PhoneAccountHandle phoneAccountHandle, int callVideoState, 586 String postDialDigits, UserHandle initiatingUser, long callDataUsage) { 587 Call fakeCall = mock(Call.class); 588 when(fakeCall.getDisconnectCause()).thenReturn( 589 new DisconnectCause(disconnectCauseCode)); 590 when(fakeCall.isConference()).thenReturn(isConference); 591 when(fakeCall.isIncoming()).thenReturn(isIncoming); 592 when(fakeCall.getCreationTimeMillis()).thenReturn(creationTimeMillis); 593 when(fakeCall.getAgeMillis()).thenReturn(ageMillis); 594 when(fakeCall.getOriginalHandle()).thenReturn(callHandle); 595 when(fakeCall.getTargetPhoneAccount()).thenReturn(phoneAccountHandle); 596 when(fakeCall.getVideoStateHistory()).thenReturn(callVideoState); 597 when(fakeCall.getPostDialDigits()).thenReturn(postDialDigits); 598 when(fakeCall.getInitiatingUser()).thenReturn(initiatingUser); 599 when(fakeCall.getCallDataUsage()).thenReturn(callDataUsage); 600 return fakeCall; 601 } 602 603 private PhoneAccount makeFakePhoneAccount(PhoneAccountHandle phoneAccountHandle, 604 int capabilities) { 605 return PhoneAccount.builder(phoneAccountHandle, "testing") 606 .setCapabilities(capabilities).build(); 607 } 608} 609