summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorandroid-build-team Robot <android-build-team-robot@google.com>2019-02-20 04:12:41 +0000
committerandroid-build-team Robot <android-build-team-robot@google.com>2019-02-20 04:12:41 +0000
commita3e354fe4c66de82f1834c7e195c1ae8a5116984 (patch)
tree2c3c3edd2f3c46abe9aa02ab77f045b24b71c003
parentf89adbf3e7b2d56b8806ce2bd797dc9b2aec3526 (diff)
parent0b7dfd2253af0f4713af3a7f6ca5f233f0fbf8b9 (diff)
downloadandroid_frameworks_opt_net_wifi-a3e354fe4c66de82f1834c7e195c1ae8a5116984.tar.gz
android_frameworks_opt_net_wifi-a3e354fe4c66de82f1834c7e195c1ae8a5116984.tar.bz2
android_frameworks_opt_net_wifi-a3e354fe4c66de82f1834c7e195c1ae8a5116984.zip
Snap for 5322077 from 0b7dfd2253af0f4713af3a7f6ca5f233f0fbf8b9 to pi-qpr3-release
Change-Id: I4971ec001f76ca0ad3a2e28f8df18a09e984095f
-rw-r--r--service/java/com/android/server/wifi/SarInfo.java8
-rw-r--r--service/java/com/android/server/wifi/SarManager.java144
-rw-r--r--service/java/com/android/server/wifi/WifiStateMachine.java2
-rw-r--r--service/java/com/android/server/wifi/WifiVendorHal.java10
-rw-r--r--tests/wifitests/src/com/android/server/wifi/SarInfoTest.java15
-rw-r--r--tests/wifitests/src/com/android/server/wifi/WifiVendorHalTest.java29
6 files changed, 202 insertions, 6 deletions
diff --git a/service/java/com/android/server/wifi/SarInfo.java b/service/java/com/android/server/wifi/SarInfo.java
index a62307e13..7d580656b 100644
--- a/service/java/com/android/server/wifi/SarInfo.java
+++ b/service/java/com/android/server/wifi/SarInfo.java
@@ -74,6 +74,7 @@ public class SarInfo {
public boolean isWifiSapEnabled = false;
public boolean isWifiScanOnlyEnabled = false;
public boolean isVoiceCall = false;
+ public boolean isEarPieceActive = false;
public int attemptedSarScenario = RESET_SAR_SCENARIO;
private boolean mAllWifiDisabled = true;
@@ -82,6 +83,7 @@ public class SarInfo {
private int mLastReportedSensorState = SAR_SENSOR_FREE_SPACE;
private boolean mLastReportedIsWifiSapEnabled = false;
private boolean mLastReportedIsVoiceCall = false;
+ private boolean mLastReportedIsEarPieceActive = false;
private int mLastReportedScenario = INITIAL_SAR_SCENARIO;
private long mLastReportedScenarioTs = 0;
@@ -113,7 +115,8 @@ public class SarInfo {
/* Check if some change happened since last successful reporting */
if ((sensorState != mLastReportedSensorState)
|| (isWifiSapEnabled != mLastReportedIsWifiSapEnabled)
- || (isVoiceCall != mLastReportedIsVoiceCall)) {
+ || (isVoiceCall != mLastReportedIsVoiceCall)
+ || (isEarPieceActive != mLastReportedIsEarPieceActive)) {
return true;
} else {
return false;
@@ -129,6 +132,7 @@ public class SarInfo {
mLastReportedSensorState = sensorState;
mLastReportedIsWifiSapEnabled = isWifiSapEnabled;
mLastReportedIsVoiceCall = isVoiceCall;
+ mLastReportedIsEarPieceActive = isEarPieceActive;
mLastReportedScenario = attemptedSarScenario;
mLastReportedScenarioTs = System.currentTimeMillis();
@@ -169,10 +173,12 @@ public class SarInfo {
pw.println(" Wifi Client state is: " + isWifiClientEnabled);
pw.println(" Wifi Soft AP state is: " + isWifiSapEnabled);
pw.println(" Wifi ScanOnly state is: " + isWifiScanOnlyEnabled);
+ pw.println(" Earpiece state is : " + isEarPieceActive);
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);
+ pw.println(" Earpiece state is: " + mLastReportedIsEarPieceActive);
pw.println("Last reported scenario: " + mLastReportedScenario);
pw.println("Reported " + (System.currentTimeMillis() - mLastReportedScenarioTs) / 1000
+ " seconds ago");
diff --git a/service/java/com/android/server/wifi/SarManager.java b/service/java/com/android/server/wifi/SarManager.java
index 598e5c964..f0319fb6b 100644
--- a/service/java/com/android/server/wifi/SarManager.java
+++ b/service/java/com/android/server/wifi/SarManager.java
@@ -20,12 +20,18 @@ 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.media.AudioManager;
+import android.media.AudioSystem;
import android.net.wifi.WifiManager;
+import android.os.Handler;
import android.os.Looper;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
@@ -33,6 +39,7 @@ import android.text.TextUtils;
import android.util.Log;
import com.android.internal.R;
+import com.android.server.wifi.util.WifiHandler;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -49,6 +56,8 @@ import java.util.List;
* - It constructs the sar info and send it towards the HAL
*/
public class SarManager {
+ // Period for checking on voice steam active (in ms)
+ private static final int CHECK_VOICE_STREAM_INTERVAL_MS = 5000;
/* For Logging */
private static final String TAG = "WifiSarManager";
private boolean mVerboseLoggingEnabled = true;
@@ -66,6 +75,10 @@ public class SarManager {
private int mSarSensorEventNearHand;
private int mSarSensorEventNearHead;
+ // Device starts with screen on
+ private boolean mScreenOn = false;
+ private boolean mIsVoiceStreamCheckEnabled = false;
+
/**
* Other parameters passed in or created in the constructor.
*/
@@ -75,6 +88,7 @@ public class SarManager {
private final WifiNative mWifiNative;
private final SarSensorEventListener mSensorListener;
private final SensorManager mSensorManager;
+ private final Handler mHandler;
private final Looper mLooper;
/**
@@ -89,6 +103,7 @@ public class SarManager {
mTelephonyManager = telephonyManager;
mWifiNative = wifiNative;
mLooper = looper;
+ mHandler = new WifiHandler(TAG, looper);
mSensorManager = sensorManager;
mPhoneStateListener = new WifiPhoneStateListener(looper);
mSensorListener = new SarSensorEventListener();
@@ -101,6 +116,80 @@ public class SarManager {
}
}
+ /**
+ * Notify SarManager of screen status change
+ */
+ public void handleScreenStateChanged(boolean screenOn) {
+ if (!mSupportSarVoiceCall) {
+ return;
+ }
+
+ if (mScreenOn == screenOn) {
+ return;
+ }
+
+ if (mVerboseLoggingEnabled) {
+ Log.d(TAG, "handleScreenStateChanged: screenOn = " + screenOn);
+ }
+
+ mScreenOn = screenOn;
+
+ // Only schedule a voice stream check if screen is turning on, and it is currently not
+ // scheduled
+ if (mScreenOn && !mIsVoiceStreamCheckEnabled) {
+ mHandler.post(() -> {
+ checkAudioDevice();
+ });
+
+ mIsVoiceStreamCheckEnabled = true;
+ }
+ }
+
+ private boolean isVoiceCallOnEarpiece() {
+ AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
+
+ return (audioManager.getDevicesForStream(AudioManager.STREAM_VOICE_CALL)
+ == AudioManager.DEVICE_OUT_EARPIECE);
+ }
+
+ private boolean isVoiceCallStreamActive() {
+ return AudioSystem.isStreamActive(AudioManager.STREAM_VOICE_CALL, 0);
+ }
+
+ private void checkAudioDevice() {
+ // First Check if audio stream is on
+ boolean voiceStreamActive = isVoiceCallStreamActive();
+ boolean earPieceActive;
+
+ if (voiceStreamActive) {
+ // Check on the audio route
+ earPieceActive = isVoiceCallOnEarpiece();
+
+ if (mVerboseLoggingEnabled) {
+ Log.d(TAG, "EarPiece active = " + earPieceActive);
+ }
+ } else {
+ earPieceActive = false;
+ }
+
+ // If audio route has changed, update SAR
+ if (earPieceActive != mSarInfo.isEarPieceActive) {
+ mSarInfo.isEarPieceActive = earPieceActive;
+ updateSarScenario();
+ }
+
+ // Now should we proceed with the checks
+ if (!mScreenOn && !voiceStreamActive) {
+ // No need to continue checking
+ mIsVoiceStreamCheckEnabled = false;
+ } else {
+ // Schedule another check
+ mHandler.postDelayed(() -> {
+ checkAudioDevice();
+ }, CHECK_VOICE_STREAM_INTERVAL_MS);
+ }
+ }
+
private void readSarConfigs() {
mSupportSarTxPowerLimit = mContext.getResources().getBoolean(
R.bool.config_wifi_framework_enable_sar_tx_power_limit);
@@ -145,6 +234,7 @@ public class SarManager {
if (mSupportSarVoiceCall) {
/* Listen for Phone State changes */
registerPhoneStateListener();
+ registerVoiceStreamListener();
}
/* Only listen for SAR sensor if supported */
@@ -159,6 +249,56 @@ public class SarManager {
}
}
+ private void registerVoiceStreamListener() {
+ Log.i(TAG, "Registering for voice stream status");
+
+ // Register for listening to transitions of change of voice stream devices
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(AudioManager.STREAM_DEVICES_CHANGED_ACTION);
+
+ mContext.registerReceiver(
+ new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ boolean voiceStreamActive = isVoiceCallStreamActive();
+ if (!voiceStreamActive) {
+ // No need to proceed, there is no voice call ongoing
+ return;
+ }
+
+ String action = intent.getAction();
+ int streamType =
+ intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1);
+ int device = intent.getIntExtra(
+ AudioManager.EXTRA_VOLUME_STREAM_DEVICES, -1);
+ int oldDevice = intent.getIntExtra(
+ AudioManager.EXTRA_PREV_VOLUME_STREAM_DEVICES, -1);
+
+ if (streamType == AudioManager.STREAM_VOICE_CALL) {
+ boolean earPieceActive = mSarInfo.isEarPieceActive;
+ if (device == AudioManager.DEVICE_OUT_EARPIECE) {
+ if (mVerboseLoggingEnabled) {
+ Log.d(TAG, "Switching to earpiece : HEAD ON");
+ Log.d(TAG, "Old device = " + oldDevice);
+ }
+ earPieceActive = true;
+ } else if (oldDevice == AudioManager.DEVICE_OUT_EARPIECE) {
+ if (mVerboseLoggingEnabled) {
+ Log.d(TAG, "Switching from earpiece : HEAD OFF");
+ Log.d(TAG, "New device = " + device);
+ }
+ earPieceActive = false;
+ }
+
+ if (earPieceActive != mSarInfo.isEarPieceActive) {
+ mSarInfo.isEarPieceActive = earPieceActive;
+ updateSarScenario();
+ }
+ }
+ }
+ }, filter, null, mHandler);
+ }
+
/**
* Register the phone state listener.
*/
@@ -277,6 +417,10 @@ public class SarManager {
/* Report change to HAL if needed */
if (mSarInfo.isVoiceCall != newIsVoiceCall) {
mSarInfo.isVoiceCall = newIsVoiceCall;
+
+ if (mVerboseLoggingEnabled) {
+ Log.d(TAG, "Voice Call = " + newIsVoiceCall);
+ }
updateSarScenario();
}
}
diff --git a/service/java/com/android/server/wifi/WifiStateMachine.java b/service/java/com/android/server/wifi/WifiStateMachine.java
index 67b1ad6e7..390a10238 100644
--- a/service/java/com/android/server/wifi/WifiStateMachine.java
+++ b/service/java/com/android/server/wifi/WifiStateMachine.java
@@ -2392,6 +2392,8 @@ public class WifiStateMachine extends StateMachine {
mWifiConnectivityManager.handleScreenStateChanged(screenOn);
}
+ mSarManager.handleScreenStateChanged(screenOn);
+
if (mVerboseLoggingEnabled) log("handleScreenStateChanged Exit: " + screenOn);
}
diff --git a/service/java/com/android/server/wifi/WifiVendorHal.java b/service/java/com/android/server/wifi/WifiVendorHal.java
index fad90d140..cff9a91e7 100644
--- a/service/java/com/android/server/wifi/WifiVendorHal.java
+++ b/service/java/com/android/server/wifi/WifiVendorHal.java
@@ -2664,7 +2664,7 @@ public class WifiVendorHal {
/* As long as no voice call is active (in case voice call is supported),
* no backoff is needed */
if (sarInfo.sarVoiceCallSupported) {
- return sarInfo.isVoiceCall;
+ return (sarInfo.isVoiceCall || sarInfo.isEarPieceActive);
} else {
return false;
}
@@ -2679,7 +2679,7 @@ public class WifiVendorHal {
* Otherwise, an exception is thrown.
*/
private int frameworkToHalTxPowerScenario_1_1(SarInfo sarInfo) {
- if (sarInfo.sarVoiceCallSupported && sarInfo.isVoiceCall) {
+ if (sarInfo.sarVoiceCallSupported && (sarInfo.isVoiceCall || sarInfo.isEarPieceActive)) {
return android.hardware.wifi.V1_1.IWifiChip.TxPowerScenario.VOICE_CALL;
} else {
throw new IllegalArgumentException("bad scenario: voice call not active/supported");
@@ -2703,7 +2703,7 @@ public class WifiVendorHal {
if (sarInfo.sarSapSupported && sarInfo.isWifiSapEnabled) {
return true;
}
- if (sarInfo.sarVoiceCallSupported && sarInfo.isVoiceCall) {
+ if (sarInfo.sarVoiceCallSupported && (sarInfo.isVoiceCall || sarInfo.isEarPieceActive)) {
return true;
}
return false;
@@ -2752,7 +2752,7 @@ public class WifiVendorHal {
throw new IllegalArgumentException("bad scenario: Invalid sensor state");
}
} else if (sarInfo.sarSapSupported && sarInfo.sarVoiceCallSupported) {
- if (sarInfo.isVoiceCall) {
+ if (sarInfo.isVoiceCall || sarInfo.isEarPieceActive) {
return android.hardware.wifi.V1_2.IWifiChip
.TxPowerScenario.ON_HEAD_CELL_ON;
} else if (sarInfo.isWifiSapEnabled) {
@@ -2763,7 +2763,7 @@ public class WifiVendorHal {
}
} else if (sarInfo.sarVoiceCallSupported) {
/* SAR Sensors and SoftAP not supported, act like V1_1 */
- if (sarInfo.isVoiceCall) {
+ if (sarInfo.isVoiceCall || sarInfo.isEarPieceActive) {
return android.hardware.wifi.V1_1.IWifiChip.TxPowerScenario.VOICE_CALL;
} else {
throw new IllegalArgumentException("bad scenario: voice call not active");
diff --git a/tests/wifitests/src/com/android/server/wifi/SarInfoTest.java b/tests/wifitests/src/com/android/server/wifi/SarInfoTest.java
index 2bf1f3ee4..50aec5917 100644
--- a/tests/wifitests/src/com/android/server/wifi/SarInfoTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/SarInfoTest.java
@@ -231,6 +231,21 @@ public class SarInfoTest {
}
/**
+ * Test a change in earpiece status, shouldReport should return true
+ * Note: will need to report once before making the change to remove
+ * the effect of sensor state change.
+ */
+ @Test
+ public void testSarInfo_earpiece_wifi_enabled() throws Exception {
+ mSarInfo.isWifiClientEnabled = true;
+ assertTrue(mSarInfo.shouldReport());
+ mSarInfo.reportingSuccessful();
+
+ mSarInfo.isEarPieceActive = 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.
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiVendorHalTest.java b/tests/wifitests/src/com/android/server/wifi/WifiVendorHalTest.java
index f089ebbe7..ebeecbd28 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiVendorHalTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiVendorHalTest.java
@@ -2259,6 +2259,35 @@ public class WifiVendorHalTest {
}
/**
+ * Test the selectTxPowerScenario HIDL method invocation with no sensor support, but with
+ * SAP and voice call support.
+ * When earpiece is active, should result in cell with near head scenario
+ * Using IWifiChip 1.2 interface
+ */
+ @Test
+ public void testEarPieceScenarios_SelectTxPowerV1_2() throws RemoteException {
+ // Create a SAR info record (with sensor and SAP support)
+ SarInfo sarInfo = new SarInfo();
+ sarInfo.sarVoiceCallSupported = true;
+ sarInfo.sarSapSupported = true;
+ sarInfo.sarSensorSupported = false;
+
+ sarInfo.isEarPieceActive = true;
+
+ // Expose the 1.2 IWifiChip.
+ mWifiVendorHal = new WifiVendorHalSpyV1_2(mHalDeviceManager, mLooper.getLooper());
+ when(mIWifiChipV12.selectTxPowerScenario_1_2(anyInt())).thenReturn(mWifiStatusSuccess);
+
+ // ON_HEAD_CELL_ON
+ assertTrue(mWifiVendorHal.startVendorHalSta());
+ assertTrue(mWifiVendorHal.selectTxPowerScenario(sarInfo));
+ verify(mIWifiChipV12).selectTxPowerScenario_1_2(
+ eq(android.hardware.wifi.V1_2.IWifiChip.TxPowerScenario.ON_HEAD_CELL_ON));
+ verify(mIWifiChipV12, never()).resetTxPowerScenario();
+ mWifiVendorHal.stopVendorHal();
+ }
+
+ /**
* Test the selectTxPowerScenario HIDL method invocation with sensor related scenarios
* to IWifiChip 1.2 interface
*/