summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Pasanen <dan.pasanen@gmail.com>2017-04-05 07:54:13 -0500
committerDan Pasanen <dan.pasanen@gmail.com>2017-04-05 12:55:23 -0500
commitf0223d50d12fea721a37481ed0500d6ae6d774b6 (patch)
tree18be3f446cbc4d99df4703dea1683c92a0366c7d
parent2c25264908d020b03fb91ada6a92ce2728ef576f (diff)
parent89c893388a2fe8f9b84dca3dd2ec6c5a793fbea1 (diff)
downloadandroid_frameworks_opt_net_wifi-f0223d50d12fea721a37481ed0500d6ae6d774b6.tar.gz
android_frameworks_opt_net_wifi-f0223d50d12fea721a37481ed0500d6ae6d774b6.tar.bz2
android_frameworks_opt_net_wifi-f0223d50d12fea721a37481ed0500d6ae6d774b6.zip
Merge tag 'android-7.1.2_r2' into cm-14.1staging/cm-14.1_android-7.1.2_r2
Android 7.1.2 Release 2 (N2G47E) Change-Id: Id7bfdf0f54f9f0a7f149b8a1f6f62fe4b791e021
-rw-r--r--service/java/com/android/server/wifi/PropertyService.java7
-rw-r--r--service/java/com/android/server/wifi/SystemPropertyService.java5
-rw-r--r--service/java/com/android/server/wifi/WifiConfigManager.java134
-rw-r--r--service/java/com/android/server/wifi/WifiConfigStore.java45
-rw-r--r--service/java/com/android/server/wifi/WifiController.java4
-rw-r--r--service/java/com/android/server/wifi/WifiQualifiedNetworkSelector.java284
-rwxr-xr-xservice/java/com/android/server/wifi/WifiServiceImpl.java102
-rw-r--r--service/java/com/android/server/wifi/WifiStateMachine.java93
-rw-r--r--service/java/com/android/server/wifi/hotspot2/omadm/OMAParser.java3
-rw-r--r--service/java/com/android/server/wifi/util/ScanDetailUtil.java8
-rw-r--r--tests/wifitests/src/com/android/server/wifi/PasspointManagementObjectManagerTest.java36
-rw-r--r--tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java18
-rw-r--r--tests/wifitests/src/com/android/server/wifi/WifiQualifiedNetworkSelectorTest.java361
-rw-r--r--tests/wifitests/src/com/android/server/wifi/WifiStateMachineTest.java40
14 files changed, 1064 insertions, 76 deletions
diff --git a/service/java/com/android/server/wifi/PropertyService.java b/service/java/com/android/server/wifi/PropertyService.java
index 2895f43df..c998ff955 100644
--- a/service/java/com/android/server/wifi/PropertyService.java
+++ b/service/java/com/android/server/wifi/PropertyService.java
@@ -36,4 +36,11 @@ public interface PropertyService {
* @throws IllegalArgumentException if the value exceeds 92 characters
*/
void set(String key, String val);
+
+ /**
+ * Get the current value of |key|.
+ * @return value of |key|, if key exists; |defaultValue| otherwise
+ */
+ boolean getBoolean(String key, boolean defaultValue);
+
}
diff --git a/service/java/com/android/server/wifi/SystemPropertyService.java b/service/java/com/android/server/wifi/SystemPropertyService.java
index ed689c424..4c7ffb6d2 100644
--- a/service/java/com/android/server/wifi/SystemPropertyService.java
+++ b/service/java/com/android/server/wifi/SystemPropertyService.java
@@ -27,4 +27,9 @@ class SystemPropertyService implements PropertyService {
public void set(String key, String val) {
android.os.SystemProperties.set(key, val);
}
+
+ @Override
+ public boolean getBoolean(String key, boolean defaultValue) {
+ return android.os.SystemProperties.getBoolean(key, defaultValue);
+ }
}
diff --git a/service/java/com/android/server/wifi/WifiConfigManager.java b/service/java/com/android/server/wifi/WifiConfigManager.java
index 5a248bee9..9129fe612 100644
--- a/service/java/com/android/server/wifi/WifiConfigManager.java
+++ b/service/java/com/android/server/wifi/WifiConfigManager.java
@@ -51,6 +51,7 @@ import android.os.UserManager;
import android.provider.Settings;
import android.security.KeyStore;
import android.text.TextUtils;
+import android.util.ArraySet;
import android.util.LocalLog;
import android.util.Log;
import android.util.SparseArray;
@@ -94,6 +95,7 @@ import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -242,6 +244,9 @@ public class WifiConfigManager {
public AtomicInteger mCurrentNetworkBoost = new AtomicInteger();
public AtomicInteger mBandAward5Ghz = new AtomicInteger();
+ // Indicates whether the system is capable of 802.11r fast BSS transition.
+ private boolean mSystemSupportsFastBssTransition = false;
+
/**
* Framework keeps a list of ephemeral SSIDs that where deleted by user,
* so as, framework knows not to autojoin again those SSIDs based on scorer input.
@@ -254,6 +259,12 @@ public class WifiConfigManager {
/* configured networks with network id as the key */
private final ConfigurationMap mConfiguredNetworks;
+ /*
+ * Stores whether carrier networks are configured.
+ * This information is provided externally from the CarrierConfig.
+ */
+ private boolean mHasCarrierConfiguredNetworks;
+
private final LocalLog mLocalLog;
private final KeyStore mKeyStore;
private final WifiNetworkHistory mWifiNetworkHistory;
@@ -377,6 +388,8 @@ public class WifiConfigManager {
R.integer.config_wifi_framework_current_network_boost));
mNetworkSwitchingBlackListPeriodMs = mContext.getResources().getInteger(
R.integer.config_wifi_network_switching_blacklist_time);
+ mSystemSupportsFastBssTransition = mContext.getResources().getBoolean(
+ R.bool.config_wifi_fast_bss_transition_enabled);
boolean hs2on = mContext.getResources().getBoolean(R.bool.config_wifi_hotspot2_enabled);
boolean hs2onSet = (Settings.Global.getInt(mContext.getContentResolver(),
@@ -508,6 +521,22 @@ public class WifiConfigManager {
}
/**
+ * Check if Carrier networks have ben configured.
+ * @return true if carrier networks are present else false.
+ */
+ public boolean hasCarrierNetworks() {
+ return mHasCarrierConfiguredNetworks;
+ }
+
+ /**
+ * Set true/false depending on whether Carrier networks have been configured.
+ * @param hasCarrierNetworks if Carrier networks have been configured.
+ */
+ public void setHasCarrierNetworks(boolean hasCarrierNetworks) {
+ mHasCarrierConfiguredNetworks = hasCarrierNetworks;
+ }
+
+ /**
* Fetch the list of currently saved networks (i.e. all configured networks, excluding
* ephemeral networks), filled with real preSharedKeys.
* @return List of networks
@@ -1150,6 +1179,14 @@ public class WifiConfigManager {
ArrayList<WifiScanner.PnoSettings.PnoNetwork> pnoList = new ArrayList<>();
ArrayList<WifiConfiguration> wifiConfigurations =
new ArrayList<>(mConfiguredNetworks.valuesForCurrentUser());
+ // Remove any permanently disabled networks.
+ Iterator<WifiConfiguration> iter = wifiConfigurations.iterator();
+ while (iter.hasNext()) {
+ WifiConfiguration config = iter.next();
+ if (config.getNetworkSelectionStatus().isNetworkPermanentlyDisabled()) {
+ iter.remove();
+ }
+ }
Collections.sort(wifiConfigurations, pnoListComparator);
// Let's use the network list size as the highest priority and then go down from there.
// So, the most frequently connected network has the highest priority now.
@@ -1244,52 +1281,56 @@ public class WifiConfigManager {
/*
* Remove all networks associated with an application
*
- * @param packageName name of the package of networks to remove
- * @return {@code true} if all networks removed successfully, {@code false} otherwise
+ * @param app Application info of the package of networks to remove.
+ * @return the {@link Set} of networks that were removed by this call. Networks which matched
+ * but failed to remove are omitted from this set.
*/
- boolean removeNetworksForApp(ApplicationInfo app) {
+ public Set<Integer> removeNetworksForApp(ApplicationInfo app) {
if (app == null || app.packageName == null) {
- return false;
+ return Collections.<Integer>emptySet();
}
- boolean success = true;
-
- WifiConfiguration [] copiedConfigs =
- mConfiguredNetworks.valuesForCurrentUser().toArray(new WifiConfiguration[0]);
+ Log.d(TAG, "Remove all networks for app " + app);
+ Set<Integer> removedNetworks = new ArraySet<>();
+ WifiConfiguration[] copiedConfigs =
+ mConfiguredNetworks.valuesForAllUsers().toArray(new WifiConfiguration[0]);
for (WifiConfiguration config : copiedConfigs) {
if (app.uid != config.creatorUid || !app.packageName.equals(config.creatorName)) {
continue;
}
- if (mShowNetworks) {
- localLog("Removing network " + config.SSID
- + ", application \"" + app.packageName + "\" uninstalled"
- + " from user " + UserHandle.getUserId(app.uid));
+ localLog("Removing network " + config.SSID
+ + ", application \"" + app.packageName + "\" uninstalled"
+ + " from user " + UserHandle.getUserId(app.uid));
+ if (removeNetwork(config.networkId)) {
+ removedNetworks.add(config.networkId);
}
- success &= removeNetwork(config.networkId);
}
-
saveConfig();
-
- return success;
+ return removedNetworks;
}
- boolean removeNetworksForUser(int userId) {
- boolean success = true;
-
+ /**
+ * Remove all networks associated with a user.
+ *
+ * @param userId The identifier of the user which is being removed.
+ * @return the {@link Set} of networks that were removed by this call. Networks which matched
+ * but failed to remove are omitted from this set.
+ */
+ Set<Integer> removeNetworksForUser(int userId) {
+ Log.d(TAG, "Remove all networks for user " + userId);
+ Set<Integer> removedNetworks = new ArraySet<>();
WifiConfiguration[] copiedConfigs =
mConfiguredNetworks.valuesForAllUsers().toArray(new WifiConfiguration[0]);
for (WifiConfiguration config : copiedConfigs) {
if (userId != UserHandle.getUserId(config.creatorUid)) {
continue;
}
- success &= removeNetwork(config.networkId);
- if (mShowNetworks) {
- localLog("Removing network " + config.SSID
- + ", user " + userId + " removed");
+ localLog("Removing network " + config.SSID + ", user " + userId + " removed");
+ if (removeNetwork(config.networkId)) {
+ removedNetworks.add(config.networkId);
}
}
-
- return success;
+ return removedNetworks;
}
/**
@@ -1979,7 +2020,8 @@ public class WifiConfigManager {
// HasEverConnected to be set to false.
WifiConfiguration originalConfig = new WifiConfiguration(currentConfig);
- if (!mWifiConfigStore.addOrUpdateNetwork(config, currentConfig)) {
+ if (!mWifiConfigStore.addOrUpdateNetwork(config, currentConfig,
+ mSystemSupportsFastBssTransition)) {
return new NetworkUpdateResult(INVALID_NETWORK_ID);
}
int netId = config.networkId;
@@ -2018,6 +2060,7 @@ public class WifiConfigManager {
currentConfig.updateTime = config.updateTime;
currentConfig.creationTime = config.creationTime;
currentConfig.shared = config.shared;
+ currentConfig.isCarrierNetwork = config.isCarrierNetwork;
}
if (DBG) {
log("created new config netId=" + Integer.toString(netId)
@@ -3199,6 +3242,33 @@ public class WifiConfigManager {
}
/**
+ * Saves the network and set the candidate.
+ * @param config WifiConfiguration to save.
+ * @param scanResult ScanResult to be used as the network selection candidate.
+ * @return WifiConfiguration that was saved and with the status updated.
+ */
+ public WifiConfiguration saveNetworkAndSetCandidate(WifiConfiguration config,
+ ScanResult scanResult) {
+ saveNetwork(config, WifiConfiguration.UNKNOWN_UID);
+
+ config.getNetworkSelectionStatus().setCandidate(scanResult);
+ return config;
+ }
+
+
+ /**
+ * Get the Scan Result candidate.
+ * @param config WifiConfiguration to get status for.
+ * @return scanResult which is the selection candidate.
+ */
+ public ScanResult getScanResultCandidate(WifiConfiguration config) {
+ if (config == null) {
+ return null;
+ }
+ return config.getNetworkSelectionStatus().getCandidate();
+ }
+
+ /**
* Checks if uid has access to modify config.
*/
boolean canModifyNetwork(int uid, WifiConfiguration config, boolean onlyAnnotate) {
@@ -3268,10 +3338,20 @@ public class WifiConfigManager {
/**
* Check if the provided ephemeral network was deleted by the user or not.
- * @param ssid ssid of the network
+ * @param ssid caller must ensure that the SSID passed thru this API match
+ * the WifiConfiguration.SSID rules, and thus be surrounded by quotes.
* @return true if network was deleted, false otherwise.
*/
public boolean wasEphemeralNetworkDeleted(String ssid) {
return mDeletedEphemeralSSIDs.contains(ssid);
}
+
+ /**
+ * Check if the User has enabled connecting to carrier networks from Settings.
+ * @return true if enabled in Settings, false otherwise.
+ */
+ public boolean getIsCarrierNetworkEnabledByUser() {
+ return android.provider.Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.WIFI_CONNECT_CARRIER_NETWORKS, 0) == 1;
+ }
}
diff --git a/service/java/com/android/server/wifi/WifiConfigStore.java b/service/java/com/android/server/wifi/WifiConfigStore.java
index 908487152..fc4c122fa 100644
--- a/service/java/com/android/server/wifi/WifiConfigStore.java
+++ b/service/java/com/android/server/wifi/WifiConfigStore.java
@@ -350,6 +350,8 @@ public class WifiConfigStore {
readNetworkBitsetVariable(config.networkId, config.allowedKeyManagement,
WifiConfiguration.KeyMgmt.varName, WifiConfiguration.KeyMgmt.strings);
+ // The FT flags should not be exposed to external apps.
+ config.allowedKeyManagement = removeFastTransitionFlags(config.allowedKeyManagement);
readNetworkBitsetVariable(config.networkId, config.allowedAuthAlgorithms,
WifiConfiguration.AuthAlgorithm.varName, WifiConfiguration.AuthAlgorithm.strings);
@@ -430,13 +432,6 @@ public class WifiConfigStore {
}
config.setIpAssignment(IpAssignment.DHCP);
config.setProxySettings(ProxySettings.NONE);
- if (!WifiServiceImpl.isValid(config)) {
- if (mShowNetworks) {
- localLog("Ignoring network " + config.networkId + " because configuration "
- + "loaded from wpa_supplicant.conf is not valid.");
- }
- continue;
- }
// The configKey is explicitly stored in wpa_supplicant.conf, because config does
// not contain sufficient information to compute it at this point.
String configKey = extras.get(ID_STRING_KEY_CONFIG_KEY);
@@ -610,14 +605,34 @@ public class WifiConfigStore {
return true;
}
+ private BitSet addFastTransitionFlags(BitSet keyManagementFlags) {
+ BitSet modifiedFlags = keyManagementFlags;
+ if (keyManagementFlags.get(WifiConfiguration.KeyMgmt.WPA_PSK)) {
+ modifiedFlags.set(WifiConfiguration.KeyMgmt.FT_PSK);
+ }
+ if (keyManagementFlags.get(WifiConfiguration.KeyMgmt.WPA_EAP)) {
+ modifiedFlags.set(WifiConfiguration.KeyMgmt.FT_EAP);
+ }
+ return modifiedFlags;
+ }
+
+ private BitSet removeFastTransitionFlags(BitSet keyManagementFlags) {
+ BitSet modifiedFlags = keyManagementFlags;
+ modifiedFlags.clear(WifiConfiguration.KeyMgmt.FT_PSK);
+ modifiedFlags.clear(WifiConfiguration.KeyMgmt.FT_EAP);
+ return modifiedFlags;
+ }
+
/**
* Save an entire network configuration to wpa_supplicant.
*
* @param config Config corresponding to the network.
- * @param netId Net Id of the network.
+ * @param netId Net Id of the network.
+ * @param addFastTransitionFlags Add the BSS fast transition(80211r) flags to the network.
* @return true if successful, false otherwise.
*/
- private boolean saveNetwork(WifiConfiguration config, int netId) {
+ private boolean saveNetwork(WifiConfiguration config, int netId,
+ boolean addFastTransitionFlags) {
if (config == null) {
return false;
}
@@ -640,6 +655,10 @@ public class WifiConfigStore {
return false;
}
}
+ BitSet allowedKeyManagement = config.allowedKeyManagement;
+ if (addFastTransitionFlags) {
+ allowedKeyManagement = addFastTransitionFlags(config.allowedKeyManagement);
+ }
String allowedKeyManagementString =
makeString(config.allowedKeyManagement, WifiConfiguration.KeyMgmt.strings);
if (config.allowedKeyManagement.cardinality() != 0 && !mWifiNative.setNetworkVariable(
@@ -804,11 +823,13 @@ public class WifiConfigStore {
/**
* Add or update a network configuration to wpa_supplicant.
*
- * @param config Config corresponding to the network.
+ * @param config Config corresponding to the network.
* @param existingConfig Existing config corresponding to the network saved in our database.
+ * @param addFastTransitionFlags Add the BSS fast transition(80211r) flags to the network.
* @return true if successful, false otherwise.
*/
- public boolean addOrUpdateNetwork(WifiConfiguration config, WifiConfiguration existingConfig) {
+ public boolean addOrUpdateNetwork(WifiConfiguration config, WifiConfiguration existingConfig,
+ boolean addFastTransitionFlags) {
if (config == null) {
return false;
}
@@ -832,7 +853,7 @@ public class WifiConfigStore {
// Save the new network ID to the config
config.networkId = netId;
}
- if (!saveNetwork(config, netId)) {
+ if (!saveNetwork(config, netId, addFastTransitionFlags)) {
if (newNetwork) {
mWifiNative.removeNetwork(netId);
loge("Failed to set a network variable, removed network: " + netId);
diff --git a/service/java/com/android/server/wifi/WifiController.java b/service/java/com/android/server/wifi/WifiController.java
index b72540f8b..26f662adb 100644
--- a/service/java/com/android/server/wifi/WifiController.java
+++ b/service/java/com/android/server/wifi/WifiController.java
@@ -694,8 +694,10 @@ public class WifiController extends StateMachine {
@Override
public void enter() {
- mWifiStateMachine.setSupplicantRunning(true);
+ // need to set the mode before starting supplicant because WSM will assume we are going
+ // in to client mode
mWifiStateMachine.setOperationalMode(WifiStateMachine.SCAN_ONLY_WITH_WIFI_OFF_MODE);
+ mWifiStateMachine.setSupplicantRunning(true);
mWifiStateMachine.setDriverStart(true);
// Supplicant can't restart right away, so not the time we switched off
mDisabledTimestamp = SystemClock.elapsedRealtime();
diff --git a/service/java/com/android/server/wifi/WifiQualifiedNetworkSelector.java b/service/java/com/android/server/wifi/WifiQualifiedNetworkSelector.java
index 00fffdb4b..e429d835a 100644
--- a/service/java/com/android/server/wifi/WifiQualifiedNetworkSelector.java
+++ b/service/java/com/android/server/wifi/WifiQualifiedNetworkSelector.java
@@ -17,26 +17,36 @@
package com.android.server.wifi;
import android.annotation.Nullable;
+import android.content.BroadcastReceiver;
import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
import android.net.NetworkKey;
import android.net.NetworkScoreManager;
import android.net.WifiKey;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiEnterpriseConfig;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
+import android.os.PersistableBundle;
+import android.telephony.CarrierConfigManager;
import android.text.TextUtils;
+import android.util.Base64;
import android.util.LocalLog;
import android.util.Log;
import android.util.Pair;
import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.wifi.util.ScanDetailUtil;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.nio.charset.StandardCharsets;
+
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
@@ -70,6 +80,10 @@ public class WifiQualifiedNetworkSelector {
//usable only when current state is connected state default 10 s
private static final int MINIMUM_QUALIFIED_NETWORK_SELECTION_INTERVAL = 10 * 1000;
+ private static final int CARRIER_SSID = 0;
+ private static final int CARRIER_KEY = 1;
+ private static final int CARRIER_EAP_METHOD = 2;
+
//if current network is on 2.4GHz band and has a RSSI over this, need not new network selection
public static final int QUALIFIED_RSSI_24G_BAND = -73;
//if current network is on 5GHz band and has a RSSI over this, need not new network selection
@@ -109,6 +123,8 @@ public class WifiQualifiedNetworkSelector {
private int mUserPreferedBand = WifiManager.WIFI_FREQUENCY_BAND_AUTO;
private Map<String, BssidBlacklistStatus> mBssidBlacklist =
new HashMap<String, BssidBlacklistStatus>();
+ private List<WifiConfiguration> mCarrierConfiguredNetworks = new ArrayList<WifiConfiguration>();
+ private Context mContext;
/**
* class save the blacklist status of a given BSSID
@@ -127,6 +143,11 @@ public class WifiQualifiedNetworkSelector {
}
}
+ @VisibleForTesting
+ public void setCarrierConfiguredNetworks(List<WifiConfiguration> carrierConfiguredNetworks) {
+ mCarrierConfiguredNetworks = carrierConfiguredNetworks;
+ }
+
private void localLoge(String log) {
mLocalLog.log(log);
}
@@ -167,6 +188,7 @@ public class WifiQualifiedNetworkSelector {
mWifiConfigManager = configureStore;
mWifiInfo = wifiInfo;
mClock = clock;
+ mContext = context;
mScoreManager =
(NetworkScoreManager) context.getSystemService(Context.NETWORK_SCORE_SERVICE);
if (mScoreManager != null) {
@@ -193,8 +215,73 @@ public class WifiQualifiedNetworkSelector {
mNoIntnetPenalty = (mWifiConfigManager.mThresholdSaturatedRssi24.get() + mRssiScoreOffset)
* mRssiScoreSlope + mWifiConfigManager.mBandAward5Ghz.get()
+ mWifiConfigManager.mCurrentNetworkBoost.get() + mSameBssidAward + mSecurityAward;
+
+ context.registerReceiver(mBroadcastReceiver, new IntentFilter(
+ CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED));
+ }
+
+ @VisibleForTesting
+ public List<WifiConfiguration> parseCarrierSuppliedWifiInfo(String[] wifiArray) {
+ List<WifiConfiguration> carrierConfiguredNetworks = new ArrayList<WifiConfiguration>();
+ for (String config : wifiArray) {
+ String[] wc = config.split("\\|");
+ if (wc.length != 3) {
+ continue;
+ }
+ WifiConfiguration wifiConfig = new WifiConfiguration();
+ try {
+ byte[] decodedBytes = Base64.decode(wc[CARRIER_SSID], Base64.DEFAULT);
+ String ssid = new String(decodedBytes);
+ wifiConfig.SSID = "\"" + ssid + "\"";
+ } catch (IllegalArgumentException ex) {
+ localLog("mBroadcaseReceiver: Could not decode base64 string");
+ continue;
+ }
+ try {
+ int key = Integer.parseInt(wc[CARRIER_KEY]);
+ wifiConfig.allowedKeyManagement.set(key);
+ int eapType = Integer.parseInt(wc[CARRIER_EAP_METHOD]);
+ wifiConfig.enterpriseConfig = new WifiEnterpriseConfig();
+ wifiConfig.enterpriseConfig.setEapMethod(eapType);
+ } catch (NumberFormatException e) {
+ localLog("mBroadcastReceiver: not an integer:" + wc[CARRIER_KEY] + "," +
+ wc[CARRIER_EAP_METHOD]);
+ continue;
+ } catch (IllegalArgumentException e) {
+ localLog("mBroadcastReceiver: invalid config" + wc[CARRIER_KEY] + "," +
+ wc[CARRIER_EAP_METHOD]);
+ }
+ carrierConfiguredNetworks.add(wifiConfig);
+ localLog("mBroadcastReceiver: carrier config:" + wifiConfig.SSID);
+ }
+ return carrierConfiguredNetworks;
}
+ final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ localLog("mBroadcastReceiver: onReceive " + intent.getAction());
+ String[] wifiArray = null;
+ CarrierConfigManager carrierConfigManager = (CarrierConfigManager)
+ mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE);
+ if (carrierConfigManager != null) {
+ PersistableBundle b = carrierConfigManager.getConfig();
+ if (b != null) {
+ wifiArray = b.getStringArray(
+ CarrierConfigManager.KEY_CARRIER_WIFI_STRING_ARRAY);
+ }
+ }
+
+ if (wifiArray == null) {
+ return;
+ }
+ mCarrierConfiguredNetworks = parseCarrierSuppliedWifiInfo(wifiArray);
+ boolean hasCarrierNetworks = (mCarrierConfiguredNetworks == null ||
+ mCarrierConfiguredNetworks.size() == 0) ? false : true;
+ mWifiConfigManager.setHasCarrierNetworks(hasCarrierNetworks);
+ }
+ };
+
void enableVerboseLogging(int verbose) {
mDbg = verbose > 0 || FORCE_DEBUG;
}
@@ -240,7 +327,7 @@ public class WifiQualifiedNetworkSelector {
// Current network band must match with user preference selection
if (mWifiInfo.is24GHz() && (mUserPreferedBand != WifiManager.WIFI_FREQUENCY_BAND_2GHZ)) {
- localLog("Current band dose not match user preference. Start Qualified Network"
+ localLog("Current band does not match user preference. Start Qualified Network"
+ " Selection Current band = " + (mWifiInfo.is24GHz() ? "2.4GHz band"
: "5GHz band") + "UserPreference band = " + mUserPreferedBand);
return false;
@@ -591,6 +678,11 @@ public class WifiQualifiedNetworkSelector {
return status == null ? false : status.mIsBlacklisted;
}
+ private boolean isCarrierNetwork(ScanResult scanResult) {
+ return (getMatchingConfigForEAPNetworks(scanResult,
+ mCarrierConfiguredNetworks) != null ? true : false);
+ }
+
/**
* ToDo: This should be called in Connectivity Manager when it gets new scan result
* check whether a network slection is needed. If need, check all the new scan results and
@@ -614,7 +706,7 @@ public class WifiQualifiedNetworkSelector {
* false -- supplicant is not in a transient state
* @return the qualified network candidate found. If no available candidate, return null
*/
- public WifiConfiguration selectQualifiedNetwork(boolean forceSelectNetwork ,
+ public WifiConfiguration selectQualifiedNetwork(boolean forceSelectNetwork,
boolean isUntrustedConnectionsAllowed, List<ScanDetail> scanDetails,
boolean isLinkDebouncing, boolean isConnected, boolean isDisconnected,
boolean isSupplicantTransient) {
@@ -641,8 +733,11 @@ public class WifiQualifiedNetworkSelector {
int currentHighestScore = Integer.MIN_VALUE;
ScanResult scanResultCandidate = null;
WifiConfiguration networkCandidate = null;
+ WifiConfiguration carrierCandidate = null;
final ExternalScoreEvaluator externalScoreEvaluator =
new ExternalScoreEvaluator(mLocalLog, mDbg);
+ final CarrierScoreEvaluator carrierScoreEvaluator =
+ new CarrierScoreEvaluator(mLocalLog, mDbg);
String lastUserSelectedNetWorkKey = mWifiConfigManager.getLastSelectedConfiguration();
WifiConfiguration lastUserSelectedNetwork =
mWifiConfigManager.getWifiConfiguration(lastUserSelectedNetWorkKey);
@@ -660,6 +755,10 @@ public class WifiQualifiedNetworkSelector {
StringBuffer noValidSsid = new StringBuffer();
StringBuffer scoreHistory = new StringBuffer();
ArrayList<NetworkKey> unscoredNetworks = new ArrayList<NetworkKey>();
+ boolean scanResultsHaveCurrentBssid = false;
+
+ localLog("isCarrierNetworkEnabledByUser: " +
+ mWifiConfigManager.getIsCarrierNetworkEnabledByUser());
//iterate all scan results and find the best candidate with the highest score
for (ScanDetail scanDetail : mScanDetails) {
@@ -673,6 +772,12 @@ public class WifiQualifiedNetworkSelector {
continue;
}
+ //check if the scan results contain the current connected
+ //BSSID.
+ if (scanResult.BSSID.equals(mCurrentBssid)) {
+ scanResultsHaveCurrentBssid = true;
+ }
+
final String scanId = toScanId(scanResult);
//check whether this BSSID is blocked or not
if (mWifiConfigManager.isBssidBlacklisted(scanResult.BSSID)
@@ -734,12 +839,26 @@ public class WifiQualifiedNetworkSelector {
// Evaluate the potentially ephemeral network as a possible candidate if untrusted
// connections are allowed and we have an external score for the scan result.
if (potentiallyEphemeral) {
- if (isUntrustedConnectionsAllowed) {
- Integer netScore = getNetworkScore(scanResult, false);
- if (netScore != null
- && !mWifiConfigManager.wasEphemeralNetworkDeleted(scanResult.SSID)) {
- externalScoreEvaluator.evalUntrustedCandidate(netScore, scanResult);
- // scanDetail is for available ephemeral network
+ if (!mWifiConfigManager.wasEphemeralNetworkDeleted(
+ ScanDetailUtil.createQuotedSSID(scanResult.SSID))) {
+ if (isUntrustedConnectionsAllowed) {
+ Integer netScore = getNetworkScore(scanResult, false);
+ if (netScore != null) {
+ externalScoreEvaluator.evalUntrustedCandidate(netScore, scanResult);
+ // scanDetail is for available ephemeral network
+ filteredScanDetails.add(Pair.create(scanDetail,
+ potentialEphemeralCandidate));
+ }
+ // Evaluate the carrier network as a possible candidate.
+ // todo need to add flag isCarrierConnectionsAllowed, config in settings.
+ } else if (!mCarrierConfiguredNetworks.isEmpty() &&
+ isCarrierNetwork(scanResult) &&
+ mWifiConfigManager.getIsCarrierNetworkEnabledByUser()) {
+ localLog("Checking the carrierScoreEvaluator for candidates...");
+ carrierScoreEvaluator.evalCarrierCandidate(scanResult,
+ getCarrierScore(scanResult, mCurrentConnectedNetwork,
+ (mCurrentBssid == null ? false :
+ mCurrentBssid.equals(scanResult.BSSID))));
filteredScanDetails.add(Pair.create(scanDetail,
potentialEphemeralCandidate));
}
@@ -826,6 +945,16 @@ public class WifiQualifiedNetworkSelector {
localLog(scoreHistory.toString());
}
+ //QNS listens to all single scan results. Some scan requests may not include
+ //the channel of the currently connected network, so the currently connected network
+ //won't show up in the scan results. We don't act on these scan results to avoid
+ //aggressive network switching which might trigger disconnection.
+ if (isConnected && !scanResultsHaveCurrentBssid) {
+ localLog("Current connected BSSID " + mCurrentBssid + " is not in the scan results."
+ + " Skip network selection.");
+ return null;
+ }
+
//we need traverse the whole user preference to choose the one user like most now
if (scanResultCandidate != null) {
WifiConfiguration tempConfig = networkCandidate;
@@ -862,6 +991,15 @@ public class WifiQualifiedNetworkSelector {
}
if (scanResultCandidate == null) {
+ networkCandidate = getCarrierScoreCandidate(carrierScoreEvaluator);
+ localLog("Carrier candidate::" + networkCandidate);
+ if (networkCandidate != null) {
+ scanResultCandidate =
+ mWifiConfigManager.getScanResultCandidate(networkCandidate);
+ }
+ }
+
+ if (scanResultCandidate == null) {
localLog("Can not find any suitable candidates");
return null;
}
@@ -946,6 +1084,37 @@ public class WifiQualifiedNetworkSelector {
}
/**
+ * Returns the best candidate network according to the given CarrierScoreEvaluator.
+ */
+ @Nullable
+ WifiConfiguration getCarrierScoreCandidate(CarrierScoreEvaluator scoreEvaluator) {
+
+ ScanResult untrustedCarrierScanResult = scoreEvaluator.getScanResultCandidate();
+ if (untrustedCarrierScanResult == null) {
+ return null;
+ }
+
+ WifiConfiguration untrustedCandidateConfig = getMatchingConfigForEAPNetworks(
+ untrustedCarrierScanResult, mCarrierConfiguredNetworks);
+
+ if (untrustedCandidateConfig == null) {
+ return null;
+ }
+
+ WifiConfiguration newUntrustedCandidateConfig =
+ new WifiConfiguration(untrustedCandidateConfig);
+
+ // Mark this config as ephemeral so it isn't persisted.
+ newUntrustedCandidateConfig.ephemeral = true;
+ // Mark this config as a Carrier Network.
+ newUntrustedCandidateConfig.isCarrierNetwork = true;
+
+ mWifiConfigManager.saveNetworkAndSetCandidate(
+ newUntrustedCandidateConfig, untrustedCarrierScanResult);
+ return newUntrustedCandidateConfig;
+ }
+
+ /**
* Returns the available external network score or NULL if no score is available.
*
* @param scanResult The scan result of the network to score.
@@ -963,6 +1132,43 @@ public class WifiQualifiedNetworkSelector {
}
/**
+ * Returns the available external network score or NULL if no score is available.
+ *
+ * @param scanResult The scan result of the network to score.
+ * @return A valid external score if one is available or NULL.
+ */
+ int getCarrierScore(ScanResult scanResult, WifiConfiguration currentNetwork,
+ boolean sameBssid) {
+ localLog("Calc Carrier score: w/" + sameBssid);
+ if (currentNetwork != null) {
+ localLog("scoring: compare::" + scanResult.SSID + ", with:" + currentNetwork.SSID);
+ }
+ int score = 0;
+ // Calculate the RSSI score.
+ int rssi = scanResult.level <= mWifiConfigManager.mThresholdSaturatedRssi24.get()
+ ? scanResult.level : mWifiConfigManager.mThresholdSaturatedRssi24.get();
+ score += (rssi + mRssiScoreOffset) * mRssiScoreSlope;
+
+ // 5GHz band bonus.
+ if (scanResult.is5GHz()) {
+ score += BAND_AWARD_5GHz;
+ }
+
+ //same network award
+ if ((currentNetwork != null) && currentNetwork.SSID.equals(scanResult.SSID)) {
+ score += mWifiConfigManager.mCurrentNetworkBoost.get();
+ }
+
+ //same BSSID award
+ if (sameBssid) {
+ score += mSameBssidAward;
+ }
+
+ localLog("Calc Carrier score:" + score);
+ return score;
+ }
+
+ /**
* Formats the given ScanResult as a scan ID for logging.
*/
private static String toScanId(@Nullable ScanResult scanResult) {
@@ -1051,4 +1257,66 @@ public class WifiQualifiedNetworkSelector {
}
}
}
+
+ /**
+ * Used to track and evaluate networks that are assigned by the Carriers.
+ */
+ static class CarrierScoreEvaluator {
+ // Always set to the best known candidate
+ private int mHighScore = WifiNetworkScoreCache.INVALID_NETWORK_SCORE;
+ private ScanResult mScanResultCandidate;
+ private final LocalLog mLocalLog;
+ private final boolean mDbg;
+
+ CarrierScoreEvaluator(LocalLog localLog, boolean dbg) {
+ mLocalLog = localLog;
+ mDbg = dbg;
+ }
+
+ // Determines whether or not the given scan result is the best one its seen so far.
+ void evalCarrierCandidate(ScanResult scanResult, int score) {
+ if (score > mHighScore) {
+ mHighScore = score;
+ mScanResultCandidate = scanResult;
+ localLog(toScanId(scanResult) +
+ " become the new untrusted carrier network candidate");
+ }
+ }
+
+ int getHighScore() {
+ return mHighScore;
+ }
+
+ public ScanResult getScanResultCandidate() {
+ return mScanResultCandidate;
+ }
+
+ private void localLog(String log) {
+ if (mDbg) {
+ mLocalLog.log(log);
+ }
+ }
+ }
+
+ private WifiConfiguration getMatchingConfigForEAPNetworks(
+ ScanResult scanResult, List<WifiConfiguration> candidateConfigs) {
+ if (scanResult == null || candidateConfigs == null) {
+ return null;
+ }
+ // TODO currently we only support EAP. We'll add to this in OC.
+ if (!scanResult.capabilities.contains("EAP")) {
+ return null;
+ }
+ String ssid = "\"" + scanResult.SSID + "\"";
+ for (WifiConfiguration config : candidateConfigs) {
+ if (config.SSID.equals(ssid)) {
+ // TODO currently we only support EAP. We'll add to this in OC.
+ if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_EAP) ||
+ config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.IEEE8021X)) {
+ return config;
+ }
+ }
+ }
+ return null;
+ }
}
diff --git a/service/java/com/android/server/wifi/WifiServiceImpl.java b/service/java/com/android/server/wifi/WifiServiceImpl.java
index e5a537dd0..bea194908 100755
--- a/service/java/com/android/server/wifi/WifiServiceImpl.java
+++ b/service/java/com/android/server/wifi/WifiServiceImpl.java
@@ -37,6 +37,7 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
import android.database.ContentObserver;
@@ -72,6 +73,7 @@ import android.os.Looper;
import android.os.Message;
import android.os.Messenger;
import android.os.PowerManager;
+import android.os.Process;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.SystemClock;
@@ -188,6 +190,8 @@ public class WifiServiceImpl extends IWifiManager.Stub {
*/
private AsyncChannel mWifiStateMachineChannel;
+ private final boolean mPermissionReviewRequired;
+
/**
* Handles client connections
*/
@@ -390,6 +394,10 @@ public class WifiServiceImpl extends IWifiManager.Stub {
}
// Set the WifiController for WifiLastResortWatchdog
mWifiInjector.getWifiLastResortWatchdog().setWifiController(mWifiController);
+
+ mPermissionReviewRequired = Build.PERMISSIONS_REVIEW_REQUIRED
+ || context.getResources().getBoolean(
+ com.android.internal.R.bool.config_permissionReviewRequired);
}
@@ -451,7 +459,13 @@ public class WifiServiceImpl extends IWifiManager.Stub {
// If we are already disabled (could be due to airplane mode), avoid changing persist
// state here
- if (wifiEnabled) setWifiEnabled(wifiEnabled);
+ if (wifiEnabled) {
+ try {
+ setWifiEnabled(mContext.getPackageName(), wifiEnabled);
+ } catch (RemoteException e) {
+ /* ignore - local call */
+ }
+ }
}
public void handleUserSwitch(int userId) {
@@ -594,12 +608,12 @@ public class WifiServiceImpl extends IWifiManager.Stub {
* @return {@code true} if the enable/disable operation was
* started or is already in the queue.
*/
- public synchronized boolean setWifiEnabled(boolean enable) {
+ public synchronized boolean setWifiEnabled(String packageName, boolean enable)
+ throws RemoteException {
enforceChangePermission();
Slog.d(TAG, "setWifiEnabled: " + enable + " pid=" + Binder.getCallingPid()
+ ", uid=" + Binder.getCallingUid());
if(isStrictOpEnable()){
- String packageName = mContext.getPackageManager().getNameForUid(Binder.getCallingUid());
if((Binder.getCallingUid() > 10000) && (packageName.indexOf("android.uid.systemui") !=0) && (packageName.indexOf("android.uid.system") != 0)) {
AppOpsManager mAppOpsManager = mContext.getSystemService(AppOpsManager.class);
int result = mAppOpsManager.noteOp(AppOpsManager.OP_CHANGE_WIFI_STATE,Binder.getCallingUid(),packageName);
@@ -612,7 +626,6 @@ public class WifiServiceImpl extends IWifiManager.Stub {
* Caller might not have WRITE_SECURE_SETTINGS,
* only CHANGE_WIFI_STATE is enforced
*/
-
long ident = Binder.clearCallingIdentity();
try {
if (! mSettingsStore.handleWifiToggled(enable)) {
@@ -627,6 +640,26 @@ public class WifiServiceImpl extends IWifiManager.Stub {
Slog.e(TAG,"WifiController is not yet started, abort setWifiEnabled");
return false;
}
+
+ if (mPermissionReviewRequired) {
+ final int wiFiEnabledState = getWifiEnabledState();
+ if (enable) {
+ if (wiFiEnabledState == WifiManager.WIFI_STATE_DISABLING
+ || wiFiEnabledState == WifiManager.WIFI_STATE_DISABLED) {
+ if (startConsentUi(packageName, Binder.getCallingUid(),
+ WifiManager.ACTION_REQUEST_ENABLE)) {
+ return true;
+ }
+ }
+ } else if (wiFiEnabledState == WifiManager.WIFI_STATE_ENABLING
+ || wiFiEnabledState == WifiManager.WIFI_STATE_ENABLED) {
+ if (startConsentUi(packageName, Binder.getCallingUid(),
+ WifiManager.ACTION_REQUEST_DISABLE)) {
+ return true;
+ }
+ }
+ }
+
mWifiController.sendMessage(CMD_WIFI_TOGGLED);
return true;
}
@@ -860,6 +893,21 @@ public class WifiServiceImpl extends IWifiManager.Stub {
}
/**
+ * see {@link android.net.wifi.WifiManager#getHasCarrierNetworks()}
+ * @return if Carrier Networks have been configured
+ */
+ public boolean hasCarrierConfiguredNetworks() {
+ enforceAccessPermission();
+ if (mWifiStateMachineChannel != null) {
+ return mWifiStateMachine.syncHasCarrierConfiguredNetworks(Binder.getCallingUid(),
+ mWifiStateMachineChannel);
+ } else {
+ Slog.e(TAG, "mWifiStateMachineChannel is not initialized");
+ return false;
+ }
+ }
+
+ /**
* see {@link android.net.wifi.WifiManager#getPrivilegedConfiguredNetworks()}
* @return the list of configured networks with real preSharedKey
*/
@@ -1456,7 +1504,11 @@ public class WifiServiceImpl extends IWifiManager.Stub {
}
} else if ( state == WifiManager.WIFI_STATE_DISABLED) {
if (mSubSystemRestart) {
- setWifiEnabled(true);
+ try {
+ setWifiEnabled(mContext.getPackageName(), true);
+ } catch (RemoteException e) {
+ /* ignore - local call */
+ }
}
}
} else if (action.equals(WifiManager.WIFI_AP_STATE_CHANGED_ACTION)) {
@@ -1465,7 +1517,11 @@ public class WifiServiceImpl extends IWifiManager.Stub {
if (mSubSystemRestart) {
if (wifiApState == WifiManager.WIFI_AP_STATE_DISABLED) {
if (getWifiEnabledState() == WifiManager.WIFI_STATE_ENABLED) {
- setWifiEnabled(false);
+ try {
+ setWifiEnabled(mContext.getPackageName(), false);
+ } catch (RemoteException e) {
+ /* ignore - local call */
+ }
} else {
/**
* STA in DISABLED state, hence just restart SAP.
@@ -1487,6 +1543,34 @@ public class WifiServiceImpl extends IWifiManager.Stub {
}
};
+ private boolean startConsentUi(String packageName,
+ int callingUid, String intentAction) throws RemoteException {
+ if (UserHandle.getAppId(callingUid) == Process.SYSTEM_UID) {
+ return false;
+ }
+ try {
+ // Validate the package only if we are going to use it
+ ApplicationInfo applicationInfo = mContext.getPackageManager()
+ .getApplicationInfoAsUser(packageName,
+ PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
+ UserHandle.getUserId(callingUid));
+ if (applicationInfo.uid != callingUid) {
+ throw new SecurityException("Package " + callingUid
+ + " not in uid " + callingUid);
+ }
+
+ // Permission review mode, trigger a user prompt
+ Intent intent = new Intent(intentAction);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+ | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+ intent.putExtra(Intent.EXTRA_PACKAGE_NAME, packageName);
+ mContext.startActivity(intent);
+ return true;
+ } catch (PackageManager.NameNotFoundException e) {
+ throw new RemoteException(e.getMessage());
+ }
+ }
+
/**
* Observes settings changes to scan always mode.
*/
@@ -1860,7 +1944,11 @@ public class WifiServiceImpl extends IWifiManager.Stub {
} else {
mIsFactoryResetOn = true;
// Enable wifi
- setWifiEnabled(true);
+ try {
+ setWifiEnabled(mContext.getOpPackageName(), true);
+ } catch (RemoteException e) {
+ /* ignore - local call */
+ }
}
}
}
diff --git a/service/java/com/android/server/wifi/WifiStateMachine.java b/service/java/com/android/server/wifi/WifiStateMachine.java
index 5d1906aca..f34d0b1e9 100644
--- a/service/java/com/android/server/wifi/WifiStateMachine.java
+++ b/service/java/com/android/server/wifi/WifiStateMachine.java
@@ -663,6 +663,8 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss
static final int CMD_GET_PRIVILEGED_CONFIGURED_NETWORKS = BASE + 62;
/* Get Link Layer Stats thru HAL */
static final int CMD_GET_LINK_LAYER_STATS = BASE + 63;
+ /* Has Carrier configured networks */
+ static final int CMD_HAS_CARRIER_CONFIGURED_NETWORKS = BASE + 64;
/* Supplicant commands after driver start*/
/* Initiate a scan */
static final int CMD_START_SCAN = BASE + 71;
@@ -1071,7 +1073,6 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss
mP2pSupported = mContext.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_WIFI_DIRECT);
-
mWifiConfigManager = mFacade.makeWifiConfigManager(context, mWifiNative, facade,
mWifiInjector.getClock(), userManager, mWifiInjector.getKeyStore());
@@ -2151,6 +2152,21 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss
return result;
}
+ /**
+ * Check if Carrier networks have been configured synchronously
+ *
+ * @param channel
+ * @return
+ */
+ public boolean syncHasCarrierConfiguredNetworks(
+ int uuid, AsyncChannel channel) {
+ Message resultMsg = channel.sendMessageSynchronously(
+ CMD_HAS_CARRIER_CONFIGURED_NETWORKS, uuid);
+ boolean result = resultMsg.obj != null && (boolean) resultMsg.obj;
+ resultMsg.recycle();
+ return result;
+ }
+
public List<WifiConfiguration> syncGetPrivilegedConfiguredNetwork(AsyncChannel channel) {
Message resultMsg = channel.sendMessageSynchronously(
CMD_GET_PRIVILEGED_CONFIGURED_NETWORKS);
@@ -2186,6 +2202,14 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss
Message resultMsg = channel.sendMessageSynchronously(CMD_GET_SUPPORTED_FEATURES);
int supportedFeatureSet = resultMsg.arg1;
resultMsg.recycle();
+
+ // Mask the feature set against system properties.
+ boolean disableRtt = mPropertyService.getBoolean("config.disable_rtt", false);
+ if (disableRtt) {
+ supportedFeatureSet &=
+ ~(WifiManager.WIFI_FEATURE_D2D_RTT | WifiManager.WIFI_FEATURE_D2AP_RTT);
+ }
+
return supportedFeatureSet;
}
@@ -2911,6 +2935,13 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss
sb.append(Integer.toString(msg.arg2));
sb.append(" num=").append(mWifiConfigManager.getConfiguredNetworksSize());
break;
+ case CMD_HAS_CARRIER_CONFIGURED_NETWORKS:
+ sb.append(" ");
+ sb.append(Integer.toString(msg.arg1));
+ sb.append(" ");
+ sb.append(Integer.toString(msg.arg2));
+ sb.append(" hasCarrierNetworks=").append(mWifiConfigManager.hasCarrierNetworks());
+ break;
case DhcpClient.CMD_PRE_DHCP_ACTION:
sb.append(" ");
sb.append(Integer.toString(msg.arg1));
@@ -4196,6 +4227,9 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss
case CMD_GET_CONFIGURED_NETWORKS:
replyToMessage(message, message.what, (List<WifiConfiguration>) null);
break;
+ case CMD_HAS_CARRIER_CONFIGURED_NETWORKS:
+ replyToMessage(message, message.what, null);
+ break;
case CMD_GET_PRIVILEGED_CONFIGURED_NETWORKS:
replyToMessage(message, message.what, (List<WifiConfiguration>) null);
break;
@@ -4562,7 +4596,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss
switch(message.what) {
case WifiMonitor.SUP_CONNECTION_EVENT:
if (DBG) log("Supplicant connection established");
- setWifiState(WIFI_STATE_ENABLED);
+
mSupplicantRestartCount = 0;
/* Reset the supplicant state to indicate the supplicant
* state is not known at this time */
@@ -4627,10 +4661,6 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss
class SupplicantStartedState extends State {
@Override
public void enter() {
- /* Wifi is available as long as we have a connection to supplicant */
- mNetworkInfo.setIsAvailable(true);
- if (mNetworkAgent != null) mNetworkAgent.sendNetworkInfo(mNetworkInfo);
-
int defaultInterval = mContext.getResources().getInteger(
R.integer.config_wifi_supplicant_scan_interval);
@@ -5518,18 +5548,30 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss
@Override
public void enter() {
+ // Let the system know that wifi is enabled
+ setWifiState(WIFI_STATE_ENABLED);
+
+ mNetworkInfo.setIsAvailable(true);
+ if (mNetworkAgent != null) mNetworkAgent.sendNetworkInfo(mNetworkInfo);
+
+ // initialize network state
+ setNetworkDetailedState(DetailedState.DISCONNECTED);
+
// Inform WifiConnectivityManager that Wifi is enabled
if (mWifiConnectivityManager != null) {
mWifiConnectivityManager.setWifiEnabled(true);
}
// Inform metrics that Wifi is Enabled (but not yet connected)
mWifiMetrics.setWifiState(WifiMetricsProto.WifiLog.WIFI_DISCONNECTED);
-
-
}
@Override
public void exit() {
+ // Let the system know that wifi is not available since we are exiting client mode.
+ setWifiState(WIFI_STATE_DISABLED);
+ mNetworkInfo.setIsAvailable(false);
+ if (mNetworkAgent != null) mNetworkAgent.sendNetworkInfo(mNetworkInfo);
+
// Inform WifiConnectivityManager that Wifi is disabled
if (mWifiConnectivityManager != null) {
mWifiConnectivityManager.setWifiEnabled(false);
@@ -5547,6 +5589,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss
String bssid;
String ssid;
NetworkUpdateResult result;
+ Set<Integer> removedNetworkIds;
logStateAndMessage(message, this);
switch (message.what) {
@@ -5830,6 +5873,10 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss
replyToMessage(message, message.what,
mWifiConfigManager.getSavedNetworks());
break;
+ case CMD_HAS_CARRIER_CONFIGURED_NETWORKS:
+ replyToMessage(message, message.what,
+ (Boolean)mWifiConfigManager.hasCarrierNetworks());
+ break;
case WifiMonitor.SUP_REQUEST_IDENTITY:
int networkId = message.arg2;
boolean identitySent = false;
@@ -5843,8 +5890,10 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss
// For SIM & AKA/AKA' EAP method Only, get identity from ICC
if (targetWificonfiguration != null
&& targetWificonfiguration.networkId == networkId
- && targetWificonfiguration.allowedKeyManagement
+ && (targetWificonfiguration.allowedKeyManagement
.get(WifiConfiguration.KeyMgmt.IEEE8021X)
+ || targetWificonfiguration.allowedKeyManagement
+ .get(WifiConfiguration.KeyMgmt.WPA_EAP))
&& TelephonyUtil.isSimEapMethod(eapMethod)) {
String identity = TelephonyUtil.getSimIdentity(mContext, eapMethod);
if (identity != null) {
@@ -5994,7 +6043,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss
//Determine if this CONNECTION is for a user selection
if (mWifiConfigManager.isLastSelectedConfiguration(config)
&& mWifiConfigManager.isCurrentUserProfile(
- UserHandle.getUserId(config.lastConnectUid))) {
+ UserHandle.getUserId(config.lastConnectUid))) {
lastConnectUid = config.lastConnectUid;
mWifiMetrics.setConnectionEventRoamType(
WifiMetricsProto.ConnectionEvent.ROAM_USER_SELECTED);
@@ -6039,10 +6088,22 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss
}
break;
case CMD_REMOVE_APP_CONFIGURATIONS:
- mWifiConfigManager.removeNetworksForApp((ApplicationInfo) message.obj);
+ removedNetworkIds =
+ mWifiConfigManager.removeNetworksForApp((ApplicationInfo) message.obj);
+ if (removedNetworkIds.contains(mTargetNetworkId) ||
+ removedNetworkIds.contains(mLastNetworkId)) {
+ // Disconnect and let autojoin reselect a new network.
+ sendMessage(CMD_DISCONNECT);
+ }
break;
case CMD_REMOVE_USER_CONFIGURATIONS:
- mWifiConfigManager.removeNetworksForUser(message.arg1);
+ removedNetworkIds =
+ mWifiConfigManager.removeNetworksForUser((Integer) message.arg1);
+ if (removedNetworkIds.contains(mTargetNetworkId) ||
+ removedNetworkIds.contains(mLastNetworkId)) {
+ // Disconnect and let autojoin reselect a new network.
+ sendMessage(CMD_DISCONNECT);
+ }
break;
case WifiManager.CONNECT_NETWORK:
// Only the current foreground user and System UI (which runs as user 0 but acts
@@ -6473,7 +6534,9 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss
private void updateCapabilities(WifiConfiguration config) {
NetworkCapabilities networkCapabilities = new NetworkCapabilities(mDfltNetworkCapabilities);
if (config != null) {
- if (config.ephemeral) {
+ Log.d(TAG, "updateCapabilities for config:" + config.getPrintableSsid() + config.ephemeral +
+ "," + config.isCarrierNetwork);
+ if (config.ephemeral && !config.isCarrierNetwork) {
networkCapabilities.removeCapability(
NetworkCapabilities.NET_CAPABILITY_TRUSTED);
} else {
@@ -7460,6 +7523,10 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss
break;
} else {
config = mWifiConfigManager.getWifiConfiguration(netId);
+ if (config == null) {
+ loge("AUTO_ROAM and invalid netowrk ID, bail out...");
+ break;
+ }
}
setTargetBssid(config, bssid);
diff --git a/service/java/com/android/server/wifi/hotspot2/omadm/OMAParser.java b/service/java/com/android/server/wifi/hotspot2/omadm/OMAParser.java
index cbcd81d16..d39fa33a1 100644
--- a/service/java/com/android/server/wifi/hotspot2/omadm/OMAParser.java
+++ b/service/java/com/android/server/wifi/hotspot2/omadm/OMAParser.java
@@ -26,6 +26,9 @@ public class OMAParser extends DefaultHandler {
}
public MOTree parse(String text, String urn) throws IOException, SAXException {
+ if (text == null) {
+ throw new IOException("Missing text string");
+ }
try {
SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
parser.parse(new InputSource(new StringReader(text)), this);
diff --git a/service/java/com/android/server/wifi/util/ScanDetailUtil.java b/service/java/com/android/server/wifi/util/ScanDetailUtil.java
index a83900e0a..c5ec92af9 100644
--- a/service/java/com/android/server/wifi/util/ScanDetailUtil.java
+++ b/service/java/com/android/server/wifi/util/ScanDetailUtil.java
@@ -37,4 +37,12 @@ public class ScanDetailUtil {
scanResult.informationElements, scanResult.anqpLines, scanResult.frequency);
return new ScanDetail(scanResult, networkDetail, null);
}
+
+ /**
+ * Helper method to quote the SSID in Scan result to use for comparing/filling SSID stored in
+ * WifiConfiguration object.
+ */
+ public static String createQuotedSSID(String ssid) {
+ return "\"" + ssid + "\"";
+ }
}
diff --git a/tests/wifitests/src/com/android/server/wifi/PasspointManagementObjectManagerTest.java b/tests/wifitests/src/com/android/server/wifi/PasspointManagementObjectManagerTest.java
index c76bf91a3..d3022b932 100644
--- a/tests/wifitests/src/com/android/server/wifi/PasspointManagementObjectManagerTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/PasspointManagementObjectManagerTest.java
@@ -193,6 +193,21 @@ public class PasspointManagementObjectManagerTest {
assertEquals("testIdentity1", homeSP.getCredential().getUserName());
}
+ /** Verify IOException is thrown when trying to add a SP from a null XML string. */
+ @Test(expected = IOException.class)
+ public void addSPFromNullXmlString() throws Exception {
+ File file = tempFolder.newFile("PerProviderSubscription.conf");
+ PasspointManagementObjectManager moMgr = new PasspointManagementObjectManager(file, true);
+ String xml = null; // Needed to avoid ambiguity on function call.
+ moMgr.addSP(xml);
+ }
+
+ /** Verify IOException is thrown when trying to build a SP from a null XML string. */
+ @Test(expected = IOException.class)
+ public void buildSPFromNullXmlString() throws Exception {
+ PasspointManagementObjectManager.buildSP(null);
+ }
+
/** verify that xml serialization/deserialization works */
public void checkXml() throws Exception {
InputStream in = getClass().getClassLoader().getResourceAsStream(R2_TTLS_XML_FILE);
@@ -268,6 +283,27 @@ public class PasspointManagementObjectManagerTest {
assertEquals(9, homeSP.getUpdateIdentifier());
}
+ /** Verify IOException is thrown when trying to modify a SP using a null XML string. */
+ @Test(expected = IOException.class)
+ public void modifySPFromNullXmlString() throws Exception {
+ File file = createFileFromResource(R2_CONFIG_FILE);
+ PasspointManagementObjectManager moMgr = new PasspointManagementObjectManager(file, true);
+ List<HomeSP> homeSPs = moMgr.loadAllSPs();
+ assertEquals(2, homeSPs.size());
+
+ /* PasspointManagementObjectDefinition with null xmlTree. */
+ String urn = "wfa:mo:hotspot2dot0-perprovidersubscription:1.0";
+ String baseUri = "./Wi-Fi/wi-fi.org/PerProviderSubscription/UpdateIdentifier";
+ String xmlTree = null;
+
+ PasspointManagementObjectDefinition moDef =
+ new PasspointManagementObjectDefinition(baseUri, urn, xmlTree);
+ List<PasspointManagementObjectDefinition> moDefs =
+ new ArrayList<PasspointManagementObjectDefinition>();
+ moDefs.add(moDef);
+ moMgr.modifySP("wi-fi.org", moDefs);
+ }
+
/** verify removing an existing service provider works */
@Test
public void removeSP() throws Exception {
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java b/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java
index a5850005f..fab06bd56 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java
@@ -1060,9 +1060,12 @@ public class WifiConfigManagerTest {
config.priority = rand.nextInt(10000);
config.getNetworkSelectionStatus().setNetworkSelectionStatus(
networkSelectionStatusValues.pop());
- networkSelectionStatusToNetworkIdMap.put(
- config.getNetworkSelectionStatus().getNetworkSelectionStatus(),
- config.networkId);
+ // Permanently disabled networks should not be present in PNO scan request.
+ if (!config.getNetworkSelectionStatus().isNetworkPermanentlyDisabled()) {
+ networkSelectionStatusToNetworkIdMap.put(
+ config.getNetworkSelectionStatus().getNetworkSelectionStatus(),
+ config.networkId);
+ }
Log.i(TAG, "networkID: " + config.networkId + ", NetworkSelectionStatus: "
+ config.getNetworkSelectionStatus().getNetworkSelectionStatus());
}
@@ -1150,9 +1153,12 @@ public class WifiConfigManagerTest {
config.priority = rand.nextInt(10000);
config.getNetworkSelectionStatus().setNetworkSelectionStatus(
networkSelectionStatusValues.pop());
- networkSelectionStatusToNetworkIdMap.put(
- config.getNetworkSelectionStatus().getNetworkSelectionStatus(),
- config.networkId);
+ // Permanently disabled networks should not be present in PNO scan request.
+ if (!config.getNetworkSelectionStatus().isNetworkPermanentlyDisabled()) {
+ networkSelectionStatusToNetworkIdMap.put(
+ config.getNetworkSelectionStatus().getNetworkSelectionStatus(),
+ config.networkId);
+ }
Log.i(TAG, "networkID: " + config.networkId + ", NetworkSelectionStatus: "
+ config.getNetworkSelectionStatus().getNetworkSelectionStatus());
}
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiQualifiedNetworkSelectorTest.java b/tests/wifitests/src/com/android/server/wifi/WifiQualifiedNetworkSelectorTest.java
index 1726e7d32..c97618d6a 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiQualifiedNetworkSelectorTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiQualifiedNetworkSelectorTest.java
@@ -23,9 +23,12 @@ import static com.android.server.wifi.WifiConfigurationTestUtil.generateWifiConf
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+import org.mockito.AdditionalAnswers;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyObject;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.validateMockitoUsage;
@@ -41,11 +44,14 @@ import android.net.wifi.WifiEnterpriseConfig;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiSsid;
import android.os.SystemClock;
+import android.os.UserManager;
import android.test.suitebuilder.annotation.SmallTest;
import android.util.LocalLog;
+import com.android.server.wifi.NetworkUpdateResult;
import com.android.internal.R;
import com.android.server.wifi.MockAnswerUtil.AnswerWithArguments;
+import com.android.server.wifi.util.ScanDetailUtil;
import org.junit.After;
import org.junit.Before;
@@ -79,6 +85,31 @@ public class WifiQualifiedNetworkSelectorTest {
mWifiQualifiedNetworkSelector.setUserPreferredBand(1);
mWifiQualifiedNetworkSelector.setWifiNetworkScoreCache(mScoreCache);
when(mClock.elapsedRealtime()).thenReturn(SystemClock.elapsedRealtime());
+
+ //setup Carrier Networks
+ int eapType = 4;
+
+ WifiConfiguration wifiConfig = new WifiConfiguration();
+ wifiConfig.SSID = "\"TEST1\"";
+ wifiConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP);
+ wifiConfig.enterpriseConfig = new WifiEnterpriseConfig();
+ wifiConfig.enterpriseConfig.setEapMethod(eapType);
+ mCarrierConfiguredNetworks.add(wifiConfig);
+
+ WifiConfiguration wifiConfig1 = new WifiConfiguration();
+ wifiConfig1.SSID = "\"TEST2\"";
+ wifiConfig1.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP);
+ wifiConfig1.enterpriseConfig = new WifiEnterpriseConfig();
+ wifiConfig1.enterpriseConfig.setEapMethod(eapType);
+ mCarrierConfiguredNetworks.add(wifiConfig1);
+
+ WifiConfiguration wifiConfig2 = new WifiConfiguration();
+ wifiConfig2.SSID = "\"TEST3\"";
+ wifiConfig2.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP);
+ wifiConfig2.enterpriseConfig = new WifiEnterpriseConfig();
+ wifiConfig2.enterpriseConfig.setEapMethod(eapType);
+ mCarrierConfiguredNetworks.add(wifiConfig2);
+ mWifiQualifiedNetworkSelector.setCarrierConfiguredNetworks(mCarrierConfiguredNetworks);
}
@After
@@ -98,6 +129,7 @@ public class WifiQualifiedNetworkSelectorTest {
private static final String[] DEFAULT_SSIDS = {"\"test1\"", "\"test2\""};
private static final String[] DEFAULT_BSSIDS = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"};
private static final String TAG = "QNS Unit Test";
+ List<WifiConfiguration> mCarrierConfiguredNetworks = new ArrayList<WifiConfiguration>();
private List<ScanDetail> getScanDetails(String[] ssids, String[] bssids, int[] frequencies,
String[] caps, int[] levels) {
@@ -1070,6 +1102,10 @@ public class WifiQualifiedNetworkSelectorTest {
//first QNS
mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, false, scanDetails, false,
false, true, false);
+ when(mWifiInfo.getNetworkId()).thenReturn(1);
+ when(mWifiInfo.getBSSID()).thenReturn(bssids[1]);
+ when(mWifiInfo.is24GHz()).thenReturn(false);
+ when(mWifiConfigManager.getEnableAutoJoinWhenAssociated()).thenReturn(true);
//immediately second QNS
WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(true,
false, scanDetails, false, true, false, false);
@@ -1879,10 +1915,12 @@ public class WifiQualifiedNetworkSelectorTest {
// The second scan result is for an ephemeral network which was previously deleted
when(mWifiConfigManager
- .wasEphemeralNetworkDeleted(scanDetails.get(0).getScanResult().SSID))
+ .wasEphemeralNetworkDeleted(ScanDetailUtil.createQuotedSSID(
+ scanDetails.get(0).getScanResult().SSID)))
.thenReturn(false);
when(mWifiConfigManager
- .wasEphemeralNetworkDeleted(scanDetails.get(1).getScanResult().SSID))
+ .wasEphemeralNetworkDeleted(ScanDetailUtil.createQuotedSSID(
+ scanDetails.get(1).getScanResult().SSID)))
.thenReturn(true);
WifiConfiguration.NetworkSelectionStatus selectionStatus =
@@ -2325,4 +2363,323 @@ public class WifiQualifiedNetworkSelectorTest {
false, scanDetails, false, true, false, false);
verifySelectedResult(chosenScanResult, candidate);
}
+
+ /**
+ * Case #48 no new QNS if current network doesn't show up in the
+ * scan results.
+ *
+ * In this test. we simulate following scenario:
+ * WifiStateMachine is under connected state and 2.4GHz test1 is connected.
+ * The second scan results contains test2 which is 5GHz but no test1. Skip
+ * QNS to avoid aggressive network switching.
+ *
+ * expected return null
+ */
+ @Test
+ public void noNewQNSCurrentNetworkNotInScanResults() {
+ //Prepare saved network configurations.
+ String[] ssidsConfig = DEFAULT_SSIDS;
+ int[] security = {SECURITY_PSK, SECURITY_PSK};
+ WifiConfiguration[] savedConfigs = generateWifiConfigurations(ssidsConfig, security);
+ prepareConfigStore(savedConfigs);
+ final List<WifiConfiguration> savedNetwork = Arrays.asList(savedConfigs);
+ when(mWifiConfigManager.getSavedNetworks()).thenReturn(savedNetwork);
+
+ //Prepare the first scan results.
+ String[] ssids = {DEFAULT_SSIDS[0]};
+ String[] bssids = {DEFAULT_BSSIDS[0]};
+ int[] frequencies = {2437};
+ String[] caps = {"[WPA2-EAP-CCMP][ESS]"};
+ int[] levels = {-78};
+ List<ScanDetail> scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels);
+ scanResultLinkConfiguration(savedConfigs, scanDetails);
+
+ //Connect to test1.
+ mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, false, scanDetails, false,
+ false, true, false);
+
+ when(mWifiInfo.getNetworkId()).thenReturn(1);
+ when(mWifiInfo.getBSSID()).thenReturn(bssids[0]);
+ when(mWifiInfo.is24GHz()).thenReturn(true);
+ mWifiQualifiedNetworkSelector.setWifiNetworkScoreCache(null);
+ when(mWifiConfigManager.getEnableAutoJoinWhenAssociated()).thenReturn(true);
+ when(mClock.elapsedRealtime()).thenReturn(SystemClock.elapsedRealtime() + 11 * 1000);
+
+ //Prepare the second scan results which doesn't contain test1.
+ ssids[0] = DEFAULT_SSIDS[1];
+ bssids[0] = DEFAULT_BSSIDS[1];
+ frequencies[0] = 5180;
+ caps[0] = "[WPA2-EAP-CCMP][ESS]";
+ levels[0] = WifiQualifiedNetworkSelector.QUALIFIED_RSSI_5G_BAND;
+ scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels);
+ scanResultLinkConfiguration(savedConfigs, scanDetails);
+
+ //Skip the second network selection since current connected network is
+ //missing from the scan results.
+ WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false,
+ false, scanDetails, false, true, false, false);
+ assertEquals("Expect no network selection", null, candidate);
+ }
+
+ boolean compareCarrierConfigs(WifiConfiguration candidate, WifiConfiguration carrierConfig) {
+ if (!candidate.SSID.equals(carrierConfig.SSID)) {
+ return false;
+ }
+ if (!candidate.ephemeral || carrierConfig.ephemeral) {
+ return false;
+ }
+ if (!candidate.isCarrierNetwork || carrierConfig.isCarrierNetwork) {
+ return false;
+ }
+ if (candidate.enterpriseConfig.getEapMethod() !=
+ carrierConfig.enterpriseConfig.getEapMethod()) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Case #49 Between two 2G Carrier networks, choose the one with stronger RSSI value
+ * if other conditions are the same and the RSSI values are not staturated.
+ */
+ @Test
+ public void chooseStrongerRssi2GCarrierNetwork() {
+
+ String[] ssids = {"TEST1", "TEST2"};
+ String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"};
+ int[] frequencies = {2470, 2437};
+ String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]"};
+ int[] levels = {-65,-55};
+ int[] security = {SECURITY_PSK, SECURITY_PSK};
+
+ List<ScanDetail> scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels);
+ ScanResult chosenScanResult = scanDetails.get(1).getScanResult();
+ when(mWifiConfigManager.updateSavedNetworkWithNewScanDetail(any(ScanDetail.class),
+ any(Boolean.class))).thenReturn(null);
+ when(mWifiConfigManager.saveNetworkAndSetCandidate(any(WifiConfiguration.class),
+ any(ScanResult.class))).then(AdditionalAnswers.returnsFirstArg());
+ when(mWifiConfigManager.getScanResultCandidate(any(WifiConfiguration.class)))
+ .thenReturn(chosenScanResult);
+ when(mWifiConfigManager.getIsCarrierNetworkEnabledByUser()).thenReturn(true);
+
+ WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false,
+ false, scanDetails, false, false, true, false);
+ assertTrue(compareCarrierConfigs(candidate, mCarrierConfiguredNetworks.get(1)));
+ }
+
+
+ /**
+ * Case #50 Choose 5G over 2G.
+ */
+ @Test
+ public void choose5GNetworkOver2GNetwork() {
+
+ String[] ssids = {"TEST1", "TEST2"};
+ String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"};
+ int[] frequencies = {2437, 5240};
+ String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]"};
+ int[] levels = {-65,-55};
+
+ List<ScanDetail> scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels);
+ ScanResult chosenScanResult = scanDetails.get(1).getScanResult();
+ when(mWifiConfigManager.updateSavedNetworkWithNewScanDetail(any(ScanDetail.class),
+ any(Boolean.class))).thenReturn(null);
+ when(mWifiConfigManager.saveNetworkAndSetCandidate(any(WifiConfiguration.class),
+ any(ScanResult.class))).then(AdditionalAnswers.returnsFirstArg());
+ when(mWifiConfigManager.getScanResultCandidate(any(WifiConfiguration.class)))
+ .thenReturn(chosenScanResult);
+ when(mWifiConfigManager.getIsCarrierNetworkEnabledByUser()).thenReturn(true);
+
+ WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false,
+ false, scanDetails, false, false, true, false);
+ assertTrue(compareCarrierConfigs(candidate, mCarrierConfiguredNetworks.get(1)));
+ }
+
+ /**
+ * Case #51 Stay on same BSSID & SSID.
+ */
+ @Test
+ public void chooseSameNetwork() {
+
+ String[] ssids = {"TEST1", "TEST2"};
+ String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"};
+ int[] frequencies = {2470, 2437};
+ String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]"};
+ int[] levels = {-65,-55};
+ int[] security = {SECURITY_PSK, SECURITY_PSK};
+
+ List<ScanDetail> scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels);
+ WifiConfiguration[] savedConfigs = generateWifiConfigurations(ssids, security);
+ prepareConfigStore(savedConfigs);
+
+ ScanResult chosenScanResult = scanDetails.get(0).getScanResult();
+ when(mWifiConfigManager.updateSavedNetworkWithNewScanDetail(any(ScanDetail.class),
+ any(Boolean.class))).thenReturn(null);
+ when(mWifiConfigManager.saveNetworkAndSetCandidate(any(WifiConfiguration.class),
+ any(ScanResult.class))).then(AdditionalAnswers.returnsFirstArg());
+ when(mWifiConfigManager.getScanResultCandidate(any(WifiConfiguration.class)))
+ .thenReturn(chosenScanResult);
+ when(mWifiInfo.getNetworkId()).thenReturn(0);
+ when(mWifiInfo.getBSSID()).thenReturn(bssids[0]);
+ when(mWifiConfigManager.getIsCarrierNetworkEnabledByUser()).thenReturn(true);
+
+ WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false,
+ false, scanDetails, false, true, false, false);
+
+ assertTrue(compareCarrierConfigs(candidate, mCarrierConfiguredNetworks.get(0)));
+ }
+
+ /**
+ * Case #52 Test condition where no Carrier networks are defined.
+ */
+ @Test
+ public void testNoCarrierNetworks() {
+
+ String[] ssids = {"TEST1", "TEST2"};
+ String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"};
+ int[] frequencies = {5200, 5240};
+ String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]"};
+ // test2 has slightly stronger RSSI value than test1
+ int[] levels = {-65,-53};
+
+ List<ScanDetail> scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels);
+
+ List<WifiConfiguration> nullCarrierConfiguredNetworks = new ArrayList<WifiConfiguration>();
+ mWifiQualifiedNetworkSelector.setCarrierConfiguredNetworks(nullCarrierConfiguredNetworks);
+ when(mWifiConfigManager.getIsCarrierNetworkEnabledByUser()).thenReturn(true);
+
+ WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false,
+ true, scanDetails, false, false, true, false);
+ assertEquals("Expect no network selection", null, candidate);
+ }
+
+ /**
+ * Case #53 Test condition where no Carrier networks are defined.
+ */
+ @Test
+ public void testParseCarrierInfoSuccess() {
+ String[] wifiArray = new String[3];
+ wifiArray[0] = "V2lmaSBFeHRyYQ==|2|4";
+ wifiArray[1] = "R29vZ2xlLUE=|2|4";
+ wifiArray[2] = "R29vZ2xlLUd1ZXN0|2|4";
+
+ List<WifiConfiguration> configList =
+ mWifiQualifiedNetworkSelector.parseCarrierSuppliedWifiInfo(wifiArray);
+ assertEquals("Expect right number of etnries", configList.size(), 3);
+ assertEquals("Expect right network", configList.get(0).SSID, "\"Wifi Extra\"");
+ assertEquals("Expect right network", configList.get(1).SSID, "\"Google-A\"");
+ assertEquals("Expect right network", configList.get(2).SSID, "\"Google-Guest\"");
+ assertTrue("Expect right key",
+ configList.get(0).allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_EAP));
+ assertEquals("Expect right EAP method",
+ configList.get(0).enterpriseConfig.getEapMethod(), 4);
+ }
+
+ /**
+ * Case #54 Test condition where string has non-numerics.
+ */
+ @Test
+ public void testParseCarrierInfoBadEntries1() {
+ String[] wifiArray = new String[3];
+ wifiArray[0] = "V2lmaSBFeHRyYQ==|2|4";
+ wifiArray[1] = "R29vZ2xlLUE=|2|A"; //Invalid entry. Non-numeric.
+ wifiArray[2] = "R29vZ2xlLUd1ZXN0|2|4";
+
+ List<WifiConfiguration> configList =
+ mWifiQualifiedNetworkSelector.parseCarrierSuppliedWifiInfo(wifiArray);
+ assertEquals("Expect right number of etnries", configList.size(), 2);
+ assertEquals("Expect right network", configList.get(0).SSID, "\"Wifi Extra\"");
+ assertEquals("Expect right network", configList.get(1).SSID, "\"Google-Guest\"");
+ }
+
+ /**
+ * Case #55 Test condition where the config does not have the right number of entries.
+ */
+ @Test
+ public void testParseCarrierInfoBadEntries2() {
+ String[] wifiArray = new String[3];
+ wifiArray[0] = "V2lmaSBFeHRyYQ==|2"; //Invalid number of entries
+ wifiArray[1] = "R29vZ2xlLUE=|2|4";
+ wifiArray[2] = "R29vZ2xlLUd1ZXN0|2|4";
+
+ List<WifiConfiguration> configList =
+ mWifiQualifiedNetworkSelector.parseCarrierSuppliedWifiInfo(wifiArray);
+ assertEquals("Expect right network", configList.get(0).SSID, "\"Google-A\"");
+ assertEquals("Expect right network", configList.get(1).SSID, "\"Google-Guest\"");
+ }
+
+ /**
+ * Case #56 Test invalid base-64.
+ */
+ @Test
+ public void testParseCarrierInfoBadBase64() {
+ String[] wifiArray = new String[3];
+ wifiArray[0] = "V2lmaSBFeHRyYQ==|2|4";
+ wifiArray[1] = "xyz==|2|4"; //Invalid base64
+ wifiArray[2] = "R29vZ2xlLUd1ZXN0|2|4";
+
+ List<WifiConfiguration> configList =
+ mWifiQualifiedNetworkSelector.parseCarrierSuppliedWifiInfo(wifiArray);
+ assertEquals("Expect right network", configList.get(0).SSID, "\"Wifi Extra\"");
+ assertEquals("Expect right network", configList.get(1).SSID, "\"Google-Guest\"");
+ }
+
+ /**
+ * Case #56 Test invalid eap-method
+ */
+ @Test
+ public void testParseCarrierInfoBadEapMethod() {
+ String[] wifiArray = new String[3];
+ wifiArray[0] = "V2lmaSBFeHRyYQ==|2|4";
+ wifiArray[1] = "R29vZ2xlLUE=|2|4";
+ wifiArray[2] = "R29vZ2xlLUd1ZXN0|2|11"; //Invalid eap-method
+
+ List<WifiConfiguration> configList =
+ mWifiQualifiedNetworkSelector.parseCarrierSuppliedWifiInfo(wifiArray);
+ assertEquals("Expect right network", configList.get(0).SSID, "\"Wifi Extra\"");
+ assertEquals("Expect right network", configList.get(1).SSID, "\"Google-A\"");
+ }
+
+ /**
+ * Case #56 Test invalid key
+ */
+ @Test
+ public void testParseCarrierInfoBadKey() {
+ String[] wifiArray = new String[3];
+ wifiArray[0] = "V2lmaSBFeHRyYQ==|2|4";
+ wifiArray[1] = "R29vZ2xlLUE=|9|4"; //Invalid key
+ wifiArray[2] = "R29vZ2xlLUd1ZXN0|2|4";
+
+ List<WifiConfiguration> configList =
+ mWifiQualifiedNetworkSelector.parseCarrierSuppliedWifiInfo(wifiArray);
+ assertEquals("Expect right network", configList.get(0).SSID, "\"Wifi Extra\"");
+ assertEquals("Expect right network", configList.get(2).SSID, "\"Google-Guest\"");
+ }
+
+ /**
+ * Case #57 Test condition where no Carrier networks are defined.
+ */
+ @Test
+ public void testCarrierNotEnabledByUser() {
+
+ String[] ssids = {"TEST1", "TEST2"};
+ String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"};
+ int[] frequencies = {2437, 5240};
+ String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]"};
+ int[] levels = {-65,-55};
+
+ List<ScanDetail> scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels);
+ ScanResult chosenScanResult = scanDetails.get(1).getScanResult();
+ when(mWifiConfigManager.updateSavedNetworkWithNewScanDetail(any(ScanDetail.class),
+ any(Boolean.class))).thenReturn(null);
+ when(mWifiConfigManager.saveNetworkAndSetCandidate(any(WifiConfiguration.class),
+ any(ScanResult.class))).then(AdditionalAnswers.returnsFirstArg());
+ when(mWifiConfigManager.getScanResultCandidate(any(WifiConfiguration.class)))
+ .thenReturn(chosenScanResult);
+ when(mWifiConfigManager.getIsCarrierNetworkEnabledByUser()).thenReturn(false);
+
+ WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false,
+ false, scanDetails, false, false, true, false);
+ assertEquals("Expect no network selection", null, candidate);
+ }
}
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiStateMachineTest.java b/tests/wifitests/src/com/android/server/wifi/WifiStateMachineTest.java
index a881d8f04..f3fe0cda2 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiStateMachineTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiStateMachineTest.java
@@ -1224,4 +1224,44 @@ public class WifiStateMachineTest {
mWsm.enableVerboseLogging(1);
verify(mPropertyService, never()).set(anyString(), anyString());
}
+
+ private int testGetSupportedFeaturesCase(int supportedFeatures, boolean rttConfigured) {
+ AsyncChannel channel = mock(AsyncChannel.class);
+ Message reply = Message.obtain();
+ reply.arg1 = supportedFeatures;
+ reset(mPropertyService); // Ignore calls made in setUp()
+ when(channel.sendMessageSynchronously(WifiStateMachine.CMD_GET_SUPPORTED_FEATURES))
+ .thenReturn(reply);
+ when(mPropertyService.getBoolean("config.disable_rtt", false))
+ .thenReturn(rttConfigured);
+ return mWsm.syncGetSupportedFeatures(channel);
+ }
+
+ /** Verifies that syncGetSupportedFeatures() masks out capabilities based on system flags. */
+ @Test
+ public void syncGetSupportedFeatures() {
+ final int featureNan = WifiManager.WIFI_FEATURE_NAN;
+ final int featureInfra = WifiManager.WIFI_FEATURE_INFRA;
+ final int featureD2dRtt = WifiManager.WIFI_FEATURE_D2D_RTT;
+ final int featureD2apRtt = WifiManager.WIFI_FEATURE_D2AP_RTT;
+
+ assertEquals(0, testGetSupportedFeaturesCase(0, false));
+ assertEquals(0, testGetSupportedFeaturesCase(0, true));
+ assertEquals(featureNan | featureInfra,
+ testGetSupportedFeaturesCase(featureNan | featureInfra, false));
+ assertEquals(featureNan | featureInfra,
+ testGetSupportedFeaturesCase(featureNan | featureInfra, true));
+ assertEquals(featureInfra | featureD2dRtt,
+ testGetSupportedFeaturesCase(featureInfra | featureD2dRtt, false));
+ assertEquals(featureInfra,
+ testGetSupportedFeaturesCase(featureInfra | featureD2dRtt, true));
+ assertEquals(featureInfra | featureD2apRtt,
+ testGetSupportedFeaturesCase(featureInfra | featureD2apRtt, false));
+ assertEquals(featureInfra,
+ testGetSupportedFeaturesCase(featureInfra | featureD2apRtt, true));
+ assertEquals(featureInfra | featureD2dRtt | featureD2apRtt,
+ testGetSupportedFeaturesCase(featureInfra | featureD2dRtt | featureD2apRtt, false));
+ assertEquals(featureInfra,
+ testGetSupportedFeaturesCase(featureInfra | featureD2dRtt | featureD2apRtt, true));
+ }
}