import android.app.settings.SettingsEnums;
import android.content.Context;
import android.content.Intent;
+import android.graphics.Color;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffColorFilter;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
+import android.net.NetworkInfo;
+import android.net.NetworkInfo.State;
import android.net.Uri;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiSsid;
import android.os.Bundle;
+import android.text.Spannable;
+import android.text.SpannableString;
import android.text.TextUtils;
+import android.text.style.ForegroundColorSpan;
import androidx.annotation.VisibleForTesting;
import androidx.core.graphics.drawable.IconCompat;
@Override
public Slice getSlice() {
+ // Reload theme for switching dark mode on/off
+ mContext.getTheme().applyStyle(R.style.Theme_Settings_Home, true /* force */);
+
final boolean isWifiEnabled = isWifiEnabled();
final IconCompat icon = IconCompat.createWithResource(mContext,
R.drawable.ic_settings_wireless);
final String title = mContext.getString(R.string.wifi_settings);
final CharSequence summary = getSummary();
- @ColorInt final int color = getSliceAccentColor();
final PendingIntent toggleAction = getBroadcastIntent(mContext);
final PendingIntent primaryAction = getPrimaryAction();
final SliceAction primarySliceAction = SliceAction.createDeeplink(primaryAction, icon,
null /* actionTitle */, isWifiEnabled);
final ListBuilder listBuilder = new ListBuilder(mContext, getUri(), ListBuilder.INFINITY)
- .setAccentColor(color)
+ .setAccentColor(COLOR_NOT_TINTED)
.addRow(new ListBuilder.RowBuilder()
.setTitle(title)
.setSubtitle(summary)
final SliceBackgroundWorker worker = SliceBackgroundWorker.getInstance(getUri());
final List<AccessPoint> results = worker != null ? worker.getResults() : null;
-
- // Need a loading text when results are not ready.
- boolean needLoadingRow = results == null;
- final int apCount = needLoadingRow ? 0 : results.size();
+ final int apCount = results == null ? 0 : results.size();
+
+ // Need a loading text when results are not ready or out of date.
+ boolean needLoadingRow = true;
+ int index = apCount > 0 && results.get(0).isActive() ? 1 : 0;
+ // This loop checks the existence of reachable APs to determine the validity of the current
+ // AP list.
+ for (; index < apCount; index++) {
+ if (results.get(index).isReachable()) {
+ needLoadingRow = false;
+ break;
+ }
+ }
// Add AP rows
final CharSequence placeholder = mContext.getText(R.string.summary_placeholder);
if (i < apCount) {
listBuilder.addRow(getAccessPointRow(results.get(i)));
} else if (needLoadingRow) {
- listBuilder.addRow(new ListBuilder.RowBuilder()
- .setTitle(mContext.getText(R.string.wifi_empty_list_wifi_on)));
+ listBuilder.addRow(getLoadingRow());
needLoadingRow = false;
} else {
listBuilder.addRow(new ListBuilder.RowBuilder()
}
private ListBuilder.RowBuilder getAccessPointRow(AccessPoint accessPoint) {
- final CharSequence title = accessPoint.getConfigName();
+ final CharSequence title = getAccessPointName(accessPoint);
final IconCompat levelIcon = getAccessPointLevelIcon(accessPoint);
final ListBuilder.RowBuilder rowBuilder = new ListBuilder.RowBuilder()
.setTitleItem(levelIcon, ListBuilder.ICON_IMAGE)
- .setTitle(title)
+ .setSubtitle(title)
.setPrimaryAction(SliceAction.create(
getAccessPointAction(accessPoint), levelIcon, ListBuilder.ICON_IMAGE,
title));
return rowBuilder;
}
- protected IconCompat getAccessPointLevelIcon(AccessPoint accessPoint) {
- return IconCompat.createWithResource(mContext,
- com.android.settingslib.Utils.getWifiIconResource(accessPoint.getLevel()));
+ private CharSequence getAccessPointName(AccessPoint accessPoint) {
+ final CharSequence name = accessPoint.getConfigName();
+ final Spannable span = new SpannableString(name);
+ @ColorInt final int color = Utils.getColorAttrDefaultColor(mContext,
+ android.R.attr.textColorPrimary);
+ span.setSpan(new ForegroundColorSpan(color), 0, name.length(),
+ Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+ return span;
}
- @ColorInt
- protected int getSliceAccentColor() {
- return Utils.getColorAccentDefaultColor(mContext);
+ private IconCompat getAccessPointLevelIcon(AccessPoint accessPoint) {
+ final Drawable d = mContext.getDrawable(
+ com.android.settingslib.Utils.getWifiIconResource(accessPoint.getLevel()));
+
+ @ColorInt int color;
+ if (accessPoint.isActive()) {
+ final NetworkInfo.State state = accessPoint.getNetworkInfo().getState();
+ if (state == NetworkInfo.State.CONNECTED) {
+ color = Utils.getColorAccentDefaultColor(mContext);
+ } else { // connecting
+ color = Utils.getDisabled(mContext, Utils.getColorAttrDefaultColor(mContext,
+ android.R.attr.colorControlNormal));
+ }
+ } else {
+ color = Utils.getColorAttrDefaultColor(mContext, android.R.attr.colorControlNormal);
+ }
+
+ d.setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.SRC_IN));
+ return Utils.createIconWithDrawable(d);
}
private IconCompat getEndIcon(AccessPoint accessPoint) {
if (accessPoint.isActive()) {
- return IconCompat.createWithResource(mContext, R.drawable.ic_settings_accent);
+ return null;
} else if (accessPoint.getSecurity() != AccessPoint.SECURITY_NONE) {
return IconCompat.createWithResource(mContext, R.drawable.ic_friction_lock_closed);
} else if (accessPoint.isMetered()) {
intent, 0 /* flags */);
}
+ private ListBuilder.RowBuilder getLoadingRow() {
+ final CharSequence title = mContext.getText(R.string.wifi_empty_list_wifi_on);
+
+ // for aligning to the Wi-Fi AP's name
+ final IconCompat emptyIcon = Utils.createIconWithDrawable(
+ new ColorDrawable(Color.TRANSPARENT));
+
+ return new ListBuilder.RowBuilder()
+ .setTitleItem(emptyIcon, ListBuilder.ICON_IMAGE)
+ .setSubtitle(title);
+ }
+
/**
* Update the current wifi status to the boolean value keyed by
* {@link android.app.slice.Slice#EXTRA_TOGGLE_STATE} on {@param intent}.
@Override
public void onConnectedChanged() {
- notifySliceChange();
}
@Override
final List<AccessPoint> resultList = new ArrayList<>();
for (AccessPoint ap : accessPoints) {
if (ap.isReachable()) {
- resultList.add(ap);
+ resultList.add(clone(ap));
+ if (resultList.size() >= DEFAULT_EXPANDED_ROW_COUNT) {
+ break;
+ }
}
}
updateResults(resultList);
}
+
+ private AccessPoint clone(AccessPoint accessPoint) {
+ final Bundle savedState = new Bundle();
+ accessPoint.saveWifiState(savedState);
+ return new AccessPoint(mContext, savedState);
+ }
+
+ @Override
+ protected boolean areListsTheSame(List<AccessPoint> a, List<AccessPoint> b) {
+ if (!a.equals(b)) {
+ return false;
+ }
+
+ // compare access point states one by one
+ final int listSize = a.size();
+ for (int i = 0; i < listSize; i++) {
+ if (getState(a.get(i)) != getState(b.get(i))) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private State getState(AccessPoint accessPoint) {
+ final NetworkInfo networkInfo = accessPoint.getNetworkInfo();
+ if (networkInfo != null) {
+ return networkInfo.getState();
+ }
+ return null;
+ }
}
}