Merge changes I5d55b287,I3d39c193,If60282ad,I132fd395,I09a7f6f5
* changes:
WifiLog: add CheckReturnValue annotation
logging: add convenience APIs for literal messages
WifiDiagnostics: migrate to chained logging API
logging: add chained logging API
WifiDiagnostics: remove getAllRingBufferData()
diff --git a/service/java/com/android/server/wifi/ScanDetail.java b/service/java/com/android/server/wifi/ScanDetail.java
index 23e52db..dba8ab3 100644
--- a/service/java/com/android/server/wifi/ScanDetail.java
+++ b/service/java/com/android/server/wifi/ScanDetail.java
@@ -50,7 +50,7 @@
networkDetail.getAnqpDomainID(), networkDetail.getOsuProviders(),
caps, level, frequency, tsf);
mSeen = System.currentTimeMillis();
- //mScanResult.seen = mSeen;
+ mScanResult.seen = mSeen;
mScanResult.channelWidth = networkDetail.getChannelWidth();
mScanResult.centerFreq0 = networkDetail.getCenterfreq0();
mScanResult.centerFreq1 = networkDetail.getCenterfreq1();
@@ -70,7 +70,7 @@
mNetworkDetail = null;
mScanResult = new ScanResult(wifiSsid, bssid, 0L, -1, null, caps, level, frequency, tsf);
mSeen = seen;
- //mScanResult.seen = mSeen;
+ mScanResult.seen = mSeen;
mScanResult.channelWidth = 0;
mScanResult.centerFreq0 = 0;
mScanResult.centerFreq1 = 0;
diff --git a/service/java/com/android/server/wifi/WifiConfigManagerNew.java b/service/java/com/android/server/wifi/WifiConfigManagerNew.java
index 922405f..2dc77cd 100644
--- a/service/java/com/android/server/wifi/WifiConfigManagerNew.java
+++ b/service/java/com/android/server/wifi/WifiConfigManagerNew.java
@@ -40,6 +40,7 @@
import android.util.LocalLog;
import android.util.Log;
+import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.LocalServices;
import com.android.server.wifi.util.ScanResultUtil;
@@ -51,6 +52,7 @@
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
@@ -139,6 +141,17 @@
@VisibleForTesting
public static final int SCAN_CACHE_ENTRIES_TRIM_SIZE = 128;
/**
+ * Link networks only if they have less than this number of scan cache entries.
+ */
+ @VisibleForTesting
+ public static final int LINK_CONFIGURATION_MAX_SCAN_CACHE_ENTRIES = 6;
+ /**
+ * Link networks only if the bssid in scan results for the networks match in the first
+ * 16 ASCII chars in the bssid string. For example = "af:de:56;34:15:7"
+ */
+ @VisibleForTesting
+ public static final int LINK_CONFIGURATION_BSSID_MATCH_LENGTH = 16;
+ /**
* Flags to be passed in for |canModifyNetwork| to decide if the change is minor and can
* bypass the lockdown checks.
*/
@@ -202,7 +215,15 @@
* The SSIDs are encoded in a String as per definition of WifiConfiguration.SSID field.
*/
private final Set<String> mDeletedEphemeralSSIDs;
-
+ /**
+ * Flag to indicate if only networks with the same psk should be linked.
+ * TODO(b/30706406): Remove this flag if unused.
+ */
+ private final boolean mOnlyLinkSameCredentialConfigurations;
+ /**
+ * Number of channels to scan for during partial scans initiated while connected.
+ */
+ private final int mMaxNumActiveChannelsForPartialScans;
/**
* Verbose logging flag. Toggled by developer options.
*/
@@ -233,7 +254,12 @@
mConfiguredNetworks = new ConfigurationMap(userManager);
mScanDetailCaches = new ConcurrentHashMap<>(16, 0.75f, 2);
- mDeletedEphemeralSSIDs = new HashSet<String>();
+ mDeletedEphemeralSSIDs = new HashSet<>();
+
+ mOnlyLinkSameCredentialConfigurations = mContext.getResources().getBoolean(
+ R.bool.config_wifi_only_link_same_credential_configurations);
+ mMaxNumActiveChannelsForPartialScans = mContext.getResources().getInteger(
+ R.integer.config_wifi_framework_associated_partial_scan_max_num_active_channels);
}
/**
@@ -403,7 +429,12 @@
if (internalConfig != null) {
return internalConfig;
}
- return mConfiguredNetworks.getByConfigKeyForCurrentUser(config.configKey());
+ internalConfig = mConfiguredNetworks.getByConfigKeyForCurrentUser(config.configKey());
+ if (internalConfig == null) {
+ Log.e(TAG, "Cannot find network with networkId " + config.networkId
+ + " or configKey " + config.configKey());
+ }
+ return internalConfig;
}
/**
@@ -411,7 +442,24 @@
* provided network ID in our database.
*/
private WifiConfiguration getInternalConfiguredNetwork(int networkId) {
- return mConfiguredNetworks.getForCurrentUser(networkId);
+ WifiConfiguration internalConfig = mConfiguredNetworks.getForCurrentUser(networkId);
+ if (internalConfig == null) {
+ Log.e(TAG, "Cannot find network with networkId " + networkId);
+ }
+ return internalConfig;
+ }
+
+ /**
+ * Helper method to retrieve the internal WifiConfiguration object corresponding to the
+ * provided configKey in our database.
+ */
+ private WifiConfiguration getInternalConfiguredNetwork(String configKey) {
+ WifiConfiguration internalConfig =
+ mConfiguredNetworks.getByConfigKeyForCurrentUser(configKey);
+ if (internalConfig == null) {
+ Log.e(TAG, "Cannot find network with configKey " + configKey);
+ }
+ return internalConfig;
}
/**
@@ -870,7 +918,6 @@
public boolean removeNetwork(int networkId) {
WifiConfiguration config = getInternalConfiguredNetwork(networkId);
if (config == null) {
- Log.e(TAG, "Cannot find network with networkId " + networkId);
return false;
}
if (!removeNetworkInternal(config)) {
@@ -1000,7 +1047,7 @@
*
* Each network has 2 status:
* 1. NetworkSelectionStatus: This is internal selection status of the network. This is used
- * for temporarily disabling a network for QNS.
+ * for temporarily disabling a network for Network Selector.
* 2. Status: This is the exposed status for a network. This is mostly set by
* the public API's {@link WifiManager#enableNetwork(int, boolean)} &
* {@link WifiManager#disableNetwork(int)}.
@@ -1012,7 +1059,6 @@
public boolean updateNetworkSelectionStatus(int networkId, int reason) {
WifiConfiguration config = getInternalConfiguredNetwork(networkId);
if (config == null) {
- Log.e(TAG, "Cannot find network with networkId " + networkId);
return false;
}
return updateNetworkSelectionStatus(config, reason);
@@ -1061,7 +1107,6 @@
public boolean tryEnableNetwork(int networkId) {
WifiConfiguration config = getInternalConfiguredNetwork(networkId);
if (config == null) {
- Log.e(TAG, "Cannot find network with networkId " + networkId);
return false;
}
return tryEnableNetwork(config);
@@ -1077,7 +1122,6 @@
public boolean enableNetwork(int networkId, int uid) {
WifiConfiguration config = getInternalConfiguredNetwork(networkId);
if (config == null) {
- Log.e(TAG, "Cannot find network with networkId " + networkId);
return false;
}
if (!canModifyNetwork(config, uid, DISALLOW_LOCKDOWN_CHECK_BYPASS)) {
@@ -1099,7 +1143,6 @@
public boolean disableNetwork(int networkId, int uid) {
WifiConfiguration config = getInternalConfiguredNetwork(networkId);
if (config == null) {
- Log.e(TAG, "Cannot find network with networkId " + networkId);
return false;
}
if (!canModifyNetwork(config, uid, DISALLOW_LOCKDOWN_CHECK_BYPASS)) {
@@ -1123,7 +1166,6 @@
public boolean checkAndUpdateLastConnectUid(int networkId, int uid) {
WifiConfiguration config = getInternalConfiguredNetwork(networkId);
if (config == null) {
- Log.e(TAG, "Cannot find network with networkId " + networkId);
return false;
}
if (!canModifyNetwork(config, uid, ALLOW_LOCKDOWN_CHECK_BYPASS)) {
@@ -1149,7 +1191,6 @@
public boolean updateNetworkAfterConnect(int networkId) {
WifiConfiguration config = getInternalConfiguredNetwork(networkId);
if (config == null) {
- Log.e(TAG, "Cannot find network with networkId " + networkId);
return false;
}
config.lastConnected = mClock.getWallClockMillis();
@@ -1160,13 +1201,75 @@
}
/**
+ * Set default GW MAC address for the provided network.
+ *
+ * @param networkId network ID corresponding to the network.
+ * @param macAddress MAC address of the gateway to be set.
+ * @return true if the network was found, false otherwise.
+ */
+ public boolean setNetworkDefaultGwMacAddress(int networkId, String macAddress) {
+ WifiConfiguration config = getInternalConfiguredNetwork(networkId);
+ if (config == null) {
+ return false;
+ }
+ config.defaultGwMacAddress = macAddress;
+ return true;
+ }
+
+ /**
+ * Helper method to clear the {@link NetworkSelectionStatus#mCandidate},
+ * {@link NetworkSelectionStatus#mCandidateScore} &
+ * {@link NetworkSelectionStatus#mSeenInLastQualifiedNetworkSelection} for the provided network.
+ *
+ * This is invoked by Network Selector at the start of every selection procedure to clear all
+ * configured networks' scan-result-candidates.
+ *
+ * @param networkId network ID corresponding to the network.
+ * @return true if the network was found, false otherwise.
+ */
+ public boolean clearNetworkCandidateScanResult(int networkId) {
+ WifiConfiguration config = getInternalConfiguredNetwork(networkId);
+ if (config == null) {
+ return false;
+ }
+ config.getNetworkSelectionStatus().setCandidate(null);
+ config.getNetworkSelectionStatus().setCandidateScore(Integer.MIN_VALUE);
+ config.getNetworkSelectionStatus().setSeenInLastQualifiedNetworkSelection(false);
+ return true;
+ }
+
+ /**
+ * Helper method to set the {@link NetworkSelectionStatus#mCandidate},
+ * {@link NetworkSelectionStatus#mCandidateScore} &
+ * {@link NetworkSelectionStatus#mSeenInLastQualifiedNetworkSelection} for the provided network.
+ *
+ * This is invoked by Network Selector when it sees a network during network selection procedure to set the
+ * scan result candidate.
+ *
+ * @param networkId network ID corresponding to the network.
+ * @param scanResult Candidate ScanResult associated with this network.
+ * @param score Score assigned to the candidate.
+ * @return true if the network was found, false otherwise.
+ */
+ public boolean setNetworkCandidateScanResult(int networkId, ScanResult scanResult, int score) {
+ WifiConfiguration config = getInternalConfiguredNetwork(networkId);
+ if (config == null) {
+ return false;
+ }
+ config.getNetworkSelectionStatus().setCandidate(scanResult);
+ config.getNetworkSelectionStatus().setCandidateScore(score);
+ // Update the network selection status.
+ config.getNetworkSelectionStatus().setSeenInLastQualifiedNetworkSelection(true);
+ return true;
+ }
+
+ /**
* Helper method to get the scan detail cache entry {@link #mScanDetailCaches} for the provided
* network.
*
* @param networkId network ID corresponding to the network.
* @return existing {@link ScanDetailCache} entry if one exists or null.
*/
- @VisibleForTesting
public ScanDetailCache getScanDetailCacheForNetwork(int networkId) {
return mScanDetailCaches.get(networkId);
}
@@ -1183,9 +1286,8 @@
if (config == null) return null;
ScanDetailCache cache = getScanDetailCacheForNetwork(config.networkId);
if (cache == null && config.networkId != WifiConfiguration.INVALID_NETWORK_ID) {
- cache =
- new ScanDetailCache(
- config, SCAN_CACHE_ENTRIES_MAX_SIZE, SCAN_CACHE_ENTRIES_TRIM_SIZE);
+ cache = new ScanDetailCache(
+ config, SCAN_CACHE_ENTRIES_MAX_SIZE, SCAN_CACHE_ENTRIES_TRIM_SIZE);
mScanDetailCaches.put(config.networkId, cache);
}
return cache;
@@ -1226,8 +1328,9 @@
// Add the scan detail to this network's scan detail cache.
scanDetailCache.put(scanDetail);
- // Since we added a scan result to this configuration, re-attempt linking
- // TODO: linkConfiguration(config);
+ // Since we added a scan result to this configuration, re-attempt linking.
+ // TODO: Do we really need to do this after every scan result?
+ attemptNetworkLinking(config);
}
/**
@@ -1277,52 +1380,260 @@
}
/**
- * Helper method to clear the {@link NetworkSelectionStatus#mCandidate},
- * {@link NetworkSelectionStatus#mCandidateScore} &
- * {@link NetworkSelectionStatus#mSeenInLastQualifiedNetworkSelection} for the provided network.
+ * Helper method to check if the 2 provided networks can be linked or not.
+ * Networks are considered for linking if:
+ * 1. Share the same GW MAC address.
+ * 2. Scan results for the networks have AP's with MAC address which differ only in the last
+ * nibble.
*
- * This is invoked by QNS at the start of every selection procedure to clear all configured
- * networks' scan-result-candidates.
- *
- * @param networkId network ID corresponding to the network.
- * @return true if the network was found, false otherwise.
+ * @param network1 WifiConfiguration corresponding to network 1.
+ * @param network2 WifiConfiguration corresponding to network 2.
+ * @param scanDetailCache1 ScanDetailCache entry for network 1.
+ * @param scanDetailCache1 ScanDetailCache entry for network 2.
+ * @return true if the networks should be linked, false if the networks should be unlinked.
*/
- public boolean clearNetworkCandidateScanResult(int networkId) {
- WifiConfiguration config = getInternalConfiguredNetwork(networkId);
- if (config == null) {
- Log.e(TAG, "Cannot find network with networkId " + networkId);
- return false;
+ private boolean shouldNetworksBeLinked(
+ WifiConfiguration network1, WifiConfiguration network2,
+ ScanDetailCache scanDetailCache1, ScanDetailCache scanDetailCache2) {
+ // TODO (b/30706406): Link networks only with same passwords if the
+ // |mOnlyLinkSameCredentialConfigurations| flag is set.
+ if (mOnlyLinkSameCredentialConfigurations) {
+ if (!TextUtils.equals(network1.preSharedKey, network2.preSharedKey)) {
+ if (mVerboseLoggingEnabled) {
+ Log.v(TAG, "shouldNetworksBeLinked unlink due to password mismatch");
+ }
+ return false;
+ }
}
- config.getNetworkSelectionStatus().setCandidate(null);
- config.getNetworkSelectionStatus().setCandidateScore(Integer.MIN_VALUE);
- config.getNetworkSelectionStatus().setSeenInLastQualifiedNetworkSelection(false);
+ if (network1.defaultGwMacAddress != null && network2.defaultGwMacAddress != null) {
+ // If both default GW are known, link only if they are equal
+ if (network1.defaultGwMacAddress.equals(network2.defaultGwMacAddress)) {
+ if (mVerboseLoggingEnabled) {
+ Log.v(TAG, "shouldNetworksBeLinked link due to same gw " + network2.SSID
+ + " and " + network1.SSID + " GW " + network1.defaultGwMacAddress);
+ }
+ return true;
+ }
+ } else {
+ // We do not know BOTH default gateways hence we will try to link
+ // hoping that WifiConfigurations are indeed behind the same gateway.
+ // once both WifiConfiguration have been tried and thus once both default gateways
+ // are known we will revisit the choice of linking them.
+ if (scanDetailCache1 != null && scanDetailCache2 != null) {
+ for (String abssid : scanDetailCache1.keySet()) {
+ for (String bbssid : scanDetailCache2.keySet()) {
+ if (abssid.regionMatches(
+ true, 0, bbssid, 0, LINK_CONFIGURATION_BSSID_MATCH_LENGTH)) {
+ // If first 16 ASCII characters of BSSID matches,
+ // we assume this is a DBDC.
+ if (mVerboseLoggingEnabled) {
+ Log.v(TAG, "shouldNetworksBeLinked link due to DBDC BSSID match "
+ + network2.SSID + " and " + network1.SSID
+ + " bssida " + abssid + " bssidb " + bbssid);
+ }
+ return true;
+ }
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Helper methods to link 2 networks together.
+ *
+ * @param network1 WifiConfiguration corresponding to network 1.
+ * @param network2 WifiConfiguration corresponding to network 2.
+ */
+ private void linkNetworks(WifiConfiguration network1, WifiConfiguration network2) {
+ if (mVerboseLoggingEnabled) {
+ Log.v(TAG, "linkNetworks will link " + network2.configKey()
+ + " and " + network1.configKey());
+ }
+ if (network2.linkedConfigurations == null) {
+ network2.linkedConfigurations = new HashMap<>();
+ }
+ if (network1.linkedConfigurations == null) {
+ network1.linkedConfigurations = new HashMap<>();
+ }
+ // TODO (b/30638473): This needs to become a set instead of map, but it will need
+ // public interface changes and need some migration of existing store data.
+ network2.linkedConfigurations.put(network1.configKey(), 1);
+ network1.linkedConfigurations.put(network2.configKey(), 1);
+ }
+
+ /**
+ * Helper methods to unlink 2 networks from each other.
+ *
+ * @param network1 WifiConfiguration corresponding to network 1.
+ * @param network2 WifiConfiguration corresponding to network 2.
+ */
+ private void unlinkNetworks(WifiConfiguration network1, WifiConfiguration network2) {
+ if (network2.linkedConfigurations != null
+ && (network2.linkedConfigurations.get(network1.configKey()) != null)) {
+ if (mVerboseLoggingEnabled) {
+ Log.v(TAG, "unlinkNetworks un-link " + network1.configKey()
+ + " from " + network2.configKey());
+ }
+ network2.linkedConfigurations.remove(network1.configKey());
+ }
+ if (network1.linkedConfigurations != null
+ && (network1.linkedConfigurations.get(network2.configKey()) != null)) {
+ if (mVerboseLoggingEnabled) {
+ Log.v(TAG, "unlinkNetworks un-link " + network2.configKey()
+ + " from " + network1.configKey());
+ }
+ network1.linkedConfigurations.remove(network2.configKey());
+ }
+ }
+
+ /**
+ * This method runs through all the saved networks and checks if the provided network can be
+ * linked with any of them.
+ *
+ * @param config WifiConfiguration object corresponding to the network that needs to be
+ * checked for potential links.
+ */
+ private void attemptNetworkLinking(WifiConfiguration config) {
+ // Only link WPA_PSK config.
+ if (!config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_PSK)) {
+ return;
+ }
+ ScanDetailCache scanDetailCache = getScanDetailCacheForNetwork(config.networkId);
+ // Ignore configurations with large number of BSSIDs.
+ if (scanDetailCache != null
+ && scanDetailCache.size() > LINK_CONFIGURATION_MAX_SCAN_CACHE_ENTRIES) {
+ return;
+ }
+ for (WifiConfiguration linkConfig : getInternalConfiguredNetworks()) {
+ if (linkConfig.configKey().equals(config.configKey())) {
+ continue;
+ }
+ if (linkConfig.ephemeral) {
+ continue;
+ }
+ // Network Selector will be allowed to dynamically jump from a linked configuration
+ // to another, hence only link configurations that have WPA_PSK security type.
+ if (!linkConfig.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_PSK)) {
+ continue;
+ }
+ ScanDetailCache linkScanDetailCache =
+ getScanDetailCacheForNetwork(linkConfig.networkId);
+ // Ignore configurations with large number of BSSIDs.
+ if (linkScanDetailCache != null
+ && linkScanDetailCache.size() > LINK_CONFIGURATION_MAX_SCAN_CACHE_ENTRIES) {
+ continue;
+ }
+ // Check if the networks should be linked/unlinked.
+ if (shouldNetworksBeLinked(
+ config, linkConfig, scanDetailCache, linkScanDetailCache)) {
+ linkNetworks(config, linkConfig);
+ } else {
+ unlinkNetworks(config, linkConfig);
+ }
+ }
+ }
+
+ /**
+ * Helper method to fetch list of channels for a network from the associated ScanResult's cache
+ * and add it to the provided channel as long as the size of the set is less than
+ * |maxChannelSetSize|.
+ *
+ * @param channelSet Channel set holding all the channels for the network.
+ * @param scanDetailCache ScanDetailCache entry associated with the network.
+ * @param nowInMillis current timestamp to be used for age comparison.
+ * @param ageInMillis only consider scan details whose timestamps are earlier than this
+ * value.
+ * @param maxChannelSetSize Maximum number of channels to be added to the set.
+ * @return false if the list is full, true otherwise.
+ */
+ private boolean addToChannelSetForNetworkFromScanDetailCache(
+ Set<Integer> channelSet, ScanDetailCache scanDetailCache,
+ long nowInMillis, long ageInMillis, int maxChannelSetSize) {
+ if (scanDetailCache != null && scanDetailCache.size() > 0) {
+ for (ScanDetail scanDetail : scanDetailCache.values()) {
+ ScanResult result = scanDetail.getScanResult();
+ boolean valid = (nowInMillis - result.seen) < ageInMillis;
+ if (mVerboseLoggingEnabled) {
+ Log.v(TAG, "fetchChannelSetForNetwork has " + result.BSSID + " freq "
+ + result.frequency + " age " + (nowInMillis - result.seen)
+ + " ?=" + valid);
+ }
+ if (valid) {
+ channelSet.add(result.frequency);
+ }
+ if (channelSet.size() >= maxChannelSetSize) {
+ return false;
+ }
+ }
+ }
return true;
}
/**
- * Helper method to set the {@link NetworkSelectionStatus#mCandidate},
- * {@link NetworkSelectionStatus#mCandidateScore} &
- * {@link NetworkSelectionStatus#mSeenInLastQualifiedNetworkSelection} for the provided network.
+ * Retrieve a set of channels on which AP's for the provided network was seen using the
+ * internal ScanResult's cache {@link #mScanDetailCaches}. This is used for initiating partial
+ * scans for the currently connected network.
*
- * This is invoked by QNS when it sees a network during network selection procedure to set the
- * scan result candidate.
- *
- * @param networkId network ID corresponding to the network.
- * @param scanResult Candidate ScanResult associated with this network.
- * @param score Score assigned to the candidate.
- * @return true if the network was found, false otherwise.
+ * @param networkId network ID corresponding to the network.
+ * @param ageInMillis only consider scan details whose timestamps are earlier than this value.
+ * @return Set containing the frequencies on which this network was found, null if the network
+ * was not found or there are no associated scan details in the cache.
*/
- public boolean setNetworkCandidateScanResult(int networkId, ScanResult scanResult, int score) {
+ public Set<Integer> fetchChannelSetForNetworkForPartialScan(int networkId, long ageInMillis) {
WifiConfiguration config = getInternalConfiguredNetwork(networkId);
if (config == null) {
- Log.e(TAG, "Cannot find network with networkId " + networkId);
- return false;
+ return null;
}
- config.getNetworkSelectionStatus().setCandidate(scanResult);
- config.getNetworkSelectionStatus().setCandidateScore(score);
- // Update the network selection status.
- config.getNetworkSelectionStatus().setSeenInLastQualifiedNetworkSelection(true);
- return true;
+ ScanDetailCache scanDetailCache = getScanDetailCacheForNetwork(networkId);
+ if (scanDetailCache == null && config.linkedConfigurations == null) {
+ Log.i(TAG, "No scan detail and linked configs associated with networkId " + networkId);
+ return null;
+ }
+ if (mVerboseLoggingEnabled) {
+ StringBuilder dbg = new StringBuilder();
+ dbg.append("fetchChannelSetForNetworkForPartialScan ageInMillis ")
+ .append(ageInMillis)
+ .append(" for ")
+ .append(config.configKey())
+ .append(" max ")
+ .append(mMaxNumActiveChannelsForPartialScans);
+ if (scanDetailCache != null) {
+ dbg.append(" bssids " + scanDetailCache.size());
+ }
+ if (config.linkedConfigurations != null) {
+ dbg.append(" linked " + config.linkedConfigurations.size());
+ }
+ Log.v(TAG, dbg.toString());
+ }
+ Set<Integer> channelSet = new HashSet<>();
+ long nowInMillis = mClock.getWallClockMillis();
+
+ // First get channels for the network.
+ if (!addToChannelSetForNetworkFromScanDetailCache(
+ channelSet, scanDetailCache, nowInMillis, ageInMillis,
+ mMaxNumActiveChannelsForPartialScans)) {
+ return channelSet;
+ }
+
+ // Now get channels for linked networks.
+ if (config.linkedConfigurations != null) {
+ for (String configKey : config.linkedConfigurations.keySet()) {
+ WifiConfiguration linkedConfig = getInternalConfiguredNetwork(configKey);
+ if (linkedConfig == null) {
+ continue;
+ }
+ ScanDetailCache linkedScanDetailCache =
+ getScanDetailCacheForNetwork(linkedConfig.networkId);
+ if (!addToChannelSetForNetworkFromScanDetailCache(
+ channelSet, linkedScanDetailCache, nowInMillis, ageInMillis,
+ mMaxNumActiveChannelsForPartialScans)) {
+ break;
+ }
+ }
+ }
+ return channelSet;
}
/**
diff --git a/service/java/com/android/server/wifi/WifiNative.java b/service/java/com/android/server/wifi/WifiNative.java
index 7c20dd6..38d9f77 100644
--- a/service/java/com/android/server/wifi/WifiNative.java
+++ b/service/java/com/android/server/wifi/WifiNative.java
@@ -390,7 +390,9 @@
public boolean setNetworkVariable(int netId, String name, String value) {
if (TextUtils.isEmpty(name) || TextUtils.isEmpty(value)) return false;
if (name.equals(WifiConfiguration.pskVarName)
- || name.equals(WifiEnterpriseConfig.PASSWORD_KEY)) {
+ || name.equals(WifiEnterpriseConfig.PASSWORD_KEY)
+ || name.equals(WifiEnterpriseConfig.IDENTITY_KEY)
+ || name.equals(WifiEnterpriseConfig.ANON_IDENTITY_KEY)) {
return doBooleanCommandWithoutLogging("SET_NETWORK " + netId + " " + name + " " + value);
} else {
return doBooleanCommand("SET_NETWORK " + netId + " " + name + " " + value);
@@ -2151,13 +2153,12 @@
synchronized (sLock) {
if (isHalStarted()) {
if (sRttCmdId != 0) {
- Log.v("TAG", "Last one is still under measurement!");
+ Log.w(TAG, "Last one is still under measurement!");
return false;
} else {
sRttCmdId = getNewCmdIdLocked();
}
sRttEventHandler = handler;
- Log.v(TAG, "native issue RTT request");
return requestRangeNative(sWlan0Index, sRttCmdId, params);
} else {
return false;
@@ -2176,7 +2177,6 @@
if (cancelRangeRequestNative(sWlan0Index, sRttCmdId, params)) {
sRttEventHandler = null;
- Log.v(TAG, "RTT cancel Request Successfully");
return true;
} else {
Log.e(TAG, "RTT cancel Request failed");
diff --git a/service/java/com/android/server/wifi/WifiStateMachine.java b/service/java/com/android/server/wifi/WifiStateMachine.java
index 131d2b0..3caa1f6 100644
--- a/service/java/com/android/server/wifi/WifiStateMachine.java
+++ b/service/java/com/android/server/wifi/WifiStateMachine.java
@@ -1766,6 +1766,14 @@
}
/**
+ * Allow tests to confirm the operational mode for WSM.
+ */
+ @VisibleForTesting
+ protected int getOperationalModeForTest() {
+ return mOperationalMode;
+ }
+
+ /**
* TODO: doc
*/
public List<ScanResult> syncGetScanResultsList() {
@@ -4136,6 +4144,9 @@
mWificond = mWifiInjector.makeWificond();
transitionTo(mSoftApState);
break;
+ case CMD_SET_OPERATIONAL_MODE:
+ mOperationalMode = message.arg1;
+ break;
default:
return NOT_HANDLED;
}
@@ -5443,8 +5454,10 @@
// For SIM & AKA/AKA' EAP method Only, get identity from ICC
if (targetWificonfiguration != null
&& targetWificonfiguration.networkId == networkId
- && targetWificonfiguration.allowedKeyManagement
- .get(WifiConfiguration.KeyMgmt.IEEE8021X)
+ && (targetWificonfiguration.allowedKeyManagement
+ .get(WifiConfiguration.KeyMgmt.WPA_EAP)
+ || targetWificonfiguration.allowedKeyManagement
+ .get(WifiConfiguration.KeyMgmt.IEEE8021X))
&& TelephonyUtil.isSimEapMethod(eapMethod)) {
String identity =
TelephonyUtil.getSimIdentity(getTelephonyManager(), eapMethod);
diff --git a/service/java/com/android/server/wifi/nan/WifiNanDataPathStateManager.java b/service/java/com/android/server/wifi/nan/WifiNanDataPathStateManager.java
index 20535f6..f6d80b1 100644
--- a/service/java/com/android/server/wifi/nan/WifiNanDataPathStateManager.java
+++ b/service/java/com/android/server/wifi/nan/WifiNanDataPathStateManager.java
@@ -432,8 +432,12 @@
}
nnri.networkAgent = new WifiNanNetworkAgent(mLooper, mContext,
- AGENT_TAG_PREFIX + nnri.ndpId, networkInfo, networkCapabilities, linkProperties,
- NETWORK_FACTORY_SCORE_AVAIL, networkSpecifier, ndpId);
+ AGENT_TAG_PREFIX + nnri.ndpId,
+ new NetworkInfo(ConnectivityManager.TYPE_WIFI_P2P, 0, NETWORK_TAG, ""),
+ networkCapabilities, new LinkProperties(), NETWORK_FACTORY_SCORE_AVAIL,
+ networkSpecifier, ndpId);
+ nnri.networkAgent.sendNetworkInfo(networkInfo);
+ nnri.networkAgent.sendLinkProperties(linkProperties);
} else {
if (DBG) {
Log.d(TAG, "onDataPathConfirm: data-path for networkSpecifier=" + networkSpecifier
diff --git a/service/java/com/android/server/wifi/scanner/WifiScanningServiceImpl.java b/service/java/com/android/server/wifi/scanner/WifiScanningServiceImpl.java
index fdf3dfa..df0c6e6 100644
--- a/service/java/com/android/server/wifi/scanner/WifiScanningServiceImpl.java
+++ b/service/java/com/android/server/wifi/scanner/WifiScanningServiceImpl.java
@@ -189,7 +189,7 @@
ClientInfo ci = mClients.get(msg.replyTo);
if (ci == null) {
- loge("Could not find client info for message " + msg.replyTo);
+ loge("Could not find client info for message " + msg.replyTo + ", msg=" + msg);
replyFailed(msg, WifiScanner.REASON_INVALID_LISTENER, "Could not find listener");
return;
}
diff --git a/service/jni/com_android_server_wifi_WifiNative.cpp b/service/jni/com_android_server_wifi_WifiNative.cpp
index 8297392..e86f4fc 100644
--- a/service/jni/com_android_server_wifi_WifiNative.cpp
+++ b/service/jni/com_android_server_wifi_WifiNative.cpp
@@ -1051,7 +1051,7 @@
JNIHelper helper(mVM);
- ALOGD("onRttResults called, vm = %p, obj = %p", mVM, mCls);
+ if (DBG) ALOGD("onRttResults called, vm = %p, obj = %p", mVM, mCls);
JNIObject<jobjectArray> rttResults = helper.newObjectArray(
num_results, "android/net/wifi/RttManager$RttResult", NULL);
@@ -1099,14 +1099,12 @@
JNIObject<jobject> LCI = helper.createObject(
"android/net/wifi/RttManager$WifiInformationElement");
if (result->LCI != NULL && result->LCI->len > 0) {
- ALOGD("Add LCI in result");
helper.setByteField(LCI, "id", result->LCI->id);
JNIObject<jbyteArray> elements = helper.newByteArray(result->LCI->len);
jbyte *bytes = (jbyte *)&(result->LCI->data[0]);
helper.setByteArrayRegion(elements, 0, result->LCI->len, bytes);
helper.setObjectField(LCI, "data", "[B", elements);
} else {
- ALOGD("No LCI in result");
helper.setByteField(LCI, "id", (byte)(0xff));
}
helper.setObjectField(rttResult, "LCI",
@@ -1115,14 +1113,12 @@
JNIObject<jobject> LCR = helper.createObject(
"android/net/wifi/RttManager$WifiInformationElement");
if (result->LCR != NULL && result->LCR->len > 0) {
- ALOGD("Add LCR in result");
helper.setByteField(LCR, "id", result->LCR->id);
JNIObject<jbyteArray> elements = helper.newByteArray(result->LCI->len);
jbyte *bytes = (jbyte *)&(result->LCR->data[0]);
helper.setByteArrayRegion(elements, 0, result->LCI->len, bytes);
helper.setObjectField(LCR, "data", "[B", elements);
} else {
- ALOGD("No LCR in result");
helper.setByteField(LCR, "id", (byte)(0xff));
}
helper.setObjectField(rttResult, "LCR",
@@ -1143,7 +1139,7 @@
JNIHelper helper(env);
wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
- ALOGD("sending rtt request [%d] = %p", id, handle);
+ if (DBG) ALOGD("sending rtt request [%d] = %p", id, handle);
if (params == NULL) {
ALOGE("ranging params are empty");
return false;
@@ -1161,7 +1157,7 @@
JNIObject<jobject> param = helper.getObjectArrayElement((jobjectArray)params, i);
if (param == NULL) {
- ALOGD("could not get element %d", i);
+ ALOGW("could not get element %d", i);
continue;
}
@@ -1186,18 +1182,6 @@
config.burst_duration = (unsigned) helper.getIntField(param, "burstTimeout");
config.preamble = (wifi_rtt_preamble) helper.getIntField(param, "preamble");
config.bw = (wifi_rtt_bw) helper.getIntField(param, "bandwidth");
-
- ALOGD("RTT request destination %d: type is %d, peer is %d, bw is %d, center_freq is %d ", i,
- config.type,config.peer, config.channel.width, config.channel.center_freq);
- ALOGD("center_freq0 is %d, center_freq1 is %d, num_burst is %d,interval is %d",
- config.channel.center_freq0, config.channel.center_freq1, config.num_burst,
- config.burst_period);
- ALOGD("frames_per_burst is %d, retries of measurement frame is %d, retries_per_ftmr is %d",
- config.num_frames_per_burst, config.num_retries_per_rtt_frame,
- config.num_retries_per_ftmr);
- ALOGD("LCI_requestis %d, LCR_request is %d, burst_timeout is %d, preamble is %d, bw is %d",
- config.LCI_request, config.LCR_request, config.burst_duration, config.preamble,
- config.bw);
}
wifi_rtt_event_handler handler;
@@ -1211,7 +1195,7 @@
JNIHelper helper(env);
wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
- ALOGD("cancelling rtt request [%d] = %p", id, handle);
+ if (DBG) ALOGD("cancelling rtt request [%d] = %p", id, handle);
if (params == NULL) {
ALOGE("ranging params are empty");
@@ -1230,7 +1214,7 @@
JNIObject<jobject> param = helper.getObjectArrayElement(params, i);
if (param == NULL) {
- ALOGD("could not get element %d", i);
+ ALOGW("could not get element %d", i);
continue;
}
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerNewTest.java b/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerNewTest.java
index 53e2d80..c190ac1 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerNewTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerNewTest.java
@@ -31,12 +31,13 @@
import android.net.wifi.WifiManager;
import android.net.wifi.WifiScanner;
import android.net.wifi.WifiSsid;
-import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManager;
import android.test.suitebuilder.annotation.SmallTest;
import android.text.TextUtils;
+import com.android.internal.R;
+
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
@@ -46,6 +47,7 @@
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.HashSet;
import java.util.List;
/**
@@ -60,8 +62,11 @@
private static final long TEST_ELAPSED_UPDATE_NETWORK_SELECTION_TIME_MILLIS = 29457631;
private static final int TEST_CREATOR_UID = 5;
private static final int TEST_UPDATE_UID = 4;
+ private static final int TEST_MAX_NUM_ACTIVE_CHANNELS_FOR_PARTIAL_SCAN = 5;
+ private static final Integer[] TEST_FREQ_LIST = {2400, 2450, 5150, 5175, 5650};
private static final String TEST_CREATOR_NAME = "com.wificonfigmanagerNew.creator";
private static final String TEST_UPDATE_NAME = "com.wificonfigmanagerNew.update";
+ private static final String TEST_DEFAULT_GW_MAC_ADDRESS = "0f:67:ad:ef:09:34";
@Mock private Context mContext;
@Mock private FrameworkFacade mFrameworkFacade;
@@ -71,8 +76,8 @@
@Mock private WifiConfigStoreNew mWifiConfigStore;
@Mock private PackageManager mPackageManager;
+ private MockResources mResources;
private InOrder mContextConfigStoreMockOrder;
-
private WifiConfigManagerNew mWifiConfigManager;
/**
@@ -88,6 +93,14 @@
// Set up the package name stuff & permission override.
when(mContext.getPackageManager()).thenReturn(mPackageManager);
+ mResources = new MockResources();
+ mResources.setBoolean(
+ R.bool.config_wifi_only_link_same_credential_configurations, true);
+ mResources.setInteger(
+ R.integer.config_wifi_framework_associated_partial_scan_max_num_active_channels,
+ TEST_MAX_NUM_ACTIVE_CHANNELS_FOR_PARTIAL_SCAN);
+ when(mContext.getResources()).thenReturn(mResources);
+
doAnswer(new AnswerWithArguments() {
public String answer(int uid) throws Exception {
if (uid == TEST_CREATOR_UID) {
@@ -115,11 +128,7 @@
.updateNetworkKeys(any(WifiConfiguration.class), any(WifiConfiguration.class)))
.thenReturn(true);
- mWifiConfigManager =
- new WifiConfigManagerNew(
- mContext, mFrameworkFacade, mClock, mUserManager, mWifiKeyStore,
- mWifiConfigStore);
- mWifiConfigManager.enableVerboseLogging(1);
+ createWifiConfigManager();
}
/**
@@ -1173,6 +1182,411 @@
}
/**
+ * Verifies the linking of networks when they have the same default GW Mac address in
+ * {@link WifiConfigManagerNew#getOrCreateScanDetailCacheForNetwork(WifiConfiguration)}.
+ */
+ @Test
+ public void testNetworkLinkUsingGwMacAddress() {
+ WifiConfiguration network1 = WifiConfigurationTestUtil.createPskNetwork();
+ WifiConfiguration network2 = WifiConfigurationTestUtil.createPskNetwork();
+ WifiConfiguration network3 = WifiConfigurationTestUtil.createPskNetwork();
+ verifyAddNetworkToWifiConfigManager(network1);
+ verifyAddNetworkToWifiConfigManager(network2);
+ verifyAddNetworkToWifiConfigManager(network3);
+
+ // Set the same default GW mac address for all of the networks.
+ assertTrue(mWifiConfigManager.setNetworkDefaultGwMacAddress(
+ network1.networkId, TEST_DEFAULT_GW_MAC_ADDRESS));
+ assertTrue(mWifiConfigManager.setNetworkDefaultGwMacAddress(
+ network2.networkId, TEST_DEFAULT_GW_MAC_ADDRESS));
+ assertTrue(mWifiConfigManager.setNetworkDefaultGwMacAddress(
+ network3.networkId, TEST_DEFAULT_GW_MAC_ADDRESS));
+
+ // Now create dummy scan detail corresponding to the networks.
+ ScanDetail networkScanDetail1 = createScanDetailForNetwork(network1);
+ ScanDetail networkScanDetail2 = createScanDetailForNetwork(network2);
+ ScanDetail networkScanDetail3 = createScanDetailForNetwork(network3);
+
+ // Now save all these scan details corresponding to each of this network and expect
+ // all of these networks to be linked with each other.
+ assertNotNull(mWifiConfigManager.getSavedNetworkForScanDetailAndCache(networkScanDetail1));
+ assertNotNull(mWifiConfigManager.getSavedNetworkForScanDetailAndCache(networkScanDetail2));
+ assertNotNull(mWifiConfigManager.getSavedNetworkForScanDetailAndCache(networkScanDetail3));
+
+ List<WifiConfiguration> retrievedNetworks =
+ mWifiConfigManager.getConfiguredNetworks();
+ for (WifiConfiguration network : retrievedNetworks) {
+ assertEquals(2, network.linkedConfigurations.size());
+ for (WifiConfiguration otherNetwork : retrievedNetworks) {
+ if (otherNetwork == network) {
+ continue;
+ }
+ assertNotNull(network.linkedConfigurations.get(otherNetwork.configKey()));
+ }
+ }
+ }
+
+ /**
+ * Verifies the linking of networks when they have scan results with same first 16 ASCII of
+ * bssid in
+ * {@link WifiConfigManagerNew#getOrCreateScanDetailCacheForNetwork(WifiConfiguration)}.
+ */
+ @Test
+ public void testNetworkLinkUsingBSSIDMatch() {
+ WifiConfiguration network1 = WifiConfigurationTestUtil.createPskNetwork();
+ WifiConfiguration network2 = WifiConfigurationTestUtil.createPskNetwork();
+ WifiConfiguration network3 = WifiConfigurationTestUtil.createPskNetwork();
+ verifyAddNetworkToWifiConfigManager(network1);
+ verifyAddNetworkToWifiConfigManager(network2);
+ verifyAddNetworkToWifiConfigManager(network3);
+
+ // Create scan results with bssid which is different in only the last char.
+ ScanDetail networkScanDetail1 = createScanDetailForNetwork(network1, "af:89:56:34:56:67");
+ ScanDetail networkScanDetail2 = createScanDetailForNetwork(network2, "af:89:56:34:56:68");
+ ScanDetail networkScanDetail3 = createScanDetailForNetwork(network3, "af:89:56:34:56:69");
+
+ // Now save all these scan details corresponding to each of this network and expect
+ // all of these networks to be linked with each other.
+ assertNotNull(mWifiConfigManager.getSavedNetworkForScanDetailAndCache(networkScanDetail1));
+ assertNotNull(mWifiConfigManager.getSavedNetworkForScanDetailAndCache(networkScanDetail2));
+ assertNotNull(mWifiConfigManager.getSavedNetworkForScanDetailAndCache(networkScanDetail3));
+
+ List<WifiConfiguration> retrievedNetworks =
+ mWifiConfigManager.getConfiguredNetworks();
+ for (WifiConfiguration network : retrievedNetworks) {
+ assertEquals(2, network.linkedConfigurations.size());
+ for (WifiConfiguration otherNetwork : retrievedNetworks) {
+ if (otherNetwork == network) {
+ continue;
+ }
+ assertNotNull(network.linkedConfigurations.get(otherNetwork.configKey()));
+ }
+ }
+ }
+
+ /**
+ * Verifies the linking of networks does not happen for non WPA networks when they have scan
+ * results with same first 16 ASCII of bssid in
+ * {@link WifiConfigManagerNew#getOrCreateScanDetailCacheForNetwork(WifiConfiguration)}.
+ */
+ @Test
+ public void testNoNetworkLinkUsingBSSIDMatchForNonWpaNetworks() {
+ WifiConfiguration network1 = WifiConfigurationTestUtil.createOpenNetwork();
+ WifiConfiguration network2 = WifiConfigurationTestUtil.createPskNetwork();
+ verifyAddNetworkToWifiConfigManager(network1);
+ verifyAddNetworkToWifiConfigManager(network2);
+
+ // Create scan results with bssid which is different in only the last char.
+ ScanDetail networkScanDetail1 = createScanDetailForNetwork(network1, "af:89:56:34:56:67");
+ ScanDetail networkScanDetail2 = createScanDetailForNetwork(network2, "af:89:56:34:56:68");
+
+ assertNotNull(mWifiConfigManager.getSavedNetworkForScanDetailAndCache(networkScanDetail1));
+ assertNotNull(mWifiConfigManager.getSavedNetworkForScanDetailAndCache(networkScanDetail2));
+
+ List<WifiConfiguration> retrievedNetworks =
+ mWifiConfigManager.getConfiguredNetworks();
+ for (WifiConfiguration network : retrievedNetworks) {
+ assertNull(network.linkedConfigurations);
+ }
+ }
+
+ /**
+ * Verifies the linking of networks does not happen for networks with more than
+ * {@link WifiConfigManagerNew#LINK_CONFIGURATION_MAX_SCAN_CACHE_ENTRIES} scan
+ * results with same first 16 ASCII of bssid in
+ * {@link WifiConfigManagerNew#getOrCreateScanDetailCacheForNetwork(WifiConfiguration)}.
+ */
+ @Test
+ public void testNoNetworkLinkUsingBSSIDMatchForNetworksWithHighScanDetailCacheSize() {
+ WifiConfiguration network1 = WifiConfigurationTestUtil.createPskNetwork();
+ WifiConfiguration network2 = WifiConfigurationTestUtil.createPskNetwork();
+ verifyAddNetworkToWifiConfigManager(network1);
+ verifyAddNetworkToWifiConfigManager(network2);
+
+ // Create 7 scan results with bssid which is different in only the last char.
+ String test_bssid_base = "af:89:56:34:56:6";
+ int scan_result_num = 0;
+ for (; scan_result_num < WifiConfigManagerNew.LINK_CONFIGURATION_MAX_SCAN_CACHE_ENTRIES + 1;
+ scan_result_num++) {
+ ScanDetail networkScanDetail =
+ createScanDetailForNetwork(
+ network1, test_bssid_base + Integer.toString(scan_result_num));
+ assertNotNull(
+ mWifiConfigManager.getSavedNetworkForScanDetailAndCache(networkScanDetail));
+ }
+
+ // Now add 1 scan result to the other network with bssid which is different in only the
+ // last char.
+ ScanDetail networkScanDetail2 =
+ createScanDetailForNetwork(
+ network2, test_bssid_base + Integer.toString(scan_result_num++));
+ assertNotNull(mWifiConfigManager.getSavedNetworkForScanDetailAndCache(networkScanDetail2));
+
+ List<WifiConfiguration> retrievedNetworks =
+ mWifiConfigManager.getConfiguredNetworks();
+ for (WifiConfiguration network : retrievedNetworks) {
+ assertNull(network.linkedConfigurations);
+ }
+ }
+
+ /**
+ * Verifies the linking of networks when they have scan results with same first 16 ASCII of
+ * bssid in {@link WifiConfigManagerNew#getOrCreateScanDetailCacheForNetwork(WifiConfiguration)}
+ * and then subsequently delinked when the networks have default gateway set which do not match.
+ */
+ @Test
+ public void testNetworkLinkUsingBSSIDMatchAndThenUnlinkDueToGwMacAddress() {
+ WifiConfiguration network1 = WifiConfigurationTestUtil.createPskNetwork();
+ WifiConfiguration network2 = WifiConfigurationTestUtil.createPskNetwork();
+ verifyAddNetworkToWifiConfigManager(network1);
+ verifyAddNetworkToWifiConfigManager(network2);
+
+ // Create scan results with bssid which is different in only the last char.
+ ScanDetail networkScanDetail1 = createScanDetailForNetwork(network1, "af:89:56:34:56:67");
+ ScanDetail networkScanDetail2 = createScanDetailForNetwork(network2, "af:89:56:34:56:68");
+
+ // Now save all these scan details corresponding to each of this network and expect
+ // all of these networks to be linked with each other.
+ assertNotNull(mWifiConfigManager.getSavedNetworkForScanDetailAndCache(networkScanDetail1));
+ assertNotNull(mWifiConfigManager.getSavedNetworkForScanDetailAndCache(networkScanDetail2));
+
+ List<WifiConfiguration> retrievedNetworks =
+ mWifiConfigManager.getConfiguredNetworks();
+ for (WifiConfiguration network : retrievedNetworks) {
+ assertEquals(1, network.linkedConfigurations.size());
+ for (WifiConfiguration otherNetwork : retrievedNetworks) {
+ if (otherNetwork == network) {
+ continue;
+ }
+ assertNotNull(network.linkedConfigurations.get(otherNetwork.configKey()));
+ }
+ }
+
+ // Now Set different GW mac address for both the networks and ensure they're unlinked.
+ assertTrue(mWifiConfigManager.setNetworkDefaultGwMacAddress(
+ network1.networkId, "de:ad:fe:45:23:34"));
+ assertTrue(mWifiConfigManager.setNetworkDefaultGwMacAddress(
+ network2.networkId, "ad:de:fe:45:23:34"));
+
+ // Add some dummy scan results again to re-evaluate the linking of networks.
+ assertNotNull(mWifiConfigManager.getSavedNetworkForScanDetailAndCache(
+ createScanDetailForNetwork(network1, "af:89:56:34:45:67")));
+ assertNotNull(mWifiConfigManager.getSavedNetworkForScanDetailAndCache(
+ createScanDetailForNetwork(network1, "af:89:56:34:45:68")));
+
+ retrievedNetworks = mWifiConfigManager.getConfiguredNetworks();
+ for (WifiConfiguration network : retrievedNetworks) {
+ assertNull(network.linkedConfigurations);
+ }
+ }
+
+ /*
+ * Verifies the creation of channel list using
+ * {@link WifiConfigManagerNew#fetchChannelSetForNetworkForPartialScan(int, long)}.
+ */
+ @Test
+ public void testFetchChannelSetForNetwork() {
+ WifiConfiguration network = WifiConfigurationTestUtil.createPskNetwork();
+ verifyAddNetworkToWifiConfigManager(network);
+
+ // Create 5 scan results with different bssid's & frequencies.
+ String test_bssid_base = "af:89:56:34:56:6";
+ for (int i = 0; i < TEST_FREQ_LIST.length; i++) {
+ ScanDetail networkScanDetail =
+ createScanDetailForNetwork(
+ network, test_bssid_base + Integer.toString(i), 0, TEST_FREQ_LIST[i]);
+ assertNotNull(
+ mWifiConfigManager.getSavedNetworkForScanDetailAndCache(networkScanDetail));
+
+ }
+ assertEquals(new HashSet<Integer>(Arrays.asList(TEST_FREQ_LIST)),
+ mWifiConfigManager.fetchChannelSetForNetworkForPartialScan(network.networkId, 1));
+ }
+
+ /**
+ * Verifies the creation of channel list using
+ * {@link WifiConfigManagerNew#fetchChannelSetForNetworkForPartialScan(int, long)} and ensures
+ * that scan results which have a timestamp beyond the provided age are not used in the
+ * channel list.
+ */
+ @Test
+ public void testFetchChannelSetForNetworkIgnoresStaleScanResults() {
+ WifiConfiguration network = WifiConfigurationTestUtil.createPskNetwork();
+ verifyAddNetworkToWifiConfigManager(network);
+
+ long wallClockBase = 0;
+ // Create 5 scan results with different bssid's & frequencies.
+ String test_bssid_base = "af:89:56:34:56:6";
+ for (int i = 0; i < TEST_FREQ_LIST.length; i++) {
+ // Increment the seen value in the scan results for each of them.
+ when(mClock.getWallClockMillis()).thenReturn(wallClockBase + i);
+ ScanDetail networkScanDetail =
+ createScanDetailForNetwork(
+ network, test_bssid_base + Integer.toString(i), 0, TEST_FREQ_LIST[i]);
+ assertNotNull(
+ mWifiConfigManager.getSavedNetworkForScanDetailAndCache(networkScanDetail));
+
+ }
+ int ageInMillis = 4;
+ // Now fetch only scan results which are 4 millis stale. This should ignore the first
+ // scan result.
+ assertEquals(
+ new HashSet<>(Arrays.asList(
+ Arrays.copyOfRange(
+ TEST_FREQ_LIST,
+ TEST_FREQ_LIST.length - ageInMillis, TEST_FREQ_LIST.length))),
+ mWifiConfigManager.fetchChannelSetForNetworkForPartialScan(
+ network.networkId, ageInMillis));
+ }
+
+ /**
+ * Verifies the creation of channel list using
+ * {@link WifiConfigManagerNew#fetchChannelSetForNetworkForPartialScan(int, long)} and ensures
+ * that the list size does not exceed the max configured for the device.
+ */
+ @Test
+ public void testFetchChannelSetForNetworkIsLimitedToConfiguredSize() {
+ // Need to recreate the WifiConfigManagerNew instance for this test to modify the config
+ // value which is read only in the constructor.
+ int maxListSize = 3;
+ mResources.setInteger(
+ R.integer.config_wifi_framework_associated_partial_scan_max_num_active_channels,
+ maxListSize);
+ createWifiConfigManager();
+
+ WifiConfiguration network = WifiConfigurationTestUtil.createPskNetwork();
+ verifyAddNetworkToWifiConfigManager(network);
+
+ // Create 5 scan results with different bssid's & frequencies.
+ String test_bssid_base = "af:89:56:34:56:6";
+ for (int i = 0; i < TEST_FREQ_LIST.length; i++) {
+ ScanDetail networkScanDetail =
+ createScanDetailForNetwork(
+ network, test_bssid_base + Integer.toString(i), 0, TEST_FREQ_LIST[i]);
+ assertNotNull(
+ mWifiConfigManager.getSavedNetworkForScanDetailAndCache(networkScanDetail));
+
+ }
+ // Ensure that the fetched list size is limited.
+ assertEquals(maxListSize,
+ mWifiConfigManager.fetchChannelSetForNetworkForPartialScan(
+ network.networkId, 1).size());
+ }
+
+ /**
+ * Verifies the creation of channel list using
+ * {@link WifiConfigManagerNew#fetchChannelSetForNetworkForPartialScan(int, long)} and ensures
+ * that scan results from linked networks are used in the channel list.
+ */
+ @Test
+ public void testFetchChannelSetForNetworkIncludesLinkedNetworks() {
+ WifiConfiguration network1 = WifiConfigurationTestUtil.createPskNetwork();
+ WifiConfiguration network2 = WifiConfigurationTestUtil.createPskNetwork();
+ verifyAddNetworkToWifiConfigManager(network1);
+ verifyAddNetworkToWifiConfigManager(network2);
+
+ String test_bssid_base = "af:89:56:34:56:6";
+ int TEST_FREQ_LISTIdx = 0;
+ // Create 3 scan results with different bssid's & frequencies for network 1.
+ for (; TEST_FREQ_LISTIdx < TEST_FREQ_LIST.length / 2; TEST_FREQ_LISTIdx++) {
+ ScanDetail networkScanDetail =
+ createScanDetailForNetwork(
+ network1, test_bssid_base + Integer.toString(TEST_FREQ_LISTIdx), 0,
+ TEST_FREQ_LIST[TEST_FREQ_LISTIdx]);
+ assertNotNull(
+ mWifiConfigManager.getSavedNetworkForScanDetailAndCache(networkScanDetail));
+
+ }
+ // Create 3 scan results with different bssid's & frequencies for network 2.
+ for (; TEST_FREQ_LISTIdx < TEST_FREQ_LIST.length; TEST_FREQ_LISTIdx++) {
+ ScanDetail networkScanDetail =
+ createScanDetailForNetwork(
+ network2, test_bssid_base + Integer.toString(TEST_FREQ_LISTIdx), 0,
+ TEST_FREQ_LIST[TEST_FREQ_LISTIdx]);
+ assertNotNull(
+ mWifiConfigManager.getSavedNetworkForScanDetailAndCache(networkScanDetail));
+ }
+
+ // Link the 2 configurations together using the GwMacAddress.
+ assertTrue(mWifiConfigManager.setNetworkDefaultGwMacAddress(
+ network1.networkId, TEST_DEFAULT_GW_MAC_ADDRESS));
+ assertTrue(mWifiConfigManager.setNetworkDefaultGwMacAddress(
+ network2.networkId, TEST_DEFAULT_GW_MAC_ADDRESS));
+
+ // The channel list fetched should include scan results from both the linked networks.
+ assertEquals(new HashSet<Integer>(Arrays.asList(TEST_FREQ_LIST)),
+ mWifiConfigManager.fetchChannelSetForNetworkForPartialScan(network1.networkId, 1));
+ assertEquals(new HashSet<Integer>(Arrays.asList(TEST_FREQ_LIST)),
+ mWifiConfigManager.fetchChannelSetForNetworkForPartialScan(network2.networkId, 1));
+ }
+
+ /**
+ * Verifies the creation of channel list using
+ * {@link WifiConfigManagerNew#fetchChannelSetForNetworkForPartialScan(int, long)} and ensures
+ * that scan results from linked networks are used in the channel list and that the list size
+ * does not exceed the max configured for the device.
+ */
+ @Test
+ public void testFetchChannelSetForNetworkIncludesLinkedNetworksIsLimitedToConfiguredSize() {
+ // Need to recreate the WifiConfigManagerNew instance for this test to modify the config
+ // value which is read only in the constructor.
+ int maxListSize = 3;
+ mResources.setInteger(
+ R.integer.config_wifi_framework_associated_partial_scan_max_num_active_channels,
+ maxListSize);
+
+ createWifiConfigManager();
+ WifiConfiguration network1 = WifiConfigurationTestUtil.createPskNetwork();
+ WifiConfiguration network2 = WifiConfigurationTestUtil.createPskNetwork();
+ verifyAddNetworkToWifiConfigManager(network1);
+ verifyAddNetworkToWifiConfigManager(network2);
+
+ String test_bssid_base = "af:89:56:34:56:6";
+ int TEST_FREQ_LISTIdx = 0;
+ // Create 3 scan results with different bssid's & frequencies for network 1.
+ for (; TEST_FREQ_LISTIdx < TEST_FREQ_LIST.length / 2; TEST_FREQ_LISTIdx++) {
+ ScanDetail networkScanDetail =
+ createScanDetailForNetwork(
+ network1, test_bssid_base + Integer.toString(TEST_FREQ_LISTIdx), 0,
+ TEST_FREQ_LIST[TEST_FREQ_LISTIdx]);
+ assertNotNull(
+ mWifiConfigManager.getSavedNetworkForScanDetailAndCache(networkScanDetail));
+
+ }
+ // Create 3 scan results with different bssid's & frequencies for network 2.
+ for (; TEST_FREQ_LISTIdx < TEST_FREQ_LIST.length; TEST_FREQ_LISTIdx++) {
+ ScanDetail networkScanDetail =
+ createScanDetailForNetwork(
+ network2, test_bssid_base + Integer.toString(TEST_FREQ_LISTIdx), 0,
+ TEST_FREQ_LIST[TEST_FREQ_LISTIdx]);
+ assertNotNull(
+ mWifiConfigManager.getSavedNetworkForScanDetailAndCache(networkScanDetail));
+ }
+
+ // Link the 2 configurations together using the GwMacAddress.
+ assertTrue(mWifiConfigManager.setNetworkDefaultGwMacAddress(
+ network1.networkId, TEST_DEFAULT_GW_MAC_ADDRESS));
+ assertTrue(mWifiConfigManager.setNetworkDefaultGwMacAddress(
+ network2.networkId, TEST_DEFAULT_GW_MAC_ADDRESS));
+
+ // Ensure that the fetched list size is limited.
+ assertEquals(maxListSize,
+ mWifiConfigManager.fetchChannelSetForNetworkForPartialScan(
+ network1.networkId, 1).size());
+ assertEquals(maxListSize,
+ mWifiConfigManager.fetchChannelSetForNetworkForPartialScan(
+ network2.networkId, 1).size());
+ }
+
+ private void createWifiConfigManager() {
+ mWifiConfigManager =
+ new WifiConfigManagerNew(
+ mContext, mFrameworkFacade, mClock, mUserManager, mWifiKeyStore,
+ mWifiConfigStore);
+ mWifiConfigManager.enableVerboseLogging(1);
+ }
+
+ /**
* This method sets defaults in the provided WifiConfiguration object if not set
* so that it can be used for comparison with the configuration retrieved from
* WifiConfigManager.
@@ -1586,9 +2000,11 @@
}
/**
- * Creates a scan detail corresponding to the provided network and BSSID value.
+ * Creates a scan detail corresponding to the provided network and given BSSID, level &frequency
+ * values.
*/
- private ScanDetail createScanDetailForNetwork(WifiConfiguration configuration, String bssid) {
+ private ScanDetail createScanDetailForNetwork(
+ WifiConfiguration configuration, String bssid, int level, int frequency) {
String caps;
if (configuration.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_PSK)) {
caps = "[WPA2-PSK-CCMP]";
@@ -1604,7 +2020,15 @@
WifiSsid ssid = WifiSsid.createFromAsciiEncoded(configuration.getPrintableSsid());
// Fill in 0's in the fields we don't care about.
return new ScanDetail(
- ssid, bssid, caps, 0, 0, SystemClock.uptimeMillis(), System.currentTimeMillis());
+ ssid, bssid, caps, level, frequency, mClock.getUptimeSinceBootMillis(),
+ mClock.getWallClockMillis());
+ }
+
+ /**
+ * Creates a scan detail corresponding to the provided network and BSSID value.
+ */
+ private ScanDetail createScanDetailForNetwork(WifiConfiguration configuration, String bssid) {
+ return createScanDetailForNetwork(configuration, bssid, 0, 0);
}
/**
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiConfigurationTestUtil.java b/tests/wifitests/src/com/android/server/wifi/WifiConfigurationTestUtil.java
index e45ddef..bdfdbc8 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiConfigurationTestUtil.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiConfigurationTestUtil.java
@@ -60,7 +60,7 @@
*/
public static final int TEST_NETWORK_ID = -1;
public static final int TEST_UID = 1;
- public static final String TEST_SSID = "WifiConfigurationTestUtilSSID_";
+ public static final String TEST_SSID = "WifiConfigurationTestUtilSSID";
public static final String TEST_PSK = "WifiConfigurationTestUtilPsk";
public static final String[] TEST_WEP_KEYS =
{"WifiConfigurationTestUtilWep1", "WifiConfigurationTestUtilWep2",
@@ -80,6 +80,7 @@
public static final String TEST_PAC_PROXY_LOCATION = "http://";
public static final String TEST_CA_CERT_ALIAS = "WifiConfigurationTestUtilCaCertAlias";
+ private static final int MAX_SSID_LENGTH = 32;
/**
* Index used to assign unique SSIDs for the generation of predefined WifiConfiguration objects.
*/
@@ -214,7 +215,9 @@
* Create a new SSID for the the network being created.
*/
private static String createNewSSID() {
- return "\"" + TEST_SSID + sNetworkIndex++ + "\"";
+ String ssid = TEST_SSID + sNetworkIndex++;
+ assertTrue(ssid.length() <= MAX_SSID_LENGTH);
+ return "\"" + ssid + "\"";
}
/**
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiStateMachineTest.java b/tests/wifitests/src/com/android/server/wifi/WifiStateMachineTest.java
index 5531eea..0fa9538 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiStateMachineTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiStateMachineTest.java
@@ -519,6 +519,73 @@
assertEquals("InitialState", getCurrentState().getName());
}
+ /**
+ * Test to check that mode changes from WifiController will be properly handled in the
+ * InitialState by WifiStateMachine.
+ */
+ @Test
+ public void checkOperationalModeInInitialState() throws Exception {
+ when(mWifiNative.startHal()).thenReturn(true);
+ when(mWifiNative.startSupplicant(anyBoolean())).thenReturn(true);
+
+ mLooper.dispatchAll();
+ assertEquals("InitialState", getCurrentState().getName());
+ assertEquals(WifiStateMachine.CONNECT_MODE, mWsm.getOperationalModeForTest());
+
+ mWsm.setOperationalMode(WifiStateMachine.SCAN_ONLY_WITH_WIFI_OFF_MODE);
+ mLooper.dispatchAll();
+ assertEquals(WifiStateMachine.SCAN_ONLY_WITH_WIFI_OFF_MODE,
+ mWsm.getOperationalModeForTest());
+
+ mWsm.setOperationalMode(WifiStateMachine.SCAN_ONLY_MODE);
+ mLooper.dispatchAll();
+ assertEquals(WifiStateMachine.SCAN_ONLY_MODE, mWsm.getOperationalModeForTest());
+
+ mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
+ mLooper.dispatchAll();
+ assertEquals(WifiStateMachine.CONNECT_MODE, mWsm.getOperationalModeForTest());
+ }
+
+ /**
+ * Test that mode changes for WifiStateMachine in the InitialState are realized when supplicant
+ * is started.
+ */
+ @Test
+ public void checkStartInCorrectStateAfterChangingInitialState() throws Exception {
+ when(mWifiNative.startHal()).thenReturn(true);
+ when(mWifiNative.startSupplicant(anyBoolean())).thenReturn(true);
+
+ // Check initial state
+ mLooper.dispatchAll();
+ assertEquals("InitialState", getCurrentState().getName());
+ assertEquals(WifiStateMachine.CONNECT_MODE, mWsm.getOperationalModeForTest());
+
+ // Update the mode
+ mWsm.setOperationalMode(WifiStateMachine.SCAN_ONLY_MODE);
+ mLooper.dispatchAll();
+ assertEquals(WifiStateMachine.SCAN_ONLY_MODE, mWsm.getOperationalModeForTest());
+
+ // Start supplicant so we move to the next state
+ mWsm.setSupplicantRunning(true);
+ mLooper.dispatchAll();
+ assertEquals("SupplicantStartingState", getCurrentState().getName());
+ when(mWifiNative.setBand(anyInt())).thenReturn(true);
+ when(mWifiNative.setDeviceName(anyString())).thenReturn(true);
+ when(mWifiNative.setManufacturer(anyString())).thenReturn(true);
+ when(mWifiNative.setModelName(anyString())).thenReturn(true);
+ when(mWifiNative.setModelNumber(anyString())).thenReturn(true);
+ when(mWifiNative.setSerialNumber(anyString())).thenReturn(true);
+ when(mWifiNative.setConfigMethods(anyString())).thenReturn(true);
+ when(mWifiNative.setDeviceType(anyString())).thenReturn(true);
+ when(mWifiNative.setSerialNumber(anyString())).thenReturn(true);
+ when(mWifiNative.setScanningMacOui(any(byte[].class))).thenReturn(true);
+
+ mWsm.sendMessage(WifiMonitor.SUP_CONNECTION_EVENT);
+ mLooper.dispatchAll();
+
+ assertEquals("ScanModeState", getCurrentState().getName());
+ }
+
private void addNetworkAndVerifySuccess() throws Exception {
addNetworkAndVerifySuccess(false);
}