summaryrefslogtreecommitdiff
path: root/service
diff options
context:
space:
mode:
Diffstat (limited to 'service')
-rw-r--r--service/java/com/android/server/wifi/WifiNative.java17
-rw-r--r--service/java/com/android/server/wifi/WifiVendorHal.java229
2 files changed, 245 insertions, 1 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) {