summaryrefslogtreecommitdiff
path: root/service
diff options
context:
space:
mode:
authorRebecca Silberstein <silberst@google.com>2016-11-21 19:22:06 +0000
committerandroid-build-merger <android-build-merger@google.com>2016-11-21 19:22:06 +0000
commit9dee6afa78e114fb6405746d3f40502a34978002 (patch)
treed3bbaaf8ef8675d8074beca2f299cac0e74fe12e /service
parent44a2888f8d4d213c013c9976fb4df1c9b9a99ff6 (diff)
parentbfc30bd4c2ff0c62d6cfff22088a935878966a46 (diff)
WifiStateMachinePrime: Implement SoftApMode path
am: bfc30bd4c2 Change-Id: I6ec7a1f7270387ba2faeee033b4464ba7169f757
Diffstat (limited to 'service')
-rw-r--r--service/java/com/android/server/wifi/WifiStateMachinePrime.java296
1 files changed, 278 insertions, 18 deletions
diff --git a/service/java/com/android/server/wifi/WifiStateMachinePrime.java b/service/java/com/android/server/wifi/WifiStateMachinePrime.java
index 33cccbb88..dbb826293 100644
--- a/service/java/com/android/server/wifi/WifiStateMachinePrime.java
+++ b/service/java/com/android/server/wifi/WifiStateMachinePrime.java
@@ -16,8 +16,17 @@
package com.android.server.wifi;
+import android.net.wifi.IApInterface;
+import android.net.wifi.IWificond;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiManager;
+import android.os.INetworkManagementService;
+import android.os.Looper;
import android.os.Message;
+import android.os.RemoteException;
+import android.util.Log;
+import com.android.internal.util.Protocol;
import com.android.internal.util.State;
import com.android.internal.util.StateMachine;
@@ -32,8 +41,99 @@ public class WifiStateMachinePrime {
private ModeStateMachine mModeStateMachine;
- WifiStateMachinePrime() {
- mModeStateMachine = new ModeStateMachine(TAG);
+ private final WifiInjector mWifiInjector;
+ private final Looper mLooper;
+ private final INetworkManagementService mNMService;
+
+ private IWificond mWificond;
+
+ /* The base for wifi message types */
+ static final int BASE = Protocol.BASE_WIFI;
+
+ /* 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;
+
+ WifiStateMachinePrime(WifiInjector wifiInjector,
+ Looper looper,
+ INetworkManagementService nmService) {
+ mWifiInjector = wifiInjector;
+ mLooper = looper;
+ mNMService = nmService;
+
+ // Clean up existing interfaces in wificond.
+ // This ensures that the framework and wificond are in a consistent state after a framework
+ // restart.
+ try {
+ mWificond = mWifiInjector.makeWificond();
+ if (mWificond != null) {
+ mWificond.tearDownInterfaces();
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "wificond died during framework startup");
+ }
+ }
+
+ /**
+ * Method to switch wifi into client mode where connections to configured networks will be
+ * attempted.
+ */
+ public void enterClientMode() {
+ changeMode(ModeStateMachine.CMD_START_CLIENT_MODE);
+ }
+
+ /**
+ * 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);
+ }
+
+ /**
+ * Method to enable soft ap for wifi hotspot.
+ */
+ public void enterSoftAPMode() {
+ changeMode(ModeStateMachine.CMD_START_SOFT_AP_MODE);
+ }
+
+ /**
+ * Method to fully disable wifi.
+ *
+ * This mode will completely shut down wifi and will not perform any network scans.
+ */
+ public void disableWifi() {
+ changeMode(ModeStateMachine.CMD_DISABLE_WIFI);
+ }
+
+ protected String getCurrentMode() {
+ if (mModeStateMachine != null) {
+ return mModeStateMachine.getCurrentMode();
+ }
+ return "WifiDisabledState";
+ }
+
+ private void changeMode(int newMode) {
+ if (mModeStateMachine == null) {
+ if (newMode == ModeStateMachine.CMD_DISABLE_WIFI) {
+ // command is to disable wifi, but it is already disabled.
+ Log.e(TAG, "Received call to disable wifi when it is already disabled.");
+ return;
+ }
+ // state machine was not initialized yet, we must be starting up
+ mModeStateMachine = new ModeStateMachine(newMode);
+ } else {
+ // we have a current state, go ahead and prep for the new state
+ mModeStateMachine.sendMessage(newMode);
+ }
}
private class ModeStateMachine extends StateMachine {
@@ -43,7 +143,6 @@ public class WifiStateMachinePrime {
public static final int CMD_START_SOFT_AP_MODE = 2;
public static final int CMD_DISABLE_WIFI = 3;
-
// Create the base modes for WSM.
private final State mClientModeState = new ClientModeState();
private final State mScanOnlyModeState = new ScanOnlyModeState();
@@ -55,8 +154,8 @@ public class WifiStateMachinePrime {
private final State mScanOnlyModeActiveState = new ScanOnlyModeActiveState();
private final State mSoftAPModeActiveState = new SoftAPModeActiveState();
- ModeStateMachine(String name) {
- super(name);
+ ModeStateMachine(int initialMode) {
+ super(TAG, mLooper);
// CHECKSTYLE:OFF IndentationCheck
addState(mClientModeState);
@@ -67,54 +166,168 @@ public class WifiStateMachinePrime {
addState(mSoftAPModeActiveState, mSoftAPModeState);
addState(mWifiDisabledState);
// CHECKSTYLE:ON IndentationCheck
+
+ State startingState;
+ switch(initialMode) {
+ case CMD_START_CLIENT_MODE:
+ startingState = mClientModeState;
+ break;
+ case CMD_START_SCAN_ONLY_MODE:
+ startingState = mScanOnlyModeState;
+ break;
+ case CMD_START_SOFT_AP_MODE:
+ startingState = mSoftAPModeState;
+ break;
+ default:
+ Log.e(TAG, "Attempting to start WifiStateMachinePrime "
+ + "in an invalid operating mode: " + initialMode);
+ throw new IllegalArgumentException("Invalid wifi operating mode");
+ }
+ Log.d(TAG, "Switching from WifiDisabled to " + startingState.getName());
+ setInitialState(startingState);
+ start();
}
private String getCurrentMode() {
- try {
- return getCurrentState().getName();
- } catch (NullPointerException e) {
- // current state is not set
- return null;
+ return getCurrentState().getName();
+ }
+
+ private boolean checkForAndHandleModeChange(Message message) {
+ switch(message.what) {
+ case ModeStateMachine.CMD_START_CLIENT_MODE:
+ Log.d(TAG, "Switching from " + getCurrentMode() + " to ClientMode");
+ mModeStateMachine.transitionTo(mClientModeState);
+ break;
+ case ModeStateMachine.CMD_START_SCAN_ONLY_MODE:
+ Log.d(TAG, "Switching from " + getCurrentMode() + " to ScanOnlyMode");
+ mModeStateMachine.transitionTo(mScanOnlyModeState);
+ break;
+ case ModeStateMachine.CMD_START_SOFT_AP_MODE:
+ Log.d(TAG, "Switching from " + getCurrentMode() + " to SoftApMode");
+ mModeStateMachine.transitionTo(mSoftAPModeState);
+ break;
+ case ModeStateMachine.CMD_DISABLE_WIFI:
+ Log.d(TAG, "Switching from " + getCurrentMode() + " to WifiDisabled");
+ mModeStateMachine.transitionTo(mWifiDisabledState);
+ break;
+ default:
+ return NOT_HANDLED;
+ }
+ return HANDLED;
+ }
+
+ private void tearDownInterfaces() {
+ if (mWificond != null) {
+ try {
+ mWificond.tearDownInterfaces();
+ } catch (RemoteException e) {
+ // There is very little we can do here
+ Log.e(TAG, "Failed to tear down interfaces via wificond");
+ }
+ mWificond = null;
}
+ return;
}
class ClientModeState extends State {
+ @Override
+ public void enter() {
+ mWificond = mWifiInjector.makeWificond();
+ }
@Override
public boolean processMessage(Message message) {
+ if (checkForAndHandleModeChange(message)) {
+ return HANDLED;
+ }
return NOT_HANDLED;
}
@Override
public void exit() {
-
+ tearDownInterfaces();
}
}
class ScanOnlyModeState extends State {
+ @Override
+ public void enter() {
+ }
@Override
public boolean processMessage(Message message) {
- // handle Mode changes and any events requiring setup or restarting services
-
+ if (checkForAndHandleModeChange(message)) {
+ return HANDLED;
+ }
return NOT_HANDLED;
}
@Override
public void exit() {
- // tear down running services
+ // Do not tear down interfaces yet since this mode is not actively controlled or
+ // used in tests at this time.
+ // tearDownInterfaces();
}
}
class SoftAPModeState extends State {
+ IApInterface mApInterface = null;
+
+ @Override
+ public void enter() {
+ mApInterface = null;
+ mWificond = mWifiInjector.makeWificond();
+ if (mWificond == null) {
+ Log.e(TAG, "Failed to get reference to wificond");
+ mModeStateMachine.sendMessage(CMD_START_AP_FAILURE);
+ return;
+ }
+
+ try {
+ mApInterface = mWificond.createApInterface();
+ } catch (RemoteException e1) { }
+
+ if (mApInterface == null) {
+ Log.e(TAG, "Could not get IApInterface instance from wificond");
+ mModeStateMachine.sendMessage(CMD_START_AP_FAILURE);
+ return;
+ }
+ mModeStateMachine.sendMessage(CMD_START_AP);
+ }
@Override
public boolean processMessage(Message message) {
- return NOT_HANDLED;
+ if (checkForAndHandleModeChange(message)) {
+ return HANDLED;
+ }
+
+ switch(message.what) {
+ case CMD_START_AP:
+ Log.d(TAG, "Transitioning to softapmodeactivestate");
+ mModeStateMachine.transitionTo(mSoftAPModeActiveState);
+ break;
+ case CMD_STOP_AP:
+ // not in active state, nothing to stop.
+ break;
+ case CMD_START_AP_FAILURE:
+ Log.e(TAG, "Failed to start SoftApMode. Wait for next mode command.");
+ break;
+ case CMD_AP_STOPPED:
+ Log.d(TAG, "SoftApModeActiveState stopped. Wait for next mode command.");
+ break;
+ default:
+ return NOT_HANDLED;
+ }
+ return HANDLED;
}
@Override
public void exit() {
+ tearDownInterfaces();
+ }
+
+ protected IApInterface getInterface() {
+ return mApInterface;
}
}
@@ -163,11 +376,58 @@ public class WifiStateMachinePrime {
}
class SoftAPModeActiveState extends ModeActiveState {
+ private class SoftApListener implements SoftApManager.Listener {
+ @Override
+ public void onStateChanged(int state, int reason) {
+ if (state == WifiManager.WIFI_AP_STATE_DISABLED) {
+ mModeStateMachine.sendMessage(CMD_AP_STOPPED);
+ } else if (state == WifiManager.WIFI_AP_STATE_FAILED) {
+ mModeStateMachine.sendMessage(CMD_START_AP_FAILURE);
+ }
+ }
+ }
+
@Override
public void enter() {
- // The SoftApManager is not empty at this time, will populate in later CLs.
- //this.mActiveModeManager = new SoftApManager();
+ Log.d(TAG, "Entering SoftApModeActiveState");
+ final Message message = mModeStateMachine.getCurrentMessage();
+ if (message.what != CMD_START_AP) {
+ throw new RuntimeException("Illegal transition to SoftApState: " + message);
+ }
+ // The WifiConfiguration is generally going to be null to indicate that the
+ // currently saved config in WifiApConfigManager should be used. When the config is
+ // not null, it will be saved in the WifiApConfigManager. This save is performed in
+ // the constructor of SoftApManager.
+ WifiConfiguration config = (WifiConfiguration) message.obj;
+ this.mActiveModeManager = mWifiInjector.makeSoftApManager(mNMService,
+ new SoftApListener(), ((SoftAPModeState) mSoftAPModeState).getInterface(),
+ config);
+ mActiveModeManager.start();
+ }
+
+ @Override
+ public boolean processMessage(Message message) {
+ switch(message.what) {
+ case CMD_START_AP:
+ Log.d(TAG, "Received CMD_START_AP with SoftApMode already active. drop");
+ break;
+ case CMD_STOP_AP:
+ mActiveModeManager.stop();
+ break;
+ case CMD_START_AP_FAILURE:
+ Log.d(TAG, "Failed to start SoftApMode. Return to SoftApMode (inactive).");
+ mModeStateMachine.transitionTo(mSoftAPModeState);
+ break;
+ case CMD_AP_STOPPED:
+ Log.d(TAG, "SoftApModeActiveState stopped."
+ + " Return to SoftApMode (inactive).");
+ mModeStateMachine.transitionTo(mSoftAPModeState);
+ break;
+ default:
+ return NOT_HANDLED;
+ }
+ return HANDLED;
}
}
- } // class ModeStateMachine
+ } // class ModeStateMachine
}