Hide wifi card sometimes.

When there is a connected wifi, we now hide the wifi slice card.

However, if we initially shows this card but later wifi is connected
while the card is visible, we keep showing this card to avoid janky
animation. The card will be gone if user nagivates to a different UI and
comes back.

- Create a new slice ContextualWifiSlice for homepage use case, all
  special logic for homepage are added here.
- Change reference for WIFI_SLICE to CONTEXTUAL_WIFI_SLICE where make
  sense.

Change-Id: Ibd87f88058f357aabef0f7d68a5bf48350d75b06
Fixes: 121040746
Test: robotests
This commit is contained in:
Fan Zhang
2018-12-17 13:22:42 -08:00
parent c86fa1eb2a
commit 0db4ead2b3
12 changed files with 207 additions and 20 deletions

View File

@@ -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<List<ContextualCard>
}
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);
}

View File

@@ -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 =

View File

@@ -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);

View File

@@ -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.
*/

View File

@@ -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;

View File

@@ -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();
}
}

View File

@@ -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);
}

View File

@@ -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")

View File

@@ -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;
}
}

View File

@@ -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;

View File

@@ -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<SliceAction> 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<SliceItem> sliceItems = wifiSlice.getItems();
SliceTester.assertTitle(sliceItems, mContext.getString(R.string.wifi_settings));
}
}

View File

@@ -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;