1package com.android.systemui.statusbar.policy; 2 3import android.content.Intent; 4import android.net.NetworkBadging; 5import android.net.NetworkCapabilities; 6import android.net.NetworkInfo; 7import android.net.NetworkKey; 8import android.net.RssiCurve; 9import android.net.ScoredNetwork; 10import android.net.WifiKey; 11import android.net.wifi.WifiInfo; 12import android.net.wifi.WifiManager; 13import android.net.wifi.WifiNetworkScoreCache; 14import android.os.Bundle; 15import android.provider.Settings; 16import android.support.test.runner.AndroidJUnit4; 17import android.test.suitebuilder.annotation.SmallTest; 18 19import com.android.settingslib.Utils; 20import com.android.systemui.statusbar.policy.NetworkController.IconState; 21 22import org.junit.Test; 23import org.junit.runner.RunWith; 24import org.mockito.ArgumentCaptor; 25import org.mockito.Matchers; 26import org.mockito.Mockito; 27import org.mockito.invocation.InvocationOnMock; 28import org.mockito.stubbing.Answer; 29 30import static junit.framework.Assert.assertEquals; 31 32import static org.mockito.Matchers.any; 33import static org.mockito.Matchers.anyBoolean; 34import static org.mockito.Matchers.anyInt; 35import static org.mockito.Mockito.doAnswer; 36import static org.mockito.Mockito.mock; 37import static org.mockito.Mockito.verify; 38import static org.mockito.Mockito.when; 39 40import java.util.Arrays; 41import java.util.ArrayList; 42import java.util.List; 43import java.util.concurrent.CountDownLatch; 44import java.util.concurrent.TimeUnit; 45 46@SmallTest 47@RunWith(AndroidJUnit4.class) 48public class NetworkControllerWifiTest extends NetworkControllerBaseTest { 49 // These match the constants in WifiManager and need to be kept up to date. 50 private static final int MIN_RSSI = -100; 51 private static final int MAX_RSSI = -55; 52 53 private static final int LATCH_TIMEOUT = 2000; 54 private static final String TEST_SSID = "\"Test SSID\""; 55 private static final String TEST_BSSID = "00:00:00:00:00:00"; 56 57 private final List<NetworkKey> mRequestedKeys = new ArrayList<>(); 58 private CountDownLatch mRequestScoresLatch; 59 60 @Test 61 public void testWifiIcon() { 62 String testSsid = "Test SSID"; 63 setWifiEnabled(true); 64 verifyLastWifiIcon(false, WifiIcons.WIFI_NO_NETWORK); 65 66 setWifiState(true, testSsid); 67 verifyLastWifiIcon(true, WifiIcons.WIFI_SIGNAL_STRENGTH[0][0]); 68 69 for (int testLevel = 0; testLevel < WifiIcons.WIFI_LEVEL_COUNT; testLevel++) { 70 setWifiLevel(testLevel); 71 72 setConnectivity(NetworkCapabilities.TRANSPORT_WIFI, true, true); 73 verifyLastWifiIcon(true, WifiIcons.WIFI_SIGNAL_STRENGTH[1][testLevel]); 74 setConnectivity(NetworkCapabilities.TRANSPORT_WIFI, false, true); 75 verifyLastWifiIcon(true, WifiIcons.WIFI_SIGNAL_STRENGTH[0][testLevel]); 76 } 77 } 78 79 @Test 80 public void testBadgedWifiIcon() throws Exception { 81 // TODO(sghuman): Refactor this setup code when creating a test for the badged QsIcon. 82 int testLevel = 1; 83 RssiCurve mockBadgeCurve = mock(RssiCurve.class); 84 Bundle attr = new Bundle(); 85 attr.putParcelable(ScoredNetwork.ATTRIBUTES_KEY_BADGING_CURVE, mockBadgeCurve); 86 ScoredNetwork score = 87 new ScoredNetwork( 88 new NetworkKey(new WifiKey(TEST_SSID, TEST_BSSID)), 89 null, 90 false /* meteredHint */, 91 attr); 92 93 // Must set the Settings value before instantiating the NetworkControllerImpl due to bugs in 94 // TestableSettingsProvider. 95 Settings.Global.putString(mContext.getContentResolver(), 96 Settings.Global.NETWORK_SCORING_UI_ENABLED, 97 "1"); 98 super.setUp(); // re-instantiate NetworkControllImpl now that setting has been updated 99 setupNetworkScoreManager(); 100 101 // Test Requesting Scores 102 mRequestScoresLatch = new CountDownLatch(1); 103 setWifiEnabled(true); 104 setWifiState(true, TEST_SSID, TEST_BSSID); 105 mRequestScoresLatch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS); 106 107 when(mockBadgeCurve.lookupScore(anyInt())).thenReturn((byte) NetworkBadging.BADGING_SD); 108 109 ArgumentCaptor<WifiNetworkScoreCache> scoreCacheCaptor = 110 ArgumentCaptor.forClass(WifiNetworkScoreCache.class); 111 verify(mMockNetworkScoreManager).registerNetworkScoreCache( 112 anyInt(), 113 scoreCacheCaptor.capture(), 114 Matchers.anyInt()); 115 scoreCacheCaptor.getValue().updateScores(Arrays.asList(score)); 116 117 // Test badge is set 118 setWifiLevel(testLevel); 119 120 ArgumentCaptor<IconState> iconArg = ArgumentCaptor.forClass(IconState.class); 121 Mockito.verify(mCallbackHandler, Mockito.atLeastOnce()).setWifiIndicators( 122 anyBoolean(), iconArg.capture(), any(), anyBoolean(), anyBoolean(), 123 any(), anyBoolean()); 124 IconState iconState = iconArg.getValue(); 125 126 assertEquals("Badged Wifi Resource is set", 127 Utils.WIFI_PIE_FOR_BADGING[testLevel], 128 iconState.icon); 129 assertEquals("SD Badge is set", 130 Utils.getWifiBadgeResource(NetworkBadging.BADGING_SD), 131 iconState.iconOverlay); 132 } 133 134 private void setupNetworkScoreManager() { 135 // Capture requested keys and count down latch if present 136 doAnswer( 137 new Answer<Boolean>() { 138 @Override 139 public Boolean answer(InvocationOnMock input) { 140 if (mRequestScoresLatch != null) { 141 mRequestScoresLatch.countDown(); 142 } 143 NetworkKey[] keys = (NetworkKey[]) input.getArguments()[0]; 144 for (NetworkKey key : keys) { 145 mRequestedKeys.add(key); 146 } 147 return true; 148 } 149 }).when(mMockNetworkScoreManager).requestScores(Matchers.<NetworkKey[]>any()); 150 } 151 152 @Test 153 public void testQsWifiIcon() { 154 String testSsid = "Test SSID"; 155 156 setWifiEnabled(false); 157 verifyLastQsWifiIcon(false, false, WifiIcons.QS_WIFI_NO_NETWORK, null); 158 159 setWifiEnabled(true); 160 verifyLastQsWifiIcon(true, false, WifiIcons.QS_WIFI_NO_NETWORK, null); 161 162 setWifiState(true, testSsid); 163 for (int testLevel = 0; testLevel < WifiIcons.WIFI_LEVEL_COUNT; testLevel++) { 164 setWifiLevel(testLevel); 165 166 setConnectivity(NetworkCapabilities.TRANSPORT_WIFI, true, true); 167 verifyLastQsWifiIcon(true, true, WifiIcons.QS_WIFI_SIGNAL_STRENGTH[1][testLevel], 168 testSsid); 169 setConnectivity(NetworkCapabilities.TRANSPORT_WIFI, false, true); 170 verifyLastQsWifiIcon(true, true, WifiIcons.QS_WIFI_SIGNAL_STRENGTH[0][testLevel], 171 testSsid); 172 } 173 } 174 175 @Test 176 public void testQsDataDirection() { 177 // Setup normal connection 178 String testSsid = "Test SSID"; 179 int testLevel = 2; 180 setWifiEnabled(true); 181 setWifiState(true, testSsid); 182 setWifiLevel(testLevel); 183 setConnectivity(NetworkCapabilities.TRANSPORT_WIFI, true, true); 184 verifyLastQsWifiIcon(true, true, 185 WifiIcons.QS_WIFI_SIGNAL_STRENGTH[1][testLevel], testSsid); 186 187 // Set to different activity state first to ensure a callback happens. 188 setWifiActivity(WifiManager.DATA_ACTIVITY_IN); 189 190 setWifiActivity(WifiManager.DATA_ACTIVITY_NONE); 191 verifyLastQsDataDirection(false, false); 192 setWifiActivity(WifiManager.DATA_ACTIVITY_IN); 193 verifyLastQsDataDirection(true, false); 194 setWifiActivity(WifiManager.DATA_ACTIVITY_OUT); 195 verifyLastQsDataDirection(false, true); 196 setWifiActivity(WifiManager.DATA_ACTIVITY_INOUT); 197 verifyLastQsDataDirection(true, true); 198 } 199 200 @Test 201 public void testRoamingIconDuringWifi() { 202 // Setup normal connection 203 String testSsid = "\"Test SSID\""; 204 int testLevel = 2; 205 setWifiEnabled(true); 206 setWifiState(true, testSsid); 207 setWifiLevel(testLevel); 208 setConnectivity(NetworkCapabilities.TRANSPORT_WIFI, true, true); 209 verifyLastWifiIcon(true, WifiIcons.WIFI_SIGNAL_STRENGTH[1][testLevel]); 210 211 setupDefaultSignal(); 212 setGsmRoaming(true); 213 // Still be on wifi though. 214 setConnectivity(NetworkCapabilities.TRANSPORT_WIFI, true, true); 215 setConnectivity(NetworkCapabilities.TRANSPORT_CELLULAR, false, false); 216 verifyLastMobileDataIndicators(true, 217 DEFAULT_LEVEL, 218 0, true); 219 } 220 221 protected void setWifiActivity(int activity) { 222 // TODO: Not this, because this variable probably isn't sticking around. 223 mNetworkController.mWifiSignalController.setActivity(activity); 224 } 225 226 protected void setWifiLevel(int level) { 227 float amountPerLevel = (MAX_RSSI - MIN_RSSI) / (WifiIcons.WIFI_LEVEL_COUNT - 1); 228 int rssi = (int)(MIN_RSSI + level * amountPerLevel); 229 // Put RSSI in the middle of the range. 230 rssi += amountPerLevel / 2; 231 Intent i = new Intent(WifiManager.RSSI_CHANGED_ACTION); 232 i.putExtra(WifiManager.EXTRA_NEW_RSSI, rssi); 233 mNetworkController.onReceive(mContext, i); 234 } 235 236 protected void setWifiEnabled(boolean enabled) { 237 Intent i = new Intent(WifiManager.WIFI_STATE_CHANGED_ACTION); 238 i.putExtra(WifiManager.EXTRA_WIFI_STATE, 239 enabled ? WifiManager.WIFI_STATE_ENABLED : WifiManager.WIFI_STATE_DISABLED); 240 mNetworkController.onReceive(mContext, i); 241 } 242 243 protected void setWifiState(boolean connected, String ssid) { 244 setWifiState(connected, ssid, null); 245 } 246 247 protected void setWifiState(boolean connected, String ssid, String bssid) { 248 Intent i = new Intent(WifiManager.NETWORK_STATE_CHANGED_ACTION); 249 NetworkInfo networkInfo = Mockito.mock(NetworkInfo.class); 250 Mockito.when(networkInfo.isConnected()).thenReturn(connected); 251 252 WifiInfo wifiInfo = Mockito.mock(WifiInfo.class); 253 Mockito.when(wifiInfo.getSSID()).thenReturn(ssid); 254 if (bssid != null) { 255 Mockito.when(wifiInfo.getBSSID()).thenReturn(bssid); 256 } 257 258 i.putExtra(WifiManager.EXTRA_NETWORK_INFO, networkInfo); 259 i.putExtra(WifiManager.EXTRA_WIFI_INFO, wifiInfo); 260 mNetworkController.onReceive(mContext, i); 261 } 262 263 protected void verifyLastQsDataDirection(boolean in, boolean out) { 264 ArgumentCaptor<Boolean> inArg = ArgumentCaptor.forClass(Boolean.class); 265 ArgumentCaptor<Boolean> outArg = ArgumentCaptor.forClass(Boolean.class); 266 267 Mockito.verify(mCallbackHandler, Mockito.atLeastOnce()).setWifiIndicators( 268 anyBoolean(), any(), any(), inArg.capture(), outArg.capture(), any(), anyBoolean()); 269 assertEquals("WiFi data in, in quick settings", in, (boolean) inArg.getValue()); 270 assertEquals("WiFi data out, in quick settings", out, (boolean) outArg.getValue()); 271 } 272 273 protected void verifyLastQsWifiIcon(boolean enabled, boolean connected, int icon, 274 String description) { 275 ArgumentCaptor<IconState> iconArg = ArgumentCaptor.forClass(IconState.class); 276 ArgumentCaptor<Boolean> enabledArg = ArgumentCaptor.forClass(Boolean.class); 277 ArgumentCaptor<String> descArg = ArgumentCaptor.forClass(String.class); 278 279 Mockito.verify(mCallbackHandler, Mockito.atLeastOnce()).setWifiIndicators( 280 enabledArg.capture(), any(), iconArg.capture(), anyBoolean(), 281 anyBoolean(), descArg.capture(), anyBoolean()); 282 IconState iconState = iconArg.getValue(); 283 assertEquals("WiFi enabled, in quick settings", enabled, (boolean) enabledArg.getValue()); 284 assertEquals("WiFi connected, in quick settings", connected, iconState.visible); 285 assertEquals("WiFi signal, in quick settings", icon, iconState.icon); 286 assertEquals("WiFI desc (ssid), in quick settings", description, descArg.getValue()); 287 } 288 289 protected void verifyLastWifiIcon(boolean visible, int icon) { 290 ArgumentCaptor<IconState> iconArg = ArgumentCaptor.forClass(IconState.class); 291 292 Mockito.verify(mCallbackHandler, Mockito.atLeastOnce()).setWifiIndicators( 293 anyBoolean(), iconArg.capture(), any(), anyBoolean(), anyBoolean(), 294 any(), anyBoolean()); 295 IconState iconState = iconArg.getValue(); 296 assertEquals("WiFi visible, in status bar", visible, iconState.visible); 297 assertEquals("WiFi signal, in status bar", icon, iconState.icon); 298 } 299} 300