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