summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Su <dysu@google.com>2019-11-18 12:38:29 -0800
committerDavid Su <dysu@google.com>2019-11-20 15:16:33 -0800
commit715d84220344db0b13fd2abf1c6a1640f8e494d6 (patch)
treeda5777d7b671825bbcf2f804c500daab8b2bc7cd
parentdda5fd8b34cc817823f4cd6a597c2a14cd0aebe6 (diff)
Allow RSSI Level thresholds to be customized
RSSI Level thresholds can now be customized using an overlay. Migrated calls of WifiManager.calculateSignalLevel(rssi, numLevels) in Wifi Service to WifiManager.calculateSignalLevel(rssi) to take into account the overlaid thresholds. Bug: 140781184 Test: atest FrameworksWifiTests Test: overlay thresholds, see that calculateSignalLevel(rssi) uses the overlaid thresholds. Change-Id: Ib9d0a3da363d152d6c4f49c26431fede4c3acdab
-rw-r--r--service/java/com/android/server/wifi/ClientModeImpl.java5
-rw-r--r--service/java/com/android/server/wifi/WifiServiceImpl.java7
-rw-r--r--service/java/com/android/server/wifi/util/RssiUtil.java44
-rw-r--r--service/res/values/config.xml25
-rw-r--r--service/res/values/overlayable.xml1
-rw-r--r--tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java3
-rw-r--r--tests/wifitests/src/com/android/server/wifi/util/RssiUtilTest.java124
7 files changed, 206 insertions, 3 deletions
diff --git a/service/java/com/android/server/wifi/ClientModeImpl.java b/service/java/com/android/server/wifi/ClientModeImpl.java
index dfd92d3e2..e3966289d 100644
--- a/service/java/com/android/server/wifi/ClientModeImpl.java
+++ b/service/java/com/android/server/wifi/ClientModeImpl.java
@@ -113,6 +113,7 @@ import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiIsUnusableEvent;
import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiUsabilityStats;
import com.android.server.wifi.util.ExternalCallbackTracker;
import com.android.server.wifi.util.NativeUtil;
+import com.android.server.wifi.util.RssiUtil;
import com.android.server.wifi.util.TelephonyUtil;
import com.android.server.wifi.util.TelephonyUtil.SimAuthRequestData;
import com.android.server.wifi.util.TelephonyUtil.SimAuthResponseData;
@@ -2293,7 +2294,7 @@ public class ClientModeImpl extends StateMachine {
* interested in RSSI of all the changes in signal
* level.
*/
- int newSignalLevel = WifiManager.calculateSignalLevel(newRssi, WifiManager.RSSI_LEVELS);
+ int newSignalLevel = RssiUtil.calculateSignalLevel(mContext, newRssi);
if (newSignalLevel != mLastSignalLevel) {
updateCapabilities();
sendRssiChangeBroadcast(newRssi);
@@ -2386,7 +2387,7 @@ public class ClientModeImpl extends StateMachine {
private void sendRssiChangeBroadcast(final int newRssi) {
mBatteryStatsManager.noteWifiRssiChanged(newRssi);
StatsLog.write(StatsLog.WIFI_SIGNAL_STRENGTH_CHANGED,
- WifiManager.calculateSignalLevel(newRssi, WifiManager.RSSI_LEVELS));
+ RssiUtil.calculateSignalLevel(mContext, newRssi));
Intent intent = new Intent(WifiManager.RSSI_CHANGED_ACTION);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
diff --git a/service/java/com/android/server/wifi/WifiServiceImpl.java b/service/java/com/android/server/wifi/WifiServiceImpl.java
index b4e749ca7..38b501a7b 100644
--- a/service/java/com/android/server/wifi/WifiServiceImpl.java
+++ b/service/java/com/android/server/wifi/WifiServiceImpl.java
@@ -81,7 +81,6 @@ import android.os.BatteryStats;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
-import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
@@ -109,6 +108,7 @@ import com.android.internal.util.AsyncChannel;
import com.android.server.wifi.hotspot2.PasspointManager;
import com.android.server.wifi.hotspot2.PasspointProvider;
import com.android.server.wifi.util.ExternalCallbackTracker;
+import com.android.server.wifi.util.RssiUtil;
import com.android.server.wifi.util.WifiHandler;
import com.android.server.wifi.util.WifiPermissionsUtil;
import com.android.wifi.R;
@@ -3574,4 +3574,9 @@ public class WifiServiceImpl extends BaseWifiService {
.unregisterSuggestionConnectionStatusListener(listenerIdentifier,
packageName));
}
+
+ @Override
+ public int calculateSignalLevel(int rssi) {
+ return RssiUtil.calculateSignalLevel(mContext, rssi);
+ }
}
diff --git a/service/java/com/android/server/wifi/util/RssiUtil.java b/service/java/com/android/server/wifi/util/RssiUtil.java
new file mode 100644
index 000000000..a1a1d57c2
--- /dev/null
+++ b/service/java/com/android/server/wifi/util/RssiUtil.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2019 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.util;
+
+import android.annotation.NonNull;
+import android.content.Context;
+
+import com.android.wifi.R;
+
+/** Utilities for computations involving RSSI. */
+public class RssiUtil {
+ private RssiUtil() {}
+
+ /** Calculate RSSI level from RSSI using overlaid RSSI level thresholds. */
+ public static int calculateSignalLevel(Context context, int rssi) {
+ int[] thresholds = getRssiLevelThresholds(context);
+
+ for (int level = 0; level < thresholds.length; level++) {
+ if (rssi < thresholds[level]) {
+ return level;
+ }
+ }
+ return thresholds.length;
+ }
+
+ @NonNull
+ private static int[] getRssiLevelThresholds(Context context) {
+ // getIntArray() will never return null, it will throw instead
+ return context.getResources().getIntArray(R.array.config_wifiRssiLevelThresholds);
+ }
+}
diff --git a/service/res/values/config.xml b/service/res/values/config.xml
index 6d595d8d0..ff0befd5b 100644
--- a/service/res/values/config.xml
+++ b/service/res/values/config.xml
@@ -179,4 +179,29 @@
<!-- Indicates that wifi watchdog is enabled on this device -->
<bool translatable="false" name="config_wifi_watchdog_enabled">true</bool>
+
+ <!--
+ Controls the mapping between RSSI and RSSI levels.
+
+ RSSI RSSI Level
+ (-infinity, thresholds[0]) 0
+ [threshold[0], threshold[1]) 1
+ [threshold[1], threshold[2]) 2
+ ... ...
+ [threshold[len-2], threshold[len-1]) len-1
+ [threshold[len-1], +infinity) len
+
+ where:
+ [a, b) is the range of integers `n` such that a <= n < b
+ `threshold[i]` represents the i'th element of the config_wifiRssiLevelThresholds array
+ and `len` is the length of the config_wifiRssiLevelThresholds array.
+ -->
+ <integer-array translatable="false" name="config_wifiRssiLevelThresholds">
+ <!-- RSSI RSSI Level -->
+ <item>-88</item> <!-- (-infinity, -88) 0 -->
+ <item>-77</item> <!-- [-88, -77) 1 -->
+ <item>-66</item> <!-- [-77, -66) 2 -->
+ <item>-55</item> <!-- [-66, -55) 3 -->
+ <!-- [-55, +infinity) 4 -->
+ </integer-array>
</resources>
diff --git a/service/res/values/overlayable.xml b/service/res/values/overlayable.xml
index 6003e05e7..b7bcad273 100644
--- a/service/res/values/overlayable.xml
+++ b/service/res/values/overlayable.xml
@@ -77,6 +77,7 @@
<item type="string" name="wifi_localhotspot_configure_ssid_default" />
<item type="bool" name="config_wifi_diagnostics_bugreport_enabled" />
<item type="bool" name="config_wifi_watchdog_enabled" />
+ <item type="array" name="config_wifiRssiLevelThresholds" />
<!-- Params from config.xml that can be overlayed -->
<!-- Params from strings.xml that can be overlayed -->
diff --git a/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java b/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java
index b59ee2a2a..4f4ccb6f6 100644
--- a/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java
@@ -99,6 +99,7 @@ import com.android.server.wifi.proto.nano.WifiMetricsProto;
import com.android.server.wifi.proto.nano.WifiMetricsProto.StaEvent;
import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiIsUnusableEvent;
import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiUsabilityStats;
+import com.android.server.wifi.util.RssiUtilTest;
import com.android.server.wifi.util.TelephonyUtil;
import com.android.server.wifi.util.WifiPermissionsUtil;
import com.android.server.wifi.util.WifiPermissionsWrapper;
@@ -483,6 +484,8 @@ public class ClientModeImplTest extends WifiBaseTest {
mResources = getMockResources();
mResources.setBoolean(R.bool.config_wifi_connected_mac_randomization_supported, true);
+ mResources.setIntArray(R.array.config_wifiRssiLevelThresholds,
+ RssiUtilTest.RSSI_THRESHOLDS);
when(mContext.getResources()).thenReturn(mResources);
when(mFrameworkFacade.getIntegerSetting(mContext,
diff --git a/tests/wifitests/src/com/android/server/wifi/util/RssiUtilTest.java b/tests/wifitests/src/com/android/server/wifi/util/RssiUtilTest.java
new file mode 100644
index 000000000..cebf83766
--- /dev/null
+++ b/tests/wifitests/src/com/android/server/wifi/util/RssiUtilTest.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2019 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.util;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.res.Resources;
+import android.net.wifi.IWifiManager;
+import android.net.wifi.WifiManager;
+import android.os.Build;
+import android.os.Looper;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.server.wifi.WifiBaseTest;
+import com.android.wifi.R;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+
+/** Unit tests for {@link RssiUtil}. */
+@SmallTest
+public class RssiUtilTest extends WifiBaseTest {
+
+ public static final int[] RSSI_THRESHOLDS = {-88, -77, -66, -55};
+
+ @Mock private Context mContext;
+ @Mock private Resources mResources;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ when(mContext.getResources()).thenReturn(mResources);
+ when(mResources.getIntArray(R.array.config_wifiRssiLevelThresholds))
+ .thenReturn(RSSI_THRESHOLDS);
+ }
+
+ /**
+ * Tests that our default RSSI thresholds matches what would be calculated by
+ * {@link WifiManager#calculateSignalLevel(int, int)}.
+ */
+ @Test
+ public void testCalculateSignalLevelImplementationsConsistent() {
+ for (int rssi = -100; rssi <= 0; rssi++) {
+ int expected = WifiManager.calculateSignalLevel(rssi, WifiManager.RSSI_LEVELS);
+ int actual = RssiUtil.calculateSignalLevel(mContext, rssi);
+ assertWithMessage("RSSI: %s", rssi).that(actual).isEqualTo(expected);
+ }
+ }
+
+ /** Tests the signal level at RSSIs at around the thresholds. */
+ @Test
+ public void testCalculateSignalLevel() {
+ assertThat(RssiUtil.calculateSignalLevel(mContext, -100)).isEqualTo(0);
+ assertThat(RssiUtil.calculateSignalLevel(mContext, -89)).isEqualTo(0);
+ assertThat(RssiUtil.calculateSignalLevel(mContext, -88)).isEqualTo(1);
+ assertThat(RssiUtil.calculateSignalLevel(mContext, -78)).isEqualTo(1);
+ assertThat(RssiUtil.calculateSignalLevel(mContext, -77)).isEqualTo(2);
+ assertThat(RssiUtil.calculateSignalLevel(mContext, -67)).isEqualTo(2);
+ assertThat(RssiUtil.calculateSignalLevel(mContext, -66)).isEqualTo(3);
+ assertThat(RssiUtil.calculateSignalLevel(mContext, -56)).isEqualTo(3);
+ assertThat(RssiUtil.calculateSignalLevel(mContext, -55)).isEqualTo(4);
+ assertThat(RssiUtil.calculateSignalLevel(mContext, 0)).isEqualTo(4);
+ assertThat(RssiUtil.calculateSignalLevel(mContext, Integer.MAX_VALUE)).isEqualTo(4);
+ }
+
+ /** Tests that an empty thresholds array always returns level 0. */
+ @Test
+ public void testCalculateSignalLevelEmptyThresholdsArray() {
+ when(mResources.getIntArray(R.array.config_wifiRssiLevelThresholds))
+ .thenReturn(new int[0]);
+ assertThat(RssiUtil.calculateSignalLevel(mContext, -100)).isEqualTo(0);
+ assertThat(RssiUtil.calculateSignalLevel(mContext, -50)).isEqualTo(0);
+ assertThat(RssiUtil.calculateSignalLevel(mContext, 0)).isEqualTo(0);
+
+ assertThat(RssiUtil.calculateSignalLevel(mContext, Integer.MAX_VALUE)).isEqualTo(0);
+ }
+
+ /** Tests that the expected default max signal level is returned. */
+ @Test
+ public void testGetMaxSignalLevel() throws Exception {
+ IWifiManager iWifiManager = mock(IWifiManager.class);
+
+ doAnswer(invocation -> {
+ int rssi = invocation.getArgument(0);
+ return RssiUtil.calculateSignalLevel(mContext, rssi);
+ }).when(iWifiManager).calculateSignalLevel(anyInt());
+
+ ApplicationInfo applicationInfo = mock(ApplicationInfo.class);
+ applicationInfo.targetSdkVersion = Build.VERSION_CODES.Q;
+ Context context = mock(Context.class);
+ when(context.getApplicationInfo()).thenReturn(applicationInfo);
+ when(context.getOpPackageName()).thenReturn("TestPackage");
+ WifiManager wifiManager = new WifiManager(
+ context, iWifiManager, mock(Looper.class));
+
+ int level = wifiManager.getMaxSignalLevel();
+ assertThat(level).isEqualTo(4);
+ }
+}