diff options
author | Ahmed ElArabawy <arabawy@google.com> | 2018-05-22 22:55:16 -0700 |
---|---|---|
committer | Ahmed ElArabawy <arabawy@google.com> | 2018-06-08 09:11:52 -0700 |
commit | 2e6fdb80cbcd264d774c6e13dd350c2665d21bb1 (patch) | |
tree | b029fb58fcc1bf61057c261b251678823e602f33 | |
parent | dc3d066444208c13ed4caf69bebee6b68e7488f3 (diff) |
WiFi: SAR Support: Use SarInfo in WifiVendorHal
In a previous commit, the class SarInfo was introduced.
This commit utilizes this class to pass SAR related inputs to
WifiVendorHal to select the SAR scenario.
Note that the functionality introduced in this commit is not
called yet during operation. Hence the legacy code is left in
place until the new functionality is fully utilized.
Bug: 65174506
Test: Run Wifi unit test suite
Test: ./frameworks/opt/net/wifi/tests/wifitests/runtests.sh
Change-Id: Idb00f2c265d64ea4e8fc3a6e2ed7fc9bc08539fb
Signed-off-by: Ahmed ElArabawy <arabawy@google.com>
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 |