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 android.telephony.ims.cts;
18 
19 import static junit.framework.Assert.assertNotNull;
20 import static junit.framework.Assert.assertTrue;
21 
22 import static org.junit.Assert.assertEquals;
23 import static org.junit.Assert.assertFalse;
24 import static org.junit.Assert.assertNull;
25 import static org.junit.Assert.fail;
26 import static org.junit.Assume.assumeTrue;
27 
28 import static java.nio.charset.StandardCharsets.UTF_8;
29 
30 import android.content.BroadcastReceiver;
31 import android.content.Context;
32 import android.content.Intent;
33 import android.content.IntentFilter;
34 import android.net.InetAddresses;
35 import android.net.Uri;
36 import android.os.Parcel;
37 import android.os.PersistableBundle;
38 import android.telephony.CarrierConfigManager;
39 import android.telephony.SubscriptionManager;
40 import android.telephony.TelephonyManager;
41 import android.telephony.cts.util.TelephonyUtils;
42 import android.telephony.ims.DelegateRegistrationState;
43 import android.telephony.ims.DelegateRequest;
44 import android.telephony.ims.FeatureTagState;
45 import android.telephony.ims.ImsException;
46 import android.telephony.ims.ImsManager;
47 import android.telephony.ims.ImsService;
48 import android.telephony.ims.ImsStateCallback;
49 import android.telephony.ims.SipDelegateConfiguration;
50 import android.telephony.ims.SipDelegateManager;
51 import android.telephony.ims.SipDialogState;
52 import android.telephony.ims.SipDialogStateCallback;
53 import android.telephony.ims.SipMessage;
54 import android.telephony.ims.feature.ImsFeature;
55 import android.telephony.ims.stub.ImsFeatureConfiguration;
56 import android.util.ArraySet;
57 
58 import androidx.test.ext.junit.runners.AndroidJUnit4;
59 import androidx.test.platform.app.InstrumentationRegistry;
60 
61 import com.android.compatibility.common.util.ShellIdentityUtils;
62 import com.android.internal.telephony.flags.Flags;
63 
64 import org.junit.After;
65 import org.junit.AfterClass;
66 import org.junit.Before;
67 import org.junit.BeforeClass;
68 import org.junit.Ignore;
69 import org.junit.Test;
70 import org.junit.runner.RunWith;
71 
72 import java.net.InetSocketAddress;
73 import java.util.Arrays;
74 import java.util.Collections;
75 import java.util.List;
76 import java.util.Set;
77 import java.util.concurrent.Callable;
78 import java.util.concurrent.CountDownLatch;
79 import java.util.concurrent.TimeUnit;
80 import java.util.stream.Collectors;
81 
82 /**
83  * CTS tests for {@link SipDelegateManager} API.
84  */
85 @RunWith(AndroidJUnit4.class)
86 public class SipDelegateManagerTest {
87     private static final String MMTEL_TAG =
88             "+g.3gpp.iari-ref=\"urn%3Aurn-7%3A3gpp-service.ims.icsi.mmtel\"";
89     private static final String ONE_TO_ONE_CHAT_TAG =
90             "+g.3gpp.icsi-ref=\"urn%3Aurn-7%3A3gppservice.ims.icsi.oma.cpm.msg\"";
91     private static final String GROUP_CHAT_TAG =
92             "+g.3gpp.icsi-ref=\"urn%3Aurn-7%3A3gppservice.ims.icsi.oma.cpm.session\"";
93     private static final String FILE_TRANSFER_HTTP_TAG =
94             "+g.3gpp.iari-ref=\"urn%3Aurn-7%3A3gppapplication.ims.iari.rcs.fthttp\"";
95     private static final String CHATBOT_COMMUNICATION_USING_SESSION_TAG =
96             "+g.3gpp.iari-ref=\"urn%3Aurn-7%3A3gpp-application.ims.iari.rcs.chatbot\"";
97     private static final String[] DEFAULT_FEATURE_TAGS = {
98             ONE_TO_ONE_CHAT_TAG, GROUP_CHAT_TAG, FILE_TRANSFER_HTTP_TAG,
99             CHATBOT_COMMUNICATION_USING_SESSION_TAG};
100 
101     private static class CarrierConfigReceiver extends BroadcastReceiver {
102         private CountDownLatch mLatch = new CountDownLatch(1);
103         private final int mSubId;
104 
CarrierConfigReceiver(int subId)105         CarrierConfigReceiver(int subId) {
106             mSubId = subId;
107         }
108 
109         @Override
onReceive(Context context, Intent intent)110         public void onReceive(Context context, Intent intent) {
111             if (CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED.equals(intent.getAction())) {
112                 int subId = intent.getIntExtra(CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX, -1);
113                 if (mSubId == subId) {
114                     mLatch.countDown();
115                 }
116             }
117         }
118 
clearQueue()119         void clearQueue() {
120             mLatch = new CountDownLatch(1);
121         }
122 
waitForCarrierConfigChanged()123         void waitForCarrierConfigChanged() throws Exception {
124             mLatch.await(5000, TimeUnit.MILLISECONDS);
125         }
126     }
127 
128     /**
129      * Encapsulates the interfaces created during SipDelegateManager testing.
130      */
131     public class TransportInterfaces {
132         public final DelegateRequest request;
133         public final Set<FeatureTagState> deniedTags;
134         public final SipDelegateManager manager;
135         public TestSipTransport transport;
136         public TestImsRegistration reg;
137         public TestSipDelegate delegate;
138         public TestSipDelegateConnection delegateConn;
139         private final int mDelegateIndex;
140 
TransportInterfaces(DelegateRequest request, Set<FeatureTagState> deniedTags, int delegateIndex)141         public TransportInterfaces(DelegateRequest request, Set<FeatureTagState>  deniedTags,
142                 int delegateIndex) {
143             this.request = request;
144             this.deniedTags = deniedTags;
145             manager = getSipDelegateManager();
146             mDelegateIndex = delegateIndex;
147         }
148 
connect()149         public void connect() throws Exception {
150             assertTrue(sServiceConnector.setDefaultSmsApp());
151             connectTestImsServiceWithSipTransportAndConfig();
152 
153             transport = sServiceConnector.getCarrierService().getSipTransport();
154             reg = sServiceConnector.getCarrierService().getImsRegistration();
155             delegateConn = new TestSipDelegateConnection(request);
156 
157             delegate = createSipDelegateConnectionAndVerify(manager, delegateConn,
158                     transport, deniedTags, mDelegateIndex);
159             assertNotNull(delegate);
160             // ensure we got a callback for initial reg state.
161             verifyUpdateRegistrationCalled(reg);
162 
163             InetSocketAddress localAddr = new InetSocketAddress(
164                     InetAddresses.parseNumericAddress("1.1.1.1"), 80);
165             InetSocketAddress serverAddr = new InetSocketAddress(
166                     InetAddresses.parseNumericAddress("2.2.2.2"), 81);
167             SipDelegateConfiguration c = new SipDelegateConfiguration.Builder(1,
168                     SipDelegateConfiguration.SIP_TRANSPORT_TCP, localAddr, serverAddr).build();
169             // send first SIP config and verify
170             verifyRegisteredAndSendSipConfig(delegateConn, delegate, request.getFeatureTags(),
171                     deniedTags, c);
172         }
173 
174         /**
175          * Create a connection between fake app interface and fake ImsService impl and set up the
176          * framework to accept incoming/outgoing messages. Once done, verify the transport is open.
177          */
connectAndVerify()178         public void connectAndVerify() throws Exception {
179             connect();
180 
181             // Verify message transport is open.
182             verifyOutgoingTransport(delegateConn, delegate);
183             verifyIncomingTransport(delegateConn, delegate);
184         }
185     }
186 
187     private static int sTestSlot = 0;
188     private static int sTestSub = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
189     private static ImsServiceConnector sServiceConnector;
190     private static CarrierConfigReceiver sReceiver;
191     private static int sUpdatedStateSize = 0;
192     private static boolean sUpdatedState = false;
193 
194     @BeforeClass
beforeAllTests()195     public static void beforeAllTests() throws Exception {
196         // First, only populate test slot/sub
197         if (!ImsUtils.shouldTestTelephony()) {
198             return;
199         }
200 
201         TelephonyManager tm = (TelephonyManager) getContext()
202                 .getSystemService(Context.TELEPHONY_SERVICE);
203         sTestSub = ImsUtils.getPreferredActiveSubId();
204         sTestSlot = SubscriptionManager.getSlotIndex(sTestSub);
205         if (tm.getSimState(sTestSlot) != TelephonyManager.SIM_STATE_READY) {
206             return;
207         }
208         // Next, only start tests that require ImsResolver to bind to test ImsService if
209         // feature FEATURE_TELEPHONY_IMS is supported on this device.
210         if (!ImsUtils.shouldTestImsService()) {
211             return;
212         }
213         sServiceConnector = new ImsServiceConnector(InstrumentationRegistry.getInstrumentation());
214         // Remove all live ImsServices until after these tests are done
215         sServiceConnector.clearAllActiveImsServices(sTestSlot);
216 
217         sReceiver = new CarrierConfigReceiver(sTestSub);
218         IntentFilter filter = new IntentFilter(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
219         // ACTION_CARRIER_CONFIG_CHANGED is sticky, so we will get a callback right away.
220         InstrumentationRegistry.getInstrumentation().getContext()
221                 .registerReceiver(sReceiver, filter);
222 
223         if (!ImsUtils.shouldTestImsSingleRegistration()) {
224             // override FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION setting for this test to enable
225             // APIs.
226             sServiceConnector.setDeviceSingleRegistrationEnabled(true);
227         }
228 
229         setFeatureTagsCarrierAllowed(DEFAULT_FEATURE_TAGS);
230     }
231 
232     @AfterClass
afterAllTests()233     public static void afterAllTests() throws Exception {
234         // Only clean up ImsResolver overrides if feature FEATURE_TELEPHONY_IMS is supported.
235         if (!ImsUtils.shouldTestImsService()) {
236             return;
237         }
238 
239         // Restore all ImsService configurations that existed before the test.
240         if (sServiceConnector != null) {
241             sServiceConnector.disconnectServices();
242         }
243         sServiceConnector = null;
244 
245         // Ensure there are no CarrierConfig overrides as well as reset the ImsResolver in case the
246         // ImsService override changed in CarrierConfig while we were overriding it.
247         overrideCarrierConfig(null);
248 
249         if (sReceiver != null) {
250             InstrumentationRegistry.getInstrumentation().getContext().unregisterReceiver(sReceiver);
251             sReceiver = null;
252         }
253     }
254 
255     @Before
beforeTest()256     public void beforeTest() {
257         if (Flags.enforceTelephonyFeatureMappingForPublicApis()) {
258             // If the device does not have FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION,
259             // skip the all tests
260             assumeTrue(ImsUtils.shouldTestImsSingleRegistration());
261         } else {
262             if (!ImsUtils.shouldTestTelephony()) {
263                 return;
264             }
265         }
266         TelephonyManager tm = (TelephonyManager) InstrumentationRegistry.getInstrumentation()
267                 .getContext().getSystemService(Context.TELEPHONY_SERVICE);
268         if (tm.getSimState(sTestSlot) != TelephonyManager.SIM_STATE_READY) {
269             fail("This test requires that there is a SIM in the device!");
270         }
271         // Correctness check: ensure that the subscription hasn't changed between tests.
272         int subId = SubscriptionManager.getSubscriptionId(sTestSlot);
273         if (subId != sTestSub) {
274             fail("The found subId " + subId + " does not match the test sub id " + sTestSub);
275         }
276     }
277 
278     @After
afterTest()279     public void afterTest() throws Exception {
280         if (!ImsUtils.shouldTestImsService()) {
281             return;
282         }
283         // Unbind the ImsService after the test completes only if feature FEATURE_TELEPHONY_IMS
284         // is enabled.
285         if (sServiceConnector != null) {
286             sServiceConnector.disconnectCarrierImsService();
287             sServiceConnector.restoreDefaultSmsApp();
288         }
289     }
290 
291     @Test
292     // Note this test can run on devices with only feature FEATURE_TELEPHONY, so ImsResolver may not
293     // be running.
testIncorrectPermissions()294     public void testIncorrectPermissions() throws Exception {
295         if (!ImsUtils.shouldTestTelephony()) {
296             return;
297         }
298         SipDelegateManager manager = getSipDelegateManager();
299         try {
300             manager.isSupported();
301             fail("isSupported requires READ_PRIVILEGED_PHONE_STATE or "
302                     + "PERFORM_IMS_SINGLE_REGISTRATION");
303         } catch (SecurityException e) {
304             //expected
305         }
306         try {
307             ShellIdentityUtils.invokeThrowableMethodWithShellPermissions(
308                     manager, SipDelegateManager::isSupported, ImsException.class,
309                     "android.permission.PERFORM_IMS_SINGLE_REGISTRATION");
310         } catch (ImsException e) {
311             // Not a problem, only checking permissions here.
312         } catch (SecurityException e) {
313             fail("isSupported requires READ_PRIVILEGED_PHONE_STATE or "
314                     + "PERFORM_IMS_SINGLE_REGISTRATION, exception:" + e);
315         }
316         try {
317             ShellIdentityUtils.invokeThrowableMethodWithShellPermissions(
318                     manager, SipDelegateManager::isSupported, ImsException.class,
319                     "android.permission.READ_PRIVILEGED_PHONE_STATE");
320 
321         } catch (ImsException e) {
322             // Not a problem, only checking permissions here.
323         } catch (SecurityException e) {
324             fail("isSupported requires READ_PRIVILEGED_PHONE_STATE or "
325                     + "PERFORM_IMS_SINGLE_REGISTRATION, exception:" + e);
326         }
327 
328         DelegateRequest d = new DelegateRequest(Collections.emptySet());
329         TestSipDelegateConnection c = new TestSipDelegateConnection(d);
330         try {
331             manager.createSipDelegate(d, Runnable::run, c, c);
332             fail("createSipDelegate requires PERFORM_IMS_SINGLE_REGISTRATION");
333         } catch (SecurityException e) {
334             //expected
335         }
336 
337 
338         ImsStateCallback callback = new ImsStateCallback() {
339             @Override
340             public void onUnavailable(int reason) { }
341             @Override
342             public void onAvailable() { }
343             @Override
344             public void onError() { }
345         };
346 
347         try {
348             manager.registerImsStateCallback(Runnable::run, callback);
349             fail("registerImsStateCallback requires PERFORM_IMS_SINGLE_REGISTRATION or "
350                     + "READ_PRIVILEGED_PHONE_STATE permission.");
351         } catch (SecurityException e) {
352             //expected
353         } catch (ImsException ignore) {
354             fail("registerImsStateCallback requires PERFORM_IMS_SINGLE_REGISTRATION or "
355                     + "READ_PRIVILEGED_PHONE_STATE permission.");
356         }
357 
358         try {
359             ShellIdentityUtils.invokeThrowableMethodWithShellPermissionsNoReturn(manager,
360                     m -> m.registerImsStateCallback(Runnable::run, callback),
361                     ImsException.class, "android.permission.PERFORM_IMS_SINGLE_REGISTRATION");
362         } catch (SecurityException e) {
363             fail("registerImsStateCallback requires PERFORM_IMS_SINGLE_REGISTRATION permission.");
364         } catch (ImsException ignore) {
365             // don't care, permission check passed
366         }
367 
368         try {
369             manager.unregisterImsStateCallback(callback);
370         } catch (SecurityException e) {
371             fail("uregisterImsStateCallback requires no permission.");
372         }
373 
374         try {
375             ShellIdentityUtils.invokeThrowableMethodWithShellPermissionsNoReturn(manager,
376                     m -> m.registerImsStateCallback(Runnable::run, callback),
377                     ImsException.class, "android.permission.READ_PRIVILEGED_PHONE_STATE");
378         } catch (SecurityException e) {
379             fail("registerImsStateCallback requires READ_PRIVILEGED_PHONE_STATE permission.");
380         } catch (ImsException ignore) {
381             // don't care, permission check passed
382         }
383 
384         try {
385             manager.unregisterImsStateCallback(callback);
386         } catch (SecurityException e) {
387             // unreachable, already passed permission check
388             fail("uregisterImsStateCallback requires no permission.");
389         }
390     }
391 
392     @Test
testSipDialogStateChanges()393     public void testSipDialogStateChanges() throws Exception {
394         if (!ImsUtils.shouldTestImsService()) {
395             return;
396         }
397         SipDialogStateCallback callback = new SipDialogStateCallback() {
398             @Override
399             public void onActiveSipDialogsChanged(List<SipDialogState> dialogs) {
400                 int confirmedSize = dialogs.stream().filter(
401                         d -> d.getState() == SipDialogState.STATE_CONFIRMED)
402                         .collect(Collectors.toSet()).size();
403                 if (confirmedSize > 0) {
404                     sUpdatedState = true;
405                 } else {
406                     sUpdatedState = false;
407                 }
408             }
409             @Override
410             public void onError() { }
411         };
412 
413         TransportInterfaces ifaces = new TransportInterfaces(getDefaultRequest(),
414                 Collections.emptySet(), 0);
415         ifaces.connect();
416         try {
417             ShellIdentityUtils.invokeThrowableMethodWithShellPermissionsNoReturn(ifaces.manager,
418                     m -> m.registerSipDialogStateCallback(Runnable::run, callback),
419                     ImsException.class, "android.permission.READ_PRIVILEGED_PHONE_STATE");
420         } catch (SecurityException e) {
421             fail("registerSipDialogStateCallback requires READ_PRIVILEGED_PHONE_STATE permission.");
422         } catch (ImsException ignore) {
423             // don't care, permission check passed
424         }
425         ifaces.delegateConn.setOperationCountDownLatch(1);
426         ifaces.delegateConn.waitForCountDown(1000);
427         // Send invite
428         SipDialogAttributes attr = new SipDialogAttributes();
429         sendChatInvite(attr, ifaces);
430         assertFalse(sUpdatedState);
431         // receive 200 OK
432         receive200OkResponse(attr, ifaces);
433         ifaces.delegateConn.setOperationCountDownLatch(1);
434         ifaces.delegateConn.waitForCountDown(1000);
435         // SipDialog Confirmed
436         assertTrue(sUpdatedState);
437         // Send ACK
438         sendAck(attr, ifaces);
439         // Send BYE
440         sendByeRequest(attr, ifaces);
441         // SipDialog Closed
442         ifaces.delegateConn.setOperationCountDownLatch(1);
443         ifaces.delegateConn.waitForCountDown(1000);
444         assertFalse(sUpdatedState);
445 
446         // Send the cleanup, which will trigger destroy to complete.
447         ifaces.delegateConn.sendCleanupSession(attr.callId);
448         ifaces.delegate.verifyCleanupSession(attr.callId);
449         ifaces.delegateConn.setOperationCountDownLatch(1);
450         ifaces.delegateConn.waitForCountDown(1000);
451         try {
452             ShellIdentityUtils.invokeThrowableMethodWithShellPermissionsNoReturn(ifaces.manager,
453                     m -> m.unregisterSipDialogStateCallback(callback),
454                     ImsException.class, "android.permission.READ_PRIVILEGED_PHONE_STATE");
455         } catch (SecurityException e) {
456             fail("registerSipDialogStateCallback requires READ_PRIVILEGED_PHONE_STATE permission.");
457         }
458         destroySipDelegateAndVerify(ifaces);
459         assertEquals("There should be no more delegates", 0,
460                 ifaces.transport.getDelegates().size());
461         verifyUpdateRegistrationCalled(ifaces.reg);
462     }
463 
464     @Test
testSipDialogStateChangesOnMultipleDelegates()465     public void testSipDialogStateChangesOnMultipleDelegates() throws Exception {
466         if (!ImsUtils.shouldTestImsService()) {
467             return;
468         }
469         InetSocketAddress localAddr = new InetSocketAddress(
470                 InetAddresses.parseNumericAddress("1.1.1.1"), 80);
471         InetSocketAddress serverAddr = new InetSocketAddress(
472                 InetAddresses.parseNumericAddress("2.2.2.2"), 81);
473         SipDelegateConfiguration c = new SipDelegateConfiguration.Builder(1,
474                 SipDelegateConfiguration.SIP_TRANSPORT_TCP, localAddr, serverAddr).build();
475 
476         SipDialogStateCallback callback = new SipDialogStateCallback() {
477             @Override
478             public void onActiveSipDialogsChanged(List<SipDialogState> dialogs) {
479                 sUpdatedStateSize = dialogs.stream()
480                         .filter(d -> d.getState() == SipDialogState.STATE_CONFIRMED)
481                         .collect(Collectors.toList()).size();
482             }
483             @Override
484             public void onError() { }
485         };
486 
487         SipDelegateManager manager = getSipDelegateManager();
488         assertTrue(sServiceConnector.setDefaultSmsApp());
489         connectTestImsServiceWithSipTransportAndConfig();
490         TestSipTransport transportImpl = sServiceConnector.getCarrierService().getSipTransport();
491         TestImsRegistration regImpl = sServiceConnector.getCarrierService().getImsRegistration();
492 
493         // create delegate#1
494         DelegateRequest request1 = getChatOnlyRequest();
495         TestSipDelegateConnection delegateConn1 = new TestSipDelegateConnection(request1);
496         TestSipDelegate delegate1 = createSipDelegateConnectionAndVerify(manager, delegateConn1,
497                 transportImpl, Collections.emptySet(), 0);
498         Set<String> registeredTags1 = new ArraySet<>(request1.getFeatureTags());
499         assertNotNull(delegate1);
500         verifyRegisteredAndSendSipConfig(delegateConn1, delegate1, registeredTags1,
501                 Collections.emptySet(), c);
502         //delegate : 1, dialog confirmed : 0
503         assertEquals(0, sUpdatedStateSize);
504         try {
505             ShellIdentityUtils.invokeThrowableMethodWithShellPermissionsNoReturn(manager,
506                     m -> m.registerSipDialogStateCallback(Runnable::run, callback),
507                     ImsException.class, "android.permission.READ_PRIVILEGED_PHONE_STATE");
508         } catch (SecurityException e) {
509             fail("registerSipDialogStateCallback requires READ_PRIVILEGED_PHONE_STATE permission.");
510         } catch (ImsException ignore) {
511             // don't care, permission check passed
512         }
513         // INVITE/200OK on Delegate#1
514         SipDialogAttributes attr = new SipDialogAttributes();
515         SipDialogAttributes invAttr = attr.fromExisting().copyWithNewBranch();
516         invAttr.addAcceptContactTag(GROUP_CHAT_TAG);
517         SipMessage invite = SipMessageUtils.generateSipRequest(SipMessageUtils.INVITE_SIP_METHOD,
518                 invAttr);
519         delegateConn1.sendMessageAndVerifyCompletedSuccessfully(invite);
520         SipMessage resp = SipMessageUtils.generateSipResponse("200", "OK",
521                 attr);
522         delegate1.receiveMessageAndVerifyReceivedCalled(resp);
523         delegateConn1.verifyMessageReceived(resp);
524         delegateConn1.setOperationCountDownLatch(1);
525         delegateConn1.waitForCountDown(/*ImsUtils.TEST_TIMEOUT_MS*/1000);
526         //delegate : 1, dialog confirmed : 1
527         assertEquals(1, sUpdatedStateSize);
528 
529         // create delegate#2
530         DelegateRequest request2 = getDefaultRequest();
531         TestSipDelegateConnection delegateConn2 = new TestSipDelegateConnection(request2);
532         Set<String> registeredTags2 = new ArraySet<>(request2.getFeatureTags());
533         TestSipDelegate delegate2 = createSipDelegateConnectionAndVerify(manager, delegateConn2,
534                 transportImpl, Collections.emptySet(), 1);
535         assertNotNull(delegate2);
536         verifyUpdateRegistrationCalled(regImpl);
537         Set<FeatureTagState> deniedSet = generateDeniedSetFromRequest(request1.getFeatureTags(),
538                 request2.getFeatureTags(),
539                 SipDelegateManager.DENIED_REASON_IN_USE_BY_ANOTHER_DELEGATE);
540         verifyRegisteredAndSendSipConfig(delegateConn2, delegate2, registeredTags2, deniedSet, c);
541         // INVITE/200OK on Delegate#2
542         SipDialogAttributes attr2 = new SipDialogAttributes();
543         SipDialogAttributes invAttr2 = attr2.fromExisting().copyWithNewBranch();
544         invAttr2.addAcceptContactTag(CHATBOT_COMMUNICATION_USING_SESSION_TAG);
545         SipMessage invite2 = SipMessageUtils.generateSipRequest(SipMessageUtils.INVITE_SIP_METHOD,
546                 invAttr2);
547         delegateConn2.sendMessageAndVerifyCompletedSuccessfully(invite2);
548         SipMessage resp2 = SipMessageUtils.generateSipResponse("200", "OK",
549                 attr2);
550         delegate2.receiveMessageAndVerifyReceivedCalled(resp2);
551         delegateConn2.verifyMessageReceived(resp2);
552         delegateConn2.setOperationCountDownLatch(1);
553         delegateConn2.waitForCountDown(/*ImsUtils.TEST_TIMEOUT_MS*/1000);
554         //delegate : 2, dialog confirmed : 2
555         assertEquals(2, sUpdatedStateSize);
556         // Destroying delegate 1 will transfer all feature tags over to delegate 2
557         destroySipDelegate(manager, transportImpl, delegateConn1, delegate1);
558         // If one delegate is destroyed in multiple delegates,
559         // it internally triggers the destruction of the remaining delegates
560         // and then the recreation of another delegate with the new feature set that it supports.
561         verifySipDelegateDestroyed(transportImpl, delegate2);
562         delegateConn2.setOperationCountDownLatch(1);
563         delegateConn2.waitForCountDown(/*ImsUtils.TEST_TIMEOUT_MS*/1000);
564         //delegate : 1, dialog confirmed : 0
565         assertEquals(0, sUpdatedStateSize);
566         delegate2 = getSipDelegate(transportImpl, Collections.emptySet(), 0);
567         verifyUpdateRegistrationCalled(regImpl);
568         verifyRegisteredAndSendSipConfig(delegateConn2, delegate2, request2.getFeatureTags(),
569                 Collections.emptySet(), c);
570         destroySipDelegateAndVerifyConnDestroyed(manager, transportImpl, delegateConn2, delegate2);
571         assertEquals("There should be no more delegates", 0,
572                 transportImpl.getDelegates().size());
573     }
574 
575     @Test
576     // Note this test can run on devices with only feature FEATURE_TELEPHONY, so ImsResolver may not
577     // be running.
testFeatureImsNotSupported()578     public void testFeatureImsNotSupported() throws Exception {
579         if (!ImsUtils.shouldTestTelephony()) {
580             return;
581         }
582 
583         if (sServiceConnector != null) {
584             // Override FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION for this test so that telephony
585             // will report not enabled.
586             sServiceConnector.setDeviceSingleRegistrationEnabled(false);
587         }
588 
589         try {
590             SipDelegateManager manager = getSipDelegateManager();
591 
592             try {
593                 // If FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION is not supported this should
594                 // return false.
595                 Boolean result = ShellIdentityUtils.invokeThrowableMethodWithShellPermissions(
596                         manager, SipDelegateManager::isSupported, ImsException.class,
597                         "android.permission.PERFORM_IMS_SINGLE_REGISTRATION");
598                 assertNotNull(result);
599                 assertFalse("isSupported should return false on devices that do not "
600                         + "support feature FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION", result);
601             } catch (SecurityException e) {
602                 fail("isSupported requires PERFORM_IMS_SINGLE_REGISTRATION permission");
603             }
604 
605             try {
606                 // If FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION is not supported, this should throw
607                 // an ImsException
608                 DelegateRequest request = new DelegateRequest(Collections.emptySet());
609                 TestSipDelegateConnection delegateConn = new TestSipDelegateConnection(request);
610                 ShellIdentityUtils.invokeThrowableMethodWithShellPermissionsNoReturn(
611                         manager, (m) -> m.createSipDelegate(request, Runnable::run,
612                                 delegateConn, delegateConn), ImsException.class,
613                         "android.permission.PERFORM_IMS_SINGLE_REGISTRATION");
614                 fail("createSipDelegate should throw an ImsException with code "
615                         + "CODE_ERROR_UNSUPPORTED_OPERATION on devices that do not support feature "
616                         + "FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION");
617             } catch (SecurityException e) {
618                 fail("isSupported requires PERFORM_IMS_SINGLE_REGISTRATION permission");
619             } catch (ImsException e) {
620                 // expecting CODE_ERROR_UNSUPPORTED_OPERATION
621                 if (e.getCode() != ImsException.CODE_ERROR_UNSUPPORTED_OPERATION) {
622                     fail("createSipDelegate should throw an ImsException with code "
623                             + "CODE_ERROR_UNSUPPORTED_OPERATION on devices that do not support "
624                             + "feature FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION");
625                 }
626             }
627         } finally {
628             if (sServiceConnector != null) {
629                 // restore override for the rest of the tests.
630                 sServiceConnector.setDeviceSingleRegistrationEnabled(true);
631             }
632         }
633     }
634 
635     @Test
testIsSupportedWithSipTransportCapable()636     public void testIsSupportedWithSipTransportCapable() throws Exception {
637         if (!ImsUtils.shouldTestImsService()) {
638             return;
639         }
640         PersistableBundle b = new PersistableBundle();
641         b.putBoolean(CarrierConfigManager.Ims.KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL, true);
642         overrideCarrierConfig(b);
643         connectTestImsServiceWithSipTransport();
644 
645         SipDelegateManager manager = getSipDelegateManager();
646         Boolean result = null;
647         try {
648             result = callUntilImsServiceIsAvailable(() ->
649                     ShellIdentityUtils.invokeThrowableMethodWithShellPermissions(manager,
650                             SipDelegateManager::isSupported, ImsException.class,
651                             "android.permission.PERFORM_IMS_SINGLE_REGISTRATION"));
652         } catch (SecurityException e) {
653             fail("isSupported requires PERFORM_IMS_SINGLE_REGISTRATION permission");
654         }
655         assertNotNull(result);
656         assertTrue("isSupported should return true", result);
657     }
658 
659     @Test
testIsSupportedWithSipTransportCapableCarrierConfigNotSet()660     public void testIsSupportedWithSipTransportCapableCarrierConfigNotSet() throws Exception {
661         if (!ImsUtils.shouldTestImsService()) {
662             return;
663         }
664         PersistableBundle b = new PersistableBundle();
665         // Carrier Config is explicitly set to not support single registration.
666         b.putBoolean(CarrierConfigManager.Ims.KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL, false);
667         overrideCarrierConfig(b);
668         connectTestImsServiceWithSipTransport();
669 
670         Boolean result = callUntilImsServiceIsAvailable(() ->
671                 ShellIdentityUtils.invokeThrowableMethodWithShellPermissions(
672                         getSipDelegateManager(), SipDelegateManager::isSupported,
673                         ImsException.class, "android.permission.PERFORM_IMS_SINGLE_REGISTRATION"));
674         assertNotNull(result);
675         assertFalse("isSupported should return false if"
676                 + "CarrierConfigManager.Ims.KEY_RCS_SINGLE_REGISTRATION_REQUIRED_BOOL is set to "
677                 + "false", result);
678     }
679 
680     @Ignore("Disabling for integration b/175766573")
681     @Test
testIsSupportedWithSipTransportCapableOnlyRcs()682     public void testIsSupportedWithSipTransportCapableOnlyRcs() throws Exception {
683         if (!ImsUtils.shouldTestImsService()) {
684             return;
685         }
686         PersistableBundle b = new PersistableBundle();
687         b.putBoolean(CarrierConfigManager.Ims.KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL, true);
688         overrideCarrierConfig(b);
689 
690         assertTrue(sServiceConnector.connectCarrierImsServiceLocally());
691         // set SipTransport as supported with RCS only attached.
692         sServiceConnector.getCarrierService().addCapabilities(
693                 ImsService.CAPABILITY_SIP_DELEGATE_CREATION);
694         sServiceConnector.getCarrierService().setSipTransportImplemented();
695 
696         ImsFeatureConfiguration c = getConfigForRcs();
697         assertTrue(sServiceConnector.triggerFrameworkConnectionToCarrierImsService(c));
698         verifyImsServiceState(c);
699 
700         Boolean result = callUntilImsServiceIsAvailable(() ->
701                 ShellIdentityUtils.invokeThrowableMethodWithShellPermissions(
702                         getSipDelegateManager(), SipDelegateManager::isSupported,
703                         ImsException.class, "android.permission.PERFORM_IMS_SINGLE_REGISTRATION"));
704         assertNotNull(result);
705         assertFalse("isSupported should return false in the case that the ImsService is only "
706                 + "attached for RCS and not MMTEL and RCS", result);
707     }
708 
709 
710     @Test
testIsSupportedWithSipTransportCapableButNotImplemented()711     public void testIsSupportedWithSipTransportCapableButNotImplemented() throws Exception {
712         if (!ImsUtils.shouldTestImsService()) {
713             return;
714         }
715         PersistableBundle b = new PersistableBundle();
716         b.putBoolean(CarrierConfigManager.Ims.KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL, true);
717         overrideCarrierConfig(b);
718 
719         assertTrue(sServiceConnector.connectCarrierImsServiceLocally());
720         // SipTransport set as capable, but no SipTransport implementation is returned.
721         sServiceConnector.getCarrierService().addCapabilities(
722                 ImsService.CAPABILITY_SIP_DELEGATE_CREATION);
723         ImsFeatureConfiguration c = getConfigForMmTelAndRcs();
724         assertTrue(sServiceConnector.triggerFrameworkConnectionToCarrierImsService(c));
725         verifyImsServiceState(c);
726 
727         Boolean result = callUntilImsServiceIsAvailable(() ->
728                 ShellIdentityUtils.invokeThrowableMethodWithShellPermissions(
729                         getSipDelegateManager(), SipDelegateManager::isSupported,
730                         ImsException.class, "android.permission.PERFORM_IMS_SINGLE_REGISTRATION"));
731         assertNotNull(result);
732         assertFalse("isSupported should return false in the case that SipTransport is not "
733                 + "implemented", result);
734     }
735 
736     @Test
testIsSupportedWithSipTransportImplementedButNotCapable()737     public void testIsSupportedWithSipTransportImplementedButNotCapable() throws Exception {
738         if (!ImsUtils.shouldTestImsService()) {
739             return;
740         }
741         PersistableBundle b = new PersistableBundle();
742         b.putBoolean(CarrierConfigManager.Ims.KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL, true);
743         overrideCarrierConfig(b);
744 
745         assertTrue(sServiceConnector.connectCarrierImsServiceLocally());
746         // SipTransport is set as Implemented, but not Capable
747         sServiceConnector.getCarrierService().setSipTransportImplemented();
748         ImsFeatureConfiguration c = getConfigForMmTelAndRcs();
749         assertTrue(sServiceConnector.triggerFrameworkConnectionToCarrierImsService(c));
750         verifyImsServiceState(c);
751 
752         Boolean result = callUntilImsServiceIsAvailable(() ->
753                 ShellIdentityUtils.invokeThrowableMethodWithShellPermissions(
754                         getSipDelegateManager(), SipDelegateManager::isSupported,
755                         ImsException.class, "android.permission.PERFORM_IMS_SINGLE_REGISTRATION"));
756         assertNotNull(result);
757         assertFalse("isSupported should return false in the case that SipTransport is not "
758                 + "set as capable in ImsService#getImsServiceCapabilities", result);
759     }
760 
761     @Test
testIsSupportedWithSipTransportNotImplementedNotCapable()762     public void testIsSupportedWithSipTransportNotImplementedNotCapable() throws Exception {
763         if (!ImsUtils.shouldTestImsService()) {
764             return;
765         }
766         PersistableBundle b = new PersistableBundle();
767         b.putBoolean(CarrierConfigManager.Ims.KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL, true);
768         overrideCarrierConfig(b);
769 
770         assertTrue(sServiceConnector.connectCarrierImsServiceLocally());
771         // Not Implemented/capable
772         ImsFeatureConfiguration c = getConfigForMmTelAndRcs();
773         assertTrue(sServiceConnector.triggerFrameworkConnectionToCarrierImsService(c));
774         verifyImsServiceState(c);
775 
776         Boolean result = callUntilImsServiceIsAvailable(() ->
777                 ShellIdentityUtils.invokeThrowableMethodWithShellPermissions(
778                         getSipDelegateManager(), SipDelegateManager::isSupported,
779                         ImsException.class, "android.permission.PERFORM_IMS_SINGLE_REGISTRATION"));
780         assertNotNull(result);
781         assertFalse("isSupported should return false in the case that SipTransport is not "
782                 + "set as capable in ImsService#getImsServiceCapabilities", result);
783     }
784 
785     @Test
testCreateDestroyDelegateNotDefaultMessagingApp()786     public void testCreateDestroyDelegateNotDefaultMessagingApp() throws Exception {
787         if (!ImsUtils.shouldTestImsService()) {
788             return;
789         }
790         connectTestImsServiceWithSipTransportAndConfig();
791 
792         TestSipTransport transportImpl = sServiceConnector.getCarrierService().getSipTransport();
793         TestImsRegistration imsReg = sServiceConnector.getCarrierService().getImsRegistration();
794         SipDelegateManager manager = getSipDelegateManager();
795         DelegateRequest request = getDefaultRequest();
796         TestSipDelegateConnection delegateConn = new TestSipDelegateConnection(request);
797 
798         // wait for onCreated and registration state change to be called.
799         createSipDelegateConnectionNoDelegateExpected(manager, delegateConn, transportImpl);
800 
801         // TODO deal with this case better when we can filter messages.
802         delegateConn.sendMessageAndVerifyFailure(SipMessageUtils.TEST_SIP_MESSAGE,
803                 SipDelegateManager.MESSAGE_FAILURE_REASON_DELEGATE_DEAD);
804 
805         delegateConn.triggerFullNetworkRegistration(manager, 403, "FORBIDDEN");
806         // wait 5 seconds, this should not return.
807         TestImsRegistration.NetworkRegistrationInfo info =
808                 imsReg.getNextFullNetworkRegRequest(5000);
809         assertNull("If there is no valid SipTransport, this should not be called", info);
810 
811         destroySipDelegateConnectionNoDelegate(manager, delegateConn);
812     }
813 
814     @Test
testCreateDelegateBasicUseCases()815     public void testCreateDelegateBasicUseCases() throws Exception {
816         if (!ImsUtils.shouldTestImsService()) {
817             return;
818         }
819         TransportInterfaces ifaces = new TransportInterfaces(getDefaultRequest(),
820                 Collections.emptySet(), 0);
821         ifaces.connectAndVerify();
822 
823         // Ensure requests to perform a full network re-registration work properly.
824         verifyFullRegistrationTriggered(ifaces);
825 
826         destroySipDelegateAndVerify(ifaces);
827         assertEquals("There should be no more delegates", 0,
828                 ifaces.transport.getDelegates().size());
829         verifyUpdateRegistrationCalled(ifaces.reg);
830     }
831 
832     @Test
testImsServiceDisconnected()833     public void testImsServiceDisconnected() throws Exception {
834         if (!ImsUtils.shouldTestImsService()) {
835             return;
836         }
837         assertTrue(sServiceConnector.setDefaultSmsApp());
838         connectTestImsServiceWithSipTransportAndConfig();
839 
840         TestSipTransport transportImpl = sServiceConnector.getCarrierService().getSipTransport();
841         TestImsRegistration regImpl = sServiceConnector.getCarrierService().getImsRegistration();
842         SipDelegateManager manager = getSipDelegateManager();
843         DelegateRequest request = getDefaultRequest();
844         TestSipDelegateConnection delegateConn = new TestSipDelegateConnection(request);
845 
846         TestSipDelegate delegate = createSipDelegateConnectionAndVerify(manager, delegateConn,
847                 transportImpl, Collections.emptySet(), 0);
848         assertNotNull(delegate);
849         verifyUpdateRegistrationCalled(regImpl);
850 
851         InetSocketAddress localAddr = new InetSocketAddress(
852                 InetAddresses.parseNumericAddress("1.1.1.1"), 80);
853         InetSocketAddress serverAddr = new InetSocketAddress(
854                 InetAddresses.parseNumericAddress("2.2.2.2"), 81);
855         SipDelegateConfiguration c = new SipDelegateConfiguration.Builder(1,
856                 SipDelegateConfiguration.SIP_TRANSPORT_TCP, localAddr, serverAddr).build();
857         verifyRegisteredAndSendSipConfig(delegateConn, delegate, request.getFeatureTags(),
858                 Collections.emptySet(), c);
859 
860         verifyOutgoingTransport(delegateConn, delegate);
861         verifyIncomingTransport(delegateConn, delegate);
862 
863         sServiceConnector.disconnectCarrierImsService();
864         // unbind ImsService suddenly and wait for on destroyed
865         delegateConn.setOperationCountDownLatch(1);
866         transportImpl.waitForLatchCountdownAndReset(TestSipTransport.LATCH_DESTROY_DELEGATE);
867         delegate.notifyOnDestroyed(
868                 SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_SERVICE_DEAD);
869         delegateConn.waitForCountDown(ImsUtils.TEST_TIMEOUT_MS);
870         delegateConn.verifyDestroyed(
871                 SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_SERVICE_DEAD);
872     }
873 
874     @Test
testCreateDelegateTestInvalidSipMessages()875     public void testCreateDelegateTestInvalidSipMessages() throws Exception {
876         if (!ImsUtils.shouldTestImsService()) {
877             return;
878         }
879         TransportInterfaces ifaces = new TransportInterfaces(getDefaultRequest(),
880                 Collections.emptySet(), 0);
881         ifaces.connectAndVerify();
882 
883         // Verify restricted SIP request methods are not sent to the delegate.
884         sendRestrictedRequestsAndVerifyFailed(ifaces.delegateConn);
885         // Verify malformed messages are not sent to the delegate.
886         sendInvalidRequestsAndVerifyFailed(ifaces.delegateConn);
887 
888         destroySipDelegateAndVerify(ifaces);
889         assertEquals("There should be no more delegates", 0,
890                 ifaces.transport.getDelegates().size());
891         verifyUpdateRegistrationCalled(ifaces.reg);
892     }
893 
894     @Test
testDelegateRegistrationChanges()895     public void testDelegateRegistrationChanges() throws Exception {
896         if (!ImsUtils.shouldTestImsService()) {
897             return;
898         }
899         try {
900             TelephonyUtils.enableCompatCommand(InstrumentationRegistry.getInstrumentation(),
901                     TelephonyUtils.CTS_APP_PACKAGE,
902                     TelephonyUtils.SUPPORT_REGISTERING_DELEGATE_STATE_STRING);
903             TelephonyUtils.enableCompatCommand(InstrumentationRegistry.getInstrumentation(),
904                     TelephonyUtils.CTS_APP_PACKAGE,
905                     TelephonyUtils.SUPPORT_DEREGISTERING_LOSING_PDN_STATE_STRING);
906 
907             TransportInterfaces ifaces = new TransportInterfaces(getDefaultRequest(),
908                     Collections.emptySet(), 0);
909             ifaces.connectAndVerify();
910             Set<String> registeredTags = new ArraySet<>(ifaces.request.getFeatureTags());
911 
912             // move reg state to registering, deregistering and then deregistered
913             ifaces.delegateConn.setOperationCountDownLatch(1);
914             DelegateRegistrationState s = getRegisteringRegistrationState(registeredTags);
915             ifaces.delegate.notifyImsRegistrationUpdate(s);
916             ifaces.delegateConn.waitForCountDown(ImsUtils.TEST_TIMEOUT_MS);
917             ifaces.delegateConn.verifyRegistrationStateEquals(s);
918 
919             ifaces.delegateConn.setOperationCountDownLatch(1);
920             s = getDeregisteringState(registeredTags,
921                     DelegateRegistrationState.DEREGISTERING_REASON_LOSING_PDN);
922             ifaces.delegate.notifyImsRegistrationUpdate(s);
923             ifaces.delegateConn.waitForCountDown(ImsUtils.TEST_TIMEOUT_MS);
924             ifaces.delegateConn.verifyRegistrationStateEquals(s);
925 
926             ifaces.delegateConn.setOperationCountDownLatch(1);
927             s = getRegisteredRegistrationState(registeredTags);
928             ifaces.delegate.notifyImsRegistrationUpdate(s);
929             ifaces.delegateConn.waitForCountDown(ImsUtils.TEST_TIMEOUT_MS);
930             ifaces.delegateConn.verifyRegistrationStateEquals(s);
931 
932             destroySipDelegateAndVerify(ifaces);
933             assertEquals("There should be no more delegates", 0,
934                     ifaces.transport.getDelegates().size());
935         } finally {
936             TelephonyUtils.resetCompatCommand(InstrumentationRegistry.getInstrumentation(),
937                     TelephonyUtils.CTS_APP_PACKAGE,
938                     TelephonyUtils.SUPPORT_REGISTERING_DELEGATE_STATE_STRING);
939             TelephonyUtils.resetCompatCommand(InstrumentationRegistry.getInstrumentation(),
940                     TelephonyUtils.CTS_APP_PACKAGE,
941                     TelephonyUtils.SUPPORT_DEREGISTERING_LOSING_PDN_STATE_STRING);
942         }
943     }
944 
945     @Ignore("the compatibility framework does not currently support changing compatibility flags"
946             + "on user builds for device side CTS tests. Ignore this test until support is added")
947     @Test
testDelegateRegistrationChangesCompatDisabled()948     public void testDelegateRegistrationChangesCompatDisabled() throws Exception {
949         if (!ImsUtils.shouldTestImsService()) {
950             return;
951         }
952         try {
953             TelephonyUtils.disableCompatCommand(InstrumentationRegistry.getInstrumentation(),
954                     TelephonyUtils.CTS_APP_PACKAGE,
955                     TelephonyUtils.SUPPORT_REGISTERING_DELEGATE_STATE_STRING);
956             TelephonyUtils.disableCompatCommand(InstrumentationRegistry.getInstrumentation(),
957                     TelephonyUtils.CTS_APP_PACKAGE,
958                     TelephonyUtils.SUPPORT_DEREGISTERING_LOSING_PDN_STATE_STRING);
959 
960             TransportInterfaces ifaces = new TransportInterfaces(getDefaultRequest(),
961                     Collections.emptySet(), 0);
962             ifaces.connectAndVerify();
963             Set<String> registeredTags = new ArraySet<>(ifaces.request.getFeatureTags());
964 
965             // The registering state should move to the deregistered state
966             // with the reason DEREGISTERED_REASON_NOT_REGISTERED when the registering state is not
967             // supported.
968             ifaces.delegateConn.setOperationCountDownLatch(1);
969             DelegateRegistrationState s = getRegisteringRegistrationState(registeredTags);
970             ifaces.delegate.notifyImsRegistrationUpdate(s);
971             ifaces.delegateConn.waitForCountDown(ImsUtils.TEST_TIMEOUT_MS);
972             s = getDeregisteredState(registeredTags,
973                     DelegateRegistrationState.DEREGISTERED_REASON_NOT_REGISTERED);
974             ifaces.delegateConn.verifyRegistrationStateEquals(s);
975 
976             // The reason DEREGISTERING_REASON_LOSING_PDN of the deregistering state will be changed
977             // to the reason DEREGISTERING_REASON_PDN_CHANGE when DEREGISTERING_LOSING_PDN_STATE is
978             // not supported.
979             ifaces.delegateConn.setOperationCountDownLatch(1);
980             s = getDeregisteringState(registeredTags,
981                     DelegateRegistrationState.DEREGISTERING_REASON_LOSING_PDN);
982             ifaces.delegate.notifyImsRegistrationUpdate(s);
983             ifaces.delegateConn.waitForCountDown(ImsUtils.TEST_TIMEOUT_MS);
984             s = getDeregisteringState(registeredTags,
985                     DelegateRegistrationState.DEREGISTERING_REASON_PDN_CHANGE);
986             ifaces.delegateConn.verifyRegistrationStateEquals(s);
987 
988             ifaces.delegateConn.setOperationCountDownLatch(1);
989             s = getRegisteredRegistrationState(registeredTags);
990             ifaces.delegate.notifyImsRegistrationUpdate(s);
991             ifaces.delegateConn.waitForCountDown(ImsUtils.TEST_TIMEOUT_MS);
992             ifaces.delegateConn.verifyRegistrationStateEquals(s);
993 
994             destroySipDelegateAndVerify(ifaces);
995             assertEquals("There should be no more delegates", 0,
996                     ifaces.transport.getDelegates().size());
997         } finally {
998             TelephonyUtils.resetCompatCommand(InstrumentationRegistry.getInstrumentation(),
999                     TelephonyUtils.CTS_APP_PACKAGE,
1000                     TelephonyUtils.SUPPORT_REGISTERING_DELEGATE_STATE_STRING);
1001             TelephonyUtils.resetCompatCommand(InstrumentationRegistry.getInstrumentation(),
1002                     TelephonyUtils.CTS_APP_PACKAGE,
1003                     TelephonyUtils.SUPPORT_DEREGISTERING_LOSING_PDN_STATE_STRING);
1004         }
1005     }
1006 
1007     @Test
testCreateMultipleDelegates()1008     public void testCreateMultipleDelegates() throws Exception {
1009         if (!ImsUtils.shouldTestImsService()) {
1010             return;
1011         }
1012         assertTrue(sServiceConnector.setDefaultSmsApp());
1013         connectTestImsServiceWithSipTransportAndConfig();
1014         TestSipTransport transportImpl = sServiceConnector.getCarrierService().getSipTransport();
1015         TestImsRegistration regImpl = sServiceConnector.getCarrierService().getImsRegistration();
1016         SipDelegateManager manager = getSipDelegateManager();
1017 
1018         DelegateRequest request1 = getChatOnlyRequest();
1019         TestSipDelegateConnection delegateConn1 = new TestSipDelegateConnection(request1);
1020         Set<String> registeredTags1 = new ArraySet<>(request1.getFeatureTags());
1021         TestSipDelegate delegate1 = createSipDelegateConnectionAndVerify(manager, delegateConn1,
1022                 transportImpl, Collections.emptySet(), 0);
1023         assertNotNull(delegate1);
1024 
1025         InetSocketAddress localAddr = new InetSocketAddress(
1026                 InetAddresses.parseNumericAddress("1.1.1.1"), 80);
1027         InetSocketAddress serverAddr = new InetSocketAddress(
1028                 InetAddresses.parseNumericAddress("2.2.2.2"), 81);
1029         SipDelegateConfiguration c = new SipDelegateConfiguration.Builder(1,
1030                 SipDelegateConfiguration.SIP_TRANSPORT_TCP, localAddr, serverAddr).build();
1031         verifyRegisteredAndSendSipConfig(delegateConn1, delegate1, registeredTags1,
1032                 Collections.emptySet(), c);
1033 
1034         // This will only be granted File transfer FT
1035         DelegateRequest request2 = getDefaultRequest();
1036         TestSipDelegateConnection delegateConn2 = new TestSipDelegateConnection(request2);
1037         Set<String> registeredTags2 = new ArraySet<>();
1038         registeredTags2.add(FILE_TRANSFER_HTTP_TAG);
1039         TestSipDelegate delegate2 = createSipDelegateConnectionAndVerify(manager, delegateConn2,
1040                 transportImpl, Collections.emptySet(), 1);
1041         assertNotNull(delegate2);
1042         verifyUpdateRegistrationCalled(regImpl);
1043         Set<FeatureTagState> deniedSet = generateDeniedSetFromRequest(request1.getFeatureTags(),
1044                 request2.getFeatureTags(),
1045                 SipDelegateManager.DENIED_REASON_IN_USE_BY_ANOTHER_DELEGATE);
1046         verifyRegisteredAndSendSipConfig(delegateConn2, delegate2, registeredTags2,
1047                 deniedSet, c);
1048 
1049         // Destroying delegate 1 will transfer all feature tags over to delegate 2
1050         destroySipDelegate(manager, transportImpl, delegateConn1, delegate1);
1051         // This internally triggers the destruction of the internal delegate2 and then recreation
1052         // of another delegate with the new feature set that it supports.
1053         verifySipDelegateDestroyed(transportImpl, delegate2);
1054         delegate2 = getSipDelegate(transportImpl, Collections.emptySet(), 0);
1055         verifyUpdateRegistrationCalled(regImpl);
1056         verifyRegisteredAndSendSipConfig(delegateConn2, delegate2, request2.getFeatureTags(),
1057                 Collections.emptySet(), c);
1058 
1059         destroySipDelegateAndVerifyConnDestroyed(manager, transportImpl, delegateConn2, delegate2);
1060         assertEquals("There should be no more delegates", 0,
1061                 transportImpl.getDelegates().size());
1062     }
1063 
1064     @Test
testCreateDelegateMessagingAppChangesToApp()1065     public void testCreateDelegateMessagingAppChangesToApp() throws Exception {
1066         if (!ImsUtils.shouldTestImsService()) {
1067             return;
1068         }
1069         // start with no features granted
1070         connectTestImsServiceWithSipTransportAndConfig();
1071 
1072         TestSipTransport transportImpl = sServiceConnector.getCarrierService().getSipTransport();
1073         TestImsRegistration regImpl = sServiceConnector.getCarrierService().getImsRegistration();
1074         SipDelegateManager manager = getSipDelegateManager();
1075         DelegateRequest request = getDefaultRequest();
1076         TestSipDelegateConnection delegateConn = new TestSipDelegateConnection(request);
1077 
1078         // wait for onCreated and registration state change to be called.
1079         createSipDelegateConnectionNoDelegateExpected(manager, delegateConn, transportImpl);
1080 
1081         // Make this app the DMA
1082         regImpl.resetLatch(TestImsRegistration.LATCH_TRIGGER_DEREGISTRATION, 1);
1083         assertTrue(sServiceConnector.setDefaultSmsApp());
1084         assertTrue(regImpl.waitForLatchCountDown(TestImsRegistration.LATCH_TRIGGER_DEREGISTRATION,
1085                 ImsUtils.TEST_TIMEOUT_MS));
1086         TestSipDelegate delegate = getSipDelegate(transportImpl, Collections.emptySet(), 0);
1087         verifyUpdateRegistrationCalled(regImpl);
1088         InetSocketAddress localAddr = new InetSocketAddress(
1089                 InetAddresses.parseNumericAddress("1.1.1.1"), 80);
1090         InetSocketAddress serverAddr = new InetSocketAddress(
1091                 InetAddresses.parseNumericAddress("2.2.2.2"), 81);
1092         SipDelegateConfiguration c = new SipDelegateConfiguration.Builder(1,
1093                 SipDelegateConfiguration.SIP_TRANSPORT_TCP, localAddr, serverAddr).build();
1094         verifyRegisteredAndSendSipConfig(delegateConn, delegate, request.getFeatureTags(),
1095                 Collections.emptySet(), c);
1096         destroySipDelegateAndVerifyConnDestroyed(manager, transportImpl, delegateConn, delegate);
1097         assertEquals("There should be no more delegates", 0,
1098                 transportImpl.getDelegates().size());
1099     }
1100 
1101     @Test
testCreateDelegateMessagingAppChangesAwayFromApp()1102     public void testCreateDelegateMessagingAppChangesAwayFromApp() throws Exception {
1103         if (!ImsUtils.shouldTestImsService()) {
1104             return;
1105         }
1106         // Make this app the DMA
1107         TransportInterfaces ifaces = new TransportInterfaces(getDefaultRequest(),
1108                 Collections.emptySet(), 0);
1109         ifaces.connectAndVerify();
1110 
1111         // Move DMA to another app, we should receive a registration update.
1112         ifaces.reg.resetLatch(TestImsRegistration.LATCH_TRIGGER_DEREGISTRATION, 1);
1113         sServiceConnector.restoreDefaultSmsApp();
1114         assertTrue(ifaces.reg.waitForLatchCountDown(
1115                 TestImsRegistration.LATCH_TRIGGER_DEREGISTRATION, ImsUtils.TEST_TIMEOUT_MS));
1116         // we should get another reg update with all tags denied.
1117         ifaces.delegateConn.setOperationCountDownLatch(1);
1118         verifySipDelegateDestroyed(ifaces.transport, ifaces.delegate);
1119         ifaces.delegateConn.waitForCountDown(ImsUtils.TEST_TIMEOUT_MS);
1120         ifaces.delegateConn.verifyRegistrationStateEmpty();
1121         // All requested features should have been denied due to the app not being the default sms
1122         // app.
1123         ifaces.delegateConn.verifyAllDenied(SipDelegateManager.DENIED_REASON_NOT_ALLOWED);
1124         // There should not be any delegates left, as the only delegate should have been cleaned up.
1125         assertEquals("SipDelegate should not have any delegates", 0,
1126                 ifaces.transport.getDelegates().size());
1127         verifyUpdateRegistrationCalled(ifaces.reg);
1128         destroySipDelegateConnectionNoDelegate(ifaces.manager, ifaces.delegateConn);
1129     }
1130 
1131     @Test
testParcelUnparcelDelegateRequest()1132     public void testParcelUnparcelDelegateRequest() {
1133         ArraySet<String> testTags = new ArraySet<>();
1134         testTags.add(MMTEL_TAG);
1135         testTags.add(ONE_TO_ONE_CHAT_TAG);
1136         testTags.add(GROUP_CHAT_TAG);
1137         testTags.add(FILE_TRANSFER_HTTP_TAG);
1138         DelegateRequest r = new DelegateRequest(testTags);
1139         Parcel p = Parcel.obtain();
1140         r.writeToParcel(p, 0);
1141         p.setDataPosition(0);
1142         DelegateRequest unparcelled = DelegateRequest.CREATOR.createFromParcel(p);
1143         assertEquals(r, unparcelled);
1144         assertEquals(r.getFeatureTags(), unparcelled.getFeatureTags());
1145     }
1146 
1147     @Test
testParcelUnparcelFeatureTagState()1148     public void testParcelUnparcelFeatureTagState() {
1149         FeatureTagState f = new FeatureTagState(MMTEL_TAG,
1150                 DelegateRegistrationState.DEREGISTERED_REASON_NOT_REGISTERED);
1151         Parcel p = Parcel.obtain();
1152         f.writeToParcel(p, 0);
1153         p.setDataPosition(0);
1154         FeatureTagState unparcelled = FeatureTagState.CREATOR.createFromParcel(p);
1155         assertEquals(f, unparcelled);
1156         assertEquals(f.getFeatureTag(), unparcelled.getFeatureTag());
1157         assertEquals(f.getState(), unparcelled.getState());
1158     }
1159 
1160     @Test
testParcelUnparcelRegistrationState()1161     public void testParcelUnparcelRegistrationState() {
1162         ArraySet<String> regTags = new ArraySet<>();
1163         regTags.add(MMTEL_TAG);
1164         ArraySet<String> registeringTags = new ArraySet<>();
1165         registeringTags.add(CHATBOT_COMMUNICATION_USING_SESSION_TAG);
1166         DelegateRegistrationState s = new DelegateRegistrationState.Builder()
1167                 .addRegisteredFeatureTags(regTags)
1168                 .addRegisteredFeatureTag(ONE_TO_ONE_CHAT_TAG)
1169                 .addDeregisteringFeatureTag(GROUP_CHAT_TAG,
1170                         DelegateRegistrationState.DEREGISTERING_REASON_PDN_CHANGE)
1171                 .addDeregisteredFeatureTag(FILE_TRANSFER_HTTP_TAG,
1172                         DelegateRegistrationState.DEREGISTERED_REASON_NOT_REGISTERED)
1173                 .addRegisteringFeatureTags(registeringTags)
1174                 .build();
1175         Parcel p = Parcel.obtain();
1176         s.writeToParcel(p, 0);
1177         p.setDataPosition(0);
1178         DelegateRegistrationState unparcel = DelegateRegistrationState.CREATOR.createFromParcel(p);
1179         assertEquals(s, unparcel);
1180         assertEquals(s.getRegisteredFeatureTags(), unparcel.getRegisteredFeatureTags());
1181         assertEquals(s.getDeregisteringFeatureTags(), unparcel.getDeregisteringFeatureTags());
1182         assertEquals(s.getDeregisteredFeatureTags(), unparcel.getDeregisteredFeatureTags());
1183         assertEquals(s.getRegisteringFeatureTags(), unparcel.getRegisteringFeatureTags());
1184     }
1185 
1186     @Test
testParcelUnparcelConfiguration()1187     public void testParcelUnparcelConfiguration() {
1188         // Set everything to a non-default value
1189         SipDelegateConfiguration c = generateNewTestConfig();
1190         assertEquals(1, c.getVersion());
1191         assertEquals(SipDelegateConfiguration.SIP_TRANSPORT_TCP, c.getTransportType());
1192         assertEquals("1.1.1.1", c.getLocalAddress().getAddress().getHostAddress());
1193         assertEquals(80, c.getLocalAddress().getPort());
1194         assertEquals("2.2.2.2", c.getSipServerAddress().getAddress().getHostAddress());
1195         assertEquals(81, c.getSipServerAddress().getPort());
1196         assertTrue(c.isSipCompactFormEnabled());
1197         assertTrue(c.isSipKeepaliveEnabled());
1198         assertEquals(508, c.getMaxUdpPayloadSizeBytes());
1199         assertEquals("test1", c.getPublicUserIdentifier());
1200         assertEquals("test2", c.getPrivateUserIdentifier());
1201         assertEquals("test.domain", c.getHomeDomain());
1202         assertEquals("testImei", c.getImei());
1203         assertEquals("sipauth", c.getSipAuthenticationHeader());
1204         assertEquals("sipnonce", c.getSipAuthenticationNonce());
1205         assertEquals("srvroute", c.getSipServiceRouteHeader());
1206         assertEquals("path", c.getSipPathHeader());
1207         assertEquals("ua", c.getSipUserAgentHeader());
1208         assertEquals("user", c.getSipContactUserParameter());
1209         assertEquals("pani", c.getSipPaniHeader());
1210         assertEquals("plani", c.getSipPlaniHeader());
1211         assertEquals("cni", c.getSipCniHeader());
1212         assertEquals("uri", c.getSipAssociatedUriHeader());
1213         Uri gruuUri = Uri.parse("sip:blah@gruu.net");
1214         assertEquals(gruuUri, c.getPublicGruuUri());
1215 
1216         Parcel p = Parcel.obtain();
1217         c.writeToParcel(p, 0);
1218         p.setDataPosition(0);
1219         SipDelegateConfiguration unparcelConfig =
1220                 SipDelegateConfiguration.CREATOR.createFromParcel(p);
1221         assertEquals(c, unparcelConfig);
1222     }
1223 
1224     // this test is required to avoid pre-submit check (API coverage check FAIL)
1225     @Test
testSipDialogStateDescribeContents()1226     public void testSipDialogStateDescribeContents() {
1227         SipDialogState state = new SipDialogState.Builder(SipDialogState.STATE_CONFIRMED).build();
1228         assertNotNull(state);
1229         int describe = state.describeContents();
1230         assertTrue(describe == 0);
1231     }
1232 
1233     @Test
testParcelUnparcelSipDialogState()1234     public void testParcelUnparcelSipDialogState() {
1235         SipDialogState state = new SipDialogState.Builder(SipDialogState.STATE_CONFIRMED).build();
1236         assertEquals(SipDialogState.STATE_CONFIRMED, state.getState());
1237         Parcel p = Parcel.obtain();
1238         state.writeToParcel(p, 0);
1239         p.setDataPosition(0);
1240         SipDialogState unparcelled = SipDialogState.CREATOR.createFromParcel(p);
1241         assertEquals(state, unparcelled);
1242         assertEquals(state.getState() , unparcelled.getState());
1243     }
1244 
1245     @Test
testCopyConfiguration()1246     public void testCopyConfiguration() {
1247         // Set everything to a non-default value
1248         SipDelegateConfiguration c = generateNewTestConfig();
1249         // The config should be exactly the same, but with an incremented version.
1250         SipDelegateConfiguration configInc = new SipDelegateConfiguration.Builder(c).build();
1251         assertEquals(2, configInc.getVersion());
1252         assertEquals(SipDelegateConfiguration.SIP_TRANSPORT_TCP, configInc.getTransportType());
1253         assertEquals("1.1.1.1", configInc.getLocalAddress().getAddress().getHostAddress());
1254         assertEquals(80, configInc.getLocalAddress().getPort());
1255         assertEquals("2.2.2.2",
1256                 configInc.getSipServerAddress().getAddress().getHostAddress());
1257         assertEquals(81, configInc.getSipServerAddress().getPort());
1258         assertTrue(configInc.isSipCompactFormEnabled());
1259         assertTrue(configInc.isSipKeepaliveEnabled());
1260         assertEquals(508, configInc.getMaxUdpPayloadSizeBytes());
1261         assertEquals("test1", configInc.getPublicUserIdentifier());
1262         assertEquals("test2", configInc.getPrivateUserIdentifier());
1263         assertEquals("test.domain", configInc.getHomeDomain());
1264         assertEquals("testImei", configInc.getImei());
1265         assertEquals("sipauth", configInc.getSipAuthenticationHeader());
1266         assertEquals("sipnonce", configInc.getSipAuthenticationNonce());
1267         assertEquals("srvroute", configInc.getSipServiceRouteHeader());
1268         assertEquals("path", configInc.getSipPathHeader());
1269         assertEquals("ua", configInc.getSipUserAgentHeader());
1270         assertEquals("user", configInc.getSipContactUserParameter());
1271         assertEquals("pani", configInc.getSipPaniHeader());
1272         assertEquals("plani", configInc.getSipPlaniHeader());
1273         assertEquals("cni", configInc.getSipCniHeader());
1274         assertEquals("uri", configInc.getSipAssociatedUriHeader());
1275         Uri gruuUri = Uri.parse("sip:blah@gruu.net");
1276         assertEquals(gruuUri, configInc.getPublicGruuUri());
1277         SipDelegateConfiguration.IpSecConfiguration ipSecConfig = configInc.getIpSecConfiguration();
1278         assertEquals(123, ipSecConfig.getLocalTxPort());
1279         assertEquals(124, ipSecConfig.getLocalRxPort());
1280         assertEquals(125, ipSecConfig.getLastLocalTxPort());
1281         assertEquals(126, ipSecConfig.getRemoteTxPort());
1282         assertEquals(127, ipSecConfig.getRemoteRxPort());
1283         assertEquals(128, ipSecConfig.getLastRemoteTxPort());
1284         assertEquals("secverify", ipSecConfig.getSipSecurityVerifyHeader());
1285         InetSocketAddress natAddr = configInc.getNatSocketAddress();
1286         assertEquals("3.3.3.3", natAddr.getAddress().getHostAddress());
1287         assertEquals(129, natAddr.getPort());
1288     }
1289 
1290     @Test
testParcelUnparcelSipMessage()1291     public void testParcelUnparcelSipMessage() {
1292         String startLine =
1293                 "INVITE sip:12345678@[2607:fc20:3806:2a44:0:6:42ae:5b01]:49155 SIP/2.0\r\n";
1294         String header = "Via: SIP/2.0/TCP [FD00:976A:C202:1808::1]:65529;"
1295                 + "branch=z9hG4bKg3Zqkv7iivdfzmfqu68sro3cuht97q846\r\n"
1296                 + "To: <sip:12345678;phone-context=xxx.com@xxx.com;user=phone>\r\n"
1297                 + "From: <sip:12345679@xxx.com>;tag=ABC\r\n"
1298                 + "Call-ID: 000050B04074-79e-fc9b8700-29df64-5f3e5811-26fa8\r\n";
1299         String branch = "z9hG4bKg3Zqkv7iivdfzmfqu68sro3cuht97q846";
1300         String callId = "000050B04074-79e-fc9b8700-29df64-5f3e5811-26fa8";
1301         byte[] bytes = new byte[1];
1302         bytes[0] = 'a';
1303         SipMessage m = new SipMessage(startLine, header, bytes);
1304         Parcel p = Parcel.obtain();
1305         m.writeToParcel(p, 0);
1306         p.setDataPosition(0);
1307         SipMessage unparcel = SipMessage.CREATOR.createFromParcel(p);
1308         assertEquals(m, unparcel);
1309         assertEquals(m.getStartLine(), unparcel.getStartLine());
1310         assertEquals(m.getHeaderSection(), unparcel.getHeaderSection());
1311         assertTrue(Arrays.equals(m.getContent(), unparcel.getContent()));
1312         assertEquals(branch, m.getViaBranchParameter());
1313         assertEquals(callId, m.getCallIdParameter());
1314         assertEquals(m.getViaBranchParameter(), unparcel.getViaBranchParameter());
1315         assertEquals(m.getCallIdParameter(), unparcel.getCallIdParameter());
1316     }
1317 
1318     @Test
testEncodeSipMessage()1319     public void testEncodeSipMessage() {
1320         String startLine =
1321                 "INVITE sip:12345678@[2607:fc20:3806:2a44:0:6:42ae:5b01]:49155 SIP/2.0\r\n";
1322         String header = "Via: SIP/2.0/TCP [FD00:976A:C202:1808::1]:65529;"
1323                 + "branch=z9hG4bKg3Zqkv7iivdfzmfqu68sro3cuht97q846\r\n"
1324                 + "To: <sip:12345678;phone-context=xxx.com@xxx.com;"
1325                 + "user=phone>\r\n"
1326                 + "From: <sip:12345679@xxx.com>;"
1327                 + "tag=h7g4Esbg_mavodi-e-10b-123-6-ffffffff-_000050B04074-79e-fc9b8700-29df65"
1328                 + "-5f3e5811-27196\r\n"
1329                 + "Call-ID: 000050B04074-79e-fc9b8700-29df64-5f3e5811-26fa8\r\n";
1330         byte[] content1 = ("v=0\r\n"
1331                 + "o=- 10 1000 IN IP6 FD00:976A:C202:1808::1\r\n"
1332                 + "s=VOIP\r\n"
1333                 + "c=IN IP6 fd00:976a:c002:1940::4\r\n").getBytes(UTF_8);
1334         byte[] content2 = new byte[0];
1335 
1336         SipMessage m = new SipMessage(startLine, header, content1);
1337         byte[] encodedMsg = m.toEncodedMessage();
1338         String decodedStr = new String(encodedMsg, UTF_8);
1339         SipMessage decodedMsg = generateSipMessage(decodedStr);
1340         assertEquals(decodedMsg.getStartLine(), m.getStartLine());
1341         assertEquals(decodedMsg.getHeaderSection(), m.getHeaderSection());
1342         assertTrue(Arrays.equals(decodedMsg.getContent(), m.getContent()));
1343 
1344         // Test empty content
1345         m = new SipMessage(startLine, header, content2);
1346         encodedMsg = m.toEncodedMessage();
1347         decodedStr = new String(encodedMsg, UTF_8);
1348         decodedMsg = generateSipMessage(decodedStr);
1349         assertEquals(decodedMsg.getStartLine(), m.getStartLine());
1350         assertEquals(decodedMsg.getHeaderSection(), m.getHeaderSection());
1351         assertTrue(Arrays.equals(decodedMsg.getContent(), m.getContent()));
1352     }
1353 
1354     @Test
testFeatureTagDeniedByCarrierConfig()1355     public void testFeatureTagDeniedByCarrierConfig() throws Exception {
1356         if (!ImsUtils.shouldTestImsService()) {
1357             return;
1358         }
1359 
1360         setFeatureTagsCarrierAllowed(new String[]{FILE_TRANSFER_HTTP_TAG});
1361         assertTrue(sServiceConnector.setDefaultSmsApp());
1362         connectTestImsServiceWithSipTransportAndConfig();
1363         TestSipTransport transportImpl = sServiceConnector.getCarrierService().getSipTransport();
1364         SipDelegateManager manager = getSipDelegateManager();
1365         DelegateRequest request = getDefaultRequest();
1366         TestSipDelegateConnection delegateConn = new TestSipDelegateConnection(request);
1367         Set<String> deniedTags = new ArraySet<>(request.getFeatureTags());
1368         deniedTags.remove(FILE_TRANSFER_HTTP_TAG);
1369 
1370         TestSipDelegate delegate = createSipDelegateConnectionAndVerify(manager, delegateConn,
1371                 transportImpl, getDeniedTagsForReason(deniedTags,
1372                         SipDelegateManager.DENIED_REASON_NOT_ALLOWED), 0);
1373         assertNotNull(delegate);
1374 
1375         Set<String> registeredTags = new ArraySet<>(
1376                 Arrays.asList(new String[]{FILE_TRANSFER_HTTP_TAG}));
1377         delegateConn.setOperationCountDownLatch(1);
1378         DelegateRegistrationState s = getRegisteredRegistrationState(registeredTags);
1379         delegate.notifyImsRegistrationUpdate(s);
1380         delegateConn.waitForCountDown(ImsUtils.TEST_TIMEOUT_MS);
1381         delegateConn.verifyRegistrationStateEquals(s);
1382         destroySipDelegateAndVerifyConnDestroyed(manager, transportImpl, delegateConn, delegate);
1383         assertEquals("There should be no more delegates", 0,
1384                 transportImpl.getDelegates().size());
1385         setFeatureTagsCarrierAllowed(getDefaultRequest().getFeatureTags().toArray(new String[0]));
1386     }
1387 
1388     @Test
testCloseActiveDialog()1389     public void testCloseActiveDialog() throws Exception {
1390         if (!ImsUtils.shouldTestImsService()) {
1391             return;
1392         }
1393         TransportInterfaces ifaces = new TransportInterfaces(getDefaultRequest(),
1394                 Collections.emptySet(), 0);
1395         ifaces.connect();
1396         // Send invite
1397         SipDialogAttributes attr = new SipDialogAttributes();
1398         sendChatInvite(attr, ifaces);
1399         // send close from app
1400         ifaces.delegateConn.disconnect(ifaces.manager,
1401                 SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
1402         // Registration state will change to deregistering during this time.
1403         ifaces.delegateConn.setOperationCountDownLatch(1);
1404         ifaces.delegateConn.waitForCountDown(ImsUtils.TEST_TIMEOUT_MS);
1405         assertTrue(ifaces.delegateConn.verifyDeregisteringStateContains(ONE_TO_ONE_CHAT_TAG,
1406                 DelegateRegistrationState.DEREGISTERING_REASON_DESTROY_PENDING));
1407         // receive 200 OK
1408         receive200OkResponse(attr, ifaces);
1409         // Send ACK
1410         sendAck(attr, ifaces);
1411         // Send BYE
1412         sendByeRequest(attr, ifaces);
1413         // destroy should not be called until cleanupSession is sent.
1414         assertFalse(ifaces.transport.isLatchCountDownFinished(
1415                 TestSipTransport.LATCH_DESTROY_DELEGATE));
1416 
1417         ifaces.delegateConn.setOperationCountDownLatch(1);
1418         // Send the cleanup, which will trigger destroy to complete.
1419         ifaces.delegateConn.sendCleanupSession(attr.callId);
1420         ifaces.delegate.verifyCleanupSession(attr.callId);
1421         ifaces.transport.waitForLatchCountdownAndReset(TestSipTransport.LATCH_DESTROY_DELEGATE);
1422         ifaces.delegate.notifyOnDestroyed(
1423                 SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
1424         ifaces.delegateConn.waitForCountDown(ImsUtils.TEST_TIMEOUT_MS);
1425         ifaces.delegateConn.verifyDestroyed(
1426                 SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
1427 
1428         assertEquals("There should be no more delegates", 0,
1429                 ifaces.transport.getDelegates().size());
1430         verifyUpdateRegistrationCalled(ifaces.reg);
1431     }
1432 
1433     @Test
testReceivedActiveDialogClose()1434     public void testReceivedActiveDialogClose() throws Exception {
1435         if (!ImsUtils.shouldTestImsService()) {
1436             return;
1437         }
1438         TransportInterfaces ifaces = new TransportInterfaces(getDefaultRequest(),
1439                 Collections.emptySet(), 0);
1440         ifaces.connect();
1441         // receive invite
1442         SipDialogAttributes attr = new SipDialogAttributes();
1443         receiveChatInvite(attr, ifaces);
1444         // send close from app
1445         ifaces.delegateConn.disconnect(ifaces.manager,
1446                 SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
1447         // Registration state will change to deregistering during this time.
1448         ifaces.delegateConn.setOperationCountDownLatch(1);
1449         ifaces.delegateConn.waitForCountDown(ImsUtils.TEST_TIMEOUT_MS);
1450         assertTrue(ifaces.delegateConn.verifyDeregisteringStateContains(ONE_TO_ONE_CHAT_TAG,
1451                 DelegateRegistrationState.DEREGISTERING_REASON_DESTROY_PENDING));
1452         // Send 200 OK
1453         send200OkResponse(attr, ifaces);
1454         // receive ACK
1455         receiveAck(attr, ifaces);
1456         // Send BYE
1457         receiveByeRequest(attr, ifaces);
1458         ifaces.delegateConn.setOperationCountDownLatch(1);
1459         // Send the cleanup, which will trigger destroy to complete.
1460         ifaces.delegateConn.sendCleanupSession(attr.callId);
1461         ifaces.delegate.verifyCleanupSession(attr.callId);
1462         ifaces.transport.waitForLatchCountdownAndReset(TestSipTransport.LATCH_DESTROY_DELEGATE);
1463         ifaces.delegate.notifyOnDestroyed(
1464                 SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
1465         ifaces.delegateConn.waitForCountDown(ImsUtils.TEST_TIMEOUT_MS);
1466         ifaces.delegateConn.verifyDestroyed(
1467                 SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
1468 
1469         assertEquals("There should be no more delegates", 0,
1470                 ifaces.transport.getDelegates().size());
1471         verifyUpdateRegistrationCalled(ifaces.reg);
1472     }
1473 
1474     @Test
testActiveDialogPendingNewInvite()1475     public void testActiveDialogPendingNewInvite() throws Exception {
1476         if (!ImsUtils.shouldTestImsService()) {
1477             return;
1478         }
1479         TransportInterfaces ifaces = new TransportInterfaces(getDefaultRequest(),
1480                 Collections.emptySet(), 0);
1481         ifaces.connect();
1482         // Send invite
1483         SipDialogAttributes attr = new SipDialogAttributes();
1484         sendChatInvite(attr, ifaces);
1485         // send close from app
1486         ifaces.delegateConn.disconnect(ifaces.manager,
1487                 SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
1488         // Registration state will change to deregistering during this time.
1489         ifaces.delegateConn.setOperationCountDownLatch(1);
1490         ifaces.delegateConn.waitForCountDown(ImsUtils.TEST_TIMEOUT_MS);
1491         assertTrue(ifaces.delegateConn.verifyDeregisteringStateContains(ONE_TO_ONE_CHAT_TAG,
1492                 DelegateRegistrationState.DEREGISTERING_REASON_DESTROY_PENDING));
1493         // receive 200 OK
1494         receive200OkResponse(attr, ifaces);
1495         // Send ACK
1496         sendAck(attr, ifaces);
1497         // Send invite
1498         SipDialogAttributes attr2 = new SipDialogAttributes();
1499         attr2.addAcceptContactTag(ONE_TO_ONE_CHAT_TAG);
1500         // Should be denied because the transport is now restricted
1501         sendDeniedChatInvite(attr2, ifaces,
1502                 SipDelegateManager.MESSAGE_FAILURE_REASON_DELEGATE_CLOSED);
1503         // Send BYE on original invite
1504         sendByeRequest(attr, ifaces);
1505         // destroy should not be called until cleanupSession is sent.
1506         assertFalse(ifaces.transport.isLatchCountDownFinished(
1507                 TestSipTransport.LATCH_DESTROY_DELEGATE));
1508         ifaces.delegateConn.setOperationCountDownLatch(1);
1509         // Send the cleanup, which will trigger destroy to complete.
1510         ifaces.delegateConn.sendCleanupSession(attr.callId);
1511         ifaces.delegate.verifyCleanupSession(attr.callId);
1512         ifaces.transport.waitForLatchCountdownAndReset(TestSipTransport.LATCH_DESTROY_DELEGATE);
1513         ifaces.delegate.notifyOnDestroyed(
1514                 SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
1515         ifaces.delegateConn.waitForCountDown(ImsUtils.TEST_TIMEOUT_MS);
1516         ifaces.delegateConn.verifyDestroyed(
1517                 SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
1518 
1519         assertEquals("There should be no more delegates", 0,
1520                 ifaces.transport.getDelegates().size());
1521         verifyUpdateRegistrationCalled(ifaces.reg);
1522     }
1523 
1524     @Test
testCloseSessionByePendingCleanup()1525     public void testCloseSessionByePendingCleanup() throws Exception {
1526         if (!ImsUtils.shouldTestImsService()) {
1527             return;
1528         }
1529         TransportInterfaces ifaces = new TransportInterfaces(getDefaultRequest(),
1530                 Collections.emptySet(), 0);
1531         ifaces.connect();
1532         // Send invite
1533         SipDialogAttributes attr = new SipDialogAttributes();
1534         sendChatInvite(attr, ifaces);
1535         // send close from app
1536         ifaces.delegateConn.disconnect(ifaces.manager,
1537                 SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
1538         // receive 200 OK
1539         receive200OkResponse(attr, ifaces);
1540         // Send ACK
1541         sendAck(attr, ifaces);
1542         // Send BYE
1543         sendByeRequest(attr, ifaces);
1544         assertFalse(ifaces.transport.isLatchCountDownFinished(
1545                 TestSipTransport.LATCH_DESTROY_DELEGATE));
1546         // Registration state will change to deregistering during this time.
1547         ifaces.delegateConn.setOperationCountDownLatch(1);
1548         ifaces.delegateConn.waitForCountDown(ImsUtils.TEST_TIMEOUT_MS);
1549         assertTrue(ifaces.delegateConn.verifyDeregisteringStateContains(ONE_TO_ONE_CHAT_TAG,
1550                 DelegateRegistrationState.DEREGISTERING_REASON_DESTROY_PENDING));
1551         // waiting for delegate connection onDestroy to be called.
1552         ifaces.delegateConn.setOperationCountDownLatch(1);
1553         // no cleanupSession called, so cleanup session should be called from internal and then
1554         // the delegate should be closed.
1555         ifaces.delegate.verifyCleanupSession(attr.callId);
1556         ifaces.transport.waitForLatchCountdownAndReset(TestSipTransport.LATCH_DESTROY_DELEGATE);
1557         ifaces.delegate.notifyOnDestroyed(
1558                 SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
1559         ifaces.delegateConn.waitForCountDown(ImsUtils.TEST_TIMEOUT_MS);
1560         ifaces.delegateConn.verifyDestroyed(
1561                 SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
1562         assertEquals("There should be no more delegates", 0,
1563                 ifaces.transport.getDelegates().size());
1564         verifyUpdateRegistrationCalled(ifaces.reg);
1565     }
1566 
1567     @Test
testCloseSessionPendingBye()1568     public void testCloseSessionPendingBye() throws Exception {
1569         if (!ImsUtils.shouldTestImsService()) {
1570             return;
1571         }
1572         TransportInterfaces ifaces = new TransportInterfaces(getDefaultRequest(),
1573                 Collections.emptySet(), 0);
1574         ifaces.connect();
1575         // Send invite
1576         SipDialogAttributes attr = new SipDialogAttributes();
1577         sendChatInvite(attr, ifaces);
1578         // send close from app
1579         ifaces.delegateConn.disconnect(ifaces.manager,
1580                 SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
1581         // receive 200 OK
1582         receive200OkResponse(attr, ifaces);
1583         // Send ACK
1584         sendAck(attr, ifaces);
1585         // Don't send BYE or cleanupSession
1586         assertFalse(ifaces.transport.isLatchCountDownFinished(
1587                 TestSipTransport.LATCH_DESTROY_DELEGATE));
1588         // Registration state will change to deregistering during this time.
1589         ifaces.delegateConn.setOperationCountDownLatch(1);
1590         ifaces.delegateConn.waitForCountDown(ImsUtils.TEST_TIMEOUT_MS);
1591         assertTrue(ifaces.delegateConn.verifyDeregisteringStateContains(ONE_TO_ONE_CHAT_TAG,
1592                 DelegateRegistrationState.DEREGISTERING_REASON_DESTROY_PENDING));
1593         // waiting for delegate connection onDestroy to be called.
1594         ifaces.delegateConn.setOperationCountDownLatch(1);
1595         // no cleanupSession called, so cleanup session should be called from internal and then
1596         // the delegate should be closed.
1597         ifaces.delegate.verifyCleanupSession(attr.callId);
1598         ifaces.transport.waitForLatchCountdownAndReset(TestSipTransport.LATCH_DESTROY_DELEGATE);
1599         ifaces.delegate.notifyOnDestroyed(
1600                 SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
1601         ifaces.delegateConn.waitForCountDown(ImsUtils.TEST_TIMEOUT_MS);
1602         ifaces.delegateConn.verifyDestroyed(
1603                 SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
1604         assertEquals("There should be no more delegates", 0,
1605                 ifaces.transport.getDelegates().size());
1606         verifyUpdateRegistrationCalled(ifaces.reg);
1607     }
1608 
1609     @Test
testCloseMultipleSessionsPendingBye()1610     public void testCloseMultipleSessionsPendingBye() throws Exception {
1611         if (!ImsUtils.shouldTestImsService()) {
1612             return;
1613         }
1614         TransportInterfaces ifaces = new TransportInterfaces(getDefaultRequest(),
1615                 Collections.emptySet(), 0);
1616         ifaces.connect();
1617         // Send invite 1
1618         SipDialogAttributes attr = new SipDialogAttributes();
1619         sendChatInvite(attr, ifaces);
1620         // Send invite 2
1621         SipDialogAttributes attr2 = new SipDialogAttributes();
1622         sendChatInvite(attr2, ifaces);
1623         // send close from app
1624         ifaces.delegateConn.disconnect(ifaces.manager,
1625                 SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
1626         // receive 200 OK
1627         receive200OkResponse(attr, ifaces);
1628         receive200OkResponse(attr2, ifaces);
1629         // Send ACK
1630         sendAck(attr, ifaces);
1631         sendAck(attr2, ifaces);
1632         // Don't send BYE or cleanupSession
1633         assertFalse(ifaces.transport.isLatchCountDownFinished(
1634                 TestSipTransport.LATCH_DESTROY_DELEGATE));
1635         // Registration state will change to deregistering during this time.
1636         ifaces.delegateConn.setOperationCountDownLatch(1);
1637         ifaces.delegateConn.waitForCountDown(ImsUtils.TEST_TIMEOUT_MS);
1638         assertTrue(ifaces.delegateConn.verifyDeregisteringStateContains(ONE_TO_ONE_CHAT_TAG,
1639                 DelegateRegistrationState.DEREGISTERING_REASON_DESTROY_PENDING));
1640         // waiting for delegate connection onDestroy to be called.
1641         ifaces.delegateConn.setOperationCountDownLatch(1);
1642         // no cleanupSession called, so cleanup session should be called from internal and then
1643         // the delegate should be closed.
1644         ifaces.delegate.verifyCleanupSession(attr.callId, attr2.callId);
1645         ifaces.transport.waitForLatchCountdownAndReset(TestSipTransport.LATCH_DESTROY_DELEGATE);
1646         ifaces.delegate.notifyOnDestroyed(
1647                 SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
1648         ifaces.delegateConn.waitForCountDown(ImsUtils.TEST_TIMEOUT_MS);
1649         ifaces.delegateConn.verifyDestroyed(
1650                 SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
1651         assertEquals("There should be no more delegates", 0,
1652                 ifaces.transport.getDelegates().size());
1653         verifyUpdateRegistrationCalled(ifaces.reg);
1654     }
1655 
1656     @Test
testCloseSessionBye()1657     public void testCloseSessionBye() throws Exception {
1658         if (!ImsUtils.shouldTestImsService()) {
1659             return;
1660         }
1661         TransportInterfaces ifaces = new TransportInterfaces(getDefaultRequest(),
1662                 Collections.emptySet(), 0);
1663         ifaces.connect();
1664         // Send invite
1665         SipDialogAttributes attr = new SipDialogAttributes();
1666         sendChatInvite(attr, ifaces);
1667         // receive 200 OK
1668         receive200OkResponse(attr, ifaces);
1669         // Send ACK
1670         sendAck(attr, ifaces);
1671         // send close from app
1672         ifaces.delegateConn.disconnect(ifaces.manager,
1673                 SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
1674         // Send BYE
1675         sendByeRequest(attr, ifaces);
1676         assertFalse(ifaces.transport.isLatchCountDownFinished(
1677                 TestSipTransport.LATCH_DESTROY_DELEGATE));
1678         // Registration state will change to deregistering during this time.
1679         ifaces.delegateConn.setOperationCountDownLatch(1);
1680         ifaces.delegateConn.waitForCountDown(ImsUtils.TEST_TIMEOUT_MS);
1681         assertTrue(ifaces.delegateConn.verifyDeregisteringStateContains(ONE_TO_ONE_CHAT_TAG,
1682                 DelegateRegistrationState.DEREGISTERING_REASON_DESTROY_PENDING));
1683         // waiting for delegate connection onDestroy to be called.
1684         ifaces.delegateConn.setOperationCountDownLatch(1);
1685         // Send the cleanup, which will trigger destroy to complete.
1686         ifaces.delegateConn.sendCleanupSession(attr.callId);
1687         ifaces.delegate.verifyCleanupSession(attr.callId);
1688         ifaces.transport.waitForLatchCountdownAndReset(TestSipTransport.LATCH_DESTROY_DELEGATE);
1689         ifaces.delegate.notifyOnDestroyed(
1690                 SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
1691         ifaces.delegateConn.waitForCountDown(ImsUtils.TEST_TIMEOUT_MS);
1692         ifaces.delegateConn.verifyDestroyed(
1693                 SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
1694         assertEquals("There should be no more delegates", 0,
1695                 ifaces.transport.getDelegates().size());
1696         verifyUpdateRegistrationCalled(ifaces.reg);
1697     }
1698 
1699     @Test
testSwitchAppPendingBye()1700     public void testSwitchAppPendingBye() throws Exception {
1701         if (!ImsUtils.shouldTestImsService()) {
1702             return;
1703         }
1704         TransportInterfaces ifaces = new TransportInterfaces(getDefaultRequest(),
1705                 Collections.emptySet(), 0);
1706         ifaces.connect();
1707         // Send invite
1708         SipDialogAttributes attr = new SipDialogAttributes();
1709         sendChatInvite(attr, ifaces);
1710         // receive 200 OK
1711         receive200OkResponse(attr, ifaces);
1712         // Restore the default SMS app.
1713         sServiceConnector.restoreDefaultSmsApp();
1714         // Registration state will change to deregistering during this time.
1715         ifaces.delegateConn.setOperationCountDownLatch(1);
1716         ifaces.delegateConn.waitForCountDown(ImsUtils.TEST_TIMEOUT_MS);
1717         assertTrue(ifaces.delegateConn.verifyDeregisteringStateContains(ONE_TO_ONE_CHAT_TAG,
1718                 DelegateRegistrationState.DEREGISTERING_REASON_FEATURE_TAGS_CHANGING));
1719         // Don't send BYE or cleanup, session should still be cleaned up.
1720         assertFalse(ifaces.transport.isLatchCountDownFinished(
1721                 TestSipTransport.LATCH_DESTROY_DELEGATE));
1722         // wait for delegate connection feature tag state to be updated with denied features.
1723         ifaces.delegateConn.setOperationCountDownLatch(1);
1724         // verify framework internally calls cleanup on the session before destroy.
1725         ifaces.delegate.verifyCleanupSession(attr.callId);
1726         ifaces.transport.waitForLatchCountdownAndReset(TestSipTransport.LATCH_DESTROY_DELEGATE);
1727         ifaces.delegate.notifyOnDestroyed(
1728                 SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
1729         assertEquals("There should be no more delegates", 0,
1730                 ifaces.transport.getDelegates().size());
1731         verifyUpdateRegistrationCalled(ifaces.reg);
1732         ifaces.delegateConn.waitForCountDown(ImsUtils.TEST_TIMEOUT_MS);
1733         ifaces.delegateConn.verifyRegistrationStateEmpty();
1734         ifaces.delegateConn.verifyAllDenied(SipDelegateManager.DENIED_REASON_NOT_ALLOWED);
1735     }
1736 
1737     @Test
testSwitchAppActiveSession()1738     public void testSwitchAppActiveSession() throws Exception {
1739         if (!ImsUtils.shouldTestImsService()) {
1740             return;
1741         }
1742         TransportInterfaces ifaces = new TransportInterfaces(getDefaultRequest(),
1743                 Collections.emptySet(), 0);
1744         ifaces.connect();
1745         // Send invite
1746         SipDialogAttributes attr = new SipDialogAttributes();
1747         sendChatInvite(attr, ifaces);
1748         // receive 200 OK
1749         receive200OkResponse(attr, ifaces);
1750         // Restore the default SMS app.
1751         sServiceConnector.restoreDefaultSmsApp();
1752         // Registration state will change to deregistering during this time.
1753         ifaces.delegateConn.setOperationCountDownLatch(1);
1754         ifaces.delegateConn.waitForCountDown(ImsUtils.TEST_TIMEOUT_MS);
1755         assertTrue(ifaces.delegateConn.verifyDeregisteringStateContains(ONE_TO_ONE_CHAT_TAG,
1756                 DelegateRegistrationState.DEREGISTERING_REASON_FEATURE_TAGS_CHANGING));
1757         // BYE should still be able to be sent
1758         sendByeRequest(attr, ifaces);
1759         assertFalse(ifaces.transport.isLatchCountDownFinished(
1760                 TestSipTransport.LATCH_DESTROY_DELEGATE));
1761         // wait for delegate connection feature tag state to be updated with denied features.
1762         ifaces.delegateConn.setOperationCountDownLatch(1);
1763         // Send the cleanup, which will trigger delegate destroy to complete.
1764         ifaces.delegateConn.sendCleanupSession(attr.callId);
1765         ifaces.delegate.verifyCleanupSession(attr.callId);
1766         ifaces.transport.waitForLatchCountdownAndReset(TestSipTransport.LATCH_DESTROY_DELEGATE);
1767         ifaces.delegate.notifyOnDestroyed(
1768                 SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
1769         assertEquals("There should be no more delegates", 0,
1770                 ifaces.transport.getDelegates().size());
1771         verifyUpdateRegistrationCalled(ifaces.reg);
1772         ifaces.delegateConn.waitForCountDown(ImsUtils.TEST_TIMEOUT_MS);
1773         ifaces.delegateConn.verifyAllDenied(SipDelegateManager.DENIED_REASON_NOT_ALLOWED);
1774     }
1775 
1776     @Test
testActiveSessionDeregistering()1777     public void testActiveSessionDeregistering() throws Exception {
1778         if (!ImsUtils.shouldTestImsService()) {
1779             return;
1780         }
1781         TransportInterfaces ifaces = new TransportInterfaces(getDefaultRequest(),
1782                 Collections.emptySet(), 0);
1783         ifaces.connect();
1784         // Send invite
1785         SipDialogAttributes attr = new SipDialogAttributes();
1786         sendChatInvite(attr, ifaces);
1787         // move chat to deregistering
1788         Set<String> regFeatures = new ArraySet<>(Arrays.asList(DEFAULT_FEATURE_TAGS));
1789         regFeatures.remove(ONE_TO_ONE_CHAT_TAG);
1790         DelegateRegistrationState state = getDeregisteringState(regFeatures,
1791                 Collections.singleton(ONE_TO_ONE_CHAT_TAG),
1792                 DelegateRegistrationState.DEREGISTERING_REASON_PROVISIONING_CHANGE);
1793         verifyRegistrationState(ifaces, state);
1794         // receive 200 OK
1795         receive200OkResponse(attr, ifaces);
1796         // Send ACK
1797         sendAck(attr, ifaces);
1798         // Send BYE and clean up
1799         sendByeRequest(attr, ifaces);
1800         ifaces.delegateConn.sendCleanupSession(attr.callId);
1801         ifaces.delegate.verifyCleanupSession(attr.callId);
1802 
1803         destroySipDelegateAndVerify(ifaces);
1804         assertEquals("There should be no more delegates", 0,
1805                 ifaces.transport.getDelegates().size());
1806         verifyUpdateRegistrationCalled(ifaces.reg);
1807     }
1808 
1809     @Test
testActiveSessionDeregisteringNoResponse()1810     public void testActiveSessionDeregisteringNoResponse() throws Exception {
1811         if (!ImsUtils.shouldTestImsService()) {
1812             return;
1813         }
1814         TransportInterfaces ifaces = new TransportInterfaces(getDefaultRequest(),
1815                 Collections.emptySet(), 0);
1816         ifaces.connect();
1817         // Send invite
1818         SipDialogAttributes attr = new SipDialogAttributes();
1819         sendChatInvite(attr, ifaces);
1820         // move chat to deregistering
1821         Set<String> regFeatures = new ArraySet<>(Arrays.asList(DEFAULT_FEATURE_TAGS));
1822         regFeatures.remove(ONE_TO_ONE_CHAT_TAG);
1823         DelegateRegistrationState state = getDeregisteringState(regFeatures,
1824                 Collections.singleton(ONE_TO_ONE_CHAT_TAG),
1825                 DelegateRegistrationState.DEREGISTERING_REASON_PROVISIONING_CHANGE);
1826         verifyRegistrationState(ifaces, state);
1827         // receive 200 OK
1828         receive200OkResponse(attr, ifaces);
1829         // Send ACK
1830         sendAck(attr, ifaces);
1831         // Don't send BYE or cleanup and ensure that we still get call to clean up after timeout.
1832         ifaces.delegate.verifyCleanupSession(attr.callId);
1833 
1834         destroySipDelegateAndVerify(ifaces);
1835         assertEquals("There should be no more delegates", 0,
1836                 ifaces.transport.getDelegates().size());
1837         verifyUpdateRegistrationCalled(ifaces.reg);
1838     }
1839 
1840     @Test
testMultipleActiveSessionDeregisteringNoResponse()1841     public void testMultipleActiveSessionDeregisteringNoResponse() throws Exception {
1842         if (!ImsUtils.shouldTestImsService()) {
1843             return;
1844         }
1845         TransportInterfaces ifaces = new TransportInterfaces(getDefaultRequest(),
1846                 Collections.emptySet(), 0);
1847         ifaces.connect();
1848         // Send invite 1
1849         SipDialogAttributes attr = new SipDialogAttributes();
1850         sendChatInvite(attr, ifaces);
1851         // Send invite 2
1852         SipDialogAttributes attr2 = new SipDialogAttributes();
1853         sendChatInvite(attr2, ifaces);
1854         // move chat to deregistering
1855         Set<String> regFeatures = new ArraySet<>(Arrays.asList(DEFAULT_FEATURE_TAGS));
1856         regFeatures.remove(ONE_TO_ONE_CHAT_TAG);
1857         DelegateRegistrationState state = getDeregisteringState(regFeatures,
1858                 Collections.singleton(ONE_TO_ONE_CHAT_TAG),
1859                 DelegateRegistrationState.DEREGISTERING_REASON_PROVISIONING_CHANGE);
1860         verifyRegistrationState(ifaces, state);
1861         // receive 200 OK for invite 1
1862         receive200OkResponse(attr, ifaces);
1863         // Don't send BYE or cleanup and ensure that we still get call to clean up after timeout.
1864         ifaces.delegate.verifyCleanupSession(attr.callId, attr2.callId);
1865         destroySipDelegateAndVerify(ifaces);
1866         assertEquals("There should be no more delegates", 0,
1867                 ifaces.transport.getDelegates().size());
1868         verifyUpdateRegistrationCalled(ifaces.reg);
1869     }
1870 
1871     @Test
testActiveSessionDeregisteringNewInviteDenied()1872     public void testActiveSessionDeregisteringNewInviteDenied() throws Exception {
1873         if (!ImsUtils.shouldTestImsService()) {
1874             return;
1875         }
1876         TransportInterfaces ifaces = new TransportInterfaces(getDefaultRequest(),
1877                 Collections.emptySet(), 0);
1878         ifaces.connect();
1879         // Send invite
1880         SipDialogAttributes attr = new SipDialogAttributes();
1881         sendChatInvite(attr, ifaces);
1882         // move chat to deregistering
1883         Set<String> regFeatures = new ArraySet<>(Arrays.asList(DEFAULT_FEATURE_TAGS));
1884         regFeatures.remove(ONE_TO_ONE_CHAT_TAG);
1885         DelegateRegistrationState state = getDeregisteringState(regFeatures,
1886                 Collections.singleton(ONE_TO_ONE_CHAT_TAG),
1887                 DelegateRegistrationState.DEREGISTERING_REASON_PROVISIONING_CHANGE);
1888         verifyRegistrationState(ifaces, state);
1889         // receive 200 OK
1890         receive200OkResponse(attr, ifaces);
1891         // Send ACK
1892         sendAck(attr, ifaces);
1893         // send a new invite over the same feature tag, which should be denied because the tag
1894         // is deregistering
1895         SipDialogAttributes attr2 = new SipDialogAttributes();
1896         attr2.addAcceptContactTag(ONE_TO_ONE_CHAT_TAG);
1897         sendDeniedChatInvite(attr2, ifaces,
1898                 SipDelegateManager.MESSAGE_FAILURE_REASON_INVALID_FEATURE_TAG);
1899         // Send BYE and clean up
1900         sendByeRequest(attr, ifaces);
1901         ifaces.delegateConn.sendCleanupSession(attr.callId);
1902         ifaces.delegate.verifyCleanupSession(attr.callId);
1903 
1904         destroySipDelegateAndVerify(ifaces);
1905         assertEquals("There should be no more delegates", 0,
1906                 ifaces.transport.getDelegates().size());
1907         verifyUpdateRegistrationCalled(ifaces.reg);
1908     }
1909 
1910     @Test
testInviteDeniedTag()1911     public void testInviteDeniedTag() throws Exception {
1912         if (!ImsUtils.shouldTestImsService()) {
1913             return;
1914         }
1915         // Deny ONE_TO_ONE_CHAT access to this delegate
1916         TransportInterfaces ifaces = new TransportInterfaces(getDefaultRequest(),
1917                 Collections.singleton(new FeatureTagState(ONE_TO_ONE_CHAT_TAG,
1918                         SipDelegateManager.DENIED_REASON_IN_USE_BY_ANOTHER_DELEGATE)), 0);
1919         ifaces.connect();
1920         // send a new invite over the chat feature tag, which should be denied because the tag was
1921         // denied
1922         SipDialogAttributes attr = new SipDialogAttributes();
1923         attr.addAcceptContactTag(ONE_TO_ONE_CHAT_TAG);
1924         sendDeniedChatInvite(attr, ifaces,
1925                 SipDelegateManager.MESSAGE_FAILURE_REASON_INVALID_FEATURE_TAG);
1926 
1927         destroySipDelegateAndVerify(ifaces);
1928         assertEquals("There should be no more delegates", 0,
1929                 ifaces.transport.getDelegates().size());
1930         verifyUpdateRegistrationCalled(ifaces.reg);
1931     }
1932 
1933     @Test
testInviteAcceptContactNotAssociated()1934     public void testInviteAcceptContactNotAssociated() throws Exception {
1935         if (!ImsUtils.shouldTestImsService()) {
1936             return;
1937         }
1938         TransportInterfaces ifaces = new TransportInterfaces(getDefaultRequest(),
1939                 Collections.emptySet(), 0);
1940         ifaces.connect();
1941         // send a new invite over the MMTEL feature tag, which is not in the set of feature tags
1942         // associated with this delegate.
1943         SipDialogAttributes attr = new SipDialogAttributes();
1944         attr.addAcceptContactTag(MMTEL_TAG);
1945         sendDeniedChatInvite(attr, ifaces,
1946                 SipDelegateManager.MESSAGE_FAILURE_REASON_INVALID_FEATURE_TAG);
1947 
1948         destroySipDelegateAndVerify(ifaces);
1949         assertEquals("There should be no more delegates", 0,
1950                 ifaces.transport.getDelegates().size());
1951         verifyUpdateRegistrationCalled(ifaces.reg);
1952     }
1953 
1954     @Test
testIncomingInviteDeregistering()1955     public void testIncomingInviteDeregistering() throws Exception {
1956         if (!ImsUtils.shouldTestImsService()) {
1957             return;
1958         }
1959         TransportInterfaces ifaces = new TransportInterfaces(getDefaultRequest(),
1960                 Collections.emptySet(), 0);
1961         ifaces.connect();
1962         // move chat to deregistering
1963         Set<String> regFeatures = new ArraySet<>(Arrays.asList(DEFAULT_FEATURE_TAGS));
1964         regFeatures.remove(ONE_TO_ONE_CHAT_TAG);
1965         DelegateRegistrationState state = getDeregisteringState(regFeatures,
1966                 Collections.singleton(ONE_TO_ONE_CHAT_TAG),
1967                 DelegateRegistrationState.DEREGISTERING_REASON_PROVISIONING_CHANGE);
1968         verifyRegistrationState(ifaces, state);
1969         // receive invite, which can not be blocked
1970         SipDialogAttributes attr = new SipDialogAttributes();
1971         receiveChatInvite(attr, ifaces);
1972         // ensure delegate connection can still respond to the request, even if in restricted state.
1973         send200OkResponse(attr, ifaces);
1974         receiveAck(attr, ifaces);
1975         // receive BYE and clean up
1976         receiveByeRequest(attr, ifaces);
1977         ifaces.delegateConn.sendCleanupSession(attr.callId);
1978         ifaces.delegate.verifyCleanupSession(attr.callId);
1979 
1980         destroySipDelegateAndVerify(ifaces);
1981         assertEquals("There should be no more delegates", 0,
1982                 ifaces.transport.getDelegates().size());
1983         verifyUpdateRegistrationCalled(ifaces.reg);
1984     }
1985 
generateSipMessage(String str)1986     private SipMessage generateSipMessage(String str) {
1987         String crlf = "\r\n";
1988         String[] components = str.split(crlf);
1989         String startLine = "";
1990         String header = "";
1991         String content = "";
1992         StringBuilder sb = new StringBuilder();
1993         int idx = 1;
1994         if (components.length > 0) {
1995             startLine = components[0] + crlf;
1996         }
1997         // generate sip header
1998         idx = composeSipSection(idx, components, sb);
1999         header = sb.toString();
2000 
2001         idx++;
2002         sb.setLength(0);
2003         // generate sip body
2004         idx = composeSipSection(idx, components, sb);
2005         content = sb.toString();
2006 
2007         return new SipMessage(startLine, header, content.getBytes(UTF_8));
2008     }
2009 
composeSipSection(int index, String[] components, StringBuilder sb)2010     private int composeSipSection(int index, String[] components, StringBuilder sb) {
2011         String crlf = "\r\n";
2012         while (index < components.length) {
2013             if (components[index].length() > 0) {
2014                 sb.append(components[index]).append(crlf);
2015                 index++;
2016             } else {
2017                 break;
2018             }
2019         }
2020         return index;
2021     }
2022 
sendChatInvite(SipDialogAttributes attr, TransportInterfaces ifaces)2023     private void sendChatInvite(SipDialogAttributes attr,
2024             TransportInterfaces ifaces) throws Exception {
2025         SipDialogAttributes invAttr = attr.fromExisting().copyWithNewBranch();
2026         invAttr.addAcceptContactTag(ONE_TO_ONE_CHAT_TAG);
2027         SipMessage invite = SipMessageUtils.generateSipRequest(SipMessageUtils.INVITE_SIP_METHOD,
2028                 invAttr);
2029         sendMessageAndVerifyAck(invite, ifaces);
2030     }
2031 
sendDeniedChatInvite(SipDialogAttributes attr, TransportInterfaces ifaces, int denyReason)2032     private void sendDeniedChatInvite(SipDialogAttributes attr,
2033             TransportInterfaces ifaces, int denyReason) throws Exception {
2034         SipDialogAttributes invAttr = attr.fromExisting().copyWithNewBranch();
2035         SipMessage invite = SipMessageUtils.generateSipRequest(SipMessageUtils.INVITE_SIP_METHOD,
2036                 invAttr);
2037         ifaces.delegateConn.sendMessageAndVerifyFailure(invite, denyReason);
2038     }
2039 
receiveChatInvite(SipDialogAttributes attr, TransportInterfaces ifaces)2040     private void receiveChatInvite(SipDialogAttributes attr,
2041             TransportInterfaces ifaces) throws Exception {
2042         SipDialogAttributes invAttr = attr.fromExisting().copyWithNewBranch();
2043         invAttr.addAcceptContactTag(ONE_TO_ONE_CHAT_TAG);
2044         SipMessage invite = SipMessageUtils.generateSipRequest(SipMessageUtils.INVITE_SIP_METHOD,
2045                 invAttr);
2046         receiveMessageAndVerifyAck(invite, ifaces);
2047     }
2048 
send200OkResponse(SipDialogAttributes attr, TransportInterfaces ifaces)2049     private void send200OkResponse(SipDialogAttributes attr,
2050             TransportInterfaces ifaces) throws Exception {
2051         attr.setToTag();
2052         // do not update branch here, as it is a response to a request.
2053         SipMessage resp = SipMessageUtils.generateSipResponse("200", "OK",
2054                 attr);
2055         sendMessageAndVerifyAck(resp, ifaces);
2056     }
2057 
receive200OkResponse(SipDialogAttributes attr, TransportInterfaces ifaces)2058     private void receive200OkResponse(SipDialogAttributes attr,
2059             TransportInterfaces ifaces) throws Exception {
2060         attr.setToTag();
2061         // do not update branch here, as it is a response to a request.
2062         SipMessage resp = SipMessageUtils.generateSipResponse("200", "OK",
2063                 attr);
2064         receiveMessageAndVerifyAck(resp, ifaces);
2065     }
2066 
sendAck(SipDialogAttributes attr, TransportInterfaces ifaces)2067     private void sendAck(SipDialogAttributes attr,
2068             TransportInterfaces ifaces) throws Exception {
2069         attr = attr.copyWithNewBranch();
2070         SipMessage invite = SipMessageUtils.generateSipRequest(SipMessageUtils.ACK_SIP_METHOD,
2071                 attr);
2072         sendMessageAndVerifyAck(invite, ifaces);
2073     }
2074 
receiveAck(SipDialogAttributes attr, TransportInterfaces ifaces)2075     private void receiveAck(SipDialogAttributes attr,
2076             TransportInterfaces ifaces) throws Exception {
2077         attr = attr.copyWithNewBranch();
2078         SipMessage invite = SipMessageUtils.generateSipRequest(SipMessageUtils.ACK_SIP_METHOD,
2079                 attr);
2080         receiveMessageAndVerifyAck(invite, ifaces);
2081     }
2082 
sendByeRequest(SipDialogAttributes attr, TransportInterfaces ifaces)2083     private void sendByeRequest(SipDialogAttributes attr,
2084             TransportInterfaces ifaces) throws Exception {
2085         attr = attr.copyWithNewBranch();
2086         SipMessage invite = SipMessageUtils.generateSipRequest(SipMessageUtils.BYE_SIP_METHOD,
2087                 attr);
2088         sendMessageAndVerifyAck(invite, ifaces);
2089     }
2090 
receiveByeRequest(SipDialogAttributes attr, TransportInterfaces ifaces)2091     private void receiveByeRequest(SipDialogAttributes attr,
2092             TransportInterfaces ifaces) throws Exception {
2093         attr = attr.copyWithNewBranch();
2094         SipMessage invite = SipMessageUtils.generateSipRequest(SipMessageUtils.BYE_SIP_METHOD,
2095                 attr);
2096         receiveMessageAndVerifyAck(invite, ifaces);
2097     }
2098 
createSipDelegateConnectionNoDelegateExpected(SipDelegateManager manager, TestSipDelegateConnection conn, TestSipTransport transport)2099     private void createSipDelegateConnectionNoDelegateExpected(SipDelegateManager manager,
2100             TestSipDelegateConnection conn, TestSipTransport transport) throws Exception {
2101         // wait for onCreated and reg state changed
2102         conn.setOperationCountDownLatch(2);
2103         conn.connect(manager);
2104         conn.waitForCountDown(ImsUtils.TEST_TIMEOUT_MS);
2105         conn.verifyDelegateCreated();
2106         conn.verifyRegistrationStateEmpty();
2107         // All requested features should have been denied due to the app not being the default sms
2108         // app.
2109         conn.verifyAllDenied(SipDelegateManager.DENIED_REASON_NOT_ALLOWED);
2110         // There should not have been a call to create a SipDelegate on the service side, since all
2111         // features were denied due to permissions issues.
2112         assertEquals("SipDelegate should not have been created", 0,
2113                 transport.getDelegates().size());
2114     }
2115 
destroySipDelegateConnectionNoDelegate(SipDelegateManager manager, TestSipDelegateConnection delegateConn)2116     private void destroySipDelegateConnectionNoDelegate(SipDelegateManager manager,
2117             TestSipDelegateConnection delegateConn) throws Exception {
2118         delegateConn.setOperationCountDownLatch(1);
2119         delegateConn.disconnect(manager,
2120                 SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
2121         delegateConn.waitForCountDown(ImsUtils.TEST_TIMEOUT_MS);
2122         delegateConn.verifyDestroyed(
2123                 SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
2124     }
2125 
destroySipDelegate(SipDelegateManager manager, TestSipTransport transportImpl, TestSipDelegateConnection delegateConn, TestSipDelegate delegate)2126     private void destroySipDelegate(SipDelegateManager manager,
2127             TestSipTransport transportImpl, TestSipDelegateConnection delegateConn,
2128             TestSipDelegate delegate) throws Exception {
2129         delegateConn.disconnect(manager,
2130                 SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
2131         transportImpl.waitForLatchCountdownAndReset(TestSipTransport.LATCH_DESTROY_DELEGATE);
2132         delegate.notifyOnDestroyed(
2133                 SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
2134 
2135     }
2136 
destroySipDelegateAndVerifyConnDestroyed(SipDelegateManager manager, TestSipTransport transportImpl, TestSipDelegateConnection delegateConn, TestSipDelegate delegate)2137     private void destroySipDelegateAndVerifyConnDestroyed(SipDelegateManager manager,
2138             TestSipTransport transportImpl, TestSipDelegateConnection delegateConn,
2139             TestSipDelegate delegate) throws Exception {
2140         delegateConn.setOperationCountDownLatch(1);
2141         destroySipDelegate(manager, transportImpl, delegateConn, delegate);
2142         delegateConn.waitForCountDown(ImsUtils.TEST_TIMEOUT_MS);
2143         delegateConn.verifyDestroyed(
2144                 SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
2145     }
2146 
destroySipDelegateAndVerify(TransportInterfaces ifaces)2147     private void destroySipDelegateAndVerify(TransportInterfaces ifaces) throws Exception {
2148         // wait for on destroyed
2149         destroySipDelegateAndVerifyConnDestroyed(ifaces.manager, ifaces.transport,
2150                 ifaces.delegateConn, ifaces.delegate);
2151     }
2152 
verifySipDelegateDestroyed(TestSipTransport transportImpl, TestSipDelegate delegate)2153     private void verifySipDelegateDestroyed(TestSipTransport transportImpl,
2154             TestSipDelegate delegate) {
2155         transportImpl.waitForLatchCountdownAndReset(TestSipTransport.LATCH_DESTROY_DELEGATE);
2156         delegate.notifyOnDestroyed(
2157                 SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
2158     }
2159 
createSipDelegateConnectionAndVerify(SipDelegateManager manager, TestSipDelegateConnection conn, TestSipTransport transport, Set<FeatureTagState> deniedTags, int delegateIndex)2160     private TestSipDelegate createSipDelegateConnectionAndVerify(SipDelegateManager manager,
2161             TestSipDelegateConnection conn, TestSipTransport transport,
2162             Set<FeatureTagState>  deniedTags, int delegateIndex) throws Exception {
2163         conn.setOperationCountDownLatch(1);
2164         conn.connect(manager);
2165         TestSipDelegate d = getSipDelegate(transport, deniedTags, delegateIndex);
2166         conn.waitForCountDown(ImsUtils.TEST_TIMEOUT_MS);
2167         conn.verifyDelegateCreated();
2168         return d;
2169     }
2170 
getSipDelegate(TestSipTransport transport, Set<FeatureTagState> deniedTags, int delegateIndex)2171     private TestSipDelegate getSipDelegate(TestSipTransport transport,
2172             Set<FeatureTagState> deniedTags, int delegateIndex) {
2173         transport.waitForLatchCountdownAndReset(TestSipTransport.LATCH_CREATE_DELEGATE);
2174         // There must have been a call to create a SipDelegate on the service side.
2175         assertEquals("SipDelegate should have been created", delegateIndex + 1,
2176                 transport.getDelegates().size());
2177         TestSipDelegate d = transport.getDelegates().get(delegateIndex);
2178         d.notifyOnCreated(deniedTags);
2179         return d;
2180     }
2181 
verifyRegisteredAndSendSipConfig(TestSipDelegateConnection delegateConn, TestSipDelegate delegate, Set<String> registeredTags, Set<FeatureTagState> deniedTags, SipDelegateConfiguration sipConfig)2182     private void verifyRegisteredAndSendSipConfig(TestSipDelegateConnection delegateConn,
2183             TestSipDelegate delegate, Set<String> registeredTags,
2184             Set<FeatureTagState> deniedTags, SipDelegateConfiguration sipConfig) {
2185         // wait for reg change to be called
2186         delegateConn.setOperationCountDownLatch(1);
2187         DelegateRegistrationState s = getRegisteredRegistrationState(registeredTags);
2188         delegate.notifyImsRegistrationUpdate(s);
2189         delegateConn.waitForCountDown(ImsUtils.TEST_TIMEOUT_MS);
2190         delegateConn.verifyRegistrationStateRegistered(registeredTags);
2191         delegateConn.verifyDenied(deniedTags);
2192 
2193         // send config change as well.
2194         sendConfigChange(sipConfig, delegateConn, delegate);
2195     }
2196 
generateDeniedSetFromRequest(Set<String> grantedTags, Set<String> newTags, int reason)2197     private Set<FeatureTagState> generateDeniedSetFromRequest(Set<String> grantedTags,
2198             Set<String> newTags, int reason) {
2199         // Deny features from newTags that are already granted in grantedTags.
2200         return grantedTags.stream().filter(newTags::contains)
2201                 .map(s -> new FeatureTagState(s, reason))
2202                 .collect(Collectors.toSet());
2203     }
2204 
verifyUpdateRegistrationCalled(TestImsRegistration regImpl)2205     private void verifyUpdateRegistrationCalled(TestImsRegistration regImpl) {
2206         regImpl.resetLatch(TestImsRegistration.LATCH_UPDATE_REGISTRATION, 1);
2207         // it is okay to reset and wait here (without race conditions) because there is a
2208         // second delay between triggering update registration and the latch being triggered.
2209         assertTrue(regImpl.waitForLatchCountDown(TestImsRegistration.LATCH_UPDATE_REGISTRATION,
2210                 ImsUtils.TEST_TIMEOUT_MS));
2211     }
2212 
sendRestrictedRequestsAndVerifyFailed( TestSipDelegateConnection delegateConn)2213     private void sendRestrictedRequestsAndVerifyFailed(
2214             TestSipDelegateConnection delegateConn) throws Exception {
2215         delegateConn.sendMessageAndVerifyFailure(SipMessageUtils.TEST_INVALID_SIP_REGISTER,
2216                 SipDelegateManager.MESSAGE_FAILURE_REASON_INVALID_START_LINE);
2217         delegateConn.sendMessageAndVerifyFailure(SipMessageUtils.TEST_INVALID_SIP_PUBLISH,
2218                 SipDelegateManager.MESSAGE_FAILURE_REASON_INVALID_START_LINE);
2219         delegateConn.sendMessageAndVerifyFailure(SipMessageUtils.TEST_INVALID_SIP_OPTIONS,
2220                 SipDelegateManager.MESSAGE_FAILURE_REASON_INVALID_START_LINE);
2221         delegateConn.sendMessageAndVerifyFailure(
2222                 SipMessageUtils.TEST_INVALID_SIP_SUBSCRIBE_PRESENCE,
2223                 SipDelegateManager.MESSAGE_FAILURE_REASON_INVALID_HEADER_FIELDS);
2224     }
2225 
verifyFullRegistrationTriggered(TransportInterfaces ifaces)2226     private void verifyFullRegistrationTriggered(TransportInterfaces ifaces) throws Exception {
2227         ifaces.delegateConn.verifyDelegateCreated();
2228         ifaces.delegateConn.triggerFullNetworkRegistration(ifaces.manager, 403, "FORBIDDEN");
2229         TestImsRegistration.NetworkRegistrationInfo info =
2230                 ifaces.reg.getNextFullNetworkRegRequest(ImsUtils.TEST_TIMEOUT_MS);
2231         assertNotNull("full registration requested, but ImsRegistrationImplBase "
2232                 + "implementation did not receive a request.", info);
2233         assertEquals(403, info.sipCode);
2234         assertEquals("FORBIDDEN", info.sipReason);
2235     }
2236 
sendInvalidRequestsAndVerifyFailed( TestSipDelegateConnection delegateConn)2237     private void sendInvalidRequestsAndVerifyFailed(
2238             TestSipDelegateConnection delegateConn) throws Exception {
2239         delegateConn.sendMessageAndVerifyFailure(SipMessageUtils.TEST_SIP_MESSAGE_INVALID_REQUEST,
2240                 SipDelegateManager.MESSAGE_FAILURE_REASON_INVALID_START_LINE);
2241         delegateConn.sendMessageAndVerifyFailure(SipMessageUtils.TEST_SIP_MESSAGE_INVALID_RESPONSE,
2242                 SipDelegateManager.MESSAGE_FAILURE_REASON_INVALID_START_LINE);
2243     }
2244 
verifyOutgoingTransport(TestSipDelegateConnection delegateConn, TestSipDelegate delegate)2245     private void verifyOutgoingTransport(TestSipDelegateConnection delegateConn,
2246             TestSipDelegate delegate) throws Exception {
2247         // Send a message and ensure it gets received on the other end as well as acked
2248         delegateConn.sendMessageAndVerifyCompletedSuccessfully(SipMessageUtils.TEST_SIP_MESSAGE);
2249         delegate.verifyMessageSend(SipMessageUtils.TEST_SIP_MESSAGE);
2250         delegateConn.sendCleanupSession(SipMessageUtils.TEST_SIP_MESSAGE.getCallIdParameter());
2251         delegate.verifyCleanupSession(SipMessageUtils.TEST_SIP_MESSAGE.getCallIdParameter());
2252         // send a message and notify connection that it failed
2253         delegate.setSendMessageDenyReason(
2254                 SipDelegateManager.MESSAGE_FAILURE_REASON_NETWORK_NOT_AVAILABLE);
2255         delegateConn.sendMessageAndVerifyFailure(SipMessageUtils.TEST_SIP_MESSAGE,
2256                 SipDelegateManager.MESSAGE_FAILURE_REASON_NETWORK_NOT_AVAILABLE);
2257         delegate.verifyMessageSend(SipMessageUtils.TEST_SIP_MESSAGE);
2258     }
2259 
sendMessageAndVerifyAck(SipMessage message, TransportInterfaces ifaces)2260     private void sendMessageAndVerifyAck(SipMessage message,
2261             TransportInterfaces ifaces) throws Exception {
2262         // Send a message and ensure it gets received on the other end as well as acked
2263         ifaces.delegateConn.sendMessageAndVerifyCompletedSuccessfully(message);
2264     }
2265 
verifyIncomingTransport(TestSipDelegateConnection delegateConn, TestSipDelegate delegate)2266     private void verifyIncomingTransport(TestSipDelegateConnection delegateConn,
2267             TestSipDelegate delegate) throws Exception {
2268         // Receive a message and ensure it gets received on the other end as well as acked
2269         delegate.receiveMessageAndVerifyReceivedCalled(SipMessageUtils.TEST_SIP_MESSAGE);
2270         delegateConn.verifyMessageReceived(SipMessageUtils.TEST_SIP_MESSAGE);
2271         // Receive a message and have connection notify that it didn't complete
2272         delegateConn.setReceivedMessageErrorResponseReason(
2273                 SipDelegateManager.MESSAGE_FAILURE_REASON_INVALID_BODY_CONTENT);
2274         delegate.receiveMessageAndVerifyReceiveErrorCalled(SipMessageUtils.TEST_SIP_MESSAGE,
2275                 SipDelegateManager.MESSAGE_FAILURE_REASON_INVALID_BODY_CONTENT);
2276     }
2277 
receiveMessageAndVerifyAck(SipMessage message, TransportInterfaces ifaces)2278     private void receiveMessageAndVerifyAck(SipMessage message,
2279             TransportInterfaces ifaces) throws Exception {
2280         // Receive a message and ensure it gets received on the other end as well as acked
2281         ifaces.delegate.receiveMessageAndVerifyReceivedCalled(message);
2282         ifaces.delegateConn.verifyMessageReceived(message);
2283     }
2284 
verifyRegistrationState(TransportInterfaces ifaces, DelegateRegistrationState state)2285     private void verifyRegistrationState(TransportInterfaces ifaces,
2286             DelegateRegistrationState state) {
2287         ifaces.delegateConn.setOperationCountDownLatch(1);
2288         ifaces.delegate.notifyImsRegistrationUpdate(state);
2289         ifaces.delegateConn.waitForCountDown(ImsUtils.TEST_TIMEOUT_MS);
2290         ifaces.delegateConn.verifyRegistrationStateEquals(state);
2291     }
2292 
getDeregisteringState(Set<String> registered, Set<String> deregistering, int deregisteringReason)2293     private DelegateRegistrationState getDeregisteringState(Set<String> registered,
2294             Set<String> deregistering, int deregisteringReason) {
2295         DelegateRegistrationState.Builder b = new DelegateRegistrationState.Builder();
2296         b.addRegisteredFeatureTags(registered);
2297         for (String dereg : deregistering) {
2298             b.addDeregisteringFeatureTag(dereg, deregisteringReason);
2299         }
2300         return b.build();
2301     }
2302 
sendConfigChange(SipDelegateConfiguration c, TestSipDelegateConnection delegateConn, TestSipDelegate delegate)2303     private void sendConfigChange(SipDelegateConfiguration c,
2304             TestSipDelegateConnection delegateConn, TestSipDelegate delegate) {
2305         delegateConn.setOperationCountDownLatch(1);
2306         delegate.notifyConfigurationUpdate(c);
2307         delegateConn.waitForCountDown(ImsUtils.TEST_TIMEOUT_MS);
2308         delegateConn.verifyConfigEquals(c);
2309     }
2310 
2311     /**
2312      * @return A new test SipDelegateConfiguration that has all fields populated.1
2313      */
generateNewTestConfig()2314     private SipDelegateConfiguration generateNewTestConfig() {
2315         InetSocketAddress localAddr = new InetSocketAddress(
2316                 InetAddresses.parseNumericAddress("1.1.1.1"), 80);
2317         InetSocketAddress serverAddr = new InetSocketAddress(
2318                 InetAddresses.parseNumericAddress("2.2.2.2"), 81);
2319         SipDelegateConfiguration.Builder b = new SipDelegateConfiguration.Builder(1,
2320                 SipDelegateConfiguration.SIP_TRANSPORT_TCP, localAddr, serverAddr);
2321         b.setSipCompactFormEnabled(true);
2322         b.setSipKeepaliveEnabled(true);
2323         b.setMaxUdpPayloadSizeBytes(508);
2324         b.setPublicUserIdentifier("test1");
2325         b.setPrivateUserIdentifier("test2");
2326         b.setHomeDomain("test.domain");
2327         b.setImei("testImei");
2328         b.setSipAuthenticationHeader("sipauth");
2329         b.setSipAuthenticationNonce("sipnonce");
2330         b.setSipServiceRouteHeader("srvroute");
2331         b.setSipPathHeader("path");
2332         b.setSipUserAgentHeader("ua");
2333         b.setSipContactUserParameter("user");
2334         b.setSipPaniHeader("pani");
2335         b.setSipPlaniHeader("plani");
2336         b.setSipCniHeader("cni");
2337         b.setSipAssociatedUriHeader("uri");
2338         Uri gruuUri = Uri.parse("sip:blah@gruu.net");
2339         b.setPublicGruuUri(gruuUri);
2340         SipDelegateConfiguration.IpSecConfiguration ipSecConfig =
2341                 new SipDelegateConfiguration.IpSecConfiguration(123, 124,
2342                         125, 126, 127, 128, "secverify");
2343         assertEquals(123, ipSecConfig.getLocalTxPort());
2344         assertEquals(124, ipSecConfig.getLocalRxPort());
2345         assertEquals(125, ipSecConfig.getLastLocalTxPort());
2346         assertEquals(126, ipSecConfig.getRemoteTxPort());
2347         assertEquals(127, ipSecConfig.getRemoteRxPort());
2348         assertEquals(128, ipSecConfig.getLastRemoteTxPort());
2349         assertEquals("secverify", ipSecConfig.getSipSecurityVerifyHeader());
2350         b.setIpSecConfiguration(ipSecConfig);
2351         InetSocketAddress natAddr = new InetSocketAddress(
2352                 InetAddresses.parseNumericAddress("3.3.3.3"), 129);
2353         b.setNatSocketAddress(natAddr);
2354         assertEquals("3.3.3.3", natAddr.getAddress().getHostAddress());
2355         assertEquals(129, natAddr.getPort());
2356         return b.build();
2357     }
2358 
getRegisteredRegistrationState(Set<String> registered)2359     private DelegateRegistrationState getRegisteredRegistrationState(Set<String> registered) {
2360         return new DelegateRegistrationState.Builder().addRegisteredFeatureTags(registered).build();
2361     }
2362 
getRegisteringRegistrationState(Set<String> registering)2363     private DelegateRegistrationState getRegisteringRegistrationState(Set<String> registering) {
2364         return new DelegateRegistrationState.Builder().addRegisteringFeatureTags(registering)
2365                 .build();
2366     }
2367 
getDeregisteringState(Set<String> deregisterTags, int reason)2368     private DelegateRegistrationState getDeregisteringState(Set<String> deregisterTags,
2369             int reason) {
2370         DelegateRegistrationState.Builder b = new DelegateRegistrationState.Builder();
2371         for (String t : deregisterTags) {
2372             b.addDeregisteringFeatureTag(t, reason);
2373         }
2374         return b.build();
2375     }
2376 
getDeregisteredState(Set<String> deregisterTags, int reason)2377     private DelegateRegistrationState getDeregisteredState(Set<String> deregisterTags,
2378             int reason) {
2379         DelegateRegistrationState.Builder b = new DelegateRegistrationState.Builder();
2380         for (String t : deregisterTags) {
2381             b.addDeregisteredFeatureTag(t, reason);
2382         }
2383         return b.build();
2384     }
2385 
2386 
connectTestImsServiceWithSipTransportAndConfig()2387     private void connectTestImsServiceWithSipTransportAndConfig() throws Exception {
2388         PersistableBundle b = new PersistableBundle();
2389         b.putBoolean(CarrierConfigManager.Ims.KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL, true);
2390         overrideCarrierConfig(b);
2391 
2392         assertTrue(sServiceConnector.connectCarrierImsServiceLocally());
2393         sServiceConnector.getCarrierService().addCapabilities(
2394                 ImsService.CAPABILITY_SIP_DELEGATE_CREATION);
2395         sServiceConnector.getCarrierService().setSipTransportImplemented();
2396         ImsFeatureConfiguration c = getConfigForMmTelAndRcs();
2397         assertTrue(sServiceConnector.triggerFrameworkConnectionToCarrierImsService(c));
2398         verifyImsServiceState(c);
2399     }
2400 
2401 
connectTestImsServiceWithSipTransport()2402     private void connectTestImsServiceWithSipTransport() throws Exception {
2403         assertTrue(sServiceConnector.connectCarrierImsServiceLocally());
2404         sServiceConnector.getCarrierService().addCapabilities(
2405                 ImsService.CAPABILITY_SIP_DELEGATE_CREATION);
2406         sServiceConnector.getCarrierService().setSipTransportImplemented();
2407         ImsFeatureConfiguration c = getConfigForMmTelAndRcs();
2408         assertTrue(sServiceConnector.triggerFrameworkConnectionToCarrierImsService(c));
2409         verifyImsServiceState(c);
2410     }
2411 
verifyImsServiceState(ImsFeatureConfiguration config)2412     private void verifyImsServiceState(ImsFeatureConfiguration config) {
2413         for (ImsFeatureConfiguration.FeatureSlotPair p : config.getServiceFeatures()) {
2414             switch (p.featureType) {
2415                 case ImsFeature.FEATURE_MMTEL: {
2416                     sServiceConnector.getCarrierService().waitForLatchCountdown(
2417                             TestImsService.LATCH_CREATE_MMTEL);
2418                     assertNotNull("ImsService created, but ImsService#createMmTelFeature was not "
2419                             + "called!", sServiceConnector.getCarrierService().getMmTelFeature());
2420                     break;
2421                 }
2422                 case ImsFeature.FEATURE_RCS: {
2423                     sServiceConnector.getCarrierService().waitForLatchCountdown(
2424                             TestImsService.LATCH_CREATE_RCS);
2425                     assertNotNull("ImsService created, but ImsService#createRcsFeature was not "
2426                             + "called!", sServiceConnector.getCarrierService().getRcsFeature());
2427                     break;
2428                 }
2429             }
2430         }
2431     }
2432 
2433     /**
2434      * Wait up to five seconds (retrying a command 1 time per second) until ImsExceptions due to the
2435      * ImsService not being available go away. If the ImsService never becomes available, this
2436      * method will return null.
2437      */
callUntilImsServiceIsAvailable(Callable<T> command)2438     private <T> T callUntilImsServiceIsAvailable(Callable<T> command) throws Exception {
2439         int retry = 0;
2440         while (retry < 5) {
2441             try {
2442                 return command.call();
2443             } catch (ImsException e) {
2444                 // we want to absorb only the unavailable error, as telephony may still be
2445                 // internally setting up. Any other type of ImsException is unexpected.
2446                 if (e.getCode() != ImsException.CODE_ERROR_SERVICE_UNAVAILABLE) {
2447                     throw e;
2448                 }
2449             }
2450             Thread.sleep(1000);
2451             retry++;
2452         }
2453         return null;
2454     }
2455 
getDefaultRequest()2456     private DelegateRequest getDefaultRequest() {
2457         ArraySet<String> features = new ArraySet<>(Arrays.asList(DEFAULT_FEATURE_TAGS));
2458         return new DelegateRequest(features);
2459     }
2460 
getChatOnlyRequest()2461     private DelegateRequest getChatOnlyRequest() {
2462         ArraySet<String> features = new ArraySet<>(3);
2463         features.add(ONE_TO_ONE_CHAT_TAG);
2464         features.add(GROUP_CHAT_TAG);
2465         return new DelegateRequest(features);
2466     }
2467 
getConfigForMmTelAndRcs()2468     private ImsFeatureConfiguration getConfigForMmTelAndRcs() {
2469         return new ImsFeatureConfiguration.Builder()
2470                 .addFeature(sTestSlot, ImsFeature.FEATURE_EMERGENCY_MMTEL)
2471                 .addFeature(sTestSlot, ImsFeature.FEATURE_MMTEL)
2472                 .addFeature(sTestSlot, ImsFeature.FEATURE_RCS)
2473                 .build();
2474     }
2475 
getConfigForRcs()2476     private ImsFeatureConfiguration getConfigForRcs() {
2477         return new ImsFeatureConfiguration.Builder()
2478                 .addFeature(sTestSlot, ImsFeature.FEATURE_RCS)
2479                 .build();
2480     }
2481 
getDeniedTagsForReason(Set<String> deniedTags, int reason)2482     private Set<FeatureTagState> getDeniedTagsForReason(Set<String> deniedTags, int reason) {
2483         return deniedTags.stream().map(t -> new FeatureTagState(t, reason))
2484                 .collect(Collectors.toSet());
2485     }
2486 
overrideCarrierConfig(PersistableBundle bundle)2487     private static void overrideCarrierConfig(PersistableBundle bundle) throws Exception {
2488         CarrierConfigManager carrierConfigManager = InstrumentationRegistry.getInstrumentation()
2489                 .getContext().getSystemService(CarrierConfigManager.class);
2490         sReceiver.clearQueue();
2491         ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(carrierConfigManager,
2492                 (m) -> m.overrideConfig(sTestSub, bundle));
2493         sReceiver.waitForCarrierConfigChanged();
2494     }
2495 
setFeatureTagsCarrierAllowed(String[] tags)2496     private static void setFeatureTagsCarrierAllowed(String[] tags) throws Exception {
2497         PersistableBundle bundle = new PersistableBundle();
2498         bundle.putStringArray(CarrierConfigManager.Ims.KEY_RCS_FEATURE_TAG_ALLOWED_STRING_ARRAY,
2499                 tags);
2500         overrideCarrierConfig(bundle);
2501     }
2502 
getSipDelegateManager()2503     private SipDelegateManager getSipDelegateManager() {
2504         ImsManager imsManager = getContext().getSystemService(ImsManager.class);
2505         assertNotNull(imsManager);
2506         return imsManager.getSipDelegateManager(sTestSub);
2507     }
2508 
getContext()2509     private static Context getContext() {
2510         return InstrumentationRegistry.getInstrumentation().getContext();
2511     }
2512 }
2513