1 /* 2 * Copyright (C) 2020 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.services.telephony.rcs; 18 19 import static org.junit.Assert.assertEquals; 20 import static org.junit.Assert.assertFalse; 21 import static org.junit.Assert.assertNotNull; 22 import static org.junit.Assert.assertTrue; 23 import static org.junit.Assert.fail; 24 import static org.mockito.ArgumentMatchers.any; 25 import static org.mockito.ArgumentMatchers.anyInt; 26 import static org.mockito.ArgumentMatchers.anyString; 27 import static org.mockito.ArgumentMatchers.eq; 28 import static org.mockito.Mockito.doAnswer; 29 import static org.mockito.Mockito.doReturn; 30 import static org.mockito.Mockito.doThrow; 31 import static org.mockito.Mockito.mock; 32 import static org.mockito.Mockito.never; 33 import static org.mockito.Mockito.times; 34 import static org.mockito.Mockito.verify; 35 36 import android.app.role.RoleManager; 37 import android.os.IBinder; 38 import android.os.PersistableBundle; 39 import android.os.UserHandle; 40 import android.telephony.CarrierConfigManager; 41 import android.telephony.ims.DelegateRequest; 42 import android.telephony.ims.FeatureTagState; 43 import android.telephony.ims.ImsException; 44 import android.telephony.ims.SipDelegateManager; 45 import android.telephony.ims.aidl.IImsRegistration; 46 import android.telephony.ims.aidl.ISipDelegate; 47 import android.telephony.ims.aidl.ISipDelegateConnectionStateCallback; 48 import android.telephony.ims.aidl.ISipDelegateMessageCallback; 49 import android.telephony.ims.aidl.ISipTransport; 50 import android.util.ArraySet; 51 import android.util.Pair; 52 53 import androidx.test.filters.SmallTest; 54 import androidx.test.runner.AndroidJUnit4; 55 56 import com.android.TelephonyTestBase; 57 import com.android.TestExecutorService; 58 import com.android.ims.RcsFeatureManager; 59 import com.android.phone.RcsProvisioningMonitor; 60 61 import org.junit.After; 62 import org.junit.Before; 63 import org.junit.Test; 64 import org.junit.runner.RunWith; 65 import org.mockito.ArgumentCaptor; 66 import org.mockito.Mock; 67 68 import java.util.ArrayList; 69 import java.util.Collections; 70 import java.util.Set; 71 import java.util.concurrent.CompletableFuture; 72 import java.util.concurrent.CountDownLatch; 73 import java.util.concurrent.Executors; 74 import java.util.concurrent.ScheduledExecutorService; 75 import java.util.concurrent.TimeUnit; 76 import java.util.stream.Collectors; 77 78 @RunWith(AndroidJUnit4.class) 79 public class SipTransportControllerTest extends TelephonyTestBase { 80 private static final int TEST_SUB_ID = 1; 81 private static final int TEST_UID = 1001; 82 private static final String TEST_PACKAGE_NAME = "com.test_pkg"; 83 private static final String TEST_PACKAGE_NAME_2 = "com.test_pkg2"; 84 private static final int TIMEOUT_MS = 200; 85 private static final int THROTTLE_MS = 50; 86 87 private class SipDelegateControllerContainer { 88 public final int subId; 89 public final String packageName; 90 public final DelegateRequest delegateRequest; 91 public final SipDelegateController delegateController; 92 private final ISipDelegate mMockDelegate; 93 public final IBinder mockDelegateBinder; 94 public final ISipDelegateConnectionStateCallback mockDelegateConnectionCallback; 95 public final ISipDelegateMessageCallback mockMessageCallback; 96 public final IBinder mockMessageCallbackBinder; 97 SipDelegateControllerContainer(int id, String name, DelegateRequest request)98 SipDelegateControllerContainer(int id, String name, DelegateRequest request) { 99 delegateController = mock(SipDelegateController.class); 100 mMockDelegate = mock(ISipDelegate.class); 101 mockDelegateBinder = mock(IBinder.class); 102 doReturn(mockDelegateBinder).when(mMockDelegate).asBinder(); 103 mockDelegateConnectionCallback = mock(ISipDelegateConnectionStateCallback.class); 104 mockMessageCallback = mock(ISipDelegateMessageCallback.class); 105 mockMessageCallbackBinder = mock(IBinder.class); 106 doReturn(mockMessageCallbackBinder).when(mockMessageCallback).asBinder(); 107 doReturn(name).when(delegateController).getPackageName(); 108 doReturn(request).when(delegateController).getInitialRequest(); 109 doReturn(mMockDelegate).when(delegateController).getSipDelegateInterface(); 110 doReturn(mockMessageCallback).when(delegateController).getAppMessageCallback(); 111 subId = id; 112 packageName = name; 113 delegateRequest = request; 114 } 115 } 116 117 @Mock private RcsFeatureManager mRcsManager; 118 @Mock private ISipTransport mSipTransport; 119 @Mock private IImsRegistration mImsRegistration; 120 @Mock private SipTransportController.SipDelegateControllerFactory 121 mMockDelegateControllerFactory; 122 @Mock private SipTransportController.RoleManagerAdapter mMockRoleManager; 123 124 private ScheduledExecutorService mExecutorService = null; 125 private final ArrayList<SipDelegateControllerContainer> mMockControllers = new ArrayList<>(); 126 private final ArrayList<String> mSmsPackageName = new ArrayList<>(1); 127 128 @Before setUp()129 public void setUp() throws Exception { 130 super.setUp(); 131 doReturn(mSmsPackageName).when(mMockRoleManager).getRoleHolders(RoleManager.ROLE_SMS); 132 doReturn(mImsRegistration).when(mRcsManager).getImsRegistration(); 133 mSmsPackageName.add(TEST_PACKAGE_NAME); 134 doAnswer(invocation -> { 135 Integer subId = invocation.getArgument(0); 136 String packageName = invocation.getArgument(3); 137 DelegateRequest request = invocation.getArgument(2); 138 SipDelegateController c = getMockDelegateController(subId, packageName, request); 139 assertNotNull("create called with no corresponding controller set up", c); 140 return c; 141 }).when(mMockDelegateControllerFactory).create(anyInt(), anyInt(), any(), anyString(), 142 any(), any(), any(), any(), any()); 143 setFeatureAllowedConfig(TEST_SUB_ID, new String[]{ImsSignallingUtils.MMTEL_TAG, 144 ImsSignallingUtils.ONE_TO_ONE_CHAT_TAG, ImsSignallingUtils.GROUP_CHAT_TAG, 145 ImsSignallingUtils.FILE_TRANSFER_HTTP_TAG}); 146 } 147 148 @After tearDown()149 public void tearDown() throws Exception { 150 var monitor = RcsProvisioningMonitor.getInstance(); 151 if (monitor != null) { 152 monitor.overrideImsFeatureValidation(TEST_SUB_ID, null); 153 } 154 155 if (mExecutorService != null && !mExecutorService.isShutdown()) { 156 mExecutorService.shutdownNow(); 157 } 158 159 super.tearDown(); 160 } 161 162 @SmallTest 163 @Test isSupportedRcsNotConnected()164 public void isSupportedRcsNotConnected() { 165 SipTransportController controller = createController(new TestExecutorService()); 166 try { 167 controller.isSupported(TEST_SUB_ID); 168 fail(); 169 } catch (ImsException e) { 170 assertEquals(ImsException.CODE_ERROR_SERVICE_UNAVAILABLE, e.getCode()); 171 } 172 } 173 174 @SmallTest 175 @Test isSupportedInvalidSubId()176 public void isSupportedInvalidSubId() { 177 SipTransportController controller = createController(new TestExecutorService()); 178 try { 179 controller.isSupported(TEST_SUB_ID + 1); 180 fail(); 181 } catch (ImsException e) { 182 assertEquals(ImsException.CODE_ERROR_INVALID_SUBSCRIPTION, e.getCode()); 183 } 184 } 185 186 @SmallTest 187 @Test isSupportedSubIdChanged()188 public void isSupportedSubIdChanged() { 189 SipTransportController controller = createController(new TestExecutorService()); 190 controller.onAssociatedSubscriptionUpdated(TEST_SUB_ID + 1); 191 try { 192 controller.isSupported(TEST_SUB_ID); 193 fail(); 194 } catch (ImsException e) { 195 assertEquals(ImsException.CODE_ERROR_INVALID_SUBSCRIPTION, e.getCode()); 196 } 197 } 198 199 @SmallTest 200 @Test isSupportedSipTransportAvailableRcsConnected()201 public void isSupportedSipTransportAvailableRcsConnected() throws Exception { 202 SipTransportController controller = createController(new TestExecutorService()); 203 doReturn(mSipTransport).when(mRcsManager).getSipTransport(); 204 controller.onRcsConnected(mRcsManager); 205 try { 206 assertTrue(controller.isSupported(TEST_SUB_ID)); 207 } catch (ImsException e) { 208 fail(); 209 } 210 } 211 212 @SmallTest 213 @Test isSupportedSipTransportNotAvailableRcsDisconnected()214 public void isSupportedSipTransportNotAvailableRcsDisconnected() throws Exception { 215 SipTransportController controller = createController(new TestExecutorService()); 216 doReturn(mSipTransport).when(mRcsManager).getSipTransport(); 217 controller.onRcsConnected(mRcsManager); 218 controller.onRcsDisconnected(); 219 try { 220 controller.isSupported(TEST_SUB_ID); 221 fail(); 222 } catch (ImsException e) { 223 assertEquals(ImsException.CODE_ERROR_SERVICE_UNAVAILABLE, e.getCode()); 224 } 225 } 226 227 @SmallTest 228 @Test isSupportedSipTransportNotAvailableRcsConnected()229 public void isSupportedSipTransportNotAvailableRcsConnected() throws Exception { 230 SipTransportController controller = createController(new TestExecutorService()); 231 doReturn(null).when(mRcsManager).getSipTransport(); 232 controller.onRcsConnected(mRcsManager); 233 try { 234 assertFalse(controller.isSupported(TEST_SUB_ID)); 235 } catch (ImsException e) { 236 fail(); 237 } 238 } 239 240 @SmallTest 241 @Test isSupportedImsServiceNotAvailableRcsConnected()242 public void isSupportedImsServiceNotAvailableRcsConnected() throws Exception { 243 SipTransportController controller = createController(new TestExecutorService()); 244 doThrow(new ImsException("", ImsException.CODE_ERROR_SERVICE_UNAVAILABLE)) 245 .when(mRcsManager).getSipTransport(); 246 controller.onRcsConnected(mRcsManager); 247 try { 248 controller.isSupported(TEST_SUB_ID); 249 fail(); 250 } catch (ImsException e) { 251 assertEquals(ImsException.CODE_ERROR_SERVICE_UNAVAILABLE, e.getCode()); 252 } 253 } 254 255 @SmallTest 256 @Test createImsServiceAvailableSubIdIncorrect()257 public void createImsServiceAvailableSubIdIncorrect() throws Exception { 258 SipTransportController controller = createController(new TestExecutorService()); 259 doReturn(mSipTransport).when(mRcsManager).getSipTransport(); 260 controller.onRcsConnected(mRcsManager); 261 try { 262 controller.createSipDelegate(TEST_SUB_ID + 1, TEST_UID, 263 new DelegateRequest(Collections.emptySet()), TEST_PACKAGE_NAME, 264 mock(ISipDelegateConnectionStateCallback.class), 265 mock(ISipDelegateMessageCallback.class)); 266 fail(); 267 } catch (ImsException e) { 268 assertEquals(ImsException.CODE_ERROR_INVALID_SUBSCRIPTION, e.getCode()); 269 } 270 } 271 272 @SmallTest 273 @Test createImsServiceDoesntSupportTransport()274 public void createImsServiceDoesntSupportTransport() throws Exception { 275 SipTransportController controller = createController(new TestExecutorService()); 276 doReturn(null).when(mRcsManager).getSipTransport(); 277 controller.onRcsConnected(mRcsManager); 278 try { 279 controller.createSipDelegate(TEST_SUB_ID, TEST_UID, 280 new DelegateRequest(Collections.emptySet()), TEST_PACKAGE_NAME, 281 mock(ISipDelegateConnectionStateCallback.class), 282 mock(ISipDelegateMessageCallback.class)); 283 fail(); 284 } catch (ImsException e) { 285 assertEquals(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION, e.getCode()); 286 } 287 } 288 289 @SmallTest 290 @Test createImsServiceNotAvailable()291 public void createImsServiceNotAvailable() throws Exception { 292 SipTransportController controller = createController(new TestExecutorService()); 293 doThrow(new ImsException("", ImsException.CODE_ERROR_SERVICE_UNAVAILABLE)) 294 .when(mRcsManager).getSipTransport(); 295 // No RCS connected message 296 try { 297 controller.createSipDelegate(TEST_SUB_ID, TEST_UID, 298 new DelegateRequest(Collections.emptySet()), TEST_PACKAGE_NAME, 299 mock(ISipDelegateConnectionStateCallback.class), 300 mock(ISipDelegateMessageCallback.class)); 301 fail(); 302 } catch (ImsException e) { 303 assertEquals(ImsException.CODE_ERROR_SERVICE_UNAVAILABLE, e.getCode()); 304 } 305 } 306 307 @SmallTest 308 @Test basicCreate()309 public void basicCreate() throws Exception { 310 SipTransportController controller = setupLiveTransportController(); 311 312 DelegateRequest r = getBaseDelegateRequest(); 313 314 SipDelegateControllerContainer c = injectMockDelegateController(TEST_PACKAGE_NAME, r); 315 createDelegateAndVerify(controller, c, r.getFeatureTags(), Collections.emptySet()); 316 verifyDelegateRegistrationChangedEvent(1 /*times*/, 0 /*waitMs*/); 317 triggerFullNetworkRegistrationAndVerify(controller, c); 318 } 319 320 @SmallTest 321 @Test basicCreateDestroy()322 public void basicCreateDestroy() throws Exception { 323 SipTransportController controller = setupLiveTransportController(); 324 325 DelegateRequest r = getBaseDelegateRequest(); 326 SipDelegateControllerContainer c = injectMockDelegateController(TEST_PACKAGE_NAME, r); 327 createDelegateAndVerify(controller, c, r.getFeatureTags(), Collections.emptySet()); 328 verify(c.mockMessageCallbackBinder).linkToDeath(any(), anyInt()); 329 verifyDelegateRegistrationChangedEvent(1, 0 /*throttle*/); 330 331 destroyDelegateAndVerify(controller, c, false, 332 SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP); 333 verify(c.mockMessageCallbackBinder).unlinkToDeath(any(), anyInt()); 334 verifyDelegateRegistrationChangedEvent(2 /*times*/, 0 /*waitMs*/); 335 triggerFullNetworkRegistrationAndVerifyNever(controller, c); 336 } 337 338 @SmallTest 339 @Test createDestroyAppDied()340 public void createDestroyAppDied() throws Exception { 341 SipTransportController controller = setupLiveTransportController(); 342 DelegateRequest r = getBaseDelegateRequest(); 343 SipDelegateControllerContainer c = injectMockDelegateController(TEST_PACKAGE_NAME, r); 344 createDelegateAndVerify(controller, c, r.getFeatureTags(), Collections.emptySet()); 345 ArgumentCaptor<IBinder.DeathRecipient> captor = 346 ArgumentCaptor.forClass(IBinder.DeathRecipient.class); 347 verify(c.mockMessageCallbackBinder).linkToDeath(captor.capture(), anyInt()); 348 IBinder.DeathRecipient deathRecipient = captor.getValue(); 349 assertNotNull(deathRecipient); 350 verifyDelegateRegistrationChangedEvent(1, 0 /*throttle*/); 351 352 CompletableFuture<Integer> pendingDestroy = setDestroyFuture(c.delegateController, true, 353 SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_SERVICE_DEAD); 354 // Simulate app dying 355 deathRecipient.binderDied(); 356 waitForExecutorAction(mExecutorService, TIMEOUT_MS); 357 verifyDestroyDelegate(c.delegateController, pendingDestroy, true, 358 SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_SERVICE_DEAD); 359 // If binderDied is called, then unregister does not lead to unlinkToDeath 360 triggerFullNetworkRegistrationAndVerifyNever(controller, c); 361 } 362 363 @SmallTest 364 @Test testCreateButNotInRole()365 public void testCreateButNotInRole() throws Exception { 366 SipTransportController controller = setupLiveTransportController(); 367 368 DelegateRequest r = getBaseDelegateRequest(); 369 Set<FeatureTagState> getDeniedTags = getDeniedTagsForReason(r.getFeatureTags(), 370 SipDelegateManager.DENIED_REASON_NOT_ALLOWED); 371 372 // Try to create a SipDelegate for a package that is not the default sms role. 373 SipDelegateControllerContainer c = injectMockDelegateController(TEST_PACKAGE_NAME_2, r); 374 createDelegateAndVerify(controller, c, Collections.emptySet(), getDeniedTags); 375 } 376 377 @SmallTest 378 @Test createTwoAndDenyOverlappingTags()379 public void createTwoAndDenyOverlappingTags() throws Exception { 380 SipTransportController controller = setupLiveTransportController(0 /*reeval*/, 381 THROTTLE_MS); 382 383 // First delegate requests RCS message + File transfer 384 ArraySet<String> firstDelegate = new ArraySet<>(getBaseDelegateRequest().getFeatureTags()); 385 firstDelegate.remove(ImsSignallingUtils.GROUP_CHAT_TAG); 386 DelegateRequest firstDelegateRequest = new DelegateRequest(firstDelegate); 387 SipDelegateControllerContainer c1 = injectMockDelegateController(TEST_PACKAGE_NAME, 388 firstDelegateRequest); 389 createDelegateAndVerify(controller, c1, firstDelegate, Collections.emptySet()); 390 // there is a delay in the indication to update reg, so it should not happen yet. 391 verifyNoDelegateRegistrationChangedEvent(); 392 393 // First delegate requests RCS message + Group RCS message. For this delegate, single RCS 394 // message should be denied. 395 ArraySet<String> secondDelegate = new ArraySet<>(getBaseDelegateRequest().getFeatureTags()); 396 secondDelegate.remove(ImsSignallingUtils.FILE_TRANSFER_HTTP_TAG); 397 DelegateRequest secondDelegateRequest = new DelegateRequest(secondDelegate); 398 Pair<Set<String>, Set<FeatureTagState>> grantedAndDenied = getAllowedAndDeniedTagsForConfig( 399 secondDelegateRequest, SipDelegateManager.DENIED_REASON_IN_USE_BY_ANOTHER_DELEGATE, 400 firstDelegate); 401 SipDelegateControllerContainer c2 = injectMockDelegateController(TEST_PACKAGE_NAME, 402 secondDelegateRequest); 403 createDelegateAndVerify(controller, c2, grantedAndDenied.first, 404 grantedAndDenied.second, 1); 405 // a reg changed event should happen after wait. 406 verifyDelegateRegistrationChangedEvent(1, 2 * THROTTLE_MS); 407 } 408 409 @SmallTest 410 @Test createTwoAndTriggerRoleChange()411 public void createTwoAndTriggerRoleChange() throws Exception { 412 SipTransportController controller = setupLiveTransportController(0 /*reeval*/, THROTTLE_MS); 413 414 DelegateRequest firstDelegateRequest = getBaseDelegateRequest(); 415 Set<FeatureTagState> firstDeniedTags = getDeniedTagsForReason( 416 firstDelegateRequest.getFeatureTags(), 417 SipDelegateManager.DENIED_REASON_NOT_ALLOWED); 418 SipDelegateControllerContainer c1 = injectMockDelegateController(TEST_PACKAGE_NAME, 419 firstDelegateRequest); 420 createDelegateAndVerify(controller, c1, firstDelegateRequest.getFeatureTags(), 421 Collections.emptySet()); 422 verifyDelegateRegistrationChangedEvent(1 /*times*/, THROTTLE_MS); 423 424 DelegateRequest secondDelegateRequest = getBaseDelegateRequest(); 425 Set<FeatureTagState> secondDeniedTags = getDeniedTagsForReason( 426 secondDelegateRequest.getFeatureTags(), 427 SipDelegateManager.DENIED_REASON_NOT_ALLOWED); 428 // Try to create a SipDelegate for a package that is not the default sms role. 429 SipDelegateControllerContainer c2 = injectMockDelegateController(TEST_PACKAGE_NAME_2, 430 secondDelegateRequest); 431 createDelegateAndVerify(controller, c2, Collections.emptySet(), secondDeniedTags, 1); 432 433 // now swap the SMS role. 434 CompletableFuture<Boolean> pendingC1Change = setChangeSupportedFeatureTagsFuture( 435 c1.delegateController, Collections.emptySet(), firstDeniedTags); 436 CompletableFuture<Boolean> pendingC2Change = setChangeSupportedFeatureTagsFuture( 437 c2.delegateController, secondDelegateRequest.getFeatureTags(), 438 Collections.emptySet()); 439 setSmsRoleAndEvaluate(controller, TEST_PACKAGE_NAME_2); 440 // swapping roles should trigger a deregistration event on the ImsService side. 441 verifyDelegateDeregistrationEvent(); 442 // there should also not be any new registration changed events 443 verifyDelegateRegistrationChangedEvent(1 /*times*/, THROTTLE_MS); 444 // trigger completion stage to run 445 waitForExecutorAction(mExecutorService, TIMEOUT_MS); 446 verify(c1.delegateController).changeSupportedFeatureTags(Collections.emptySet(), 447 firstDeniedTags); 448 // we should not get a change for c2 until pendingC1Change completes. 449 verify(c2.delegateController, never()).changeSupportedFeatureTags( 450 secondDelegateRequest.getFeatureTags(), Collections.emptySet()); 451 // ensure we are not blocking executor here 452 waitForExecutorAction(mExecutorService, TIMEOUT_MS); 453 completePendingChange(pendingC1Change, true); 454 // trigger completion stage to run 455 waitForExecutorAction(mExecutorService, TIMEOUT_MS); 456 verify(c2.delegateController).changeSupportedFeatureTags( 457 secondDelegateRequest.getFeatureTags(), Collections.emptySet()); 458 // ensure we are not blocking executor here 459 waitForExecutorAction(mExecutorService, TIMEOUT_MS); 460 completePendingChange(pendingC2Change, true); 461 // verify we now get a second registration changed event 462 verifyDelegateRegistrationChangedEvent(2 /*times*/, THROTTLE_MS); 463 } 464 465 @SmallTest 466 @Test createTwoAndDestroyOlder()467 public void createTwoAndDestroyOlder() throws Exception { 468 SipTransportController controller = setupLiveTransportController(0 /*reeval*/, THROTTLE_MS); 469 470 // First delegate requests RCS message + File transfer 471 ArraySet<String> firstDelegate = new ArraySet<>(getBaseDelegateRequest().getFeatureTags()); 472 firstDelegate.remove(ImsSignallingUtils.GROUP_CHAT_TAG); 473 DelegateRequest firstDelegateRequest = new DelegateRequest(firstDelegate); 474 SipDelegateControllerContainer c1 = injectMockDelegateController(TEST_PACKAGE_NAME, 475 firstDelegateRequest); 476 createDelegateAndVerify(controller, c1, firstDelegate, Collections.emptySet()); 477 verifyNoDelegateRegistrationChangedEvent(); 478 479 // First delegate requests RCS message + Group RCS message. For this delegate, single RCS 480 // message should be denied. 481 ArraySet<String> secondDelegate = new ArraySet<>(getBaseDelegateRequest().getFeatureTags()); 482 secondDelegate.remove(ImsSignallingUtils.FILE_TRANSFER_HTTP_TAG); 483 DelegateRequest secondDelegateRequest = new DelegateRequest(secondDelegate); 484 Pair<Set<String>, Set<FeatureTagState>> grantedAndDenied = getAllowedAndDeniedTagsForConfig( 485 secondDelegateRequest, SipDelegateManager.DENIED_REASON_IN_USE_BY_ANOTHER_DELEGATE, 486 firstDelegate); 487 SipDelegateControllerContainer c2 = injectMockDelegateController(TEST_PACKAGE_NAME, 488 secondDelegateRequest); 489 createDelegateAndVerify(controller, c2, grantedAndDenied.first, grantedAndDenied.second, 1); 490 verifyNoDelegateRegistrationChangedEvent(); 491 492 // Destroy the firstDelegate, which should now cause all previously denied tags to be 493 // granted to the new delegate. 494 CompletableFuture<Boolean> pendingC2Change = setChangeSupportedFeatureTagsFuture( 495 c2.delegateController, secondDelegate, Collections.emptySet()); 496 destroyDelegateAndVerify(controller, c1, false /*force*/, 497 SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP); 498 // wait for create to be processed. 499 assertTrue(waitForExecutorAction(mExecutorService, TIMEOUT_MS)); 500 verify(c2.delegateController).changeSupportedFeatureTags(secondDelegate, 501 Collections.emptySet()); 502 completePendingChange(pendingC2Change, true); 503 504 verifyDelegateRegistrationChangedEvent(1 /*times*/, THROTTLE_MS); 505 } 506 507 @SmallTest 508 @Test testThrottling()509 public void testThrottling() throws Exception { 510 SipTransportController controller = setupLiveTransportController(THROTTLE_MS, THROTTLE_MS); 511 512 // First delegate requests RCS message + File transfer 513 ArraySet<String> firstDelegate = new ArraySet<>(getBaseDelegateRequest().getFeatureTags()); 514 firstDelegate.remove(ImsSignallingUtils.GROUP_CHAT_TAG); 515 DelegateRequest firstDelegateRequest = new DelegateRequest(firstDelegate); 516 SipDelegateControllerContainer c1 = injectMockDelegateController(TEST_PACKAGE_NAME, 517 firstDelegateRequest); 518 CompletableFuture<Boolean> pendingC1Change = createDelegate(controller, c1, 519 firstDelegate, Collections.emptySet()); 520 521 // Request RCS message + group RCS Message. For this delegate, single RCS message should be 522 // denied. 523 ArraySet<String> secondDelegate = new ArraySet<>(getBaseDelegateRequest().getFeatureTags()); 524 secondDelegate.remove(ImsSignallingUtils.FILE_TRANSFER_HTTP_TAG); 525 DelegateRequest secondDelegateRequest = new DelegateRequest(secondDelegate); 526 Pair<Set<String>, Set<FeatureTagState>> grantedAndDeniedC2 = 527 getAllowedAndDeniedTagsForConfig(secondDelegateRequest, 528 SipDelegateManager.DENIED_REASON_IN_USE_BY_ANOTHER_DELEGATE, firstDelegate); 529 SipDelegateControllerContainer c2 = injectMockDelegateController(TEST_PACKAGE_NAME, 530 secondDelegateRequest); 531 CompletableFuture<Boolean> pendingC2Change = createDelegate(controller, c2, 532 grantedAndDeniedC2.first, grantedAndDeniedC2.second); 533 534 // Request group RCS message + file transfer. All should be denied at first 535 ArraySet<String> thirdDelegate = new ArraySet<>(getBaseDelegateRequest().getFeatureTags()); 536 thirdDelegate.remove(ImsSignallingUtils.ONE_TO_ONE_CHAT_TAG); 537 DelegateRequest thirdDelegateRequest = new DelegateRequest(thirdDelegate); 538 Pair<Set<String>, Set<FeatureTagState>> grantedAndDeniedC3 = 539 getAllowedAndDeniedTagsForConfig(thirdDelegateRequest, 540 SipDelegateManager.DENIED_REASON_IN_USE_BY_ANOTHER_DELEGATE, firstDelegate, 541 grantedAndDeniedC2.first); 542 SipDelegateControllerContainer c3 = injectMockDelegateController(TEST_PACKAGE_NAME, 543 thirdDelegateRequest); 544 CompletableFuture<Boolean> pendingC3Change = createDelegate(controller, c3, 545 grantedAndDeniedC3.first, grantedAndDeniedC3.second); 546 547 verifyNoDelegateRegistrationChangedEvent(); 548 assertTrue(scheduleDelayedWait(2 * THROTTLE_MS)); 549 verifyDelegateChanged(c1.delegateController, pendingC1Change, firstDelegate, 550 Collections.emptySet(), 0); 551 verifyDelegateChanged(c2.delegateController, pendingC2Change, grantedAndDeniedC2.first, 552 grantedAndDeniedC2.second, 0); 553 verifyDelegateChanged(c3.delegateController, pendingC3Change, grantedAndDeniedC3.first, 554 grantedAndDeniedC3.second, 0); 555 verifyDelegateRegistrationChangedEvent(1, 2 * THROTTLE_MS); 556 557 // Destroy the first and second controller in quick succession, this should only generate 558 // one reevaluate for the third controller. 559 CompletableFuture<Boolean> pendingChangeC3 = setChangeSupportedFeatureTagsFuture( 560 c3.delegateController, thirdDelegate, Collections.emptySet()); 561 CompletableFuture<Integer> pendingDestroyC1 = destroyDelegate(controller, 562 c1.delegateController, false /*force*/, 563 SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP); 564 CompletableFuture<Integer> pendingDestroyC2 = destroyDelegate(controller, 565 c2.delegateController, false /*force*/, 566 SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP); 567 assertTrue(scheduleDelayedWait(2 * THROTTLE_MS)); 568 verifyDestroyDelegate(c1.delegateController, pendingDestroyC1, false /*force*/, 569 SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP); 570 verifyDestroyDelegate(c2.delegateController, pendingDestroyC2, false /*force*/, 571 SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP); 572 573 // All requested features should now be granted 574 completePendingChange(pendingChangeC3, true); 575 verify(c3.delegateController) 576 .changeSupportedFeatureTags(thirdDelegate, Collections.emptySet()); 577 // In total reeval should have only been called twice. 578 verify(c3.delegateController, times(2)) 579 .changeSupportedFeatureTags(any(), any()); 580 verifyDelegateRegistrationChangedEvent(2 /*times*/, 2 * THROTTLE_MS); 581 } 582 583 @SmallTest 584 @Test testSubIdChangeDestroyTriggered()585 public void testSubIdChangeDestroyTriggered() throws Exception { 586 SipTransportController controller = setupLiveTransportController(); 587 588 ArraySet<String> firstDelegate = new ArraySet<>(getBaseDelegateRequest().getFeatureTags()); 589 DelegateRequest firstDelegateRequest = new DelegateRequest(firstDelegate); 590 SipDelegateControllerContainer c = injectMockDelegateController(TEST_PACKAGE_NAME, 591 firstDelegateRequest); 592 createDelegateAndVerify(controller, c, firstDelegate, Collections.emptySet()); 593 verifyDelegateRegistrationChangedEvent(1 /*times*/, 0 /*waitMs*/); 594 595 CompletableFuture<Integer> pendingDestroy = setDestroyFuture(c.delegateController, true, 596 SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_SUBSCRIPTION_TORN_DOWN); 597 controller.onAssociatedSubscriptionUpdated(TEST_SUB_ID + 1); 598 waitForExecutorAction(mExecutorService, TIMEOUT_MS); 599 verifyDestroyDelegate(c.delegateController, pendingDestroy, true /*force*/, 600 SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_SUBSCRIPTION_TORN_DOWN); 601 verifyDelegateRegistrationChangedEvent(2 /*times*/, 0 /*waitMs*/); 602 } 603 604 @SmallTest 605 @Test testRcsManagerGoneDestroyTriggered()606 public void testRcsManagerGoneDestroyTriggered() throws Exception { 607 SipTransportController controller = setupLiveTransportController(); 608 609 ArraySet<String> firstDelegate = new ArraySet<>(getBaseDelegateRequest().getFeatureTags()); 610 DelegateRequest firstDelegateRequest = new DelegateRequest(firstDelegate); 611 SipDelegateControllerContainer c = injectMockDelegateController(TEST_PACKAGE_NAME, 612 firstDelegateRequest); 613 createDelegateAndVerify(controller, c, firstDelegate, Collections.emptySet()); 614 615 CompletableFuture<Integer> pendingDestroy = setDestroyFuture(c.delegateController, true, 616 SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_SERVICE_DEAD); 617 controller.onRcsDisconnected(); 618 waitForExecutorAction(mExecutorService, TIMEOUT_MS); 619 verifyDestroyDelegate(c.delegateController, pendingDestroy, true /*force*/, 620 SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_SERVICE_DEAD); 621 verifyDelegateRegistrationChangedEvent(1, 0 /*waitMs*/); 622 } 623 624 @SmallTest 625 @Test testDestroyTriggered()626 public void testDestroyTriggered() throws Exception { 627 SipTransportController controller = setupLiveTransportController(); 628 629 ArraySet<String> firstDelegate = new ArraySet<>(getBaseDelegateRequest().getFeatureTags()); 630 DelegateRequest firstDelegateRequest = new DelegateRequest(firstDelegate); 631 SipDelegateControllerContainer c = injectMockDelegateController(TEST_PACKAGE_NAME, 632 firstDelegateRequest); 633 createDelegateAndVerify(controller, c, firstDelegate, Collections.emptySet()); 634 635 CompletableFuture<Integer> pendingDestroy = setDestroyFuture(c.delegateController, 636 true, SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_SUBSCRIPTION_TORN_DOWN); 637 controller.onDestroy(); 638 waitForExecutorAction(mExecutorService, TIMEOUT_MS); 639 verifyDelegateDeregistrationEvent(); 640 // verify change was called. 641 verify(c.delegateController).destroy(true /*force*/, 642 SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_SUBSCRIPTION_TORN_DOWN); 643 // ensure thread is not blocked while waiting for pending complete. 644 waitForExecutorAction(mExecutorService, TIMEOUT_MS); 645 completePendingDestroy(pendingDestroy, 646 SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_SUBSCRIPTION_TORN_DOWN); 647 } 648 649 @SmallTest 650 @Test testTimingSubIdChangedAndCreateNewSubId()651 public void testTimingSubIdChangedAndCreateNewSubId() throws Exception { 652 SipTransportController controller = setupLiveTransportController(THROTTLE_MS, 0); 653 setFeatureAllowedConfig(TEST_SUB_ID + 1, new String[]{ImsSignallingUtils.MMTEL_TAG, 654 ImsSignallingUtils.ONE_TO_ONE_CHAT_TAG, ImsSignallingUtils.GROUP_CHAT_TAG, 655 ImsSignallingUtils.FILE_TRANSFER_HTTP_TAG}); 656 657 ArraySet<String> firstDelegate = new ArraySet<>(getBaseDelegateRequest().getFeatureTags()); 658 DelegateRequest firstDelegateRequest = new DelegateRequest(firstDelegate); 659 SipDelegateControllerContainer c1 = injectMockDelegateController(TEST_PACKAGE_NAME, 660 firstDelegateRequest); 661 CompletableFuture<Boolean> pendingC1Change = createDelegate(controller, c1, 662 firstDelegate, Collections.emptySet()); 663 assertTrue(scheduleDelayedWait(2 * THROTTLE_MS)); 664 verifyDelegateChanged(c1.delegateController, pendingC1Change, firstDelegate, 665 Collections.emptySet(), 0); 666 667 668 CompletableFuture<Integer> pendingDestroy = setDestroyFuture(c1.delegateController, 669 true, SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_SUBSCRIPTION_TORN_DOWN); 670 // triggers reeval now. 671 controller.onAssociatedSubscriptionUpdated(TEST_SUB_ID + 1); 672 waitForExecutorAction(mExecutorService, TIMEOUT_MS); 673 674 // mock a second delegate with the new subId associated with the slot. 675 ArraySet<String> secondDelegate = new ArraySet<>(); 676 secondDelegate.add(ImsSignallingUtils.ONE_TO_ONE_CHAT_TAG); 677 secondDelegate.add(ImsSignallingUtils.FILE_TRANSFER_HTTP_TAG); 678 DelegateRequest secondDelegateRequest = new DelegateRequest(secondDelegate); 679 SipDelegateControllerContainer c2 = injectMockDelegateController(TEST_SUB_ID + 1, 680 TEST_PACKAGE_NAME, secondDelegateRequest); 681 CompletableFuture<Boolean> pendingC2Change = createDelegate(controller, c2, secondDelegate, 682 Collections.emptySet()); 683 assertTrue(scheduleDelayedWait(THROTTLE_MS)); 684 685 //trigger destroyed event 686 verifyDestroyDelegate(c1.delegateController, pendingDestroy, true /*force*/, 687 SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_SUBSCRIPTION_TORN_DOWN); 688 assertTrue(scheduleDelayedWait(2 * THROTTLE_MS)); 689 verifyDelegateChanged(c2.delegateController, pendingC2Change, secondDelegate, 690 Collections.emptySet(), 0); 691 } 692 693 @SmallTest 694 @Test testFeatureTagsDeniedByConfig()695 public void testFeatureTagsDeniedByConfig() throws Exception { 696 setFeatureAllowedConfig(TEST_SUB_ID, new String[]{ImsSignallingUtils.GROUP_CHAT_TAG, 697 ImsSignallingUtils.FILE_TRANSFER_HTTP_TAG}); 698 SipTransportController controller = setupLiveTransportController(THROTTLE_MS, 0); 699 700 ArraySet<String> requestTags = new ArraySet<>(getBaseDelegateRequest().getFeatureTags()); 701 ArraySet<String> allowedTags = new ArraySet<>(requestTags); 702 ArraySet<String> deniedTags = new ArraySet<>(); 703 DelegateRequest delegateRequest = new DelegateRequest(requestTags); 704 SipDelegateControllerContainer c = injectMockDelegateController(TEST_PACKAGE_NAME, 705 delegateRequest); 706 CompletableFuture<Boolean> pendingScChange = createDelegate(controller, c, requestTags, 707 Collections.emptySet()); 708 allowedTags.remove(ImsSignallingUtils.ONE_TO_ONE_CHAT_TAG); 709 deniedTags.add(ImsSignallingUtils.ONE_TO_ONE_CHAT_TAG); 710 711 assertTrue(scheduleDelayedWait(2 * THROTTLE_MS)); 712 verifyDelegateChanged(c.delegateController, pendingScChange, allowedTags, 713 getDeniedTagsForReason(deniedTags, 714 SipDelegateManager.DENIED_REASON_NOT_ALLOWED), 0); 715 } 716 717 @SmallTest 718 @Test testFeatureTagsDeniedByOverride()719 public void testFeatureTagsDeniedByOverride() throws Exception { 720 RcsProvisioningMonitor.getInstance().overrideImsFeatureValidation(TEST_SUB_ID, false); 721 SipTransportController controller = setupLiveTransportController(THROTTLE_MS, 0); 722 723 ArraySet<String> requestTags = new ArraySet<>(getBaseDelegateRequest().getFeatureTags()); 724 ArraySet<String> deniedTags = new ArraySet<>(requestTags); 725 DelegateRequest delegateRequest = new DelegateRequest(requestTags); 726 SipDelegateControllerContainer c = injectMockDelegateController(TEST_PACKAGE_NAME, 727 delegateRequest); 728 CompletableFuture<Boolean> pendingScChange = createDelegate(controller, c, requestTags, 729 Collections.emptySet()); 730 731 assertTrue(scheduleDelayedWait(2 * THROTTLE_MS)); 732 verifyDelegateChanged(c.delegateController, pendingScChange, Collections.emptySet(), 733 getDeniedTagsForReason(deniedTags, 734 SipDelegateManager.DENIED_REASON_NOT_ALLOWED), 0); 735 } 736 737 @SmallTest 738 @Test testFeatureTagsDeniedByConfigAllowedByOverride()739 public void testFeatureTagsDeniedByConfigAllowedByOverride() throws Exception { 740 setFeatureAllowedConfig(TEST_SUB_ID, new String[]{}); 741 RcsProvisioningMonitor.getInstance().overrideImsFeatureValidation(TEST_SUB_ID, true); 742 SipTransportController controller = setupLiveTransportController(THROTTLE_MS, 0); 743 744 ArraySet<String> requestTags = new ArraySet<>(getBaseDelegateRequest().getFeatureTags()); 745 ArraySet<String> allowedTags = new ArraySet<>(requestTags); 746 DelegateRequest delegateRequest = new DelegateRequest(requestTags); 747 SipDelegateControllerContainer controllerContainer = 748 injectMockDelegateController(TEST_PACKAGE_NAME, delegateRequest); 749 CompletableFuture<Boolean> pendingScChange = createDelegate(controller, controllerContainer, 750 requestTags, Collections.emptySet()); 751 752 assertTrue(scheduleDelayedWait(2 * THROTTLE_MS)); 753 verifyDelegateChanged(controllerContainer.delegateController, pendingScChange, allowedTags, 754 Collections.emptySet(), 0); 755 } 756 757 @SafeVarargs getAllowedAndDeniedTagsForConfig( DelegateRequest r, int denyReason, Set<String>... previousRequestedTagSets)758 private final Pair<Set<String>, Set<FeatureTagState>> getAllowedAndDeniedTagsForConfig( 759 DelegateRequest r, int denyReason, Set<String>... previousRequestedTagSets) { 760 ArraySet<String> rejectedTags = new ArraySet<>(r.getFeatureTags()); 761 ArraySet<String> grantedTags = new ArraySet<>(r.getFeatureTags()); 762 Set<String> previousRequestedTags = new ArraySet<>(); 763 for (Set<String> s : previousRequestedTagSets) { 764 previousRequestedTags.addAll(s); 765 } 766 rejectedTags.retainAll(previousRequestedTags); 767 grantedTags.removeAll(previousRequestedTags); 768 Set<FeatureTagState> deniedTags = getDeniedTagsForReason(rejectedTags, denyReason); 769 return new Pair<>(grantedTags, deniedTags); 770 } 771 completePendingChange(CompletableFuture<Boolean> change, boolean result)772 private void completePendingChange(CompletableFuture<Boolean> change, boolean result) { 773 mExecutorService.execute(() -> change.complete(result)); 774 waitForExecutorAction(mExecutorService, TIMEOUT_MS); 775 } 776 completePendingDestroy(CompletableFuture<Integer> destroy, int result)777 private void completePendingDestroy(CompletableFuture<Integer> destroy, int result) { 778 mExecutorService.execute(() -> destroy.complete(result)); 779 waitForExecutorAction(mExecutorService, TIMEOUT_MS); 780 } 781 setupLiveTransportController()782 private SipTransportController setupLiveTransportController() throws Exception { 783 return setupLiveTransportController(0 /*throttleMs*/, 0 /*regDelayMs*/); 784 } 785 setupLiveTransportController(int throttleMs, int regDelayMs)786 private SipTransportController setupLiveTransportController(int throttleMs, int regDelayMs) 787 throws Exception { 788 mExecutorService = Executors.newSingleThreadScheduledExecutor(); 789 SipTransportController controller = createControllerAndThrottle(mExecutorService, 790 throttleMs, regDelayMs); 791 doReturn(mSipTransport).when(mRcsManager).getSipTransport(); 792 controller.onAssociatedSubscriptionUpdated(TEST_SUB_ID); 793 controller.onRcsConnected(mRcsManager); 794 waitForExecutorAction(mExecutorService, TIMEOUT_MS); 795 return controller; 796 } 797 createDelegateAndVerify(SipTransportController controller, SipDelegateControllerContainer controllerContainer, Set<String> allowedTags, Set<FeatureTagState> deniedTags, int numPreviousChanges)798 private void createDelegateAndVerify(SipTransportController controller, 799 SipDelegateControllerContainer controllerContainer, Set<String> allowedTags, 800 Set<FeatureTagState> deniedTags, int numPreviousChanges) { 801 802 CompletableFuture<Boolean> pendingChange = createDelegate(controller, controllerContainer, 803 allowedTags, deniedTags); 804 verifyDelegateChanged(controllerContainer.delegateController, pendingChange, allowedTags, 805 deniedTags, numPreviousChanges); 806 } 807 createDelegateAndVerify(SipTransportController controller, SipDelegateControllerContainer controllerContainer, Set<String> allowedTags, Set<FeatureTagState> deniedTags)808 private void createDelegateAndVerify(SipTransportController controller, 809 SipDelegateControllerContainer controllerContainer, Set<String> allowedTags, 810 Set<FeatureTagState> deniedTags) { 811 createDelegateAndVerify(controller, controllerContainer, allowedTags, deniedTags, 0); 812 } 813 createDelegate(SipTransportController controller, SipDelegateControllerContainer delegateControllerContainer, Set<String> allowedTags, Set<FeatureTagState> deniedTags)814 private CompletableFuture<Boolean> createDelegate(SipTransportController controller, 815 SipDelegateControllerContainer delegateControllerContainer, Set<String> allowedTags, 816 Set<FeatureTagState> deniedTags) { 817 CompletableFuture<Boolean> pendingChange = setChangeSupportedFeatureTagsFuture( 818 delegateControllerContainer.delegateController, allowedTags, deniedTags); 819 try { 820 controller.createSipDelegate(delegateControllerContainer.subId, TEST_UID, 821 delegateControllerContainer.delegateRequest, 822 delegateControllerContainer.packageName, 823 delegateControllerContainer.mockDelegateConnectionCallback, 824 delegateControllerContainer.mockMessageCallback); 825 } catch (ImsException e) { 826 fail("ImsException thrown:" + e); 827 } 828 // move to internal & schedule eval 829 waitForExecutorAction(mExecutorService, TIMEOUT_MS); 830 // reeval 831 waitForExecutorAction(mExecutorService, TIMEOUT_MS); 832 return pendingChange; 833 } 834 verifyDelegateChanged(SipDelegateController delegateController, CompletableFuture<Boolean> pendingChange, Set<String> allowedTags, Set<FeatureTagState> deniedTags, int numPreviousChangeStages)835 private void verifyDelegateChanged(SipDelegateController delegateController, 836 CompletableFuture<Boolean> pendingChange, Set<String> allowedTags, 837 Set<FeatureTagState> deniedTags, int numPreviousChangeStages) { 838 // empty the queue of pending changeSupportedFeatureTags before running the one we are 839 // interested in, since the reevaluate waits for one stage to complete before moving to the 840 // next. 841 for (int i = 0; i < numPreviousChangeStages + 1; i++) { 842 assertTrue(waitForExecutorAction(mExecutorService, TIMEOUT_MS)); 843 } 844 // verify change was called. 845 verify(delegateController).changeSupportedFeatureTags(allowedTags, deniedTags); 846 // ensure thread is not blocked while waiting for pending complete. 847 assertTrue(waitForExecutorAction(mExecutorService, TIMEOUT_MS)); 848 completePendingChange(pendingChange, true); 849 // process pending change. 850 assertTrue(waitForExecutorAction(mExecutorService, TIMEOUT_MS)); 851 } 852 destroyDelegateAndVerify(SipTransportController controller, SipDelegateControllerContainer controllerContainer, boolean force, int reason)853 private void destroyDelegateAndVerify(SipTransportController controller, 854 SipDelegateControllerContainer controllerContainer, boolean force, int reason) { 855 SipDelegateController delegateController = controllerContainer.delegateController; 856 CompletableFuture<Integer> pendingDestroy = destroyDelegate(controller, delegateController, 857 force, reason); 858 verifyDestroyDelegate(delegateController, pendingDestroy, force, reason); 859 } 860 destroyDelegate(SipTransportController controller, SipDelegateController delegateController, boolean force, int reason)861 private CompletableFuture<Integer> destroyDelegate(SipTransportController controller, 862 SipDelegateController delegateController, boolean force, int reason) { 863 CompletableFuture<Integer> pendingDestroy = setDestroyFuture(delegateController, force, 864 reason); 865 controller.destroySipDelegate(TEST_SUB_ID, delegateController.getSipDelegateInterface(), 866 reason); 867 // move to internal & schedule eval 868 waitForExecutorAction(mExecutorService, TIMEOUT_MS); 869 // reeval 870 waitForExecutorAction(mExecutorService, TIMEOUT_MS); 871 return pendingDestroy; 872 } 873 verifyDestroyDelegate(SipDelegateController delegateController, CompletableFuture<Integer> pendingDestroy, boolean force, int reason)874 private void verifyDestroyDelegate(SipDelegateController delegateController, 875 CompletableFuture<Integer> pendingDestroy, boolean force, int reason) { 876 // verify destroy was called. 877 verify(delegateController).destroy(force, reason); 878 // ensure thread is not blocked while waiting for pending complete. 879 waitForExecutorAction(mExecutorService, TIMEOUT_MS); 880 completePendingDestroy(pendingDestroy, reason); 881 } 882 triggerFullNetworkRegistrationAndVerify(SipTransportController controller, SipDelegateControllerContainer controllerContainer)883 private void triggerFullNetworkRegistrationAndVerify(SipTransportController controller, 884 SipDelegateControllerContainer controllerContainer) { 885 SipDelegateController delegateController = controllerContainer.delegateController; 886 controller.triggerFullNetworkRegistration(TEST_SUB_ID, 887 delegateController.getSipDelegateInterface(), 403, "forbidden"); 888 // move to internal & trigger event 889 waitForExecutorAction(mExecutorService, TIMEOUT_MS); 890 verify(delegateController).triggerFullNetworkRegistration(403, "forbidden"); 891 } 892 triggerFullNetworkRegistrationAndVerifyNever(SipTransportController controller, SipDelegateControllerContainer controllerContainer)893 private void triggerFullNetworkRegistrationAndVerifyNever(SipTransportController controller, 894 SipDelegateControllerContainer controllerContainer) { 895 SipDelegateController delegateController = controllerContainer.delegateController; 896 controller.triggerFullNetworkRegistration(TEST_SUB_ID, 897 delegateController.getSipDelegateInterface(), 403, "forbidden"); 898 // move to internal & potentially trigger event 899 waitForExecutorAction(mExecutorService, TIMEOUT_MS); 900 verify(delegateController, never()).triggerFullNetworkRegistration(anyInt(), anyString()); 901 } 902 getBaseDelegateRequest()903 private DelegateRequest getBaseDelegateRequest() { 904 Set<String> featureTags = new ArraySet<>(); 905 featureTags.add(ImsSignallingUtils.ONE_TO_ONE_CHAT_TAG); 906 featureTags.add(ImsSignallingUtils.GROUP_CHAT_TAG); 907 featureTags.add(ImsSignallingUtils.FILE_TRANSFER_HTTP_TAG); 908 return new DelegateRequest(featureTags); 909 } 910 getDeniedTagsForReason(Set<String> deniedTags, int reason)911 private Set<FeatureTagState> getDeniedTagsForReason(Set<String> deniedTags, int reason) { 912 return deniedTags.stream().map(t -> new FeatureTagState(t, reason)) 913 .collect(Collectors.toSet()); 914 } 915 injectMockDelegateController(String packageName, DelegateRequest r)916 private SipDelegateControllerContainer injectMockDelegateController(String packageName, 917 DelegateRequest r) { 918 return injectMockDelegateController(TEST_SUB_ID, packageName, r); 919 } 920 injectMockDelegateController(int subId, String packageName, DelegateRequest r)921 private SipDelegateControllerContainer injectMockDelegateController(int subId, 922 String packageName, DelegateRequest r) { 923 SipDelegateControllerContainer c = new SipDelegateControllerContainer(subId, 924 packageName, r); 925 mMockControllers.add(c); 926 return c; 927 } 928 getMockDelegateController(int subId, String packageName, DelegateRequest r)929 private SipDelegateController getMockDelegateController(int subId, String packageName, 930 DelegateRequest r) { 931 return mMockControllers.stream() 932 .filter(c -> c.subId == subId && c.packageName.equals(packageName) 933 && c.delegateRequest.equals(r)) 934 .map(c -> c.delegateController).findFirst().orElse(null); 935 } 936 setChangeSupportedFeatureTagsFuture(SipDelegateController c, Set<String> supportedSet, Set<FeatureTagState> deniedSet)937 private CompletableFuture<Boolean> setChangeSupportedFeatureTagsFuture(SipDelegateController c, 938 Set<String> supportedSet, Set<FeatureTagState> deniedSet) { 939 CompletableFuture<Boolean> result = new CompletableFuture<>(); 940 doReturn(result).when(c).changeSupportedFeatureTags(eq(supportedSet), eq(deniedSet)); 941 return result; 942 } 943 setDestroyFuture(SipDelegateController c, boolean force, int destroyReason)944 private CompletableFuture<Integer> setDestroyFuture(SipDelegateController c, boolean force, 945 int destroyReason) { 946 CompletableFuture<Integer> result = new CompletableFuture<>(); 947 doReturn(result).when(c).destroy(force, destroyReason); 948 return result; 949 } 950 setSmsRoleAndEvaluate(SipTransportController c, String packageName)951 private void setSmsRoleAndEvaluate(SipTransportController c, String packageName) { 952 verify(mMockRoleManager).addOnRoleHoldersChangedListenerAsUser(any(), any(), any()); 953 mSmsPackageName.clear(); 954 mSmsPackageName.add(packageName); 955 c.onRoleHoldersChanged(RoleManager.ROLE_SMS, UserHandle.SYSTEM); 956 // finish internal throttled re-evaluate 957 waitForExecutorAction(mExecutorService, TIMEOUT_MS); 958 } 959 verifyNoDelegateRegistrationChangedEvent()960 private void verifyNoDelegateRegistrationChangedEvent() throws Exception { 961 // event is scheduled and then executed. 962 waitForExecutorAction(mExecutorService, TIMEOUT_MS); 963 verify(mImsRegistration, never()).triggerUpdateSipDelegateRegistration(); 964 } 965 verifyDelegateRegistrationChangedEvent(int times, int waitMs)966 private void verifyDelegateRegistrationChangedEvent(int times, int waitMs) 967 throws Exception { 968 // event is scheduled and then executed. 969 assertTrue(scheduleDelayedWait(waitMs)); 970 waitForExecutorAction(mExecutorService, TIMEOUT_MS); 971 verify(mImsRegistration, times(times)).triggerUpdateSipDelegateRegistration(); 972 } 973 974 verifyDelegateDeregistrationEvent()975 private void verifyDelegateDeregistrationEvent() throws Exception { 976 verify(mImsRegistration).triggerSipDelegateDeregistration(); 977 } 978 createController(ScheduledExecutorService e)979 private SipTransportController createController(ScheduledExecutorService e) { 980 return createControllerAndThrottle(e, 0 /*throttleMs*/, 0 /*regDelayMs*/); 981 } 982 createControllerAndThrottle(ScheduledExecutorService e, int throttleMs, int regDelayMs)983 private SipTransportController createControllerAndThrottle(ScheduledExecutorService e, 984 int throttleMs, int regDelayMs) { 985 return new SipTransportController(mContext, 0 /*slotId*/, TEST_SUB_ID, 986 mMockDelegateControllerFactory, mMockRoleManager, 987 // Remove delays for testing. 988 new SipTransportController.TimerAdapter() { 989 @Override 990 public int getReevaluateThrottleTimerMilliseconds() { 991 return throttleMs; 992 } 993 994 @Override 995 public int getUpdateRegistrationDelayMilliseconds() { 996 return regDelayMs; 997 } 998 }, e); 999 } 1000 1001 private boolean scheduleDelayedWait(long timeMs) { 1002 CountDownLatch l = new CountDownLatch(1); 1003 mExecutorService.schedule(l::countDown, timeMs, TimeUnit.MILLISECONDS); 1004 while (l.getCount() > 0) { 1005 try { 1006 return l.await(TIMEOUT_MS, TimeUnit.MILLISECONDS); 1007 } catch (InterruptedException e) { 1008 // try again 1009 } 1010 } 1011 return true; 1012 } 1013 1014 private void setFeatureAllowedConfig(int subId, String[] tags) { 1015 PersistableBundle bundle = mContext.getCarrierConfig(subId); 1016 bundle.putStringArray( 1017 CarrierConfigManager.Ims.KEY_RCS_FEATURE_TAG_ALLOWED_STRING_ARRAY, tags); 1018 } 1019 } 1020