2 * Copyright (C) 2018 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package com.android.settings.wifi.slice;
19 import static android.app.slice.Slice.HINT_LIST_ITEM;
20 import static android.app.slice.SliceItem.FORMAT_SLICE;
22 import static com.android.settings.wifi.slice.WifiSlice.DEFAULT_EXPANDED_ROW_COUNT;
24 import static com.google.common.truth.Truth.assertThat;
26 import static org.mockito.ArgumentMatchers.any;
27 import static org.mockito.Mockito.doReturn;
28 import static org.mockito.Mockito.mock;
29 import static org.mockito.Mockito.spy;
31 import android.content.ContentResolver;
32 import android.content.Context;
33 import android.content.Intent;
34 import android.net.ConnectivityManager;
35 import android.net.NetworkCapabilities;
36 import android.net.NetworkInfo;
37 import android.net.Uri;
38 import android.net.wifi.WifiManager;
40 import androidx.core.graphics.drawable.IconCompat;
41 import androidx.slice.Slice;
42 import androidx.slice.SliceItem;
43 import androidx.slice.SliceMetadata;
44 import androidx.slice.SliceProvider;
45 import androidx.slice.core.SliceAction;
46 import androidx.slice.core.SliceQuery;
47 import androidx.slice.widget.SliceLiveData;
49 import com.android.settings.R;
50 import com.android.settings.slices.SliceBackgroundWorker;
51 import com.android.settings.testutils.SliceTester;
52 import com.android.settingslib.wifi.AccessPoint;
54 import java.util.ArrayList;
55 import java.util.List;
57 import org.junit.Before;
58 import org.junit.Test;
59 import org.junit.runner.RunWith;
60 import org.robolectric.RobolectricTestRunner;
61 import org.robolectric.RuntimeEnvironment;
62 import org.robolectric.annotation.Config;
63 import org.robolectric.annotation.Implementation;
64 import org.robolectric.annotation.Implements;
66 @RunWith(RobolectricTestRunner.class)
67 @Config(shadows = WifiSliceTest.ShadowSliceBackgroundWorker.class)
68 public class WifiSliceTest {
70 private static final String AP1_NAME = "ap1";
71 private static final String AP2_NAME = "ap2";
73 private Context mContext;
74 private ContentResolver mResolver;
75 private WifiManager mWifiManager;
76 private ConnectivityManager mConnectivityManager;
77 private WifiSlice mWifiSlice;
81 mContext = spy(RuntimeEnvironment.application);
82 mResolver = mock(ContentResolver.class);
83 doReturn(mResolver).when(mContext).getContentResolver();
84 mWifiManager = mContext.getSystemService(WifiManager.class);
86 // Set-up specs for SliceMetadata.
87 SliceProvider.setSpecs(SliceLiveData.SUPPORTED_SPECS);
88 mWifiManager.setWifiEnabled(true);
90 mConnectivityManager = spy(mContext.getSystemService(ConnectivityManager.class));
91 doReturn(mConnectivityManager).when(mContext).getSystemService(ConnectivityManager.class);
93 mWifiSlice = new WifiSlice(mContext);
97 public void getWifiSlice_shouldHaveTitleAndToggle() {
98 final Slice wifiSlice = mWifiSlice.getSlice();
100 final SliceMetadata metadata = SliceMetadata.from(mContext, wifiSlice);
101 assertThat(metadata.getTitle()).isEqualTo(mContext.getString(R.string.wifi_settings));
103 final List<SliceAction> toggles = metadata.getToggles();
104 assertThat(toggles).hasSize(1);
106 final SliceAction primaryAction = metadata.getPrimaryAction();
107 final IconCompat expectedToggleIcon = IconCompat.createWithResource(mContext,
108 R.drawable.ic_settings_wireless);
109 assertThat(primaryAction.getIcon().toString()).isEqualTo(expectedToggleIcon.toString());
113 public void getWifiSlice_wifiOff_shouldReturnSingleRow() {
114 mWifiManager.setWifiEnabled(false);
116 final Slice wifiSlice = mWifiSlice.getSlice();
118 final int rows = SliceQuery.findAll(wifiSlice, FORMAT_SLICE, HINT_LIST_ITEM,
119 null /* nonHints */).size();
122 assertThat(rows).isEqualTo(1);
126 public void getWifiSlice_noAp_shouldReturnLoadingRow() {
127 final Slice wifiSlice = mWifiSlice.getSlice();
129 final int rows = SliceQuery.findAll(wifiSlice, FORMAT_SLICE, HINT_LIST_ITEM,
130 null /* nonHints */).size();
131 final List<SliceItem> sliceItems = wifiSlice.getItems();
133 // All AP rows + title row
134 assertThat(rows).isEqualTo(DEFAULT_EXPANDED_ROW_COUNT + 1);
136 SliceTester.assertAnySliceItemContainsSubtitle(sliceItems,
137 mContext.getString(R.string.wifi_empty_list_wifi_on));
140 private AccessPoint createAccessPoint(String name, boolean active, boolean reachable) {
141 final AccessPoint accessPoint = mock(AccessPoint.class);
142 doReturn(name).when(accessPoint).getTitle();
143 doReturn(active).when(accessPoint).isActive();
144 doReturn(reachable).when(accessPoint).isReachable();
146 final NetworkInfo networkInfo = mock(NetworkInfo.class);
147 doReturn(networkInfo).when(accessPoint).getNetworkInfo();
148 doReturn(NetworkInfo.State.CONNECTED).when(networkInfo).getState();
153 private void setWorkerResults(AccessPoint... accessPoints) {
154 final ArrayList<AccessPoint> results = new ArrayList<>();
155 for (AccessPoint ap : accessPoints) {
158 final SliceBackgroundWorker worker = SliceBackgroundWorker.getInstance(mWifiSlice.getUri());
159 doReturn(results).when(worker).getResults();
163 public void getWifiSlice_noReachableAp_shouldReturnLoadingRow() {
165 createAccessPoint(AP1_NAME, false, false),
166 createAccessPoint(AP2_NAME, false, false));
168 final Slice wifiSlice = mWifiSlice.getSlice();
169 final List<SliceItem> sliceItems = wifiSlice.getItems();
171 SliceTester.assertAnySliceItemContainsTitle(sliceItems, AP1_NAME);
172 SliceTester.assertAnySliceItemContainsTitle(sliceItems, AP2_NAME);
174 SliceTester.assertAnySliceItemContainsSubtitle(sliceItems,
175 mContext.getString(R.string.wifi_empty_list_wifi_on));
179 public void getWifiSlice_oneActiveAp_shouldReturnLoadingRow() {
180 setWorkerResults(createAccessPoint(AP1_NAME, true, true));
182 final Slice wifiSlice = mWifiSlice.getSlice();
183 final List<SliceItem> sliceItems = wifiSlice.getItems();
185 SliceTester.assertAnySliceItemContainsTitle(sliceItems, AP1_NAME);
187 SliceTester.assertAnySliceItemContainsSubtitle(sliceItems,
188 mContext.getString(R.string.wifi_empty_list_wifi_on));
192 public void getWifiSlice_oneActiveApAndOneUnreachableAp_shouldReturnLoadingRow() {
194 createAccessPoint(AP1_NAME, true, true),
195 createAccessPoint(AP2_NAME, false, false));
197 final Slice wifiSlice = mWifiSlice.getSlice();
198 final List<SliceItem> sliceItems = wifiSlice.getItems();
200 SliceTester.assertAnySliceItemContainsTitle(sliceItems, AP1_NAME);
201 SliceTester.assertAnySliceItemContainsTitle(sliceItems, AP2_NAME);
203 SliceTester.assertAnySliceItemContainsSubtitle(sliceItems,
204 mContext.getString(R.string.wifi_empty_list_wifi_on));
208 public void getWifiSlice_oneReachableAp_shouldNotReturnLoadingRow() {
209 setWorkerResults(createAccessPoint(AP1_NAME, false, true));
211 final Slice wifiSlice = mWifiSlice.getSlice();
212 final List<SliceItem> sliceItems = wifiSlice.getItems();
214 SliceTester.assertAnySliceItemContainsTitle(sliceItems, AP1_NAME);
216 SliceTester.assertNoSliceItemContainsSubtitle(sliceItems,
217 mContext.getString(R.string.wifi_empty_list_wifi_on));
221 public void getWifiSlice_allReachableAps_shouldNotReturnLoadingRow() {
223 createAccessPoint(AP1_NAME, false, true),
224 createAccessPoint(AP2_NAME, false, true));
226 final Slice wifiSlice = mWifiSlice.getSlice();
227 final List<SliceItem> sliceItems = wifiSlice.getItems();
229 SliceTester.assertAnySliceItemContainsTitle(sliceItems, AP1_NAME);
230 SliceTester.assertAnySliceItemContainsTitle(sliceItems, AP2_NAME);
232 SliceTester.assertNoSliceItemContainsSubtitle(sliceItems,
233 mContext.getString(R.string.wifi_empty_list_wifi_on));
237 public void getWifiSlice_isCaptivePortal_shouldHaveCaptivePortalItems() {
238 setWorkerResults(createAccessPoint(AP1_NAME, true, true));
239 doReturn(makeCaptivePortalNetworkCapabilities()).when(mConnectivityManager)
240 .getNetworkCapabilities(any());
242 final Slice wifiSlice = mWifiSlice.getSlice();
243 final List<SliceItem> sliceItems = wifiSlice.getItems();
245 SliceTester.assertAnySliceItemContainsTitle(sliceItems, AP1_NAME);
246 assertCaptivePortalItems(sliceItems);
249 private void assertCaptivePortalItems(List<SliceItem> sliceItems) {
250 final String expectedSummary = mContext.getString(R.string.switch_on_text);
251 SliceTester.assertAnySliceItemContainsSubtitle(sliceItems, expectedSummary);
253 final IconCompat expectedIcon = IconCompat.createWithResource(mContext,
254 R.drawable.ic_settings_accent);
255 SliceTester.assertAnySliceItemContainsIcon(sliceItems, expectedIcon);
258 static NetworkCapabilities makeCaptivePortalNetworkCapabilities() {
259 final NetworkCapabilities nc = new NetworkCapabilities();
261 nc.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
262 nc.addCapability(NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL);
267 public void handleUriChange_updatesWifi() {
268 final Intent intent = mWifiSlice.getIntent();
269 intent.putExtra(android.app.slice.Slice.EXTRA_TOGGLE_STATE, true);
270 final WifiManager wifiManager = mContext.getSystemService(WifiManager.class);
272 mWifiSlice.onNotifyChange(intent);
274 assertThat(wifiManager.getWifiState()).isEqualTo(WifiManager.WIFI_STATE_ENABLED);
277 @Implements(SliceBackgroundWorker.class)
278 public static class ShadowSliceBackgroundWorker {
279 private static WifiScanWorker mWifiScanWorker = mock(WifiScanWorker.class);
282 public static SliceBackgroundWorker getInstance(Uri uri) {
283 return mWifiScanWorker;