1 /*
2  * Copyright (C) 2019 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 com.android.settings.wifi.WifiConfigUiBase2.MODE_CONNECT;
19 import static com.android.settings.wifi.WifiConfigUiBase2.MODE_MODIFY;
20 
21 import static com.google.common.truth.Truth.assertThat;
22 
23 import static org.mockito.ArgumentMatchers.any;
24 import static org.mockito.ArgumentMatchers.anyBoolean;
25 import static org.mockito.ArgumentMatchers.anyInt;
26 import static org.mockito.ArgumentMatchers.eq;
27 import static org.mockito.Mockito.doNothing;
28 import static org.mockito.Mockito.doReturn;
29 import static org.mockito.Mockito.mock;
30 import static org.mockito.Mockito.spy;
31 import static org.mockito.Mockito.times;
32 import static org.mockito.Mockito.verify;
33 import static org.mockito.Mockito.when;
34 
35 import android.app.Activity;
36 import android.content.ContentResolver;
37 import android.content.Context;
38 import android.content.Intent;
39 import android.content.res.Resources;
40 import android.net.wifi.WifiConfiguration;
41 import android.net.wifi.WifiManager;
42 import android.os.Bundle;
43 import android.os.PowerManager;
44 import android.os.UserManager;
45 import android.provider.Settings;
46 import android.util.FeatureFlagUtils;
47 import android.view.ContextMenu;
48 import android.view.View;
49 
50 import androidx.fragment.app.FragmentActivity;
51 import androidx.preference.Preference;
52 import androidx.preference.PreferenceManager;
53 import androidx.preference.PreferenceScreen;
54 import androidx.recyclerview.widget.RecyclerView;
55 
56 import com.android.settings.R;
57 import com.android.settings.datausage.DataUsagePreference;
58 import com.android.settings.testutils.shadow.ShadowDataUsageUtils;
59 import com.android.settings.testutils.shadow.ShadowFragment;
60 import com.android.settingslib.wifi.LongPressWifiEntryPreference;
61 import com.android.wifitrackerlib.WifiEntry;
62 import com.android.wifitrackerlib.WifiPickerTracker;
63 
64 import org.junit.Before;
65 import org.junit.Test;
66 import org.junit.runner.RunWith;
67 import org.mockito.Mock;
68 import org.mockito.MockitoAnnotations;
69 import org.robolectric.RobolectricTestRunner;
70 import org.robolectric.RuntimeEnvironment;
71 import org.robolectric.annotation.Config;
72 import org.robolectric.shadows.ShadowToast;
73 
74 @RunWith(RobolectricTestRunner.class)
75 public class WifiSettingsTest {
76 
77     private static final int NUM_NETWORKS = 4;
78     private static final String FAKE_URI_STRING = "fakeuri";
79 
80     @Mock
81     private PowerManager mPowerManager;
82     @Mock
83     private WifiManager mWifiManager;
84     @Mock
85     private DataUsagePreference mDataUsagePreference;
86     private Context mContext;
87     private WifiSettings mWifiSettings;
88     @Mock
89     private WifiPickerTracker mMockWifiPickerTracker;
90     @Mock
91     private PreferenceManager mPreferenceManager;
92 
93     @Before
setUp()94     public void setUp() {
95         MockitoAnnotations.initMocks(this);
96         mContext = spy(RuntimeEnvironment.application);
97 
98         mWifiSettings = spy(new WifiSettings());
99         doReturn(mContext).when(mWifiSettings).getContext();
100         doReturn(mPreferenceManager).when(mWifiSettings).getPreferenceManager();
101         doReturn(mPowerManager).when(mContext).getSystemService(PowerManager.class);
102         doReturn(mWifiManager).when(mContext).getSystemService(WifiManager.class);
103         doReturn(mContext).when(mPreferenceManager).getContext();
104         mWifiSettings.mAddWifiNetworkPreference = new AddWifiNetworkPreference(mContext);
105         mWifiSettings.mSavedNetworksPreference = new Preference(mContext);
106         mWifiSettings.mConfigureWifiSettingsPreference = new Preference(mContext);
107         mWifiSettings.mWifiPickerTracker = mMockWifiPickerTracker;
108         mWifiSettings.mWifiManager = mWifiManager;
109         mWifiSettings.IS_ENABLED_PROVIDER_MODEL = false;
110     }
111 
112     @Test
addNetworkFragmentSendResult_onActivityResult_shouldHandleEvent()113     public void addNetworkFragmentSendResult_onActivityResult_shouldHandleEvent() {
114         final WifiSettings WifiSettings = spy(new WifiSettings());
115         final Intent intent = new Intent();
116         doNothing().when(WifiSettings).handleAddNetworkRequest(anyInt(), any(Intent.class));
117 
118         WifiSettings.onActivityResult(WifiSettings.ADD_NETWORK_REQUEST, Activity.RESULT_OK,
119                 intent);
120 
121         verify(WifiSettings).handleAddNetworkRequest(anyInt(), any(Intent.class));
122     }
123 
124     @Test
setAdditionalSettingsSummaries_hasSavedNetwork_preferenceVisible()125     public void setAdditionalSettingsSummaries_hasSavedNetwork_preferenceVisible() {
126         when(mMockWifiPickerTracker.getNumSavedNetworks()).thenReturn(NUM_NETWORKS);
127         when(mMockWifiPickerTracker.getNumSavedSubscriptions()).thenReturn(0 /* count */);
128 
129         mWifiSettings.setAdditionalSettingsSummaries();
130 
131         assertThat(mWifiSettings.mSavedNetworksPreference.isVisible()).isTrue();
132         assertThat(mWifiSettings.mSavedNetworksPreference.getSummary()).isEqualTo(
133                 mContext.getResources().getQuantityString(
134                         R.plurals.wifi_saved_access_points_summary,
135                         NUM_NETWORKS, NUM_NETWORKS));
136     }
137 
138     @Test
setAdditionalSettingsSummaries_hasSavedPasspointNetwork_preferenceVisible()139     public void setAdditionalSettingsSummaries_hasSavedPasspointNetwork_preferenceVisible() {
140         when(mMockWifiPickerTracker.getNumSavedNetworks()).thenReturn(0 /* count */);
141         when(mMockWifiPickerTracker.getNumSavedSubscriptions()).thenReturn(NUM_NETWORKS);
142 
143         mWifiSettings.setAdditionalSettingsSummaries();
144 
145         assertThat(mWifiSettings.mSavedNetworksPreference.isVisible()).isTrue();
146         assertThat(mWifiSettings.mSavedNetworksPreference.getSummary()).isEqualTo(
147                 mContext.getResources().getQuantityString(
148                         R.plurals.wifi_saved_passpoint_access_points_summary,
149                         NUM_NETWORKS, NUM_NETWORKS));
150     }
151 
152     @Test
setAdditionalSettingsSummaries_hasTwoKindsSavedNetwork_preferenceVisible()153     public void setAdditionalSettingsSummaries_hasTwoKindsSavedNetwork_preferenceVisible() {
154         when(mMockWifiPickerTracker.getNumSavedNetworks()).thenReturn(NUM_NETWORKS);
155         when(mMockWifiPickerTracker.getNumSavedSubscriptions()).thenReturn(NUM_NETWORKS);
156 
157         mWifiSettings.setAdditionalSettingsSummaries();
158 
159         assertThat(mWifiSettings.mSavedNetworksPreference.isVisible()).isTrue();
160         assertThat(mWifiSettings.mSavedNetworksPreference.getSummary()).isEqualTo(
161                 mContext.getResources().getQuantityString(
162                         R.plurals.wifi_saved_all_access_points_summary,
163                         NUM_NETWORKS*2, NUM_NETWORKS*2));
164     }
165 
166     @Test
setAdditionalSettingsSummaries_noSavedNetwork_preferenceInvisible()167     public void setAdditionalSettingsSummaries_noSavedNetwork_preferenceInvisible() {
168         when(mMockWifiPickerTracker.getNumSavedNetworks()).thenReturn(0 /* count */);
169         when(mMockWifiPickerTracker.getNumSavedSubscriptions()).thenReturn(0 /* count */);
170 
171         mWifiSettings.setAdditionalSettingsSummaries();
172 
173         assertThat(mWifiSettings.mSavedNetworksPreference.isVisible()).isFalse();
174     }
175 
176     @Test
setAdditionalSettingsSummaries_wifiWakeupEnabled_displayOn()177     public void setAdditionalSettingsSummaries_wifiWakeupEnabled_displayOn() {
178         final ContentResolver contentResolver = mContext.getContentResolver();
179         when(mWifiManager.isAutoWakeupEnabled()).thenReturn(true);
180         when(mWifiManager.isScanAlwaysAvailable()).thenReturn(true);
181         Settings.Global.putInt(contentResolver, Settings.Global.AIRPLANE_MODE_ON, 0);
182         when(mPowerManager.isPowerSaveMode()).thenReturn(false);
183 
184         mWifiSettings.setAdditionalSettingsSummaries();
185 
186         assertThat(mWifiSettings.mConfigureWifiSettingsPreference.getSummary()).isEqualTo(
187                 mContext.getString(R.string.wifi_configure_settings_preference_summary_wakeup_on));
188     }
189 
190     @Test
setAdditionalSettingsSummaries_wifiWakeupDisabled_displayOff()191     public void setAdditionalSettingsSummaries_wifiWakeupDisabled_displayOff() {
192         final ContentResolver contentResolver = mContext.getContentResolver();
193         when(mWifiManager.isAutoWakeupEnabled()).thenReturn(false);
194 
195         mWifiSettings.setAdditionalSettingsSummaries();
196 
197         assertThat(mWifiSettings.mConfigureWifiSettingsPreference.getSummary()).isEqualTo(
198                 mContext.getString(R.string.wifi_configure_settings_preference_summary_wakeup_off));
199     }
200 
201     @Test
checkAddWifiNetworkPrefernce_preferenceVisible()202     public void checkAddWifiNetworkPrefernce_preferenceVisible() {
203         assertThat(mWifiSettings.mAddWifiNetworkPreference.isVisible()).isTrue();
204         assertThat(mWifiSettings.mAddWifiNetworkPreference.getTitle()).isEqualTo(
205                 mContext.getString(R.string.wifi_add_network));
206     }
207 
setUpForOnCreate()208     private void setUpForOnCreate() {
209         final FragmentActivity activity = mock(FragmentActivity.class);
210         when(mWifiSettings.getActivity()).thenReturn(activity);
211         final Resources.Theme theme = mContext.getTheme();
212         when(activity.getTheme()).thenReturn(theme);
213         UserManager userManager = mock(UserManager.class);
214         when(activity.getSystemService(Context.USER_SERVICE))
215                 .thenReturn(userManager);
216 
217         when(mWifiSettings.findPreference(WifiSettings.PREF_KEY_DATA_USAGE))
218                 .thenReturn(mDataUsagePreference);
219     }
220 
221     @Test
222     @Config(shadows = {ShadowDataUsageUtils.class, ShadowFragment.class})
checkDataUsagePreference_perferenceInvisibleIfWifiNotSupported()223     public void checkDataUsagePreference_perferenceInvisibleIfWifiNotSupported() {
224         setUpForOnCreate();
225         ShadowDataUsageUtils.IS_WIFI_SUPPORTED = false;
226 
227         mWifiSettings.onCreate(Bundle.EMPTY);
228 
229         verify(mDataUsagePreference).setVisible(false);
230     }
231 
232     @Test
233     @Config(shadows = {ShadowDataUsageUtils.class, ShadowFragment.class})
checkDataUsagePreference_perferenceVisibleIfWifiSupported()234     public void checkDataUsagePreference_perferenceVisibleIfWifiSupported() {
235         setUpForOnCreate();
236         ShadowDataUsageUtils.IS_WIFI_SUPPORTED = true;
237 
238         mWifiSettings.onCreate(Bundle.EMPTY);
239 
240         verify(mDataUsagePreference).setVisible(true);
241         verify(mDataUsagePreference).setTemplate(any(), eq(0) /*subId*/, eq(null) /*service*/);
242     }
243 
244     @Test
onCreateAdapter_hasStableIdsTrue()245     public void onCreateAdapter_hasStableIdsTrue() {
246         final PreferenceScreen preferenceScreen = mock(PreferenceScreen.class);
247         when(preferenceScreen.getContext()).thenReturn(mContext);
248 
249         RecyclerView.Adapter adapter = mWifiSettings.onCreateAdapter(preferenceScreen);
250 
251         assertThat(adapter.hasStableIds()).isTrue();
252     }
253 
254     @Test
onCreateContextMenu_shouldHaveForgetAndDisconnectMenuForConnectedWifiEntry()255     public void onCreateContextMenu_shouldHaveForgetAndDisconnectMenuForConnectedWifiEntry() {
256         final FragmentActivity activity = mock(FragmentActivity.class);
257         when(activity.getApplicationContext()).thenReturn(mContext);
258         when(mWifiSettings.getActivity()).thenReturn(activity);
259 
260         final WifiEntry wifiEntry = mock(WifiEntry.class);
261         when(wifiEntry.canDisconnect()).thenReturn(true);
262         when(wifiEntry.canForget()).thenReturn(true);
263         when(wifiEntry.isSaved()).thenReturn(true);
264         when(wifiEntry.getConnectedState()).thenReturn(WifiEntry.CONNECTED_STATE_CONNECTED);
265 
266         final LongPressWifiEntryPreference connectedWifiEntryPreference =
267                 mWifiSettings.createLongPressWifiEntryPreference(wifiEntry);
268         final View view = mock(View.class);
269         when(view.getTag()).thenReturn(connectedWifiEntryPreference);
270 
271         final ContextMenu menu = mock(ContextMenu.class);
272         mWifiSettings.onCreateContextMenu(menu, view, null /* info */);
273 
274         verify(menu).add(anyInt(), eq(WifiSettings.MENU_ID_FORGET), anyInt(), anyInt());
275         verify(menu).add(anyInt(), eq(WifiSettings.MENU_ID_DISCONNECT), anyInt(), anyInt());
276     }
277 
278     @Test
onWifiEntriesChanged_shouldChangeNextButtonState()279     public void onWifiEntriesChanged_shouldChangeNextButtonState() {
280         mWifiSettings.onWifiEntriesChanged();
281 
282         verify(mWifiSettings).changeNextButtonState(anyBoolean());
283     }
284 
285     @Test
openSubscriptionHelpPage_shouldCallStartActivityForResult()286     public void openSubscriptionHelpPage_shouldCallStartActivityForResult() {
287         doReturn(new Intent()).when(mWifiSettings).getHelpIntent(mContext, FAKE_URI_STRING);
288         doNothing().when(mWifiSettings).startActivityForResult(any(Intent.class), anyInt());
289         final WifiEntry mockWifiEntry = mock(WifiEntry.class);
290         when(mockWifiEntry.getHelpUriString()).thenReturn(FAKE_URI_STRING);
291 
292         mWifiSettings.openSubscriptionHelpPage(mockWifiEntry);
293 
294         verify(mWifiSettings, times(1)).startActivityForResult(any(), anyInt());
295     }
296 
297     @Test
onNumSavedNetworksChanged_isFinishing_ShouldNotCrash()298     public void onNumSavedNetworksChanged_isFinishing_ShouldNotCrash() {
299         final FragmentActivity activity = mock(FragmentActivity.class);
300         when(activity.isFinishing()).thenReturn(true);
301         when(mWifiSettings.getActivity()).thenReturn(activity);
302         when(mWifiSettings.getContext()).thenReturn(null);
303 
304         mWifiSettings.onNumSavedNetworksChanged();
305     }
306 
307     @Test
onNumSavedSubscriptionsChanged_isFinishing_ShouldNotCrash()308     public void onNumSavedSubscriptionsChanged_isFinishing_ShouldNotCrash() {
309         final FragmentActivity activity = mock(FragmentActivity.class);
310         when(activity.isFinishing()).thenReturn(true);
311         when(mWifiSettings.getActivity()).thenReturn(activity);
312         when(mWifiSettings.getContext()).thenReturn(null);
313 
314         mWifiSettings.onNumSavedSubscriptionsChanged();
315     }
316 
317     @Test
onSubmit_modeModifyNoConfig_toastErrorMessage()318     public void onSubmit_modeModifyNoConfig_toastErrorMessage() {
319         WifiDialog2 dialog = createWifiDialog2(MODE_MODIFY, null /* config */);
320 
321         mWifiSettings.onSubmit(dialog);
322 
323         assertThat(ShadowToast.getTextOfLatestToast()).isEqualTo(
324                 mContext.getString(R.string.wifi_failed_save_message));
325     }
326 
327     @Test
onSubmit_modeModifyHasConfig_saveWifiManager()328     public void onSubmit_modeModifyHasConfig_saveWifiManager() {
329         final WifiConfiguration config = mock(WifiConfiguration.class);
330         WifiDialog2 dialog = createWifiDialog2(MODE_MODIFY, config);
331 
332         mWifiSettings.onSubmit(dialog);
333 
334         verify(mWifiManager).save(eq(config), any());
335     }
336 
337     @Test
onSubmit_modeConnectNoConfig_connectWifiEntry()338     public void onSubmit_modeConnectNoConfig_connectWifiEntry() {
339         WifiDialog2 dialog = createWifiDialog2(MODE_CONNECT, null /* config */);
340         final WifiEntry wifiEntry = dialog.getWifiEntry();
341 
342         mWifiSettings.onAttach(mContext);
343         mWifiSettings.onSubmit(dialog);
344 
345         verify(mWifiSettings).connect(wifiEntry, false /* editIfNoConfig */,
346                 false /* fullScreenEdit*/);
347     }
348 
349     @Test
onSubmit_modeConnectHasConfig_connectWifiManager()350     public void onSubmit_modeConnectHasConfig_connectWifiManager() {
351         final WifiConfiguration config = mock(WifiConfiguration.class);
352         WifiDialog2 dialog = createWifiDialog2(MODE_CONNECT, config);
353 
354         mWifiSettings.onSubmit(dialog);
355 
356         verify(mWifiManager).connect(eq(config), any(WifiManager.ActionListener.class));
357     }
358 
createWifiDialog2(int mode, WifiConfiguration config)359     private WifiDialog2 createWifiDialog2(int mode, WifiConfiguration config) {
360         final WifiEntry wifiEntry = mock(WifiEntry.class);
361         when(wifiEntry.canConnect()).thenReturn(true);
362         final WifiConfigController2 controller = mock(WifiConfigController2.class);
363         when(controller.getConfig()).thenReturn(config);
364         final WifiDialog2 wifiDialog2 =  spy(WifiDialog2.createModal(mContext, null /* listener */,
365                 wifiEntry, mode));
366         when(wifiDialog2.getController()).thenReturn(controller);
367         return wifiDialog2;
368     }
369 }
370