Centralize access to wifi framework scoring knobs

One-stop shopping for the configuration values that control
connected network scoring and network selection.

Bug: 65216267
Test: atest FrameworkWifiTests
Change-Id: I9a6c6741a43cbb9b4b47c564ccf392b39e52a897
diff --git a/service/java/com/android/server/wifi/ScoringParams.java b/service/java/com/android/server/wifi/ScoringParams.java
new file mode 100644
index 0000000..71ec781
--- /dev/null
+++ b/service/java/com/android/server/wifi/ScoringParams.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright 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.server.wifi;
+
+import android.content.Context;
+
+import com.android.internal.R;
+
+/**
+ * Holds parameters used for scoring networks.
+ *
+ * Doing this in one place means that there's a better chance of consistency between
+ * connected score and network selection.
+ *
+ */
+public class ScoringParams {
+    private static final int EXIT = 0;
+    private static final int ENTRY = 1;
+    private static final int SUFFICIENT = 2;
+    private static final int GOOD = 3;
+    private final int[] mRssi2 = {-83, -80, -73, -60};
+    private final int[] mRssi5 = {-80, -77, -70, -57};
+
+    public ScoringParams() {
+    }
+
+    public ScoringParams(Context context) {
+        mRssi2[EXIT] = context.getResources().getInteger(
+                R.integer.config_wifi_framework_wifi_score_bad_rssi_threshold_24GHz);
+        mRssi2[ENTRY] = context.getResources().getInteger(
+                R.integer.config_wifi_framework_wifi_score_entry_rssi_threshold_24GHz);
+        mRssi2[SUFFICIENT] = context.getResources().getInteger(
+                R.integer.config_wifi_framework_wifi_score_low_rssi_threshold_24GHz);
+        mRssi2[GOOD] = context.getResources().getInteger(
+                R.integer.config_wifi_framework_wifi_score_good_rssi_threshold_24GHz);
+        mRssi5[EXIT] = context.getResources().getInteger(
+                R.integer.config_wifi_framework_wifi_score_bad_rssi_threshold_5GHz);
+        mRssi5[ENTRY] = context.getResources().getInteger(
+                R.integer.config_wifi_framework_wifi_score_entry_rssi_threshold_5GHz);
+        mRssi5[SUFFICIENT] = context.getResources().getInteger(
+                R.integer.config_wifi_framework_wifi_score_low_rssi_threshold_5GHz);
+        mRssi5[GOOD] = context.getResources().getInteger(
+                R.integer.config_wifi_framework_wifi_score_good_rssi_threshold_5GHz);
+    }
+
+    private static final int MINIMUM_5GHZ_BAND_FREQUENCY_IN_MEGAHERTZ = 5000;
+
+    /** Constant to denote someplace in the 2.4 GHz band */
+    public static final int BAND2 = 2400;
+
+    /** Constant to denote someplace in the 5 GHz band */
+    public static final int BAND5 = 5000;
+
+    /**
+     * Returns the RSSI value at which the connection is deemed to be unusable,
+     * in the absence of other indications.
+     */
+    public int getExitRssi(int frequencyMegaHertz) {
+        return getRssiArray(frequencyMegaHertz)[EXIT];
+    }
+
+    /**
+     * Returns the minimum scan RSSI for making a connection attempt.
+     */
+    public int getEntryRssi(int frequencyMegaHertz) {
+        return getRssiArray(frequencyMegaHertz)[ENTRY];
+    }
+
+    /**
+     * Returns a connected RSSI value that indicates the connection is
+     * good enough that we needn't scan for alternatives.
+     */
+    public int getSufficientRssi(int frequencyMegaHertz) {
+        return getRssiArray(frequencyMegaHertz)[SUFFICIENT];
+    }
+
+    /**
+     * Returns a connected RSSI value that indicates a good connection.
+     */
+    public int getGoodRssi(int frequencyMegaHertz) {
+        return getRssiArray(frequencyMegaHertz)[GOOD];
+    }
+
+    private int[] getRssiArray(int frequencyMegaHertz) {
+        if (frequencyMegaHertz < MINIMUM_5GHZ_BAND_FREQUENCY_IN_MEGAHERTZ) {
+            return mRssi2;
+        } else {
+            return mRssi5;
+        }
+    }
+}
diff --git a/service/java/com/android/server/wifi/VelocityBasedConnectedScore.java b/service/java/com/android/server/wifi/VelocityBasedConnectedScore.java
index bfc51f6..e4f42d2 100644
--- a/service/java/com/android/server/wifi/VelocityBasedConnectedScore.java
+++ b/service/java/com/android/server/wifi/VelocityBasedConnectedScore.java
@@ -33,7 +33,7 @@
     private final int mThresholdMinimumRssi5;      // -82
     private final int mThresholdMinimumRssi24;     // -85
 
-    private int mFrequency = 5000;
+    private int mFrequency = ScoringParams.BAND5;
     private double mThresholdMinimumRssi;
     private double mThresholdAdjustment;
     private final KalmanFilter mFilter;
