1 /* 2 * Copyright (C) 2017 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 package com.android.settings.wifi; 17 18 import static android.support.test.InstrumentationRegistry.getInstrumentation; 19 import static android.support.test.espresso.Espresso.onView; 20 import static android.support.test.espresso.assertion.ViewAssertions.doesNotExist; 21 import static android.support.test.espresso.assertion.ViewAssertions.matches; 22 import static android.support.test.espresso.matcher.ViewMatchers.Visibility.VISIBLE; 23 import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed; 24 import static android.support.test.espresso.matcher.ViewMatchers.withEffectiveVisibility; 25 import static android.support.test.espresso.matcher.ViewMatchers.withId; 26 import static android.support.test.espresso.matcher.ViewMatchers.withText; 27 28 import static com.google.common.truth.Truth.assertThat; 29 30 import static org.hamcrest.Matchers.allOf; 31 import static org.hamcrest.Matchers.not; 32 import static org.hamcrest.Matchers.startsWith; 33 import static org.mockito.Mockito.atMost; 34 import static org.mockito.Mockito.verify; 35 import static org.mockito.Mockito.when; 36 37 import android.app.Activity; 38 import android.app.Fragment; 39 import android.content.Context; 40 import android.content.Intent; 41 import android.net.ConnectivityManager; 42 import android.net.NetworkInfo; 43 import android.net.wifi.WifiConfiguration; 44 import android.net.wifi.WifiInfo; 45 import android.net.wifi.WifiManager; 46 import android.net.wifi.WifiSsid; 47 import android.provider.Settings; 48 import android.support.test.InstrumentationRegistry; 49 import android.support.test.rule.ActivityTestRule; 50 import android.support.test.runner.AndroidJUnit4; 51 52 import com.android.settings.Settings.WifiSettingsActivity; 53 import com.android.settingslib.wifi.AccessPoint; 54 import com.android.settingslib.wifi.TestAccessPointBuilder; 55 import com.android.settingslib.wifi.WifiTracker; 56 import com.android.settingslib.wifi.WifiTracker.WifiListener; 57 import com.android.settingslib.wifi.WifiTrackerFactory; 58 59 import com.google.common.collect.Lists; 60 61 import org.junit.Before; 62 import org.junit.Rule; 63 import org.junit.Test; 64 import org.junit.runner.RunWith; 65 import org.mockito.Mock; 66 import org.mockito.MockitoAnnotations; 67 68 import java.util.List; 69 70 @RunWith(AndroidJUnit4.class) 71 public class WifiSettingsUiTest { 72 private static final String TEST_SSID = "\"Test Ssid\""; 73 private static final String TEST_UNQUOTED_SSID = "Test Ssid"; 74 private static final String TEST_BSSID = "0a:08:5c:67:89:00"; 75 private static final int TEST_RSSI = 123; 76 private static final int TEST_NETWORK_ID = 1; 77 78 // Keys used to lookup resources by name (see the resourceId/resourceString helper methods). 79 private static final String ID = "id"; 80 private static final String STRING = "string"; 81 private static final String WIFI_CONFIGURE_SETTINGS_PREFERENCE_TITLE = 82 "wifi_configure_settings_preference_title"; 83 private static final String WIFI_SAVED_ACCESS_POINTS_LABEL = "wifi_saved_access_points_label"; 84 private static final String WIFI_EMPTY_LIST_WIFI_OFF = "wifi_empty_list_wifi_off"; 85 private static final String WIFI_DISPLAY_STATUS_CONNECTED = "wifi_display_status_connected"; 86 private static final String WIFI_PASSWORD = "wifi_password"; 87 private static final String WIFI_SHOW_PASSWORD = "wifi_show_password"; 88 private static final String PASSWORD_LAYOUT = "password_layout"; 89 private static final String PASSWORD = "password"; 90 91 @Mock 92 private WifiTracker mWifiTracker; 93 @Mock 94 private WifiManager mWifiManager; 95 private Context mContext; 96 private WifiListener mWifiListener; 97 98 @Rule 99 public ActivityTestRule<WifiSettingsActivity> mActivityRule = 100 new ActivityTestRule<>(WifiSettingsActivity.class, true); 101 102 @Before setUp()103 public void setUp() { 104 MockitoAnnotations.initMocks(this); 105 mContext = InstrumentationRegistry.getTargetContext(); 106 WifiTrackerFactory.setTestingWifiTracker(mWifiTracker); 107 when(mWifiTracker.getManager()).thenReturn(mWifiManager); 108 } 109 110 /** 111 * Helper to get around the problem that directly accessing settings resource id's from 112 * com.android.settings.R via R.(type).(name) (eg R.id.password or 113 * R.string.wifi_configure_settings_preference_title) may not work due to mismatched resource 114 * ids. See b/37714546 and b/63546650. 115 */ resourceId(String type, String name)116 private int resourceId(String type, String name) { 117 return mContext.getResources().getIdentifier(name, type, mContext.getPackageName()); 118 } 119 120 /** Similar to {@link #resourceId}, but for accessing R.string.<name> values. */ resourceString(String name)121 private String resourceString(String name) { 122 return mContext.getResources().getString(resourceId(STRING, name)); 123 } 124 setupConnectedAccessPoint()125 private void setupConnectedAccessPoint() { 126 WifiConfiguration config = new WifiConfiguration(); 127 config.SSID = TEST_SSID; 128 config.BSSID = TEST_BSSID; 129 config.networkId = TEST_NETWORK_ID; 130 WifiInfo wifiInfo = new WifiInfo(); 131 wifiInfo.setSSID(WifiSsid.createFromAsciiEncoded(TEST_UNQUOTED_SSID)); 132 wifiInfo.setBSSID(TEST_BSSID); 133 wifiInfo.setRssi(TEST_RSSI); 134 wifiInfo.setNetworkId(TEST_NETWORK_ID); 135 NetworkInfo networkInfo = new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0, null, null); 136 networkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, null, null); 137 AccessPoint accessPoint = new AccessPoint(mContext, config); 138 accessPoint.update(config, wifiInfo, networkInfo); 139 140 assertThat(accessPoint.getSsidStr()).isEqualTo(TEST_UNQUOTED_SSID); 141 assertThat(accessPoint.getBssid()).isEqualTo(TEST_BSSID); 142 assertThat(accessPoint.getNetworkInfo()).isNotNull(); 143 assertThat(accessPoint.isActive()).isTrue(); 144 assertThat(accessPoint.getSettingsSummary()).isEqualTo( 145 resourceString(WIFI_DISPLAY_STATUS_CONNECTED)); 146 147 when(mWifiTracker.getAccessPoints()).thenReturn( 148 Lists.asList(accessPoint, new AccessPoint[]{})); 149 } 150 151 /** Launch the activity via an Intent with a String extra. */ launchActivity(String extraName, String extraValue)152 private void launchActivity(String extraName, String extraValue) { 153 Intent intent = new Intent(Settings.ACTION_WIFI_SETTINGS); 154 if (extraName != null && extraValue != null) { 155 intent.putExtra(extraName, extraValue); 156 } 157 mActivityRule.launchActivity(intent); 158 159 verify(mWifiTracker).getManager(); 160 161 List<Fragment> fragments = mActivityRule.getActivity().getFragmentManager().getFragments(); 162 assertThat(fragments.size()).isEqualTo(1); 163 mWifiListener = (WifiSettings) fragments.get(0); 164 assertThat(mWifiListener).isNotNull(); 165 } 166 167 /** Helper to launch the activity with no extra. */ launchActivity()168 private void launchActivity() { 169 launchActivity(null, null); 170 } 171 setWifiState(int wifiState)172 private void setWifiState(int wifiState) { 173 when(mWifiManager.getWifiState()).thenReturn(wifiState); 174 when(mWifiManager.isWifiEnabled()).thenReturn(wifiState == WifiManager.WIFI_STATE_ENABLED); 175 } 176 callOnWifiStateChanged(int state)177 private void callOnWifiStateChanged(int state) { 178 mActivityRule.getActivity().getMainThreadHandler() 179 .post(() -> mWifiListener.onWifiStateChanged(state)); 180 } 181 182 @Test launchActivityShouldSucceed()183 public void launchActivityShouldSucceed() { 184 launchActivity(); 185 } 186 187 @Test shouldShowWifiPreferences()188 public void shouldShowWifiPreferences() { 189 launchActivity(); 190 191 onView(withText(resourceId(STRING, WIFI_CONFIGURE_SETTINGS_PREFERENCE_TITLE))).check( 192 matches(isDisplayed())); 193 } 194 195 @Test noSavedNetworks_wifiEnabled_shouldNotShowSavedNetworksButton()196 public void noSavedNetworks_wifiEnabled_shouldNotShowSavedNetworksButton() { 197 setWifiState(WifiManager.WIFI_STATE_ENABLED); 198 when(mWifiTracker.getNumSavedNetworks()).thenReturn(0); 199 200 launchActivity(); 201 202 onView(withText(resourceId(STRING, WIFI_SAVED_ACCESS_POINTS_LABEL))).check( 203 matches(not(isDisplayed()))); 204 } 205 206 @Test noSavedNetworks_wifiDisabled_shouldNotShowSavedNetworksButton()207 public void noSavedNetworks_wifiDisabled_shouldNotShowSavedNetworksButton() { 208 setWifiState(WifiManager.WIFI_STATE_DISABLED); 209 when(mWifiTracker.getNumSavedNetworks()).thenReturn(0); 210 211 launchActivity(); 212 213 onView(withText(resourceId(STRING, WIFI_SAVED_ACCESS_POINTS_LABEL))).check( 214 doesNotExist()); 215 } 216 217 @Test savedNetworksExist_shouldShowSavedNetworksButton()218 public void savedNetworksExist_shouldShowSavedNetworksButton() { 219 setWifiState(WifiManager.WIFI_STATE_ENABLED); 220 when(mWifiTracker.getNumSavedNetworks()).thenReturn(1); 221 222 launchActivity(); 223 224 onView(allOf(withText(resourceId(STRING, WIFI_SAVED_ACCESS_POINTS_LABEL)), 225 withEffectiveVisibility(VISIBLE))).check(matches(isDisplayed())); 226 } 227 228 @Test onDisableWifi_seeOffMessage()229 public void onDisableWifi_seeOffMessage() { 230 setWifiState(WifiManager.WIFI_STATE_DISABLED); 231 232 launchActivity(); 233 callOnWifiStateChanged(WifiManager.WIFI_STATE_DISABLED); 234 235 onView(withText(startsWith(resourceString(WIFI_EMPTY_LIST_WIFI_OFF)))).check( 236 matches(isDisplayed())); 237 } 238 239 @Test onEnableWifi_shouldNotSeeOffMessage()240 public void onEnableWifi_shouldNotSeeOffMessage() { 241 setWifiState(WifiManager.WIFI_STATE_ENABLED); 242 243 launchActivity(); 244 callOnWifiStateChanged(WifiManager.WIFI_STATE_ENABLED); 245 246 onView(withText(startsWith(resourceString(WIFI_EMPTY_LIST_WIFI_OFF)))).check( 247 doesNotExist()); 248 } 249 250 @Test onConnected_shouldSeeConnectedMessage()251 public void onConnected_shouldSeeConnectedMessage() { 252 setWifiState(WifiManager.WIFI_STATE_ENABLED); 253 setupConnectedAccessPoint(); 254 when(mWifiTracker.isConnected()).thenReturn(true); 255 256 launchActivity(); 257 258 onView(withText(resourceString(WIFI_DISPLAY_STATUS_CONNECTED))).check( 259 matches(isDisplayed())); 260 } 261 262 @Test resumingAp_shouldNotForceUpdateWhenExistingAPsAreListed()263 public void resumingAp_shouldNotForceUpdateWhenExistingAPsAreListed() { 264 setWifiState(WifiManager.WIFI_STATE_ENABLED); 265 setupConnectedAccessPoint(); 266 when(mWifiTracker.isConnected()).thenReturn(true); 267 268 launchActivity(); 269 270 onView(withText(resourceString(WIFI_DISPLAY_STATUS_CONNECTED))).check( 271 matches(isDisplayed())); 272 verify(mWifiTracker).forceUpdate(); 273 274 Activity activity = mActivityRule.getActivity(); 275 activity.finish(); 276 getInstrumentation().waitForIdleSync(); 277 278 getInstrumentation().callActivityOnStart(activity); 279 verify(mWifiTracker, atMost(1)).forceUpdate(); 280 } 281 282 @Test changingSecurityStateOnApShouldNotCauseMultipleListItems()283 public void changingSecurityStateOnApShouldNotCauseMultipleListItems() { 284 setWifiState(WifiManager.WIFI_STATE_ENABLED); 285 TestAccessPointBuilder builder = new TestAccessPointBuilder(mContext) 286 .setSsid(TEST_SSID) 287 .setSecurity(AccessPoint.SECURITY_NONE) 288 .setRssi(TEST_RSSI); 289 AccessPoint open = builder.build(); 290 291 builder.setSecurity(AccessPoint.SECURITY_EAP); 292 AccessPoint eap = builder.build(); 293 294 builder.setSecurity(AccessPoint.SECURITY_WEP); 295 AccessPoint wep = builder.build(); 296 297 // Return a different security state each time getAccessPoints is invoked 298 when(mWifiTracker.getAccessPoints()) 299 .thenReturn(Lists.newArrayList(open)) 300 .thenReturn(Lists.newArrayList(eap)) 301 .thenReturn(Lists.newArrayList(wep)); 302 303 launchActivity(); 304 305 onView(withText(TEST_SSID)).check(matches(isDisplayed())); 306 307 mWifiListener.onAccessPointsChanged(); 308 onView(withText(TEST_SSID)).check(matches(isDisplayed())); 309 310 mWifiListener.onAccessPointsChanged(); 311 onView(withText(TEST_SSID)).check(matches(isDisplayed())); 312 } 313 314 @Test wrongPasswordSavedNetwork()315 public void wrongPasswordSavedNetwork() { 316 setWifiState(WifiManager.WIFI_STATE_ENABLED); 317 318 // Set up an AccessPoint that is disabled due to incorrect password. 319 WifiConfiguration config = new WifiConfiguration(); 320 config.SSID = TEST_SSID; 321 config.BSSID = TEST_BSSID; 322 config.networkId = TEST_NETWORK_ID; 323 config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK); 324 325 WifiConfiguration.NetworkSelectionStatus selectionStatus = 326 new WifiConfiguration.NetworkSelectionStatus(); 327 selectionStatus.setNetworkSelectionDisableReason( 328 WifiConfiguration.NetworkSelectionStatus.DISABLED_BY_WRONG_PASSWORD); 329 selectionStatus.setNetworkSelectionStatus( 330 WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_TEMPORARY_DISABLED); 331 config.setNetworkSelectionStatus(selectionStatus); 332 333 WifiInfo wifiInfo = new WifiInfo(); 334 wifiInfo.setSSID(WifiSsid.createFromAsciiEncoded(TEST_UNQUOTED_SSID)); 335 wifiInfo.setBSSID(TEST_BSSID); 336 wifiInfo.setRssi(TEST_RSSI); 337 wifiInfo.setNetworkId(TEST_NETWORK_ID); 338 AccessPoint accessPoint = new AccessPoint(mContext, config); 339 accessPoint.update(config, wifiInfo, null); 340 341 // Make sure we've set up our access point correctly. 342 assertThat(accessPoint.getSsidStr()).isEqualTo(TEST_UNQUOTED_SSID); 343 assertThat(accessPoint.getBssid()).isEqualTo(TEST_BSSID); 344 assertThat(accessPoint.isActive()).isFalse(); 345 assertThat(accessPoint.getConfig()).isNotNull(); 346 WifiConfiguration.NetworkSelectionStatus networkStatus = 347 accessPoint.getConfig().getNetworkSelectionStatus(); 348 assertThat(networkStatus).isNotNull(); 349 assertThat(networkStatus.isNetworkEnabled()).isFalse(); 350 assertThat(networkStatus.getNetworkSelectionDisableReason()).isEqualTo( 351 WifiConfiguration.NetworkSelectionStatus.DISABLED_BY_WRONG_PASSWORD); 352 353 when(mWifiTracker.getAccessPoints()).thenReturn(Lists.newArrayList(accessPoint)); 354 launchActivity(WifiSettings.EXTRA_START_CONNECT_SSID, accessPoint.getSsidStr()); 355 356 // Make sure that the password dialog is visible. 357 onView(withText(resourceId(STRING, WIFI_PASSWORD))).check(matches(isDisplayed())); 358 onView(withText(resourceId(STRING, WIFI_SHOW_PASSWORD))).check(matches(isDisplayed())); 359 onView(withId(resourceId(ID, PASSWORD_LAYOUT))).check(matches(isDisplayed())); 360 onView(withId(resourceId(ID, PASSWORD))).check(matches(isDisplayed())); 361 } 362 } 363