diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java b/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java index 71b262de7d7..6d4bd205190 100644 --- a/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java +++ b/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java @@ -21,7 +21,7 @@ import static android.app.slice.Slice.HINT_ERROR; import static androidx.slice.widget.SliceLiveData.SUPPORTED_SPECS; import static com.android.settings.slices.CustomSliceRegistry.BLUETOOTH_DEVICES_SLICE_URI; -import static com.android.settings.slices.CustomSliceRegistry.WIFI_SLICE_URI; +import static com.android.settings.slices.CustomSliceRegistry.CONTEXTUAL_WIFI_SLICE_URI; import android.content.ContentProviderClient; import android.content.ContentResolver; @@ -204,7 +204,7 @@ public class ContextualCardLoader extends AsyncLoaderCompat } private boolean isLargeCard(ContextualCard card) { - return card.getSliceUri().equals(WIFI_SLICE_URI) + return card.getSliceUri().equals(CONTEXTUAL_WIFI_SLICE_URI) || card.getSliceUri().equals(BLUETOOTH_DEVICES_SLICE_URI); } diff --git a/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProvider.java b/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProvider.java index d5500fb37e3..57970433150 100644 --- a/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProvider.java +++ b/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProvider.java @@ -34,8 +34,8 @@ public class SettingsContextualCardProvider extends ContextualCardProvider { public ContextualCardList getContextualCards() { final ContextualCard wifiCard = ContextualCard.newBuilder() - .setSliceUri(CustomSliceRegistry.WIFI_SLICE_URI.toString()) - .setCardName(CustomSliceRegistry.WIFI_SLICE_URI.toString()) + .setSliceUri(CustomSliceRegistry.CONTEXTUAL_WIFI_SLICE_URI.toString()) + .setCardName(CustomSliceRegistry.CONTEXTUAL_WIFI_SLICE_URI.toString()) .setCardCategory(ContextualCard.Category.IMPORTANT) .build(); final ContextualCard connectedDeviceCard = diff --git a/src/com/android/settings/slices/CustomSliceManager.java b/src/com/android/settings/slices/CustomSliceManager.java index 4a9de15d841..bb47df28622 100644 --- a/src/com/android/settings/slices/CustomSliceManager.java +++ b/src/com/android/settings/slices/CustomSliceManager.java @@ -32,7 +32,8 @@ import com.android.settings.homepage.contextualcards.slices.BatteryFixSlice; import com.android.settings.homepage.contextualcards.slices.BluetoothDevicesSlice; import com.android.settings.homepage.contextualcards.slices.LowStorageSlice; import com.android.settings.location.LocationSlice; -import com.android.settings.wifi.WifiSlice; +import com.android.settings.wifi.slice.ContextualWifiSlice; +import com.android.settings.wifi.slice.WifiSlice; import java.util.Map; import java.util.WeakHashMap; @@ -107,6 +108,7 @@ public class CustomSliceManager { mUriMap.put(CustomSliceRegistry.BATTERY_FIX_SLICE_URI, BatteryFixSlice.class); mUriMap.put(CustomSliceRegistry.BATTERY_INFO_SLICE_URI, BatterySlice.class); mUriMap.put(CustomSliceRegistry.BLUETOOTH_DEVICES_SLICE_URI, BluetoothDevicesSlice.class); + mUriMap.put(CustomSliceRegistry.CONTEXTUAL_WIFI_SLICE_URI, ContextualWifiSlice.class); mUriMap.put(CustomSliceRegistry.DATA_USAGE_SLICE_URI, DataUsageSlice.class); mUriMap.put(CustomSliceRegistry.DEVICE_INFO_SLICE_URI, DeviceInfoSlice.class); mUriMap.put(CustomSliceRegistry.EMERGENCY_INFO_SLICE_URI, EmergencyInfoSlice.class); diff --git a/src/com/android/settings/slices/CustomSliceRegistry.java b/src/com/android/settings/slices/CustomSliceRegistry.java index 1b8cffef509..bdf8b35ebda 100644 --- a/src/com/android/settings/slices/CustomSliceRegistry.java +++ b/src/com/android/settings/slices/CustomSliceRegistry.java @@ -80,6 +80,17 @@ public class CustomSliceRegistry { .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION) .appendPath("bluetooth_devices") .build(); + + /** + * Backing Uri for the Wifi Slice. + */ + public static final Uri CONTEXTUAL_WIFI_SLICE_URI = new Uri.Builder() + .scheme(ContentResolver.SCHEME_CONTENT) + .authority(SettingsSlicesContract.AUTHORITY) + .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION) + .appendPath("contextual_wifi") + .build(); + /** * Backing Uri for the Data usage Slice. */ @@ -216,6 +227,7 @@ public class CustomSliceRegistry { .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION) .appendPath(KEY_WIFI) .build(); + /** * Backing Uri for the Zen Mode Slice. */ diff --git a/src/com/android/settings/wifi/WifiDialogActivity.java b/src/com/android/settings/wifi/WifiDialogActivity.java index 9ef6a39a028..c32bcf3d0c6 100644 --- a/src/com/android/settings/wifi/WifiDialogActivity.java +++ b/src/com/android/settings/wifi/WifiDialogActivity.java @@ -38,6 +38,8 @@ public class WifiDialogActivity extends Activity implements WifiDialog.WifiDialo private static final String TAG = "WifiDialogActivity"; + public static final String KEY_ACCESS_POINT_STATE = "access_point_state"; + /** * Boolean extra indicating whether this activity should connect to an access point on the * caller's behalf. If this is set to false, the caller should check @@ -46,9 +48,8 @@ public class WifiDialogActivity extends Activity implements WifiDialog.WifiDialo */ @VisibleForTesting static final String KEY_CONNECT_FOR_CALLER = "connect_for_caller"; - static final String KEY_ACCESS_POINT_STATE = "access_point_state"; - private static final String KEY_WIFI_CONFIGURATION = "wifi_configuration"; + private static final String KEY_WIFI_CONFIGURATION = "wifi_configuration"; private static final int RESULT_CONNECTED = RESULT_FIRST_USER; private static final int RESULT_FORGET = RESULT_FIRST_USER + 1; diff --git a/src/com/android/settings/wifi/slice/ContextualWifiSlice.java b/src/com/android/settings/wifi/slice/ContextualWifiSlice.java new file mode 100644 index 00000000000..fa8c2678e29 --- /dev/null +++ b/src/com/android/settings/wifi/slice/ContextualWifiSlice.java @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.wifi.slice; + +import android.content.Context; +import android.net.Uri; +import android.net.wifi.WifiSsid; +import android.text.TextUtils; +import android.util.Log; + +import androidx.annotation.VisibleForTesting; +import androidx.slice.Slice; + +import com.android.settings.slices.CustomSliceRegistry; +import com.android.settings.slices.CustomSliceable; + +/** + * {@link CustomSliceable} for Wi-Fi, used by contextual homepage. + */ +public class ContextualWifiSlice extends WifiSlice { + + private static final String TAG = "ContextualWifiSlice"; + @VisibleForTesting + boolean mPreviouslyDisplayed; + + public ContextualWifiSlice(Context context) { + super(context); + } + + @Override + public Uri getUri() { + return CustomSliceRegistry.CONTEXTUAL_WIFI_SLICE_URI; + } + + @Override + public Slice getSlice() { + if (!mPreviouslyDisplayed && !TextUtils.equals(getActiveSSID(), WifiSsid.NONE)) { + Log.d(TAG, "Wifi is connected, no point showing any suggestion."); + return null; + } + // Set mPreviouslyDisplayed to true - we will show *something* on the screen. So we should + // keep showing this card to keep UI stable, even if wifi connects to a network later. + mPreviouslyDisplayed = true; + + return super.getSlice(); + } +} diff --git a/src/com/android/settings/wifi/WifiSlice.java b/src/com/android/settings/wifi/slice/WifiSlice.java similarity index 95% rename from src/com/android/settings/wifi/WifiSlice.java rename to src/com/android/settings/wifi/slice/WifiSlice.java index 9f05783421f..4d3a95ad217 100644 --- a/src/com/android/settings/wifi/WifiSlice.java +++ b/src/com/android/settings/wifi/slice/WifiSlice.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.settings.wifi; +package com.android.settings.wifi.slice; import static android.app.slice.Slice.EXTRA_TOGGLE_STATE; import static android.provider.SettingsSlicesContract.KEY_WIFI; @@ -46,6 +46,8 @@ import com.android.settings.core.SubSettingLauncher; import com.android.settings.slices.CustomSliceable; import com.android.settings.slices.SliceBackgroundWorker; import com.android.settings.slices.SliceBuilderUtils; +import com.android.settings.wifi.WifiDialogActivity; +import com.android.settings.wifi.WifiSettings; import com.android.settings.wifi.details.WifiNetworkDetailsFragment; import com.android.settingslib.wifi.AccessPoint; import com.android.settingslib.wifi.WifiTracker; @@ -54,15 +56,15 @@ import java.util.ArrayList; import java.util.List; /** - * Utility class to build a Wifi Slice, and handle all associated actions. + * {@link CustomSliceable} for Wi-Fi, used by generic clients. */ public class WifiSlice implements CustomSliceable { @VisibleForTesting static final int DEFAULT_EXPANDED_ROW_COUNT = 3; + protected final WifiManager mWifiManager; private final Context mContext; - private final WifiManager mWifiManager; public WifiSlice(Context context) { mContext = context; @@ -77,6 +79,7 @@ public class WifiSlice implements CustomSliceable { @Override public Slice getSlice() { final boolean isWifiEnabled = isWifiEnabled(); + final IconCompat icon = IconCompat.createWithResource(mContext, R.drawable.ic_settings_wireless); final String title = mContext.getString(R.string.wifi_settings); @@ -208,6 +211,13 @@ public class WifiSlice implements CustomSliceable { return intent; } + protected String getActiveSSID() { + if (mWifiManager.getWifiState() != WifiManager.WIFI_STATE_ENABLED) { + return WifiSsid.NONE; + } + return WifiInfo.removeDoubleQuotes(mWifiManager.getConnectionInfo().getSSID()); + } + private boolean isWifiEnabled() { switch (mWifiManager.getWifiState()) { case WifiManager.WIFI_STATE_ENABLED: @@ -221,8 +231,7 @@ public class WifiSlice implements CustomSliceable { private CharSequence getSummary() { switch (mWifiManager.getWifiState()) { case WifiManager.WIFI_STATE_ENABLED: - final String ssid = WifiInfo.removeDoubleQuotes(mWifiManager.getConnectionInfo() - .getSSID()); + final String ssid = getActiveSSID(); if (TextUtils.equals(ssid, WifiSsid.NONE)) { return mContext.getText(R.string.disconnected); } diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java index 101ca75ec2d..c62a6bbbfdb 100644 --- a/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java +++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java @@ -145,7 +145,7 @@ public class ContextualCardLoaderTest { cards.add(new ContextualCard.Builder() .setName("test_wifi") .setCardType(ContextualCard.CardType.SLICE) - .setSliceUri(CustomSliceRegistry.WIFI_SLICE_URI) + .setSliceUri(CustomSliceRegistry.CONTEXTUAL_WIFI_SLICE_URI) .build()); cards.add(new ContextualCard.Builder() .setName("test_flashlight") diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProviderTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProviderTest.java index 8f36ea59652..d4b67f51ef1 100644 --- a/tests/robotests/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProviderTest.java +++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProviderTest.java @@ -70,11 +70,12 @@ public class SettingsContextualCardProviderTest { } @Test - public void getContextualCards_wifiSlice_shouldGetCorrectCategory() { + public void getContextualCards_wifiSlice_shouldGetImportantCategory() { final ContextualCardList cards = mProvider.getContextualCards(); ContextualCard wifiCard = null; for (ContextualCard card : cards.getCardList()) { - if (card.getSliceUri().equals(CustomSliceRegistry.WIFI_SLICE_URI.toString())) { + if (card.getSliceUri().equals( + CustomSliceRegistry.CONTEXTUAL_WIFI_SLICE_URI.toString())) { wifiCard = card; } } diff --git a/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java b/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java index b1292677898..7eae3e4ad1a 100644 --- a/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java +++ b/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java @@ -55,7 +55,7 @@ import com.android.settings.testutils.shadow.ShadowLockPatternUtils; import com.android.settings.testutils.shadow.ShadowThreadUtils; import com.android.settings.testutils.shadow.ShadowUserManager; import com.android.settings.testutils.shadow.ShadowUtils; -import com.android.settings.wifi.WifiSlice; +import com.android.settings.wifi.slice.WifiSlice; import com.android.settingslib.wifi.WifiTracker; import org.junit.After; diff --git a/tests/robotests/src/com/android/settings/wifi/slice/ContextualWifiSliceTest.java b/tests/robotests/src/com/android/settings/wifi/slice/ContextualWifiSliceTest.java new file mode 100644 index 00000000000..bf5fba83cc0 --- /dev/null +++ b/tests/robotests/src/com/android/settings/wifi/slice/ContextualWifiSliceTest.java @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.wifi.slice; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; + +import android.content.ContentResolver; +import android.content.Context; +import android.net.wifi.WifiConfiguration; +import android.net.wifi.WifiManager; + +import androidx.core.graphics.drawable.IconCompat; +import androidx.slice.Slice; +import androidx.slice.SliceItem; +import androidx.slice.SliceMetadata; +import androidx.slice.SliceProvider; +import androidx.slice.core.SliceAction; +import androidx.slice.widget.SliceLiveData; + +import com.android.settings.R; +import com.android.settings.testutils.SliceTester; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.RuntimeEnvironment; + +import java.util.List; + +@RunWith(RobolectricTestRunner.class) +public class ContextualWifiSliceTest { + + private Context mContext; + private ContentResolver mResolver; + private WifiManager mWifiManager; + private ContextualWifiSlice mWifiSlice; + + @Before + public void setUp() { + mContext = spy(RuntimeEnvironment.application); + mResolver = mock(ContentResolver.class); + doReturn(mResolver).when(mContext).getContentResolver(); + mWifiManager = mContext.getSystemService(WifiManager.class); + + // Set-up specs for SliceMetadata. + SliceProvider.setSpecs(SliceLiveData.SUPPORTED_SPECS); + mWifiManager.setWifiEnabled(true); + + mWifiSlice = new ContextualWifiSlice(mContext); + } + + @Test + public void getWifiSlice_hasActiveConnection_shouldReturnNull() { + final WifiConfiguration config = new WifiConfiguration(); + config.SSID = "123"; + mWifiManager.connect(config, null /* listener */); + + final Slice wifiSlice = mWifiSlice.getSlice(); + + assertThat(wifiSlice).isNull(); + } + + @Test + public void getWifiSlice_previousDisplayed_hasActiveConnection_shouldHaveTitleAndToggle() { + mWifiSlice.mPreviouslyDisplayed = true; + final WifiConfiguration config = new WifiConfiguration(); + config.SSID = "123"; + mWifiManager.connect(config, null /* listener */); + + final Slice wifiSlice = mWifiSlice.getSlice(); + final SliceMetadata metadata = SliceMetadata.from(mContext, wifiSlice); + + final List toggles = metadata.getToggles(); + assertThat(toggles).hasSize(1); + + final SliceAction primaryAction = metadata.getPrimaryAction(); + final IconCompat expectedToggleIcon = IconCompat.createWithResource(mContext, + R.drawable.ic_settings_wireless); + assertThat(primaryAction.getIcon().toString()).isEqualTo(expectedToggleIcon.toString()); + + final List sliceItems = wifiSlice.getItems(); + SliceTester.assertTitle(sliceItems, mContext.getString(R.string.wifi_settings)); + } +} diff --git a/tests/robotests/src/com/android/settings/wifi/WifiSliceTest.java b/tests/robotests/src/com/android/settings/wifi/slice/WifiSliceTest.java similarity index 96% rename from tests/robotests/src/com/android/settings/wifi/WifiSliceTest.java rename to tests/robotests/src/com/android/settings/wifi/slice/WifiSliceTest.java index 2d4dd045f38..3c78749ddfb 100644 --- a/tests/robotests/src/com/android/settings/wifi/WifiSliceTest.java +++ b/tests/robotests/src/com/android/settings/wifi/slice/WifiSliceTest.java @@ -12,16 +12,15 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * */ -package com.android.settings.wifi; +package com.android.settings.wifi.slice; import static android.app.slice.Slice.HINT_LIST_ITEM; import static android.app.slice.SliceItem.FORMAT_SLICE; import static com.android.settings.slices.CustomSliceRegistry.WIFI_SLICE_URI; -import static com.android.settings.wifi.WifiSlice.DEFAULT_EXPANDED_ROW_COUNT; +import static com.android.settings.wifi.slice.WifiSlice.DEFAULT_EXPANDED_ROW_COUNT; import static com.google.common.truth.Truth.assertThat; @@ -29,7 +28,6 @@ import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; import android.content.ContentResolver; import android.content.Context;