diff options
author | Ahmed ElArabawy <arabawy@google.com> | 2018-03-09 10:30:50 -0800 |
---|---|---|
committer | Ahmed ElArabawy <arabawy@google.com> | 2018-05-02 16:47:03 -0700 |
commit | d55d1c65e5f4569652492828e4ab3eb201921ae8 (patch) | |
tree | b1aedba7810af11c51f59900aba9fb3ae27b9a97 | |
parent | 6b9f7ba3c20a01689c1027043b6e6eb5b253348e (diff) |
WiFi: Move SAR implementation to SarManager
This commit is the first stage of extending SAR Support in WiFi.
This stage include removing SAR handling from the WifiStateMachine and
putting it in a separate SarManager.
No new functionality is added yet in this stage.
Note that unit test cases for SAR related functionality in WifiStateMachine
are removed and added to SarManager
Bug: 65174506
Test: Run Wifi unit test suite
Test: ./frameworks/opt/net/wifi/tests/wifitests/runtests.sh
Change-Id: I0a08180cfff22002f75a6966009e62b9c66044c3
Signed-off-by: Ahmed ElArabawy <arabawy@google.com>
5 files changed, 524 insertions, 220 deletions
diff --git a/service/java/com/android/server/wifi/SarManager.java b/service/java/com/android/server/wifi/SarManager.java new file mode 100644 index 000000000..da48a8537 --- /dev/null +++ b/service/java/com/android/server/wifi/SarManager.java @@ -0,0 +1,245 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.wifi; + +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.net.wifi.WifiManager; +import android.os.Looper; +import android.telephony.PhoneStateListener; +import android.telephony.TelephonyManager; +import android.util.Log; + +import com.android.internal.R; + +import java.io.FileDescriptor; +import java.io.PrintWriter; +import java.util.List; + +/** + * This class provides the Support for SAR to control WiFi TX power limits. + * 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. + */ +public class SarManager { + + /* For Logging */ + private static final String TAG = "WifiSarManager"; + private boolean mVerboseLoggingEnabled = true; + + /* Configuration for SAR */ + private boolean mEnableSarTxPowerLimit; + + /* 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. + */ + private final Context mContext; + private final TelephonyManager mTelephonyManager; + private final WifiPhoneStateListener mPhoneStateListener; + private final WifiNative mWifiNative; + private final Looper mLooper; + + /** + * Create new instance of SarManager. + */ + SarManager(Context context, + TelephonyManager telephonyManager, + Looper looper, + WifiNative wifiNative) { + mContext = context; + mTelephonyManager = telephonyManager; + mWifiNative = wifiNative; + mLooper = looper; + mPhoneStateListener = new WifiPhoneStateListener(looper); + + registerListeners(); + } + + /** + * Starts the SAR Manager by initializing the different listeners + */ + 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); + + /* Only Start listening for events if SAR is enabled */ + if (mEnableSarTxPowerLimit) { + Log.d(TAG, "Registering Listeners for the SAR Manager"); + + /* Listen for Phone State changes */ + registerPhoneListener(); + } + } + + /** + * Report Cell state event + */ + private void onCellStateChangeEvent(int state) { + boolean currentCellOn = mCellOn; + + switch (state) { + case CALL_STATE_OFFHOOK: + case CALL_STATE_RINGING: + mCellOn = true; + break; + + case CALL_STATE_IDLE: + mCellOn = false; + break; + + default: + Log.e(TAG, "Invalid Cell State: " + state); + } + + if (mCellOn != currentCellOn) { + updateSarScenario(); + } + } + + /** + * Update Wifi Client State + */ + 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; + + /* Since no wifi interface was up, + time for SAR scenario to take effect */ + sendTxPowerScenario(mCurrentSarScenario); + } + } + + /** + * Enable/disable verbose logging. + */ + public void enableVerboseLogging(int verbose) { + Log.d(TAG, "Inside enableVerboseLogging: " + verbose); + if (verbose > 0) { + mVerboseLoggingEnabled = true; + } else { + mVerboseLoggingEnabled = false; + } + } + + 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. + */ + private void registerPhoneListener() { + Log.i(TAG, "Registering for telephony call state changes"); + mTelephonyManager.listen( + mPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE); + } + + /** + * Listen for phone call state events to set/reset TX power limits for SAR requirements. + */ + private class WifiPhoneStateListener extends PhoneStateListener { + WifiPhoneStateListener(Looper looper) { + super(looper); + } + + @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; + + onCellStateChangeEvent(state); + } + } + + /** + * update the Current SAR Scenario based on factors including: + * - Do we have an ongoing cellular voice call. + */ + private void updateSarScenario() { + int newSarScenario; + + if (mCellOn) { + newSarScenario = WifiNative.TX_POWER_SCENARIO_VOICE_CALL; + } else { + newSarScenario = WifiNative.TX_POWER_SCENARIO_NORMAL; + } + + if (newSarScenario != mCurrentSarScenario) { + + // Only update HAL with new scenario if WiFi interface is enabled + if (mWifiStaEnabled) { + Log.d(TAG, "Sending SAR Scenario #" + scenarioToString(newSarScenario)); + sendTxPowerScenario(newSarScenario); + } + + mCurrentSarScenario = newSarScenario; + } + } + + /** + * 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"); + } + } + + /** + * Convert SAR Scenario to string + */ + 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; + } + + return str; + } +} diff --git a/service/java/com/android/server/wifi/WifiInjector.java b/service/java/com/android/server/wifi/WifiInjector.java index a64075006..7fc49ece2 100644 --- a/service/java/com/android/server/wifi/WifiInjector.java +++ b/service/java/com/android/server/wifi/WifiInjector.java @@ -137,6 +137,7 @@ public class WifiInjector { private final WakeupController mWakeupController; private final INetworkManagementService mNwManagementService; private final ScanRequestProxy mScanRequestProxy; + private final SarManager mSarManager; private final boolean mUseRealLogger; @@ -252,10 +253,13 @@ public class WifiInjector { mWifiPermissionsUtil, mWifiMetrics, mClock); // mWifiStateMachine has an implicit dependency on mJavaRuntime due to WifiDiagnostics. mJavaRuntime = Runtime.getRuntime(); + mSarManager = new SarManager(mContext, makeTelephonyManager(), wifiStateMachineLooper, + mWifiNative); mWifiStateMachine = new WifiStateMachine(mContext, mFrameworkFacade, wifiStateMachineLooper, UserManager.get(mContext), this, mBackupManagerProxy, mCountryCode, mWifiNative, - new WrongPasswordNotifier(mContext, mFrameworkFacade)); + new WrongPasswordNotifier(mContext, mFrameworkFacade), + mSarManager); IBinder b = mFrameworkFacade.getService(Context.NETWORKMANAGEMENT_SERVICE); mWifiStateMachinePrime = new WifiStateMachinePrime(this, mContext, wifiStateMachineLooper, mWifiNative, new DefaultModeManager(mContext, wifiStateMachineLooper), @@ -358,6 +362,10 @@ public class WifiInjector { return mWifiApConfigStore; } + public SarManager getSarManager() { + return mSarManager; + } + public WifiStateMachine getWifiStateMachine() { return mWifiStateMachine; } diff --git a/service/java/com/android/server/wifi/WifiStateMachine.java b/service/java/com/android/server/wifi/WifiStateMachine.java index af0b8c257..6b0bec244 100644 --- a/service/java/com/android/server/wifi/WifiStateMachine.java +++ b/service/java/com/android/server/wifi/WifiStateMachine.java @@ -21,8 +21,6 @@ import static android.net.wifi.WifiManager.WIFI_STATE_DISABLING; import static android.net.wifi.WifiManager.WIFI_STATE_ENABLED; import static android.net.wifi.WifiManager.WIFI_STATE_ENABLING; import static android.net.wifi.WifiManager.WIFI_STATE_UNKNOWN; -import static android.telephony.TelephonyManager.CALL_STATE_IDLE; -import static android.telephony.TelephonyManager.CALL_STATE_OFFHOOK; import android.app.ActivityManager; import android.app.PendingIntent; @@ -81,7 +79,6 @@ import android.os.UserManager; import android.os.WorkSource; import android.provider.Settings; import android.system.OsConstants; -import android.telephony.PhoneStateListener; import android.telephony.TelephonyManager; import android.text.TextUtils; import android.util.Log; @@ -199,6 +196,7 @@ public class WifiStateMachine extends StateMachine { private final WifiCountryCode mCountryCode; // Object holding most recent wifi score report and bad Linkspeed count private final WifiScoreReport mWifiScoreReport; + private final SarManager mSarManager; public WifiScoreReport getWifiScoreReport() { return mWifiScoreReport; } @@ -643,9 +641,6 @@ public class WifiStateMachine extends StateMachine { /* Indicates that diagnostics should time out a connection start event. */ private static final int CMD_DIAGS_CONNECT_TIMEOUT = BASE + 252; - /* Used to set the tx power limit for SAR during the start of a phone call. */ - private static final int CMD_SELECT_TX_POWER_SCENARIO = BASE + 253; - // Start subscription provisioning with a given provider private static final int CMD_START_SUBSCRIPTION_PROVISIONING = BASE + 254; @@ -709,7 +704,6 @@ public class WifiStateMachine extends StateMachine { private final int mThresholdMinimumRssi24; private final boolean mEnableChipWakeUpWhenAssociated; private final boolean mEnableRssiPollWhenAssociated; - private final boolean mEnableVoiceCallSarTxPowerLimit; int mRunningBeaconCount = 0; @@ -771,7 +765,6 @@ public class WifiStateMachine extends StateMachine { } return mTelephonyManager; } - private final WifiPhoneStateListener mPhoneStateListener; private final IBatteryStats mBatteryStats; @@ -789,7 +782,8 @@ public class WifiStateMachine extends StateMachine { UserManager userManager, WifiInjector wifiInjector, BackupManagerProxy backupManagerProxy, WifiCountryCode countryCode, WifiNative wifiNative, - WrongPasswordNotifier wrongPasswordNotifier) { + WrongPasswordNotifier wrongPasswordNotifier, + SarManager sarManager) { super("WifiStateMachine", looper); mWifiInjector = wifiInjector; mWifiMetrics = mWifiInjector.getWifiMetrics(); @@ -801,6 +795,7 @@ public class WifiStateMachine extends StateMachine { mWifiNative = wifiNative; mBackupManagerProxy = backupManagerProxy; mWrongPasswordNotifier = wrongPasswordNotifier; + mSarManager = sarManager; // TODO refactor WifiNative use of context out into it's own class mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0, NETWORKTYPE, ""); @@ -827,7 +822,6 @@ public class WifiStateMachine extends StateMachine { mFacade.makeSupplicantStateTracker(context, mWifiConfigManager, getHandler()); mLinkProperties = new LinkProperties(); - mPhoneStateListener = new WifiPhoneStateListener(looper); mMcastLockManagerFilterController = new McastLockManagerFilterController(); mNetworkInfo.setIsAvailable(false); @@ -922,8 +916,6 @@ public class WifiStateMachine extends StateMachine { R.integer.config_wifi_framework_wifi_score_bad_rssi_threshold_5GHz); mThresholdMinimumRssi24 = context.getResources().getInteger( R.integer.config_wifi_framework_wifi_score_bad_rssi_threshold_24GHz); - mEnableVoiceCallSarTxPowerLimit = mContext.getResources().getBoolean( - R.bool.config_wifi_framework_enable_voice_call_sar_tx_power_limit); mEnableChipWakeUpWhenAssociated = true; mEnableRssiPollWhenAssociated = true; @@ -3216,40 +3208,6 @@ public class WifiStateMachine extends StateMachine { } } - /** - * Register the phone listener if we need to set/reset the power limits during voice call for - * this device. - */ - private void maybeRegisterPhoneListener() { - if (mEnableVoiceCallSarTxPowerLimit) { - logd("Registering for telephony call state changes"); - getTelephonyManager().listen( - mPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE); - } - } - - /** - * Listen for phone call state events to set/reset TX power limits for SAR requirements. - */ - private class WifiPhoneStateListener extends PhoneStateListener { - WifiPhoneStateListener(Looper looper) { - super(looper); - } - - @Override - public void onCallStateChanged(int state, String incomingNumber) { - if (mEnableVoiceCallSarTxPowerLimit) { - if (state == CALL_STATE_OFFHOOK) { - sendMessage(CMD_SELECT_TX_POWER_SCENARIO, - WifiNative.TX_POWER_SCENARIO_VOICE_CALL); - } else if (state == CALL_STATE_IDLE) { - sendMessage(CMD_SELECT_TX_POWER_SCENARIO, - WifiNative.TX_POWER_SCENARIO_NORMAL); - } - } - } - } - /** * Dynamically change the MAC address to use the locally randomized * MAC address generated for each network. @@ -3416,7 +3374,6 @@ public class WifiStateMachine extends StateMachine { Log.e(TAG, "Failed to load from config store"); } maybeRegisterNetworkFactory(); - maybeRegisterPhoneListener(); break; case CMD_SCREEN_STATE_CHANGED: handleScreenStateChanged(message.arg1 != 0); @@ -3448,7 +3405,6 @@ public class WifiStateMachine extends StateMachine { case CMD_ROAM_WATCHDOG_TIMER: case CMD_DISABLE_P2P_WATCHDOG_TIMER: case CMD_DISABLE_EPHEMERAL_NETWORK: - case CMD_SELECT_TX_POWER_SCENARIO: messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; break; case CMD_SET_OPERATIONAL_MODE: @@ -3762,14 +3718,6 @@ public class WifiStateMachine extends StateMachine { * driver are changed to reduce interference with bluetooth */ mWifiNative.setBluetoothCoexistenceScanMode(mInterfaceName, mBluetoothConnectionActive); - // Check if there is a voice call on-going and set/reset the tx power limit appropriately. - if (mEnableVoiceCallSarTxPowerLimit) { - if (getTelephonyManager().isOffhook()) { - sendMessage(CMD_SELECT_TX_POWER_SCENARIO, WifiNative.TX_POWER_SCENARIO_VOICE_CALL); - } else { - sendMessage(CMD_SELECT_TX_POWER_SCENARIO, WifiNative.TX_POWER_SCENARIO_NORMAL); - } - } // initialize network state setNetworkDetailedState(DetailedState.DISCONNECTED); @@ -3903,6 +3851,8 @@ public class WifiStateMachine extends StateMachine { mWifiMetrics.setWifiState(WifiMetricsProto.WifiLog.WIFI_DISCONNECTED); // Inform p2p service that wifi is up and ready when applicable p2pSendMessage(WifiStateMachine.CMD_ENABLE_P2P); + // Inform sar manager that wifi is Enabled + mSarManager.setClientWifiState(WifiManager.WIFI_STATE_ENABLED); } @Override @@ -3916,6 +3866,8 @@ public class WifiStateMachine extends StateMachine { mWifiConnectivityManager.setWifiEnabled(false); // Inform metrics that Wifi is being disabled (Toggled, airplane enabled, etc) mWifiMetrics.setWifiState(WifiMetricsProto.WifiLog.WIFI_DISABLED); + // Inform sar manager that wifi is being disabled + mSarManager.setClientWifiState(WifiManager.WIFI_STATE_DISABLED); if (!mWifiNative.removeAllNetworks(mInterfaceName)) { loge("Failed to remove networks on exiting connect mode"); @@ -4530,14 +4482,6 @@ public class WifiStateMachine extends StateMachine { case CMD_ENABLE_WIFI_CONNECTIVITY_MANAGER: mWifiConnectivityManager.enable(message.arg1 == 1 ? true : false); break; - case CMD_SELECT_TX_POWER_SCENARIO: - int txPowerScenario = message.arg1; - logd("Setting Tx power scenario to " + txPowerScenario); - if (!mWifiNative.selectTxPowerScenario(txPowerScenario)) { - loge("Failed to set TX power scenario"); - } - break; - default: return NOT_HANDLED; } diff --git a/tests/wifitests/src/com/android/server/wifi/SarManagerTest.java b/tests/wifitests/src/com/android/server/wifi/SarManagerTest.java new file mode 100644 index 000000000..163280a39 --- /dev/null +++ b/tests/wifitests/src/com/android/server/wifi/SarManagerTest.java @@ -0,0 +1,256 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.wifi; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.mockito.Mockito.*; + +import static android.telephony.TelephonyManager.CALL_STATE_IDLE; +import static android.telephony.TelephonyManager.CALL_STATE_OFFHOOK; + +import android.app.test.MockAnswerUtil.AnswerWithArguments; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.IntentFilter; +import android.content.pm.ApplicationInfo; +import android.hardware.SensorEvent; +import android.net.wifi.WifiManager; +import android.os.Build; +import android.os.test.TestLooper; +import android.support.test.filters.SmallTest; +import android.telephony.PhoneStateListener; +import android.telephony.TelephonyManager; +import android.util.Log; + +import com.android.internal.R; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.mockito.ArgumentCaptor; +import org.mockito.InOrder; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +/** + * unit tests for {@link com.android.server.wifi.SarManager}. + */ +@SmallTest +public class SarManagerTest { + private static final String TAG = "WifiSarManagerTest"; + private static final String OP_PACKAGE_NAME = "com.xxx"; + + private void enableDebugLogs() { + mSarMgr.enableVerboseLogging(1); + } + + private MockResources getMockResources() { + MockResources resources = new MockResources(); + return resources; + } + + private SarManager mSarMgr; + private TestLooper mLooper; + private MockResources mResources; + private PhoneStateListener mPhoneStateListener; + + @Mock private Context mContext; + @Mock TelephonyManager mTelephonyManager; + @Mock private ApplicationInfo mMockApplInfo; + @Mock WifiNative mWifiNative; + + @Before + public void setUp() throws Exception { + Log.e(TAG, "Setting Up ..."); + + // Ensure Looper exists + mLooper = new TestLooper(); + + MockitoAnnotations.initMocks(this); + + /* Default behavior is to return with success */ + when(mWifiNative.selectTxPowerScenario(anyInt())).thenReturn(true); + + mResources = getMockResources(); + + when(mContext.getResources()).thenReturn(mResources); + mMockApplInfo.targetSdkVersion = Build.VERSION_CODES.P; + when(mContext.getApplicationInfo()).thenReturn(mMockApplInfo); + when(mContext.getOpPackageName()).thenReturn(OP_PACKAGE_NAME); + } + + @After + public void cleanUp() throws Exception { + mSarMgr = null; + mLooper = null; + mContext = null; + mResources = null; + } + + /** + * Helper function to set configuration for SAR and create the SAR Manager + * + */ + private void createSarManager(boolean isSarEnabled) { + mResources.setBoolean( + R.bool.config_wifi_framework_enable_voice_call_sar_tx_power_limit, isSarEnabled); + + mSarMgr = new SarManager(mContext, mTelephonyManager, mLooper.getLooper(), + mWifiNative); + + if (isSarEnabled) { + /* Capture the PhoneStateListener */ + ArgumentCaptor<PhoneStateListener> phoneStateListenerCaptor = + ArgumentCaptor.forClass(PhoneStateListener.class); + verify(mTelephonyManager).listen(phoneStateListenerCaptor.capture(), + eq(PhoneStateListener.LISTEN_CALL_STATE)); + mPhoneStateListener = phoneStateListenerCaptor.getValue(); + } + + /* Enable logs from SarManager */ + enableDebugLogs(); + } + + /** + * Test that we do register the telephony call state listener on devices which do support + * setting/resetting Tx power limit. + */ + @Test + public void testSarMgr_enabledTxPowerScenario_registerPhone() throws Exception { + createSarManager(true); + verify(mTelephonyManager).listen(any(), eq(PhoneStateListener.LISTEN_CALL_STATE)); + } + + /** + * Test that we do not register the telephony call state listener on devices which + * do not support setting/resetting Tx power limit. + */ + @Test + public void testSarMgr_disabledTxPowerScenario_registerPhone() throws Exception { + createSarManager(false); + verify(mTelephonyManager, never()).listen(any(), anyInt()); + } + + /** + * Test that for devices that support setting/resetting Tx Power limits, device sets the proper + * Tx power scenario upon receiving {@link TelephonyManager#CALL_STATE_OFFHOOK} when WiFi STA + * is enabled + * In this case Wifi is enabled first, then off-hook is detected + * Expectation is to get {@link WifiNative#TX_POWER_SCENARIO_NORMAL} when WiFi is turned on + * followed by {@link WifiNative#TX_POWER_SCENARIO_VOICE_CALL} when OFFHOOK event is detected + */ + @Test + public void testSarMgr_enabledTxPowerScenario_wifiOn_offHook() throws Exception { + createSarManager(true); + assertNotNull(mPhoneStateListener); + + InOrder inOrder = inOrder(mWifiNative); + + /* Enable WiFi State */ + mSarMgr.setClientWifiState(WifiManager.WIFI_STATE_ENABLED); + + inOrder.verify(mWifiNative).selectTxPowerScenario( + eq(WifiNative.TX_POWER_SCENARIO_NORMAL)); + + /* Set phone state to OFFHOOK */ + mPhoneStateListener.onCallStateChanged(CALL_STATE_OFFHOOK, ""); + + inOrder.verify(mWifiNative).selectTxPowerScenario( + eq(WifiNative.TX_POWER_SCENARIO_VOICE_CALL)); + } + + /** + * Test that for devices that support setting/resetting Tx Power limits, device sets the proper + * Tx power scenario upon receiving {@link TelephonyManager#CALL_STATE_OFFHOOK} when WiFi STA + * is enabled + * In this case off-hook event is detected first, then wifi is turned on + * Expectation is to get {@link WifiNative#TX_POWER_SCENARIO_VOICE_CALL} once wifi is turned on + */ + @Test + public void testSarMgr_enabledTxPowerScenario_offHook_wifiOn() throws Exception { + createSarManager(true); + assertNotNull(mPhoneStateListener); + + /* Set phone state to OFFHOOK */ + mPhoneStateListener.onCallStateChanged(CALL_STATE_OFFHOOK, ""); + + /* Enable WiFi State */ + mSarMgr.setClientWifiState(WifiManager.WIFI_STATE_ENABLED); + + verify(mWifiNative).selectTxPowerScenario( + eq(WifiNative.TX_POWER_SCENARIO_VOICE_CALL)); + } + + /** + * Test that for devices that support setting/resetting Tx Power limits, device sets the proper + * Tx power scenarios upon receiving {@link TelephonyManager#CALL_STATE_OFFHOOK} and + * {@link TelephonyManager#CALL_STATE_OFFHOOK} when WiFi STA is enabled + */ + @Test + public void testSarMgr_enabledTxPowerScenario_wifiOn_offHook_onHook() throws Exception { + createSarManager(true); + assertNotNull(mPhoneStateListener); + + InOrder inOrder = inOrder(mWifiNative); + + /* Enable WiFi State */ + mSarMgr.setClientWifiState(WifiManager.WIFI_STATE_ENABLED); + + /* Now device should set tx power scenario to NORMAL */ + inOrder.verify(mWifiNative).selectTxPowerScenario( + eq(WifiNative.TX_POWER_SCENARIO_NORMAL)); + + /* Set phone state to OFFHOOK */ + mPhoneStateListener.onCallStateChanged(CALL_STATE_OFFHOOK, ""); + + /* Device should set tx power scenario to Voice call */ + inOrder.verify(mWifiNative).selectTxPowerScenario( + eq(WifiNative.TX_POWER_SCENARIO_VOICE_CALL)); + + /* Set state back to ONHOOK */ + mPhoneStateListener.onCallStateChanged(CALL_STATE_IDLE, ""); + + /* Device should set tx power scenario to NORMAL again */ + inOrder.verify(mWifiNative).selectTxPowerScenario( + eq(WifiNative.TX_POWER_SCENARIO_NORMAL)); + } + + /** + * Test that for devices that support setting/resetting Tx Power limits, device does not + * sets the Tx power scenarios upon receiving {@link TelephonyManager#CALL_STATE_OFFHOOK} and + * {@link TelephonyManager#CALL_STATE_OFFHOOK} when WiFi STA is disabled + */ + @Test + public void testSarMgr_enabledTxPowerScenario_wifiOff_offHook_onHook() throws Exception { + createSarManager(true); + assertNotNull(mPhoneStateListener); + + InOrder inOrder = inOrder(mWifiNative); + + /* Set phone state to OFFHOOK */ + mPhoneStateListener.onCallStateChanged(CALL_STATE_OFFHOOK, ""); + + /* Set state back to ONHOOK */ + mPhoneStateListener.onCallStateChanged(CALL_STATE_IDLE, ""); + + /* Device should not set tx power scenario at all */ + inOrder.verify(mWifiNative, never()).selectTxPowerScenario(anyInt()); + } +} diff --git a/tests/wifitests/src/com/android/server/wifi/WifiStateMachineTest.java b/tests/wifitests/src/com/android/server/wifi/WifiStateMachineTest.java index 1907c56b7..60ada8140 100644 --- a/tests/wifitests/src/com/android/server/wifi/WifiStateMachineTest.java +++ b/tests/wifitests/src/com/android/server/wifi/WifiStateMachineTest.java @@ -245,8 +245,6 @@ public class WifiStateMachineTest { private MockResources getMockResources() { MockResources resources = new MockResources(); resources.setBoolean(R.bool.config_wifi_enable_wifi_firmware_debugging, false); - resources.setBoolean( - R.bool.config_wifi_framework_enable_voice_call_sar_tx_power_limit, false); return resources; } @@ -347,6 +345,7 @@ public class WifiStateMachineTest { @Mock PropertyService mPropertyService; @Mock BuildProperties mBuildProperties; @Mock IBinder mPackageManagerBinder; + @Mock SarManager mSarManager; @Mock WifiConfigManager mWifiConfigManager; @Mock WifiNative mWifiNative; @Mock WifiConnectivityManager mWifiConnectivityManager; @@ -491,7 +490,7 @@ public class WifiStateMachineTest { private void initializeWsm() throws Exception { mWsm = new WifiStateMachine(mContext, mFrameworkFacade, mLooper.getLooper(), mUserManager, mWifiInjector, mBackupManagerProxy, mCountryCode, mWifiNative, - mWrongPasswordNotifier); + mWrongPasswordNotifier, mSarManager); mWsmThread = getWsmHandlerThread(mWsm); registerAsyncChannel((x) -> { @@ -1804,6 +1803,7 @@ public class WifiStateMachineTest { @Test public void testWifiInfoCleanedUpEnteringExitingConnectModeState() throws Exception { InOrder inOrder = inOrder(mWifiConnectivityManager); + InOrder inOrderSarMgr = inOrder(mSarManager); Log.i(TAG, mWsm.getCurrentState().getName()); String initialBSSID = "aa:bb:cc:dd:ee:ff"; WifiInfo wifiInfo = mWsm.getWifiInfo(); @@ -1814,6 +1814,7 @@ public class WifiStateMachineTest { assertEquals(WifiStateMachine.CONNECT_MODE, mWsm.getOperationalModeForTest()); assertEquals(WifiManager.WIFI_STATE_ENABLED, mWsm.syncGetWifiState()); inOrder.verify(mWifiConnectivityManager).setWifiEnabled(eq(true)); + inOrderSarMgr.verify(mSarManager).setClientWifiState(WifiManager.WIFI_STATE_ENABLED); assertNull(wifiInfo.getBSSID()); // Send a SUPPLICANT_STATE_CHANGE_EVENT, verify WifiInfo is updated @@ -1833,6 +1834,7 @@ public class WifiStateMachineTest { assertEquals("DefaultState", getCurrentState().getName()); assertEquals(WifiManager.WIFI_STATE_DISABLED, mWsm.syncGetWifiState()); inOrder.verify(mWifiConnectivityManager).setWifiEnabled(eq(false)); + inOrderSarMgr.verify(mSarManager).setClientWifiState(WifiManager.WIFI_STATE_DISABLED); assertNull(wifiInfo.getBSSID()); assertEquals(SupplicantState.DISCONNECTED, wifiInfo.getSupplicantState()); @@ -1853,6 +1855,7 @@ public class WifiStateMachineTest { assertEquals(WifiStateMachine.CONNECT_MODE, mWsm.getOperationalModeForTest()); assertEquals(WifiManager.WIFI_STATE_ENABLED, mWsm.syncGetWifiState()); inOrder.verify(mWifiConnectivityManager).setWifiEnabled(eq(true)); + inOrderSarMgr.verify(mSarManager).setClientWifiState(WifiManager.WIFI_STATE_ENABLED); assertEquals("DisconnectedState", getCurrentState().getName()); assertEquals(SupplicantState.DISCONNECTED, wifiInfo.getSupplicantState()); assertNull(wifiInfo.getBSSID()); @@ -1947,158 +1950,6 @@ public class WifiStateMachineTest { } /** - * Test that we do register the telephony call state listener on devices which do support - * setting/resetting Tx power limit. - */ - @Test - public void testVoiceCallSar_enabledTxPowerScenario_WifiOn() throws Exception { - mResources.setBoolean( - R.bool.config_wifi_framework_enable_voice_call_sar_tx_power_limit, true); - initializeWsm(); - - loadComponentsInStaMode(); - assertEquals(WifiStateMachine.CONNECT_MODE, mWsm.getOperationalModeForTest()); - assertEquals("DisconnectedState", getCurrentState().getName()); - assertNotNull(mPhoneStateListener); - } - - /** - * Test that we do register the telephony call state listener on devices which do support - * setting/resetting Tx power limit and set the tx power level if we're in state - * {@link TelephonyManager#CALL_STATE_OFFHOOK}. - */ - @Test - public void testVoiceCallSar_enabledTxPowerScenarioCallStateOffHook_WhenWifiTurnedOn() - throws Exception { - mResources.setBoolean( - R.bool.config_wifi_framework_enable_voice_call_sar_tx_power_limit, true); - initializeWsm(); - - when(mWifiNative.selectTxPowerScenario(anyInt())).thenReturn(true); - when(mTelephonyManager.isOffhook()).thenReturn(true); - - loadComponentsInStaMode(); - assertEquals(WifiStateMachine.CONNECT_MODE, mWsm.getOperationalModeForTest()); - assertEquals("DisconnectedState", getCurrentState().getName()); - assertNotNull(mPhoneStateListener); - verify(mWifiNative).selectTxPowerScenario(eq(WifiNative.TX_POWER_SCENARIO_VOICE_CALL)); - } - - /** - * Test that we do register the telephony call state listener on devices which do support - * setting/resetting Tx power limit and set the tx power level if we're in state - * {@link TelephonyManager#CALL_STATE_IDLE}. - */ - @Test - public void testVoiceCallSar_enabledTxPowerScenarioCallStateIdle_WhenWifiTurnedOn() - throws Exception { - mResources.setBoolean( - R.bool.config_wifi_framework_enable_voice_call_sar_tx_power_limit, true); - initializeWsm(); - - when(mWifiNative.selectTxPowerScenario(anyInt())).thenReturn(true); - when(mTelephonyManager.isIdle()).thenReturn(true); - - loadComponentsInStaMode(); - assertEquals(WifiStateMachine.CONNECT_MODE, mWsm.getOperationalModeForTest()); - assertEquals("DisconnectedState", getCurrentState().getName()); - assertNotNull(mPhoneStateListener); - } - - /** - * Test that we do register the telephony call state listener on devices which do support - * setting/resetting Tx power limit and set the tx power level if we're in state - * {@link TelephonyManager#CALL_STATE_OFFHOOK}. This test checks if the - * {@link WifiNative#selectTxPowerScenario(int)} failure is handled correctly. - */ - @Test - public void testVoiceCallSar_enabledTxPowerScenarioCallStateOffHook_WhenWifiTurnedOn_Fails() - throws Exception { - mResources.setBoolean( - R.bool.config_wifi_framework_enable_voice_call_sar_tx_power_limit, true); - initializeWsm(); - - when(mWifiNative.selectTxPowerScenario(anyInt())).thenReturn(false); - when(mTelephonyManager.isOffhook()).thenReturn(true); - - loadComponentsInStaMode(); - assertEquals(WifiStateMachine.CONNECT_MODE, mWsm.getOperationalModeForTest()); - assertEquals("DisconnectedState", getCurrentState().getName()); - assertNotNull(mPhoneStateListener); - verify(mWifiNative).selectTxPowerScenario(eq(WifiNative.TX_POWER_SCENARIO_VOICE_CALL)); - } - - /** - * Test that we invoke the corresponding WifiNative method when - * {@link PhoneStateListener#onCallStateChanged(int, String)} is invoked with state - * {@link TelephonyManager#CALL_STATE_OFFHOOK}. - */ - @Test - public void testVoiceCallSar_enabledTxPowerScenarioCallStateOffHook_WhenWifiOn() - throws Exception { - when(mWifiNative.selectTxPowerScenario(anyInt())).thenReturn(true); - testVoiceCallSar_enabledTxPowerScenario_WifiOn(); - - mPhoneStateListener.onCallStateChanged(TelephonyManager.CALL_STATE_OFFHOOK, ""); - mLooper.dispatchAll(); - verify(mWifiNative).selectTxPowerScenario(eq(WifiNative.TX_POWER_SCENARIO_VOICE_CALL)); - } - - /** - * Test that we invoke the corresponding WifiNative method when - * {@link PhoneStateListener#onCallStateChanged(int, String)} is invoked with state - * {@link TelephonyManager#CALL_STATE_IDLE}. - */ - @Test - public void testVoiceCallSar_enabledTxPowerScenarioCallStateIdle_WhenWifiOn() throws Exception { - when(mWifiNative.selectTxPowerScenario(anyInt())).thenReturn(true); - testVoiceCallSar_enabledTxPowerScenario_WifiOn(); - - mPhoneStateListener.onCallStateChanged(TelephonyManager.CALL_STATE_IDLE, ""); - mLooper.dispatchAll(); - verify(mWifiNative, atLeastOnce()) - .selectTxPowerScenario(eq(WifiNative.TX_POWER_SCENARIO_NORMAL)); - } - - /** - * Test that we invoke the corresponding WifiNative method when - * {@link PhoneStateListener#onCallStateChanged(int, String)} is invoked with state - * {@link TelephonyManager#CALL_STATE_OFFHOOK}. This test checks if the - * {@link WifiNative#selectTxPowerScenario(int)} failure is handled correctly. - */ - @Test - public void testVoiceCallSar_enabledTxPowerScenarioCallStateOffHook_WhenWifiOn_Fails() - throws Exception { - when(mWifiNative.selectTxPowerScenario(anyInt())).thenReturn(false); - testVoiceCallSar_enabledTxPowerScenario_WifiOn(); - - mPhoneStateListener.onCallStateChanged(TelephonyManager.CALL_STATE_OFFHOOK, ""); - mLooper.dispatchAll(); - verify(mWifiNative).selectTxPowerScenario(eq(WifiNative.TX_POWER_SCENARIO_VOICE_CALL)); - } - - /** - * Test that we don't invoke the corresponding WifiNative method when - * {@link PhoneStateListener#onCallStateChanged(int, String)} is invoked with state - * {@link TelephonyManager#CALL_STATE_IDLE} or {@link TelephonyManager#CALL_STATE_OFFHOOK} when - * wifi is off (state machine is not in SupplicantStarted state). - */ - @Test - public void testVoiceCallSar_enabledTxPowerScenarioCallState_WhenWifiOff() throws Exception { - mResources.setBoolean( - R.bool.config_wifi_framework_enable_voice_call_sar_tx_power_limit, true); - initializeWsm(); - - mPhoneStateListener.onCallStateChanged(TelephonyManager.CALL_STATE_OFFHOOK, ""); - mLooper.dispatchAll(); - verify(mWifiNative, never()).selectTxPowerScenario(anyInt()); - - mPhoneStateListener.onCallStateChanged(TelephonyManager.CALL_STATE_IDLE, ""); - mLooper.dispatchAll(); - verify(mWifiNative, never()).selectTxPowerScenario(anyInt()); - } - - /** * Verifies that a network disconnection event will result in WifiStateMachine invoking * {@link WifiConfigManager#removeAllEphemeralOrPasspointConfiguredNetworks()} to remove * any ephemeral or passpoint networks from it's internal database. |