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