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.mockito.ArgumentMatchers.any; 20 import static org.mockito.ArgumentMatchers.anyInt; 21 import static org.mockito.ArgumentMatchers.eq; 22 import static org.mockito.Mockito.doReturn; 23 import static org.mockito.Mockito.never; 24 import static org.mockito.Mockito.spy; 25 import static org.mockito.Mockito.times; 26 import static org.mockito.Mockito.verify; 27 28 import android.app.PropertyInvalidatedCache; 29 import android.content.BroadcastReceiver; 30 import android.content.Intent; 31 import android.os.PersistableBundle; 32 import android.telephony.CarrierConfigManager; 33 import android.telephony.SubscriptionManager; 34 import android.telephony.TelephonyManager; 35 36 import androidx.test.runner.AndroidJUnit4; 37 38 import com.android.TelephonyTestBase; 39 import com.android.ims.FeatureConnector; 40 import com.android.ims.RcsFeatureManager; 41 import com.android.internal.telephony.ISub; 42 import com.android.internal.telephony.flags.FeatureFlags; 43 44 import org.junit.After; 45 import org.junit.Before; 46 import org.junit.Test; 47 import org.junit.runner.RunWith; 48 import org.mockito.ArgumentCaptor; 49 import org.mockito.Captor; 50 import org.mockito.Mock; 51 52 @RunWith(AndroidJUnit4.class) 53 public class TelephonyRcsServiceTest extends TelephonyTestBase { 54 55 @Captor ArgumentCaptor<BroadcastReceiver> mReceiverCaptor; 56 @Mock TelephonyRcsService.FeatureFactory mFeatureFactory; 57 @Mock TelephonyRcsService.ResourceProxy mResourceProxy; 58 @Mock UceControllerManager mMockUceSlot0; 59 @Mock UceControllerManager mMockUceSlot1; 60 @Mock SipTransportController mMockSipTransportSlot0; 61 @Mock SipTransportController mMockSipTransportSlot1; 62 @Mock RcsFeatureController.RegistrationHelperFactory mRegistrationFactory; 63 @Mock RcsFeatureController.FeatureConnectorFactory<RcsFeatureManager> mFeatureConnectorFactory; 64 @Mock FeatureConnector<RcsFeatureManager> mFeatureConnector; 65 66 @Mock 67 private ISub mISub; 68 69 @Mock 70 private TelephonyManager mTelephonyManager; 71 72 @Mock FeatureFlags mFeatureFlags; 73 74 private RcsFeatureController mFeatureControllerSlot0; 75 private RcsFeatureController mFeatureControllerSlot1; 76 77 @Before setUp()78 public void setUp() throws Exception { 79 super.setUp(); 80 TelephonyManager.setupISubForTest(mISub); 81 TelephonyManager.enableServiceHandleCaching(); 82 PropertyInvalidatedCache.disableForTestMode(); 83 84 //set up default slot-> sub ID mappings. 85 setSlotToSubIdMapping(0 /*slotId*/, 1/*subId*/); 86 setSlotToSubIdMapping(1 /*slotId*/, 2/*subId*/); 87 88 doReturn(mFeatureConnector).when(mFeatureConnectorFactory).create(any(), anyInt(), 89 any(), any(), any()); 90 mFeatureControllerSlot0 = createFeatureController(0 /*slotId*/, 1 /*subId*/); 91 mFeatureControllerSlot1 = createFeatureController(1 /*slotId*/, 2 /*subId*/); 92 doReturn(mFeatureControllerSlot0).when(mFeatureFactory).createController(any(), eq(0), 93 anyInt()); 94 doReturn(mFeatureControllerSlot1).when(mFeatureFactory).createController(any(), eq(1), 95 anyInt()); 96 doReturn(mMockUceSlot0).when(mFeatureFactory).createUceControllerManager(any(), eq(0), 97 anyInt(), any()); 98 doReturn(mMockUceSlot1).when(mFeatureFactory).createUceControllerManager(any(), eq(1), 99 anyInt(), any()); 100 doReturn(mMockSipTransportSlot0).when(mFeatureFactory).createSipTransportController(any(), 101 eq(0), anyInt()); 102 doReturn(mMockSipTransportSlot1).when(mFeatureFactory).createSipTransportController(any(), 103 eq(1), anyInt()); 104 doReturn(true).when(mResourceProxy).getDeviceUceEnabled(any()); 105 106 replaceInstance(TelephonyManager.class, "sInstance", null, mTelephonyManager); 107 doReturn(2).when(mTelephonyManager).getActiveModemCount(); 108 } 109 110 @After tearDown()111 public void tearDown() throws Exception { 112 super.tearDown(); 113 } 114 115 @Test testUceControllerPresenceConnected()116 public void testUceControllerPresenceConnected() { 117 setCarrierConfig(1 /*subId*/, 118 CarrierConfigManager.Ims.KEY_ENABLE_PRESENCE_PUBLISH_BOOL, 119 true /*isEnabled*/); 120 createRcsService(1 /*numSlots*/); 121 verify(mFeatureControllerSlot0).addFeature(mMockUceSlot0, UceControllerManager.class); 122 verify(mFeatureControllerSlot0).connect(); 123 } 124 125 @Test testUceControllerOptionsConnected()126 public void testUceControllerOptionsConnected() { 127 setCarrierConfig(1 /*subId*/, CarrierConfigManager.KEY_USE_RCS_SIP_OPTIONS_BOOL, 128 true /*isEnabled*/); 129 createRcsService(1 /*numSlots*/); 130 verify(mFeatureControllerSlot0).addFeature(mMockUceSlot0, UceControllerManager.class); 131 verify(mFeatureControllerSlot0).connect(); 132 } 133 134 @Test testNoFeaturesEnabled()135 public void testNoFeaturesEnabled() { 136 createRcsService(1 /*numSlots*/); 137 // No carrier config set for UCE. 138 verify(mFeatureControllerSlot0, never()).addFeature(mMockUceSlot0, 139 UceControllerManager.class); 140 verify(mFeatureControllerSlot0, never()).connect(); 141 } 142 143 @Test testSipTransportConnected()144 public void testSipTransportConnected() { 145 createRcsService(1 /*numSlots*/); 146 verify(mFeatureControllerSlot0, never()).addFeature(mMockSipTransportSlot0, 147 SipTransportController.class); 148 verify(mFeatureControllerSlot0, never()).connect(); 149 150 151 // Send carrier config update for each slot. 152 setCarrierConfig(1 /*subId*/, 153 CarrierConfigManager.Ims.KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL, 154 true /*isEnabled*/); 155 sendCarrierConfigChanged(0 /*slotId*/, 1 /*subId*/); 156 verify(mFeatureControllerSlot0).addFeature(mMockSipTransportSlot0, 157 SipTransportController.class); 158 verify(mFeatureControllerSlot0).connect(); 159 verify(mFeatureControllerSlot0).updateAssociatedSubscription(1); 160 } 161 162 @Test testSipTransportConnectedOneSlot()163 public void testSipTransportConnectedOneSlot() { 164 createRcsService(2 /*numSlots*/); 165 verify(mFeatureControllerSlot0, never()).addFeature(mMockSipTransportSlot0, 166 SipTransportController.class); 167 verify(mFeatureControllerSlot0, never()).connect(); 168 verify(mFeatureControllerSlot0, never()).addFeature(mMockSipTransportSlot1, 169 SipTransportController.class); 170 verify(mFeatureControllerSlot1, never()).connect(); 171 172 173 // Send carrier config update for slot 0 only 174 setCarrierConfig(1 /*subId*/, 175 CarrierConfigManager.Ims.KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL, 176 true /*isEnabled*/); 177 setCarrierConfig(2 /*subId*/, 178 CarrierConfigManager.Ims.KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL, 179 false /*isEnabled*/); 180 sendCarrierConfigChanged(0 /*slotId*/, 1 /*subId*/); 181 sendCarrierConfigChanged(1 /*slotId*/, 2 /*subId*/); 182 verify(mFeatureControllerSlot0).addFeature(mMockSipTransportSlot0, 183 SipTransportController.class); 184 verify(mFeatureControllerSlot1, never()).addFeature(mMockSipTransportSlot0, 185 SipTransportController.class); 186 verify(mFeatureControllerSlot0).connect(); 187 verify(mFeatureControllerSlot1, never()).connect(); 188 verify(mFeatureControllerSlot0).updateAssociatedSubscription(1); 189 verify(mFeatureControllerSlot1, never()).updateAssociatedSubscription(1); 190 } 191 192 @Test testNoFeaturesEnabledCarrierConfigChanged()193 public void testNoFeaturesEnabledCarrierConfigChanged() { 194 createRcsService(1 /*numSlots*/); 195 // No carrier config set for UCE. 196 197 sendCarrierConfigChanged(0, SubscriptionManager.INVALID_SUBSCRIPTION_ID); 198 verify(mFeatureControllerSlot0, never()).addFeature(mMockUceSlot0, 199 UceControllerManager.class); 200 verify(mFeatureControllerSlot0, never()).connect(); 201 verify(mFeatureControllerSlot0, never()).updateAssociatedSubscription(anyInt()); 202 } 203 204 205 @Test testSlotUpdates()206 public void testSlotUpdates() { 207 setCarrierConfig(1 /*subId*/, 208 CarrierConfigManager.Ims.KEY_ENABLE_PRESENCE_PUBLISH_BOOL, 209 true /*isEnabled*/); 210 setCarrierConfig(2 /*subId*/, 211 CarrierConfigManager.Ims.KEY_ENABLE_PRESENCE_PUBLISH_BOOL, 212 true /*isEnabled*/); 213 TelephonyRcsService service = createRcsService(1 /*numSlots*/); 214 verify(mFeatureControllerSlot0).addFeature(mMockUceSlot0, UceControllerManager.class); 215 verify(mFeatureControllerSlot0).connect(); 216 217 // there should be no changes if the new num slots = old num 218 service.updateFeatureControllerSize(1 /*newNumSlots*/); 219 verify(mFeatureControllerSlot0, times(1)).addFeature(mMockUceSlot0, 220 UceControllerManager.class); 221 verify(mFeatureControllerSlot0, times(1)).connect(); 222 223 // Add a new slot. 224 verify(mFeatureControllerSlot1, never()).addFeature(mMockUceSlot1, 225 UceControllerManager.class); 226 verify(mFeatureControllerSlot1, never()).connect(); 227 service.updateFeatureControllerSize(2 /*newNumSlots*/); 228 // This shouldn't have changed for slot 0. 229 verify(mFeatureControllerSlot0, times(1)).addFeature(mMockUceSlot0, 230 UceControllerManager.class); 231 verify(mFeatureControllerSlot0, times(1)).connect(); 232 verify(mFeatureControllerSlot1).addFeature(mMockUceSlot1, UceControllerManager.class); 233 verify(mFeatureControllerSlot1, times(1)).connect(); 234 235 // Remove a slot. 236 verify(mFeatureControllerSlot0, never()).destroy(); 237 verify(mFeatureControllerSlot1, never()).destroy(); 238 service.updateFeatureControllerSize(1 /*newNumSlots*/); 239 // addFeature/connect shouldn't have been called again 240 verify(mFeatureControllerSlot0, times(1)).addFeature(mMockUceSlot0, 241 UceControllerManager.class); 242 verify(mFeatureControllerSlot0, times(1)).connect(); 243 verify(mFeatureControllerSlot1, times(1)).addFeature(mMockUceSlot1, 244 UceControllerManager.class); 245 verify(mFeatureControllerSlot1, times(1)).connect(); 246 // Verify destroy is only called for slot 1. 247 verify(mFeatureControllerSlot0, never()).destroy(); 248 verify(mFeatureControllerSlot1, times(1)).destroy(); 249 } 250 251 @Test testCarrierConfigUpdateAssociatedSub()252 public void testCarrierConfigUpdateAssociatedSub() { 253 setCarrierConfig(1 /*subId*/, 254 CarrierConfigManager.Ims.KEY_ENABLE_PRESENCE_PUBLISH_BOOL, 255 true /*isEnabled*/); 256 setCarrierConfig(2 /*subId*/, 257 CarrierConfigManager.Ims.KEY_ENABLE_PRESENCE_PUBLISH_BOOL, 258 true /*isEnabled*/); 259 createRcsService(2 /*numSlots*/); 260 verify(mFeatureControllerSlot0).addFeature(mMockUceSlot0, UceControllerManager.class); 261 verify(mFeatureControllerSlot1).addFeature(mMockUceSlot1, UceControllerManager.class); 262 verify(mFeatureControllerSlot0).connect(); 263 verify(mFeatureControllerSlot1).connect(); 264 265 266 // Send carrier config update for each slot. 267 sendCarrierConfigChanged(0 /*slotId*/, 1 /*subId*/); 268 verify(mFeatureControllerSlot0).updateAssociatedSubscription(1); 269 verify(mFeatureControllerSlot1, never()).updateAssociatedSubscription(1); 270 sendCarrierConfigChanged(1 /*slotId*/, 2 /*subId*/); 271 verify(mFeatureControllerSlot0, never()).updateAssociatedSubscription(2); 272 verify(mFeatureControllerSlot1, times(1)).updateAssociatedSubscription(2); 273 } 274 275 @Test testCarrierConfigNotifyFeatures()276 public void testCarrierConfigNotifyFeatures() { 277 setCarrierConfig(1 /*subId*/, 278 CarrierConfigManager.Ims.KEY_ENABLE_PRESENCE_PUBLISH_BOOL, 279 true /*isEnabled*/); 280 createRcsService(1 /*numSlots*/); 281 verify(mFeatureControllerSlot0).addFeature(mMockUceSlot0, UceControllerManager.class); 282 verify(mFeatureControllerSlot0).connect(); 283 284 285 // Send carrier config update twice with no update to subId 286 sendCarrierConfigChanged(0 /*slotId*/, 1 /*subId*/); 287 verify(mFeatureControllerSlot0).updateAssociatedSubscription(1); 288 verify(mFeatureControllerSlot0, never()).onCarrierConfigChangedForSubscription(); 289 sendCarrierConfigChanged(0 /*slotId*/, 1 /*subId*/); 290 verify(mFeatureControllerSlot0, times(1)).updateAssociatedSubscription(1); 291 // carrier config changed should be sent here 292 verify(mFeatureControllerSlot0).onCarrierConfigChangedForSubscription(); 293 } 294 295 @Test testCarrierConfigUpdateUceToNoUce()296 public void testCarrierConfigUpdateUceToNoUce() { 297 setCarrierConfig(1 /*subId*/, 298 CarrierConfigManager.Ims.KEY_ENABLE_PRESENCE_PUBLISH_BOOL, 299 true /*isEnabled*/); 300 createRcsService(1 /*numSlots*/); 301 verify(mFeatureControllerSlot0).addFeature(mMockUceSlot0, UceControllerManager.class); 302 verify(mFeatureControllerSlot0).connect(); 303 304 305 // Send carrier config update for each slot. 306 setCarrierConfig(1 /*subId*/, 307 CarrierConfigManager.Ims.KEY_ENABLE_PRESENCE_PUBLISH_BOOL, 308 false /*isEnabled*/); 309 sendCarrierConfigChanged(0 /*slotId*/, 1 /*subId*/); 310 verify(mFeatureControllerSlot0).removeFeature(UceControllerManager.class); 311 verify(mFeatureControllerSlot0).updateAssociatedSubscription(1); 312 } 313 314 @Test testCarrierConfigUpdateTransportToNoTransport()315 public void testCarrierConfigUpdateTransportToNoTransport() { 316 setCarrierConfig(1 /*subId*/, 317 CarrierConfigManager.Ims.KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL, 318 true /*isEnabled*/); 319 createRcsService(1 /*numSlots*/); 320 verify(mFeatureControllerSlot0).addFeature(mMockSipTransportSlot0, 321 SipTransportController.class); 322 verify(mFeatureControllerSlot0).connect(); 323 324 325 // Send carrier config update for each slot. 326 setCarrierConfig(1 /*subId*/, 327 CarrierConfigManager.Ims.KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL, 328 false /*isEnabled*/); 329 sendCarrierConfigChanged(0 /*slotId*/, 1 /*subId*/); 330 verify(mFeatureControllerSlot0).removeFeature(SipTransportController.class); 331 verify(mFeatureControllerSlot0).updateAssociatedSubscription(1); 332 } 333 334 @Test testCarrierConfigUpdateNoUceToUce()335 public void testCarrierConfigUpdateNoUceToUce() { 336 createRcsService(1 /*numSlots*/); 337 verify(mFeatureControllerSlot0, never()).addFeature(mMockUceSlot0, 338 UceControllerManager.class); 339 verify(mFeatureControllerSlot0, never()).connect(); 340 341 342 // Send carrier config update for each slot. 343 setCarrierConfig(1 /*subId*/, 344 CarrierConfigManager.Ims.KEY_ENABLE_PRESENCE_PUBLISH_BOOL, 345 true /*isEnabled*/); 346 sendCarrierConfigChanged(0 /*slotId*/, 1 /*subId*/); 347 verify(mFeatureControllerSlot0).addFeature(mMockUceSlot0, UceControllerManager.class); 348 verify(mFeatureControllerSlot0).connect(); 349 verify(mFeatureControllerSlot0).updateAssociatedSubscription(1); 350 } 351 sendCarrierConfigChanged(int slotId, int subId)352 private void sendCarrierConfigChanged(int slotId, int subId) { 353 Intent intent = new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED); 354 intent.putExtra(CarrierConfigManager.EXTRA_SLOT_INDEX, slotId); 355 intent.putExtra(CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX, subId); 356 mReceiverCaptor.getValue().onReceive(mContext, intent); 357 } 358 setCarrierConfig(int subId, String key, boolean value)359 private void setCarrierConfig(int subId, String key, boolean value) { 360 PersistableBundle bundle = mContext.getCarrierConfig(subId); 361 bundle.putBoolean(key, value); 362 } 363 setSlotToSubIdMapping(int slotId, int loadedSubId)364 private void setSlotToSubIdMapping(int slotId, int loadedSubId) throws Exception { 365 doReturn(loadedSubId).when(mISub).getSubId(slotId); 366 } 367 createRcsService(int numSlots)368 private TelephonyRcsService createRcsService(int numSlots) { 369 TelephonyRcsService service = new TelephonyRcsService(mContext, numSlots, mResourceProxy, 370 mFeatureFlags); 371 service.setFeatureFactory(mFeatureFactory); 372 service.initialize(); 373 verify(mContext).registerReceiver(mReceiverCaptor.capture(), any()); 374 return service; 375 } 376 createFeatureController(int slotId, int subId)377 private RcsFeatureController createFeatureController(int slotId, int subId) { 378 // Create a spy instead of a mock because TelephonyRcsService relies on state provided by 379 // RcsFeatureController. 380 RcsFeatureController controller = spy(new RcsFeatureController(mContext, slotId, subId, 381 mRegistrationFactory)); 382 controller.setFeatureConnectorFactory(mFeatureConnectorFactory); 383 return controller; 384 } 385 } 386