summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--service/java/com/android/server/wifi/SarInfo.java194
-rw-r--r--tests/wifitests/src/com/android/server/wifi/SarInfoTest.java287
2 files changed, 481 insertions, 0 deletions
diff --git a/service/java/com/android/server/wifi/SarInfo.java b/service/java/com/android/server/wifi/SarInfo.java
new file mode 100644
index 000000000..6eb777c65
--- /dev/null
+++ b/service/java/com/android/server/wifi/SarInfo.java
@@ -0,0 +1,194 @@
+/*
+ * 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 java.io.FileDescriptor;
+import java.io.PrintWriter;
+
+/**
+ * This class represents the list of SAR inputs that will be used to select the proper
+ * power profile.
+ * This includes:
+ * - SAR body sensor status
+ * - Is there an ongoing voice call
+ * - Is SoftAP active
+ * It also contains info about state of the other Wifi modes
+ * - Client mode (Sta)
+ * - ScanOnly mode
+ * It also keeps history for the reporting of SAR states/scenario to avoid unnecessary reporting
+ * - keeps track of the last reported states
+ * - keeps track of the last reported SAR scenario
+ * - keeps track of if all wifi modes were disabled (no reporting should happen then)
+ */
+public class SarInfo {
+ /**
+ * This value is used as an initial value for the last reported scenario
+ * It is intended to be different than all valid SAR scenario values (including the
+ * reset value).
+ * Using this to initialize the lastReportedScenario results in that the first scenario
+ * (including reset) would be reported.
+ */
+ public static final int INITIAL_SAR_SCENARIO = -2;
+
+ /**
+ * This value is used for the reset scenario (no TX Power backoff)
+ * Valid scenario values only include scenarios with Tx Power backoff,
+ * so we need this one to represent the "No backoff" case.
+ */
+ public static final int RESET_SAR_SCENARIO = -1;
+
+ private static final String SAR_SENSOR_FREE_SPACE_STR = "SAR_SENSOR_FREE_SPACE";
+ private static final String SAR_SENSOR_NEAR_BODY_STR = "SAR_SENSOR_NEAR_BODY";
+ private static final String SAR_SENSOR_NEAR_HAND_STR = "SAR_SENSOR_NEAR_HAND";
+ private static final String SAR_SENSOR_NEAR_HEAD_STR = "SAR_SENSOR_NEAR_HEAD";
+
+ public static final int SAR_SENSOR_FREE_SPACE = 1;
+ public static final int SAR_SENSOR_NEAR_HAND = 2;
+ public static final int SAR_SENSOR_NEAR_HEAD = 3;
+ public static final int SAR_SENSOR_NEAR_BODY = 4;
+
+ /* For Logging */
+ private static final String TAG = "WifiSarInfo";
+
+ public boolean mSarSensorEnabled;
+
+ public int mSensorState = SAR_SENSOR_FREE_SPACE;
+ public boolean mIsWifiClientEnabled = false;
+ public boolean mIsWifiSapEnabled = false;
+ public boolean mIsWifiScanOnlyEnabled = false;
+ public boolean mIsVoiceCall = false;
+ public int mAttemptedSarScenario = RESET_SAR_SCENARIO;
+
+ private boolean mAllWifiDisabled = true;
+
+ /* Variables representing the last successfully reported values to hal */
+ private int mLastReportedSensorState = SAR_SENSOR_FREE_SPACE;
+ private boolean mLastReportedIsWifiSapEnabled = false;
+ private boolean mLastReportedIsVoiceCall = false;
+ private int mLastReportedScenario = INITIAL_SAR_SCENARIO;
+
+ SarInfo(boolean sarSensorEnabled) {
+ mSarSensorEnabled = sarSensorEnabled;
+ }
+
+ /**
+ * shouldReport()
+ * This method returns false in the following cases:
+ * 1. If all Wifi modes are disabled.
+ * 2. Values contributing to the SAR scenario selection have not changed
+ * since last successful reporting.
+ *
+ * Special cases to allow for devices that require setting the SAR scenario value
+ * when the chip comes up (initial startup, or during operation)
+ * 1. This method would report true even with unchanged values from last reporting,
+ * if any wifi mode is just enabled after all wifi modes were disabled.
+ * 2. This method would report true the first time it is called with any wifi mode enabled.
+ */
+ public boolean shouldReport() {
+ /* Check if all Wifi modes are disabled */
+ if (!mIsWifiClientEnabled && !mIsWifiSapEnabled && !mIsWifiScanOnlyEnabled) {
+ mAllWifiDisabled = true;
+ return false;
+ }
+
+ /* Check if Wifi was all disabled before this call */
+ if (mAllWifiDisabled) {
+ return true;
+ }
+
+ /* Check if some change happened since last successful reporting */
+ if ((mSensorState != mLastReportedSensorState)
+ || (mIsWifiSapEnabled != mLastReportedIsWifiSapEnabled)
+ || (mIsVoiceCall != mLastReportedIsVoiceCall)) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * reportingSuccessful()
+ * This method is called when reporting SAR scenario is fully successful
+ * This results in caching the last reported inputs for future comparison.
+ */
+ public void reportingSuccessful() {
+ mLastReportedSensorState = mSensorState;
+ mLastReportedIsWifiSapEnabled = mIsWifiSapEnabled;
+ mLastReportedIsVoiceCall = mIsVoiceCall;
+ mLastReportedScenario = mAttemptedSarScenario;
+
+ mAllWifiDisabled = false;
+ }
+
+ /**
+ * resetSarScenarioNeeded()
+ * Returns true if a call towards HAL to reset SAR scenario would be necessary.
+ * Returns false if the last call to HAL was already a reset, and hence
+ * another call to reset the SAR scenario would be redundant.
+ */
+ public boolean resetSarScenarioNeeded() {
+ return setSarScenarioNeeded(RESET_SAR_SCENARIO);
+ }
+
+ /**
+ * setSarScenarioNeeded()
+ * Returns true if a call towards HAL to set SAR scenario to that value would be
+ * necessary.
+ * Returns false if the last call to HAL was to set the scenario to that value, hence,
+ * another call to set the SAR scenario to the same value would be redundant.
+ */
+ public boolean setSarScenarioNeeded(int scenario) {
+ mAttemptedSarScenario = scenario;
+ return (mLastReportedScenario != scenario);
+ }
+
+ /**
+ * dump()
+ * Dumps the state of SarInfo
+ */
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ pw.println("*** WiFi SAR Info Dump ***");
+ pw.println("Current values:");
+ pw.println(" Sensor state is: " + sensorStateToString(mSensorState));
+ pw.println(" Voice Call state is: " + mIsVoiceCall);
+ pw.println(" Wifi Client state is: " + mIsWifiClientEnabled);
+ pw.println(" Wifi Soft AP state is: " + mIsWifiSapEnabled);
+ pw.println(" Wifi ScanOnly state is: " + mIsWifiScanOnlyEnabled);
+ pw.println("Last reported values:");
+ pw.println(" Sensor state is: " + sensorStateToString(mLastReportedSensorState));
+ pw.println(" Soft AP state is: " + mLastReportedIsWifiSapEnabled);
+ pw.println(" Voice Call state is: " + mLastReportedIsVoiceCall);
+ }
+
+ /**
+ * Convert SAR sensor state to string
+ */
+ public static String sensorStateToString(int sensorState) {
+ switch(sensorState) {
+ case SAR_SENSOR_FREE_SPACE:
+ return SAR_SENSOR_FREE_SPACE_STR;
+ case SAR_SENSOR_NEAR_BODY:
+ return SAR_SENSOR_NEAR_BODY_STR;
+ case SAR_SENSOR_NEAR_HAND:
+ return SAR_SENSOR_NEAR_HAND_STR;
+ case SAR_SENSOR_NEAR_HEAD:
+ return SAR_SENSOR_NEAR_HEAD_STR;
+ default:
+ return "Invalid SAR sensor state";
+ }
+ }
+}
diff --git a/tests/wifitests/src/com/android/server/wifi/SarInfoTest.java b/tests/wifitests/src/com/android/server/wifi/SarInfoTest.java
new file mode 100644
index 000000000..1f0e44c8a
--- /dev/null
+++ b/tests/wifitests/src/com/android/server/wifi/SarInfoTest.java
@@ -0,0 +1,287 @@
+/*
+ * 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.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.support.test.filters.SmallTest;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * unit tests for {@link com.android.server.wifi.SarInfo}.
+ */
+@SmallTest
+public class SarInfoTest {
+ private static final String TAG = "WifiSarInfoTest";
+
+ private SarInfo mSarInfo;
+
+ private static final int SAR_SCENARIO_1 = 1;
+ private static final int SAR_SCENARIO_2 = 2;
+
+ @Before
+ public void setUp() throws Exception {
+ mSarInfo = new SarInfo(true);
+ }
+
+ @After
+ public void cleanUp() throws Exception {
+ }
+
+ /**
+ * Test that at start, resetSarScenarioNeeded returns true,
+ * to allow for initial setting of normal scenario.
+ */
+ @Test
+ public void testSarInfo_resetSarScenarioNeed_atStart() throws Exception {
+ assertTrue(mSarInfo.resetSarScenarioNeeded());
+ }
+
+ /**
+ * Test that at start, setSarScenarioNeeded returns true.
+ */
+ @Test
+ public void testSarInfo_setSarScenarioNeeded_atStart() throws Exception {
+ assertTrue(mSarInfo.setSarScenarioNeeded(SAR_SCENARIO_1));
+ }
+
+ /**
+ * Test performing two successive reset of SAR scenario.
+ * The first should succeed, while the second should fail, since it is redundant.
+ */
+ @Test
+ public void testSarInfo_repeat_reset_scenario() throws Exception {
+ /* Initial reset is allowed */
+ assertTrue(mSarInfo.resetSarScenarioNeeded());
+ mSarInfo.reportingSuccessful();
+
+ /* Now resetting again should not be allowed */
+ assertFalse(mSarInfo.resetSarScenarioNeeded());
+ }
+
+ /**
+ * Test performing set SAR scenario after reset.
+ * The two attempts should succeed.
+ */
+ @Test
+ public void testSarInfo_set_after_reset_scenario() throws Exception {
+ assertTrue(mSarInfo.resetSarScenarioNeeded());
+ mSarInfo.reportingSuccessful();
+
+ /* Setting scenario should be allowed, since last call was for a reset */
+ assertTrue(mSarInfo.setSarScenarioNeeded(SAR_SCENARIO_1));
+ }
+
+ /**
+ * Test performing setting SAR scenario twice with same value.
+ * The second attempt should fail.
+ */
+ @Test
+ public void testSarInfo_set_twice_same_value_scenario() throws Exception {
+ assertTrue(mSarInfo.setSarScenarioNeeded(SAR_SCENARIO_1));
+ mSarInfo.reportingSuccessful();
+
+ /* Second attempt should fail */
+ assertFalse(mSarInfo.setSarScenarioNeeded(SAR_SCENARIO_1));
+ }
+
+ /**
+ * Test performing setting SAR scenario twice with different values.
+ * Both attempts should succeed.
+ */
+ @Test
+ public void testSarInfo_set_twice_different_values_scenario() throws Exception {
+ assertTrue(mSarInfo.setSarScenarioNeeded(SAR_SCENARIO_1));
+ mSarInfo.reportingSuccessful();
+
+ /* Setting scenario should be allowed */
+ assertTrue(mSarInfo.setSarScenarioNeeded(SAR_SCENARIO_2));
+ }
+
+ /**
+ * Test performing reset of SAR scenario after setting it.
+ * Both attempts should succeed.
+ */
+ @Test
+ public void testSarInfo_reset_after_set_scenario() throws Exception {
+ assertTrue(mSarInfo.setSarScenarioNeeded(SAR_SCENARIO_1));
+ mSarInfo.reportingSuccessful();
+
+ /* Resetting scenario should be allowed */
+ assertTrue(mSarInfo.resetSarScenarioNeeded());
+ }
+
+ /**
+ * Test that at start, shouldReport returns false (wifi modes still disabled).
+ */
+ @Test
+ public void testSarInfo_shouldReport_all_wifi_disabled() throws Exception {
+ assertFalse(mSarInfo.shouldReport());
+ }
+
+ /**
+ * Test that once Wifi (any mode) is enabled, shouldReport returns true.
+ */
+ @Test
+ public void testSarInfo_shouldReport_wifi_enabled() throws Exception {
+ mSarInfo.mIsWifiClientEnabled = true;
+ assertTrue(mSarInfo.shouldReport());
+ }
+
+ /**
+ * Test that setting sensor (with wifi disabled), shouldReport returns false.
+ */
+ @Test
+ public void testSarInfo_check_sensor_wifi_disabled() throws Exception {
+ mSarInfo.mSensorState = SarInfo.SAR_SENSOR_NEAR_HEAD;
+ assertFalse(mSarInfo.shouldReport());
+ }
+
+ /**
+ * Test that setting sensor (with some wifi mode enabled), shouldReport returns true.
+ */
+ @Test
+ public void testSarInfo_check_sensor_wifi_enabled() throws Exception {
+ mSarInfo.mIsWifiSapEnabled = true;
+ assertTrue(mSarInfo.shouldReport());
+ mSarInfo.reportingSuccessful();
+
+ mSarInfo.mSensorState = SarInfo.SAR_SENSOR_NEAR_HEAD;
+ assertTrue(mSarInfo.shouldReport());
+ }
+
+ /**
+ * Test that setting sensor (with some wifi mode enabled), shouldReport returns true
+ * only the first time, following attempts should return false (since sensor state
+ * did not change)
+ */
+ @Test
+ public void testSarInfo_check_sensor_multiple_wifi_enabled() throws Exception {
+ mSarInfo.mIsWifiScanOnlyEnabled = true;
+ mSarInfo.mSensorState = SarInfo.SAR_SENSOR_NEAR_HEAD;
+ assertTrue(mSarInfo.shouldReport());
+ mSarInfo.reportingSuccessful();
+
+ assertFalse(mSarInfo.shouldReport());
+ }
+
+ /**
+ * Test that setting sensor with different values (with wifi enabled),
+ * shouldReport returns true every time.
+ */
+ @Test
+ public void testSarInfo_check_sensor_multiple_values_wifi_enabled() throws Exception {
+ mSarInfo.mIsWifiClientEnabled = true;
+ mSarInfo.mSensorState = SarInfo.SAR_SENSOR_NEAR_HEAD;
+ assertTrue(mSarInfo.shouldReport());
+ mSarInfo.reportingSuccessful();
+
+ mSarInfo.mSensorState = SarInfo.SAR_SENSOR_NEAR_BODY;
+ assertTrue(mSarInfo.shouldReport());
+ mSarInfo.reportingSuccessful();
+
+ mSarInfo.mSensorState = SarInfo.SAR_SENSOR_NEAR_HEAD;
+ assertTrue(mSarInfo.shouldReport());
+ }
+
+ /**
+ * Test setting sensor while wifi is disabled, then enable wifi.
+ */
+ @Test
+ public void testSarInfo_change_sensors_while_wifi_disabled() throws Exception {
+ mSarInfo.mSensorState = SarInfo.SAR_SENSOR_NEAR_HEAD;
+ assertFalse(mSarInfo.shouldReport());
+
+ mSarInfo.mIsWifiClientEnabled = true;
+ assertTrue(mSarInfo.shouldReport());
+ mSarInfo.reportingSuccessful();
+ }
+
+ /**
+ * Test having a voice call, shouldReport should return true
+ * Note: will need to report once before starting the call to remove
+ * the effect of sensor state change.
+ */
+ @Test
+ public void testSarInfo_voice_call_wifi_enabled() throws Exception {
+ mSarInfo.mIsWifiClientEnabled = true;
+ assertTrue(mSarInfo.shouldReport());
+ mSarInfo.reportingSuccessful();
+
+ mSarInfo.mIsVoiceCall = true;
+ assertTrue(mSarInfo.shouldReport());
+ }
+
+ /**
+ * Test starting SAP, shouldReport should return true
+ * Note: will need to report once before starting SAP to remove
+ * the effect of sensor state change.
+ */
+ @Test
+ public void testSarInfo_sap_wifi_enabled() throws Exception {
+ mSarInfo.mIsWifiClientEnabled = true;
+ assertTrue(mSarInfo.shouldReport());
+ mSarInfo.reportingSuccessful();
+
+ mSarInfo.mIsWifiSapEnabled = true;
+ assertTrue(mSarInfo.shouldReport());
+ }
+
+ /**
+ * Test that setting sensor (with wifi enabled), reporting not successful
+ * Then, we should expect that shouldReport returns true evne if we have
+ * no further changes until reporting is successful.
+ */
+ @Test
+ public void testSarInfo_check_sensor_reporting_no_success_reporting() throws Exception {
+ mSarInfo.mIsWifiClientEnabled = true;
+ mSarInfo.mSensorState = SarInfo.SAR_SENSOR_NEAR_HEAD;
+ assertTrue(mSarInfo.shouldReport());
+
+ /* No call to reportingSuccessful() will be done */
+ assertTrue(mSarInfo.shouldReport());
+
+ /* Now call reportingSuccessful() */
+ mSarInfo.reportingSuccessful();
+ assertFalse(mSarInfo.shouldReport());
+ }
+
+ /**
+ * Test that setting sensor (with wifi enabled), reporting successful
+ * Then, changing the sensor state with no successful reporting.
+ * Followed by reverting to the previous state.
+ */
+ @Test
+ public void testSarInfo_check_sensor_reporting_no_success_reporting_revert() throws Exception {
+ mSarInfo.mIsWifiClientEnabled = true;
+ mSarInfo.mSensorState = SarInfo.SAR_SENSOR_NEAR_HEAD;
+ assertTrue(mSarInfo.shouldReport());
+ mSarInfo.reportingSuccessful();
+
+ /* Changing the sensor state and fail to report */
+ mSarInfo.mSensorState = SarInfo.SAR_SENSOR_NEAR_BODY;
+ assertTrue(mSarInfo.shouldReport());
+
+ /* Changing the sensor back to the same value as last reported */
+ mSarInfo.mSensorState = SarInfo.SAR_SENSOR_NEAR_HEAD;
+ assertFalse(mSarInfo.shouldReport());
+ }
+}