summaryrefslogtreecommitdiff
path: root/service
diff options
context:
space:
mode:
authorTreeHugger Robot <treehugger-gerrit@google.com>2019-09-13 03:39:58 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2019-09-13 03:39:58 +0000
commit278c04302d18270c3cf8b1fde333aad8224c31b1 (patch)
tree72c71bae155bd636521fc3051132dc6978d48334 /service
parent58457bff724192c55f8348571cd4f2ddc3ff53db (diff)
parentc8c5a55226be76be5d355db5c32c52df0736a249 (diff)
Merge "Revert WifiController/ActiveModeWarden refactor due to boot time regression"
Diffstat (limited to 'service')
-rw-r--r--service/java/com/android/server/wifi/ActiveModeWarden.java935
-rw-r--r--service/java/com/android/server/wifi/ClientModeImpl.java2
-rw-r--r--service/java/com/android/server/wifi/ClientModeManager.java2
-rw-r--r--service/java/com/android/server/wifi/DppManager.java2
-rw-r--r--service/java/com/android/server/wifi/OpenNetworkNotifier.java2
-rw-r--r--service/java/com/android/server/wifi/ScanRequestProxy.java2
-rw-r--r--service/java/com/android/server/wifi/SelfRecovery.java33
-rw-r--r--service/java/com/android/server/wifi/WakeupController.java6
-rw-r--r--service/java/com/android/server/wifi/WifiApConfigStore.java2
-rw-r--r--service/java/com/android/server/wifi/WifiConfigManager.java2
-rw-r--r--service/java/com/android/server/wifi/WifiConnectivityHelper.java2
-rw-r--r--service/java/com/android/server/wifi/WifiController.java482
-rw-r--r--service/java/com/android/server/wifi/WifiInjector.java28
-rw-r--r--service/java/com/android/server/wifi/WifiLastResortWatchdog.java9
-rw-r--r--service/java/com/android/server/wifi/WifiServiceImpl.java286
-rw-r--r--service/java/com/android/server/wifi/WifiThreadRunner.java105
-rw-r--r--service/java/com/android/server/wifi/hotspot2/PasspointManager.java2
17 files changed, 1035 insertions, 867 deletions
diff --git a/service/java/com/android/server/wifi/ActiveModeWarden.java b/service/java/com/android/server/wifi/ActiveModeWarden.java
index 4f1a00371..9a8abdf0c 100644
--- a/service/java/com/android/server/wifi/ActiveModeWarden.java
+++ b/service/java/com/android/server/wifi/ActiveModeWarden.java
@@ -17,11 +17,7 @@
package com.android.server.wifi;
import android.annotation.NonNull;
-import android.content.BroadcastReceiver;
import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.location.LocationManager;
import android.net.wifi.WifiManager;
import android.os.BatteryStats;
import android.os.Handler;
@@ -31,19 +27,16 @@ import android.os.RemoteException;
import android.util.ArraySet;
import android.util.Log;
-import com.android.internal.R;
-import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.IBatteryStats;
import com.android.internal.util.IState;
import com.android.internal.util.Preconditions;
import com.android.internal.util.Protocol;
import com.android.internal.util.State;
import com.android.internal.util.StateMachine;
-import com.android.server.wifi.util.WifiPermissionsUtil;
+import com.android.server.wifi.WifiNative.StatusListener;
import java.io.FileDescriptor;
import java.io.PrintWriter;
-import java.util.Collection;
/**
* This class provides the implementation for different WiFi operating modes.
@@ -52,25 +45,64 @@ public class ActiveModeWarden {
private static final String TAG = "WifiActiveModeWarden";
private static final String STATE_MACHINE_EXITED_STATE_NAME = "STATE_MACHINE_EXITED";
+ private ModeStateMachine mModeStateMachine;
+
// Holder for active mode managers
private final ArraySet<ActiveModeManager> mActiveModeManagers;
// DefaultModeManager used to service API calls when there are not active mode managers.
- private final DefaultModeManager mDefaultModeManager;
+ private DefaultModeManager mDefaultModeManager;
private final WifiInjector mWifiInjector;
+ private final Context mContext;
private final Looper mLooper;
private final Handler mHandler;
- private final Context mContext;
- private final ClientModeImpl mClientModeImpl;
- private final WifiSettingsStore mSettingsStore;
- private final FrameworkFacade mFacade;
- private final WifiPermissionsUtil mWifiPermissionsUtil;
+ private final WifiNative mWifiNative;
private final IBatteryStats mBatteryStats;
+ private final SelfRecovery mSelfRecovery;
+ private BaseWifiDiagnostics mWifiDiagnostics;
private final ScanRequestProxy mScanRequestProxy;
- private final WifiController mWifiController;
+
+ // The base for wifi message types
+ static final int BASE = Protocol.BASE_WIFI;
+
+ // The message identifiers below are mapped to those in ClientModeImpl when applicable.
+ // Start the soft access point
+ static final int CMD_START_AP = BASE + 21;
+ // Indicates soft ap start failed
+ static final int CMD_START_AP_FAILURE = BASE + 22;
+ // Stop the soft access point
+ static final int CMD_STOP_AP = BASE + 23;
+ // Soft access point teardown is completed
+ static final int CMD_AP_STOPPED = BASE + 24;
+
+ // Start Scan Only mode
+ static final int CMD_START_SCAN_ONLY_MODE = BASE + 200;
+ // Indicates that start Scan only mode failed
+ static final int CMD_START_SCAN_ONLY_MODE_FAILURE = BASE + 201;
+ // Indicates that scan only mode stopped
+ static final int CMD_STOP_SCAN_ONLY_MODE = BASE + 202;
+ // ScanOnly mode teardown is complete
+ static final int CMD_SCAN_ONLY_MODE_STOPPED = BASE + 203;
+ // ScanOnly mode failed
+ static final int CMD_SCAN_ONLY_MODE_FAILED = BASE + 204;
+
+ // Start Client mode
+ static final int CMD_START_CLIENT_MODE = BASE + 300;
+ // Indicates that start client mode failed
+ static final int CMD_START_CLIENT_MODE_FAILURE = BASE + 301;
+ // Indicates that client mode stopped
+ static final int CMD_STOP_CLIENT_MODE = BASE + 302;
+ // Client mode teardown is complete
+ static final int CMD_CLIENT_MODE_STOPPED = BASE + 303;
+ // Client mode failed
+ static final int CMD_CLIENT_MODE_FAILED = BASE + 304;
+
+ private StatusListener mWifiNativeStatusListener;
private WifiManager.SoftApCallback mSoftApCallback;
private WifiManager.SoftApCallback mLohsCallback;
+ private ScanOnlyModeManager.Listener mScanOnlyCallback;
+ private ClientModeManager.Listener mClientModeCallback;
/**
* Called from WifiServiceImpl to register a callback for notifications from SoftApManager
@@ -87,107 +119,59 @@ public class ActiveModeWarden {
mLohsCallback = callback;
}
+ /**
+ * Called from WifiController to register a callback for notifications from ScanOnlyModeManager
+ */
+ public void registerScanOnlyCallback(@NonNull ScanOnlyModeManager.Listener callback) {
+ mScanOnlyCallback = callback;
+ }
+
+ /**
+ * Called from WifiController to register a callback for notifications from ClientModeManager
+ */
+ public void registerClientModeCallback(@NonNull ClientModeManager.Listener callback) {
+ mClientModeCallback = callback;
+ }
+
ActiveModeWarden(WifiInjector wifiInjector,
+ Context context,
Looper looper,
WifiNative wifiNative,
DefaultModeManager defaultModeManager,
- IBatteryStats batteryStats,
- BaseWifiDiagnostics wifiDiagnostics,
- Context context,
- ClientModeImpl clientModeImpl,
- WifiSettingsStore settingsStore,
- FrameworkFacade facade,
- WifiPermissionsUtil wifiPermissionsUtil) {
+ IBatteryStats batteryStats) {
mWifiInjector = wifiInjector;
+ mContext = context;
mLooper = looper;
mHandler = new Handler(looper);
- mContext = context;
- mClientModeImpl = clientModeImpl;
- mSettingsStore = settingsStore;
- mFacade = facade;
- mWifiPermissionsUtil = wifiPermissionsUtil;
+ mWifiNative = wifiNative;
mActiveModeManagers = new ArraySet<>();
mDefaultModeManager = defaultModeManager;
mBatteryStats = batteryStats;
- mScanRequestProxy = wifiInjector.getScanRequestProxy();
- mWifiController = new WifiController();
-
- wifiNative.registerStatusListener(isReady -> {
- if (!isReady) {
- mHandler.post(() -> {
- Log.e(TAG, "One of the native daemons died. Triggering recovery");
- wifiDiagnostics.captureBugReportData(
- WifiDiagnostics.REPORT_REASON_WIFINATIVE_FAILURE);
-
- // immediately trigger SelfRecovery if we receive a notice about an
- // underlying daemon failure
- // Note: SelfRecovery has a circular dependency with ActiveModeWarden and is
- // instantiated after ActiveModeWarden, so use WifiInjector to get the instance
- // instead of directly passing in SelfRecovery in the constructor.
- mWifiInjector.getSelfRecovery().trigger(SelfRecovery.REASON_WIFINATIVE_FAILURE);
- });
- }
- });
- }
-
- /** Begin listening to broadcasts and start the internal state machine. */
- public void start() {
- mWifiController.start();
- }
-
- /** Disable Wifi for recovery purposes. */
- public void recoveryDisableWifi() {
- mWifiController.sendMessage(WifiController.CMD_RECOVERY_DISABLE_WIFI);
+ mSelfRecovery = mWifiInjector.getSelfRecovery();
+ mWifiDiagnostics = mWifiInjector.getWifiDiagnostics();
+ mScanRequestProxy = mWifiInjector.getScanRequestProxy();
+ mModeStateMachine = new ModeStateMachine();
+ mWifiNativeStatusListener = new WifiNativeStatusListener();
+ mWifiNative.registerStatusListener(mWifiNativeStatusListener);
}
/**
- * Restart Wifi for recovery purposes.
- * @param reason One of {@link SelfRecovery.RecoveryReason}
+ * Method to switch wifi into client mode where connections to configured networks will be
+ * attempted.
*/
- public void recoveryRestartWifi(@SelfRecovery.RecoveryReason int reason) {
- mWifiController.sendMessage(WifiController.CMD_RECOVERY_RESTART_WIFI, reason);
- }
-
- /** Wifi has been toggled. */
- public void wifiToggled() {
- mWifiController.sendMessage(WifiController.CMD_WIFI_TOGGLED);
- }
-
- /** Airplane Mode has been toggled. */
- public void airplaneModeToggled() {
- mWifiController.sendMessage(WifiController.CMD_AIRPLANE_TOGGLED);
+ public void enterClientMode() {
+ changeMode(ModeStateMachine.CMD_START_CLIENT_MODE);
}
- /** Starts SoftAp. */
- public void startSoftAp(SoftApModeConfiguration softApConfig) {
- mWifiController.sendMessage(WifiController.CMD_SET_AP, 1, 0, softApConfig);
- }
-
- /** Stop SoftAp. */
- public void stopSoftAp(int mode) {
- mWifiController.sendMessage(WifiController.CMD_SET_AP, 0, mode);
- }
-
- /** Emergency Callback Mode has changed. */
- public void emergencyCallbackModeChanged(boolean isInEmergencyCallbackMode) {
- mWifiController.sendMessage(
- WifiController.CMD_EMERGENCY_MODE_CHANGED, isInEmergencyCallbackMode ? 1 : 0);
- }
-
- /** Emergency Call state has changed. */
- public void emergencyCallStateChanged(boolean isInEmergencyCall) {
- mWifiController.sendMessage(
- WifiController.CMD_EMERGENCY_CALL_STATE_CHANGED, isInEmergencyCall ? 1 : 0);
- }
-
- /** Scan always mode has changed. */
- public void scanAlwaysModeChanged() {
- mWifiController.sendMessage(WifiController.CMD_SCAN_ALWAYS_MODE_CHANGED);
- }
-
- /** When SoftAp has stopped. */
- public void softApStopped() {
- mWifiController.sendMessage(ActiveModeWarden.WifiController.CMD_AP_STOPPED);
+ /**
+ * Method to switch wifi into scan only mode where network connection attempts will not be made.
+ *
+ * This mode is utilized by location scans. If wifi is disabled by a user, but they have
+ * previously configured their device to perform location scans, this mode allows wifi to
+ * fulfill the location scan requests but will not be used for connectivity.
+ */
+ public void enterScanOnlyMode() {
+ changeMode(ModeStateMachine.CMD_START_SCAN_ONLY_MODE);
}
/**
@@ -197,20 +181,9 @@ public class ActiveModeWarden {
* the persisted config is to be used) and the target operating mode (ex,
* {@link WifiManager#IFACE_IP_MODE_TETHERED} {@link WifiManager#IFACE_IP_MODE_LOCAL_ONLY}).
*
- * @param softApConfig SoftApModeConfiguration for the hostapd softap
*/
- private void enterSoftAPMode(@NonNull SoftApModeConfiguration softApConfig) {
- mHandler.post(() -> {
- Log.d(TAG, "Starting SoftApModeManager config = "
- + softApConfig.getWifiConfiguration());
-
- SoftApCallbackImpl callback = new SoftApCallbackImpl(softApConfig.getTargetMode());
- ActiveModeManager manager = mWifiInjector.makeSoftApManager(callback, softApConfig);
- callback.setActiveModeManager(manager);
- manager.start();
- mActiveModeManagers.add(manager);
- updateBatteryStatsWifiState(true);
- });
+ public void enterSoftAPMode(@NonNull SoftApModeConfiguration softApConfig) {
+ mHandler.post(() -> startSoftAp(softApConfig));
}
/**
@@ -223,7 +196,7 @@ public class ActiveModeWarden {
* {@link WifiManager#IFACE_IP_MODE_LOCAL_ONLY}).
* Use {@link WifiManager#IFACE_IP_MODE_UNSPECIFIED} to stop all APs.
*/
- private void stopSoftAPMode(int mode) {
+ public void stopSoftAPMode(int mode) {
mHandler.post(() -> {
for (ActiveModeManager manager : mActiveModeManagers) {
if (!(manager instanceof SoftApManager)) continue;
@@ -240,9 +213,18 @@ public class ActiveModeWarden {
}
/**
+ * Method to disable wifi in sta/client mode scenarios.
+ *
+ * This mode will stop any client/scan modes and will not perform any network scans.
+ */
+ public void disableWifi() {
+ changeMode(ModeStateMachine.CMD_DISABLE_WIFI);
+ }
+
+ /**
* Method to stop all active modes, for example, when toggling airplane mode.
*/
- private void shutdownWifi() {
+ public void shutdownWifi() {
mHandler.post(() -> {
for (ActiveModeManager manager : mActiveModeManagers) {
manager.stop();
@@ -254,33 +236,24 @@ public class ActiveModeWarden {
/**
* Dump current state for active mode managers.
*
- * Must be called from the main Wifi thread.
+ * Must be called from ClientModeImpl thread.
*/
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println("Dump of " + TAG);
+
pw.println("Current wifi mode: " + getCurrentMode());
pw.println("NumActiveModeManagers: " + mActiveModeManagers.size());
for (ActiveModeManager manager : mActiveModeManagers) {
manager.dump(fd, pw, args);
}
- mWifiController.dump(fd, pw, args);
- }
-
- @VisibleForTesting
- String getCurrentMode() {
- IState state = mWifiController.getCurrentState();
- return state == null ? STATE_MACHINE_EXITED_STATE_NAME : state.getName();
}
- @VisibleForTesting
- Collection<ActiveModeManager> getActiveModeManagers() {
- return new ArraySet<>(mActiveModeManagers);
+ protected String getCurrentMode() {
+ return mModeStateMachine.getCurrentMode();
}
- @VisibleForTesting
- boolean isInEmergencyMode() {
- IState state = mWifiController.getCurrentState();
- return ((WifiController.BaseState) state).isInEmergencyMode();
+ private void changeMode(int newMode) {
+ mModeStateMachine.sendMessage(newMode);
}
/**
@@ -298,327 +271,65 @@ public class ActiveModeWarden {
}
}
- private class SoftApCallbackImpl extends ModeCallback implements WifiManager.SoftApCallback {
- private final int mMode;
+ private class ModeStateMachine extends StateMachine {
+ // Commands for the state machine - these will be removed,
+ // along with the StateMachine itself
+ public static final int CMD_START_CLIENT_MODE = 0;
+ public static final int CMD_START_SCAN_ONLY_MODE = 1;
+ public static final int CMD_DISABLE_WIFI = 3;
- SoftApCallbackImpl(int mode) {
- Preconditions.checkArgument(mode == WifiManager.IFACE_IP_MODE_TETHERED
- || mode == WifiManager.IFACE_IP_MODE_LOCAL_ONLY);
- mMode = mode;
- }
+ private final State mWifiDisabledState = new WifiDisabledState();
+ private final State mClientModeActiveState = new ClientModeActiveState();
+ private final State mScanOnlyModeActiveState = new ScanOnlyModeActiveState();
- @Override
- public void onStateChanged(int state, int reason) {
- if (state == WifiManager.WIFI_AP_STATE_DISABLED) {
- mActiveModeManagers.remove(getActiveModeManager());
- updateBatteryStatsWifiState(false);
- } else if (state == WifiManager.WIFI_AP_STATE_FAILED) {
- mActiveModeManagers.remove(getActiveModeManager());
- updateBatteryStatsWifiState(false);
- }
- switch (mMode) {
- case WifiManager.IFACE_IP_MODE_TETHERED:
- if (mSoftApCallback != null) mSoftApCallback.onStateChanged(state, reason);
- break;
- case WifiManager.IFACE_IP_MODE_LOCAL_ONLY:
- if (mLohsCallback != null) mLohsCallback.onStateChanged(state, reason);
- break;
- }
- }
-
- @Override
- public void onNumClientsChanged(int numClients) {
- switch (mMode) {
- case WifiManager.IFACE_IP_MODE_TETHERED:
- if (mSoftApCallback != null) mSoftApCallback.onNumClientsChanged(numClients);
- break;
- case WifiManager.IFACE_IP_MODE_LOCAL_ONLY:
- if (mLohsCallback != null) mLohsCallback.onNumClientsChanged(numClients);
- break;
- }
- }
- }
-
- /**
- * Helper method to report wifi state as on/off (doesn't matter which mode).
- *
- * @param enabled boolean indicating that some mode has been turned on or off
- */
- private void updateBatteryStatsWifiState(boolean enabled) {
- try {
- if (enabled) {
- if (mActiveModeManagers.size() == 1) {
- // only report wifi on if we haven't already
- mBatteryStats.noteWifiOn();
- }
- } else {
- if (mActiveModeManagers.size() == 0) {
- // only report if we don't have any active modes
- mBatteryStats.noteWifiOff();
- }
- }
- } catch (RemoteException e) {
- Log.e(TAG, "Failed to note battery stats in wifi");
- }
- }
-
- private void updateBatteryStatsScanModeActive() {
- try {
- mBatteryStats.noteWifiState(BatteryStats.WIFI_STATE_OFF_SCANNING, null);
- } catch (RemoteException e) {
- Log.e(TAG, "Failed to note battery stats in wifi");
- }
- }
-
- /**
- * WifiController is the class used to manage wifi state for various operating
- * modes (normal, airplane, wifi hotspot, etc.).
- */
- private class WifiController extends StateMachine {
- private static final String TAG = "WifiController";
-
- // Maximum limit to use for timeout delay if the value from overlay setting is too large.
- private static final int MAX_RECOVERY_TIMEOUT_DELAY_MS = 4000;
-
- private final int mRecoveryDelayMillis;
-
- private static final int BASE = Protocol.BASE_WIFI_CONTROLLER;
-
- static final int CMD_EMERGENCY_MODE_CHANGED = BASE + 1;
- static final int CMD_SCAN_ALWAYS_MODE_CHANGED = BASE + 7;
- static final int CMD_WIFI_TOGGLED = BASE + 8;
- static final int CMD_AIRPLANE_TOGGLED = BASE + 9;
- static final int CMD_SET_AP = BASE + 10;
- static final int CMD_EMERGENCY_CALL_STATE_CHANGED = BASE + 14;
- static final int CMD_AP_STOPPED = BASE + 15;
- static final int CMD_STA_START_FAILURE = BASE + 16;
- // Command used to trigger a wifi stack restart when in active mode
- static final int CMD_RECOVERY_RESTART_WIFI = BASE + 17;
- // Internal command used to complete wifi stack restart
- private static final int CMD_RECOVERY_RESTART_WIFI_CONTINUE = BASE + 18;
- // Command to disable wifi when SelfRecovery is throttled or otherwise not doing full
- // recovery
- static final int CMD_RECOVERY_DISABLE_WIFI = BASE + 19;
- static final int CMD_STA_STOPPED = BASE + 20;
- static final int CMD_SCANNING_STOPPED = BASE + 21;
- static final int CMD_DEFERRED_RECOVERY_RESTART_WIFI = BASE + 22;
- static final int CMD_SCANNING_START_FAILURE = BASE + 23;
-
- private final StaEnabledState mStaEnabledState = new StaEnabledState();
- private final StaDisabledState mStaDisabledState = new StaDisabledState();
- private final StaDisabledWithScanState mStaDisabledWithScanState =
- new StaDisabledWithScanState();
-
- WifiController() {
+ ModeStateMachine() {
super(TAG, mLooper);
- DefaultState defaultState = new DefaultState();
- addState(defaultState); {
- addState(mStaDisabledState, defaultState);
- addState(mStaEnabledState, defaultState);
- addState(mStaDisabledWithScanState, defaultState);
- }
-
- setLogRecSize(100);
- setLogOnlyTransitions(false);
+ addState(mClientModeActiveState);
+ addState(mScanOnlyModeActiveState);
+ addState(mWifiDisabledState);
- mRecoveryDelayMillis = readWifiRecoveryDelay();
+ Log.d(TAG, "Starting Wifi in WifiDisabledState");
+ setInitialState(mWifiDisabledState);
+ start();
}
- @Override
- public void start() {
- boolean isAirplaneModeOn = mSettingsStore.isAirplaneModeOn();
- boolean isWifiEnabled = mSettingsStore.isWifiToggleEnabled();
- boolean isScanningAlwaysAvailable = mSettingsStore.isScanAlwaysAvailable();
- boolean isLocationModeActive = mWifiPermissionsUtil.isLocationModeEnabled();
-
- log("isAirplaneModeOn = " + isAirplaneModeOn
- + ", isWifiEnabled = " + isWifiEnabled
- + ", isScanningAvailable = " + isScanningAlwaysAvailable
- + ", isLocationModeActive = " + isLocationModeActive);
-
- if (checkScanOnlyModeAvailable()) {
- setInitialState(mStaDisabledWithScanState);
+ private String getCurrentMode() {
+ IState state = getCurrentState();
+ if (state == null) {
+ return STATE_MACHINE_EXITED_STATE_NAME;
} else {
- setInitialState(mStaDisabledState);
- }
- mContext.registerReceiver(new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- // Location mode has been toggled... trigger with the scan change
- // update to make sure we are in the correct mode
- scanAlwaysModeChanged();
- }
- }, new IntentFilter(LocationManager.MODE_CHANGED_ACTION));
- super.start();
- }
-
- private boolean checkScanOnlyModeAvailable() {
- return mWifiPermissionsUtil.isLocationModeEnabled()
- && mSettingsStore.isScanAlwaysAvailable();
- }
-
- private int readWifiRecoveryDelay() {
- int recoveryDelayMillis = mContext.getResources().getInteger(
- R.integer.config_wifi_framework_recovery_timeout_delay);
- if (recoveryDelayMillis > MAX_RECOVERY_TIMEOUT_DELAY_MS) {
- recoveryDelayMillis = MAX_RECOVERY_TIMEOUT_DELAY_MS;
- Log.w(TAG, "Overriding timeout delay with maximum limit value");
+ return state.getName();
}
- return recoveryDelayMillis;
}
- abstract class BaseState extends State {
- private boolean mIsInEmergencyCall;
- private boolean mIsInEmergencyCallbackMode;
-
- private boolean mWasWifiDisabled;
-
- @Override
- public void enter() {
- super.enter();
- // Not allowed to change state when ECM is enabled!
- // Thus reset to false when changing states just to be safe.
- mIsInEmergencyCall = false;
- mIsInEmergencyCallbackMode = false;
- mWasWifiDisabled = false;
- }
-
- @VisibleForTesting
- boolean isInEmergencyMode() {
- return mIsInEmergencyCall || mIsInEmergencyCallbackMode;
- }
-
- private void updateEmergencyMode(Message msg) {
- if (msg.what == CMD_EMERGENCY_CALL_STATE_CHANGED) {
- mIsInEmergencyCall = msg.arg1 == 1;
- } else if (msg.what == CMD_EMERGENCY_MODE_CHANGED) {
- mIsInEmergencyCallbackMode = msg.arg1 == 1;
- }
- }
-
- private void enterEmergencyMode() {
- stopSoftAPMode(WifiManager.IFACE_IP_MODE_UNSPECIFIED);
- boolean configWiFiDisableInECBM = mFacade.getConfigWiFiDisableInECBM(mContext);
- log("WifiController msg getConfigWiFiDisableInECBM " + configWiFiDisableInECBM);
- if (configWiFiDisableInECBM) {
- // TODO: this will shut down Soft AP twice in conjunction with stopSoftAPMode()
- // above, is this a problem?
- shutdownWifi();
- mWasWifiDisabled = true;
- }
- }
-
- private void exitEmergencyMode() {
- State stateToTransitionTo;
- if (mSettingsStore.isWifiToggleEnabled()) {
- stateToTransitionTo = mStaEnabledState;
- } else if (checkScanOnlyModeAvailable()) {
- stateToTransitionTo = mStaDisabledWithScanState;
- } else {
- stateToTransitionTo = mStaDisabledState;
- }
-
- if (stateToTransitionTo == this) {
- // stay in same state
- if (mWasWifiDisabled) {
- // if Wifi was shutdown, restart the current state
- this.enter();
- }
- } else {
- transitionTo(stateToTransitionTo);
- }
- }
-
- @Override
- public final boolean processMessage(Message msg) {
- // potentially enter emergency mode
- if (msg.what == CMD_EMERGENCY_CALL_STATE_CHANGED
- || msg.what == CMD_EMERGENCY_MODE_CHANGED) {
- boolean wasInEmergencyMode = isInEmergencyMode();
- updateEmergencyMode(msg);
- boolean isInEmergencyMode = isInEmergencyMode();
- if (!wasInEmergencyMode && isInEmergencyMode) {
- enterEmergencyMode();
- } else if (wasInEmergencyMode && !isInEmergencyMode) {
- exitEmergencyMode();
- }
- return HANDLED;
- }
- // already in emergency mode, drop all messages
- if (isInEmergencyMode()) {
- return HANDLED;
- }
- // not in emergency mode, process messages normally
- return processMessageFiltered(msg);
+ private boolean checkForAndHandleModeChange(Message message) {
+ switch(message.what) {
+ case ModeStateMachine.CMD_START_CLIENT_MODE:
+ Log.d(TAG, "Switching from " + getCurrentMode() + " to ClientMode");
+ mModeStateMachine.transitionTo(mClientModeActiveState);
+ break;
+ case ModeStateMachine.CMD_START_SCAN_ONLY_MODE:
+ Log.d(TAG, "Switching from " + getCurrentMode() + " to ScanOnlyMode");
+ mModeStateMachine.transitionTo(mScanOnlyModeActiveState);
+ break;
+ case ModeStateMachine.CMD_DISABLE_WIFI:
+ Log.d(TAG, "Switching from " + getCurrentMode() + " to WifiDisabled");
+ mModeStateMachine.transitionTo(mWifiDisabledState);
+ break;
+ default:
+ return NOT_HANDLED;
}
-
- protected abstract boolean processMessageFiltered(Message msg);
+ return HANDLED;
}
- class DefaultState extends State {
+ class ModeActiveState extends State {
+ ActiveModeManager mManager;
@Override
- public boolean processMessage(Message msg) {
- switch (msg.what) {
- case CMD_SCAN_ALWAYS_MODE_CHANGED:
- case CMD_WIFI_TOGGLED:
- case CMD_SCANNING_STOPPED:
- case CMD_STA_STOPPED:
- case CMD_STA_START_FAILURE:
- case CMD_RECOVERY_RESTART_WIFI_CONTINUE:
- case CMD_DEFERRED_RECOVERY_RESTART_WIFI:
- break;
- case CMD_RECOVERY_DISABLE_WIFI:
- log("Recovery has been throttled, disable wifi");
- shutdownWifi();
- transitionTo(mStaDisabledState);
- break;
- case CMD_RECOVERY_RESTART_WIFI:
- deferMessage(obtainMessage(CMD_DEFERRED_RECOVERY_RESTART_WIFI));
- shutdownWifi();
- transitionTo(mStaDisabledState);
- break;
- case CMD_SET_AP:
- // note: CMD_SET_AP is handled/dropped in ECM mode - will not start here
- if (msg.arg1 == 1) {
- enterSoftAPMode((SoftApModeConfiguration) msg.obj);
- } else {
- stopSoftAPMode(msg.arg2);
- }
- break;
- case CMD_AIRPLANE_TOGGLED:
- if (mSettingsStore.isAirplaneModeOn()) {
- log("Airplane mode toggled, shutdown all modes");
- shutdownWifi();
- transitionTo(mStaDisabledState);
- } else {
- log("Airplane mode disabled, determine next state");
- if (mSettingsStore.isWifiToggleEnabled()) {
- transitionTo(mStaEnabledState);
- } else if (checkScanOnlyModeAvailable()) {
- transitionTo(mStaDisabledWithScanState);
- }
- // wifi should remain disabled, do not need to transition
- }
- break;
- case CMD_AP_STOPPED:
- log("SoftAp mode disabled, determine next state");
- if (mSettingsStore.isWifiToggleEnabled()) {
- transitionTo(mStaEnabledState);
- } else if (checkScanOnlyModeAvailable()) {
- transitionTo(mStaDisabledWithScanState);
- }
- // wifi should remain disabled, do not need to transition
- break;
- default:
- throw new RuntimeException("WifiController.handleMessage " + msg.what);
- }
- return HANDLED;
+ public boolean processMessage(Message message) {
+ // handle messages for changing modes here
+ return NOT_HANDLED;
}
- }
-
- abstract class ModeActiveState extends BaseState {
- protected ActiveModeManager mManager;
@Override
public void exit() {
@@ -631,18 +342,17 @@ public class ActiveModeWarden {
updateScanMode();
}
updateBatteryStatsWifiState(false);
- super.exit();
}
// Hook to be used by sub-classes of ModeActiveState to indicate the completion of
// bringup of the corresponding mode.
- protected void onModeActivationComplete() {
+ public void onModeActivationComplete() {
updateScanMode();
}
// Update the scan state based on all active mode managers.
// Note: This is an overkill currently because there is only 1 of scan-only or client
- // mode present today. TODO(STA+STA): multiple modes
+ // mode present today.
private void updateScanMode() {
boolean scanEnabled = false;
boolean scanningForHiddenNetworksEnabled = false;
@@ -664,88 +374,60 @@ public class ActiveModeWarden {
}
}
- class StaDisabledState extends BaseState {
+ class WifiDisabledState extends ModeActiveState {
@Override
- public boolean processMessageFiltered(Message msg) {
- switch (msg.what) {
- case CMD_WIFI_TOGGLED:
- if (mSettingsStore.isWifiToggleEnabled()) {
- transitionTo(mStaEnabledState);
- } else if (checkScanOnlyModeAvailable()) {
- // only go to scan mode if we aren't in airplane mode
- if (!mSettingsStore.isAirplaneModeOn()) {
- transitionTo(mStaDisabledWithScanState);
- }
- }
- break;
- case CMD_SCAN_ALWAYS_MODE_CHANGED:
- if (checkScanOnlyModeAvailable()) {
- transitionTo(mStaDisabledWithScanState);
- }
- break;
- case CMD_SET_AP:
- if (msg.arg1 == 1) {
- // remember that we were disabled, but pass the command up to start
- // softap
- mSettingsStore.setWifiSavedState(WifiSettingsStore.WIFI_DISABLED);
- }
- return NOT_HANDLED;
- case CMD_DEFERRED_RECOVERY_RESTART_WIFI:
- // wait mRecoveryDelayMillis for letting driver clean reset.
- sendMessageDelayed(CMD_RECOVERY_RESTART_WIFI_CONTINUE,
- mRecoveryDelayMillis);
- break;
- case CMD_RECOVERY_RESTART_WIFI_CONTINUE:
- if (mSettingsStore.isWifiToggleEnabled()) {
- // wifi is currently disabled but the toggle is on, must have had an
- // interface down before the recovery triggered
- transitionTo(mStaEnabledState);
- break;
- } else if (checkScanOnlyModeAvailable()) {
- transitionTo(mStaDisabledWithScanState);
- break;
- }
- break;
- default:
- return NOT_HANDLED;
+ public void enter() {
+ Log.d(TAG, "Entering WifiDisabledState");
+ }
+
+ @Override
+ public boolean processMessage(Message message) {
+ if (checkForAndHandleModeChange(message)) {
+ return HANDLED;
}
- return HANDLED;
+ Log.d(TAG, "Unhandled message in WifiDisabledState: " + message);
+ return NOT_HANDLED;
+ }
+
+ @Override
+ public void exit() {
+ // do not have an active mode manager... nothing to clean up
}
+
}
- class StaEnabledState extends ModeActiveState {
+ class ClientModeActiveState extends ModeActiveState {
+ ClientListener mListener;
private class ClientListener implements ClientModeManager.Listener {
@Override
public void onStateChanged(int state) {
// make sure this listener is still active
if (this != mListener) {
- log("Client mode state change from previous manager");
+ Log.d(TAG, "Client mode state change from previous manager");
return;
}
- log("State changed from client mode. state = " + state);
+ Log.d(TAG, "State changed from client mode. state = " + state);
if (state == WifiManager.WIFI_STATE_UNKNOWN) {
// error while setting up client mode or an unexpected failure.
- sendMessage(CMD_STA_START_FAILURE, this);
+ mModeStateMachine.sendMessage(CMD_CLIENT_MODE_FAILED, this);
} else if (state == WifiManager.WIFI_STATE_DISABLED) {
// client mode stopped
- sendMessage(CMD_STA_STOPPED, this);
+ mModeStateMachine.sendMessage(CMD_CLIENT_MODE_STOPPED, this);
} else if (state == WifiManager.WIFI_STATE_ENABLED) {
// client mode is ready to go
- log("client mode active");
+ Log.d(TAG, "client mode active");
onModeActivationComplete();
} else {
// only care if client mode stopped or started, dropping
}
}
}
- private ClientListener mListener;
@Override
public void enter() {
- super.enter();
- log("StaEnabledState.enter()");
+ Log.d(TAG, "Entering ClientModeActiveState");
mListener = new ClientListener();
mManager = mWifiInjector.makeClientModeManager(mListener);
@@ -757,122 +439,75 @@ public class ActiveModeWarden {
@Override
public void exit() {
- mListener = null;
super.exit();
+ mListener = null;
}
@Override
- public boolean processMessageFiltered(Message msg) {
- switch (msg.what) {
- case CMD_WIFI_TOGGLED:
- if (! mSettingsStore.isWifiToggleEnabled()) {
- if (checkScanOnlyModeAvailable()) {
- transitionTo(mStaDisabledWithScanState);
- } else {
- transitionTo(mStaDisabledState);
- }
- }
+ public boolean processMessage(Message message) {
+ switch(message.what) {
+ case CMD_START_CLIENT_MODE:
+ Log.d(TAG, "Received CMD_START_CLIENT_MODE when active - drop");
break;
- case CMD_AIRPLANE_TOGGLED:
- // airplane mode toggled on is handled in the default state
- if (mSettingsStore.isAirplaneModeOn()) {
- return NOT_HANDLED;
- } else {
- // when airplane mode is toggled off, but wifi is on, we can keep it on
- log("airplane mode toggled - and airplane mode is off. return handled");
+ case CMD_CLIENT_MODE_FAILED:
+ if (mListener != message.obj) {
+ Log.d(TAG, "Client mode state change from previous manager");
return HANDLED;
}
- case CMD_STA_START_FAILURE:
- if (mListener != msg.obj) {
- log("StaEnabledState change from previous manager");
- break;
- }
- log("StaEnabledState failed, return to StaDisabled(WithScan)State.");
- if (!checkScanOnlyModeAvailable()) {
- transitionTo(mStaDisabledState);
- } else {
- transitionTo(mStaDisabledWithScanState);
- }
- break;
- case CMD_SET_AP:
- if (msg.arg1 == 1) {
- // remember that we were enabled, but pass the command up to start
- // softap
- mSettingsStore.setWifiSavedState(WifiSettingsStore.WIFI_ENABLED);
- }
- return NOT_HANDLED;
- case CMD_AP_STOPPED:
- // already in a wifi mode, no need to check where we should go with softap
- // stopped
+ Log.d(TAG, "ClientMode failed, return to WifiDisabledState.");
+ // notify WifiController that ClientMode failed
+ mClientModeCallback.onStateChanged(WifiManager.WIFI_STATE_UNKNOWN);
+ mModeStateMachine.transitionTo(mWifiDisabledState);
break;
- case CMD_STA_STOPPED:
- if (mListener != msg.obj) {
- log("StaEnabledState change from previous manager");
- break;
+ case CMD_CLIENT_MODE_STOPPED:
+ if (mListener != message.obj) {
+ Log.d(TAG, "Client mode state change from previous manager");
+ return HANDLED;
}
- log("StaEnabledState stopped, return to StaDisabledState.");
- // Client mode stopped. Head to Disabled to wait for next command.
- // We don't check whether we should go to StaDisabledWithScanState because
- // the STA was stopped so that (for example) SoftAP can be turned on and the
- // device doesn't support STA+AP. If we instead entered
- // StaDisabledWithScanState that might kill the SoftAP that we are trying to
- // start.
- transitionTo(mStaDisabledState);
+
+ Log.d(TAG, "ClientMode stopped, return to WifiDisabledState.");
+ // notify WifiController that ClientMode stopped
+ mClientModeCallback.onStateChanged(WifiManager.WIFI_STATE_DISABLED);
+ mModeStateMachine.transitionTo(mWifiDisabledState);
break;
- case CMD_RECOVERY_RESTART_WIFI:
- final String bugTitle;
- final String bugDetail;
- if (msg.arg1 < SelfRecovery.REASON_STRINGS.length && msg.arg1 >= 0) {
- bugDetail = SelfRecovery.REASON_STRINGS[msg.arg1];
- bugTitle = "Wi-Fi BugReport: " + bugDetail;
- } else {
- bugDetail = "";
- bugTitle = "Wi-Fi BugReport";
- }
- if (msg.arg1 != SelfRecovery.REASON_LAST_RESORT_WATCHDOG) {
- mHandler.post(() -> mClientModeImpl.takeBugReport(bugTitle, bugDetail));
- }
- // after the bug report trigger, more handling needs to be done
- return NOT_HANDLED;
default:
- return NOT_HANDLED;
+ return checkForAndHandleModeChange(message);
}
- return HANDLED;
+ return NOT_HANDLED;
}
}
- class StaDisabledWithScanState extends ModeActiveState {
+ class ScanOnlyModeActiveState extends ModeActiveState {
+ ScanOnlyListener mListener;
private class ScanOnlyListener implements ScanOnlyModeManager.Listener {
@Override
public void onStateChanged(int state) {
if (this != mListener) {
- log("ScanOnly mode state change from previous manager");
+ Log.d(TAG, "ScanOnly mode state change from previous manager");
return;
}
if (state == WifiManager.WIFI_STATE_UNKNOWN) {
- log("StaDisabledWithScanState mode failed");
+ Log.d(TAG, "ScanOnlyMode mode failed");
// error while setting up scan mode or an unexpected failure.
- sendMessage(CMD_SCANNING_START_FAILURE, this);
+ mModeStateMachine.sendMessage(CMD_SCAN_ONLY_MODE_FAILED, this);
} else if (state == WifiManager.WIFI_STATE_DISABLED) {
- log("StaDisabledWithScanState stopped");
+ Log.d(TAG, "ScanOnlyMode stopped");
//scan only mode stopped
- sendMessage(CMD_SCANNING_STOPPED, this);
+ mModeStateMachine.sendMessage(CMD_SCAN_ONLY_MODE_STOPPED, this);
} else if (state == WifiManager.WIFI_STATE_ENABLED) {
// scan mode is ready to go
- log("scan mode active");
+ Log.d(TAG, "scan mode active");
onModeActivationComplete();
} else {
- log("unexpected state update: " + state);
+ Log.d(TAG, "unexpected state update: " + state);
}
}
}
- private ScanOnlyListener mListener;
@Override
public void enter() {
- super.enter();
- log("StaDisabledWithScanState.enter()");
+ Log.d(TAG, "Entering ScanOnlyModeActiveState");
mListener = new ScanOnlyListener();
mManager = mWifiInjector.makeScanOnlyModeManager(mListener);
@@ -885,52 +520,146 @@ public class ActiveModeWarden {
@Override
public void exit() {
- mListener = null;
super.exit();
+ mListener = null;
}
@Override
- public boolean processMessageFiltered(Message msg) {
- switch (msg.what) {
- case CMD_WIFI_TOGGLED:
- if (mSettingsStore.isWifiToggleEnabled()) {
- transitionTo(mStaEnabledState);
- }
- break;
- case CMD_SCAN_ALWAYS_MODE_CHANGED:
- if (!checkScanOnlyModeAvailable()) {
- log("StaDisabledWithScanState: scan no longer available");
- transitionTo(mStaDisabledState);
- }
+ public boolean processMessage(Message message) {
+ switch(message.what) {
+ case CMD_START_SCAN_ONLY_MODE:
+ Log.d(TAG, "Received CMD_START_SCAN_ONLY_MODE when active - drop");
break;
- case CMD_SET_AP:
- if (msg.arg1 == 1) {
- // remember that we were disabled, but pass the command up to start
- // softap
- mSettingsStore.setWifiSavedState(WifiSettingsStore.WIFI_DISABLED);
+ case CMD_SCAN_ONLY_MODE_FAILED:
+ if (mListener != message.obj) {
+ Log.d(TAG, "ScanOnly mode state change from previous manager");
+ return HANDLED;
}
- return NOT_HANDLED;
- case CMD_AP_STOPPED:
- // already in a wifi mode, no need to check where we should go with softap
- // stopped
+
+ Log.d(TAG, "ScanOnlyMode failed, return to WifiDisabledState.");
+ // notify WifiController that ScanOnlyMode failed
+ mScanOnlyCallback.onStateChanged(WifiManager.WIFI_STATE_UNKNOWN);
+ mModeStateMachine.transitionTo(mWifiDisabledState);
break;
- case CMD_SCANNING_START_FAILURE:
- case CMD_SCANNING_STOPPED:
- if (mListener != msg.obj) {
+ case CMD_SCAN_ONLY_MODE_STOPPED:
+ if (mListener != message.obj) {
Log.d(TAG, "ScanOnly mode state change from previous manager");
- break;
+ return HANDLED;
}
- log("StaDisabledWithScanState "
- + (msg.what == CMD_SCANNING_STOPPED ? "stopped" : "failed")
- + ", return to StaDisabledState.");
- // stopped due to interface destruction - return to disabled and wait
- transitionTo(mStaDisabledState);
+
+ Log.d(TAG, "ScanOnlyMode stopped, return to WifiDisabledState.");
+ // notify WifiController that ScanOnlyMode stopped
+ mScanOnlyCallback.onStateChanged(WifiManager.WIFI_STATE_DISABLED);
+ mModeStateMachine.transitionTo(mWifiDisabledState);
break;
default:
- return NOT_HANDLED;
+ return checkForAndHandleModeChange(message);
}
return HANDLED;
}
}
+ } // class ModeStateMachine
+
+ private class SoftApCallbackImpl extends ModeCallback implements WifiManager.SoftApCallback {
+ private final int mMode;
+
+ SoftApCallbackImpl(int mode) {
+ Preconditions.checkArgument(mode == WifiManager.IFACE_IP_MODE_TETHERED
+ || mode == WifiManager.IFACE_IP_MODE_LOCAL_ONLY);
+ mMode = mode;
+ }
+
+ @Override
+ public void onStateChanged(int state, int reason) {
+ if (state == WifiManager.WIFI_AP_STATE_DISABLED) {
+ mActiveModeManagers.remove(getActiveModeManager());
+ updateBatteryStatsWifiState(false);
+ } else if (state == WifiManager.WIFI_AP_STATE_FAILED) {
+ mActiveModeManagers.remove(getActiveModeManager());
+ updateBatteryStatsWifiState(false);
+ }
+ switch (mMode) {
+ case WifiManager.IFACE_IP_MODE_TETHERED:
+ if (mSoftApCallback != null) mSoftApCallback.onStateChanged(state, reason);
+ break;
+ case WifiManager.IFACE_IP_MODE_LOCAL_ONLY:
+ if (mLohsCallback != null) mLohsCallback.onStateChanged(state, reason);
+ break;
+ }
+ }
+
+ @Override
+ public void onNumClientsChanged(int numClients) {
+ switch (mMode) {
+ case WifiManager.IFACE_IP_MODE_TETHERED:
+ if (mSoftApCallback != null) mSoftApCallback.onNumClientsChanged(numClients);
+ break;
+ case WifiManager.IFACE_IP_MODE_LOCAL_ONLY:
+ if (mLohsCallback != null) mLohsCallback.onNumClientsChanged(numClients);
+ break;
+ }
+ }
+ }
+
+ private void startSoftAp(SoftApModeConfiguration softapConfig) {
+ Log.d(TAG, "Starting SoftApModeManager config = "
+ + softapConfig.getWifiConfiguration());
+
+ SoftApCallbackImpl callback = new SoftApCallbackImpl(softapConfig.getTargetMode());
+ ActiveModeManager manager = mWifiInjector.makeSoftApManager(callback, softapConfig);
+ callback.setActiveModeManager(manager);
+ manager.start();
+ mActiveModeManagers.add(manager);
+ updateBatteryStatsWifiState(true);
+ }
+
+ /**
+ * Helper method to report wifi state as on/off (doesn't matter which mode).
+ *
+ * @param enabled boolean indicating that some mode has been turned on or off
+ */
+ private void updateBatteryStatsWifiState(boolean enabled) {
+ try {
+ if (enabled) {
+ if (mActiveModeManagers.size() == 1) {
+ // only report wifi on if we haven't already
+ mBatteryStats.noteWifiOn();
+ }
+ } else {
+ if (mActiveModeManagers.size() == 0) {
+ // only report if we don't have any active modes
+ mBatteryStats.noteWifiOff();
+ }
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to note battery stats in wifi");
+ }
+ }
+
+ private void updateBatteryStatsScanModeActive() {
+ try {
+ mBatteryStats.noteWifiState(BatteryStats.WIFI_STATE_OFF_SCANNING, null);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to note battery stats in wifi");
+ }
}
+
+ // callback used to receive callbacks about underlying native failures
+ private final class WifiNativeStatusListener implements StatusListener {
+
+ @Override
+ public void onStatusChanged(boolean isReady) {
+ if (!isReady) {
+ mHandler.post(() -> {
+ Log.e(TAG, "One of the native daemons died. Triggering recovery");
+ mWifiDiagnostics.captureBugReportData(
+ WifiDiagnostics.REPORT_REASON_WIFINATIVE_FAILURE);
+
+ // immediately trigger SelfRecovery if we receive a notice about an
+ // underlying daemon failure
+ mWifiInjector.getSelfRecovery().trigger(SelfRecovery.REASON_WIFINATIVE_FAILURE);
+ });
+ }
+ }
+ };
}
diff --git a/service/java/com/android/server/wifi/ClientModeImpl.java b/service/java/com/android/server/wifi/ClientModeImpl.java
index 4559cf0b1..9100ad9f7 100644
--- a/service/java/com/android/server/wifi/ClientModeImpl.java
+++ b/service/java/com/android/server/wifi/ClientModeImpl.java
@@ -256,7 +256,7 @@ public class ClientModeImpl extends StateMachine {
}
private boolean mEnableRssiPolling = false;
- // Accessed via Binder thread ({get,set}PollRssiIntervalMsecs), and the main Wifi thread.
+ // Accessed via Binder thread ({get,set}PollRssiIntervalMsecs), and ClientModeImpl thread.
private volatile int mPollRssiIntervalMsecs = DEFAULT_POLL_RSSI_INTERVAL_MSECS;
private int mRssiPollToken = 0;
/* 3 operational states for STA operation: CONNECT_MODE, SCAN_ONLY_MODE, SCAN_ONLY_WIFI_OFF_MODE
diff --git a/service/java/com/android/server/wifi/ClientModeManager.java b/service/java/com/android/server/wifi/ClientModeManager.java
index d2fbe1b76..883b16a61 100644
--- a/service/java/com/android/server/wifi/ClientModeManager.java
+++ b/service/java/com/android/server/wifi/ClientModeManager.java
@@ -176,7 +176,7 @@ public class ClientModeManager implements ActiveModeManager {
// we must immediately clean up state in ClientModeImpl to unregister
// all client mode related objects
- // Note: onDestroyed is only called from the main Wifi thread
+ // Note: onDestroyed is only called from the ClientModeImpl thread
mClientModeImpl.handleIfaceDestroyed();
sendMessage(CMD_INTERFACE_DESTROYED);
diff --git a/service/java/com/android/server/wifi/DppManager.java b/service/java/com/android/server/wifi/DppManager.java
index e990f9cfb..c174c190e 100644
--- a/service/java/com/android/server/wifi/DppManager.java
+++ b/service/java/com/android/server/wifi/DppManager.java
@@ -42,7 +42,7 @@ import com.android.server.wifi.WifiNative.DppEventCallback;
*/
public class DppManager {
private static final String TAG = "DppManager";
- private final Handler mHandler;
+ public Handler mHandler;
private DppRequestInfo mDppRequestInfo = null;
private final WifiNative mWifiNative;
diff --git a/service/java/com/android/server/wifi/OpenNetworkNotifier.java b/service/java/com/android/server/wifi/OpenNetworkNotifier.java
index dffee2dc2..97f390f39 100644
--- a/service/java/com/android/server/wifi/OpenNetworkNotifier.java
+++ b/service/java/com/android/server/wifi/OpenNetworkNotifier.java
@@ -26,7 +26,7 @@ import com.android.server.wifi.nano.WifiMetricsProto;
/**
* This class handles the "open wi-fi network available" notification
*
- * NOTE: These API's are not thread safe and should only be used from the main Wifi thread.
+ * NOTE: These API's are not thread safe and should only be used from ClientModeImpl thread.
*/
public class OpenNetworkNotifier extends AvailableNetworkNotifier {
public static final String TAG = "WifiOpenNetworkNotifier";
diff --git a/service/java/com/android/server/wifi/ScanRequestProxy.java b/service/java/com/android/server/wifi/ScanRequestProxy.java
index 1b74191d5..a4678440b 100644
--- a/service/java/com/android/server/wifi/ScanRequestProxy.java
+++ b/service/java/com/android/server/wifi/ScanRequestProxy.java
@@ -63,7 +63,7 @@ import javax.annotation.concurrent.NotThreadSafe;
* {@link #SCAN_REQUEST_THROTTLE_TIME_WINDOW_FG_APPS_MS}.
* b) Background apps combined can request 1 scan every
* {@link #SCAN_REQUEST_THROTTLE_INTERVAL_BG_APPS_MS}.
- * Note: This class is not thread-safe. It needs to be invoked from the main Wifi thread only.
+ * Note: This class is not thread-safe. It needs to be invoked from ClientModeImpl thread only.
*/
@NotThreadSafe
public class ScanRequestProxy {
diff --git a/service/java/com/android/server/wifi/SelfRecovery.java b/service/java/com/android/server/wifi/SelfRecovery.java
index e789dd3a4..c9e95a77f 100644
--- a/service/java/com/android/server/wifi/SelfRecovery.java
+++ b/service/java/com/android/server/wifi/SelfRecovery.java
@@ -16,18 +16,15 @@
package com.android.server.wifi;
-import android.annotation.IntDef;
import android.util.Log;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
import java.util.Iterator;
import java.util.LinkedList;
/**
* This class is used to recover the wifi stack from a fatal failure. The recovery mechanism
* involves triggering a stack restart (essentially simulating an airplane mode toggle) using
- * {@link ActiveModeWarden}.
+ * {@link WifiController}.
* The current triggers for:
* 1. Last resort watchdog bite.
* 2. HAL/wificond crashes during normal operation.
@@ -42,14 +39,6 @@ public class SelfRecovery {
public static final int REASON_LAST_RESORT_WATCHDOG = 0;
public static final int REASON_WIFINATIVE_FAILURE = 1;
public static final int REASON_STA_IFACE_DOWN = 2;
-
- @Retention(RetentionPolicy.SOURCE)
- @IntDef(prefix = {"REASON_"}, value = {
- REASON_LAST_RESORT_WATCHDOG,
- REASON_WIFINATIVE_FAILURE,
- REASON_STA_IFACE_DOWN})
- public @interface RecoveryReason {}
-
public static final long MAX_RESTARTS_IN_TIME_WINDOW = 2; // 2 restarts per hour
public static final long MAX_RESTARTS_TIME_WINDOW_MILLIS = 60 * 60 * 1000; // 1 hour
protected static final String[] REASON_STRINGS = {
@@ -58,14 +47,14 @@ public class SelfRecovery {
"Sta Interface Down" // REASON_STA_IFACE_DOWN
};
- private final ActiveModeWarden mActiveModeWarden;
+ private final WifiController mWifiController;
private final Clock mClock;
// Time since boot (in millis) that restart occurred
private final LinkedList<Long> mPastRestartTimes;
- public SelfRecovery(ActiveModeWarden activeModeWarden, Clock clock) {
- mActiveModeWarden = activeModeWarden;
+ public SelfRecovery(WifiController wifiController, Clock clock) {
+ mWifiController = wifiController;
mClock = clock;
- mPastRestartTimes = new LinkedList<>();
+ mPastRestartTimes = new LinkedList<Long>();
}
/**
@@ -74,13 +63,13 @@ public class SelfRecovery {
* This method does the following:
* 1. Checks reason code used to trigger recovery
* 2. Checks for sta iface down triggers and disables wifi by sending {@link
- * ActiveModeWarden#recoveryDisableWifi()} to {@link ActiveModeWarden} to disable wifi.
+ * WifiController#CMD_RECOVERY_DISABLE_WIFI} to {@link WifiController} to disable wifi.
* 3. Throttles restart calls for underlying native failures
- * 4. Sends {@link ActiveModeWarden#recoveryRestartWifi(int)} to {@link ActiveModeWarden} to
+ * 4. Sends {@link WifiController#CMD_RECOVERY_RESTART_WIFI} to {@link WifiController} to
* initiate the stack restart.
* @param reason One of the above |REASON_*| codes.
*/
- public void trigger(@RecoveryReason int reason) {
+ public void trigger(int reason) {
if (!(reason == REASON_LAST_RESORT_WATCHDOG || reason == REASON_WIFINATIVE_FAILURE
|| reason == REASON_STA_IFACE_DOWN)) {
Log.e(TAG, "Invalid trigger reason. Ignoring...");
@@ -88,7 +77,7 @@ public class SelfRecovery {
}
if (reason == REASON_STA_IFACE_DOWN) {
Log.e(TAG, "STA interface down, disable wifi");
- mActiveModeWarden.recoveryDisableWifi();
+ mWifiController.sendMessage(WifiController.CMD_RECOVERY_DISABLE_WIFI);
return;
}
@@ -99,12 +88,12 @@ public class SelfRecovery {
if (mPastRestartTimes.size() >= MAX_RESTARTS_IN_TIME_WINDOW) {
Log.e(TAG, "Already restarted wifi (" + MAX_RESTARTS_IN_TIME_WINDOW + ") times in"
+ " last (" + MAX_RESTARTS_TIME_WINDOW_MILLIS + "ms ). Disabling wifi");
- mActiveModeWarden.recoveryDisableWifi();
+ mWifiController.sendMessage(WifiController.CMD_RECOVERY_DISABLE_WIFI);
return;
}
mPastRestartTimes.add(mClock.getElapsedSinceBootMillis());
}
- mActiveModeWarden.recoveryRestartWifi(reason);
+ mWifiController.sendMessage(WifiController.CMD_RECOVERY_RESTART_WIFI, reason);
}
/**
diff --git a/service/java/com/android/server/wifi/WakeupController.java b/service/java/com/android/server/wifi/WakeupController.java
index bf36c9482..a0fedd577 100644
--- a/service/java/com/android/server/wifi/WakeupController.java
+++ b/service/java/com/android/server/wifi/WakeupController.java
@@ -16,6 +16,8 @@
package com.android.server.wifi;
+import static com.android.server.wifi.WifiController.CMD_WIFI_TOGGLED;
+
import android.content.Context;
import android.database.ContentObserver;
import android.net.wifi.ScanResult;
@@ -401,14 +403,14 @@ public class WakeupController {
/**
* Enables wifi.
*
- * <p>This method ignores all checks and assumes that {@link ActiveModeWarden} is currently
+ * <p>This method ignores all checks and assumes that {@link WifiController} is currently
* in ScanModeState.
*/
private void enableWifi() {
if (USE_PLATFORM_WIFI_WAKE) {
// TODO(b/72180295): ensure that there is no race condition with WifiServiceImpl here
if (mWifiInjector.getWifiSettingsStore().handleWifiToggled(true /* wifiEnabled */)) {
- mWifiInjector.getActiveModeWarden().wifiToggled();
+ mWifiInjector.getWifiController().sendMessage(CMD_WIFI_TOGGLED);
mWifiWakeMetrics.recordWakeupEvent(mNumScansHandled);
}
}
diff --git a/service/java/com/android/server/wifi/WifiApConfigStore.java b/service/java/com/android/server/wifi/WifiApConfigStore.java
index 227e410e5..2b343fef3 100644
--- a/service/java/com/android/server/wifi/WifiApConfigStore.java
+++ b/service/java/com/android/server/wifi/WifiApConfigStore.java
@@ -176,7 +176,7 @@ public class WifiApConfigStore {
* Update the current soft access point configuration.
* Restore to default AP configuration if null is provided.
* This can be invoked under context of binder threads (WifiManager.setWifiApConfiguration)
- * and the main Wifi thread (CMD_START_AP).
+ * and ClientModeImpl thread (CMD_START_AP).
*/
public synchronized void setApConfiguration(WifiConfiguration config) {
if (config == null) {
diff --git a/service/java/com/android/server/wifi/WifiConfigManager.java b/service/java/com/android/server/wifi/WifiConfigManager.java
index 70ae6600d..71aff0592 100644
--- a/service/java/com/android/server/wifi/WifiConfigManager.java
+++ b/service/java/com/android/server/wifi/WifiConfigManager.java
@@ -94,7 +94,7 @@ import java.util.Set;
* in the internal database. Any configuration updates should be triggered with appropriate helper
* methods of this class using the configuration's unique networkId.
*
- * NOTE: These API's are not thread safe and should only be used from the main Wifi thread.
+ * NOTE: These API's are not thread safe and should only be used from ClientModeImpl thread.
*/
public class WifiConfigManager {
/**
diff --git a/service/java/com/android/server/wifi/WifiConnectivityHelper.java b/service/java/com/android/server/wifi/WifiConnectivityHelper.java
index 833c6962f..ed541a959 100644
--- a/service/java/com/android/server/wifi/WifiConnectivityHelper.java
+++ b/service/java/com/android/server/wifi/WifiConnectivityHelper.java
@@ -29,7 +29,7 @@ import java.util.ArrayList;
* access WifiNative. It starts with firmware roaming. TODO(b/34819513): Move operations
* such as connection to network and legacy framework roaming here.
*
- * NOTE: This class is not thread safe and should only be used from the main Wifi thread.
+ * NOTE: This class is not thread safe and should only be used from the ClientModeImpl thread.
*/
public class WifiConnectivityHelper {
private static final String TAG = "WifiConnectivityHelper";
diff --git a/service/java/com/android/server/wifi/WifiController.java b/service/java/com/android/server/wifi/WifiController.java
new file mode 100644
index 000000000..227d93617
--- /dev/null
+++ b/service/java/com/android/server/wifi/WifiController.java
@@ -0,0 +1,482 @@
+/*
+ * Copyright (C) 2013 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 android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.location.LocationManager;
+import android.net.wifi.WifiManager;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.util.Log;
+
+import com.android.internal.R;
+import com.android.internal.util.Protocol;
+import com.android.internal.util.State;
+import com.android.internal.util.StateMachine;
+import com.android.server.wifi.util.WifiPermissionsUtil;
+
+/**
+ * WifiController is the class used to manage wifi state for various operating
+ * modes (normal, airplane, wifi hotspot, etc.).
+ */
+public class WifiController extends StateMachine {
+ private static final String TAG = "WifiController";
+ private final Context mContext;
+
+ // Maximum limit to use for timeout delay if the value from overlay setting is too large.
+ private static final int MAX_RECOVERY_TIMEOUT_DELAY_MS = 4000;
+
+ /* References to values tracked in WifiService */
+ private final ClientModeImpl mClientModeImpl;
+ private final Handler mHandler;
+ private final ActiveModeWarden mActiveModeWarden;
+ private final WifiSettingsStore mSettingsStore;
+ private final FrameworkFacade mFacade;
+ private final WifiPermissionsUtil mWifiPermissionsUtil;
+
+ private final int mRecoveryDelayMillis;
+
+ private static final int BASE = Protocol.BASE_WIFI_CONTROLLER;
+
+ static final int CMD_EMERGENCY_MODE_CHANGED = BASE + 1;
+ static final int CMD_SCAN_ALWAYS_MODE_CHANGED = BASE + 7;
+ static final int CMD_WIFI_TOGGLED = BASE + 8;
+ static final int CMD_AIRPLANE_TOGGLED = BASE + 9;
+ static final int CMD_SET_AP = BASE + 10;
+ static final int CMD_EMERGENCY_CALL_STATE_CHANGED = BASE + 14;
+ static final int CMD_AP_STOPPED = BASE + 15;
+ static final int CMD_STA_START_FAILURE = BASE + 16;
+ // Command used to trigger a wifi stack restart when in active mode
+ static final int CMD_RECOVERY_RESTART_WIFI = BASE + 17;
+ // Internal command used to complete wifi stack restart
+ private static final int CMD_RECOVERY_RESTART_WIFI_CONTINUE = BASE + 18;
+ // Command to disable wifi when SelfRecovery is throttled or otherwise not doing full recovery
+ static final int CMD_RECOVERY_DISABLE_WIFI = BASE + 19;
+ static final int CMD_STA_STOPPED = BASE + 20;
+ static final int CMD_SCANNING_STOPPED = BASE + 21;
+ static final int CMD_DEFERRED_RECOVERY_RESTART_WIFI = BASE + 22;
+
+ private final DefaultState mDefaultState = new DefaultState();
+ private final StaEnabledState mStaEnabledState = new StaEnabledState();
+ private final StaDisabledState mStaDisabledState = new StaDisabledState();
+ private final StaDisabledWithScanState mStaDisabledWithScanState =
+ new StaDisabledWithScanState();
+ private final EcmState mEcmState = new EcmState();
+
+ WifiController(Context context, ClientModeImpl clientModeImpl, Looper looper,
+ WifiSettingsStore wss, FrameworkFacade f,
+ ActiveModeWarden amw, WifiPermissionsUtil wifiPermissionsUtil) {
+ super(TAG, looper);
+ mFacade = f;
+ mContext = context;
+ mClientModeImpl = clientModeImpl;
+ mHandler = new Handler(looper);
+ mActiveModeWarden = amw;
+ mSettingsStore = wss;
+ mWifiPermissionsUtil = wifiPermissionsUtil;
+
+ addState(mDefaultState); {
+ addState(mStaDisabledState, mDefaultState);
+ addState(mStaEnabledState, mDefaultState);
+ addState(mStaDisabledWithScanState, mDefaultState);
+ addState(mEcmState, mDefaultState);
+ }
+
+ setLogRecSize(100);
+ setLogOnlyTransitions(false);
+
+ // register for state updates via callbacks (vs the intents registered below)
+ mActiveModeWarden.registerScanOnlyCallback(state -> {
+ if (state == WifiManager.WIFI_STATE_UNKNOWN) {
+ Log.d(TAG, "ScanOnlyMode unexpected failure: state unknown");
+ } else if (state == WifiManager.WIFI_STATE_DISABLED) {
+ Log.d(TAG, "ScanOnlyMode stopped");
+ sendMessage(CMD_SCANNING_STOPPED);
+ } else if (state == WifiManager.WIFI_STATE_ENABLED) {
+ // scan mode is ready to go
+ Log.d(TAG, "scan mode active");
+ } else {
+ Log.d(TAG, "unexpected state update: " + state);
+ }
+ });
+ mActiveModeWarden.registerClientModeCallback(state -> {
+ if (state == WifiManager.WIFI_STATE_UNKNOWN) {
+ logd("ClientMode unexpected failure: state unknown");
+ sendMessage(CMD_STA_START_FAILURE);
+ } else if (state == WifiManager.WIFI_STATE_DISABLED) {
+ logd("ClientMode stopped");
+ sendMessage(CMD_STA_STOPPED);
+ } else if (state == WifiManager.WIFI_STATE_ENABLED) {
+ // scan mode is ready to go
+ logd("client mode active");
+ } else {
+ logd("unexpected state update: " + state);
+ }
+ });
+
+ mRecoveryDelayMillis = readWifiRecoveryDelay();
+ }
+
+ @Override
+ public void start() {
+ boolean isAirplaneModeOn = mSettingsStore.isAirplaneModeOn();
+ boolean isWifiEnabled = mSettingsStore.isWifiToggleEnabled();
+ boolean isScanningAlwaysAvailable = mSettingsStore.isScanAlwaysAvailable();
+ boolean isLocationModeActive = mWifiPermissionsUtil.isLocationModeEnabled();
+
+ log("isAirplaneModeOn = " + isAirplaneModeOn
+ + ", isWifiEnabled = " + isWifiEnabled
+ + ", isScanningAvailable = " + isScanningAlwaysAvailable
+ + ", isLocationModeActive = " + isLocationModeActive);
+
+ if (checkScanOnlyModeAvailable()) {
+ setInitialState(mStaDisabledWithScanState);
+ } else {
+ setInitialState(mStaDisabledState);
+ }
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(LocationManager.MODE_CHANGED_ACTION);
+ mContext.registerReceiver(
+ new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ if (action.equals(LocationManager.MODE_CHANGED_ACTION)) {
+ // Location mode has been toggled... trigger with the scan change
+ // update to make sure we are in the correct mode
+ sendMessage(CMD_SCAN_ALWAYS_MODE_CHANGED);
+ }
+ }
+ },
+ new IntentFilter(filter));
+ super.start();
+ }
+
+ private boolean checkScanOnlyModeAvailable() {
+ return mWifiPermissionsUtil.isLocationModeEnabled()
+ && mSettingsStore.isScanAlwaysAvailable();
+ }
+
+ private int readWifiRecoveryDelay() {
+ int recoveryDelayMillis = mContext.getResources().getInteger(
+ R.integer.config_wifi_framework_recovery_timeout_delay);
+ if (recoveryDelayMillis > MAX_RECOVERY_TIMEOUT_DELAY_MS) {
+ recoveryDelayMillis = MAX_RECOVERY_TIMEOUT_DELAY_MS;
+ Log.w(TAG, "Overriding timeout delay with maximum limit value");
+ }
+ return recoveryDelayMillis;
+ }
+
+ class DefaultState extends State {
+ @Override
+ public boolean processMessage(Message msg) {
+ switch (msg.what) {
+ case CMD_SCAN_ALWAYS_MODE_CHANGED:
+ case CMD_WIFI_TOGGLED:
+ case CMD_SCANNING_STOPPED:
+ case CMD_STA_STOPPED:
+ case CMD_STA_START_FAILURE:
+ case CMD_RECOVERY_RESTART_WIFI_CONTINUE:
+ case CMD_DEFERRED_RECOVERY_RESTART_WIFI:
+ break;
+ case CMD_RECOVERY_DISABLE_WIFI:
+ log("Recovery has been throttled, disable wifi");
+ mActiveModeWarden.shutdownWifi();
+ transitionTo(mStaDisabledState);
+ break;
+ case CMD_RECOVERY_RESTART_WIFI:
+ deferMessage(obtainMessage(CMD_DEFERRED_RECOVERY_RESTART_WIFI));
+ mActiveModeWarden.shutdownWifi();
+ transitionTo(mStaDisabledState);
+ break;
+ case CMD_SET_AP:
+ // note: CMD_SET_AP is handled/dropped in ECM mode - will not start here
+ if (msg.arg1 == 1) {
+ mActiveModeWarden.enterSoftAPMode((SoftApModeConfiguration) msg.obj);
+ } else {
+ mActiveModeWarden.stopSoftAPMode(msg.arg2);
+ }
+ break;
+ case CMD_AIRPLANE_TOGGLED:
+ if (mSettingsStore.isAirplaneModeOn()) {
+ log("Airplane mode toggled, shutdown all modes");
+ mActiveModeWarden.shutdownWifi();
+ transitionTo(mStaDisabledState);
+ } else {
+ log("Airplane mode disabled, determine next state");
+ if (mSettingsStore.isWifiToggleEnabled()) {
+ transitionTo(mStaEnabledState);
+ } else if (checkScanOnlyModeAvailable()) {
+ transitionTo(mStaDisabledWithScanState);
+ }
+ // wifi should remain disabled, do not need to transition
+ }
+ break;
+ case CMD_EMERGENCY_CALL_STATE_CHANGED:
+ case CMD_EMERGENCY_MODE_CHANGED:
+ if (msg.arg1 == 1) {
+ transitionTo(mEcmState);
+ }
+ break;
+ case CMD_AP_STOPPED:
+ log("SoftAp mode disabled, determine next state");
+ if (mSettingsStore.isWifiToggleEnabled()) {
+ transitionTo(mStaEnabledState);
+ } else if (checkScanOnlyModeAvailable()) {
+ transitionTo(mStaDisabledWithScanState);
+ }
+ // wifi should remain disabled, do not need to transition
+ break;
+ default:
+ throw new RuntimeException("WifiController.handleMessage " + msg.what);
+ }
+ return HANDLED;
+ }
+ }
+
+ class StaDisabledState extends State {
+ @Override
+ public void enter() {
+ mActiveModeWarden.disableWifi();
+ }
+
+ @Override
+ public boolean processMessage(Message msg) {
+ switch (msg.what) {
+ case CMD_WIFI_TOGGLED:
+ if (mSettingsStore.isWifiToggleEnabled()) {
+ transitionTo(mStaEnabledState);
+ } else if (checkScanOnlyModeAvailable()) {
+ // only go to scan mode if we aren't in airplane mode
+ if (mSettingsStore.isAirplaneModeOn()) {
+ transitionTo(mStaDisabledWithScanState);
+ }
+ }
+ break;
+ case CMD_SCAN_ALWAYS_MODE_CHANGED:
+ if (checkScanOnlyModeAvailable()) {
+ transitionTo(mStaDisabledWithScanState);
+ }
+ break;
+ case CMD_SET_AP:
+ if (msg.arg1 == 1) {
+ // remember that we were disabled, but pass the command up to start softap
+ mSettingsStore.setWifiSavedState(WifiSettingsStore.WIFI_DISABLED);
+ }
+ return NOT_HANDLED;
+ case CMD_DEFERRED_RECOVERY_RESTART_WIFI:
+ // wait mRecoveryDelayMillis for letting driver clean reset.
+ sendMessageDelayed(CMD_RECOVERY_RESTART_WIFI_CONTINUE, mRecoveryDelayMillis);
+ break;
+ case CMD_RECOVERY_RESTART_WIFI_CONTINUE:
+ if (mSettingsStore.isWifiToggleEnabled()) {
+ // wifi is currently disabled but the toggle is on, must have had an
+ // interface down before the recovery triggered
+ transitionTo(mStaEnabledState);
+ break;
+ } else if (checkScanOnlyModeAvailable()) {
+ transitionTo(mStaDisabledWithScanState);
+ break;
+ }
+ break;
+ default:
+ return NOT_HANDLED;
+ }
+ return HANDLED;
+ }
+ }
+
+ class StaEnabledState extends State {
+ @Override
+ public void enter() {
+ log("StaEnabledState.enter()");
+ mActiveModeWarden.enterClientMode();
+ }
+
+ @Override
+ public boolean processMessage(Message msg) {
+ switch (msg.what) {
+ case CMD_WIFI_TOGGLED:
+ if (! mSettingsStore.isWifiToggleEnabled()) {
+ if (checkScanOnlyModeAvailable()) {
+ transitionTo(mStaDisabledWithScanState);
+ } else {
+ transitionTo(mStaDisabledState);
+ }
+ }
+ break;
+ case CMD_AIRPLANE_TOGGLED:
+ // airplane mode toggled on is handled in the default state
+ if (mSettingsStore.isAirplaneModeOn()) {
+ return NOT_HANDLED;
+ } else {
+ // when airplane mode is toggled off, but wifi is on, we can keep it on
+ log("airplane mode toggled - and airplane mode is off. return handled");
+ return HANDLED;
+ }
+ case CMD_STA_START_FAILURE:
+ if (!checkScanOnlyModeAvailable()) {
+ transitionTo(mStaDisabledState);
+ } else {
+ transitionTo(mStaDisabledWithScanState);
+ }
+ break;
+ case CMD_SET_AP:
+ if (msg.arg1 == 1) {
+ // remember that we were enabled, but pass the command up to start softap
+ mSettingsStore.setWifiSavedState(WifiSettingsStore.WIFI_ENABLED);
+ }
+ return NOT_HANDLED;
+ case CMD_AP_STOPPED:
+ // already in a wifi mode, no need to check where we should go with softap
+ // stopped
+ break;
+ case CMD_STA_STOPPED:
+ // Client mode stopped. head to Disabled to wait for next command
+ transitionTo(mStaDisabledState);
+ break;
+ case CMD_RECOVERY_RESTART_WIFI:
+ final String bugTitle;
+ final String bugDetail;
+ if (msg.arg1 < SelfRecovery.REASON_STRINGS.length && msg.arg1 >= 0) {
+ bugDetail = SelfRecovery.REASON_STRINGS[msg.arg1];
+ bugTitle = "Wi-Fi BugReport: " + bugDetail;
+ } else {
+ bugDetail = "";
+ bugTitle = "Wi-Fi BugReport";
+ }
+ if (msg.arg1 != SelfRecovery.REASON_LAST_RESORT_WATCHDOG) {
+ mHandler.post(() -> mClientModeImpl.takeBugReport(bugTitle, bugDetail));
+ }
+ // after the bug report trigger, more handling needs to be done
+ return NOT_HANDLED;
+ default:
+ return NOT_HANDLED;
+ }
+ return HANDLED;
+ }
+ }
+
+ class StaDisabledWithScanState extends State {
+ @Override
+ public void enter() {
+ // now trigger the actual mode switch in ActiveModeWarden
+ mActiveModeWarden.enterScanOnlyMode();
+ }
+
+ @Override
+ public boolean processMessage(Message msg) {
+ switch (msg.what) {
+ case CMD_WIFI_TOGGLED:
+ if (mSettingsStore.isWifiToggleEnabled()) {
+ transitionTo(mStaEnabledState);
+ }
+ break;
+ case CMD_SCAN_ALWAYS_MODE_CHANGED:
+ if (!checkScanOnlyModeAvailable()) {
+ log("StaDisabledWithScanState: scan no longer available");
+ transitionTo(mStaDisabledState);
+ }
+ break;
+ case CMD_SET_AP:
+ if (msg.arg1 == 1) {
+ // remember that we were disabled, but pass the command up to start softap
+ mSettingsStore.setWifiSavedState(WifiSettingsStore.WIFI_DISABLED);
+ }
+ return NOT_HANDLED;
+ case CMD_AP_STOPPED:
+ // already in a wifi mode, no need to check where we should go with softap
+ // stopped
+ break;
+ case CMD_SCANNING_STOPPED:
+ // stopped due to interface destruction - return to disabled and wait
+ log("WifiController: SCANNING_STOPPED when in scan mode -> StaDisabled");
+ transitionTo(mStaDisabledState);
+ break;
+ default:
+ return NOT_HANDLED;
+ }
+ return HANDLED;
+ }
+ }
+
+ class EcmState extends State {
+ /**
+ * we can enter EcmState either because an emergency call started or because
+ * emergency callback mode started. This count keeps track of how many such
+ * events happened; so we can exit after all are undone
+ */
+ private int mEcmEntryCount;
+
+ @Override
+ public void enter() {
+ mActiveModeWarden.stopSoftAPMode(WifiManager.IFACE_IP_MODE_UNSPECIFIED);
+ boolean configWiFiDisableInECBM =
+ mFacade.getConfigWiFiDisableInECBM(mContext);
+ log("WifiController msg getConfigWiFiDisableInECBM "
+ + configWiFiDisableInECBM);
+ if (configWiFiDisableInECBM) {
+ mActiveModeWarden.shutdownWifi();
+ }
+ mEcmEntryCount = 1;
+ }
+
+ /**
+ * Handles messages received while in EcmMode.
+ */
+ @Override
+ public boolean processMessage(Message msg) {
+ switch (msg.what) {
+ case CMD_EMERGENCY_CALL_STATE_CHANGED:
+ case CMD_EMERGENCY_MODE_CHANGED:
+ if (msg.arg1 == 1) {
+ mEcmEntryCount++;
+ } else {
+ mEcmEntryCount--;
+ }
+ if (mEcmEntryCount <= 0) {
+ if (mSettingsStore.isWifiToggleEnabled()) {
+ transitionTo(mStaEnabledState);
+ } else if (checkScanOnlyModeAvailable()) {
+ transitionTo(mStaDisabledWithScanState);
+ } else {
+ transitionTo(mStaDisabledState);
+ }
+ }
+ return HANDLED;
+ case CMD_RECOVERY_RESTART_WIFI:
+ case CMD_RECOVERY_DISABLE_WIFI:
+ // do not want to restart wifi if we are in emergency mode
+ return HANDLED;
+ case CMD_AP_STOPPED:
+ case CMD_SCANNING_STOPPED:
+ case CMD_STA_STOPPED:
+ // do not want to trigger a mode switch if we are in emergency mode
+ return HANDLED;
+ case CMD_SET_AP:
+ // do not want to start softap if we are in emergency mode
+ return HANDLED;
+ default:
+ return NOT_HANDLED;
+ }
+ }
+ }
+}
diff --git a/service/java/com/android/server/wifi/WifiInjector.java b/service/java/com/android/server/wifi/WifiInjector.java
index 2a2c28da9..722b1532d 100644
--- a/service/java/com/android/server/wifi/WifiInjector.java
+++ b/service/java/com/android/server/wifi/WifiInjector.java
@@ -105,6 +105,7 @@ public class WifiInjector {
private OpenNetworkNotifier mOpenNetworkNotifier;
private final CarrierNetworkConfig mCarrierNetworkConfig;
private final WifiLockManager mLockManager;
+ private final WifiController mWifiController;
private final WificondControl mWificondControl;
private final Clock mClock = new Clock();
private final WifiMetrics mWifiMetrics;
@@ -152,7 +153,7 @@ public class WifiInjector {
private final LinkProbeManager mLinkProbeManager;
private IpMemoryStore mIpMemoryStore;
private final CellularLinkLayerStatsCollector mCellularLinkLayerStatsCollector;
- private final WifiThreadRunner mWifiThreadRunner;
+
public WifiInjector(Context context) {
if (context == null) {
@@ -189,7 +190,6 @@ public class WifiInjector {
mWifiHandlerThread.start();
Looper wifiLooper = mWifiHandlerThread.getLooper();
Handler wifiHandler = mWifiHandlerThread.getThreadHandler();
- mWifiThreadRunner = new WifiThreadRunner(wifiHandler);
mWifiP2pServiceHandlerThread = new HandlerThread("WifiP2pService");
mWifiP2pServiceHandlerThread.start();
mPasspointProvisionerHandlerThread =
@@ -306,9 +306,8 @@ public class WifiInjector {
this, mBackupManagerProxy, mCountryCode, mWifiNative,
new WrongPasswordNotifier(mContext, mFrameworkFacade),
mSarManager, mWifiTrafficPoller, mLinkProbeManager);
- mActiveModeWarden = new ActiveModeWarden(this, wifiLooper,
- mWifiNative, new DefaultModeManager(mContext), mBatteryStats, mWifiDiagnostics,
- mContext, mClientModeImpl, mSettingsStore, mFrameworkFacade, mWifiPermissionsUtil);
+ mActiveModeWarden = new ActiveModeWarden(this, mContext, wifiLooper,
+ mWifiNative, new DefaultModeManager(mContext), mBatteryStats);
WakeupNotificationFactory wakeupNotificationFactory =
new WakeupNotificationFactory(mContext, this, mFrameworkFacade);
@@ -321,7 +320,9 @@ public class WifiInjector {
this, mFrameworkFacade, mClock);
mLockManager = new WifiLockManager(mContext, BatteryStatsService.getService(),
mClientModeImpl, mFrameworkFacade, wifiHandler, mWifiNative, mClock, mWifiMetrics);
- mSelfRecovery = new SelfRecovery(mActiveModeWarden, mClock);
+ mWifiController = new WifiController(mContext, mClientModeImpl, wifiLooper,
+ mSettingsStore, mFrameworkFacade, mActiveModeWarden, mWifiPermissionsUtil);
+ mSelfRecovery = new SelfRecovery(mWifiController, mClock);
mWifiMulticastLockManager = new WifiMulticastLockManager(
mClientModeImpl.getMcastLockManagerFilterController(),
BatteryStatsService.getService());
@@ -428,6 +429,10 @@ public class WifiInjector {
return mClientModeImpl;
}
+ public Handler getClientModeImplHandler() {
+ return mClientModeImpl.getHandler();
+ }
+
public ActiveModeWarden getActiveModeWarden() {
return mActiveModeWarden;
}
@@ -440,6 +445,10 @@ public class WifiInjector {
return mLockManager;
}
+ public WifiController getWifiController() {
+ return mWifiController;
+ }
+
public WifiLastResortWatchdog getWifiLastResortWatchdog() {
return mWifiLastResortWatchdog;
}
@@ -587,8 +596,7 @@ public class WifiInjector {
mWifiConfigManager, mWifiConfigStore, clientModeImpl,
new ConnectToNetworkNotificationBuilder(mContext, this, mFrameworkFacade));
mWifiLastResortWatchdog = new WifiLastResortWatchdog(this, mContext, mClock,
- mWifiMetrics, clientModeImpl, mWifiHandlerThread.getLooper(), mDeviceConfigFacade,
- mWifiThreadRunner);
+ mWifiMetrics, clientModeImpl, mWifiHandlerThread.getLooper(), mDeviceConfigFacade);
return new WifiConnectivityManager(mContext, getScoringParams(),
clientModeImpl, this,
mWifiConfigManager, clientModeImpl.getWifiInfo(),
@@ -738,8 +746,4 @@ public class WifiInjector {
public String getWifiStackPackageName() {
return mContext.getPackageName();
}
-
- public WifiThreadRunner getWifiThreadRunner() {
- return mWifiThreadRunner;
- }
}
diff --git a/service/java/com/android/server/wifi/WifiLastResortWatchdog.java b/service/java/com/android/server/wifi/WifiLastResortWatchdog.java
index be45921a7..acd10572f 100644
--- a/service/java/com/android/server/wifi/WifiLastResortWatchdog.java
+++ b/service/java/com/android/server/wifi/WifiLastResortWatchdog.java
@@ -117,7 +117,6 @@ public class WifiLastResortWatchdog {
private boolean mWatchdogFixedWifi = true;
private long mLastStartConnectTime = 0;
private Handler mHandler;
- private final WifiThreadRunner mWifiThreadRunner;
/**
* Local log used for debugging any WifiLastResortWatchdog issues.
@@ -126,7 +125,7 @@ public class WifiLastResortWatchdog {
WifiLastResortWatchdog(WifiInjector wifiInjector, Context context, Clock clock,
WifiMetrics wifiMetrics, ClientModeImpl clientModeImpl, Looper clientModeImplLooper,
- DeviceConfigFacade deviceConfigFacade, WifiThreadRunner wifiThreadRunner) {
+ DeviceConfigFacade deviceConfigFacade) {
mWifiInjector = wifiInjector;
mClock = clock;
mWifiMetrics = wifiMetrics;
@@ -134,7 +133,6 @@ public class WifiLastResortWatchdog {
mClientModeImplLooper = clientModeImplLooper;
mContext = context;
mDeviceConfigFacade = deviceConfigFacade;
- mWifiThreadRunner = wifiThreadRunner;
mHandler = new Handler(clientModeImplLooper) {
public void handleMessage(Message msg) {
processMessage(msg);
@@ -174,8 +172,9 @@ public class WifiLastResortWatchdog {
+ abnormalConnectionDurationMs + " milliseconds. "
+ "Actually took " + durationMs + " milliseconds.";
logv("Triggering bug report for abnormal connection time.");
- mWifiThreadRunner.post(() ->
- mClientModeImpl.takeBugReport(bugTitle, bugDetail));
+ mWifiInjector.getClientModeImplHandler().post(() -> {
+ mClientModeImpl.takeBugReport(bugTitle, bugDetail);
+ });
}
}
// Should reset last connection time after each connection regardless if bugreport
diff --git a/service/java/com/android/server/wifi/WifiServiceImpl.java b/service/java/com/android/server/wifi/WifiServiceImpl.java
index e5d92356a..082f56b43 100644
--- a/service/java/com/android/server/wifi/WifiServiceImpl.java
+++ b/service/java/com/android/server/wifi/WifiServiceImpl.java
@@ -28,6 +28,13 @@ import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLING;
import static android.net.wifi.WifiManager.WIFI_AP_STATE_FAILED;
import static android.net.wifi.WifiManager.WIFI_FEATURE_INFRA_5G;
+import static com.android.server.wifi.WifiController.CMD_AIRPLANE_TOGGLED;
+import static com.android.server.wifi.WifiController.CMD_EMERGENCY_CALL_STATE_CHANGED;
+import static com.android.server.wifi.WifiController.CMD_EMERGENCY_MODE_CHANGED;
+import static com.android.server.wifi.WifiController.CMD_SCAN_ALWAYS_MODE_CHANGED;
+import static com.android.server.wifi.WifiController.CMD_SET_AP;
+import static com.android.server.wifi.WifiController.CMD_WIFI_TOGGLED;
+
import android.annotation.CheckResult;
import android.app.AppOpsManager;
import android.app.admin.DeviceAdminInfo;
@@ -99,6 +106,7 @@ import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.util.AsyncChannel;
import com.android.server.wifi.hotspot2.PasspointProvider;
import com.android.server.wifi.util.ExternalCallbackTracker;
+import com.android.server.wifi.util.GeneralUtil.Mutable;
import com.android.server.wifi.util.WifiHandler;
import com.android.server.wifi.util.WifiPermissionsUtil;
@@ -391,11 +399,12 @@ public class WifiServiceImpl extends BaseWifiService {
}
private final ClientModeImplHandler mClientModeImplHandler;
+ private final WifiController mWifiController;
private final WifiLockManager mWifiLockManager;
private final WifiMulticastLockManager mWifiMulticastLockManager;
private final DppManager mDppManager;
+
private final WifiApConfigStore mWifiApConfigStore;
- private final WifiThreadRunner mWifiThreadRunner;
public WifiServiceImpl(Context context, WifiInjector wifiInjector, AsyncChannel asyncChannel) {
mContext = context;
@@ -421,6 +430,7 @@ public class WifiServiceImpl extends BaseWifiService {
new AsyncChannelExternalClientHandler(TAG, asyncChannelHandlerThread.getLooper());
mClientModeImplHandler = new ClientModeImplHandler(TAG,
asyncChannelHandlerThread.getLooper(), asyncChannel);
+ mWifiController = mWifiInjector.getWifiController();
mWifiBackupRestore = mWifiInjector.getWifiBackupRestore();
mWifiApConfigStore = mWifiInjector.getWifiApConfigStore();
mWifiPermissionsUtil = mWifiInjector.getWifiPermissionsUtil();
@@ -434,7 +444,6 @@ public class WifiServiceImpl extends BaseWifiService {
mPowerProfile = mWifiInjector.getPowerProfile();
mWifiNetworkSuggestionsManager = mWifiInjector.getWifiNetworkSuggestionsManager();
mDppManager = mWifiInjector.getDppManager();
- mWifiThreadRunner = mWifiInjector.getWifiThreadRunner();
}
/**
@@ -466,7 +475,7 @@ public class WifiServiceImpl extends BaseWifiService {
@Override
public void onReceive(Context context, Intent intent) {
if (mSettingsStore.handleAirplaneModeToggled()) {
- mActiveModeWarden.airplaneModeToggled();
+ mWifiController.sendMessage(CMD_AIRPLANE_TOGGLED);
}
if (mSettingsStore.isAirplaneModeOn()) {
Log.d(TAG, "resetting country code because Airplane mode is ON");
@@ -501,7 +510,7 @@ public class WifiServiceImpl extends BaseWifiService {
if (!mClientModeImpl.syncInitialize(mClientModeImplChannel)) {
Log.wtf(TAG, "Failed to initialize ClientModeImpl");
}
- mActiveModeWarden.start();
+ mWifiController.start();
// If we are already disabled (could be due to airplane mode), avoid changing persist
// state here
@@ -560,14 +569,17 @@ public class WifiServiceImpl extends BaseWifiService {
}
try {
mWifiPermissionsUtil.enforceCanAccessScanResults(packageName, callingUid);
- Boolean scanSuccess = mWifiThreadRunner.call(() ->
- mScanRequestProxy.startScan(callingUid, packageName));
- if (scanSuccess == null) {
- Log.e(TAG, "Timed out while synchronously starting scan");
+ Mutable<Boolean> scanSuccess = new Mutable<>();
+ boolean runWithScissorsSuccess = mWifiInjector.getClientModeImplHandler()
+ .runWithScissors(() -> {
+ scanSuccess.value = mScanRequestProxy.startScan(callingUid, packageName);
+ }, RUN_WITH_SCISSORS_TIMEOUT_MILLIS);
+ if (!runWithScissorsSuccess) {
+ Log.e(TAG, "Failed to post runnable to start scan");
sendFailedScanBroadcast();
return false;
}
- if (!scanSuccess) {
+ if (!scanSuccess.value) {
Log.e(TAG, "Failed to start scan");
return false;
}
@@ -822,7 +834,7 @@ public class WifiServiceImpl extends BaseWifiService {
Binder.restoreCallingIdentity(ident);
}
mWifiMetrics.incrementNumWifiToggles(isPrivileged, enable);
- mActiveModeWarden.wifiToggled();
+ mWifiController.sendMessage(CMD_WIFI_TOGGLED);
return true;
}
@@ -879,7 +891,9 @@ public class WifiServiceImpl extends BaseWifiService {
mLog.info("updateInterfaceIpState uid=%").c(Binder.getCallingUid()).flush();
// hand off the work to our handler thread
- mWifiThreadRunner.post(() -> mLohsSoftApTracker.updateInterfaceIpState(ifaceName, mode));
+ mWifiInjector.getClientModeImplHandler().post(() -> {
+ mLohsSoftApTracker.updateInterfaceIpState(ifaceName, mode);
+ });
}
/**
@@ -917,7 +931,7 @@ public class WifiServiceImpl extends BaseWifiService {
// null wifiConfig is a meaningful input for CMD_SET_AP
if (wifiConfig == null || WifiApConfigStore.validateApWifiConfiguration(wifiConfig)) {
SoftApModeConfiguration softApConfig = new SoftApModeConfiguration(mode, wifiConfig);
- mActiveModeWarden.startSoftAp(softApConfig);
+ mWifiController.sendMessage(CMD_SET_AP, 1, 0, softApConfig);
return true;
}
Slog.e(TAG, "Invalid WifiConfiguration");
@@ -957,7 +971,7 @@ public class WifiServiceImpl extends BaseWifiService {
private void stopSoftApInternal(int mode) {
mLog.trace("stopSoftApInternal uid=% mode=%").c(Binder.getCallingUid()).c(mode).flush();
- mActiveModeWarden.stopSoftAp(mode);
+ mWifiController.sendMessage(CMD_SET_AP, 0, mode);
}
/**
@@ -1036,7 +1050,7 @@ public class WifiServiceImpl extends BaseWifiService {
}
// Notify WifiController so it has a chance to turn wifi back on
if (state == WIFI_AP_STATE_FAILED || state == WIFI_AP_STATE_DISABLED) {
- mActiveModeWarden.softApStopped();
+ mWifiController.sendMessage(WifiController.CMD_AP_STOPPED);
}
}
@@ -1392,7 +1406,7 @@ public class WifiServiceImpl extends BaseWifiService {
}
// post operation to handler thread
- mWifiThreadRunner.post(() -> {
+ mWifiInjector.getClientModeImplHandler().post(() -> {
if (!mTetheredSoftApTracker.registerSoftApCallback(binder, callback,
callbackIdentifier)) {
Log.e(TAG, "registerSoftApCallback: Failed to add callback");
@@ -1405,6 +1419,7 @@ public class WifiServiceImpl extends BaseWifiService {
} catch (RemoteException e) {
Log.e(TAG, "registerSoftApCallback: remote exception -- " + e);
}
+
});
}
@@ -1423,8 +1438,9 @@ public class WifiServiceImpl extends BaseWifiService {
}
// post operation to handler thread
- mWifiThreadRunner.post(() ->
- mTetheredSoftApTracker.unregisterSoftApCallback(callbackIdentifier));
+ mWifiInjector.getClientModeImplHandler().post(() -> {
+ mTetheredSoftApTracker.unregisterSoftApCallback(callbackIdentifier);
+ });
}
/**
@@ -1526,6 +1542,7 @@ public class WifiServiceImpl extends BaseWifiService {
mLog.info("stopLocalOnlyHotspot uid=% pid=%").c(uid).c(pid).flush();
mLohsSoftApTracker.stopByPid(pid);
+
}
/**
@@ -1582,12 +1599,15 @@ public class WifiServiceImpl extends BaseWifiService {
// hand off work to the ClientModeImpl handler thread to sync work between calls
// and SoftApManager starting up softap
- WifiConfiguration config = mWifiThreadRunner.call(mWifiApConfigStore::getApConfiguration);
- if (config == null) {
- Log.e(TAG, "Timed out while synchronously fetching AP config");
- return new WifiConfiguration();
+ final Mutable<WifiConfiguration> config = new Mutable<>();
+ boolean success = mWifiInjector.getClientModeImplHandler().runWithScissors(() -> {
+ config.value = mWifiApConfigStore.getApConfiguration();
+ }, RUN_WITH_SCISSORS_TIMEOUT_MILLIS);
+ if (success) {
+ return config.value;
}
- return config;
+ Log.e(TAG, "Failed to post runnable to fetch ap config");
+ return new WifiConfiguration();
}
/**
@@ -1612,7 +1632,9 @@ public class WifiServiceImpl extends BaseWifiService {
if (wifiConfig == null)
return false;
if (WifiApConfigStore.validateApWifiConfiguration(wifiConfig)) {
- mWifiThreadRunner.post(() -> mWifiApConfigStore.setApConfiguration(wifiConfig));
+ mClientModeImplHandler.post(() -> {
+ mWifiApConfigStore.setApConfiguration(wifiConfig);
+ });
return true;
} else {
Slog.e(TAG, "Invalid WifiConfiguration");
@@ -2228,10 +2250,12 @@ public class WifiServiceImpl extends BaseWifiService {
}
try {
mWifiPermissionsUtil.enforceCanAccessScanResults(callingPackage, uid);
- List<ScanResult> scanResults = mWifiThreadRunner.call(
- mScanRequestProxy::getScanResults);
- if (scanResults == null) {
- Log.e(TAG, "Timed out while synchronously fetching scan results");
+ final List<ScanResult> scanResults = new ArrayList<>();
+ boolean success = mWifiInjector.getClientModeImplHandler().runWithScissors(() -> {
+ scanResults.addAll(mScanRequestProxy.getScanResults());
+ }, RUN_WITH_SCISSORS_TIMEOUT_MILLIS);
+ if (!success) {
+ Log.e(TAG, "Failed to post runnable to fetch scan results");
return new ArrayList<>();
}
return scanResults;
@@ -2588,11 +2612,11 @@ public class WifiServiceImpl extends BaseWifiService {
} else if (action.equals(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED)) {
boolean emergencyMode =
intent.getBooleanExtra(PhoneConstants.PHONE_IN_ECM_STATE, false);
- mActiveModeWarden.emergencyCallbackModeChanged(emergencyMode);
+ mWifiController.sendMessage(CMD_EMERGENCY_MODE_CHANGED, emergencyMode ? 1 : 0);
} else if (action.equals(TelephonyIntents.ACTION_EMERGENCY_CALL_STATE_CHANGED)) {
boolean inCall =
intent.getBooleanExtra(PhoneConstants.PHONE_IN_EMERGENCY_CALL, false);
- mActiveModeWarden.emergencyCallStateChanged(inCall);
+ mWifiController.sendMessage(CMD_EMERGENCY_CALL_STATE_CHANGED, inCall ? 1 : 0);
} else if (action.equals(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED)) {
handleIdleModeChanged();
}
@@ -2607,7 +2631,7 @@ public class WifiServiceImpl extends BaseWifiService {
@Override
public void onChange(boolean selfChange) {
mSettingsStore.handleWifiScanAlwaysAvailableToggled();
- mActiveModeWarden.scanAlwaysModeChanged();
+ mWifiController.sendMessage(CMD_SCAN_ALWAYS_MODE_CHANGED);
}
};
mFrameworkFacade.registerContentObserver(mContext,
@@ -2647,8 +2671,8 @@ public class WifiServiceImpl extends BaseWifiService {
String pkgName = uri.getSchemeSpecificPart();
mClientModeImpl.removeAppConfigs(pkgName, uid);
- // Call the method in the main Wifi thread.
- mWifiThreadRunner.post(() -> {
+ // Call the method in ClientModeImpl thread.
+ mWifiInjector.getClientModeImplHandler().post(() -> {
mScanRequestProxy.clearScanRequestTimestampsForApp(pkgName, uid);
// Remove all suggestions from the package.
@@ -2658,6 +2682,7 @@ public class WifiServiceImpl extends BaseWifiService {
// Remove all Passpoint profiles from package.
mWifiInjector.getPasspointManager().removePasspointProviderWithPackage(
pkgName);
+
});
}
}
@@ -2693,10 +2718,12 @@ public class WifiServiceImpl extends BaseWifiService {
WifiScoreReport wifiScoreReport = mClientModeImpl.getWifiScoreReport();
if (wifiScoreReport != null) wifiScoreReport.dump(fd, pw, args);
} else if (args != null && args.length > 0 && WifiScoreCard.DUMP_ARG.equals(args[0])) {
- WifiScoreCard wifiScoreCard = mWifiInjector.getWifiScoreCard();
- String networkListBase64 = mWifiThreadRunner.call(() ->
- wifiScoreCard.getNetworkListBase64(true));
- pw.println(networkListBase64);
+ mWifiInjector.getClientModeImplHandler().runWithScissors(() -> {
+ WifiScoreCard wifiScoreCard = mWifiInjector.getWifiScoreCard();
+ if (wifiScoreCard != null) {
+ pw.println(wifiScoreCard.getNetworkListBase64(true));
+ }
+ }, RUN_WITH_SCISSORS_TIMEOUT_MILLIS);
} else {
// Polls link layer stats and RSSI. This allows the stats to show up in
// WifiScoreReport's dump() output when taking a bug report even if the screen is off.
@@ -2708,6 +2735,7 @@ public class WifiServiceImpl extends BaseWifiService {
Settings.Global.STAY_ON_WHILE_PLUGGED_IN, 0));
pw.println("mInIdleMode " + mInIdleMode);
pw.println("mScanPending " + mScanPending);
+ mWifiController.dump(fd, pw, args);
mSettingsStore.dump(fd, pw, args);
mWifiTrafficPoller.dump(fd, pw, args);
pw.println();
@@ -2720,27 +2748,35 @@ public class WifiServiceImpl extends BaseWifiService {
pw.println();
mClientModeImpl.dump(fd, pw, args);
pw.println();
- WifiScoreCard wifiScoreCard = mWifiInjector.getWifiScoreCard();
- String networkListBase64 = mWifiThreadRunner.call(() ->
- wifiScoreCard.getNetworkListBase64(true));
- pw.println("WifiScoreCard:");
- pw.println(networkListBase64);
+ mWifiInjector.getClientModeImplHandler().runWithScissors(() -> {
+ WifiScoreCard wifiScoreCard = mWifiInjector.getWifiScoreCard();
+ if (wifiScoreCard != null) {
+ pw.println("WifiScoreCard:");
+ pw.println(wifiScoreCard.getNetworkListBase64(true));
+ }
+ }, RUN_WITH_SCISSORS_TIMEOUT_MILLIS);
mClientModeImpl.updateWifiMetrics();
mWifiMetrics.dump(fd, pw, args);
pw.println();
- mWifiThreadRunner.run(() -> mWifiNetworkSuggestionsManager.dump(fd, pw, args));
- pw.println();
+ mWifiInjector.getClientModeImplHandler().runWithScissors(() -> {
+ mWifiNetworkSuggestionsManager.dump(fd, pw, args);
+ pw.println();
+ }, RUN_WITH_SCISSORS_TIMEOUT_MILLIS);
mWifiBackupRestore.dump(fd, pw, args);
pw.println();
pw.println("ScoringParams: settings put global " + Settings.Global.WIFI_SCORE_PARAMS
+ " " + mWifiInjector.getScoringParams());
pw.println();
- pw.println("WifiScoreReport:");
WifiScoreReport wifiScoreReport = mClientModeImpl.getWifiScoreReport();
- wifiScoreReport.dump(fd, pw, args);
+ if (wifiScoreReport != null) {
+ pw.println("WifiScoreReport:");
+ wifiScoreReport.dump(fd, pw, args);
+ }
pw.println();
SarManager sarManager = mWifiInjector.getSarManager();
- sarManager.dump(fd, pw, args);
+ if (sarManager != null) {
+ sarManager.dump(fd, pw, args);
+ }
pw.println();
}
}
@@ -2758,13 +2794,18 @@ public class WifiServiceImpl extends BaseWifiService {
WorkSource updatedWs = (ws == null || ws.isEmpty())
? new WorkSource(Binder.getCallingUid()) : ws;
- Boolean lockSuccess = mWifiThreadRunner.call(() ->
- mWifiLockManager.acquireWifiLock(lockMode, tag, binder, updatedWs));
- if (lockSuccess == null) {
- Log.e(TAG, "Timed out while synchronously calling acquireWifiLock()");
+ Mutable<Boolean> lockSuccess = new Mutable<>();
+ boolean runWithScissorsSuccess = mWifiInjector.getClientModeImplHandler().runWithScissors(
+ () -> {
+ lockSuccess.value = mWifiLockManager.acquireWifiLock(
+ lockMode, tag, binder, updatedWs);
+ }, RUN_WITH_SCISSORS_TIMEOUT_MILLIS);
+ if (!runWithScissorsSuccess) {
+ Log.e(TAG, "Failed to post runnable to acquireWifiLock");
return false;
}
- return lockSuccess;
+
+ return lockSuccess.value;
}
@Override
@@ -2779,10 +2820,12 @@ public class WifiServiceImpl extends BaseWifiService {
WorkSource updatedWs = (ws == null || ws.isEmpty())
? new WorkSource(Binder.getCallingUid()) : ws;
- boolean runSuccess = mWifiThreadRunner.run(() ->
- mWifiLockManager.updateWifiLockWorkSource(binder, updatedWs));
- if (!runSuccess) {
- Log.e(TAG, "Timed out while synchronously calling updateWifiLockWorkSource()");
+ boolean runWithScissorsSuccess = mWifiInjector.getClientModeImplHandler().runWithScissors(
+ () -> {
+ mWifiLockManager.updateWifiLockWorkSource(binder, updatedWs);
+ }, RUN_WITH_SCISSORS_TIMEOUT_MILLIS);
+ if (!runWithScissorsSuccess) {
+ Log.e(TAG, "Failed to post runnable to updateWifiLockWorkSource");
}
}
@@ -2792,14 +2835,16 @@ public class WifiServiceImpl extends BaseWifiService {
// Check on permission to make this call
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null);
-
- Boolean lockSuccess = mWifiThreadRunner.call(() ->
- mWifiLockManager.releaseWifiLock(binder));
- if (lockSuccess == null) {
- Log.e(TAG, "Timed out while synchronously calling releaseWifiLock()");
+ Mutable<Boolean> lockSuccess = new Mutable<>();
+ boolean runWithScissorsSuccess = mWifiInjector.getClientModeImplHandler().runWithScissors(
+ () -> {
+ lockSuccess.value = mWifiLockManager.releaseWifiLock(binder);
+ }, RUN_WITH_SCISSORS_TIMEOUT_MILLIS);
+ if (!runWithScissorsSuccess) {
+ Log.e(TAG, "Failed to post runnable to releaseWifiLock");
return false;
}
- return lockSuccess;
+ return lockSuccess.value;
}
@Override
@@ -2898,7 +2943,7 @@ public class WifiServiceImpl extends BaseWifiService {
}
}
- mWifiThreadRunner.post(() -> {
+ mWifiInjector.getClientModeImplHandler().post(() -> {
mWifiInjector.getWifiConfigManager().clearDeletedEphemeralNetworks();
mClientModeImpl.clearNetworkRequestUserApprovedAccessPoints();
mWifiNetworkSuggestionsManager.clear();
@@ -3097,8 +3142,9 @@ public class WifiServiceImpl extends BaseWifiService {
mLog.info("registerTrafficStateCallback uid=%").c(Binder.getCallingUid()).flush();
}
// Post operation to handler thread
- mWifiThreadRunner.post(() ->
- mWifiTrafficPoller.addCallback(binder, callback, callbackIdentifier));
+ mWifiInjector.getClientModeImplHandler().post(() -> {
+ mWifiTrafficPoller.addCallback(binder, callback, callbackIdentifier);
+ });
}
/**
@@ -3116,8 +3162,9 @@ public class WifiServiceImpl extends BaseWifiService {
mLog.info("unregisterTrafficStateCallback uid=%").c(Binder.getCallingUid()).flush();
}
// Post operation to handler thread
- mWifiThreadRunner.post(() ->
- mWifiTrafficPoller.removeCallback(callbackIdentifier));
+ mWifiInjector.getClientModeImplHandler().post(() -> {
+ mWifiTrafficPoller.removeCallback(callbackIdentifier);
+ });
}
private boolean is5GhzSupported() {
@@ -3169,8 +3216,9 @@ public class WifiServiceImpl extends BaseWifiService {
.c(Binder.getCallingUid()).flush();
}
// Post operation to handler thread
- mWifiThreadRunner.post(() -> mClientModeImpl.addNetworkRequestMatchCallback(
- binder, callback, callbackIdentifier));
+ mWifiInjector.getClientModeImplHandler().post(() -> {
+ mClientModeImpl.addNetworkRequestMatchCallback(binder, callback, callbackIdentifier);
+ });
}
/**
@@ -3189,8 +3237,9 @@ public class WifiServiceImpl extends BaseWifiService {
.c(Binder.getCallingUid()).flush();
}
// Post operation to handler thread
- mWifiThreadRunner.post(() ->
- mClientModeImpl.removeNetworkRequestMatchCallback(callbackIdentifier));
+ mWifiInjector.getClientModeImplHandler().post(() -> {
+ mClientModeImpl.removeNetworkRequestMatchCallback(callbackIdentifier);
+ });
}
/**
@@ -3211,17 +3260,20 @@ public class WifiServiceImpl extends BaseWifiService {
mLog.info("addNetworkSuggestions uid=%").c(Binder.getCallingUid()).flush();
}
int callingUid = Binder.getCallingUid();
-
- Integer success = mWifiThreadRunner.call(() -> mWifiNetworkSuggestionsManager.add(
- networkSuggestions, callingUid, callingPackageName));
- if (success == null) {
- Log.e(TAG, "Timed out while synchronously adding network suggestions");
+ Mutable<Integer> success = new Mutable<>();
+ boolean runWithScissorsSuccess = mWifiInjector.getClientModeImplHandler().runWithScissors(
+ () -> {
+ success.value = mWifiNetworkSuggestionsManager.add(
+ networkSuggestions, callingUid, callingPackageName);
+ }, RUN_WITH_SCISSORS_TIMEOUT_MILLIS);
+ if (!runWithScissorsSuccess) {
+ Log.e(TAG, "Failed to post runnable to add network suggestions");
return WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_INTERNAL;
}
- if (success != WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS) {
+ if (success.value != WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS) {
Log.e(TAG, "Failed to add network suggestions");
}
- return success;
+ return success.value;
}
/**
@@ -3242,17 +3294,20 @@ public class WifiServiceImpl extends BaseWifiService {
mLog.info("removeNetworkSuggestions uid=%").c(Binder.getCallingUid()).flush();
}
int callingUid = Binder.getCallingUid();
-
- Integer success = mWifiThreadRunner.call(() -> mWifiNetworkSuggestionsManager.remove(
- networkSuggestions, callingUid, callingPackageName));
- if (success == null) {
- Log.e(TAG, "Timed out while synchronously removing network suggestions");
+ Mutable<Integer> success = new Mutable<>();
+ boolean runWithScissorsSuccess = mWifiInjector.getClientModeImplHandler().runWithScissors(
+ () -> {
+ success.value = mWifiNetworkSuggestionsManager.remove(
+ networkSuggestions, callingUid, callingPackageName);
+ }, RUN_WITH_SCISSORS_TIMEOUT_MILLIS);
+ if (!runWithScissorsSuccess) {
+ Log.e(TAG, "Failed to post runnable to remove network suggestions");
return WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_INTERNAL;
}
- if (success != WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS) {
+ if (success.value != WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS) {
Log.e(TAG, "Failed to remove network suggestions");
}
- return success;
+ return success.value;
}
/**
@@ -3266,14 +3321,15 @@ public class WifiServiceImpl extends BaseWifiService {
if (mVerboseLoggingEnabled) {
mLog.info("getNetworkSuggestionList uid=%").c(Binder.getCallingUid()).flush();
}
-
- List<WifiNetworkSuggestion> result = mWifiThreadRunner.call(() ->
- mWifiNetworkSuggestionsManager.get(callingPackageName));
- if (result == null) {
- Log.e(TAG, "Timed out while synchronously getting network suggestions");
+ Mutable<List<WifiNetworkSuggestion>> result = new Mutable<>();
+ boolean runWithScissorsSuccess = mWifiInjector.getClientModeImplHandler().runWithScissors(
+ () -> result.value = mWifiNetworkSuggestionsManager.get(callingPackageName),
+ RUN_WITH_SCISSORS_TIMEOUT_MILLIS);
+ if (!runWithScissorsSuccess) {
+ Log.e(TAG, "Failed to post runnable to get network suggestions");
return new ArrayList<>();
}
- return result;
+ return result.value;
}
/**
@@ -3288,14 +3344,17 @@ public class WifiServiceImpl extends BaseWifiService {
throw new SecurityException("App not allowed to get Wi-Fi factory MAC address "
+ "(uid = " + uid + ")");
}
- String result = mWifiThreadRunner.call(mClientModeImpl::getFactoryMacAddress);
- // result can be null if either: WifiThreadRunner.call() timed out, or
- // ClientModeImpl.getFactoryMacAddress() returned null.
- // In this particular instance, we don't differentiate the two types of nulls.
- if (result == null) {
- return null;
+ final List<String> result = new ArrayList<>();
+ boolean success = mWifiInjector.getClientModeImplHandler().runWithScissors(() -> {
+ final String mac = mClientModeImpl.getFactoryMacAddress();
+ if (mac != null) {
+ result.add(mac);
+ }
+ }, RUN_WITH_SCISSORS_TIMEOUT_MILLIS);
+ if (success) {
+ return result.isEmpty() ? null : result.toArray(new String[0]);
}
- return new String[]{result};
+ return null;
}
/**
@@ -3314,7 +3373,8 @@ public class WifiServiceImpl extends BaseWifiService {
.flush();
}
// Post operation to handler thread
- mWifiThreadRunner.post(() -> mClientModeImpl.setDeviceMobilityState(state));
+ mWifiInjector.getClientModeImplHandler()
+ .post(() -> mClientModeImpl.setDeviceMobilityState(state));
}
/**
@@ -3358,8 +3418,10 @@ public class WifiServiceImpl extends BaseWifiService {
throw new SecurityException(TAG + ": Permission denied");
}
- mWifiThreadRunner.post(() -> mDppManager.startDppAsConfiguratorInitiator(
- uid, binder, enrolleeUri, selectedNetworkId, netRole, callback));
+ mDppManager.mHandler.post(() -> {
+ mDppManager.startDppAsConfiguratorInitiator(uid, binder, enrolleeUri,
+ selectedNetworkId, netRole, callback);
+ });
}
/**
@@ -3390,8 +3452,9 @@ public class WifiServiceImpl extends BaseWifiService {
throw new SecurityException(TAG + ": Permission denied");
}
- mWifiThreadRunner.post(() ->
- mDppManager.startDppAsEnrolleeInitiator(uid, binder, configuratorUri, callback));
+ mDppManager.mHandler.post(() -> {
+ mDppManager.startDppAsEnrolleeInitiator(uid, binder, configuratorUri, callback);
+ });
}
/**
@@ -3404,7 +3467,9 @@ public class WifiServiceImpl extends BaseWifiService {
}
final int uid = getMockableCallingUid();
- mWifiThreadRunner.post(() -> mDppManager.stopDppSession(uid));
+ mDppManager.mHandler.post(() -> {
+ mDppManager.stopDppSession(uid);
+ });
}
/**
@@ -3437,8 +3502,9 @@ public class WifiServiceImpl extends BaseWifiService {
.c(Binder.getCallingUid()).flush();
}
// Post operation to handler thread
- mWifiThreadRunner.post(() ->
- mWifiMetrics.addOnWifiUsabilityListener(binder, listener, listenerIdentifier));
+ mWifiInjector.getClientModeImplHandler().post(() -> {
+ mWifiMetrics.addOnWifiUsabilityListener(binder, listener, listenerIdentifier);
+ });
}
/**
@@ -3458,8 +3524,9 @@ public class WifiServiceImpl extends BaseWifiService {
.c(Binder.getCallingUid()).flush();
}
// Post operation to handler thread
- mWifiThreadRunner.post(() ->
- mWifiMetrics.removeOnWifiUsabilityListener(listenerIdentifier));
+ mWifiInjector.getClientModeImplHandler().post(() -> {
+ mWifiMetrics.removeOnWifiUsabilityListener(listenerIdentifier);
+ });
}
/**
@@ -3482,7 +3549,8 @@ public class WifiServiceImpl extends BaseWifiService {
.flush();
}
// Post operation to handler thread
- mWifiThreadRunner.post(() ->
- mClientModeImpl.updateWifiUsabilityScore(seqNum, score, predictionHorizonSec));
+ mWifiInjector.getClientModeImplHandler().post(
+ () -> mClientModeImpl.updateWifiUsabilityScore(seqNum, score,
+ predictionHorizonSec));
}
}
diff --git a/service/java/com/android/server/wifi/WifiThreadRunner.java b/service/java/com/android/server/wifi/WifiThreadRunner.java
deleted file mode 100644
index b44b2445e..000000000
--- a/service/java/com/android/server/wifi/WifiThreadRunner.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (C) 2019 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 android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.os.Handler;
-import android.util.Log;
-
-import com.android.server.wifi.util.GeneralUtil.Mutable;
-
-import java.util.function.Supplier;
-
-import javax.annotation.concurrent.ThreadSafe;
-
-/**
- * Runs code on the main Wifi thread from another thread, in order to prevent race conditions.
- */
-@ThreadSafe
-public class WifiThreadRunner {
- private static final String TAG = "WifiThreadRunner";
-
- /** Max wait time for posting blocking runnables */
- private static final int RUN_WITH_SCISSORS_TIMEOUT_MILLIS = 4000;
-
- private final Handler mHandler;
-
- public WifiThreadRunner(Handler handler) {
- mHandler = handler;
- }
-
- /**
- * Synchronously runs code on the main Wifi thread and return a value.
- * <b>Blocks</b> the calling thread until the callable completes execution on the main Wifi
- * thread.
- *
- * BEWARE OF DEADLOCKS!!!
- *
- * @param <T> the return type
- * @param supplier the lambda that should be run on the main Wifi thread
- * e.g. wifiThreadRunner.call(() -> mWifiApConfigStore.getApConfiguration())
- * or wifiThreadRunner.call(mWifiApConfigStore::getApConfiguration)
- * @return value retrieved from Wifi thread, or null if the call failed.
- * Beware of NullPointerExceptions when expecting a primitive (e.g. int, long) return
- * type, it may still return null and throw a NullPointerException when auto-unboxing!
- * Recommend capturing the return value in an Integer or Long instead and explicitly
- * handling nulls.
- */
- @Nullable
- public <T> T call(@NonNull Supplier<T> supplier) {
- Mutable<T> result = new Mutable<>();
- boolean runWithScissorsSuccess = mHandler.runWithScissors(
- () -> result.value = supplier.get(),
- RUN_WITH_SCISSORS_TIMEOUT_MILLIS);
- if (runWithScissorsSuccess) {
- return result.value;
- } else {
- Log.e(TAG, "WifiThreadRunner.call() timed out!", new Throwable("Stack trace:"));
- return null;
- }
- }
-
- /**
- * Runs a Runnable on the main Wifi thread and <b>blocks</b> the calling thread until the
- * Runnable completes execution on the main Wifi thread.
- *
- * BEWARE OF DEADLOCKS!!!
- *
- * @return true if the runnable executed successfully, false otherwise
- */
- public boolean run(@NonNull Runnable runnable) {
- boolean runWithScissorsSuccess =
- mHandler.runWithScissors(runnable, RUN_WITH_SCISSORS_TIMEOUT_MILLIS);
- if (runWithScissorsSuccess) {
- return true;
- } else {
- Log.e(TAG, "WifiThreadRunner.run() timed out!", new Throwable("Stack trace:"));
- return false;
- }
- }
-
- /**
- * Asynchronously runs a Runnable on the main Wifi thread.
- *
- * @return true if the runnable was successfully posted <b>(not executed)</b> to the main Wifi
- * thread, false otherwise
- */
- public boolean post(@NonNull Runnable runnable) {
- return mHandler.post(runnable);
- }
-}
diff --git a/service/java/com/android/server/wifi/hotspot2/PasspointManager.java b/service/java/com/android/server/wifi/hotspot2/PasspointManager.java
index 9e0a26fab..21019a8c9 100644
--- a/service/java/com/android/server/wifi/hotspot2/PasspointManager.java
+++ b/service/java/com/android/server/wifi/hotspot2/PasspointManager.java
@@ -98,7 +98,7 @@ import java.util.stream.Collectors;
* The provider matching requires obtaining additional information from the AP (ANQP elements).
* The ANQP elements will be cached using {@link AnqpCache} to avoid unnecessary requests.
*
- * NOTE: These API's are not thread safe and should only be used from the main Wifi thread.
+ * NOTE: These API's are not thread safe and should only be used from ClientModeImpl thread.
*/
public class PasspointManager {
private static final String TAG = "PasspointManager";