diff options
author | Rebecca Silberstein <silberst@google.com> | 2017-05-25 04:48:43 -0700 |
---|---|---|
committer | Rebecca Silberstein <silberst@google.com> | 2017-06-06 11:14:55 -0700 |
commit | 1f6626d7488bba014b42bab8bbcd4720694df485 (patch) | |
tree | 546240ddc94ad22de73db2ed3ff6ea65c6abfcf6 /service | |
parent | 2f47b2755faffaa1a011ddeb8527bd9c99bb6106 (diff) |
WifiStateMachine: add mode to softap update
Plumb the softap target mode in to WifiStateMachine so we can add it to
the softap state change broadcast.
Also cleaned up some of the error and stopping states noticed due to the
mode updates and tests. This removes extra calls to clear the requests
and uses the ap state change broadcast to notify registered callers
about the LOHS stopping instead of attempting to get intermediate state.
Bug: 62076211
Test: frameworks/opt/net/wifi/tests/wifitests/runtests.sh
Change-Id: Icff0a9b30e1eb9e5aa945d289d274da7ec8910eb
Diffstat (limited to 'service')
4 files changed, 94 insertions, 42 deletions
diff --git a/service/java/com/android/server/wifi/SoftApModeConfiguration.java b/service/java/com/android/server/wifi/SoftApModeConfiguration.java new file mode 100644 index 000000000..e8805602e --- /dev/null +++ b/service/java/com/android/server/wifi/SoftApModeConfiguration.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2017 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.net.wifi.WifiConfiguration; + +/** + * Object holding the parameters needed to start SoftAp mode. + * + * Initially, this will hold the WifiConfiguration and mode. + */ +public class SoftApModeConfiguration { + final int mTargetMode; + final WifiConfiguration mConfig; + + SoftApModeConfiguration(int targetMode, WifiConfiguration config) { + mTargetMode = targetMode; + mConfig = config; + } + + public int getTargetMode() { + return mTargetMode; + } + + public WifiConfiguration getWifiConfiguration() { + return mConfig; + } +} diff --git a/service/java/com/android/server/wifi/WifiController.java b/service/java/com/android/server/wifi/WifiController.java index ed82b2b2d..c1b186142 100644 --- a/service/java/com/android/server/wifi/WifiController.java +++ b/service/java/com/android/server/wifi/WifiController.java @@ -30,7 +30,6 @@ import android.content.IntentFilter; import android.database.ContentObserver; import android.net.ConnectivityManager; import android.net.NetworkInfo; -import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiManager; import android.os.Handler; import android.os.Looper; @@ -480,7 +479,7 @@ public class WifiController extends StateMachine { if (msg.arg2 == 0) { // previous wifi state has not been saved yet mSettingsStore.setWifiSavedState(WifiSettingsStore.WIFI_DISABLED); } - mWifiStateMachine.setHostApRunning((WifiConfiguration) msg.obj, + mWifiStateMachine.setHostApRunning((SoftApModeConfiguration) msg.obj, true); transitionTo(mApEnabledState); } diff --git a/service/java/com/android/server/wifi/WifiServiceImpl.java b/service/java/com/android/server/wifi/WifiServiceImpl.java index 1b3334d5f..d32a579ac 100644 --- a/service/java/com/android/server/wifi/WifiServiceImpl.java +++ b/service/java/com/android/server/wifi/WifiServiceImpl.java @@ -19,6 +19,7 @@ package com.android.server.wifi; import static android.net.wifi.WifiManager.EXTRA_PREVIOUS_WIFI_AP_STATE; import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_FAILURE_REASON; import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_INTERFACE_NAME; +import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_MODE; import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_STATE; import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.ERROR_GENERIC; import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.ERROR_NO_CHANNEL; @@ -27,8 +28,6 @@ import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLED; import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLING; import static android.net.wifi.WifiManager.WIFI_AP_STATE_FAILED; -import static com.android.server.connectivity.tethering.IControlsTethering.STATE_LOCAL_ONLY; -import static com.android.server.connectivity.tethering.IControlsTethering.STATE_TETHERED; import static com.android.server.wifi.LocalOnlyHotspotRequestInfo.HOTSPOT_NO_ERROR; import static com.android.server.wifi.WifiController.CMD_AIRPLANE_TOGGLED; import static com.android.server.wifi.WifiController.CMD_BATTERY_CHANGED; @@ -486,7 +485,7 @@ public class WifiServiceImpl extends IWifiManager.Stub { new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { - final int currentState = intent.getIntExtra(EXTRA_WIFI_AP_STATE, + final int currState = intent.getIntExtra(EXTRA_WIFI_AP_STATE, WIFI_AP_STATE_DISABLED); final int prevState = intent.getIntExtra(EXTRA_PREVIOUS_WIFI_AP_STATE, WIFI_AP_STATE_DISABLED); @@ -494,7 +493,9 @@ public class WifiServiceImpl extends IWifiManager.Stub { HOTSPOT_NO_ERROR); final String ifaceName = intent.getStringExtra(EXTRA_WIFI_AP_INTERFACE_NAME); - handleWifiApStateChange(currentState, prevState, errorCode, ifaceName); + final int mode = intent.getIntExtra(EXTRA_WIFI_AP_MODE, + WifiManager.IFACE_IP_MODE_UNSPECIFIED); + handleWifiApStateChange(currState, prevState, errorCode, ifaceName, mode); } }, new IntentFilter(WifiManager.WIFI_AP_STATE_CHANGED_ACTION)); @@ -821,7 +822,9 @@ public class WifiServiceImpl extends IWifiManager.Stub { } // null wifiConfig is a meaningful input for CMD_SET_AP if (wifiConfig == null || isValid(wifiConfig)) { - mWifiController.sendMessage(CMD_SET_AP, enabled ? 1 : 0, 0, wifiConfig); + int mode = WifiManager.IFACE_IP_MODE_UNSPECIFIED; + SoftApModeConfiguration softApConfig = new SoftApModeConfiguration(mode, wifiConfig); + mWifiController.sendMessage(CMD_SET_AP, enabled ? 1 : 0, 0, softApConfig); } else { Slog.e(TAG, "Invalid WifiConfiguration"); } @@ -895,14 +898,12 @@ public class WifiServiceImpl extends IWifiManager.Stub { // between a tether request and a hotspot request (tethering wins). sendHotspotFailedMessageToAllLOHSRequestInfoEntriesLocked( LocalOnlyHotspotCallback.ERROR_INCOMPATIBLE_MODE); - mLocalOnlyHotspotRequests.clear(); break; case WifiManager.IFACE_IP_MODE_CONFIGURATION_ERROR: // there was an error setting up the hotspot... trigger onFailed for the // registered LOHS requestors sendHotspotFailedMessageToAllLOHSRequestInfoEntriesLocked( LocalOnlyHotspotCallback.ERROR_GENERIC); - mLocalOnlyHotspotRequests.clear(); updateInterfaceIpStateInternal(null, WifiManager.IFACE_IP_MODE_UNSPECIFIED); break; case WifiManager.IFACE_IP_MODE_UNSPECIFIED: @@ -933,12 +934,15 @@ public class WifiServiceImpl extends IWifiManager.Stub { mLog.trace("startSoftAp uid=%").c(Binder.getCallingUid()).flush(); - // TODO: determine if we need to stop softap and clean up state if a tethering request comes - // from the user while we are just setting up. For now, the second CMD_START_AP will be - // ignored in WifiStateMachine. This will still bring up tethering and the registered LOHS - // requests will be cleared when we get the interface ip tethered status. + synchronized (mLocalOnlyHotspotRequests) { + // If a tethering request comes in while we have LOHS running (or requested), call stop + // for softap mode and restart softap with the tethering config. + if (!mLocalOnlyHotspotRequests.isEmpty()) { + stopSoftApInternal(); + } - return startSoftApInternal(wifiConfig, STATE_TETHERED); + return startSoftApInternal(wifiConfig, WifiManager.IFACE_IP_MODE_TETHERED); + } } /** @@ -951,8 +955,8 @@ public class WifiServiceImpl extends IWifiManager.Stub { // null wifiConfig is a meaningful input for CMD_SET_AP if (wifiConfig == null || isValid(wifiConfig)) { - // TODO: need a way to set the mode - mWifiController.sendMessage(CMD_SET_AP, 1, 0, wifiConfig); + SoftApModeConfiguration softApConfig = new SoftApModeConfiguration(mode, wifiConfig); + mWifiController.sendMessage(CMD_SET_AP, 1, 0, softApConfig); return true; } Slog.e(TAG, "Invalid WifiConfiguration"); @@ -969,12 +973,21 @@ public class WifiServiceImpl extends IWifiManager.Stub { // NETWORK_STACK is a signature only permission. enforceNetworkStackPermission(); + // only permitted callers are allowed to this point - they must have gone through + // connectivity service since this method is protected with the NETWORK_STACK PERMISSION + mLog.trace("stopSoftAp uid=%").c(Binder.getCallingUid()).flush(); - // add checks here to make sure this is the proper caller - apps can't disable tethering or - // instances of local only hotspot that they didn't start. return false for those cases + synchronized (mLocalOnlyHotspotRequests) { + // If a tethering request comes in while we have LOHS running (or requested), call stop + // for softap mode and restart softap with the tethering config. + if (!mLocalOnlyHotspotRequests.isEmpty()) { + mLog.trace("Call to stop Tethering while LOHS is active," + + " Registered LOHS callers will be updated when softap stopped."); + } - return stopSoftApInternal(); + return stopSoftApInternal(); + } } /** @@ -984,11 +997,6 @@ public class WifiServiceImpl extends IWifiManager.Stub { private boolean stopSoftApInternal() { mLog.trace("stopSoftApInternal uid=%").c(Binder.getCallingUid()).flush(); - // we have an allowed caller - clear local only hotspot if it was enabled - synchronized (mLocalOnlyHotspotRequests) { - mLocalOnlyHotspotRequests.clear(); - mLocalOnlyHotspotConfig = null; - } mWifiController.sendMessage(CMD_SET_AP, 0, 0); return true; } @@ -997,11 +1005,11 @@ public class WifiServiceImpl extends IWifiManager.Stub { * Private method to handle SoftAp state changes */ private void handleWifiApStateChange( - int currentState, int previousState, int errorCode, String ifaceName) { + int currentState, int previousState, int errorCode, String ifaceName, int mode) { // The AP state update from WifiStateMachine for softap Slog.d(TAG, "handleWifiApStateChange: currentState=" + currentState + " previousState=" + previousState + " errorCode= " + errorCode - + " ifaceName=" + ifaceName); + + " ifaceName=" + ifaceName + " mode=" + mode); // check if we have a failure - since it is possible (worst case scenario where // WifiController and WifiStateMachine are out of sync wrt modes) to get two FAILED @@ -1055,6 +1063,7 @@ public class WifiServiceImpl extends IWifiManager.Stub { for (LocalOnlyHotspotRequestInfo requestor : mLocalOnlyHotspotRequests.values()) { try { requestor.sendHotspotFailedMessage(arg1); + requestor.unlinkDeathRecipient(); } catch (RemoteException e) { // This will be cleaned up by binder death handling } @@ -1074,6 +1083,7 @@ public class WifiServiceImpl extends IWifiManager.Stub { for (LocalOnlyHotspotRequestInfo requestor : mLocalOnlyHotspotRequests.values()) { try { requestor.sendHotspotStoppedMessage(); + requestor.unlinkDeathRecipient(); } catch (RemoteException e) { // This will be cleaned up by binder death handling } @@ -1184,7 +1194,7 @@ public class WifiServiceImpl extends IWifiManager.Stub { // this is the first request, then set up our config and start LOHS mLocalOnlyHotspotConfig = WifiApConfigStore.generateLocalOnlyHotspotConfig(mContext); - startSoftApInternal(mLocalOnlyHotspotConfig, STATE_LOCAL_ONLY); + startSoftApInternal(mLocalOnlyHotspotConfig, WifiManager.IFACE_IP_MODE_LOCAL_ONLY); } mLocalOnlyHotspotRequests.put(pid, request); @@ -2388,8 +2398,9 @@ public class WifiServiceImpl extends IWifiManager.Stub { } if (!mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_TETHERING)) { - // Turn mobile hotspot off - setWifiApEnabled(null, false); + // Turn mobile hotspot off - will also clear any registered LOHS requests when it is + // shut down + stopSoftApInternal(); } if (!mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_WIFI)) { diff --git a/service/java/com/android/server/wifi/WifiStateMachine.java b/service/java/com/android/server/wifi/WifiStateMachine.java index 5ac8a3520..19c4812b0 100644 --- a/service/java/com/android/server/wifi/WifiStateMachine.java +++ b/service/java/com/android/server/wifi/WifiStateMachine.java @@ -1607,7 +1607,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss /** * TODO: doc */ - public void setHostApRunning(WifiConfiguration wifiConfig, boolean enable) { + public void setHostApRunning(SoftApModeConfiguration wifiConfig, boolean enable) { if (enable) { sendMessage(CMD_START_AP, wifiConfig); } else { @@ -2806,11 +2806,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); } - private void setWifiApState(int wifiApState, int reason) { - setWifiApState(wifiApState, reason, null); - } - - private void setWifiApState(int wifiApState, int reason, String ifaceName) { + private void setWifiApState(int wifiApState, int reason, String ifaceName, int mode) { final int previousWifiApState = mWifiApState.get(); try { @@ -2839,9 +2835,9 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss if (ifaceName == null) { loge("Updating wifiApState with a null iface name"); - } else { - intent.putExtra(WifiManager.EXTRA_WIFI_AP_INTERFACE_NAME, ifaceName); } + intent.putExtra(WifiManager.EXTRA_WIFI_AP_INTERFACE_NAME, ifaceName); + intent.putExtra(WifiManager.EXTRA_WIFI_AP_MODE, mode); mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); } @@ -4287,7 +4283,8 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss case CMD_START_AP: /* Cannot start soft AP while in client mode */ loge("Failed to start soft AP with a running supplicant"); - setWifiApState(WIFI_AP_STATE_FAILED, WifiManager.SAP_START_FAILURE_GENERAL); + setWifiApState(WIFI_AP_STATE_FAILED, WifiManager.SAP_START_FAILURE_GENERAL, + null, WifiManager.IFACE_IP_MODE_UNSPECIFIED); break; case CMD_SET_OPERATIONAL_MODE: mOperationalMode = message.arg1; @@ -6678,6 +6675,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss class SoftApState extends State { private SoftApManager mSoftApManager; private String mIfaceName; + private int mMode; private class SoftApListener implements SoftApManager.Listener { @Override @@ -6688,7 +6686,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss sendMessage(CMD_START_AP_FAILURE); } - setWifiApState(state, reason, mIfaceName); + setWifiApState(state, reason, mIfaceName, mMode); } } @@ -6698,11 +6696,13 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss if (message.what != CMD_START_AP) { throw new RuntimeException("Illegal transition to SoftApState: " + message); } + SoftApModeConfiguration config = (SoftApModeConfiguration) message.obj; + mMode = config.getTargetMode(); IApInterface apInterface = mWifiNative.setupForSoftApMode(); if (apInterface == null) { setWifiApState(WIFI_AP_STATE_FAILED, - WifiManager.SAP_START_FAILURE_GENERAL); + WifiManager.SAP_START_FAILURE_GENERAL, null, mMode); /** * Transition to InitialState to reset the * driver/HAL back to the initial state. @@ -6718,13 +6718,12 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss // the enabled broadcast, but since we had an error getting the name, we most likely // won't be able to fully start softap mode. } - WifiConfiguration config = (WifiConfiguration) message.obj; checkAndSetConnectivityInstance(); mSoftApManager = mWifiInjector.makeSoftApManager(mNwService, new SoftApListener(), apInterface, - config); + config.getWifiConfiguration()); mSoftApManager.start(); mWifiStateTracker.updateState(WifiStateTracker.SOFT_AP); } @@ -6733,6 +6732,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss public void exit() { mSoftApManager = null; mIfaceName = null; + mMode = WifiManager.IFACE_IP_MODE_UNSPECIFIED; } @Override |