diff --git a/tests/wifitests/src/com/android/server/wifi/ScoringParamsTest.java b/tests/wifitests/src/com/android/server/wifi/ScoringParamsTest.java
new file mode 100644
index 0000000..5047701
--- /dev/null
+++ b/tests/wifitests/src/com/android/server/wifi/ScoringParamsTest.java
@@ -0,0 +1,133 @@
+/*
+ * 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.server.wifi;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.test.filters.SmallTest;
+
+import com.android.internal.R;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.Spy;
+
+/**
+ * Unit tests for {@link com.android.server.wifi.ScoringParams}.
+ */
+@SmallTest
+public class ScoringParamsTest {
+
+    ScoringParams mScoringParams;
+
+    int mBad2GHz, mEntry2GHz, mSufficient2GHz, mGood2GHz;
+    int mBad5GHz, mEntry5GHz, mSufficient5GHz, mGood5GHz;
+
+    @Mock Context mContext;
+    @Spy private MockResources mResources = new MockResources();
+
+    private int setupIntegerResource(int resourceName, int value) {
+        doReturn(value).when(mResources).getInteger(resourceName);
+        return value;
+    }
+
+    /**
+     * Sets up resource values for testing
+     *
+     * See frameworks/base/core/res/res/values/config.xml
+     */
+    private void setUpResources(Resources resources) {
+        mBad2GHz = setupIntegerResource(
+                R.integer.config_wifi_framework_wifi_score_bad_rssi_threshold_24GHz, -88);
+        mEntry2GHz = setupIntegerResource(
+                R.integer.config_wifi_framework_wifi_score_entry_rssi_threshold_24GHz, -77);
+        mSufficient2GHz = setupIntegerResource(
+                R.integer.config_wifi_framework_wifi_score_low_rssi_threshold_24GHz, -66);
+        mGood2GHz = setupIntegerResource(
+                R.integer.config_wifi_framework_wifi_score_good_rssi_threshold_24GHz, -55);
+        mBad5GHz = setupIntegerResource(
+                R.integer.config_wifi_framework_wifi_score_bad_rssi_threshold_5GHz, -80);
+        mEntry5GHz = setupIntegerResource(
+                R.integer.config_wifi_framework_wifi_score_entry_rssi_threshold_5GHz, -70);
+        mSufficient5GHz = setupIntegerResource(
+                R.integer.config_wifi_framework_wifi_score_low_rssi_threshold_5GHz, -60);
+        mGood5GHz = setupIntegerResource(
+                R.integer.config_wifi_framework_wifi_score_good_rssi_threshold_5GHz, -50);
+    }
+
+    /**
+     * Sets up for unit test
+     */
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        setUpResources(mResources);
+        when(mContext.getResources()).thenReturn(mResources);
+        mScoringParams = new ScoringParams();
+    }
+
+    /**
+     * Check that thresholds are properly ordered, and in range.
+     */
+    private void checkThresholds(int frequency) {
+        assertTrue(-127 <= mScoringParams.getExitRssi(frequency));
+        assertTrue(mScoringParams.getExitRssi(frequency)
+                <= mScoringParams.getEntryRssi(frequency));
+        assertTrue(mScoringParams.getEntryRssi(frequency)
+                <= mScoringParams.getSufficientRssi(frequency));
+        assertTrue(mScoringParams.getSufficientRssi(frequency)
+                <= mScoringParams.getGoodRssi(frequency));
+        assertTrue(mScoringParams.getGoodRssi(frequency) < 0);
+    }
+
+    /**
+     * Test basic constuctor
+     */
+    @Test
+    public void testBasicConstructor() {
+        mScoringParams = new ScoringParams();
+        checkThresholds(2412);
+        checkThresholds(5020);
+    }
+
+    /**
+     * Check that we get the config.xml values, if that's what we want
+     */
+    @Test
+    public void testContextConstructor() {
+        mScoringParams = new ScoringParams(mContext);
+
+        assertEquals(mBad2GHz, mScoringParams.getExitRssi(2412));
+        assertEquals(mEntry2GHz, mScoringParams.getEntryRssi(2480));
+        assertEquals(mSufficient2GHz, mScoringParams.getSufficientRssi(2400));
+        assertEquals(mGood2GHz, mScoringParams.getGoodRssi(2499));
+        assertEquals(mGood2GHz, mScoringParams.getGoodRssi(ScoringParams.BAND2));
+
+        assertEquals(mBad5GHz, mScoringParams.getExitRssi(5000));
+        assertEquals(mEntry5GHz, mScoringParams.getEntryRssi(5010));
+        assertEquals(mSufficient5GHz, mScoringParams.getSufficientRssi(5100));
+        assertEquals(mGood5GHz, mScoringParams.getGoodRssi(5678));
+        assertEquals(mGood5GHz, mScoringParams.getGoodRssi(ScoringParams.BAND5));
+    }
+}