new ConcurrentHashMap<String, ScanResult>(32);
private static final long MAX_SCAN_RESULT_AGE_MS = 15000;
- private static final String KEY_NETWORKINFO = "key_networkinfo";
- private static final String KEY_WIFIINFO = "key_wifiinfo";
- private static final String KEY_SCANRESULT = "key_scanresult";
- private static final String KEY_SSID = "key_ssid";
- private static final String KEY_SECURITY = "key_security";
- private static final String KEY_PSKTYPE = "key_psktype";
- private static final String KEY_SCANRESULTCACHE = "key_scanresultcache";
- private static final String KEY_CONFIG = "key_config";
- private static final AtomicInteger sLastId = new AtomicInteger(0);
+ static final String KEY_NETWORKINFO = "key_networkinfo";
+ static final String KEY_WIFIINFO = "key_wifiinfo";
+ static final String KEY_SCANRESULT = "key_scanresult";
+ static final String KEY_SSID = "key_ssid";
+ static final String KEY_SECURITY = "key_security";
+ static final String KEY_PSKTYPE = "key_psktype";
+ static final String KEY_SCANRESULTCACHE = "key_scanresultcache";
+ static final String KEY_CONFIG = "key_config";
+ static final AtomicInteger sLastId = new AtomicInteger(0);
/**
* These values are matched in string arrays -- changes must be kept in sync
public static final int SIGNAL_LEVELS = 4;
+ static final int UNREACHABLE_RSSI = Integer.MAX_VALUE;
+
private final Context mContext;
private String ssid;
private WifiConfiguration mConfig;
- private int mRssi = Integer.MAX_VALUE;
+ private int mRssi = UNREACHABLE_RSSI;
private long mSeen = 0;
private WifiInfo mInfo;
this.mRankingScore = that.mRankingScore;
}
+ /**
+ * Returns a negative integer, zero, or a positive integer if this AccessPoint is less than,
+ * equal to, or greater than the other AccessPoint.
+ *
+ * Sort order rules for AccessPoints:
+ * 1. Active before inactive
+ * 2. Reachable before unreachable
+ * 3. Saved before unsaved
+ * 4. (Internal only) Network ranking score
+ * 5. Stronger signal before weaker signal
+ * 6. SSID alphabetically
+ *
+ * Note that AccessPoints with a signal are usually also Reachable,
+ * and will thus appear before unreachable saved AccessPoints.
+ */
@Override
public int compareTo(@NonNull AccessPoint other) {
// Active one goes first.
if (!isActive() && other.isActive()) return 1;
// Reachable one goes before unreachable one.
- if (mRssi != Integer.MAX_VALUE && other.mRssi == Integer.MAX_VALUE) return -1;
- if (mRssi == Integer.MAX_VALUE && other.mRssi != Integer.MAX_VALUE) return 1;
+ if (isReachable() && !other.isReachable()) return -1;
+ if (!isReachable() && other.isReachable()) return 1;
// Configured (saved) one goes before unconfigured one.
- if (networkId != WifiConfiguration.INVALID_NETWORK_ID
- && other.networkId == WifiConfiguration.INVALID_NETWORK_ID) return -1;
- if (networkId == WifiConfiguration.INVALID_NETWORK_ID
- && other.networkId != WifiConfiguration.INVALID_NETWORK_ID) return 1;
+ if (isSaved() && !other.isSaved()) return -1;
+ if (!isSaved() && other.isSaved()) return 1;
// Higher scores go before lower scores
- if (mRankingScore != other.mRankingScore) {
- return (mRankingScore > other.mRankingScore) ? -1 : 1;
+ if (getRankingScore() != other.getRankingScore()) {
+ return (getRankingScore() > other.getRankingScore()) ? -1 : 1;
}
// Sort by signal strength, bucketed by level
return difference;
}
// Sort by ssid.
- return ssid.compareToIgnoreCase(other.ssid);
+ return getSsidStr().compareToIgnoreCase(other.getSsidStr());
}
@Override
}
public int getLevel() {
- if (mRssi == Integer.MAX_VALUE) {
+ if (!isReachable()) {
return -1;
}
return WifiManager.calculateSignalLevel(mRssi, SIGNAL_LEVELS);
}
} else if (config != null && config.getNetworkSelectionStatus().isNotRecommended()) {
summary.append(mContext.getString(R.string.wifi_disabled_by_recommendation_provider));
- } else if (mRssi == Integer.MAX_VALUE) { // Wifi out of range
+ } else if (!isReachable()) { // Wifi out of range
summary.append(mContext.getString(R.string.wifi_not_in_range));
} else { // In range, not disabled.
if (config != null) { // Is saved network
return mBadge;
}
+ /** Return true if the current RSSI is reachable, and false otherwise. */
+ boolean isReachable() {
+ return mRssi != UNREACHABLE_RSSI;
+ }
+
public static String getSummary(Context context, String ssid, DetailedState state,
boolean isEphemeral, String passpointProvider) {
if (state == DetailedState.CONNECTED && ssid == null) {
*/
package com.android.settingslib.wifi;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertSame;
-import static org.junit.Assert.assertTrue;
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
import android.content.Context;
import android.net.ConnectivityManager;
import org.junit.runner.RunWith;
import java.util.ArrayList;
+import java.util.Collections;
@SmallTest
@RunWith(AndroidJUnit4.class)
final AccessPoint ap = new AccessPoint(InstrumentationRegistry.getTargetContext(), bundle);
final CharSequence ssid = ap.getSsid();
- assertTrue(ssid instanceof SpannableString);
+ assertThat(ssid instanceof SpannableString).isTrue();
TtsSpan[] spans = ((SpannableString) ssid).getSpans(0, TEST_SSID.length(), TtsSpan.class);
- assertEquals(1, spans.length);
- assertEquals(TtsSpan.TYPE_TELEPHONE, spans[0].getType());
+ assertThat(spans.length).isEqualTo(1);
+ assertThat(spans[0].getType()).isEqualTo(TtsSpan.TYPE_TELEPHONE);
}
@Test
originalAccessPoint.update(configuration, wifiInfo, networkInfo);
AccessPoint copy = new AccessPoint(mContext, originalAccessPoint);
- assertEquals(originalAccessPoint.getSsid().toString(), copy.getSsid().toString());
- assertEquals(originalAccessPoint.getBssid(), copy.getBssid());
- assertSame(originalAccessPoint.getConfig(), copy.getConfig());
- assertEquals(originalAccessPoint.getSecurity(), copy.getSecurity());
- assertTrue(originalAccessPoint.compareTo(copy) == 0);
+ assertThat(originalAccessPoint.getSsid().toString()).isEqualTo(copy.getSsid().toString());
+ assertThat(originalAccessPoint.getBssid()).isEqualTo(copy.getBssid());
+ assertThat(originalAccessPoint.getConfig()).isEqualTo(copy.getConfig());
+ assertThat(originalAccessPoint.getSecurity()).isEqualTo(copy.getSecurity());
+ assertThat(originalAccessPoint.compareTo(copy) == 0).isTrue();
}
@Test
bundle.putParcelableArrayList("key_scanresultcache", scanResults);
AccessPoint original = new AccessPoint(mContext, bundle);
- assertEquals(4, original.getRssi());
+ assertThat(original.getRssi()).isEqualTo(4);
AccessPoint copy = new AccessPoint(mContext, createWifiConfiguration());
- assertEquals(Integer.MIN_VALUE, copy.getRssi());
+ assertThat(copy.getRssi()).isEqualTo(Integer.MIN_VALUE);
copy.copyFrom(original);
- assertEquals(original.getRssi(), copy.getRssi());
+ assertThat(original.getRssi()).isEqualTo(copy.getRssi());
+ }
+
+ @Test
+ public void testCompareTo_GivesActiveBeforeInactive() {
+ AccessPoint activeAp = new TestAccessPointBuilder(mContext).setActive(true).build();
+ AccessPoint inactiveAp = new TestAccessPointBuilder(mContext).setActive(false).build();
+
+ assertSortingWorks(activeAp, inactiveAp);
+ }
+
+ @Test
+ public void testCompareTo_GivesReachableBeforeUnreachable() {
+ AccessPoint nearAp = new TestAccessPointBuilder(mContext).setReachable(true).build();
+ AccessPoint farAp = new TestAccessPointBuilder(mContext).setReachable(false).build();
+
+ assertSortingWorks(nearAp, farAp);
+ }
+
+ @Test
+ public void testCompareTo_GivesSavedBeforeUnsaved() {
+ AccessPoint savedAp = new TestAccessPointBuilder(mContext).setSaved(true).build();
+ AccessPoint notSavedAp = new TestAccessPointBuilder(mContext).setSaved(false).build();
+
+ assertSortingWorks(savedAp, notSavedAp);
+ }
+
+ //TODO: add tests for mRankingScore sort order if ranking is exposed
+
+ @Test
+ public void testCompareTo_GivesHighLevelBeforeLowLevel() {
+ final int highLevel = AccessPoint.SIGNAL_LEVELS - 1;
+ final int lowLevel = 1;
+ assertThat(highLevel).isGreaterThan(lowLevel);
+
+ AccessPoint strongAp = new TestAccessPointBuilder(mContext).setLevel(highLevel).build();
+ AccessPoint weakAp = new TestAccessPointBuilder(mContext).setLevel(lowLevel).build();
+
+ assertSortingWorks(strongAp, weakAp);
+ }
+
+ @Test
+ public void testCompareTo_GivesSsidAlphabetically() {
+
+ final String firstName = "AAAAAA";
+ final String secondName = "zzzzzz";
+
+ AccessPoint firstAp = new TestAccessPointBuilder(mContext).setSsid(firstName).build();
+ AccessPoint secondAp = new TestAccessPointBuilder(mContext).setSsid(secondName).build();
+
+ assertThat(firstAp.getSsidStr().compareToIgnoreCase(secondAp.getSsidStr()) < 0).isTrue();
+ assertSortingWorks(firstAp, secondAp);
+ }
+
+ @Test
+ public void testCompareTo_AllSortingRulesCombined() {
+
+ AccessPoint active = new TestAccessPointBuilder(mContext).setActive(true).build();
+ AccessPoint reachableAndMinLevel = new TestAccessPointBuilder(mContext)
+ .setReachable(true).build();
+ AccessPoint saved = new TestAccessPointBuilder(mContext).setSaved(true).build();
+ AccessPoint highLevelAndReachable = new TestAccessPointBuilder(mContext)
+ .setLevel(AccessPoint.SIGNAL_LEVELS - 1).build();
+ AccessPoint firstName = new TestAccessPointBuilder(mContext).setSsid("a").build();
+ AccessPoint lastname = new TestAccessPointBuilder(mContext).setSsid("z").build();
+
+ ArrayList<AccessPoint> points = new ArrayList<AccessPoint>();
+ points.add(lastname);
+ points.add(firstName);
+ points.add(highLevelAndReachable);
+ points.add(saved);
+ points.add(reachableAndMinLevel);
+ points.add(active);
+
+ Collections.sort(points);
+ assertThat(points.indexOf(active)).isLessThan(points.indexOf(reachableAndMinLevel));
+ assertThat(points.indexOf(reachableAndMinLevel)).isLessThan(points.indexOf(saved));
+ // note: the saved AP will not appear before highLevelAndReachable,
+ // because all APs with a signal level are reachable,
+ // and isReachable() takes higher sorting precedence than isSaved().
+ assertThat(points.indexOf(saved)).isLessThan(points.indexOf(firstName));
+ assertThat(points.indexOf(highLevelAndReachable)).isLessThan(points.indexOf(firstName));
+ assertThat(points.indexOf(firstName)).isLessThan(points.indexOf(lastname));
}
private WifiConfiguration createWifiConfiguration() {
configuration.networkId = 123;
return configuration;
}
+
+ /**
+ * Assert that the first AccessPoint appears after the second AccessPoint
+ * once sorting has been completed.
+ */
+ private void assertSortingWorks(AccessPoint first, AccessPoint second) {
+
+ ArrayList<AccessPoint> points = new ArrayList<AccessPoint>();
+
+ // add in reverse order so we can tell that sorting actually changed something
+ points.add(second);
+ points.add(first);
+ Collections.sort(points);
+ assertWithMessage(
+ String.format("After sorting: second AccessPoint should have higher array index "
+ + "than the first, but found indicies second '%s' and first '%s'.",
+ points.indexOf(second), points.indexOf(first)))
+ .that(points.indexOf(second)).isGreaterThan(points.indexOf(first));
+ }
+
+ @Test
+ public void testBuilder_setActive() {
+ AccessPoint activeAp = new TestAccessPointBuilder(mContext).setActive(true).build();
+ assertThat(activeAp.isActive()).isTrue();
+
+ AccessPoint inactiveAp = new TestAccessPointBuilder(mContext).setActive(false).build();
+ assertThat(inactiveAp.isActive()).isFalse();
+ }
+
+ @Test
+ public void testBuilder_setReachable() {
+ AccessPoint nearAp = new TestAccessPointBuilder(mContext).setReachable(true).build();
+ assertThat(nearAp.isReachable()).isTrue();
+
+ AccessPoint farAp = new TestAccessPointBuilder(mContext).setReachable(false).build();
+ assertThat(farAp.isReachable()).isFalse();
+ }
+
+ @Test
+ public void testBuilder_setSaved() {
+ AccessPoint savedAp = new TestAccessPointBuilder(mContext).setSaved(true).build();
+ assertThat(savedAp.isSaved()).isTrue();
+
+ AccessPoint newAp = new TestAccessPointBuilder(mContext).setSaved(false).build();
+ assertThat(newAp.isSaved()).isFalse();
+ }
+
+ @Test
+ public void testBuilder_setLevel() {
+ AccessPoint testAp;
+
+ for (int i = 0; i < AccessPoint.SIGNAL_LEVELS; i++) {
+ testAp = new TestAccessPointBuilder(mContext).setLevel(i).build();
+ assertThat(testAp.getLevel()).isEqualTo(i);
+ }
+
+ // numbers larger than the max level should be set to max
+ testAp = new TestAccessPointBuilder(mContext).setLevel(AccessPoint.SIGNAL_LEVELS).build();
+ assertThat(testAp.getLevel()).isEqualTo(AccessPoint.SIGNAL_LEVELS - 1);
+
+ // numbers less than 0 should give level 0
+ testAp = new TestAccessPointBuilder(mContext).setLevel(-100).build();
+ assertThat(testAp.getLevel()).isEqualTo(0);
+ }
+
+ @Test
+ public void testBuilder_settingReachableAfterLevelDoesNotAffectLevel() {
+ int level = 1;
+ assertThat(level).isLessThan(AccessPoint.SIGNAL_LEVELS - 1);
+
+ AccessPoint testAp =
+ new TestAccessPointBuilder(mContext).setLevel(level).setReachable(true).build();
+ assertThat(testAp.getLevel()).isEqualTo(level);
+ }
+
+ @Test
+ public void testBuilder_setSsid() {
+ String name = "AmazingSsid!";
+ AccessPoint namedAp = new TestAccessPointBuilder(mContext).setSsid(name).build();
+ assertThat(namedAp.getSsidStr()).isEqualTo(name);
+ }
}
--- /dev/null
+/*
+ * Copyright (C) 2017 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.settingslib.wifi;
+
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.net.wifi.WifiConfiguration;
+import android.os.Bundle;
+
+/**
+* Build and return a valid AccessPoint.
+*
+* Only intended for testing the AccessPoint class;
+* AccessPoints were designed to only be populated
+* by the mechanisms of scan results and wifi configurations.
+*/
+public class TestAccessPointBuilder {
+ // match the private values in WifiManager
+ private static final int MIN_RSSI = -100;
+ private static final int MAX_RSSI = -55;
+
+ // set some sensible defaults
+ private int mRssi = AccessPoint.UNREACHABLE_RSSI;
+ private int networkId = WifiConfiguration.INVALID_NETWORK_ID;
+ private String ssid = "TestSsid";
+ private NetworkInfo mNetworkInfo = null;
+
+ Context mContext;
+
+ public TestAccessPointBuilder(Context context) {
+ mContext = context;
+ }
+
+ public AccessPoint build() {
+ Bundle bundle = new Bundle();
+
+ WifiConfiguration wifiConig = new WifiConfiguration();
+ wifiConig.networkId = networkId;
+
+ bundle.putString(AccessPoint.KEY_SSID, ssid);
+ bundle.putParcelable(AccessPoint.KEY_CONFIG, wifiConig);
+ bundle.putParcelable(AccessPoint.KEY_NETWORKINFO, mNetworkInfo);
+ AccessPoint ap = new AccessPoint(mContext, bundle);
+ ap.setRssi(mRssi);
+ return ap;
+ }
+
+ public TestAccessPointBuilder setActive(boolean active) {
+ if (active) {
+ mNetworkInfo = new NetworkInfo(
+ ConnectivityManager.TYPE_DUMMY,
+ ConnectivityManager.TYPE_DUMMY,
+ "TestNetwork",
+ "TestNetwork");
+ } else {
+ mNetworkInfo = null;
+ }
+ return this;
+ }
+
+ /**
+ * Set the signal level.
+ * Side effect: if this AccessPoint was previously unreachable,
+ * setting the level will also make it reachable.
+ */
+ public TestAccessPointBuilder setLevel(int level) {
+ int outputRange = AccessPoint.SIGNAL_LEVELS - 1;
+
+ if (level > outputRange) {
+ level = outputRange;
+ } else if (level < 0) {
+ level = 0;
+ }
+
+ int inputRange = MAX_RSSI - MIN_RSSI;
+
+ // calculate the rssi required to get the level we want.
+ // this is a rearrangement of the formula from WifiManager.calculateSignalLevel()
+ mRssi = (int)((float)(level * inputRange) / (float)outputRange) + MIN_RSSI;
+ return this;
+ }
+
+ /**
+ * Set whether the AccessPoint is reachable.
+ * Side effect: if the signal level was not previously set,
+ * making an AccessPoint reachable will set the signal to the minimum level.
+ */
+ public TestAccessPointBuilder setReachable(boolean reachable) {
+ if (reachable) {
+ // only override the mRssi if it hasn't been set yet
+ if (mRssi == AccessPoint.UNREACHABLE_RSSI) {
+ mRssi = MIN_RSSI;
+ }
+ } else {
+ mRssi = AccessPoint.UNREACHABLE_RSSI;
+ }
+ return this;
+ }
+
+ public TestAccessPointBuilder setSaved(boolean saved){
+ if (saved) {
+ networkId = 1;
+ } else {
+ networkId = WifiConfiguration.INVALID_NETWORK_ID;
+ }
+ return this;
+ }
+
+ public TestAccessPointBuilder setSsid(String newSsid) {
+ ssid = newSsid;
+ return this;
+ }
+}