summaryrefslogtreecommitdiff
path: root/service
diff options
context:
space:
mode:
authorAhmed ElArabawy <arabawy@google.com>2018-05-23 13:51:18 -0700
committerAhmed ElArabawy <arabawy@google.com>2018-06-08 09:53:33 -0700
commit7db85489ea6deb3658ed6fc4895622e7a5ec3b18 (patch)
tree34dee11094d754c4d0371c2da5527a94191717f0 /service
parent2e6fdb80cbcd264d774c6e13dd350c2665d21bb1 (diff)
WiFi: Extend SAR in WiFi with body sensors
In previous commits, extending the SAR support of SAR sensors was introduced by adding the SarInfo class and its use in WifiVendorHal to select the proper SAR scenario. However, SarManager was not utilizing this new functionality. This commit provides the support of SarManager to the support for SAR for WiFi TX power backoff when device is in close proximity to head/hand/body of user with or without the presence of a voice call. Bug: 65174506 Test: Run Wifi unit test suite Test: ./frameworks/opt/net/wifi/tests/wifitests/runtests.sh Change-Id: Iac650f586a1419540a6fbef4b75579391fda1aba Signed-off-by: Ahmed ElArabawy <arabawy@google.com>
Diffstat (limited to 'service')
-rw-r--r--service/java/com/android/server/wifi/SarManager.java298
-rw-r--r--service/java/com/android/server/wifi/WifiInjector.java3
2 files changed, 209 insertions, 92 deletions
diff --git a/service/java/com/android/server/wifi/SarManager.java b/service/java/com/android/server/wifi/SarManager.java
index da48a8537..f157ac41e 100644
--- a/service/java/com/android/server/wifi/SarManager.java
+++ b/service/java/com/android/server/wifi/SarManager.java
@@ -20,14 +20,16 @@ import static android.telephony.TelephonyManager.CALL_STATE_IDLE;
import static android.telephony.TelephonyManager.CALL_STATE_OFFHOOK;
import static android.telephony.TelephonyManager.CALL_STATE_RINGING;
-import android.content.BroadcastReceiver;
import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
import android.net.wifi.WifiManager;
import android.os.Looper;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
+import android.text.TextUtils;
import android.util.Log;
import com.android.internal.R;
@@ -41,23 +43,25 @@ import java.util.List;
* It deals with the following:
* - Tracking the STA state through calls from the ClientModeManager.
* - Tracking the state of the Cellular calls or data.
- * - Based on above, selecting the SAR profile to use and programming it in wifi hal.
+ * - Tracking the sensor indicating proximity to user head/hand/body.
+ * - It constructs the sar info and send it towards the HAL
*/
public class SarManager {
-
/* For Logging */
private static final String TAG = "WifiSarManager";
private boolean mVerboseLoggingEnabled = true;
+ private SarInfo mSarInfo;
+
/* Configuration for SAR */
private boolean mEnableSarTxPowerLimit;
+ private boolean mEnableSarBodyProximity;
+ /* Sensor event definitions */
+ private int mSarSensorEventFreeSpace;
+ private int mSarSensorEventNearBody;
+ private int mSarSensorEventNearHand;
+ private int mSarSensorEventNearHead;
- /* Current SAR Scenario */
- private int mCurrentSarScenario = WifiNative.TX_POWER_SCENARIO_NORMAL;
-
- /* Booleans for Cell and wifi states */
- private boolean mCellOn = false;
- private boolean mWifiStaEnabled = false;
/**
* Other parameters passed in or created in the constructor.
*/
@@ -65,6 +69,8 @@ public class SarManager {
private final TelephonyManager mTelephonyManager;
private final WifiPhoneStateListener mPhoneStateListener;
private final WifiNative mWifiNative;
+ private final SarSensorEventListener mSensorListener;
+ private final SensorManager mSensorManager;
private final Looper mLooper;
/**
@@ -73,30 +79,105 @@ public class SarManager {
SarManager(Context context,
TelephonyManager telephonyManager,
Looper looper,
- WifiNative wifiNative) {
+ WifiNative wifiNative,
+ SensorManager sensorManager) {
mContext = context;
mTelephonyManager = telephonyManager;
mWifiNative = wifiNative;
mLooper = looper;
+ mSensorManager = sensorManager;
mPhoneStateListener = new WifiPhoneStateListener(looper);
+ mSensorListener = new SarSensorEventListener();
+
+ readSarConfigs();
+ if (mEnableSarTxPowerLimit) {
+ mSarInfo = new SarInfo(mEnableSarBodyProximity);
+ registerListeners();
+ }
+ }
+
+ private void readSarConfigs() {
+ mEnableSarTxPowerLimit = mContext.getResources().getBoolean(
+ R.bool.config_wifi_framework_enable_sar_tx_power_limit);
+ /* In case SAR is disabled,
+ then SAR sensor is automatically disabled as well (irrespective of the config) */
+ if (!mEnableSarTxPowerLimit) {
+ mEnableSarBodyProximity = false;
+ return;
+ }
- registerListeners();
+ mEnableSarBodyProximity = mContext.getResources().getBoolean(
+ R.bool.config_wifi_framework_enable_body_proximity_sar_tx_power_limit);
+
+ /* Read the sar sensor event Ids */
+ if (mEnableSarBodyProximity) {
+ mSarSensorEventFreeSpace = mContext.getResources().getInteger(
+ R.integer.config_wifi_framework_sar_free_space_event_id);
+ mSarSensorEventNearBody = mContext.getResources().getInteger(
+ R.integer.config_wifi_framework_sar_near_body_event_id);
+ mSarSensorEventNearHand = mContext.getResources().getInteger(
+ R.integer.config_wifi_framework_sar_near_hand_event_id);
+ mSarSensorEventNearHead = mContext.getResources().getInteger(
+ R.integer.config_wifi_framework_sar_near_head_event_id);
+ }
+ }
+
+ private void registerListeners() {
+ /* Listen for Phone State changes */
+ registerPhoneStateListener();
+
+ /* Only listen for SAR sensor if supported */
+ if (mEnableSarBodyProximity) {
+ /* Register the SAR sensor listener.
+ * If this fails, we will assume worst case (near head) */
+ if (!registerSensorListener()) {
+ Log.e(TAG, "Failed to register sensor listener, setting Sensor to NearHead");
+ /*TODO Need to add a metric to determine how often this happens */
+ mSarInfo.mSensorState = SarInfo.SAR_SENSOR_NEAR_HEAD;
+ }
+ }
}
/**
- * Starts the SAR Manager by initializing the different listeners
+ * Register the phone state listener.
*/
- private void registerListeners() {
- /* First read the configuration for SAR Support */
- mEnableSarTxPowerLimit = mContext.getResources().getBoolean(
- R.bool.config_wifi_framework_enable_voice_call_sar_tx_power_limit);
+ private void registerPhoneStateListener() {
+ Log.i(TAG, "Registering for telephony call state changes");
+ mTelephonyManager.listen(
+ mPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
+ }
- /* Only Start listening for events if SAR is enabled */
- if (mEnableSarTxPowerLimit) {
- Log.d(TAG, "Registering Listeners for the SAR Manager");
+ /**
+ * Register the body/hand/head proximity sensor.
+ */
+ private boolean registerSensorListener() {
+ Log.i(TAG, "Registering for Sensor notification Listener");
+ return mSensorListener.register();
+ }
+
+ /**
+ * Update Wifi Client State
+ */
+ public void setClientWifiState(int state) {
+ boolean newIsEnabled;
+ /* No action is taken if SAR is not enabled */
+ if (!mEnableSarTxPowerLimit) {
+ return;
+ }
+
+ if (state == WifiManager.WIFI_STATE_DISABLED) {
+ newIsEnabled = false;
+ } else if (state == WifiManager.WIFI_STATE_ENABLED) {
+ newIsEnabled = true;
+ } else {
+ /* No change so exiting with no action */
+ return;
+ }
- /* Listen for Phone State changes */
- registerPhoneListener();
+ /* Report change to HAL if needed */
+ if (mSarInfo.mIsWifiClientEnabled != newIsEnabled) {
+ mSarInfo.mIsWifiClientEnabled = newIsEnabled;
+ updateSarScenario();
}
}
@@ -104,42 +185,52 @@ public class SarManager {
* Report Cell state event
*/
private void onCellStateChangeEvent(int state) {
- boolean currentCellOn = mCellOn;
-
+ boolean newIsVoiceCall;
switch (state) {
case CALL_STATE_OFFHOOK:
case CALL_STATE_RINGING:
- mCellOn = true;
+ newIsVoiceCall = true;
break;
case CALL_STATE_IDLE:
- mCellOn = false;
+ newIsVoiceCall = false;
break;
default:
Log.e(TAG, "Invalid Cell State: " + state);
+ return;
}
- if (mCellOn != currentCellOn) {
+ /* Report change to HAL if needed */
+ if (mSarInfo.mIsVoiceCall != newIsVoiceCall) {
+ mSarInfo.mIsVoiceCall = newIsVoiceCall;
updateSarScenario();
}
}
/**
- * Update Wifi Client State
+ * Report an event from the SAR sensor
*/
- public void setClientWifiState(int state) {
- /* No action is taken if SAR is not enabled */
- if (!mEnableSarTxPowerLimit) return;
-
- if (state == WifiManager.WIFI_STATE_DISABLED && mWifiStaEnabled) {
- mWifiStaEnabled = false;
- } else if (state == WifiManager.WIFI_STATE_ENABLED && !mWifiStaEnabled) {
- mWifiStaEnabled = true;
+ private void onSarSensorEvent(int sarSensorEvent) {
+ int newSensorState;
+ if (sarSensorEvent == mSarSensorEventFreeSpace) {
+ newSensorState = SarInfo.SAR_SENSOR_FREE_SPACE;
+ } else if (sarSensorEvent == mSarSensorEventNearBody) {
+ newSensorState = SarInfo.SAR_SENSOR_NEAR_BODY;
+ } else if (sarSensorEvent == mSarSensorEventNearHand) {
+ newSensorState = SarInfo.SAR_SENSOR_NEAR_HAND;
+ } else if (sarSensorEvent == mSarSensorEventNearHead) {
+ newSensorState = SarInfo.SAR_SENSOR_NEAR_HEAD;
+ } else {
+ Log.e(TAG, "Invalid SAR sensor event id: " + sarSensorEvent);
+ return;
+ }
- /* Since no wifi interface was up,
- time for SAR scenario to take effect */
- sendTxPowerScenario(mCurrentSarScenario);
+ /* Report change to HAL if needed */
+ if (mSarInfo.mSensorState != newSensorState) {
+ Log.d(TAG, "Setting Sensor state to " + SarInfo.sensorStateToString(newSensorState));
+ mSarInfo.mSensorState = newSensorState;
+ updateSarScenario();
}
}
@@ -155,18 +246,16 @@ public class SarManager {
}
}
- public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- pw.println("*** WiFi SAR Manager Dump ***");
- pw.println("Current SAR Scenario is " + scenarioToString(mCurrentSarScenario));
- }
-
/**
- * Register the phone listener.
+ * dump()
+ * Dumps SarManager state (as well as its SarInfo member variable state)
*/
- private void registerPhoneListener() {
- Log.i(TAG, "Registering for telephony call state changes");
- mTelephonyManager.listen(
- mPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ pw.println("*** WiFi SAR Manager Dump ***");
+ pw.println("isSarEnabled: " + mEnableSarTxPowerLimit);
+ pw.println("isSarSensorEnabled: " + mEnableSarBodyProximity);
+ pw.println("");
+ mSarInfo.dump(fd, pw, args);
}
/**
@@ -177,69 +266,96 @@ public class SarManager {
super(looper);
}
+ /**
+ * onCallStateChanged()
+ * This callback is called when a SAR sensor event is received
+ * Note that this runs in the WifiStateMachineHandlerThread
+ * since the corresponding Looper was passed to the WifiPhoneStateListener constructor.
+ */
@Override
public void onCallStateChanged(int state, String incomingNumber) {
Log.d(TAG, "Received Phone State Change: " + state);
/* In case of an unsolicited event */
- if (!mEnableSarTxPowerLimit) return;
-
+ if (!mEnableSarTxPowerLimit) {
+ return;
+ }
onCellStateChangeEvent(state);
}
}
- /**
- * update the Current SAR Scenario based on factors including:
- * - Do we have an ongoing cellular voice call.
- */
- private void updateSarScenario() {
- int newSarScenario;
+ private class SarSensorEventListener implements SensorEventListener {
- if (mCellOn) {
- newSarScenario = WifiNative.TX_POWER_SCENARIO_VOICE_CALL;
- } else {
- newSarScenario = WifiNative.TX_POWER_SCENARIO_NORMAL;
- }
+ private Sensor mSensor;
+
+ /**
+ * Register the SAR listener to get SAR sensor events
+ */
+ private boolean register() {
+ /* Get the sensor type from configuration */
+ String sensorType = mContext.getResources().getString(
+ R.string.config_wifi_sar_sensor_type);
+ if (TextUtils.isEmpty(sensorType)) {
+ Log.e(TAG, "Empty SAR sensor type");
+ return false;
+ }
- if (newSarScenario != mCurrentSarScenario) {
+ /* Get the sensor object */
+ Sensor sensor = null;
+ List<Sensor> sensorList = mSensorManager.getSensorList(Sensor.TYPE_ALL);
+ for (Sensor s : sensorList) {
+ if (sensorType.equals(s.getStringType())) {
+ sensor = s;
+ break;
+ }
+ }
+ if (sensor == null) {
+ Log.e(TAG, "Failed to Find the SAR Sensor");
+ return false;
+ }
- // Only update HAL with new scenario if WiFi interface is enabled
- if (mWifiStaEnabled) {
- Log.d(TAG, "Sending SAR Scenario #" + scenarioToString(newSarScenario));
- sendTxPowerScenario(newSarScenario);
+ /* Now register the listener */
+ if (!mSensorManager.registerListener(this, sensor,
+ SensorManager.SENSOR_DELAY_NORMAL)) {
+ Log.e(TAG, "Failed to register SAR Sensor Listener");
+ return false;
}
- mCurrentSarScenario = newSarScenario;
+ return true;
}
- }
- /**
- * sendTxPowerScenario()
- * Update HAL with the new power scenario.
- */
- private void sendTxPowerScenario(int newSarScenario) {
- if (!mWifiNative.selectTxPowerScenario(newSarScenario)) {
- Log.e(TAG, "Failed to set TX power scenario");
+ /**
+ * onSensorChanged()
+ * This callback is called when a SAR sensor event is received
+ * Note that this runs in the WifiStateMachineHandlerThread
+ * since, the corresponding Looper was passed to the SensorManager instance.
+ */
+ @Override
+ public void onSensorChanged(SensorEvent event) {
+ onSarSensorEvent((int) event.values[0]);
+ }
+
+ @Override
+ public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
}
/**
- * Convert SAR Scenario to string
+ * updateSarScenario()
+ * Update HAL with the new SAR scenario if needed.
*/
- private String scenarioToString(int scenario) {
- String str;
- switch(scenario) {
- case WifiNative.TX_POWER_SCENARIO_NORMAL:
- str = "TX_POWER_SCENARIO_NORMAL";
- break;
- case WifiNative.TX_POWER_SCENARIO_VOICE_CALL:
- str = "TX_POWER_SCENARIO_VOICE_CALL";
- break;
- default:
- str = "Invalid Scenario";
- break;
+ private void updateSarScenario() {
+ if (!mSarInfo.shouldReport()) {
+ return;
+ }
+
+ /* Report info to HAL*/
+ if (mWifiNative.selectTxPowerScenario(mSarInfo)) {
+ mSarInfo.reportingSuccessful();
+ } else {
+ Log.e(TAG, "Failed in WifiNative.selectTxPowerScenario()");
}
- return str;
+ return;
}
}
diff --git a/service/java/com/android/server/wifi/WifiInjector.java b/service/java/com/android/server/wifi/WifiInjector.java
index 0e30af841..5a4fe570b 100644
--- a/service/java/com/android/server/wifi/WifiInjector.java
+++ b/service/java/com/android/server/wifi/WifiInjector.java
@@ -20,6 +20,7 @@ import android.annotation.NonNull;
import android.app.ActivityManager;
import android.app.AppOpsManager;
import android.content.Context;
+import android.hardware.SystemSensorManager;
import android.net.NetworkKey;
import android.net.NetworkScoreManager;
import android.net.wifi.IWifiScanner;
@@ -253,7 +254,7 @@ public class WifiInjector {
this, mWifiConfigManager,
mWifiPermissionsUtil, mWifiMetrics, mClock);
mSarManager = new SarManager(mContext, makeTelephonyManager(), wifiStateMachineLooper,
- mWifiNative);
+ mWifiNative, new SystemSensorManager(mContext, wifiStateMachineLooper));
if (mUseRealLogger) {
mWifiDiagnostics = new WifiDiagnostics(
mContext, this, mWifiNative, mBuildProperties,