am 1ec92c57: - detect that firmware cant stay connected to 5GHz AP and tune down 5GHz preference accordingly - use a long random string so as to obfuscate PSK of WiFiConfiguration we have deleted but keep around in the autojoin database - if autojoin doesn\'t find a kn
* commit '1ec92c57244311c7fca3ab6b244a06c2b2b58902':
- detect that firmware cant stay connected to 5GHz AP and tune down 5GHz preference accordingly - use a long random string so as to obfuscate PSK of WiFiConfiguration we have deleted but keep around in the autojoin database - if autojoin doesn't find a known network to join, and sees a known network that ConnectivityService never marked as UNWANTED due to bad signal, then add a boost of up to +8dB to this network's autojoin threshold, also includes the boost in the network's score that is sent to connectivity service
diff --git a/service/java/com/android/server/wifi/WifiAutoJoinController.java b/service/java/com/android/server/wifi/WifiAutoJoinController.java
index b7aa06a..f6741b4 100644
--- a/service/java/com/android/server/wifi/WifiAutoJoinController.java
+++ b/service/java/com/android/server/wifi/WifiAutoJoinController.java
@@ -17,12 +17,11 @@
package com.android.server.wifi;
import android.content.Context;
-
import android.net.NetworkKey;
import android.net.NetworkScoreManager;
import android.net.WifiKey;
import android.net.wifi.*;
-
+import android.net.wifi.WifiConfiguration.KeyMgmt;
import android.os.SystemClock;
import android.os.Process;
import android.text.TextUtils;
@@ -64,6 +63,9 @@
private WifiConnectionStatistics mWifiConnectionStatistics;
+ /** Whether to allow connections to untrusted networks. */
+ private boolean mAllowUntrustedConnections = false;
+
/* for debug purpose only : the untrusted SSID we would be connected to if we had VPN */
String lastUntrustedBSSID = null;
@@ -1100,6 +1102,23 @@
}
/**
+ * Set whether connections to untrusted connections are allowed.
+ */
+ void setAllowUntrustedConnections(boolean allow) {
+ boolean changed = mAllowUntrustedConnections != allow;
+ mAllowUntrustedConnections = allow;
+ if (changed) {
+ attemptAutoJoin();
+ }
+ }
+
+ private boolean isOpenNetwork(ScanResult result) {
+ return !result.capabilities.contains("WEP") &&
+ !result.capabilities.contains("PSK") &&
+ !result.capabilities.contains("EAP");
+ }
+
+ /**
* attemptAutoJoin() function implements the core of the a network switching algorithm
*/
void attemptAutoJoin() {
@@ -1201,6 +1220,14 @@
+ Integer.toString(currentConfiguration.networkId));
mWifiStateMachine.disconnectCommand();
return;
+ } else if (currentConfiguration.ephemeral && (!mAllowUntrustedConnections ||
+ !mNetworkScoreCache.isScoredNetwork(currentConfiguration.lastSeen()))) {
+ // The current connection is untrusted (the framework added it), but we're either
+ // no longer allowed to connect to such networks, or the score has been nullified
+ // since we connected. Drop the current connection and perform the rest of autojoin.
+ logDbg("attemptAutoJoin() disconnecting from unwanted ephemeral network");
+ mWifiStateMachine.disconnectCommand();
+ return;
} else {
mCurrentConfigurationKey = currentConfiguration.configKey();
}
@@ -1431,8 +1458,9 @@
}
}
- // Wait for VPN to be available on the system to make use of this code
// Now, go thru scan result to try finding a better untrusted network
+ // TODO: Consider only running this when we can actually connect to these networks. For now,
+ // this is useful for debugging.
if (mNetworkScoreCache != null) {
int rssi5 = WifiConfiguration.INVALID_RSSI;
int rssi24 = WifiConfiguration.INVALID_RSSI;
@@ -1453,7 +1481,8 @@
int rssiBoost = 0;
// We look only at untrusted networks with a valid SSID
// A trusted result would have been looked at thru it's Wificonfiguration
- if (TextUtils.isEmpty(result.SSID) || !result.untrusted) {
+ if (TextUtils.isEmpty(result.SSID) || !result.untrusted ||
+ !isOpenNetwork(result)) {
continue;
}
if ((nowMs - result.seen) < 3000) {
@@ -1492,9 +1521,16 @@
// Remember which SSID we are connecting to
lastUntrustedBSSID = untrustedCandidate.SSID;
}
+
+ // At this point, we have an untrusted network candidate.
+ // Create the new ephemeral configuration and see if we should switch over
+ if (mAllowUntrustedConnections) {
+ candidate =
+ mWifiConfigStore.wifiConfigurationFromScanResult(untrustedCandidate);
+ candidate.allowedKeyManagement.set(KeyMgmt.NONE);
+ candidate.ephemeral = true;
+ }
}
- // Now we don't have VPN, and thus don't actually connect to the untrusted candidate
- untrustedCandidate = null;
}
long lastUnwanted =
diff --git a/service/java/com/android/server/wifi/WifiConfigStore.java b/service/java/com/android/server/wifi/WifiConfigStore.java
index b9e6c80..41d27be 100644
--- a/service/java/com/android/server/wifi/WifiConfigStore.java
+++ b/service/java/com/android/server/wifi/WifiConfigStore.java
@@ -564,7 +564,7 @@
List<WifiConfiguration> networks = new ArrayList<>();
for(WifiConfiguration config : mConfiguredNetworks.values()) {
WifiConfiguration newConfig = new WifiConfiguration(config);
- if (config.autoJoinStatus == WifiConfiguration.AUTO_JOIN_DELETED) {
+ if (config.autoJoinStatus == WifiConfiguration.AUTO_JOIN_DELETED || config.ephemeral) {
// Do not enumerate and return this configuration to any one,
// for instance WiFi Picker.
// instead treat it as unknown. the configuration can still be retrieved
@@ -619,10 +619,10 @@
* @return List of networks
*/
List<WifiConfiguration> getRecentConfiguredNetworks(int milli, boolean copy) {
- List<WifiConfiguration> networks = null;
+ List<WifiConfiguration> networks = new ArrayList<WifiConfiguration>();
for (WifiConfiguration config : mConfiguredNetworks.values()) {
- if (config.autoJoinStatus == WifiConfiguration.AUTO_JOIN_DELETED) {
+ if (config.autoJoinStatus == WifiConfiguration.AUTO_JOIN_DELETED || config.ephemeral) {
// Do not enumerate and return this configuration to any one,
// instead treat it as unknown. the configuration can still be retrieved
// directly by the key or networkId
@@ -638,8 +638,6 @@
config.visibility.rssi24 == WifiConfiguration.INVALID_RSSI) {
continue;
}
- if (networks == null)
- networks = new ArrayList<WifiConfiguration>();
if (copy) {
networks.add(new WifiConfiguration(config));
} else {
@@ -2483,7 +2481,8 @@
WifiConfiguration config = mConfiguredNetworks.get(mNetworkIds.get(id));
- if (config == null || config.autoJoinStatus == WifiConfiguration.AUTO_JOIN_DELETED) {
+ if (config == null || config.autoJoinStatus == WifiConfiguration.AUTO_JOIN_DELETED ||
+ config.ephemeral) {
loge("configuration found for missing network, nid=" + id
+", ignored, networks.size=" + Integer.toString(networks.size()));
} else {
@@ -2828,6 +2827,14 @@
currentConfig.setAutoJoinStatus(WifiConfiguration.AUTO_JOIN_ENABLED);
}
+ if (currentConfig.configKey().equals(getLastSelectedConfiguration()) &&
+ currentConfig.ephemeral) {
+ // Make the config non-ephemeral since the user just explicitly clicked it.
+ currentConfig.ephemeral = false;
+ if (DBG) loge("remove ephemeral status netId=" + Integer.toString(netId)
+ + " " + currentConfig.configKey());
+ }
+
if (DBG) loge("will read network variables netId=" + Integer.toString(netId));
readNetworkVariables(currentConfig);
@@ -2866,7 +2873,7 @@
continue;
}
- if (link.autoJoinStatus == WifiConfiguration.AUTO_JOIN_DELETED) {
+ if (link.autoJoinStatus == WifiConfiguration.AUTO_JOIN_DELETED || link.ephemeral) {
continue;
}
@@ -2999,7 +3006,8 @@
for (WifiConfiguration link : mConfiguredNetworks.values()) {
boolean doLink = false;
- if (link.autoJoinStatus == WifiConfiguration.AUTO_JOIN_DELETED || link.selfAdded) {
+ if (link.autoJoinStatus == WifiConfiguration.AUTO_JOIN_DELETED || link.selfAdded ||
+ link.ephemeral) {
if (VVDBG) loge("associateWithConfiguration(): skip selfadd " + link.configKey() );
// Make sure we dont associate the scan result to a deleted config
continue;
diff --git a/service/java/com/android/server/wifi/WifiStateMachine.java b/service/java/com/android/server/wifi/WifiStateMachine.java
index 9003706..9eb7ef4 100644
--- a/service/java/com/android/server/wifi/WifiStateMachine.java
+++ b/service/java/com/android/server/wifi/WifiStateMachine.java
@@ -16,21 +16,20 @@
package com.android.server.wifi;
-import static android.net.wifi.WifiManager.WIFI_STATE_DISABLED;
-import static android.net.wifi.WifiManager.WIFI_STATE_DISABLING;
-import static android.net.wifi.WifiManager.WIFI_STATE_ENABLED;
-import static android.net.wifi.WifiManager.WIFI_STATE_ENABLING;
-import static android.net.wifi.WifiManager.WIFI_STATE_UNKNOWN;
-
-/**
- * TODO:
- * Deprecate WIFI_STATE_UNKNOWN
- */
import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLED;
import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLING;
import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLED;
import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLING;
import static android.net.wifi.WifiManager.WIFI_AP_STATE_FAILED;
+import static android.net.wifi.WifiManager.WIFI_STATE_DISABLED;
+import static android.net.wifi.WifiManager.WIFI_STATE_DISABLING;
+import static android.net.wifi.WifiManager.WIFI_STATE_ENABLED;
+import static android.net.wifi.WifiManager.WIFI_STATE_ENABLING;
+/**
+ * TODO:
+ * Deprecate WIFI_STATE_UNKNOWN
+ */
+import static android.net.wifi.WifiManager.WIFI_STATE_UNKNOWN;
import android.app.AlarmManager;
import android.app.PendingIntent;
@@ -53,12 +52,27 @@
import android.net.NetworkFactory;
import android.net.NetworkInfo;
import android.net.NetworkInfo.DetailedState;
+import android.net.NetworkRequest;
import android.net.NetworkUtils;
import android.net.RouteInfo;
import android.net.StaticIpConfiguration;
import android.net.TrafficStats;
-import android.net.wifi.*;
+import android.net.wifi.BatchedScanResult;
+import android.net.wifi.BatchedScanSettings;
+import android.net.wifi.RssiPacketCountInfo;
+import android.net.wifi.ScanResult;
+import android.net.wifi.ScanSettings;
import android.net.wifi.SupplicantState;
+import android.net.wifi.WifiChannel;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiConnectionStatistics;
+import android.net.wifi.WifiEnterpriseConfig;
+import android.net.wifi.WifiInfo;
+import android.net.wifi.WifiLinkLayerStats;
+import android.net.wifi.WifiManager;
+import android.net.wifi.WifiSsid;
+import android.net.wifi.WpsInfo;
+import android.net.wifi.WpsResult;
import android.net.wifi.WpsResult.Status;
import android.net.wifi.p2p.IWifiP2pManager;
import android.os.BatteryStats;
@@ -78,9 +92,9 @@
import android.os.WorkSource;
import android.provider.Settings;
import android.telephony.TelephonyManager;
-import android.util.LruCache;
import android.text.TextUtils;
import android.util.Log;
+import android.util.LruCache;
import com.android.internal.R;
import com.android.internal.app.IBatteryStats;
@@ -88,23 +102,26 @@
import com.android.internal.util.Protocol;
import com.android.internal.util.State;
import com.android.internal.util.StateMachine;
-import com.android.server.net.BaseNetworkObserver;
import com.android.server.net.NetlinkTracker;
-
import com.android.server.wifi.p2p.WifiP2pServiceImpl;
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.net.InetAddress;
-import java.util.*;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.regex.Pattern;
-import java.io.FileReader;
import java.io.BufferedReader;
+import java.io.FileDescriptor;
import java.io.FileNotFoundException;
+import java.io.FileReader;
import java.io.IOException;
+import java.io.PrintWriter;
import java.net.Inet4Address;
+import java.net.InetAddress;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Locale;
+import java.util.Queue;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.regex.Pattern;
/**
* Track the state of Wifi connectivity. All event handling is done here,
@@ -4325,9 +4342,17 @@
private void handleSuccessfulIpConfiguration() {
mLastSignalLevel = -1; // Force update of signal strength
WifiConfiguration c = getCurrentWifiConfiguration();
- // Reset IP failure tracking
if (c != null) {
+ // Reset IP failure tracking
c.numConnectionFailures = 0;
+
+ // Tell the framework whether the newly connected network is trusted or untrusted.
+ if (c.ephemeral) {
+ mNetworkCapabilities.removeCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED);
+ } else {
+ mNetworkCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED);
+ }
+ mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
}
if (c != null) {
ScanResult result = getCurrentScanResult();
@@ -4454,16 +4479,31 @@
}
private class WifiNetworkFactory extends NetworkFactory {
+ /** Number of outstanding NetworkRequests for untrusted networks. */
+ private int mUntrustedReqCount = 0;
+
public WifiNetworkFactory(Looper l, Context c, String TAG, NetworkCapabilities f) {
super(l, c, TAG, f);
}
- protected void startNetwork() {
- // TODO
- // Enter association mode.
+
+ @Override
+ protected void needNetworkFor(NetworkRequest networkRequest, int score) {
+ if (!networkRequest.networkCapabilities.hasCapability(
+ NetworkCapabilities.NET_CAPABILITY_TRUSTED)) {
+ if (++mUntrustedReqCount == 1) {
+ mWifiAutoJoinController.setAllowUntrustedConnections(true);
+ }
+ }
}
- protected void stopNetwork() {
- // TODO
- // Stop associating.
+
+ @Override
+ protected void releaseNetworkFor(NetworkRequest networkRequest) {
+ if (!networkRequest.networkCapabilities.hasCapability(
+ NetworkCapabilities.NET_CAPABILITY_TRUSTED)) {
+ if (--mUntrustedReqCount == 0) {
+ mWifiAutoJoinController.setAllowUntrustedConnections(false);
+ }
+ }
}
}
/********************************************************