summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--service/java/com/android/server/wifi/SavedNetworkEvaluator.java50
-rw-r--r--service/java/com/android/server/wifi/SoftApModeConfiguration.java42
-rw-r--r--service/java/com/android/server/wifi/WifiApConfigStore.java1
-rw-r--r--service/java/com/android/server/wifi/WifiBackupRestore.java12
-rw-r--r--service/java/com/android/server/wifi/WifiController.java3
-rw-r--r--service/java/com/android/server/wifi/WifiInjector.java3
-rw-r--r--service/java/com/android/server/wifi/WifiMonitor.java4
-rw-r--r--service/java/com/android/server/wifi/WifiServiceImpl.java77
-rw-r--r--service/java/com/android/server/wifi/WifiStateMachine.java33
-rw-r--r--service/java/com/android/server/wifi/p2p/WifiP2pMonitor.java4
-rw-r--r--service/java/com/android/server/wifi/scanner/WifiScanningServiceImpl.java8
-rw-r--r--service/java/com/android/server/wifi/scanner/WificondScannerImpl.java10
-rw-r--r--tests/wifitests/src/com/android/server/wifi/SavedNetworkEvaluatorTest.java27
-rw-r--r--tests/wifitests/src/com/android/server/wifi/TestUtil.java8
-rw-r--r--tests/wifitests/src/com/android/server/wifi/WifiApConfigStoreTest.java2
-rw-r--r--tests/wifitests/src/com/android/server/wifi/WifiBackupRestoreTest.java22
-rw-r--r--tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java119
-rw-r--r--tests/wifitests/src/com/android/server/wifi/WifiStateMachineTest.java81
-rw-r--r--tests/wifitests/src/com/android/server/wifi/scanner/WifiScanningServiceTest.java62
19 files changed, 394 insertions, 174 deletions
diff --git a/service/java/com/android/server/wifi/SavedNetworkEvaluator.java b/service/java/com/android/server/wifi/SavedNetworkEvaluator.java
index bf79edaf8..9ac70689b 100644
--- a/service/java/com/android/server/wifi/SavedNetworkEvaluator.java
+++ b/service/java/com/android/server/wifi/SavedNetworkEvaluator.java
@@ -107,9 +107,6 @@ public class SavedNetworkEvaluator implements WifiNetworkSelector.NetworkEvaluat
continue;
}
- WifiConfiguration.NetworkSelectionStatus status =
- network.getNetworkSelectionStatus();
-
// If a configuration is temporarily disabled, re-enable it before trying
// to connect to it.
mWifiConfigManager.tryEnableNetwork(network.networkId);
@@ -120,28 +117,26 @@ public class SavedNetworkEvaluator implements WifiNetworkSelector.NetworkEvaluat
// Clear the cached candidate, score and seen.
mWifiConfigManager.clearNetworkCandidateScanResult(network.networkId);
- boolean networkDisabled = false;
- boolean networkStringLogged = false;
- for (int index = WifiConfiguration.NetworkSelectionStatus
- .NETWORK_SELECTION_DISABLED_STARTING_INDEX;
- index < WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_DISABLED_MAX;
- index++) {
- int count = status.getDisableReasonCounter(index);
- if (count > 0) {
- networkDisabled = true;
- if (!networkStringLogged) {
- sbuf.append(" ").append(WifiNetworkSelector.toNetworkString(network))
- .append(" ");
- networkStringLogged = true;
+ // Log disabled network.
+ WifiConfiguration.NetworkSelectionStatus status = network.getNetworkSelectionStatus();
+ if (!status.isNetworkEnabled()) {
+ sbuf.append(" ").append(WifiNetworkSelector.toNetworkString(network)).append(" ");
+ for (int index = WifiConfiguration.NetworkSelectionStatus
+ .NETWORK_SELECTION_DISABLED_STARTING_INDEX;
+ index < WifiConfiguration.NetworkSelectionStatus
+ .NETWORK_SELECTION_DISABLED_MAX;
+ index++) {
+ int count = status.getDisableReasonCounter(index);
+ // Here we log the reason as long as its count is greater than zero. The
+ // network may not be disabled because of this particular reason. Logging
+ // this information anyway to help understand what happened to the network.
+ if (count > 0) {
+ sbuf.append("reason=")
+ .append(WifiConfiguration.NetworkSelectionStatus
+ .getNetworkDisableReasonString(index))
+ .append(", count=").append(count).append("; ");
}
- sbuf.append("reason=")
- .append(WifiConfiguration.NetworkSelectionStatus
- .getNetworkDisableReasonString(index))
- .append(", count=").append(count).append("; ");
}
- }
-
- if (networkDisabled) {
sbuf.append("\n");
}
}
@@ -264,11 +259,12 @@ public class SavedNetworkEvaluator implements WifiNetworkSelector.NetworkEvaluat
for (WifiConfiguration network : associatedConfigurations) {
/**
- * Ignore Passpoint networks. Passpoint networks are also considered as "saved"
- * network, but without being persisted to the storage. They are being evaluated
- * by {@link PasspointNetworkEvaluator}.
+ * Ignore Passpoint and Ephemeral networks. They are configured networks,
+ * but without being persisted to the storage. They are evaluated by
+ * {@link PasspointNetworkEvaluator} and {@link ScoredNetworkEvaluator}
+ * respectively.
*/
- if (network.isPasspoint()) {
+ if (network.isPasspoint() || network.isEphemeral()) {
continue;
}
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/WifiApConfigStore.java b/service/java/com/android/server/wifi/WifiApConfigStore.java
index 850c5aebe..9c90bcf47 100644
--- a/service/java/com/android/server/wifi/WifiApConfigStore.java
+++ b/service/java/com/android/server/wifi/WifiApConfigStore.java
@@ -218,6 +218,7 @@ public class WifiApConfigStore {
R.string.wifi_localhotspot_configure_ssid_default) + "_"
+ getRandomIntForDefaultSsid();
config.allowedKeyManagement.set(KeyMgmt.WPA2_PSK);
+ config.networkId = WifiConfiguration.LOCAL_ONLY_NETWORK_ID;
String randomUUID = UUID.randomUUID().toString();
// first 12 chars from xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx
config.preSharedKey = randomUUID.substring(0, 8) + randomUUID.substring(9, 13);
diff --git a/service/java/com/android/server/wifi/WifiBackupRestore.java b/service/java/com/android/server/wifi/WifiBackupRestore.java
index 4095d8283..60c3b488d 100644
--- a/service/java/com/android/server/wifi/WifiBackupRestore.java
+++ b/service/java/com/android/server/wifi/WifiBackupRestore.java
@@ -28,6 +28,7 @@ import android.util.Xml;
import com.android.internal.util.FastXmlSerializer;
import com.android.server.net.IpConfigStore;
import com.android.server.wifi.util.NativeUtil;
+import com.android.server.wifi.util.WifiPermissionsUtil;
import com.android.server.wifi.util.XmlUtil;
import com.android.server.wifi.util.XmlUtil.IpConfigurationXmlUtil;
import com.android.server.wifi.util.XmlUtil.WifiConfigurationXmlUtil;
@@ -96,6 +97,7 @@ public class WifiBackupRestore {
private static final String WEP_KEYS_MASK_SEARCH_PATTERN = "(<.*=)(.*)(/>)";
private static final String WEP_KEYS_MASK_REPLACE_PATTERN = "$1*$3";
+ private final WifiPermissionsUtil mWifiPermissionsUtil;
/**
* Verbose logging flag.
*/
@@ -109,6 +111,10 @@ public class WifiBackupRestore {
private byte[] mDebugLastBackupDataRestored;
private byte[] mDebugLastSupplicantBackupDataRestored;
+ public WifiBackupRestore(WifiPermissionsUtil wifiPermissionsUtil) {
+ mWifiPermissionsUtil = wifiPermissionsUtil;
+ }
+
/**
* Retrieve an XML byte stream representing the data that needs to be backed up from the
* provided configurations.
@@ -163,7 +169,9 @@ public class WifiBackupRestore {
if (configuration.isEnterprise() || configuration.isPasspoint()) {
continue;
}
- if (configuration.creatorUid >= Process.FIRST_APPLICATION_UID) {
+ if (!mWifiPermissionsUtil.checkConfigOverridePermission(configuration.creatorUid)) {
+ Log.d(TAG, "Ignoring network from an app with no config override permission: "
+ + configuration.configKey());
continue;
}
// Write this configuration data now.
@@ -702,6 +710,8 @@ public class WifiBackupRestore {
Integer.parseInt(extras.get(
SupplicantStaNetworkHal.ID_STRING_KEY_CREATOR_UID));
if (creatorUid >= Process.FIRST_APPLICATION_UID) {
+ Log.d(TAG, "Ignoring network from non-system app: "
+ + configuration.configKey());
return null;
}
}
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/WifiInjector.java b/service/java/com/android/server/wifi/WifiInjector.java
index 90e400cc1..c51778578 100644
--- a/service/java/com/android/server/wifi/WifiInjector.java
+++ b/service/java/com/android/server/wifi/WifiInjector.java
@@ -96,7 +96,7 @@ public class WifiInjector {
private final PropertyService mPropertyService = new SystemPropertyService();
private final BuildProperties mBuildProperties = new SystemBuildProperties();
private final KeyStore mKeyStore = KeyStore.getInstance();
- private final WifiBackupRestore mWifiBackupRestore = new WifiBackupRestore();
+ private final WifiBackupRestore mWifiBackupRestore;
private final WifiMulticastLockManager mWifiMulticastLockManager;
private final WifiConfigStore mWifiConfigStore;
private final WifiKeyStore mWifiKeyStore;
@@ -150,6 +150,7 @@ public class WifiInjector {
mWifiNetworkScoreCache, NetworkScoreManager.CACHE_FILTER_NONE);
mWifiPermissionsUtil = new WifiPermissionsUtil(mWifiPermissionsWrapper, mContext,
mSettingsStore, UserManager.get(mContext), mNetworkScoreManager, this);
+ mWifiBackupRestore = new WifiBackupRestore(mWifiPermissionsUtil);
mBatteryStats = IBatteryStats.Stub.asInterface(mFrameworkFacade.getService(
BatteryStats.SERVICE_NAME));
mWifiStateTracker = new WifiStateTracker(mBatteryStats);
diff --git a/service/java/com/android/server/wifi/WifiMonitor.java b/service/java/com/android/server/wifi/WifiMonitor.java
index 385bfccaa..b2fc56e25 100644
--- a/service/java/com/android/server/wifi/WifiMonitor.java
+++ b/service/java/com/android/server/wifi/WifiMonitor.java
@@ -179,9 +179,9 @@ public class WifiMonitor {
if (mConnected) {
return true;
}
- if (connectTries++ < 5) {
+ if (connectTries++ < 50) {
try {
- Thread.sleep(1000);
+ Thread.sleep(100);
} catch (InterruptedException ignore) {
}
} else {
diff --git a/service/java/com/android/server/wifi/WifiServiceImpl.java b/service/java/com/android/server/wifi/WifiServiceImpl.java
index ec05f7cec..7711e91c5 100644
--- a/service/java/com/android/server/wifi/WifiServiceImpl.java
+++ b/service/java/com/android/server/wifi/WifiServiceImpl.java
@@ -18,6 +18,8 @@ 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;
@@ -26,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;
@@ -485,13 +485,17 @@ 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);
final int errorCode = intent.getIntExtra(EXTRA_WIFI_AP_FAILURE_REASON,
HOTSPOT_NO_ERROR);
- handleWifiApStateChange(currentState, prevState, errorCode);
+ final String ifaceName =
+ intent.getStringExtra(EXTRA_WIFI_AP_INTERFACE_NAME);
+ 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));
@@ -818,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");
}
@@ -892,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:
@@ -930,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);
+ }
}
/**
@@ -948,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");
@@ -966,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();
+ }
}
/**
@@ -981,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;
}
@@ -993,10 +1004,12 @@ public class WifiServiceImpl extends IWifiManager.Stub {
/**
* Private method to handle SoftAp state changes
*/
- private void handleWifiApStateChange(int currentState, int previousState, int errorCode) {
+ private void handleWifiApStateChange(
+ 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);
+ + " previousState=" + previousState + " errorCode= " + errorCode
+ + " 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
@@ -1050,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
}
@@ -1069,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
}
@@ -1179,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);
@@ -2383,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)) {
@@ -2495,8 +2511,7 @@ public class WifiServiceImpl extends IWifiManager.Stub {
*/
@Override
public byte[] retrieveBackupData() {
- enforceReadCredentialPermission();
- enforceAccessPermission();
+ enforceNetworkSettingsPermission();
mLog.trace("retrieveBackupData uid=%").c(Binder.getCallingUid()).flush();
if (mWifiStateMachineChannel == null) {
Slog.e(TAG, "mWifiStateMachineChannel is not initialized");
@@ -2541,7 +2556,7 @@ public class WifiServiceImpl extends IWifiManager.Stub {
*/
@Override
public void restoreBackupData(byte[] data) {
- enforceChangePermission();
+ enforceNetworkSettingsPermission();
mLog.trace("restoreBackupData uid=%").c(Binder.getCallingUid()).flush();
if (mWifiStateMachineChannel == null) {
Slog.e(TAG, "mWifiStateMachineChannel is not initialized");
@@ -2563,7 +2578,7 @@ public class WifiServiceImpl extends IWifiManager.Stub {
* @param ipConfigData Raw byte stream of ipconfig.txt
*/
public void restoreSupplicantBackupData(byte[] supplicantData, byte[] ipConfigData) {
- enforceChangePermission();
+ enforceNetworkSettingsPermission();
mLog.trace("restoreSupplicantBackupData uid=%").c(Binder.getCallingUid()).flush();
if (mWifiStateMachineChannel == null) {
Slog.e(TAG, "mWifiStateMachineChannel is not initialized");
diff --git a/service/java/com/android/server/wifi/WifiStateMachine.java b/service/java/com/android/server/wifi/WifiStateMachine.java
index 7f57316a6..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,7 +2806,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss
mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
}
- private void setWifiApState(int wifiApState, int reason) {
+ private void setWifiApState(int wifiApState, int reason, String ifaceName, int mode) {
final int previousWifiApState = mWifiApState.get();
try {
@@ -2833,6 +2833,12 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss
intent.putExtra(WifiManager.EXTRA_WIFI_AP_FAILURE_REASON, reason);
}
+ if (ifaceName == null) {
+ loge("Updating wifiApState with a null iface name");
+ }
+ intent.putExtra(WifiManager.EXTRA_WIFI_AP_INTERFACE_NAME, ifaceName);
+ intent.putExtra(WifiManager.EXTRA_WIFI_AP_MODE, mode);
+
mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
}
@@ -4277,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;
@@ -6667,6 +6674,8 @@ 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
@@ -6677,7 +6686,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss
sendMessage(CMD_START_AP_FAILURE);
}
- setWifiApState(state, reason);
+ setWifiApState(state, reason, mIfaceName, mMode);
}
}
@@ -6687,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.
@@ -6700,13 +6711,19 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss
return;
}
- WifiConfiguration config = (WifiConfiguration) message.obj;
+ try {
+ mIfaceName = apInterface.getInterfaceName();
+ } catch (RemoteException e) {
+ // Failed to get the interface name. The name will not be available for
+ // the enabled broadcast, but since we had an error getting the name, we most likely
+ // won't be able to fully start softap mode.
+ }
checkAndSetConnectivityInstance();
mSoftApManager = mWifiInjector.makeSoftApManager(mNwService,
new SoftApListener(),
apInterface,
- config);
+ config.getWifiConfiguration());
mSoftApManager.start();
mWifiStateTracker.updateState(WifiStateTracker.SOFT_AP);
}
@@ -6714,6 +6731,8 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss
@Override
public void exit() {
mSoftApManager = null;
+ mIfaceName = null;
+ mMode = WifiManager.IFACE_IP_MODE_UNSPECIFIED;
}
@Override
diff --git a/service/java/com/android/server/wifi/p2p/WifiP2pMonitor.java b/service/java/com/android/server/wifi/p2p/WifiP2pMonitor.java
index 0411f3073..e14c10c91 100644
--- a/service/java/com/android/server/wifi/p2p/WifiP2pMonitor.java
+++ b/service/java/com/android/server/wifi/p2p/WifiP2pMonitor.java
@@ -158,9 +158,9 @@ public class WifiP2pMonitor {
if (mConnected) {
return true;
}
- if (connectTries++ < 5) {
+ if (connectTries++ < 50) {
try {
- Thread.sleep(1000);
+ Thread.sleep(100);
} catch (InterruptedException ignore) {
}
} else {
diff --git a/service/java/com/android/server/wifi/scanner/WifiScanningServiceImpl.java b/service/java/com/android/server/wifi/scanner/WifiScanningServiceImpl.java
index 771e336d5..08c9e1359 100644
--- a/service/java/com/android/server/wifi/scanner/WifiScanningServiceImpl.java
+++ b/service/java/com/android/server/wifi/scanner/WifiScanningServiceImpl.java
@@ -447,7 +447,6 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub {
private RequestList<ScanSettings> mActiveScans = new RequestList<>();
private RequestList<ScanSettings> mPendingScans = new RequestList<>();
- // Scan results cached from the last full single scan request.
private ScanResult[] mCachedScanResults = new ScanResult[0];
WifiSingleScanStateMachine(Looper looper) {
@@ -880,11 +879,8 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub {
entry.reportEvent(WifiScanner.CMD_SCAN_RESULT, 0, parcelableAllResults);
}
- // Since we use NoBandChannelHelper, as long as a specific band is mentioned, the scan
- // request is treated as full band (WifiScanner.WIFI_BAND_*).
- if (results.isAllChannelsScanned()) {
- mCachedScanResults = results.getResults();
- }
+ // Cache the results here so that apps can retrieve them.
+ mCachedScanResults = results.getResults();
sendScanResultBroadcast(true);
}
diff --git a/service/java/com/android/server/wifi/scanner/WificondScannerImpl.java b/service/java/com/android/server/wifi/scanner/WificondScannerImpl.java
index b088cc01d..4aa9bc972 100644
--- a/service/java/com/android/server/wifi/scanner/WificondScannerImpl.java
+++ b/service/java/com/android/server/wifi/scanner/WificondScannerImpl.java
@@ -563,6 +563,16 @@ public class WificondScannerImpl extends WifiScannerImpl implements Handler.Call
}
mLastScanSettings.pnoScanEventHandler.onPnoNetworkFound(pnoScanResultsArray);
}
+ // On pno scan result event, we are expecting a mLastScanSettings for pno scan.
+ // However, if unlikey mLastScanSettings is for single scan, we need this part
+ // to protect from leaving WifiSingleScanStateMachine in a forever wait state.
+ if (mLastScanSettings.singleScanActive
+ && mLastScanSettings.singleScanEventHandler != null) {
+ Log.w(TAG, "Polling pno scan result when single scan is active, reporting"
+ + " single scan failure");
+ mLastScanSettings.singleScanEventHandler
+ .onScanStatus(WifiNative.WIFI_SCAN_FAILED);
+ }
// mLastScanSettings is for either single/batched scan or pno scan.
// We can safely set it to null when pno scan finishes.
mLastScanSettings = null;
diff --git a/tests/wifitests/src/com/android/server/wifi/SavedNetworkEvaluatorTest.java b/tests/wifitests/src/com/android/server/wifi/SavedNetworkEvaluatorTest.java
index 78a3a3d0f..7f6360408 100644
--- a/tests/wifitests/src/com/android/server/wifi/SavedNetworkEvaluatorTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/SavedNetworkEvaluatorTest.java
@@ -172,6 +172,33 @@ public class SavedNetworkEvaluatorTest {
}
/**
+ * Do not evaluate networks that {@link WifiConfiguration#isEphemeral}.
+ */
+ @Test
+ public void ignoreEphemeralNetworks() {
+ String[] ssids = {"\"test1\"", "\"test2\""};
+ String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"};
+ int[] freqs = {2470, 2437};
+ String[] caps = {"[ESS]", "[ESS]"};
+ int[] levels = {mThresholdQualifiedRssi2G + 8, mThresholdQualifiedRssi2G + 10};
+ int[] securities = {SECURITY_NONE, SECURITY_NONE};
+
+ ScanDetailsAndWifiConfigs scanDetailsAndConfigs =
+ WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids,
+ freqs, caps, levels, securities, mWifiConfigManager, mClock);
+ List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails();
+ WifiConfiguration[] savedConfigs = scanDetailsAndConfigs.getWifiConfigs();
+ for (WifiConfiguration wifiConfiguration : savedConfigs) {
+ wifiConfiguration.ephemeral = true;
+ }
+
+ WifiConfiguration candidate = mSavedNetworkEvaluator.evaluateNetworks(scanDetails,
+ null, null, true, false, null);
+
+ assertNull(candidate);
+ }
+
+ /**
* Set the candidate {@link ScanResult} for all {@link WifiConfiguration}s regardless of
* whether they are secure saved, open saved, or {@link WifiConfiguration#useExternalScores}.
*/
diff --git a/tests/wifitests/src/com/android/server/wifi/TestUtil.java b/tests/wifitests/src/com/android/server/wifi/TestUtil.java
index 90df07a61..a0a103026 100644
--- a/tests/wifitests/src/com/android/server/wifi/TestUtil.java
+++ b/tests/wifitests/src/com/android/server/wifi/TestUtil.java
@@ -74,14 +74,18 @@ public class TestUtil {
* Send {@link WifiManager#WIFI_AP_STATE_CHANGED} broadcast.
*/
public static void sendWifiApStateChanged(BroadcastReceiver broadcastReceiver,
- Context context, int apState, int previousState, int error) {
+ Context context, int apState, int previousState, int error, String ifaceName,
+ int mode) {
Intent intent = new Intent(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
intent.putExtra(WifiManager.EXTRA_WIFI_AP_STATE, apState);
intent.putExtra(WifiManager.EXTRA_PREVIOUS_WIFI_AP_STATE, previousState);
if (apState == WifiManager.WIFI_AP_STATE_FAILED) {
- //only set reason number when softAP start failed
+ // only set reason number when softAP start failed
intent.putExtra(WifiManager.EXTRA_WIFI_AP_FAILURE_REASON, error);
}
+ intent.putExtra(WifiManager.EXTRA_WIFI_AP_INTERFACE_NAME, ifaceName);
+ intent.putExtra(WifiManager.EXTRA_WIFI_AP_MODE, mode);
+
broadcastReceiver.onReceive(context, intent);
}
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiApConfigStoreTest.java b/tests/wifitests/src/com/android/server/wifi/WifiApConfigStoreTest.java
index d4a3ff549..2d3b06695 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiApConfigStoreTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiApConfigStoreTest.java
@@ -202,5 +202,7 @@ public class WifiApConfigStoreTest {
public void generateLocalOnlyHotspotConfigIsValid() {
WifiConfiguration config = WifiApConfigStore.generateLocalOnlyHotspotConfig(mContext);
verifyDefaultApConfig(config, TEST_DEFAULT_HOTSPOT_SSID);
+ // The LOHS config should also have a specific network id set - check that as well.
+ assertEquals(WifiConfiguration.LOCAL_ONLY_NETWORK_ID, config.networkId);
}
}
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiBackupRestoreTest.java b/tests/wifitests/src/com/android/server/wifi/WifiBackupRestoreTest.java
index 362540517..58b8d394b 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiBackupRestoreTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiBackupRestoreTest.java
@@ -24,10 +24,13 @@ import android.os.Process;
import android.test.suitebuilder.annotation.SmallTest;
import com.android.server.net.IpConfigStore;
+import com.android.server.wifi.util.WifiPermissionsUtil;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
@@ -48,11 +51,15 @@ import java.util.Random;
@SmallTest
public class WifiBackupRestoreTest {
- private final WifiBackupRestore mWifiBackupRestore = new WifiBackupRestore();
+ @Mock WifiPermissionsUtil mWifiPermissionsUtil;
+ private WifiBackupRestore mWifiBackupRestore;
private boolean mCheckDump = true;
@Before
public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ when(mWifiPermissionsUtil.checkConfigOverridePermission(anyInt())).thenReturn(true);
+ mWifiBackupRestore = new WifiBackupRestore(mWifiPermissionsUtil);
// Enable verbose logging before tests to check the backup data dumps.
mWifiBackupRestore.enableVerboseLogging(1);
}
@@ -361,25 +368,34 @@ public class WifiBackupRestoreTest {
*/
@Test
public void testMultipleNetworksSystemAppBackupRestore() {
+ int systemAppUid = Process.SYSTEM_UID;
+ int nonSystemAppUid = Process.FIRST_APPLICATION_UID + 556;
+ when(mWifiPermissionsUtil.checkConfigOverridePermission(eq(systemAppUid)))
+ .thenReturn(true);
+ when(mWifiPermissionsUtil.checkConfigOverridePermission(eq(nonSystemAppUid)))
+ .thenReturn(false);
+
List<WifiConfiguration> configurations = new ArrayList<>();
List<WifiConfiguration> expectedConfigurations = new ArrayList<>();
WifiConfiguration wepNetwork = WifiConfigurationTestUtil.createWepNetwork();
+ wepNetwork.creatorUid = systemAppUid;
configurations.add(wepNetwork);
expectedConfigurations.add(wepNetwork);
// These should not be in |expectedConfigurations|.
WifiConfiguration nonSystemAppWepNetwork = WifiConfigurationTestUtil.createWepNetwork();
- nonSystemAppWepNetwork.creatorUid = Process.FIRST_APPLICATION_UID;
+ nonSystemAppWepNetwork.creatorUid = nonSystemAppUid;
configurations.add(nonSystemAppWepNetwork);
WifiConfiguration pskNetwork = WifiConfigurationTestUtil.createPskNetwork();
+ pskNetwork.creatorUid = systemAppUid;
configurations.add(pskNetwork);
expectedConfigurations.add(pskNetwork);
// These should not be in |expectedConfigurations|.
WifiConfiguration nonSystemAppPskNetwork = WifiConfigurationTestUtil.createPskNetwork();
- nonSystemAppPskNetwork.creatorUid = Process.FIRST_APPLICATION_UID + 1;
+ nonSystemAppPskNetwork.creatorUid = nonSystemAppUid;
configurations.add(nonSystemAppPskNetwork);
WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork();
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java b/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java
index 7342cdb16..45ffa8c04 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java
@@ -97,6 +97,7 @@ import org.mockito.Spy;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.io.StringWriter;
+import java.util.List;
/**
* Unit tests for {@link WifiServiceImpl}.
@@ -132,6 +133,8 @@ public class WifiServiceImplTest {
ArgumentCaptor.forClass(IntentFilter.class);
final ArgumentCaptor<Message> mMessageCaptor = ArgumentCaptor.forClass(Message.class);
+ final ArgumentCaptor<SoftApModeConfiguration> mSoftApModeConfigCaptor =
+ ArgumentCaptor.forClass(SoftApModeConfiguration.class);
@Mock Context mContext;
@Mock WifiInjector mWifiInjector;
@@ -534,7 +537,9 @@ public class WifiServiceImplTest {
when(mUserManager.hasUserRestriction(eq(UserManager.DISALLOW_CONFIG_TETHERING)))
.thenReturn(false);
mWifiServiceImpl.setWifiApEnabled(null, true);
- verify(mWifiController).sendMessage(eq(CMD_SET_AP), eq(1), eq(0), eq(null));
+ verify(mWifiController)
+ .sendMessage(eq(CMD_SET_AP), eq(1), eq(0), mSoftApModeConfigCaptor.capture());
+ assertNull(mSoftApModeConfigCaptor.getValue().getWifiConfiguration());
}
/**
@@ -549,7 +554,9 @@ public class WifiServiceImplTest {
.thenReturn(false);
WifiConfiguration apConfig = new WifiConfiguration();
mWifiServiceImpl.setWifiApEnabled(apConfig, true);
- verify(mWifiController).sendMessage(eq(CMD_SET_AP), eq(1), eq(0), eq(apConfig));
+ verify(mWifiController).sendMessage(
+ eq(CMD_SET_AP), eq(1), eq(0), mSoftApModeConfigCaptor.capture());
+ assertEquals(apConfig, mSoftApModeConfigCaptor.getValue().getWifiConfiguration());
}
/**
@@ -562,7 +569,9 @@ public class WifiServiceImplTest {
when(mUserManager.hasUserRestriction(eq(UserManager.DISALLOW_CONFIG_TETHERING)))
.thenReturn(false);
mWifiServiceImpl.setWifiApEnabled(null, false);
- verify(mWifiController).sendMessage(eq(CMD_SET_AP), eq(0), eq(0), eq(null));
+ verify(mWifiController)
+ .sendMessage(eq(CMD_SET_AP), eq(0), eq(0), mSoftApModeConfigCaptor.capture());
+ assertNull(mSoftApModeConfigCaptor.getValue().getWifiConfiguration());
}
/**
@@ -576,7 +585,8 @@ public class WifiServiceImplTest {
// mApConfig is a mock and the values are not set - triggering the invalid config. Testing
// will be improved when we actually do test softap configs in b/37280779
mWifiServiceImpl.setWifiApEnabled(mApConfig, true);
- verify(mWifiController, never()).sendMessage(eq(CMD_SET_AP), eq(1), eq(0), eq(mApConfig));
+ verify(mWifiController, never())
+ .sendMessage(eq(CMD_SET_AP), eq(1), eq(0), any(SoftApModeConfiguration.class));
}
/**
@@ -613,7 +623,9 @@ public class WifiServiceImplTest {
public void testStartSoftApWithPermissionsAndNullConfig() {
boolean result = mWifiServiceImpl.startSoftAp(null);
assertTrue(result);
- verify(mWifiController).sendMessage(eq(CMD_SET_AP), eq(1), eq(0), eq(null));
+ verify(mWifiController)
+ .sendMessage(eq(CMD_SET_AP), eq(1), eq(0), mSoftApModeConfigCaptor.capture());
+ assertNull(mSoftApModeConfigCaptor.getValue().getWifiConfiguration());
}
/**
@@ -634,7 +646,9 @@ public class WifiServiceImplTest {
WifiConfiguration config = new WifiConfiguration();
boolean result = mWifiServiceImpl.startSoftAp(config);
assertTrue(result);
- verify(mWifiController).sendMessage(eq(CMD_SET_AP), eq(1), eq(0), eq(config));
+ verify(mWifiController)
+ .sendMessage(eq(CMD_SET_AP), eq(1), eq(0), mSoftApModeConfigCaptor.capture());
+ assertEquals(config, mSoftApModeConfigCaptor.getValue().getWifiConfiguration());
}
/**
@@ -874,7 +888,7 @@ public class WifiServiceImplTest {
public void testStopLocalOnlyHotspotTriggersSoftApStopWithOneRegisteredRequest() {
registerLOHSRequestFull();
verify(mWifiController)
- .sendMessage(eq(CMD_SET_AP), eq(1), eq(0), any(WifiConfiguration.class));
+ .sendMessage(eq(CMD_SET_AP), eq(1), eq(0), any(SoftApModeConfiguration.class));
mWifiServiceImpl.stopLocalOnlyHotspot();
// there is was only one request registered, we should tear down softap
@@ -957,7 +971,8 @@ public class WifiServiceImplTest {
registerLOHSRequestFull();
TestUtil.sendWifiApStateChanged(mBroadcastReceiverCaptor.getValue(), mContext,
- WIFI_AP_STATE_FAILED, WIFI_AP_STATE_DISABLED, SAP_START_FAILURE_GENERAL);
+ WIFI_AP_STATE_FAILED, WIFI_AP_STATE_DISABLED, SAP_START_FAILURE_GENERAL,
+ WIFI_IFACE_NAME, IFACE_IP_MODE_LOCAL_ONLY);
mLooper.dispatchAll();
verify(mHandler).handleMessage(mMessageCaptor.capture());
Message message = mMessageCaptor.getValue();
@@ -981,7 +996,8 @@ public class WifiServiceImplTest {
registerLOHSRequestFull();
TestUtil.sendWifiApStateChanged(mBroadcastReceiverCaptor.getValue(), mContext,
- WIFI_AP_STATE_FAILED, WIFI_AP_STATE_DISABLED, SAP_START_FAILURE_NO_CHANNEL);
+ WIFI_AP_STATE_FAILED, WIFI_AP_STATE_DISABLED, SAP_START_FAILURE_NO_CHANNEL,
+ WIFI_IFACE_NAME, IFACE_IP_MODE_LOCAL_ONLY);
mLooper.dispatchAll();
verify(mHandler).handleMessage(mMessageCaptor.capture());
@@ -1013,7 +1029,8 @@ public class WifiServiceImplTest {
reset(mHandler);
TestUtil.sendWifiApStateChanged(mBroadcastReceiverCaptor.getValue(), mContext,
- WIFI_AP_STATE_DISABLING, WIFI_AP_STATE_ENABLED, HOTSPOT_NO_ERROR);
+ WIFI_AP_STATE_DISABLING, WIFI_AP_STATE_ENABLED, HOTSPOT_NO_ERROR,
+ WIFI_IFACE_NAME, IFACE_IP_MODE_LOCAL_ONLY);
mLooper.dispatchAll();
verify(mHandler).handleMessage(mMessageCaptor.capture());
@@ -1045,7 +1062,8 @@ public class WifiServiceImplTest {
reset(mHandler);
TestUtil.sendWifiApStateChanged(mBroadcastReceiverCaptor.getValue(), mContext,
- WIFI_AP_STATE_DISABLED, WIFI_AP_STATE_DISABLING, HOTSPOT_NO_ERROR);
+ WIFI_AP_STATE_DISABLED, WIFI_AP_STATE_DISABLING, HOTSPOT_NO_ERROR,
+ WIFI_IFACE_NAME, IFACE_IP_MODE_LOCAL_ONLY);
mLooper.dispatchAll();
verify(mHandler).handleMessage(mMessageCaptor.capture());
@@ -1069,7 +1087,8 @@ public class WifiServiceImplTest {
registerLOHSRequestFull();
TestUtil.sendWifiApStateChanged(mBroadcastReceiverCaptor.getValue(), mContext,
- WIFI_AP_STATE_ENABLED, WIFI_AP_STATE_DISABLED, HOTSPOT_NO_ERROR);
+ WIFI_AP_STATE_ENABLED, WIFI_AP_STATE_DISABLED, HOTSPOT_NO_ERROR, WIFI_IFACE_NAME,
+ IFACE_IP_MODE_LOCAL_ONLY);
mLooper.dispatchAll();
verifyNoMoreInteractions(mHandler);
@@ -1099,9 +1118,11 @@ public class WifiServiceImplTest {
reset(mHandler);
TestUtil.sendWifiApStateChanged(mBroadcastReceiverCaptor.getValue(), mContext,
- WIFI_AP_STATE_DISABLING, WIFI_AP_STATE_ENABLED, HOTSPOT_NO_ERROR);
+ WIFI_AP_STATE_DISABLING, WIFI_AP_STATE_ENABLED, HOTSPOT_NO_ERROR,
+ WIFI_IFACE_NAME, IFACE_IP_MODE_LOCAL_ONLY);
TestUtil.sendWifiApStateChanged(mBroadcastReceiverCaptor.getValue(), mContext,
- WIFI_AP_STATE_DISABLED, WIFI_AP_STATE_DISABLING, HOTSPOT_NO_ERROR);
+ WIFI_AP_STATE_DISABLED, WIFI_AP_STATE_DISABLING, HOTSPOT_NO_ERROR,
+ WIFI_IFACE_NAME, IFACE_IP_MODE_LOCAL_ONLY);
mLooper.dispatchAll();
verify(mHandler).handleMessage(mMessageCaptor.capture());
@@ -1125,9 +1146,11 @@ public class WifiServiceImplTest {
registerLOHSRequestFull();
TestUtil.sendWifiApStateChanged(mBroadcastReceiverCaptor.getValue(), mContext,
- WIFI_AP_STATE_FAILED, WIFI_AP_STATE_FAILED, ERROR_GENERIC);
+ WIFI_AP_STATE_FAILED, WIFI_AP_STATE_FAILED, ERROR_GENERIC,
+ WIFI_IFACE_NAME, IFACE_IP_MODE_LOCAL_ONLY);
TestUtil.sendWifiApStateChanged(mBroadcastReceiverCaptor.getValue(), mContext,
- WIFI_AP_STATE_FAILED, WIFI_AP_STATE_FAILED, ERROR_GENERIC);
+ WIFI_AP_STATE_FAILED, WIFI_AP_STATE_FAILED, ERROR_GENERIC,
+ WIFI_IFACE_NAME, IFACE_IP_MODE_LOCAL_ONLY);
mLooper.dispatchAll();
verify(mHandler).handleMessage(mMessageCaptor.capture());
@@ -1155,9 +1178,11 @@ public class WifiServiceImplTest {
registerLOHSRequestFull();
TestUtil.sendWifiApStateChanged(mBroadcastReceiverCaptor.getValue(), mContext,
- WIFI_AP_STATE_FAILED, WIFI_AP_STATE_FAILED, ERROR_GENERIC);
+ WIFI_AP_STATE_FAILED, WIFI_AP_STATE_FAILED, ERROR_GENERIC,
+ WIFI_IFACE_NAME, IFACE_IP_MODE_LOCAL_ONLY);
TestUtil.sendWifiApStateChanged(mBroadcastReceiverCaptor.getValue(), mContext,
- WIFI_AP_STATE_FAILED, WIFI_AP_STATE_FAILED, ERROR_GENERIC);
+ WIFI_AP_STATE_FAILED, WIFI_AP_STATE_FAILED, ERROR_GENERIC,
+ WIFI_IFACE_NAME, IFACE_IP_MODE_LOCAL_ONLY);
verify(mRequestInfo).sendHotspotFailedMessage(ERROR_GENERIC);
mLooper.dispatchAll();
@@ -1194,9 +1219,11 @@ public class WifiServiceImplTest {
reset(mHandler);
TestUtil.sendWifiApStateChanged(mBroadcastReceiverCaptor.getValue(), mContext,
- WIFI_AP_STATE_DISABLING, WIFI_AP_STATE_ENABLED, HOTSPOT_NO_ERROR);
+ WIFI_AP_STATE_DISABLING, WIFI_AP_STATE_ENABLED, HOTSPOT_NO_ERROR,
+ WIFI_IFACE_NAME, IFACE_IP_MODE_LOCAL_ONLY);
TestUtil.sendWifiApStateChanged(mBroadcastReceiverCaptor.getValue(), mContext,
- WIFI_AP_STATE_DISABLED, WIFI_AP_STATE_DISABLING, HOTSPOT_NO_ERROR);
+ WIFI_AP_STATE_DISABLED, WIFI_AP_STATE_DISABLING, HOTSPOT_NO_ERROR,
+ WIFI_IFACE_NAME, IFACE_IP_MODE_LOCAL_ONLY);
verify(mRequestInfo).sendHotspotStoppedMessage();
mLooper.dispatchAll();
@@ -1223,9 +1250,11 @@ public class WifiServiceImplTest {
mWifiServiceImpl.registerLOHSForTest(TEST_PID2, mRequestInfo2);
TestUtil.sendWifiApStateChanged(mBroadcastReceiverCaptor.getValue(), mContext,
- WIFI_AP_STATE_DISABLING, WIFI_AP_STATE_ENABLED, HOTSPOT_NO_ERROR);
+ WIFI_AP_STATE_DISABLING, WIFI_AP_STATE_ENABLED, HOTSPOT_NO_ERROR,
+ WIFI_IFACE_NAME, IFACE_IP_MODE_LOCAL_ONLY);
TestUtil.sendWifiApStateChanged(mBroadcastReceiverCaptor.getValue(), mContext,
- WIFI_AP_STATE_DISABLED, WIFI_AP_STATE_DISABLING, HOTSPOT_NO_ERROR);
+ WIFI_AP_STATE_DISABLED, WIFI_AP_STATE_DISABLING, HOTSPOT_NO_ERROR,
+ WIFI_IFACE_NAME, IFACE_IP_MODE_LOCAL_ONLY);
verify(mRequestInfo).sendHotspotFailedMessage(ERROR_GENERIC);
verify(mRequestInfo2).sendHotspotFailedMessage(ERROR_GENERIC);
@@ -1383,9 +1412,11 @@ public class WifiServiceImplTest {
// now stop the hotspot
TestUtil.sendWifiApStateChanged(mBroadcastReceiverCaptor.getValue(), mContext,
- WIFI_AP_STATE_DISABLING, WIFI_AP_STATE_ENABLED, HOTSPOT_NO_ERROR);
+ WIFI_AP_STATE_DISABLING, WIFI_AP_STATE_ENABLED, HOTSPOT_NO_ERROR,
+ WIFI_IFACE_NAME, IFACE_IP_MODE_LOCAL_ONLY);
TestUtil.sendWifiApStateChanged(mBroadcastReceiverCaptor.getValue(), mContext,
- WIFI_AP_STATE_DISABLED, WIFI_AP_STATE_DISABLING, HOTSPOT_NO_ERROR);
+ WIFI_AP_STATE_DISABLED, WIFI_AP_STATE_DISABLING, HOTSPOT_NO_ERROR,
+ WIFI_IFACE_NAME, IFACE_IP_MODE_LOCAL_ONLY);
mLooper.dispatchAll();
verify(mHandler).handleMessage(mMessageCaptor.capture());
assertEquals(HOTSPOT_STOPPED, mMessageCaptor.getValue().what);
@@ -1473,4 +1504,44 @@ public class WifiServiceImplTest {
verify(mWifiStateMachine).syncAddOrUpdatePasspointConfig(any(),
any(PasspointConfiguration.class), anyInt());
}
+
+ /**
+ * Verify that a call to {@link WifiServiceImpl#restoreBackupData(byte[])} is only allowed from
+ * callers with the signature only NETWORK_SETTINGS permission.
+ */
+ @Test(expected = SecurityException.class)
+ public void testRestoreBackupDataNotApprovedCaller() {
+ doThrow(new SecurityException()).when(mContext)
+ .enforceCallingOrSelfPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
+ eq("WifiService"));
+ mWifiServiceImpl.restoreBackupData(null);
+ verify(mWifiBackupRestore, never()).retrieveConfigurationsFromBackupData(any(byte[].class));
+ }
+
+ /**
+ * Verify that a call to {@link WifiServiceImpl#restoreSupplicantBackupData(byte[], byte[])} is
+ * only allowed from callers with the signature only NETWORK_SETTINGS permission.
+ */
+ @Test(expected = SecurityException.class)
+ public void testRestoreSupplicantBackupDataNotApprovedCaller() {
+ doThrow(new SecurityException()).when(mContext)
+ .enforceCallingOrSelfPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
+ eq("WifiService"));
+ mWifiServiceImpl.restoreSupplicantBackupData(null, null);
+ verify(mWifiBackupRestore, never()).retrieveConfigurationsFromSupplicantBackupData(
+ any(byte[].class), any(byte[].class));
+ }
+
+ /**
+ * Verify that a call to {@link WifiServiceImpl#retrieveBackupData()} is only allowed from
+ * callers with the signature only NETWORK_SETTINGS permission.
+ */
+ @Test(expected = SecurityException.class)
+ public void testRetrieveBackupDataNotApprovedCaller() {
+ doThrow(new SecurityException()).when(mContext)
+ .enforceCallingOrSelfPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
+ eq("WifiService"));
+ mWifiServiceImpl.retrieveBackupData();
+ verify(mWifiBackupRestore, never()).retrieveBackupDataFromConfigurations(any(List.class));
+ }
}
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiStateMachineTest.java b/tests/wifitests/src/com/android/server/wifi/WifiStateMachineTest.java
index be9b0c544..2a30b671b 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiStateMachineTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiStateMachineTest.java
@@ -16,6 +16,18 @@
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.WIFI_AP_STATE_DISABLED;
+import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLING;
+import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLED;
+import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLING;
+
+import static com.android.server.wifi.LocalOnlyHotspotRequestInfo.HOTSPOT_NO_ERROR;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
@@ -303,6 +315,7 @@ public class WifiStateMachineTest {
static final String sHexSSID = sWifiSsid.getHexString().replace("0x", "").replace("22", "");
static final String sBSSID = "01:02:03:04:05:06";
static final int sFreq = 2437;
+ static final String WIFI_IFACE_NAME = "mockWlan";
WifiStateMachine mWsm;
HandlerThread mWsmThread;
@@ -315,6 +328,9 @@ public class WifiStateMachineTest {
TestLooper mLooper;
Context mContext;
+ final ArgumentCaptor<SoftApManager.Listener> mSoftApManagerListenerCaptor =
+ ArgumentCaptor.forClass(SoftApManager.Listener.class);
+
@Mock WifiScanner mWifiScanner;
@Mock SupplicantStateTracker mSupplicantStateTracker;
@Mock WifiMetrics mWifiMetrics;
@@ -370,7 +386,7 @@ public class WifiStateMachineTest {
when(mWifiInjector.makeWifiConnectivityManager(any(WifiInfo.class), anyBoolean()))
.thenReturn(mWifiConnectivityManager);
when(mWifiInjector.makeSoftApManager(any(INetworkManagementService.class),
- any(SoftApManager.Listener.class), any(IApInterface.class),
+ mSoftApManagerListenerCaptor.capture(), any(IApInterface.class),
any(WifiConfiguration.class)))
.thenReturn(mSoftApManager);
when(mWifiInjector.getPasspointManager()).thenReturn(mPasspointManager);
@@ -381,7 +397,8 @@ public class WifiStateMachineTest {
when(mWifiNative.setupForClientMode()).thenReturn(mClientInterface);
when(mWifiNative.setupForSoftApMode()).thenReturn(mApInterface);
- when(mWifiNative.getInterfaceName()).thenReturn("mockWlan");
+ when(mApInterface.getInterfaceName()).thenReturn(WIFI_IFACE_NAME);
+ when(mWifiNative.getInterfaceName()).thenReturn(WIFI_IFACE_NAME);
when(mWifiNative.enableSupplicant()).thenReturn(true);
when(mWifiNative.disableSupplicant()).thenReturn(true);
when(mWifiNative.getFrameworkNetworkId(anyInt())).thenReturn(0);
@@ -478,14 +495,64 @@ public class WifiStateMachineTest {
assertEquals("DisconnectedState", getCurrentState().getName());
}
- @Test
- public void loadComponentsInApMode() throws Exception {
- mWsm.setHostApRunning(new WifiConfiguration(), true);
+ private void checkApStateChangedBroadcast(Intent intent, int expectedCurrentState,
+ int expectedPrevState, int expectedErrorCode, String expectedIfaceName,
+ int expectedMode) {
+ int currentState = intent.getIntExtra(EXTRA_WIFI_AP_STATE, WIFI_AP_STATE_DISABLED);
+ int prevState = intent.getIntExtra(EXTRA_PREVIOUS_WIFI_AP_STATE, WIFI_AP_STATE_DISABLED);
+ int errorCode = intent.getIntExtra(EXTRA_WIFI_AP_FAILURE_REASON, HOTSPOT_NO_ERROR);
+ String ifaceName = intent.getStringExtra(EXTRA_WIFI_AP_INTERFACE_NAME);
+ int mode = intent.getIntExtra(EXTRA_WIFI_AP_MODE, WifiManager.IFACE_IP_MODE_UNSPECIFIED);
+ assertEquals(expectedCurrentState, currentState);
+ assertEquals(expectedPrevState, prevState);
+ assertEquals(expectedErrorCode, errorCode);
+ assertEquals(expectedIfaceName, ifaceName);
+ assertEquals(expectedMode, mode);
+ }
+
+ private void loadComponentsInApMode(int mode) throws Exception {
+ SoftApModeConfiguration config = new SoftApModeConfiguration(mode, new WifiConfiguration());
+ mWsm.setHostApRunning(config, true);
mLooper.dispatchAll();
assertEquals("SoftApState", getCurrentState().getName());
verify(mSoftApManager).start();
+
+ // reset expectations for mContext due to previously sent AP broadcast
+ reset(mContext);
+
+ // get the SoftApManager.Listener and trigger some updates
+ SoftApManager.Listener listener = mSoftApManagerListenerCaptor.getValue();
+ listener.onStateChanged(WIFI_AP_STATE_ENABLING, 0);
+ listener.onStateChanged(WIFI_AP_STATE_ENABLED, 0);
+ listener.onStateChanged(WIFI_AP_STATE_DISABLING, 0);
+ // note, this will trigger a mode change when TestLooper is dispatched
+ listener.onStateChanged(WIFI_AP_STATE_DISABLED, 0);
+
+ ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
+ verify(mContext, times(4))
+ .sendStickyBroadcastAsUser(intentCaptor.capture(), eq(UserHandle.ALL));
+
+ List<Intent> capturedIntents = intentCaptor.getAllValues();
+ checkApStateChangedBroadcast(capturedIntents.get(0), WIFI_AP_STATE_ENABLING,
+ WIFI_AP_STATE_DISABLED, HOTSPOT_NO_ERROR, WIFI_IFACE_NAME, mode);
+ checkApStateChangedBroadcast(capturedIntents.get(1), WIFI_AP_STATE_ENABLED,
+ WIFI_AP_STATE_ENABLING, HOTSPOT_NO_ERROR, WIFI_IFACE_NAME, mode);
+ checkApStateChangedBroadcast(capturedIntents.get(2), WIFI_AP_STATE_DISABLING,
+ WIFI_AP_STATE_ENABLED, HOTSPOT_NO_ERROR, WIFI_IFACE_NAME, mode);
+ checkApStateChangedBroadcast(capturedIntents.get(3), WIFI_AP_STATE_DISABLED,
+ WIFI_AP_STATE_DISABLING, HOTSPOT_NO_ERROR, WIFI_IFACE_NAME, mode);
+ }
+
+ @Test
+ public void loadComponentsInApModeForTethering() throws Exception {
+ loadComponentsInApMode(WifiManager.IFACE_IP_MODE_TETHERED);
+ }
+
+ @Test
+ public void loadComponentsInApModeForLOHS() throws Exception {
+ loadComponentsInApMode(WifiManager.IFACE_IP_MODE_LOCAL_ONLY);
}
@Test
@@ -609,7 +676,9 @@ public class WifiStateMachineTest {
mWsm.setSupplicantRunning(false);
mWsm.sendMessage(WifiStateMachine.CMD_DISABLE_P2P_RSP);
mWsm.sendMessage(WifiMonitor.SUP_DISCONNECTION_EVENT);
- mWsm.setHostApRunning(new WifiConfiguration(), true);
+ SoftApModeConfiguration config = new SoftApModeConfiguration(
+ WifiManager.IFACE_IP_MODE_TETHERED, new WifiConfiguration());
+ mWsm.setHostApRunning(config, true);
mLooper.dispatchAll();
assertEquals("SoftApState", getCurrentState().getName());
assertEquals(WifiManager.WIFI_STATE_DISABLED, mWsm.syncGetWifiState());
diff --git a/tests/wifitests/src/com/android/server/wifi/scanner/WifiScanningServiceTest.java b/tests/wifitests/src/com/android/server/wifi/scanner/WifiScanningServiceTest.java
index d9fbb1d28..e7c5fa962 100644
--- a/tests/wifitests/src/com/android/server/wifi/scanner/WifiScanningServiceTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/scanner/WifiScanningServiceTest.java
@@ -1257,10 +1257,10 @@ public class WifiScanningServiceTest {
}
/**
- * Verify that the newest full scan results are returned by WifiService.getSingleScanResults.
+ * Verify that the newest scan results are returned by WifiService.getSingleScanResults.
*/
@Test
- public void retrieveMostRecentFullSingleScanResults() throws Exception {
+ public void retrieveMostRecentSingleScanResults() throws Exception {
WifiScanner.ScanSettings requestSettings = createRequest(WifiScanner.WIFI_BAND_BOTH, 0,
0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
ScanResults expectedResults = ScanResults.create(0, true, 2400, 5150, 5175);
@@ -1312,64 +1312,6 @@ public class WifiScanningServiceTest {
}
/**
- * Verify that the newest partial scan results are not returned by
- * WifiService.getSingleScanResults.
- */
- @Test
- public void doesNotRetrieveMostRecentPartialSingleScanResults() throws Exception {
- WifiScanner.ScanSettings fullRequestSettings = createRequest(WifiScanner.WIFI_BAND_BOTH, 0,
- 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
- ScanResults expectedFullResults = ScanResults.create(0, true, 2400, 5150, 5175);
- doSuccessfulSingleScan(fullRequestSettings,
- computeSingleScanNativeSettings(fullRequestSettings),
- expectedFullResults);
-
- Handler handler = mock(Handler.class);
- BidirectionalAsyncChannel controlChannel = connectChannel(handler);
- InOrder order = inOrder(handler, mWifiScannerImpl);
-
- controlChannel.sendMessage(
- Message.obtain(null, WifiScanner.CMD_GET_SINGLE_SCAN_RESULTS, 0));
- mLooper.dispatchAll();
- Message response = verifyHandleMessageAndGetMessage(order, handler);
-
- List<ScanResult> results = Arrays.asList(
- ((WifiScanner.ParcelableScanResults) response.obj).getResults());
- assertEquals(results.size(), expectedFullResults.getRawScanResults().length);
-
- // now update with a new scan that only has one result
- int secondScanRequestId = 35;
- WifiScanner.ScanSettings partialRequestSettings = createRequest(WifiScanner.WIFI_BAND_BOTH,
- 0, 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
- ScanResults expectedPartialResults = ScanResults.create(0, false, 5150);
- sendSingleScanRequest(controlChannel, secondScanRequestId, partialRequestSettings, null);
-
- mLooper.dispatchAll();
- WifiNative.ScanEventHandler eventHandler = verifyStartSingleScan(order,
- computeSingleScanNativeSettings(partialRequestSettings));
- verifySuccessfulResponse(order, handler, secondScanRequestId);
-
- // dispatch scan 2 results
- when(mWifiScannerImpl.getLatestSingleScanResults())
- .thenReturn(expectedPartialResults.getScanData());
- eventHandler.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
-
- mLooper.dispatchAll();
- verifyScanResultsReceived(order, handler, secondScanRequestId,
- expectedPartialResults.getScanData());
- verifySingleScanCompletedReceived(order, handler, secondScanRequestId);
-
- controlChannel.sendMessage(
- Message.obtain(null, WifiScanner.CMD_GET_SINGLE_SCAN_RESULTS, 0));
- mLooper.dispatchAll();
- Message response2 = verifyHandleMessageAndGetMessage(order, handler);
-
- List<ScanResult> results2 = Arrays.asList(
- ((WifiScanner.ParcelableScanResults) response2.obj).getResults());
- assertEquals(results2.size(), expectedFullResults.getRawScanResults().length);
- }
-
- /**
* Cached scan results should be cleared after the driver is unloaded.
*/
@Test