summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--service/java/com/android/server/wifi/WifiNative.java17
-rw-r--r--service/java/com/android/server/wifi/WifiVendorHal.java229
-rw-r--r--tests/wifitests/src/com/android/server/wifi/WifiNativeTest.java22
-rw-r--r--tests/wifitests/src/com/android/server/wifi/WifiVendorHalTest.java449
4 files changed, 713 insertions, 4 deletions
diff --git a/service/java/com/android/server/wifi/WifiNative.java b/service/java/com/android/server/wifi/WifiNative.java
index 0f785873b..5369b0e1e 100644
--- a/service/java/com/android/server/wifi/WifiNative.java
+++ b/service/java/com/android/server/wifi/WifiNative.java
@@ -2820,12 +2820,18 @@ public class WifiNative {
}
/**
+ * TODO: These constants will be removed in a future change
+ * They are left for the interim use
+ *
* Tx power level scenarios that can be selected.
*/
public static final int TX_POWER_SCENARIO_NORMAL = 0;
public static final int TX_POWER_SCENARIO_VOICE_CALL = 1;
/**
+ * TODO: This method is deprecated and will be removed in a future change to use
+ * the interface with sarInfo as an input instead.
+ *
* Select one of the pre-configured TX power level scenarios or reset it back to normal.
* Primarily used for meeting SAR requirements during voice calls.
*
@@ -2837,6 +2843,17 @@ public class WifiNative {
return mWifiVendorHal.selectTxPowerScenario(scenario);
}
+ /**
+ * Select one of the pre-configured transmit power level scenarios or reset it back to normal.
+ * Primarily used for meeting SAR requirements.
+ *
+ * @param sarInfo The collection of inputs used to select the SAR scenario.
+ * @return true for success; false for failure or if the HAL version does not support this API.
+ */
+ public boolean selectTxPowerScenario(SarInfo sarInfo) {
+ return mWifiVendorHal.selectTxPowerScenario(sarInfo);
+ }
+
/********************************************************
* JNI operations
********************************************************/
diff --git a/service/java/com/android/server/wifi/WifiVendorHal.java b/service/java/com/android/server/wifi/WifiVendorHal.java
index 0d73459b5..fdbd97fb0 100644
--- a/service/java/com/android/server/wifi/WifiVendorHal.java
+++ b/service/java/com/android/server/wifi/WifiVendorHal.java
@@ -2653,7 +2653,7 @@ public class WifiVendorHal {
return android.hardware.wifi.V1_2.IWifiStaIface.castFrom(iface);
}
-
+ /* TODO: This method is to be removed in a future change */
private int frameworkToHalTxPowerScenario(int scenario) {
switch (scenario) {
case WifiNative.TX_POWER_SCENARIO_VOICE_CALL:
@@ -2664,6 +2664,10 @@ public class WifiVendorHal {
}
/**
+ * TODO: This method will be removed in a future change
+ * It will be replaced with another method receiving SarInfo
+ * instance instead of the int for scenario
+ *
* Select one of the pre-configured TX power level scenarios or reset it back to normal.
* Primarily used for meeting SAR requirements during voice calls.
*
@@ -2699,6 +2703,229 @@ public class WifiVendorHal {
}
}
+ /**
+ * sarPowerBackoffRequired_1_1()
+ * This method checks if we need to backoff wifi Tx power due to SAR requirements.
+ * It handles the case when the device is running the V1_1 version of WifiChip HAL
+ * In that HAL version, it is required to perform wifi Tx power backoff only if
+ * a voice call is ongoing.
+ */
+ private boolean sarPowerBackoffRequired_1_1(SarInfo sarInfo) {
+ /* As long as no voice call is active, no backoff is needed */
+ return sarInfo.mIsVoiceCall;
+ }
+
+ /**
+ * frameworkToHalTxPowerScenario_1_1()
+ * This method maps the information inside the SarInfo instance into a SAR scenario
+ * when device is running the V1_1 version of WifiChip HAL.
+ * In this HAL version, only one scenario is defined which is for VOICE_CALL
+ * otherwise, an exception is thrown.
+ */
+ private int frameworkToHalTxPowerScenario_1_1(SarInfo sarInfo) {
+ if (sarInfo.mIsVoiceCall) {
+ return android.hardware.wifi.V1_1.IWifiChip.TxPowerScenario.VOICE_CALL;
+ } else {
+ throw new IllegalArgumentException("bad scenario: voice call not active");
+ }
+ }
+
+ /**
+ * sarPowerBackoffRequired_1_2()
+ * This method checks if we need to backoff wifi Tx power due to SAR requirements.
+ * It handles the case when the device is running the V1_2 version of WifiChip HAL
+ * In that HAL version, behavior depends on if SAR sensor input is considered in this device.
+ * If it is, then whenever the device is near the user body/hand/head, back-off is required.
+ * Otherwise, we should revert to the V1_1 HAL behavior which is only to perform backoff when
+ * a voice call is ongoing.
+ */
+ private boolean sarPowerBackoffRequired_1_2(SarInfo sarInfo) {
+ if (sarInfo.mSarSensorEnabled) {
+ return (sarInfo.mSensorState != SarInfo.SAR_SENSOR_FREE_SPACE);
+ } else {
+ return sarInfo.mIsVoiceCall;
+ }
+ }
+
+ /**
+ * frameworkToHalTxPowerScenario_1_2()
+ * This method maps the information inside the SarInfo instance into a SAR scenario
+ * when device is running the V1_2 version of WifiChip HAL.
+ * In this HAL version, behavior depends on if SAR sensor input is considered in this device.
+ * If it is, then based on regulatory compliance requirements,
+ * - There is no need to treat NEAR_HAND different from NEAR_BODY, both can be considered
+ * near the user body.
+ * - Running in softAP mode can be treated the same way as running a voice call from tx power
+ * backoff perspective.
+ * If SAR sensor input is not considered in this device, then we should revert to the V1_1 HAL
+ * behavior, and the only valid scenario would be when a voice call is ongoing.
+ */
+ private int frameworkToHalTxPowerScenario_1_2(SarInfo sarInfo) {
+ if (sarInfo.mSarSensorEnabled) {
+ switch(sarInfo.mSensorState) {
+ case SarInfo.SAR_SENSOR_NEAR_BODY:
+ case SarInfo.SAR_SENSOR_NEAR_HAND:
+ if (sarInfo.mIsVoiceCall || sarInfo.mIsWifiSapEnabled) {
+ return android.hardware.wifi.V1_2.IWifiChip
+ .TxPowerScenario.ON_BODY_CELL_ON;
+ } else {
+ return android.hardware.wifi.V1_2.IWifiChip
+ .TxPowerScenario.ON_BODY_CELL_OFF;
+ }
+
+ case SarInfo.SAR_SENSOR_NEAR_HEAD:
+ if (sarInfo.mIsVoiceCall || sarInfo.mIsWifiSapEnabled) {
+ return android.hardware.wifi.V1_2.IWifiChip
+ .TxPowerScenario.ON_HEAD_CELL_ON;
+ } else {
+ return android.hardware.wifi.V1_2.IWifiChip
+ .TxPowerScenario.ON_HEAD_CELL_OFF;
+ }
+
+ default:
+ throw new IllegalArgumentException("bad scenario: Invalid sensor state");
+ }
+ } else {
+ /* SAR Sensors not enabled, act like V1_1 */
+ if (sarInfo.mIsVoiceCall) {
+ return android.hardware.wifi.V1_1.IWifiChip.TxPowerScenario.VOICE_CALL;
+ } else {
+ throw new IllegalArgumentException("bad scenario: voice call not active");
+ }
+ }
+ }
+
+ /**
+ * Select one of the pre-configured TX power level scenarios or reset it back to normal.
+ * Primarily used for meeting SAR requirements during voice calls.
+ *
+ * Note: If it was found out that the scenario to be reported is the same as last reported one,
+ * then exit with success.
+ * This is to handle the case when some HAL versions deal with different inputs equally,
+ * in that case, we should not call the hal unless there is a change in scenario.
+ * Note: It is assumed that this method is only called if SAR is enabled. The logic of whether
+ * to call it or not resides in SarManager class.
+ * Note: This method is called whether SAR sensor is supported or not. The passed SarInfo object
+ * contains a flag to indicate the SAR sensor support.
+ *
+ * @param sarInfo The collection of inputs to select the SAR scenario.
+ * @return true for success; false for failure or if the HAL version does not support this API.
+ */
+ public boolean selectTxPowerScenario(SarInfo sarInfo) {
+ synchronized (sLock) {
+ // First attempt to get a V_1_2 instance of the Wifi HAL.
+ android.hardware.wifi.V1_2.IWifiChip iWifiChipV12 = getWifiChipForV1_2Mockable();
+ if (iWifiChipV12 != null) {
+ return selectTxPowerScenario_1_2(iWifiChipV12, sarInfo);
+ }
+
+ // Now attempt to get a V_1_1 instance of the Wifi HAL.
+ android.hardware.wifi.V1_1.IWifiChip iWifiChipV11 = getWifiChipForV1_1Mockable();
+ if (iWifiChipV11 != null) {
+ return selectTxPowerScenario_1_1(iWifiChipV11, sarInfo);
+ }
+
+ // HAL version does not support SAR
+ return false;
+ }
+ }
+
+ private boolean selectTxPowerScenario_1_1(
+ android.hardware.wifi.V1_1.IWifiChip iWifiChip, SarInfo sarInfo) {
+ WifiStatus status;
+ try {
+ if (sarPowerBackoffRequired_1_1(sarInfo)) {
+ // Power backoff is needed, so calculate the required scenario,
+ // and attempt to set it.
+ int halScenario = frameworkToHalTxPowerScenario_1_1(sarInfo);
+ if (sarInfo.setSarScenarioNeeded(halScenario)) {
+ status = iWifiChip.selectTxPowerScenario(halScenario);
+ if (ok(status)) {
+ mLog.e("Setting SAR scenario to " + halScenario);
+ return true;
+ } else {
+ mLog.e("Failed to set SAR scenario to " + halScenario);
+ return false;
+ }
+ }
+
+ // Reaching here means setting SAR scenario would be redundant,
+ // do nothing and return with success.
+ return true;
+ }
+
+ // We don't need to perform power backoff, so attempt to reset SAR scenario.
+ if (sarInfo.resetSarScenarioNeeded()) {
+ status = iWifiChip.resetTxPowerScenario();
+ if (ok(status)) {
+ mLog.d("Resetting SAR scenario");
+ return true;
+ } else {
+ mLog.e("Failed to reset SAR scenario");
+ return false;
+ }
+ }
+
+ // Resetting SAR scenario would be redundant,
+ // do nothing and return with success.
+ return true;
+ } catch (RemoteException e) {
+ handleRemoteException(e);
+ return false;
+ } catch (IllegalArgumentException e) {
+ mLog.err("Illegal argument for selectTxPowerScenario_1_1()").c(e.toString()).flush();
+ return false;
+ }
+ }
+
+ private boolean selectTxPowerScenario_1_2(
+ android.hardware.wifi.V1_2.IWifiChip iWifiChip, SarInfo sarInfo) {
+ WifiStatus status;
+ try {
+ if (sarPowerBackoffRequired_1_2(sarInfo)) {
+ // Power backoff is needed, so calculate the required scenario,
+ // and attempt to set it.
+ int halScenario = frameworkToHalTxPowerScenario_1_2(sarInfo);
+ if (sarInfo.setSarScenarioNeeded(halScenario)) {
+ status = iWifiChip.selectTxPowerScenario_1_2(halScenario);
+ if (ok(status)) {
+ mLog.e("Setting SAR scenario to " + halScenario);
+ return true;
+ } else {
+ mLog.e("Failed to set SAR scenario to " + halScenario);
+ return false;
+ }
+ }
+
+ // Reaching here means setting SAR scenario would be redundant,
+ // do nothing and return with success.
+ return true;
+ }
+
+ // We don't need to perform power backoff, so attempt to reset SAR scenario.
+ if (sarInfo.resetSarScenarioNeeded()) {
+ status = iWifiChip.resetTxPowerScenario();
+ if (ok(status)) {
+ mLog.d("Resetting SAR scenario");
+ return true;
+ } else {
+ mLog.e("Failed to reset SAR scenario");
+ return false;
+ }
+ }
+
+ // Resetting SAR scenario would be redundant,
+ // do nothing and return with success.
+ return true;
+ } catch (RemoteException e) {
+ handleRemoteException(e);
+ return false;
+ } catch (IllegalArgumentException e) {
+ mLog.err("Illegal argument for selectTxPowerScenario_1_2()").c(e.toString()).flush();
+ return false;
+ }
+ }
+
// This creates a blob of IE elements from the array received.
// TODO: This ugly conversion can be removed if we put IE elements in ScanResult.
private static byte[] hidlIeArrayToFrameworkIeBlob(ArrayList<WifiInformationElement> ies) {
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiNativeTest.java b/tests/wifitests/src/com/android/server/wifi/WifiNativeTest.java
index 31e7e553c..fbdc8f507 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiNativeTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiNativeTest.java
@@ -586,4 +586,26 @@ public class WifiNativeTest {
verify(mWificondControl).startHostapd(WIFI_IFACE_NAME, mockListener);
verify(mWifiMetrics).incrementNumSetupSoftApInterfaceFailureDueToHostapd();
}
+
+ /**
+ * Test that selectTxPowerScenario() calls into WifiVendorHal (success case)
+ */
+ @Test
+ public void testSelectTxPowerScenario_success() throws Exception {
+ when(mWifiVendorHal.selectTxPowerScenario(any(SarInfo.class))).thenReturn(true);
+ SarInfo sarInfo = new SarInfo(true);
+ assertTrue(mWifiNative.selectTxPowerScenario(sarInfo));
+ verify(mWifiVendorHal).selectTxPowerScenario(sarInfo);
+ }
+
+ /**
+ * Test that selectTxPowerScenario() calls into WifiVendorHal (failure case)
+ */
+ @Test
+ public void testSelectTxPowerScenario_failure() throws Exception {
+ when(mWifiVendorHal.selectTxPowerScenario(any(SarInfo.class))).thenReturn(false);
+ SarInfo sarInfo = new SarInfo(true);
+ assertFalse(mWifiNative.selectTxPowerScenario(sarInfo));
+ verify(mWifiVendorHal).selectTxPowerScenario(sarInfo);
+ }
}
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiVendorHalTest.java b/tests/wifitests/src/com/android/server/wifi/WifiVendorHalTest.java
index 0f8f56f66..60b5f81ad 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiVendorHalTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiVendorHalTest.java
@@ -32,6 +32,7 @@ import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
@@ -99,6 +100,7 @@ import com.android.server.wifi.util.NativeUtil;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
+import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.stubbing.Answer;
@@ -119,6 +121,7 @@ public class WifiVendorHalTest {
private static final String TEST_IFACE_NAME = "wlan0";
private static final String TEST_IFACE_NAME_1 = "wlan1";
private static final MacAddress TEST_MAC_ADDRESS = MacAddress.fromString("ee:33:a2:94:10:92");
+ private static final int SAR_SENSOR_INVALID_STATE = -6;
WifiVendorHal mWifiVendorHal;
private WifiStatus mWifiStatusSuccess;
@@ -1997,11 +2000,14 @@ public class WifiVendorHalTest {
}
/**
+ * TODO: This test will be removed in a following change
+ * It is going to be replaced by another test using the new structure
+ *
* Test the new selectTxPowerScenario HIDL method invocation. This should return failure if the
* HAL service is exposing the 1.0 interface.
*/
@Test
- public void testSelectTxPowerScenario() throws RemoteException {
+ public void testSelectTxPowerScenario_old() throws RemoteException {
assertTrue(mWifiVendorHal.startVendorHalSta());
// Should fail because we exposed the 1.0 IWifiChip.
assertFalse(
@@ -2023,11 +2029,14 @@ public class WifiVendorHalTest {
}
/**
+ * TODO: This test will be removed in a following change
+ * It is going to be replaced by another test using the new structure
+ *
* Test the new resetTxPowerScenario HIDL method invocation. This should return failure if the
* HAL service is exposing the 1.0 interface.
*/
@Test
- public void testResetTxPowerScenario() throws RemoteException {
+ public void testResetTxPowerScenario_old() throws RemoteException {
assertTrue(mWifiVendorHal.startVendorHalSta());
// Should fail because we exposed the 1.0 IWifiChip.
assertFalse(mWifiVendorHal.selectTxPowerScenario(WifiNative.TX_POWER_SCENARIO_NORMAL));
@@ -2046,10 +2055,13 @@ public class WifiVendorHalTest {
}
/**
+ * TODO: This test will be removed in a following change
+ * It is going to be replaced by another test using the new structure
+ *
* Test the new selectTxPowerScenario HIDL method invocation with a bad scenario index.
*/
@Test
- public void testInvalidSelectTxPowerScenario() throws RemoteException {
+ public void testInvalidSelectTxPowerScenario_old() throws RemoteException {
// Expose the 1.1 IWifiChip.
mWifiVendorHal = new WifiVendorHalSpyV1_1(mHalDeviceManager, mLooper.getLooper());
when(mIWifiChipV11.selectTxPowerScenario(anyInt())).thenReturn(mWifiStatusSuccess);
@@ -2062,6 +2074,437 @@ public class WifiVendorHalTest {
}
/**
+ * Test the selectTxPowerScenario HIDL method invocation for 1.0 interface.
+ * This should return failure since SAR is not supported for this interface version.
+ */
+ @Test
+ public void testSelectTxPowerScenario_1_0() throws RemoteException {
+ // Create a SAR info record (no sensor support)
+ SarInfo sarInfo = new SarInfo(false);
+ sarInfo.mIsVoiceCall = true;
+
+ assertTrue(mWifiVendorHal.startVendorHalSta());
+ // Should fail because we exposed the 1.0 IWifiChip.
+ assertFalse(mWifiVendorHal.selectTxPowerScenario(sarInfo));
+ verify(mIWifiChipV11, never()).selectTxPowerScenario(anyInt());
+ mWifiVendorHal.stopVendorHal();
+ }
+
+ /**
+ * Test the selectTxPowerScenario HIDL method invocation for 1.1 interface.
+ * This should return success.
+ */
+ @Test
+ public void testSelectTxPowerScenario_1_1() throws RemoteException {
+ // Create a SAR info record (no sensor support)
+ SarInfo sarInfo = new SarInfo(false);
+ sarInfo.mIsVoiceCall = true;
+
+ // Now expose the 1.1 IWifiChip.
+ mWifiVendorHal = new WifiVendorHalSpyV1_1(mHalDeviceManager, mLooper.getLooper());
+ when(mIWifiChipV11.selectTxPowerScenario(anyInt())).thenReturn(mWifiStatusSuccess);
+
+ assertTrue(mWifiVendorHal.startVendorHalSta());
+ assertTrue(mWifiVendorHal.selectTxPowerScenario(sarInfo));
+ verify(mIWifiChipV11).selectTxPowerScenario(
+ eq(android.hardware.wifi.V1_1.IWifiChip.TxPowerScenario.VOICE_CALL));
+ verify(mIWifiChipV11, never()).resetTxPowerScenario();
+ mWifiVendorHal.stopVendorHal();
+ }
+
+ /**
+ * Test the selectTxPowerScenario HIDL method invocation for 1.2 interface.
+ * This should return success.
+ */
+ @Test
+ public void testSelectTxPowerScenario_1_2() throws RemoteException {
+ // Create a SAR info record (no sensor support)
+ SarInfo sarInfo = new SarInfo(false);
+ sarInfo.mIsVoiceCall = true;
+
+ // Now expose the 1.2 IWifiChip
+ mWifiVendorHal = new WifiVendorHalSpyV1_2(mHalDeviceManager, mLooper.getLooper());
+ when(mIWifiChipV12.selectTxPowerScenario_1_2(anyInt())).thenReturn(mWifiStatusSuccess);
+
+ assertTrue(mWifiVendorHal.startVendorHalSta());
+ assertTrue(mWifiVendorHal.selectTxPowerScenario(sarInfo));
+ verify(mIWifiChipV12).selectTxPowerScenario_1_2(
+ eq(android.hardware.wifi.V1_2.IWifiChip.TxPowerScenario.VOICE_CALL));
+ verify(mIWifiChipV12, never()).resetTxPowerScenario();
+ mWifiVendorHal.stopVendorHal();
+ }
+
+ /**
+ * Test the resetTxPowerScenario HIDL method invocation for 1.0 interface.
+ * This should return failure since it does not supprt SAR.
+ */
+ @Test
+ public void testResetTxPowerScenario_1_0() throws RemoteException {
+ // Create a SAR info record (no sensor support)
+ SarInfo sarInfo = new SarInfo(false);
+
+ assertTrue(mWifiVendorHal.startVendorHalSta());
+ // Should fail because we exposed the 1.0 IWifiChip.
+ assertFalse(mWifiVendorHal.selectTxPowerScenario(sarInfo));
+ verify(mIWifiChipV11, never()).resetTxPowerScenario();
+ mWifiVendorHal.stopVendorHal();
+ }
+
+ /**
+ * Test the resetTxPowerScenario HIDL method invocation for 1.1 interface.
+ * This should return success.
+ */
+ @Test
+ public void testResetTxPowerScenario_1_1() throws RemoteException {
+ // Create a SAR info record (no sensor support)
+ SarInfo sarInfo = new SarInfo(false);
+
+ // Now expose the 1.1 IWifiChip.
+ mWifiVendorHal = new WifiVendorHalSpyV1_1(mHalDeviceManager, mLooper.getLooper());
+ when(mIWifiChipV11.resetTxPowerScenario()).thenReturn(mWifiStatusSuccess);
+
+ assertTrue(mWifiVendorHal.startVendorHalSta());
+ assertTrue(mWifiVendorHal.selectTxPowerScenario(sarInfo));
+ verify(mIWifiChipV11).resetTxPowerScenario();
+ verify(mIWifiChipV11, never()).selectTxPowerScenario(anyInt());
+ mWifiVendorHal.stopVendorHal();
+ }
+
+ /**
+ * Test resetting SAR scenario when not needed, should return true without invoking
+ * the HAL method.
+ * This is using HAL 1.1 interface.
+ */
+ @Test
+ public void testResetTxPowerScenario_not_needed_1_1() throws RemoteException {
+ InOrder inOrder = inOrder(mIWifiChipV11);
+
+ // Create a SAR info record (no sensor support)
+ SarInfo sarInfo = new SarInfo(false);
+
+ // Now expose the 1.1 IWifiChip.
+ mWifiVendorHal = new WifiVendorHalSpyV1_1(mHalDeviceManager, mLooper.getLooper());
+ when(mIWifiChipV11.resetTxPowerScenario()).thenReturn(mWifiStatusSuccess);
+
+ assertTrue(mWifiVendorHal.startVendorHalSta());
+
+ /* Calling reset once */
+ assertTrue(mWifiVendorHal.selectTxPowerScenario(sarInfo));
+ inOrder.verify(mIWifiChipV11).resetTxPowerScenario();
+ inOrder.verify(mIWifiChipV11, never()).selectTxPowerScenario(anyInt());
+ sarInfo.reportingSuccessful();
+
+ /* Calling reset second time */
+ assertTrue(mWifiVendorHal.selectTxPowerScenario(sarInfo));
+ inOrder.verify(mIWifiChipV11, never()).resetTxPowerScenario();
+ inOrder.verify(mIWifiChipV11, never()).selectTxPowerScenario(anyInt());
+
+ mWifiVendorHal.stopVendorHal();
+ }
+
+ /**
+ * Test the new resetTxPowerScenario HIDL method invocation for 1.2 interface.
+ * This should return success.
+ */
+ @Test
+ public void testResetTxPowerScenario_1_2() throws RemoteException {
+ // Create a SAR info record (no sensor support)
+ SarInfo sarInfo = new SarInfo(false);
+
+ // Now expose the 1.2 IWifiChip.
+ mWifiVendorHal = new WifiVendorHalSpyV1_2(mHalDeviceManager, mLooper.getLooper());
+ when(mIWifiChipV12.resetTxPowerScenario()).thenReturn(mWifiStatusSuccess);
+
+ assertTrue(mWifiVendorHal.startVendorHalSta());
+ assertTrue(mWifiVendorHal.selectTxPowerScenario(sarInfo));
+ verify(mIWifiChipV12).resetTxPowerScenario();
+ verify(mIWifiChipV12, never()).selectTxPowerScenario_1_2(anyInt());
+ mWifiVendorHal.stopVendorHal();
+ }
+
+ /**
+ * Test resetting SAR scenario when not needed, should return true without invoking
+ * the HAL method.
+ * This is using HAL 1.2 interface.
+ */
+ @Test
+ public void testResetTxPowerScenario_not_needed_1_2() throws RemoteException {
+ InOrder inOrder = inOrder(mIWifiChipV12);
+
+ // Create a SAR info record (no sensor support)
+ SarInfo sarInfo = new SarInfo(false);
+
+ // Now expose the 1.2 IWifiChip.
+ mWifiVendorHal = new WifiVendorHalSpyV1_2(mHalDeviceManager, mLooper.getLooper());
+ when(mIWifiChipV12.resetTxPowerScenario()).thenReturn(mWifiStatusSuccess);
+
+ assertTrue(mWifiVendorHal.startVendorHalSta());
+
+ /* Calling reset once */
+ assertTrue(mWifiVendorHal.selectTxPowerScenario(sarInfo));
+ inOrder.verify(mIWifiChipV12).resetTxPowerScenario();
+ inOrder.verify(mIWifiChipV12, never()).selectTxPowerScenario(anyInt());
+ sarInfo.reportingSuccessful();
+
+ /* Calling reset second time */
+ assertTrue(mWifiVendorHal.selectTxPowerScenario(sarInfo));
+ inOrder.verify(mIWifiChipV12, never()).resetTxPowerScenario();
+ inOrder.verify(mIWifiChipV12, never()).selectTxPowerScenario(anyInt());
+
+ mWifiVendorHal.stopVendorHal();
+ }
+
+ /**
+ * Test the selectTxPowerScenario HIDL method invocation with sensor related scenarios
+ * to IWifiChip 1.2 interface
+ */
+ @Test
+ public void testHeadSensorScenarios_SelectTxPowerV1_2() throws RemoteException {
+ // Create a SAR info record (with sensor support)
+ SarInfo sarInfo = new SarInfo(true);
+ sarInfo.mSensorState = SarInfo.SAR_SENSOR_NEAR_HEAD;
+
+ // Expose the 1.2 IWifiChip.
+ mWifiVendorHal = new WifiVendorHalSpyV1_2(mHalDeviceManager, mLooper.getLooper());
+ when(mIWifiChipV12.selectTxPowerScenario_1_2(anyInt())).thenReturn(mWifiStatusSuccess);
+
+ // ON_HEAD_CELL_OFF
+ assertTrue(mWifiVendorHal.startVendorHalSta());
+ assertTrue(mWifiVendorHal.selectTxPowerScenario(sarInfo));
+ verify(mIWifiChipV12).selectTxPowerScenario_1_2(
+ eq(android.hardware.wifi.V1_2.IWifiChip.TxPowerScenario.ON_HEAD_CELL_OFF));
+ verify(mIWifiChipV12, never()).resetTxPowerScenario();
+ mWifiVendorHal.stopVendorHal();
+ }
+
+ /**
+ * Test setting SAR scenario when not needed, should return true without invoking
+ * the HAL method.
+ * This is using HAL 1.2 interface.
+ */
+ @Test
+ public void testSetTxPowerScenario_not_needed_1_2() throws RemoteException {
+ InOrder inOrder = inOrder(mIWifiChipV12);
+
+ // Create a SAR info record (no sensor support)
+ SarInfo sarInfo = new SarInfo(true);
+ sarInfo.mSensorState = SarInfo.SAR_SENSOR_NEAR_HEAD;
+
+ // Now expose the 1.2 IWifiChip.
+ mWifiVendorHal = new WifiVendorHalSpyV1_2(mHalDeviceManager, mLooper.getLooper());
+ when(mIWifiChipV12.selectTxPowerScenario_1_2(anyInt())).thenReturn(mWifiStatusSuccess);
+
+ assertTrue(mWifiVendorHal.startVendorHalSta());
+
+ /* Calling set once */
+ assertTrue(mWifiVendorHal.selectTxPowerScenario(sarInfo));
+ inOrder.verify(mIWifiChipV12).selectTxPowerScenario_1_2(
+ eq(android.hardware.wifi.V1_2.IWifiChip.TxPowerScenario.ON_HEAD_CELL_OFF));
+ inOrder.verify(mIWifiChipV12, never()).resetTxPowerScenario();
+ sarInfo.reportingSuccessful();
+
+ /* Calling set second time */
+ assertTrue(mWifiVendorHal.selectTxPowerScenario(sarInfo));
+ inOrder.verify(mIWifiChipV12, never()).resetTxPowerScenario();
+ inOrder.verify(mIWifiChipV12, never()).selectTxPowerScenario(anyInt());
+
+ mWifiVendorHal.stopVendorHal();
+ }
+
+ /**
+ * Test the selectTxPowerScenairo HIDL method invocation with sensor events for
+ * IWifiChip 1.2 interface (Near hand event) along with a voice call.
+ * This should be reverted to BODY events (First with CELL_OFF followed by CELL_ON).
+ */
+ @Test
+ public void testHandSensorScenarios_SelectTxPowerV1_2() throws RemoteException {
+ // Create a SAR info record (with sensor support)
+ SarInfo sarInfo = new SarInfo(true);
+ sarInfo.mSensorState = SarInfo.SAR_SENSOR_NEAR_HAND;
+
+ // Expose the 1.2 IWifiChip.
+ mWifiVendorHal = new WifiVendorHalSpyV1_2(mHalDeviceManager, mLooper.getLooper());
+ when(mIWifiChipV12.selectTxPowerScenario_1_2(anyInt())).thenReturn(mWifiStatusSuccess);
+
+ assertTrue(mWifiVendorHal.startVendorHalSta());
+
+ // First select a scenario with cell off
+ assertTrue(mWifiVendorHal.selectTxPowerScenario(sarInfo));
+ verify(mIWifiChipV12).selectTxPowerScenario_1_2(
+ eq(android.hardware.wifi.V1_2.IWifiChip.TxPowerScenario.ON_BODY_CELL_OFF));
+
+ // Then select a scenario with cell on
+ sarInfo.mIsVoiceCall = true;
+ assertTrue(mWifiVendorHal.selectTxPowerScenario(sarInfo));
+ verify(mIWifiChipV12).selectTxPowerScenario_1_2(
+ eq(android.hardware.wifi.V1_2.IWifiChip.TxPowerScenario.ON_BODY_CELL_ON));
+
+ mWifiVendorHal.stopVendorHal();
+ }
+
+ /**
+ * Test the selectTxPowerScenario HIDL method invocation with a sensor info to IWifiChip
+ * 1.1 interface.
+ * Sensor mode should be ignored, and act only based on Cell on/off.
+ */
+ @Test
+ public void testOnHeadCellOffOn_SelectTxPowerScenarioV1_1() throws RemoteException {
+ // Create a SAR info record (with sensor support)
+ SarInfo sarInfo = new SarInfo(true);
+ sarInfo.mSensorState = SarInfo.SAR_SENSOR_NEAR_HEAD;
+
+ // Expose the 1.1 IWifiChip.
+ mWifiVendorHal = new WifiVendorHalSpyV1_1(mHalDeviceManager, mLooper.getLooper());
+ when(mIWifiChipV11.selectTxPowerScenario(anyInt())).thenReturn(mWifiStatusSuccess);
+ when(mIWifiChipV11.resetTxPowerScenario()).thenReturn(mWifiStatusSuccess);
+
+ assertTrue(mWifiVendorHal.startVendorHalSta());
+
+ // First select a scenario with cell off
+ assertTrue(mWifiVendorHal.selectTxPowerScenario(sarInfo));
+ verify(mIWifiChipV11).resetTxPowerScenario();
+
+ // Then select a scenario with cell on
+ sarInfo.mIsVoiceCall = true;
+ assertTrue(mWifiVendorHal.selectTxPowerScenario(sarInfo));
+ verify(mIWifiChipV11).selectTxPowerScenario(
+ eq(android.hardware.wifi.V1_1.IWifiChip.TxPowerScenario.VOICE_CALL));
+
+ mWifiVendorHal.stopVendorHal();
+ }
+
+ /**
+ * Test the new selectTxPowerScenario HIDL method invocation with a bad input.
+ * This should not result into any calls to the HAL.
+ * Use IWifiChip 1.2 interface
+ */
+ @Test
+ public void testInvalidSelectTxPowerScenario_1_2() throws RemoteException {
+ // Create a SAR info record (with sensor support)
+ SarInfo sarInfo = new SarInfo(true);
+ sarInfo.mSensorState = SAR_SENSOR_INVALID_STATE;
+
+ // Expose the 1.2 IWifiChip.
+ mWifiVendorHal = new WifiVendorHalSpyV1_2(mHalDeviceManager, mLooper.getLooper());
+
+ assertTrue(mWifiVendorHal.startVendorHalSta());
+ assertFalse(mWifiVendorHal.selectTxPowerScenario(sarInfo));
+ verify(mIWifiChipV12, never()).selectTxPowerScenario(anyInt());
+ verify(mIWifiChipV12, never()).resetTxPowerScenario();
+ mWifiVendorHal.stopVendorHal();
+ }
+
+ /**
+ * Test the selectTxPowerScenario HIDL method invocation with IWifiChip 1.2 interface.
+ * The following inputs:
+ * - Sensor support is enabled
+ * - Sensor state is NEAR_HEAD
+ * - SAP is enabled
+ * - No voice call
+ */
+ @Test
+ public void testSelectTxPowerScenario_1_2_head_sap() throws RemoteException {
+ // Create a SAR info record (with sensor support)
+ SarInfo sarInfo = new SarInfo(true);
+ sarInfo.mSensorState = SarInfo.SAR_SENSOR_NEAR_HEAD;
+ sarInfo.mIsWifiSapEnabled = true;
+ sarInfo.mIsVoiceCall = false;
+
+ // Expose the 1.2 IWifiChip.
+ mWifiVendorHal = new WifiVendorHalSpyV1_2(mHalDeviceManager, mLooper.getLooper());
+ when(mIWifiChipV12.selectTxPowerScenario_1_2(anyInt())).thenReturn(mWifiStatusSuccess);
+
+ assertTrue(mWifiVendorHal.startVendorHalSta());
+ assertTrue(mWifiVendorHal.selectTxPowerScenario(sarInfo));
+ verify(mIWifiChipV12).selectTxPowerScenario_1_2(
+ eq(android.hardware.wifi.V1_2.IWifiChip.TxPowerScenario.ON_HEAD_CELL_ON));
+
+ mWifiVendorHal.stopVendorHal();
+ }
+
+ /**
+ * Test the selectTxPowerScenario HIDL method invocation with IWifiChip 1.2 interface.
+ * The following inputs:
+ * - Sensor support is enabled
+ * - Sensor state is NEAR_HEAD
+ * - SAP is enabled
+ * - voice call is enabled
+ */
+ @Test
+ public void testSelectTxPowerScenario_1_2_head_sap_call() throws RemoteException {
+ // Create a SAR info record (with sensor support)
+ SarInfo sarInfo = new SarInfo(true);
+ sarInfo.mSensorState = SarInfo.SAR_SENSOR_NEAR_HEAD;
+ sarInfo.mIsWifiSapEnabled = true;
+ sarInfo.mIsVoiceCall = true;
+
+ // Expose the 1.2 IWifiChip.
+ mWifiVendorHal = new WifiVendorHalSpyV1_2(mHalDeviceManager, mLooper.getLooper());
+ when(mIWifiChipV12.selectTxPowerScenario_1_2(anyInt())).thenReturn(mWifiStatusSuccess);
+
+ assertTrue(mWifiVendorHal.startVendorHalSta());
+ assertTrue(mWifiVendorHal.selectTxPowerScenario(sarInfo));
+ verify(mIWifiChipV12).selectTxPowerScenario_1_2(
+ eq(android.hardware.wifi.V1_2.IWifiChip.TxPowerScenario.ON_HEAD_CELL_ON));
+
+ mWifiVendorHal.stopVendorHal();
+ }
+
+ /**
+ * Test the selectTxPowerScenario HIDL method invocation with IWifiChip 1.2 interface.
+ * The following inputs:
+ * - Sensor support is enabled
+ * - Sensor state is FREE_SPACE
+ * - SAP is enabled
+ * - No voice call
+ */
+ @Test
+ public void testSelectTxPowerScenario_1_2_freespace_sap() throws RemoteException {
+ // Create a SAR info record (with sensor support)
+ SarInfo sarInfo = new SarInfo(true);
+ sarInfo.mSensorState = SarInfo.SAR_SENSOR_FREE_SPACE;
+ sarInfo.mIsWifiSapEnabled = true;
+ sarInfo.mIsVoiceCall = false;
+
+ // Expose the 1.2 IWifiChip.
+ mWifiVendorHal = new WifiVendorHalSpyV1_2(mHalDeviceManager, mLooper.getLooper());
+ when(mIWifiChipV12.resetTxPowerScenario()).thenReturn(mWifiStatusSuccess);
+
+ assertTrue(mWifiVendorHal.startVendorHalSta());
+ assertTrue(mWifiVendorHal.selectTxPowerScenario(sarInfo));
+
+ verify(mIWifiChipV12).resetTxPowerScenario();
+ verify(mIWifiChipV12, never()).selectTxPowerScenario_1_2(anyInt());
+ mWifiVendorHal.stopVendorHal();
+ }
+
+ /**
+ * Test the selectTxPowerScenario HIDL method invocation with IWifiChip 1.2 interface.
+ * The following inputs:
+ * - Sensor support is disabled
+ * - SAP is enabled
+ * - No voice call
+ */
+ @Test
+ public void testSelectTxPowerScenario_1_2_no_sensors_sap() throws RemoteException {
+ // Create a SAR info record (with no sensor support)
+ SarInfo sarInfo = new SarInfo(false);
+ sarInfo.mIsWifiSapEnabled = true;
+ sarInfo.mIsVoiceCall = false;
+
+ // Expose the 1.2 IWifiChip.
+ mWifiVendorHal = new WifiVendorHalSpyV1_2(mHalDeviceManager, mLooper.getLooper());
+ when(mIWifiChipV12.resetTxPowerScenario()).thenReturn(mWifiStatusSuccess);
+
+ assertTrue(mWifiVendorHal.startVendorHalSta());
+ assertTrue(mWifiVendorHal.selectTxPowerScenario(sarInfo));
+
+ verify(mIWifiChipV12).resetTxPowerScenario();
+ verify(mIWifiChipV12, never()).selectTxPowerScenario_1_2(anyInt());
+ mWifiVendorHal.stopVendorHal();
+ }
+
+ /**
* Test the STA Iface creation failure due to iface name retrieval failure.
*/
@Test