1 /* 2 * Copyright (C) 2024 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.domainselection; 18 19 import static android.telephony.AccessNetworkConstants.TRANSPORT_TYPE_WWAN; 20 21 import static junit.framework.Assert.assertFalse; 22 import static junit.framework.Assert.assertTrue; 23 import static junit.framework.Assert.assertNotNull; 24 25 import static org.mockito.ArgumentMatchers.any; 26 import static org.mockito.ArgumentMatchers.anyInt; 27 import static org.mockito.ArgumentMatchers.eq; 28 import static org.mockito.Mockito.doReturn; 29 import static org.mockito.Mockito.never; 30 import static org.mockito.Mockito.times; 31 import static org.mockito.Mockito.verify; 32 33 import android.content.BroadcastReceiver; 34 import android.content.Context; 35 import android.content.Intent; 36 import android.content.IntentFilter; 37 import android.net.LinkProperties; 38 import android.os.HandlerThread; 39 import android.os.Looper; 40 import android.telephony.CarrierConfigManager; 41 import android.telephony.PreciseDataConnectionState; 42 import android.telephony.SubscriptionManager; 43 import android.telephony.TelephonyCallback; 44 import android.telephony.TelephonyManager; 45 import android.telephony.data.ApnSetting; 46 import android.testing.TestableLooper; 47 import android.util.Log; 48 49 import com.android.TestContext; 50 51 import org.junit.After; 52 import org.junit.Before; 53 import org.junit.Test; 54 import org.mockito.ArgumentCaptor; 55 import org.mockito.Mock; 56 import org.mockito.MockitoAnnotations; 57 58 import java.util.concurrent.Executor; 59 60 /** 61 * Unit tests for DataConnectionStateHelper 62 */ 63 public class DataConnectionStateHelperTest { 64 private static final String TAG = "DataConnectionStateHelperTest"; 65 66 private static final int SLOT_0 = 0; 67 private static final int SLOT_1 = 1; 68 private static final int SUB_1 = 1; 69 private static final int SUB_2 = 2; 70 71 @Mock private TelephonyManager mTm1; 72 @Mock private TelephonyManager mTm2; 73 @Mock private EmergencyCallDomainSelector mDomainSelector; 74 75 private Context mContext; 76 private HandlerThread mHandlerThread; 77 private TestableLooper mLooper; 78 private DataConnectionStateHelper mEpdnHelper; 79 private CarrierConfigManager mCarrierConfigManager; 80 private TelephonyManager mTelephonyManager; 81 82 @Before setUp()83 public void setUp() throws Exception { 84 MockitoAnnotations.initMocks(this); 85 mContext = new TestContext() { 86 private Intent mIntent; 87 88 @Override 89 public String getSystemServiceName(Class<?> serviceClass) { 90 if (serviceClass == TelephonyManager.class) { 91 return Context.TELEPHONY_SERVICE; 92 } else if (serviceClass == CarrierConfigManager.class) { 93 return Context.CARRIER_CONFIG_SERVICE; 94 } 95 return super.getSystemServiceName(serviceClass); 96 } 97 98 @Override 99 public String getOpPackageName() { 100 return ""; 101 } 102 103 @Override 104 public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) { 105 return mIntent; 106 } 107 108 @Override 109 public void sendStickyBroadcast(Intent intent) { 110 mIntent = intent; 111 } 112 }; 113 114 if (Looper.myLooper() == null) { 115 Looper.prepare(); 116 } 117 118 mHandlerThread = new HandlerThread("DataConnectionStateHelperTest"); 119 mHandlerThread.start(); 120 121 try { 122 mLooper = new TestableLooper(mHandlerThread.getLooper()); 123 } catch (Exception e) { 124 logd("Unable to create looper from handler."); 125 } 126 127 mCarrierConfigManager = mContext.getSystemService(CarrierConfigManager.class); 128 mTelephonyManager = mContext.getSystemService(TelephonyManager.class); 129 doReturn(mTm1).when(mTelephonyManager).createForSubscriptionId(eq(SUB_1)); 130 doReturn(mTm2).when(mTelephonyManager).createForSubscriptionId(eq(SUB_2)); 131 132 mEpdnHelper = new DataConnectionStateHelper(mContext, mHandlerThread.getLooper()); 133 mEpdnHelper.setEmergencyCallDomainSelector(mDomainSelector); 134 } 135 136 @After tearDown()137 public void tearDown() throws Exception { 138 if (mEpdnHelper != null) { 139 mEpdnHelper.destroy(); 140 mEpdnHelper = null; 141 } 142 143 if (mLooper != null) { 144 mLooper.destroy(); 145 mLooper = null; 146 } 147 } 148 149 @Test testInit()150 public void testInit() throws Exception { 151 ArgumentCaptor<CarrierConfigManager.CarrierConfigChangeListener> callbackCaptor = 152 ArgumentCaptor.forClass(CarrierConfigManager.CarrierConfigChangeListener.class); 153 ArgumentCaptor<Executor> executorCaptor = ArgumentCaptor.forClass(Executor.class); 154 155 verify(mCarrierConfigManager).registerCarrierConfigChangeListener(executorCaptor.capture(), 156 callbackCaptor.capture()); 157 assertNotNull(executorCaptor.getValue()); 158 assertNotNull(callbackCaptor.getValue()); 159 } 160 161 @Test testCarrierConfigChanged()162 public void testCarrierConfigChanged() throws Exception { 163 ArgumentCaptor<CarrierConfigManager.CarrierConfigChangeListener> callbackCaptor = 164 ArgumentCaptor.forClass(CarrierConfigManager.CarrierConfigChangeListener.class); 165 166 verify(mCarrierConfigManager).registerCarrierConfigChangeListener(any(), 167 callbackCaptor.capture()); 168 169 CarrierConfigManager.CarrierConfigChangeListener callback = callbackCaptor.getValue(); 170 171 assertNotNull(callback); 172 173 callback.onCarrierConfigChanged(SLOT_0, SUB_1, 0, 0); 174 175 verify(mTelephonyManager).createForSubscriptionId(eq(SUB_1)); 176 177 ArgumentCaptor<TelephonyCallback> telephonyCallbackCaptor1 = 178 ArgumentCaptor.forClass(TelephonyCallback.class); 179 180 // TelephonyCallback for SUB_1 registered 181 verify(mTm1).registerTelephonyCallback(any(), telephonyCallbackCaptor1.capture()); 182 183 assertNotNull(telephonyCallbackCaptor1.getValue()); 184 185 callback.onCarrierConfigChanged(SLOT_1, SUB_2, 0, 0); 186 187 verify(mTelephonyManager).createForSubscriptionId(eq(SUB_2)); 188 189 ArgumentCaptor<TelephonyCallback> telephonyCallbackCaptor2 = 190 ArgumentCaptor.forClass(TelephonyCallback.class); 191 192 // TelephonyCallback for SUB_2 registered 193 verify(mTm2).registerTelephonyCallback(any(), telephonyCallbackCaptor2.capture()); 194 195 assertNotNull(telephonyCallbackCaptor2.getValue()); 196 197 verify(mTm1, never()).unregisterTelephonyCallback(any()); 198 verify(mTm2, never()).unregisterTelephonyCallback(any()); 199 } 200 201 @Test testSubscriptionChangedOnTheSameSlot()202 public void testSubscriptionChangedOnTheSameSlot() throws Exception { 203 ArgumentCaptor<CarrierConfigManager.CarrierConfigChangeListener> callbackCaptor = 204 ArgumentCaptor.forClass(CarrierConfigManager.CarrierConfigChangeListener.class); 205 206 verify(mCarrierConfigManager).registerCarrierConfigChangeListener(any(), 207 callbackCaptor.capture()); 208 209 CarrierConfigManager.CarrierConfigChangeListener callback = callbackCaptor.getValue(); 210 211 assertNotNull(callback); 212 213 callback.onCarrierConfigChanged(SLOT_0, SUB_1, 0, 0); 214 215 verify(mTelephonyManager).createForSubscriptionId(eq(SUB_1)); 216 217 ArgumentCaptor<TelephonyCallback> telephonyCallbackCaptor1 = 218 ArgumentCaptor.forClass(TelephonyCallback.class); 219 220 // TelephonyCallback for SUB_1 registered 221 verify(mTm1).registerTelephonyCallback(any(), telephonyCallbackCaptor1.capture()); 222 223 TelephonyCallback telephonyCallback1 = telephonyCallbackCaptor1.getValue(); 224 225 assertNotNull(telephonyCallback1); 226 227 // Subscription changed 228 callback.onCarrierConfigChanged(SLOT_0, SUB_2, 0, 0); 229 230 // TelephonyCallback for SUB_1 unregistered 231 verify(mTelephonyManager).unregisterTelephonyCallback(eq(telephonyCallback1)); 232 233 verify(mTelephonyManager).createForSubscriptionId(eq(SUB_2)); 234 235 ArgumentCaptor<TelephonyCallback> telephonyCallbackCaptor2 = 236 ArgumentCaptor.forClass(TelephonyCallback.class); 237 238 // TelephonyCallback for SUB_2 registered 239 verify(mTm2).registerTelephonyCallback(any(), telephonyCallbackCaptor2.capture()); 240 241 TelephonyCallback telephonyCallback2 = telephonyCallbackCaptor2.getValue(); 242 243 assertNotNull(telephonyCallback2); 244 } 245 246 @Test testDataConnectionStateChanged()247 public void testDataConnectionStateChanged() throws Exception { 248 ArgumentCaptor<CarrierConfigManager.CarrierConfigChangeListener> callbackCaptor = 249 ArgumentCaptor.forClass(CarrierConfigManager.CarrierConfigChangeListener.class); 250 251 verify(mCarrierConfigManager).registerCarrierConfigChangeListener(any(), 252 callbackCaptor.capture()); 253 254 CarrierConfigManager.CarrierConfigChangeListener callback = callbackCaptor.getValue(); 255 256 assertNotNull(callback); 257 258 callback.onCarrierConfigChanged(SLOT_0, SUB_1, 0, 0); 259 260 verify(mTelephonyManager).createForSubscriptionId(eq(SUB_1)); 261 262 ArgumentCaptor<TelephonyCallback> telephonyCallbackCaptor1 = 263 ArgumentCaptor.forClass(TelephonyCallback.class); 264 265 // TelephonyCallback for SUB_1 registered 266 verify(mTm1).registerTelephonyCallback(any(), telephonyCallbackCaptor1.capture()); 267 268 TelephonyCallback cb1 = telephonyCallbackCaptor1.getValue(); 269 270 assertNotNull(cb1); 271 assertTrue(cb1 instanceof TelephonyCallback.PreciseDataConnectionStateListener); 272 273 callback.onCarrierConfigChanged(SLOT_1, SUB_2, 0, 0); 274 275 verify(mTelephonyManager).createForSubscriptionId(eq(SUB_2)); 276 277 ArgumentCaptor<TelephonyCallback> telephonyCallbackCaptor2 = 278 ArgumentCaptor.forClass(TelephonyCallback.class); 279 280 // TelephonyCallback for SUB_2 registered 281 verify(mTm2).registerTelephonyCallback(any(), telephonyCallbackCaptor2.capture()); 282 283 TelephonyCallback cb2 = telephonyCallbackCaptor2.getValue(); 284 285 assertNotNull(cb2); 286 assertTrue(cb2 instanceof TelephonyCallback.PreciseDataConnectionStateListener); 287 288 TelephonyCallback.PreciseDataConnectionStateListener listener1 = 289 (TelephonyCallback.PreciseDataConnectionStateListener) cb1; 290 TelephonyCallback.PreciseDataConnectionStateListener listener2 = 291 (TelephonyCallback.PreciseDataConnectionStateListener) cb2; 292 293 PreciseDataConnectionState state = getPreciseDataConnectionState( 294 ApnSetting.TYPE_DEFAULT, TelephonyManager.DATA_CONNECTED); 295 listener1.onPreciseDataConnectionStateChanged(state); 296 listener2.onPreciseDataConnectionStateChanged(state); 297 298 verify(mDomainSelector, never()).notifyDataConnectionStateChange(anyInt(), anyInt()); 299 verify(mDomainSelector, never()).notifyDataConnectionStateChange(anyInt(), anyInt()); 300 301 state = getPreciseDataConnectionState( 302 ApnSetting.TYPE_EMERGENCY, TelephonyManager.DATA_CONNECTED); 303 listener1.onPreciseDataConnectionStateChanged(state); 304 listener2.onPreciseDataConnectionStateChanged(state); 305 306 verify(mDomainSelector, times(1)).notifyDataConnectionStateChange( 307 eq(SLOT_0), eq(TelephonyManager.DATA_CONNECTED)); 308 verify(mDomainSelector, times(1)).notifyDataConnectionStateChange( 309 eq(SLOT_1), eq(TelephonyManager.DATA_CONNECTED)); 310 311 state = getPreciseDataConnectionState( 312 ApnSetting.TYPE_EMERGENCY, TelephonyManager.DATA_DISCONNECTING); 313 listener1.onPreciseDataConnectionStateChanged(state); 314 listener2.onPreciseDataConnectionStateChanged(state); 315 316 verify(mDomainSelector, times(1)).notifyDataConnectionStateChange( 317 eq(SLOT_0), eq(TelephonyManager.DATA_DISCONNECTING)); 318 verify(mDomainSelector, times(1)).notifyDataConnectionStateChange( 319 eq(SLOT_1), eq(TelephonyManager.DATA_DISCONNECTING)); 320 321 state = getPreciseDataConnectionState( 322 ApnSetting.TYPE_EMERGENCY, TelephonyManager.DATA_DISCONNECTED); 323 listener1.onPreciseDataConnectionStateChanged(state); 324 listener2.onPreciseDataConnectionStateChanged(state); 325 326 verify(mDomainSelector, times(1)).notifyDataConnectionStateChange( 327 eq(SLOT_0), eq(TelephonyManager.DATA_DISCONNECTED)); 328 verify(mDomainSelector, times(1)).notifyDataConnectionStateChange( 329 eq(SLOT_1), eq(TelephonyManager.DATA_DISCONNECTED)); 330 } 331 332 @Test testEmergencyCallbackModeEnter()333 public void testEmergencyCallbackModeEnter() throws Exception { 334 // Enter ECBM on slot 1 335 mContext.sendStickyBroadcast(getIntent(true, SLOT_1)); 336 337 assertFalse(mEpdnHelper.isInEmergencyCallbackMode(SLOT_0)); 338 assertTrue(mEpdnHelper.isInEmergencyCallbackMode(SLOT_1)); 339 } 340 341 @Test testEmergencyCallbackModeExit()342 public void testEmergencyCallbackModeExit() throws Exception { 343 // Exit ECBM 344 mContext.sendStickyBroadcast(getIntent(false, SLOT_0)); 345 346 assertFalse(mEpdnHelper.isInEmergencyCallbackMode(SLOT_0)); 347 } 348 getIntent(boolean inEcm, int slotIndex)349 private static Intent getIntent(boolean inEcm, int slotIndex) { 350 Intent intent = new Intent(TelephonyManager.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED); 351 intent.putExtra(TelephonyManager.EXTRA_PHONE_IN_ECM_STATE, inEcm); 352 intent.putExtra(SubscriptionManager.EXTRA_SLOT_INDEX, slotIndex); 353 return intent; 354 } 355 getPreciseDataConnectionState( int apnType, int state)356 private static PreciseDataConnectionState getPreciseDataConnectionState( 357 int apnType, int state) { 358 return new PreciseDataConnectionState.Builder() 359 .setTransportType(TRANSPORT_TYPE_WWAN) 360 .setId(1) 361 .setState(state) 362 .setNetworkType(TelephonyManager.NETWORK_TYPE_LTE) 363 .setApnSetting(new ApnSetting.Builder() 364 .setApnTypeBitmask(apnType) 365 .setApnName("default") 366 .setEntryName("default") 367 .build()) 368 .setLinkProperties(new LinkProperties()) 369 .setFailCause(0) 370 .build(); 371 } 372 logd(String str)373 private static void logd(String str) { 374 Log.d(TAG, str); 375 } 376 } 377