1 /* 2 * Copyright (C) 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.services.telephony.rcs; 18 19 import static org.junit.Assert.assertEquals; 20 import static org.mockito.ArgumentMatchers.any; 21 import static org.mockito.ArgumentMatchers.anyInt; 22 import static org.mockito.ArgumentMatchers.eq; 23 import static org.mockito.Mockito.never; 24 import static org.mockito.Mockito.times; 25 import static org.mockito.Mockito.verify; 26 27 import android.net.InetAddresses; 28 import android.telephony.ims.DelegateRegistrationState; 29 import android.telephony.ims.FeatureTagState; 30 import android.telephony.ims.SipDelegateConfiguration; 31 import android.telephony.ims.SipDelegateManager; 32 import android.telephony.ims.aidl.ISipDelegate; 33 import android.telephony.ims.aidl.ISipDelegateConnectionStateCallback; 34 import android.util.ArraySet; 35 36 import androidx.test.filters.SmallTest; 37 import androidx.test.runner.AndroidJUnit4; 38 39 import com.android.TelephonyTestBase; 40 import com.android.internal.telephony.metrics.RcsStats; 41 42 import org.junit.After; 43 import org.junit.Before; 44 import org.junit.Test; 45 import org.junit.runner.RunWith; 46 import org.mockito.ArgumentCaptor; 47 import org.mockito.Mock; 48 49 import java.net.InetSocketAddress; 50 import java.util.ArrayList; 51 import java.util.List; 52 import java.util.Set; 53 54 @RunWith(AndroidJUnit4.class) 55 public class DelegateStateTrackerTest extends TelephonyTestBase { 56 private static final int TEST_SUB_ID = 1; 57 58 @Mock private ISipDelegate mSipDelegate; 59 @Mock private ISipDelegateConnectionStateCallback mAppCallback; 60 @Mock private RcsStats mRcsStats; 61 62 @Before setUp()63 public void setUp() throws Exception { 64 super.setUp(); 65 } 66 67 @After tearDown()68 public void tearDown() throws Exception { 69 super.tearDown(); 70 } 71 72 /** 73 * When an underlying SipDelegate is created, the app should only receive one onCreated callback 74 * independent of how many times sipDelegateConnected is called. Once created, registration 75 * and IMS configuration events should propagate up to the app as well. 76 */ 77 @SmallTest 78 @Test testDelegateCreated()79 public void testDelegateCreated() throws Exception { 80 DelegateStateTracker stateTracker = new DelegateStateTracker(TEST_SUB_ID, mAppCallback, 81 mSipDelegate, mRcsStats); 82 Set<FeatureTagState> deniedTags = getMmTelDeniedTag(); 83 Set<String> supportedTags = getSupportedTags(); 84 stateTracker.sipDelegateConnected(supportedTags, deniedTags); 85 // Calling connected multiple times should not generate multiple onCreated events. 86 stateTracker.sipDelegateConnected(supportedTags, deniedTags); 87 verify(mAppCallback).onCreated(mSipDelegate); 88 verify(mRcsStats).createSipDelegateStats(TEST_SUB_ID, supportedTags); 89 90 // Ensure status updates are sent to app as expected. 91 DelegateRegistrationState regState = new DelegateRegistrationState.Builder() 92 .addRegisteredFeatureTag(ImsSignallingUtils.ONE_TO_ONE_CHAT_TAG) 93 .build(); 94 InetSocketAddress localAddr = new InetSocketAddress( 95 InetAddresses.parseNumericAddress("1.1.1.1"), 80); 96 InetSocketAddress serverAddr = new InetSocketAddress( 97 InetAddresses.parseNumericAddress("2.2.2.2"), 81); 98 SipDelegateConfiguration c = new SipDelegateConfiguration.Builder(1, 99 SipDelegateConfiguration.SIP_TRANSPORT_TCP, localAddr, serverAddr).build(); 100 stateTracker.onRegistrationStateChanged(regState); 101 stateTracker.onConfigurationChanged(c); 102 verify(mAppCallback).onFeatureTagStatusChanged(eq(regState), 103 eq(new ArrayList<>(deniedTags))); 104 verify(mRcsStats).onSipTransportFeatureTagStats(TEST_SUB_ID, deniedTags, 105 regState.getDeregisteredFeatureTags(), 106 regState.getRegisteredFeatureTags()); 107 verify(mAppCallback).onConfigurationChanged(c); 108 verify(mAppCallback, never()).onDestroyed(anyInt()); 109 } 110 111 /** 112 * onDestroyed should be called when sipDelegateDestroyed is called. 113 */ 114 @SmallTest 115 @Test testDelegateDestroyed()116 public void testDelegateDestroyed() throws Exception { 117 DelegateStateTracker stateTracker = new DelegateStateTracker(TEST_SUB_ID, mAppCallback, 118 mSipDelegate, mRcsStats); 119 Set<FeatureTagState> deniedTags = getMmTelDeniedTag(); 120 Set<String> supportedTags = getSupportedTags(); 121 stateTracker.sipDelegateConnected(supportedTags, deniedTags); 122 verify(mRcsStats).createSipDelegateStats(eq(TEST_SUB_ID), eq(supportedTags)); 123 124 stateTracker.sipDelegateDestroyed( 125 SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP); 126 verify(mAppCallback).onDestroyed( 127 SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP); 128 verify(mRcsStats).onSipDelegateStats(eq(TEST_SUB_ID), eq(supportedTags), 129 eq(SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP)); 130 } 131 132 /** 133 * When a SipDelegate is created and then an event occurs that will destroy->create a new 134 * SipDelegate underneath, we need to move the state of the features that are reporting 135 * registered to DEREGISTERING_REASON_FEATURE_TAGS_CHANGING so that the app can close dialogs on 136 * it. Once the new underlying SipDelegate is created, we must verify that the new registration 137 * is propagated up without any overrides. 138 */ 139 @SmallTest 140 @Test testDelegateChangingRegisteredTagsOverride()141 public void testDelegateChangingRegisteredTagsOverride() throws Exception { 142 DelegateStateTracker stateTracker = new DelegateStateTracker(TEST_SUB_ID, mAppCallback, 143 mSipDelegate, mRcsStats); 144 Set<FeatureTagState> deniedTags = getMmTelDeniedTag(); 145 Set<String> supportedTags = getSupportedTags(); 146 stateTracker.sipDelegateConnected(supportedTags, deniedTags); 147 // SipDelegate created 148 verify(mAppCallback).onCreated(mSipDelegate); 149 DelegateRegistrationState regState = new DelegateRegistrationState.Builder() 150 .addRegisteredFeatureTag(ImsSignallingUtils.ONE_TO_ONE_CHAT_TAG) 151 .addDeregisteringFeatureTag(ImsSignallingUtils.FILE_TRANSFER_HTTP_TAG, 152 DelegateRegistrationState.DEREGISTERING_REASON_PROVISIONING_CHANGE) 153 .addDeregisteredFeatureTag(ImsSignallingUtils.GROUP_CHAT_TAG, 154 DelegateRegistrationState.DEREGISTERED_REASON_NOT_PROVISIONED) 155 .build(); 156 stateTracker.onRegistrationStateChanged(regState); 157 // Simulate underlying SipDelegate switch 158 stateTracker.sipDelegateChanging( 159 DelegateRegistrationState.DEREGISTERING_REASON_FEATURE_TAGS_CHANGING); 160 // onFeatureTagStatusChanged should now be called with registered features overridden with 161 // DEREGISTERING_REASON_FEATURE_TAGS_CHANGING 162 DelegateRegistrationState overrideRegState = new DelegateRegistrationState.Builder() 163 .addDeregisteringFeatureTag(ImsSignallingUtils.ONE_TO_ONE_CHAT_TAG, 164 DelegateRegistrationState.DEREGISTERING_REASON_FEATURE_TAGS_CHANGING) 165 // Already Deregistering/Deregistered tags should not be overridden. 166 .addDeregisteringFeatureTag(ImsSignallingUtils.FILE_TRANSFER_HTTP_TAG, 167 DelegateRegistrationState.DEREGISTERING_REASON_PROVISIONING_CHANGE) 168 .addDeregisteredFeatureTag(ImsSignallingUtils.GROUP_CHAT_TAG, 169 DelegateRegistrationState.DEREGISTERED_REASON_NOT_PROVISIONED) 170 .build(); 171 // new underlying SipDelegate created 172 stateTracker.sipDelegateConnected(supportedTags, deniedTags); 173 stateTracker.onRegistrationStateChanged(regState); 174 175 // Verify registration state through the process: 176 ArgumentCaptor<DelegateRegistrationState> regCaptor = 177 ArgumentCaptor.forClass(DelegateRegistrationState.class); 178 verify(mAppCallback, times(3)).onFeatureTagStatusChanged( 179 regCaptor.capture(), eq(new ArrayList<>(deniedTags))); 180 List<DelegateRegistrationState> testStates = regCaptor.getAllValues(); 181 // feature tags should first be registered 182 assertEquals(regState, testStates.get(0)); 183 // registered feature tags should have moved to deregistering 184 assertEquals(overrideRegState, testStates.get(1)); 185 // and then moved back to registered after underlying FT change done. 186 assertEquals(regState, testStates.get(2)); 187 188 //onCreate should only have been called once and onDestroy should have never been called. 189 verify(mAppCallback).onCreated(mSipDelegate); 190 verify(mAppCallback, never()).onDestroyed(anyInt()); 191 } 192 193 /** 194 * Test the case that when the underlying Denied tags change in the SipDelegate, the change is 195 * properly shown in the registration update event. 196 */ 197 @SmallTest 198 @Test testDelegateChangingDeniedTagsChanged()199 public void testDelegateChangingDeniedTagsChanged() throws Exception { 200 DelegateStateTracker stateTracker = new DelegateStateTracker(TEST_SUB_ID, mAppCallback, 201 mSipDelegate, mRcsStats); 202 Set<FeatureTagState> deniedTags = getMmTelDeniedTag(); 203 Set<String> supportedTags = getSupportedTags(); 204 stateTracker.sipDelegateConnected(supportedTags, deniedTags); 205 // SipDelegate created 206 verify(mAppCallback).onCreated(mSipDelegate); 207 DelegateRegistrationState regState = new DelegateRegistrationState.Builder() 208 .addRegisteredFeatureTag(ImsSignallingUtils.ONE_TO_ONE_CHAT_TAG) 209 .build(); 210 stateTracker.onRegistrationStateChanged(regState); 211 // Simulate underlying SipDelegate switch 212 stateTracker.sipDelegateChanging( 213 DelegateRegistrationState.DEREGISTERING_REASON_FEATURE_TAGS_CHANGING); 214 // onFeatureTagStatusChanged should now be called with registered features overridden with 215 // DEREGISTERING_REASON_FEATURE_TAGS_CHANGING 216 DelegateRegistrationState overrideRegState = new DelegateRegistrationState.Builder() 217 .addDeregisteringFeatureTag(ImsSignallingUtils.ONE_TO_ONE_CHAT_TAG, 218 DelegateRegistrationState.DEREGISTERING_REASON_FEATURE_TAGS_CHANGING) 219 .build(); 220 // Verify registration state so far. 221 ArgumentCaptor<DelegateRegistrationState> regCaptor = 222 ArgumentCaptor.forClass(DelegateRegistrationState.class); 223 verify(mAppCallback, times(2)).onFeatureTagStatusChanged( 224 regCaptor.capture(), eq(new ArrayList<>(deniedTags))); 225 List<DelegateRegistrationState> testStates = regCaptor.getAllValues(); 226 assertEquals(2, testStates.size()); 227 // feature tags should first be registered 228 assertEquals(regState, testStates.get(0)); 229 // registered feature tags should have moved to deregistering 230 assertEquals(overrideRegState, testStates.get(1)); 231 232 // new underlying SipDelegate created, but SipDelegate denied one to one chat 233 deniedTags.add(new FeatureTagState(ImsSignallingUtils.ONE_TO_ONE_CHAT_TAG, 234 SipDelegateManager.DENIED_REASON_NOT_ALLOWED)); 235 stateTracker.sipDelegateConnected(supportedTags, deniedTags); 236 DelegateRegistrationState fullyDeniedRegState = new DelegateRegistrationState.Builder() 237 .build(); 238 // In this special case, it will be the SipDelegateConnectionBase that will trigger 239 // reg state change. 240 stateTracker.onRegistrationStateChanged(fullyDeniedRegState); 241 verify(mAppCallback).onFeatureTagStatusChanged(regCaptor.capture(), 242 eq(new ArrayList<>(deniedTags))); 243 // now all feature tags denied, so we should see only denied tags. 244 assertEquals(fullyDeniedRegState, regCaptor.getValue()); 245 246 //onCreate should only have been called once and onDestroy should have never been called. 247 verify(mAppCallback).onCreated(mSipDelegate); 248 verify(mAppCallback, never()).onDestroyed(anyInt()); 249 } 250 251 /** 252 * Test that when we move from changing tags state to the delegate being destroyed, we get the 253 * correct onDestroy event sent to the app. 254 */ 255 @SmallTest 256 @Test testDelegateChangingDeniedTagsChangingToDestroy()257 public void testDelegateChangingDeniedTagsChangingToDestroy() throws Exception { 258 DelegateStateTracker stateTracker = new DelegateStateTracker(TEST_SUB_ID, mAppCallback, 259 mSipDelegate, mRcsStats); 260 Set<FeatureTagState> deniedTags = getMmTelDeniedTag(); 261 Set<String> supportedTags = getSupportedTags(); 262 stateTracker.sipDelegateConnected(supportedTags, deniedTags); 263 // SipDelegate created 264 verify(mAppCallback).onCreated(mSipDelegate); 265 DelegateRegistrationState regState = new DelegateRegistrationState.Builder() 266 .addRegisteredFeatureTag(ImsSignallingUtils.ONE_TO_ONE_CHAT_TAG) 267 .addDeregisteredFeatureTag(ImsSignallingUtils.GROUP_CHAT_TAG, 268 DelegateRegistrationState.DEREGISTERED_REASON_NOT_PROVISIONED) 269 .build(); 270 stateTracker.onRegistrationStateChanged(regState); 271 verify(mAppCallback).onFeatureTagStatusChanged(any(), 272 eq(new ArrayList<>(deniedTags))); 273 // Simulate underlying SipDelegate switch 274 stateTracker.sipDelegateChanging( 275 DelegateRegistrationState.DEREGISTERING_REASON_DESTROY_PENDING); 276 // Destroy 277 stateTracker.sipDelegateDestroyed( 278 SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP); 279 280 // onFeatureTagStatusChanged should now be called with registered features overridden with 281 // DEREGISTERING_REASON_DESTROY_PENDING 282 DelegateRegistrationState overrideRegState = new DelegateRegistrationState.Builder() 283 .addDeregisteringFeatureTag(ImsSignallingUtils.ONE_TO_ONE_CHAT_TAG, 284 DelegateRegistrationState.DEREGISTERING_REASON_DESTROY_PENDING) 285 // Deregistered should stay the same. 286 .addDeregisteredFeatureTag(ImsSignallingUtils.GROUP_CHAT_TAG, 287 DelegateRegistrationState.DEREGISTERED_REASON_NOT_PROVISIONED) 288 .build(); 289 // Verify registration state through process: 290 ArgumentCaptor<DelegateRegistrationState> regCaptor = 291 ArgumentCaptor.forClass(DelegateRegistrationState.class); 292 verify(mAppCallback, times(2)).onFeatureTagStatusChanged(regCaptor.capture(), 293 eq(new ArrayList<>(deniedTags))); 294 List<DelegateRegistrationState> testStates = regCaptor.getAllValues(); 295 assertEquals(2, testStates.size()); 296 // feature tags should first be registered 297 assertEquals(regState, testStates.get(0)); 298 // registered feature tags should have moved to deregistering 299 assertEquals(overrideRegState, testStates.get(1)); 300 //onCreate/onDestroy should only be called once. 301 verify(mAppCallback).onCreated(mSipDelegate); 302 verify(mAppCallback).onDestroyed( 303 SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP); 304 } 305 getMmTelDeniedTag()306 private Set<FeatureTagState> getMmTelDeniedTag() { 307 Set<FeatureTagState> deniedTags = new ArraySet<>(); 308 deniedTags.add(new FeatureTagState(ImsSignallingUtils.MMTEL_TAG, 309 SipDelegateManager.DENIED_REASON_NOT_ALLOWED)); 310 return deniedTags; 311 } 312 getSupportedTags()313 private Set<String> getSupportedTags() { 314 Set<String> supportedTags = new ArraySet<>(); 315 supportedTags.add(ImsSignallingUtils.ONE_TO_ONE_CHAT_TAG); 316 supportedTags.add(ImsSignallingUtils.GROUP_CHAT_TAG); 317 return supportedTags; 318 } 319 } 320