1 /* 2 * Copyright (C) 2015 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.systemui.statusbar.policy; 18 19 import static junit.framework.Assert.assertEquals; 20 import static junit.framework.Assert.assertNotNull; 21 22 import static org.mockito.Matchers.any; 23 import static org.mockito.Matchers.anyBoolean; 24 import static org.mockito.Matchers.anyInt; 25 import static org.mockito.Matchers.anyString; 26 import static org.mockito.Matchers.eq; 27 import static org.mockito.Matchers.isA; 28 import static org.mockito.Mockito.atLeastOnce; 29 import static org.mockito.Mockito.doAnswer; 30 import static org.mockito.Mockito.mock; 31 import static org.mockito.Mockito.when; 32 33 import android.content.Intent; 34 import android.net.ConnectivityManager; 35 import android.net.Network; 36 import android.net.NetworkCapabilities; 37 import android.net.wifi.WifiManager; 38 import android.os.Handler; 39 import android.provider.Settings; 40 import android.provider.Settings.Global; 41 import android.telephony.PhoneStateListener; 42 import android.telephony.ServiceState; 43 import android.telephony.SignalStrength; 44 import android.telephony.SubscriptionInfo; 45 import android.telephony.SubscriptionManager; 46 import android.telephony.TelephonyManager; 47 import android.testing.TestableLooper; 48 import android.util.Log; 49 50 import com.android.internal.telephony.cdma.EriInfo; 51 import com.android.settingslib.graph.SignalDrawable; 52 import com.android.settingslib.net.DataUsageController; 53 import com.android.systemui.SysuiTestCase; 54 import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener; 55 import com.android.systemui.statusbar.policy.NetworkController.IconState; 56 import com.android.systemui.statusbar.policy.NetworkController.SignalCallback; 57 import com.android.systemui.statusbar.policy.NetworkControllerImpl.Config; 58 import com.android.systemui.statusbar.policy.NetworkControllerImpl.SubscriptionDefaults; 59 60 import org.junit.Before; 61 import org.junit.Rule; 62 import org.junit.rules.TestWatcher; 63 import org.junit.runner.Description; 64 import org.mockito.ArgumentCaptor; 65 import org.mockito.Mockito; 66 67 import java.io.PrintWriter; 68 import java.io.StringWriter; 69 import java.util.ArrayList; 70 import java.util.List; 71 72 public class NetworkControllerBaseTest extends SysuiTestCase { 73 private static final String TAG = "NetworkControllerBaseTest"; 74 protected static final int DEFAULT_LEVEL = 2; 75 protected static final int DEFAULT_SIGNAL_STRENGTH = DEFAULT_LEVEL; 76 protected static final int DEFAULT_QS_SIGNAL_STRENGTH = DEFAULT_LEVEL; 77 protected static final int DEFAULT_ICON = TelephonyIcons.ICON_3G; 78 protected static final int DEFAULT_QS_ICON = TelephonyIcons.ICON_3G; 79 80 protected NetworkControllerImpl mNetworkController; 81 protected MobileSignalController mMobileSignalController; 82 protected PhoneStateListener mPhoneStateListener; 83 protected SignalStrength mSignalStrength; 84 protected ServiceState mServiceState; 85 protected ConnectivityManager mMockCm; 86 protected WifiManager mMockWm; 87 protected SubscriptionManager mMockSm; 88 protected TelephonyManager mMockTm; 89 protected Config mConfig; 90 protected CallbackHandler mCallbackHandler; 91 protected SubscriptionDefaults mMockSubDefaults; 92 protected DeviceProvisionedController mMockProvisionController; 93 protected DeviceProvisionedListener mUserCallback; 94 95 protected int mSubId; 96 97 private NetworkCapabilities mNetCapabilities; 98 private ConnectivityManager.NetworkCallback mNetworkCallback; 99 100 @Rule 101 public TestWatcher failWatcher = new TestWatcher() { 102 @Override 103 protected void failed(Throwable e, Description description) { 104 // Print out mNetworkController state if the test fails. 105 StringWriter sw = new StringWriter(); 106 PrintWriter pw = new PrintWriter(sw); 107 mNetworkController.dump(null, pw, null); 108 pw.flush(); 109 Log.d(TAG, sw.toString()); 110 } 111 }; 112 113 @Before setUp()114 public void setUp() throws Exception { 115 Settings.Global.putInt(mContext.getContentResolver(), Global.AIRPLANE_MODE_ON, 0); 116 mMockWm = mock(WifiManager.class); 117 mMockTm = mock(TelephonyManager.class); 118 mMockSm = mock(SubscriptionManager.class); 119 mMockCm = mock(ConnectivityManager.class); 120 mMockSubDefaults = mock(SubscriptionDefaults.class); 121 mNetCapabilities = new NetworkCapabilities(); 122 when(mMockCm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE)).thenReturn(true); 123 when(mMockCm.getDefaultNetworkCapabilitiesForUser(0)).thenReturn( 124 new NetworkCapabilities[] { mNetCapabilities }); 125 126 mSignalStrength = mock(SignalStrength.class); 127 mServiceState = mock(ServiceState.class); 128 129 mConfig = new Config(); 130 mConfig.hspaDataDistinguishable = true; 131 mCallbackHandler = mock(CallbackHandler.class); 132 133 mMockProvisionController = mock(DeviceProvisionedController.class); 134 when(mMockProvisionController.isUserSetup(anyInt())).thenReturn(true); 135 doAnswer(invocation -> { 136 mUserCallback = (DeviceProvisionedListener) invocation.getArguments()[0]; 137 mUserCallback.onUserSetupChanged(); 138 mUserCallback.onDeviceProvisionedChanged(); 139 TestableLooper.get(this).processAllMessages(); 140 return null; 141 }).when(mMockProvisionController).addCallback(any()); 142 143 mNetworkController = new NetworkControllerImpl(mContext, mMockCm, mMockTm, mMockWm, mMockSm, 144 mConfig, TestableLooper.get(this).getLooper(), mCallbackHandler, 145 mock(AccessPointControllerImpl.class), mock(DataUsageController.class), 146 mMockSubDefaults, mMockProvisionController); 147 setupNetworkController(); 148 149 // Trigger blank callbacks to always get the current state (some tests don't trigger 150 // changes from default state). 151 mNetworkController.addCallback(mock(SignalCallback.class)); 152 mNetworkController.addEmergencyListener(null); 153 } 154 setupNetworkController()155 protected void setupNetworkController() { 156 // For now just pretend to be the data sim, so we can test that too. 157 mSubId = SubscriptionManager.DEFAULT_SUBSCRIPTION_ID; 158 when(mMockTm.getDataEnabled(mSubId)).thenReturn(true); 159 setDefaultSubId(mSubId); 160 setSubscriptions(mSubId); 161 mMobileSignalController = mNetworkController.mMobileSignalControllers.get(mSubId); 162 mPhoneStateListener = mMobileSignalController.mPhoneStateListener; 163 164 ArgumentCaptor<ConnectivityManager.NetworkCallback> callbackArg = 165 ArgumentCaptor.forClass(ConnectivityManager.NetworkCallback.class); 166 Mockito.verify(mMockCm, atLeastOnce()) 167 .registerDefaultNetworkCallback(callbackArg.capture(), isA(Handler.class)); 168 mNetworkCallback = callbackArg.getValue(); 169 assertNotNull(mNetworkCallback); 170 } 171 setDefaultSubId(int subId)172 protected void setDefaultSubId(int subId) { 173 when(mMockSubDefaults.getDefaultDataSubId()).thenReturn(subId); 174 when(mMockSubDefaults.getDefaultVoiceSubId()).thenReturn(subId); 175 } 176 setSubscriptions(int... subIds)177 protected void setSubscriptions(int... subIds) { 178 List<SubscriptionInfo> subs = new ArrayList<SubscriptionInfo>(); 179 for (int subId : subIds) { 180 SubscriptionInfo subscription = mock(SubscriptionInfo.class); 181 when(subscription.getSubscriptionId()).thenReturn(subId); 182 subs.add(subscription); 183 } 184 when(mMockSm.getActiveSubscriptionInfoList()).thenReturn(subs); 185 mNetworkController.doUpdateMobileControllers(); 186 } 187 setUpNoMobileData()188 protected NetworkControllerImpl setUpNoMobileData() { 189 when(mMockCm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE)).thenReturn(false); 190 NetworkControllerImpl networkControllerNoMobile 191 = new NetworkControllerImpl(mContext, mMockCm, mMockTm, mMockWm, mMockSm, 192 mConfig, TestableLooper.get(this).getLooper(), mCallbackHandler, 193 mock(AccessPointControllerImpl.class), 194 mock(DataUsageController.class), mMockSubDefaults, 195 mock(DeviceProvisionedController.class)); 196 197 setupNetworkController(); 198 199 return networkControllerNoMobile; 200 201 } 202 203 // 2 Bars 3G GSM. setupDefaultSignal()204 public void setupDefaultSignal() { 205 setIsGsm(true); 206 setVoiceRegState(ServiceState.STATE_IN_SERVICE); 207 setGsmRoaming(false); 208 setLevel(DEFAULT_LEVEL); 209 updateDataConnectionState(TelephonyManager.DATA_CONNECTED, 210 TelephonyManager.NETWORK_TYPE_UMTS); 211 setConnectivityViaBroadcast( 212 NetworkCapabilities.TRANSPORT_CELLULAR, true, true); 213 } 214 setConnectivityViaBroadcast( int networkType, boolean validated, boolean isConnected)215 public void setConnectivityViaBroadcast( 216 int networkType, boolean validated, boolean isConnected) { 217 setConnectivityCommon(networkType, validated, isConnected); 218 Intent i = new Intent(ConnectivityManager.INET_CONDITION_ACTION); 219 mNetworkController.onReceive(mContext, i); 220 } 221 setConnectivityViaCallback( int networkType, boolean validated, boolean isConnected)222 public void setConnectivityViaCallback( 223 int networkType, boolean validated, boolean isConnected){ 224 setConnectivityCommon(networkType, validated, isConnected); 225 mNetworkCallback.onCapabilitiesChanged( 226 mock(Network.class), new NetworkCapabilities(mNetCapabilities)); 227 } 228 setConnectivityCommon( int networkType, boolean validated, boolean isConnected)229 private void setConnectivityCommon( 230 int networkType, boolean validated, boolean isConnected){ 231 // TODO: Separate out into several NetworkCapabilities. 232 if (isConnected) { 233 mNetCapabilities.addTransportType(networkType); 234 } else { 235 mNetCapabilities.removeTransportType(networkType); 236 } 237 if (validated) { 238 mNetCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED); 239 } else { 240 mNetCapabilities.removeCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED); 241 } 242 } 243 setGsmRoaming(boolean isRoaming)244 public void setGsmRoaming(boolean isRoaming) { 245 when(mServiceState.getRoaming()).thenReturn(isRoaming); 246 updateServiceState(); 247 } 248 setCdmaRoaming(boolean isRoaming)249 public void setCdmaRoaming(boolean isRoaming) { 250 when(mServiceState.getCdmaEriIconIndex()).thenReturn(isRoaming ? 251 EriInfo.ROAMING_INDICATOR_ON : EriInfo.ROAMING_INDICATOR_OFF); 252 when(mServiceState.getCdmaEriIconMode()).thenReturn(isRoaming ? 253 EriInfo.ROAMING_ICON_MODE_NORMAL : -1); 254 updateServiceState(); 255 } 256 setVoiceRegState(int voiceRegState)257 public void setVoiceRegState(int voiceRegState) { 258 when(mServiceState.getVoiceRegState()).thenReturn(voiceRegState); 259 updateServiceState(); 260 } 261 setDataRegState(int dataRegState)262 public void setDataRegState(int dataRegState) { 263 when(mServiceState.getDataRegState()).thenReturn(dataRegState); 264 updateServiceState(); 265 } 266 setIsEmergencyOnly(boolean isEmergency)267 public void setIsEmergencyOnly(boolean isEmergency) { 268 when(mServiceState.isEmergencyOnly()).thenReturn(isEmergency); 269 updateServiceState(); 270 } 271 setCdmaLevel(int level)272 public void setCdmaLevel(int level) { 273 when(mSignalStrength.getCdmaLevel()).thenReturn(level); 274 updateSignalStrength(); 275 } 276 setLevel(int level)277 public void setLevel(int level) { 278 when(mSignalStrength.getLevel()).thenReturn(level); 279 updateSignalStrength(); 280 } 281 setIsGsm(boolean gsm)282 public void setIsGsm(boolean gsm) { 283 when(mSignalStrength.isGsm()).thenReturn(gsm); 284 updateSignalStrength(); 285 } 286 setCdmaEri(int index, int mode)287 public void setCdmaEri(int index, int mode) { 288 // TODO: Figure this out. 289 } 290 updateSignalStrength()291 private void updateSignalStrength() { 292 Log.d(TAG, "Sending Signal Strength: " + mSignalStrength); 293 mPhoneStateListener.onSignalStrengthsChanged(mSignalStrength); 294 } 295 updateServiceState()296 protected void updateServiceState() { 297 Log.d(TAG, "Sending Service State: " + mServiceState); 298 mPhoneStateListener.onServiceStateChanged(mServiceState); 299 } 300 updateCallState(int state)301 public void updateCallState(int state) { 302 // Inputs not currently used in NetworkControllerImpl. 303 mPhoneStateListener.onCallStateChanged(state, "0123456789"); 304 } 305 updateDataConnectionState(int dataState, int dataNetType)306 public void updateDataConnectionState(int dataState, int dataNetType) { 307 when(mServiceState.getDataNetworkType()).thenReturn(dataNetType); 308 mPhoneStateListener.onDataConnectionStateChanged(dataState, dataNetType); 309 } 310 updateDataActivity(int dataActivity)311 public void updateDataActivity(int dataActivity) { 312 mPhoneStateListener.onDataActivity(dataActivity); 313 } 314 setCarrierNetworkChange(boolean enable)315 public void setCarrierNetworkChange(boolean enable) { 316 Log.d(TAG, "setCarrierNetworkChange(" + enable + ")"); 317 mPhoneStateListener.onCarrierNetworkChange(enable); 318 } 319 verifyHasNoSims(boolean hasNoSimsVisible)320 protected void verifyHasNoSims(boolean hasNoSimsVisible) { 321 Mockito.verify(mCallbackHandler, Mockito.atLeastOnce()).setNoSims( 322 eq(hasNoSimsVisible), eq(false)); 323 } 324 verifyLastQsMobileDataIndicators(boolean visible, int icon, int typeIcon, boolean dataIn, boolean dataOut)325 protected void verifyLastQsMobileDataIndicators(boolean visible, int icon, int typeIcon, 326 boolean dataIn, boolean dataOut) { 327 ArgumentCaptor<IconState> iconArg = ArgumentCaptor.forClass(IconState.class); 328 ArgumentCaptor<Integer> typeIconArg = ArgumentCaptor.forClass(Integer.class); 329 ArgumentCaptor<Boolean> dataInArg = ArgumentCaptor.forClass(Boolean.class); 330 ArgumentCaptor<Boolean> dataOutArg = ArgumentCaptor.forClass(Boolean.class); 331 332 Mockito.verify(mCallbackHandler, Mockito.atLeastOnce()).setMobileDataIndicators( 333 any(), 334 iconArg.capture(), 335 anyInt(), 336 typeIconArg.capture(), dataInArg.capture(), dataOutArg.capture(), 337 anyString(), anyString(), anyBoolean(), anyInt(), anyBoolean()); 338 IconState iconState = iconArg.getValue(); 339 int state = SignalDrawable.getState(icon, SignalStrength.NUM_SIGNAL_STRENGTH_BINS, 340 false); 341 assertEquals("Visibility in, quick settings", visible, iconState.visible); 342 assertEquals("Signal icon in, quick settings", state, iconState.icon); 343 assertEquals("Data icon in, quick settings", typeIcon, (int) typeIconArg.getValue()); 344 assertEquals("Data direction in, in quick settings", dataIn, 345 (boolean) dataInArg.getValue()); 346 assertEquals("Data direction out, in quick settings", dataOut, 347 (boolean) dataOutArg.getValue()); 348 } 349 verifyLastMobileDataIndicators(boolean visible, int icon, int typeIcon)350 protected void verifyLastMobileDataIndicators(boolean visible, int icon, int typeIcon) { 351 verifyLastMobileDataIndicators(visible, icon, typeIcon, false); 352 } 353 verifyLastMobileDataIndicators(boolean visible, int icon, int typeIcon, boolean roaming)354 protected void verifyLastMobileDataIndicators(boolean visible, int icon, int typeIcon, 355 boolean roaming) { 356 verifyLastMobileDataIndicators(visible, icon, typeIcon, roaming, true); 357 } 358 verifyLastMobileDataIndicators(boolean visible, int icon, int typeIcon, boolean roaming, boolean inet)359 protected void verifyLastMobileDataIndicators(boolean visible, int icon, int typeIcon, 360 boolean roaming, boolean inet) { 361 ArgumentCaptor<IconState> iconArg = ArgumentCaptor.forClass(IconState.class); 362 ArgumentCaptor<Integer> typeIconArg = ArgumentCaptor.forClass(Integer.class); 363 364 // TODO: Verify all fields. 365 Mockito.verify(mCallbackHandler, Mockito.atLeastOnce()).setMobileDataIndicators( 366 iconArg.capture(), 367 any(), 368 typeIconArg.capture(), 369 anyInt(), anyBoolean(), anyBoolean(), anyString(), anyString(), anyBoolean(), 370 anyInt(), eq(roaming)); 371 IconState iconState = iconArg.getValue(); 372 373 int state = icon == -1 ? 0 374 : SignalDrawable.getState(icon, SignalStrength.NUM_SIGNAL_STRENGTH_BINS, !inet); 375 assertEquals("Signal icon in status bar", state, iconState.icon); 376 assertEquals("Data icon in status bar", typeIcon, (int) typeIconArg.getValue()); 377 assertEquals("Visibility in status bar", visible, iconState.visible); 378 } 379 verifyLastMobileDataIndicators(boolean visible, int icon, int typeIcon, boolean qsVisible, int qsIcon, int qsTypeIcon, boolean dataIn, boolean dataOut)380 protected void verifyLastMobileDataIndicators(boolean visible, int icon, int typeIcon, 381 boolean qsVisible, int qsIcon, int qsTypeIcon, boolean dataIn, boolean dataOut) { 382 verifyLastMobileDataIndicators( 383 visible, icon, typeIcon, qsVisible, qsIcon, qsTypeIcon, dataIn, dataOut, false); 384 } 385 verifyLastMobileDataIndicators(boolean visible, int icon, int typeIcon, boolean qsVisible, int qsIcon, int qsTypeIcon, boolean dataIn, boolean dataOut, boolean cutOut)386 protected void verifyLastMobileDataIndicators(boolean visible, int icon, int typeIcon, 387 boolean qsVisible, int qsIcon, int qsTypeIcon, boolean dataIn, boolean dataOut, 388 boolean cutOut) { 389 ArgumentCaptor<IconState> iconArg = ArgumentCaptor.forClass(IconState.class); 390 ArgumentCaptor<Integer> typeIconArg = ArgumentCaptor.forClass(Integer.class); 391 ArgumentCaptor<IconState> qsIconArg = ArgumentCaptor.forClass(IconState.class); 392 ArgumentCaptor<Integer> qsTypeIconArg = ArgumentCaptor.forClass(Integer.class); 393 ArgumentCaptor<Boolean> dataInArg = ArgumentCaptor.forClass(Boolean.class); 394 ArgumentCaptor<Boolean> dataOutArg = ArgumentCaptor.forClass(Boolean.class); 395 396 Mockito.verify(mCallbackHandler, Mockito.atLeastOnce()).setMobileDataIndicators( 397 iconArg.capture(), 398 qsIconArg.capture(), 399 typeIconArg.capture(), 400 qsTypeIconArg.capture(), 401 dataInArg.capture(), 402 dataOutArg.capture(), 403 anyString(), anyString(), anyBoolean(), anyInt(), anyBoolean()); 404 405 IconState iconState = iconArg.getValue(); 406 407 int state = SignalDrawable.getState(icon, SignalStrength.NUM_SIGNAL_STRENGTH_BINS, 408 cutOut); 409 assertEquals("Data icon in status bar", typeIcon, (int) typeIconArg.getValue()); 410 assertEquals("Signal icon in status bar", state, iconState.icon); 411 assertEquals("Visibility in status bar", visible, iconState.visible); 412 413 iconState = qsIconArg.getValue(); 414 assertEquals("Visibility in quick settings", qsVisible, iconState.visible); 415 assertEquals("Signal icon in quick settings", state, iconState.icon); 416 assertEquals("Data icon in quick settings", qsTypeIcon, (int) qsTypeIconArg.getValue()); 417 assertEquals("Data direction in in quick settings", dataIn, 418 (boolean) dataInArg.getValue()); 419 assertEquals("Data direction out in quick settings", dataOut, 420 (boolean) dataOutArg.getValue()); 421 } 422 assertNetworkNameEquals(String expected)423 protected void assertNetworkNameEquals(String expected) { 424 assertEquals("Network name", expected, mMobileSignalController.getState().networkName); 425 } 426 } 427