diff options
author | android-build-team Robot <android-build-team-robot@google.com> | 2019-05-13 14:38:54 -0700 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2019-05-13 14:38:54 -0700 |
commit | 2bcc5fbbcfad24eeaf4a093d249912f5989618d4 (patch) | |
tree | 2c3c3edd2f3c46abe9aa02ab77f045b24b71c003 | |
parent | c94198e1304c9a8788491033eb0b1d21bab4a7e0 (diff) | |
parent | cf551962601a2878a66a28cacaf45b58838f82ba (diff) | |
download | android_frameworks_opt_net_wifi-2bcc5fbbcfad24eeaf4a093d249912f5989618d4.tar.gz android_frameworks_opt_net_wifi-2bcc5fbbcfad24eeaf4a093d249912f5989618d4.tar.bz2 android_frameworks_opt_net_wifi-2bcc5fbbcfad24eeaf4a093d249912f5989618d4.zip |
Snap for 5450365 from 1ed8ffb8f411b72f21baffa8999386882c80bd57 to pi-platform-release
am: cf55196260
Change-Id: I45473f31f327f9958402ce477cb59bf6a3d93500
7 files changed, 213 insertions, 24 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/WifiBackupDataV1Parser.java b/service/java/com/android/server/wifi/WifiBackupDataV1Parser.java index 9a6cf36db..9b27cf434 100644 --- a/service/java/com/android/server/wifi/WifiBackupDataV1Parser.java +++ b/service/java/com/android/server/wifi/WifiBackupDataV1Parser.java @@ -167,8 +167,7 @@ class WifiBackupDataV1Parser implements WifiBackupDataParser { in, WifiBackupRestore.XML_TAG_SECTION_HEADER_WIFI_CONFIGURATION, networkTagDepth); int configTagDepth = networkTagDepth + 1; - configuration = parseWifiConfigurationFromXmlAndValidateConfigKey(in, configTagDepth, - minorVersion); + configuration = parseWifiConfigurationFromXml(in, configTagDepth, minorVersion); if (configuration == null) { return null; } @@ -182,12 +181,12 @@ class WifiBackupDataV1Parser implements WifiBackupDataParser { } /** - * Helper method to parse the WifiConfiguration object and validate the configKey parsed. + * Helper method to parse the WifiConfiguration object. */ - private WifiConfiguration parseWifiConfigurationFromXmlAndValidateConfigKey(XmlPullParser in, + private WifiConfiguration parseWifiConfigurationFromXml(XmlPullParser in, int outerTagDepth, int minorVersion) throws XmlPullParserException, IOException { Pair<String, WifiConfiguration> parsedConfig = - parseWifiConfigurationFromXml(in, outerTagDepth, minorVersion); + parseWifiConfigurationFromXmlInternal(in, outerTagDepth, minorVersion); if (parsedConfig == null || parsedConfig.first == null || parsedConfig.second == null) { return null; } @@ -195,17 +194,10 @@ class WifiBackupDataV1Parser implements WifiBackupDataParser { WifiConfiguration configuration = parsedConfig.second; String configKeyCalculated = configuration.configKey(); if (!configKeyParsed.equals(configKeyCalculated)) { - String configKeyMismatchLog = - "Configuration key does not match. Retrieved: " + configKeyParsed - + ", Calculated: " + configKeyCalculated; - if (configuration.shared) { - Log.e(TAG, configKeyMismatchLog); - return null; - } else { - // ConfigKey mismatches are expected for private networks because the - // UID is not preserved across backup/restore. - Log.w(TAG, configKeyMismatchLog); - } + // configKey is not part of the SDK. So, we can't expect this to be the same + // across OEM's. Just log a warning & continue. + Log.w(TAG, "Configuration key does not match. Retrieved: " + configKeyParsed + + ", Calculated: " + configKeyCalculated); } return configuration; } @@ -269,8 +261,9 @@ class WifiBackupDataV1Parser implements WifiBackupDataParser { * @param minorVersion minor version number parsed from incoming data. * @return Pair<Config key, WifiConfiguration object> if parsing is successful, null otherwise. */ - private static Pair<String, WifiConfiguration> parseWifiConfigurationFromXml(XmlPullParser in, - int outerTagDepth, int minorVersion) throws XmlPullParserException, IOException { + private static Pair<String, WifiConfiguration> parseWifiConfigurationFromXmlInternal( + XmlPullParser in, int outerTagDepth, int minorVersion) + throws XmlPullParserException, IOException { WifiConfiguration configuration = new WifiConfiguration(); String configKeyInData = null; Set<String> supportedTags = getSupportedWifiConfigurationTags(minorVersion); 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 */ |