From 2efcaa62b92a20fed7c370a18b948ea1fcdd7e51 Mon Sep 17 00:00:00 2001 From: Randy Pan Date: Wed, 27 Jul 2016 13:24:19 -0700 Subject: DO NOT MERGE ANYWHERE: Fix WiFiNetworkAgent#unwanted 1) No longer blacklist a network when it's unwanted by NetworkAgent. 2) Deprecate the network disable reason BAD_LINK. 3) Stop WiFi Auto_Connect attempt if neither saved Wifi network nor untrusted WiFi network is requested. Note: this CL is a cherry-pick of ag/1261693, as that CL cannot be submitted until after N DR cutoff date (expect submission on 8/18). Bug: 28558417 Tests: Unit Tests and manual tests Change-Id: I2b245cfb357b92ed925d89603e0fefded9d6865a (cherry pick from commit c4d044acc589188f25b8dcd962db52e1fc08fe8d) --- .../com/android/server/wifi/WifiConfigManager.java | 32 +-------- .../server/wifi/WifiConnectivityManager.java | 11 ++- .../com/android/server/wifi/WifiStateMachine.java | 78 ++++++++++++++++------ .../server/wifi/WifiConnectivityManagerTest.java | 2 +- 4 files changed, 70 insertions(+), 53 deletions(-) diff --git a/service/java/com/android/server/wifi/WifiConfigManager.java b/service/java/com/android/server/wifi/WifiConfigManager.java index c1a334a5d..dbe67e88e 100644 --- a/service/java/com/android/server/wifi/WifiConfigManager.java +++ b/service/java/com/android/server/wifi/WifiConfigManager.java @@ -190,7 +190,7 @@ public class WifiConfigManager { */ private static final int[] NETWORK_SELECTION_DISABLE_THRESHOLD = { -1, // threshold for NETWORK_SELECTION_ENABLE - 1, // threshold for DISABLED_BAD_LINK + 1, // threshold for DISABLED_BAD_LINK (deprecated) 5, // threshold for DISABLED_ASSOCIATION_REJECTION 5, // threshold for DISABLED_AUTHENTICATION_FAILURE 5, // threshold for DISABLED_DHCP_FAILURE @@ -206,7 +206,7 @@ public class WifiConfigManager { */ private static final int[] NETWORK_SELECTION_DISABLE_TIMEOUT = { Integer.MAX_VALUE, // threshold for NETWORK_SELECTION_ENABLE - 15, // threshold for DISABLED_BAD_LINK + 15, // threshold for DISABLED_BAD_LINK (deprecated) 5, // threshold for DISABLED_ASSOCIATION_REJECTION 5, // threshold for DISABLED_AUTHENTICATION_FAILURE 5, // threshold for DISABLED_DHCP_FAILURE @@ -242,11 +242,6 @@ public class WifiConfigManager { public AtomicInteger mCurrentNetworkBoost = new AtomicInteger(); public AtomicInteger mBandAward5Ghz = new AtomicInteger(); - /** - * If Connectivity Service has triggered an unwanted network disconnect - */ - public long mLastUnwantedNetworkDisconnectTimestamp = 0; - /** * 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. @@ -3222,29 +3217,6 @@ public class WifiConfigManager { } } - /** called when CS ask WiFistateMachine to disconnect the current network - * because the score is bad. - */ - void handleBadNetworkDisconnectReport(int netId, WifiInfo info) { - /* TODO verify the bad network is current */ - WifiConfiguration config = mConfiguredNetworks.getForCurrentUser(netId); - if (config != null) { - if ((info.is24GHz() && info.getRssi() - <= WifiQualifiedNetworkSelector.QUALIFIED_RSSI_24G_BAND) - || (info.is5GHz() && info.getRssi() - <= WifiQualifiedNetworkSelector.QUALIFIED_RSSI_5G_BAND)) { - // We do not block due to bad RSSI since network selection should not select bad - // RSSI candidate - } else { - // We got disabled but RSSI is good, so disable hard - updateNetworkSelectionStatus(config, - WifiConfiguration.NetworkSelectionStatus.DISABLED_BAD_LINK); - } - } - // Record last time Connectivity Service switched us away from WiFi and onto Cell - mLastUnwantedNetworkDisconnectTimestamp = mClock.currentTimeMillis(); - } - int getMaxDhcpRetries() { return mFacade.getIntegerSetting(mContext, Settings.Global.WIFI_MAX_DHCP_RETRY_COUNT, diff --git a/service/java/com/android/server/wifi/WifiConnectivityManager.java b/service/java/com/android/server/wifi/WifiConnectivityManager.java index 7f3d5d7d9..1c388c120 100644 --- a/service/java/com/android/server/wifi/WifiConnectivityManager.java +++ b/service/java/com/android/server/wifi/WifiConnectivityManager.java @@ -510,7 +510,7 @@ public class WifiConnectivityManager { public WifiConnectivityManager(Context context, WifiStateMachine stateMachine, WifiScanner scanner, WifiConfigManager configManager, WifiInfo wifiInfo, WifiQualifiedNetworkSelector qualifiedNetworkSelector, - WifiInjector wifiInjector, Looper looper) { + WifiInjector wifiInjector, Looper looper, boolean enable) { mStateMachine = stateMachine; mScanner = scanner; mConfigManager = configManager; @@ -545,7 +545,10 @@ public class WifiConnectivityManager { // Register for all single scan results mScanner.registerScanListener(mAllSingleScanListener); - Log.i(TAG, "ConnectivityScanManager initialized "); + mWifiConnectivityManagerEnabled = enable; + + Log.i(TAG, "ConnectivityScanManager initialized and " + + (enable ? "enabled" : "disabled")); } /** @@ -1118,6 +1121,8 @@ public class WifiConnectivityManager { stopConnectivityScan(); resetLastPeriodicSingleScanTimeStamp(); mLastConnectionAttemptBssid = null; + } else if (mWifiConnectivityManagerEnabled) { + startConnectivityScan(SCAN_IMMEDIATELY); } } @@ -1133,6 +1138,8 @@ public class WifiConnectivityManager { stopConnectivityScan(); resetLastPeriodicSingleScanTimeStamp(); mLastConnectionAttemptBssid = null; + } else if (mWifiEnabled) { + startConnectivityScan(SCAN_IMMEDIATELY); } } diff --git a/service/java/com/android/server/wifi/WifiStateMachine.java b/service/java/com/android/server/wifi/WifiStateMachine.java index ccb313624..65bf10233 100644 --- a/service/java/com/android/server/wifi/WifiStateMachine.java +++ b/service/java/com/android/server/wifi/WifiStateMachine.java @@ -96,6 +96,7 @@ import android.util.Log; import android.util.SparseArray; import com.android.internal.R; +import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.app.IBatteryStats; import com.android.internal.util.AsyncChannel; @@ -544,10 +545,14 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss private WifiScanner mWifiScanner; - private int mConnectionRequests = 0; + @GuardedBy("mWifiReqCountLock") + private int mConnectionReqCount = 0; private WifiNetworkFactory mNetworkFactory; + @GuardedBy("mWifiReqCountLock") + private int mUntrustedReqCount = 0; private UntrustedWifiNetworkFactory mUntrustedNetworkFactory; private WifiNetworkAgent mNetworkAgent; + private final Object mWifiReqCountLock = new Object(); private String[] mWhiteListedSsids = null; @@ -2535,7 +2540,8 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss sb.append(" known=").append(mNumScanResultsKnown); sb.append(" got=").append(mNumScanResultsReturned); sb.append(String.format(" bcn=%d", mRunningBeaconCount)); - sb.append(String.format(" con=%d", mConnectionRequests)); + sb.append(String.format(" con=%d", mConnectionReqCount)); + sb.append(String.format(" untrustedcn=%d", mUntrustedReqCount)); key = mWifiConfigManager.getLastSelectedConfiguration(); if (key != null) { sb.append(" last=").append(key); @@ -3906,23 +3912,33 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss @Override protected void needNetworkFor(NetworkRequest networkRequest, int score) { - ++mConnectionRequests; + synchronized (mWifiReqCountLock) { + if (++mConnectionReqCount == 1) { + if (mWifiConnectivityManager != null && mUntrustedReqCount == 0) { + mWifiConnectivityManager.enable(true); + } + } + } } @Override protected void releaseNetworkFor(NetworkRequest networkRequest) { - --mConnectionRequests; + synchronized (mWifiReqCountLock) { + if (--mConnectionReqCount == 0) { + if (mWifiConnectivityManager != null && mUntrustedReqCount == 0) { + mWifiConnectivityManager.enable(false); + } + } + } } public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - pw.println("mConnectionRequests " + mConnectionRequests); + pw.println("mConnectionReqCount " + mConnectionReqCount); } } private class UntrustedWifiNetworkFactory extends NetworkFactory { - private int mUntrustedReqCount; - public UntrustedWifiNetworkFactory(Looper l, Context c, String tag, NetworkCapabilities f) { super(l, c, tag, f); } @@ -3931,9 +3947,14 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss protected void needNetworkFor(NetworkRequest networkRequest, int score) { if (!networkRequest.networkCapabilities.hasCapability( NetworkCapabilities.NET_CAPABILITY_TRUSTED)) { - if (++mUntrustedReqCount == 1) { - if (mWifiConnectivityManager != null) { - mWifiConnectivityManager.setUntrustedConnectionAllowed(true); + synchronized (mWifiReqCountLock) { + if (++mUntrustedReqCount == 1) { + if (mWifiConnectivityManager != null) { + if (mConnectionReqCount == 0) { + mWifiConnectivityManager.enable(true); + } + mWifiConnectivityManager.setUntrustedConnectionAllowed(true); + } } } } @@ -3943,9 +3964,14 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss protected void releaseNetworkFor(NetworkRequest networkRequest) { if (!networkRequest.networkCapabilities.hasCapability( NetworkCapabilities.NET_CAPABILITY_TRUSTED)) { - if (--mUntrustedReqCount == 0) { - if (mWifiConnectivityManager != null) { - mWifiConnectivityManager.setUntrustedConnectionAllowed(false); + synchronized (mWifiReqCountLock) { + if (--mUntrustedReqCount == 0) { + if (mWifiConnectivityManager != null) { + mWifiConnectivityManager.setUntrustedConnectionAllowed(false); + if (mConnectionReqCount == 0) { + mWifiConnectivityManager.enable(false); + } + } } } } @@ -4682,10 +4708,12 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss if (mWifiScanner == null) { mWifiScanner = mFacade.makeWifiScanner(mContext, getHandler().getLooper()); - mWifiConnectivityManager = new WifiConnectivityManager(mContext, - WifiStateMachine.this, mWifiScanner, mWifiConfigManager, mWifiInfo, - mWifiQualifiedNetworkSelector, mWifiInjector, - getHandler().getLooper()); + synchronized (mWifiReqCountLock) { + mWifiConnectivityManager = new WifiConnectivityManager(mContext, + WifiStateMachine.this, mWifiScanner, mWifiConfigManager, mWifiInfo, + mWifiQualifiedNetworkSelector, mWifiInjector, + getHandler().getLooper(), hasConnectionRequests()); + } } mWifiLogger.startLogging(DBG); @@ -7063,8 +7091,6 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss break; case CMD_UNWANTED_NETWORK: if (message.arg1 == NETWORK_STATUS_UNWANTED_DISCONNECT) { - mWifiConfigManager.handleBadNetworkDisconnectReport( - mLastNetworkId, mWifiInfo); mWifiNative.disconnect(); transitionTo(mDisconnectingState); } else if (message.arg1 == NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN || @@ -8073,7 +8099,11 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss * @param bssid BSSID of the network */ public void autoConnectToNetwork(int networkId, String bssid) { - sendMessage(CMD_AUTO_CONNECT, networkId, 0, bssid); + synchronized (mWifiReqCountLock) { + if (hasConnectionRequests()) { + sendMessage(CMD_AUTO_CONNECT, networkId, 0, bssid); + } + } } /** @@ -8216,4 +8246,12 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss } return null; } + + /** + * Check if there is any connection request for WiFi network. + * Note, caller of this helper function must acquire mWifiReqCountLock. + */ + private boolean hasConnectionRequests() { + return mConnectionReqCount > 0 || mUntrustedReqCount > 0; + } } diff --git a/tests/wifitests/src/com/android/server/wifi/WifiConnectivityManagerTest.java b/tests/wifitests/src/com/android/server/wifi/WifiConnectivityManagerTest.java index 022997d67..b1f88ecc9 100644 --- a/tests/wifitests/src/com/android/server/wifi/WifiConnectivityManagerTest.java +++ b/tests/wifitests/src/com/android/server/wifi/WifiConnectivityManagerTest.java @@ -75,7 +75,7 @@ public class WifiConnectivityManagerTest { mWifiQNS = mockWifiQualifiedNetworkSelector(); mWifiConnectivityManager = new WifiConnectivityManager(mContext, mWifiStateMachine, mWifiScanner, mWifiConfigManager, mWifiInfo, mWifiQNS, mWifiInjector, - mLooper.getLooper()); + mLooper.getLooper(), true); mWifiConnectivityManager.setWifiEnabled(true); when(mClock.elapsedRealtime()).thenReturn(SystemClock.elapsedRealtime()); } -- cgit v1.2.3 From 168a9ff770b90983aaa14b9a7e21419dfb7b0917 Mon Sep 17 00:00:00 2001 From: Paul Stewart Date: Tue, 20 Sep 2016 07:03:45 +0000 Subject: Merge "WifiStateMachine: Mask RTT capabilities against System Properties" am: a78a579804 am: 21b6b83067 am: 8c0d84239a am: dd25b8603d Change-Id: Ic0a06fdcb8536389682c0da0ac877e73a109bc1b (cherry picked from commit 0703e1b30fbe529fe7d015802a4c9f2f56885cf9) --- .../com/android/server/wifi/PropertyService.java | 7 ++++ .../android/server/wifi/SystemPropertyService.java | 5 +++ .../com/android/server/wifi/WifiStateMachine.java | 8 +++++ .../android/server/wifi/WifiStateMachineTest.java | 40 ++++++++++++++++++++++ 4 files changed, 60 insertions(+) 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/WifiStateMachine.java b/service/java/com/android/server/wifi/WifiStateMachine.java index 62ffd27b6..f649986eb 100644 --- a/service/java/com/android/server/wifi/WifiStateMachine.java +++ b/service/java/com/android/server/wifi/WifiStateMachine.java @@ -2055,6 +2055,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; } diff --git a/tests/wifitests/src/com/android/server/wifi/WifiStateMachineTest.java b/tests/wifitests/src/com/android/server/wifi/WifiStateMachineTest.java index 53d8f46aa..636c93d87 100644 --- a/tests/wifitests/src/com/android/server/wifi/WifiStateMachineTest.java +++ b/tests/wifitests/src/com/android/server/wifi/WifiStateMachineTest.java @@ -1214,4 +1214,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)); + } } -- cgit v1.2.3 From a8a5644b48660a166adfad9fdc274cbdb44cdf4b Mon Sep 17 00:00:00 2001 From: Randy Pan Date: Thu, 27 Oct 2016 09:38:21 -0700 Subject: DO NOT MERGE: Check on whether an ephemeral network is deleted Add quotes to ScanResult.SSID before passing it to WifiConfigManager#waswasEphemeralNetworkDeleted. While there, improved the java doc of WifiConfigManager#waswasEphemeralNetworkDeleted to make it clear that SSID surrounded by quotes is expected. Bug: 32205260 Test: Ephemeral network added by WiFi Assistant can be forgotten Change-Id: I45afd45fd7257a31ec16aca5b6ae765d417ecead --- service/java/com/android/server/wifi/WifiConfigManager.java | 3 ++- .../com/android/server/wifi/WifiQualifiedNetworkSelector.java | 4 +++- service/java/com/android/server/wifi/util/ScanDetailUtil.java | 8 ++++++++ 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/service/java/com/android/server/wifi/WifiConfigManager.java b/service/java/com/android/server/wifi/WifiConfigManager.java index 4a27fef97..3c717c0ed 100644 --- a/service/java/com/android/server/wifi/WifiConfigManager.java +++ b/service/java/com/android/server/wifi/WifiConfigManager.java @@ -3240,7 +3240,8 @@ 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) { diff --git a/service/java/com/android/server/wifi/WifiQualifiedNetworkSelector.java b/service/java/com/android/server/wifi/WifiQualifiedNetworkSelector.java index dd8bdae50..e916c8c4a 100644 --- a/service/java/com/android/server/wifi/WifiQualifiedNetworkSelector.java +++ b/service/java/com/android/server/wifi/WifiQualifiedNetworkSelector.java @@ -32,6 +32,7 @@ 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; @@ -728,7 +729,8 @@ public class WifiQualifiedNetworkSelector { if (isUntrustedConnectionsAllowed) { Integer netScore = getNetworkScore(scanResult, false); if (netScore != null - && !mWifiConfigManager.wasEphemeralNetworkDeleted(scanResult.SSID)) { + && !mWifiConfigManager.wasEphemeralNetworkDeleted( + ScanDetailUtil.createQuotedSSID(scanResult.SSID))) { externalScoreEvaluator.evalUntrustedCandidate(netScore, scanResult); // scanDetail is for available ephemeral network filteredScanDetails.add(Pair.create(scanDetail, 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 + "\""; + } } -- cgit v1.2.3 From 81080a8430568399a14e9b85007a8aaea5c2e6eb Mon Sep 17 00:00:00 2001 From: Peter Qiu Date: Tue, 20 Sep 2016 12:36:31 -0700 Subject: DO NOT MERGE: OMAParser: throw IOException when parsing a null XML string This avoids a NullPointerException when parsing a null XML string. OMAParser.parse is only used by PasspointManagementObjectManager for adding/building/modifying a HomeSP from a XML string. It is fine to use IOException since it is already being handled gracefully by its upstream callers. Bug: 31497435 Test: unit tests Test: Verify system server crashes when executing the command below without the fix and doesn't crash with the fix: "adb shell service call wifi 8 i32 0" Change-Id: If2ad13b8573d49ba0ccbea2427f3c63d841f866d (cherry picked from commit 519056861a467ae64e142ff07d53891514ef9c70) --- .../server/wifi/hotspot2/omadm/OMAParser.java | 3 ++ .../wifi/PasspointManagementObjectManagerTest.java | 36 ++++++++++++++++++++++ 2 files changed, 39 insertions(+) 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/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 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 moDefs = + new ArrayList(); + moDefs.add(moDef); + moMgr.modifySP("wi-fi.org", moDefs); + } + /** verify removing an existing service provider works */ @Test public void removeSP() throws Exception { -- cgit v1.2.3 From 70570f92c6e0a65c144c8df2e5639ef454f1dc7a Mon Sep 17 00:00:00 2001 From: Randy Pan Date: Fri, 4 Nov 2016 16:15:49 -0700 Subject: DO NOT MERGE: QNS: less agressive roaming When connected, QNS no longer triggers network switching if the current network didn't show up in the scan results. While there, fixed a QNS unit test failure. Bug: 31707128 Test: Wifi Unit Tests Change-Id: I24a16828fb60af4015a4faf4e00c356898729173 --- .../server/wifi/WifiQualifiedNetworkSelector.java | 17 ++++++ .../wifi/WifiQualifiedNetworkSelectorTest.java | 67 +++++++++++++++++++++- 2 files changed, 82 insertions(+), 2 deletions(-) diff --git a/service/java/com/android/server/wifi/WifiQualifiedNetworkSelector.java b/service/java/com/android/server/wifi/WifiQualifiedNetworkSelector.java index e916c8c4a..1ddf6ebcb 100644 --- a/service/java/com/android/server/wifi/WifiQualifiedNetworkSelector.java +++ b/service/java/com/android/server/wifi/WifiQualifiedNetworkSelector.java @@ -652,6 +652,7 @@ public class WifiQualifiedNetworkSelector { StringBuffer noValidSsid = new StringBuffer(); StringBuffer scoreHistory = new StringBuffer(); ArrayList unscoredNetworks = new ArrayList(); + boolean scanResultsHaveCurrentBssid = false; //iterate all scan results and find the best candidate with the highest score for (ScanDetail scanDetail : mScanDetails) { @@ -665,6 +666,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) @@ -819,6 +826,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; diff --git a/tests/wifitests/src/com/android/server/wifi/WifiQualifiedNetworkSelectorTest.java b/tests/wifitests/src/com/android/server/wifi/WifiQualifiedNetworkSelectorTest.java index 1726e7d32..49343644a 100644 --- a/tests/wifitests/src/com/android/server/wifi/WifiQualifiedNetworkSelectorTest.java +++ b/tests/wifitests/src/com/android/server/wifi/WifiQualifiedNetworkSelectorTest.java @@ -46,6 +46,7 @@ import android.util.LocalLog; 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; @@ -1070,6 +1071,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 +1884,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 +2332,60 @@ 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 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 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); + 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); + } } -- cgit v1.2.3 From eb77c40b3d17153fe91ca1691aaf2ad16f3f7267 Mon Sep 17 00:00:00 2001 From: Roshan Pius Date: Tue, 22 Nov 2016 14:16:38 -0800 Subject: DO NOT MERGE: WifiConfigManager: Ignore disabled networks in PNO list These networks are not connectable even if they're detected by PNO scans. So, ignore them in the PNO list. Bug: 33055484 Test: Integration tests Change-Id: I3a33e0444639969195506321f630430520bbfcd5 --- .../com/android/server/wifi/WifiConfigManager.java | 9 +++++++++ .../com/android/server/wifi/WifiConfigManagerTest.java | 18 ++++++++++++------ 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/service/java/com/android/server/wifi/WifiConfigManager.java b/service/java/com/android/server/wifi/WifiConfigManager.java index 3c717c0ed..0cc0c9fca 100644 --- a/service/java/com/android/server/wifi/WifiConfigManager.java +++ b/service/java/com/android/server/wifi/WifiConfigManager.java @@ -94,6 +94,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; @@ -1123,6 +1124,14 @@ public class WifiConfigManager { ArrayList pnoList = new ArrayList<>(); ArrayList wifiConfigurations = new ArrayList<>(mConfiguredNetworks.valuesForCurrentUser()); + // Remove any permanently disabled networks. + Iterator 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. 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()); } -- cgit v1.2.3 From 1200cb27c41ffaa5ff7df61b1758f28be19b01d3 Mon Sep 17 00:00:00 2001 From: Paul Stewart Date: Wed, 2 Nov 2016 14:48:01 -0700 Subject: DO NOT MERGE: Upgrade WPA/EAP connections to their fast-transition equivalent The developer-visible API and settings should not have to know whether an AP supports BSS fast transitions, but from a system point of view it is beneficial (and in some cases necessary) to take advantage of it where it is possible. From a config point of view there is no additional information required except to enable the authentication type. This allows us to handle the feature addition at the lowest layer possible, assuming that the underlying hardware supports (and is validated) the fast transition feature. This implementation will be replaced with one in wificond once pushing configuration to wpa_supplicant is moved there. Bug: 32607043 Change-Id: I89a1e0bea3bba3ec8506fc9b239bea8b51c3d45c Test: Manual: Create an FT-only AP and attempt connections --- .../com/android/server/wifi/WifiConfigManager.java | 8 +++++- .../com/android/server/wifi/WifiConfigStore.java | 29 ++++++++++++++++++---- .../com/android/server/wifi/WifiStateMachine.java | 1 - 3 files changed, 31 insertions(+), 7 deletions(-) diff --git a/service/java/com/android/server/wifi/WifiConfigManager.java b/service/java/com/android/server/wifi/WifiConfigManager.java index 3c717c0ed..4c265efae 100644 --- a/service/java/com/android/server/wifi/WifiConfigManager.java +++ b/service/java/com/android/server/wifi/WifiConfigManager.java @@ -242,6 +242,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. @@ -377,6 +380,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); Log.d(Utils.hs2LogTag(getClass()), "Passpoint is " + (hs2on ? "enabled" : "disabled")); @@ -1951,7 +1956,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; diff --git a/service/java/com/android/server/wifi/WifiConfigStore.java b/service/java/com/android/server/wifi/WifiConfigStore.java index b693e2344..cfed460cb 100644 --- a/service/java/com/android/server/wifi/WifiConfigStore.java +++ b/service/java/com/android/server/wifi/WifiConfigStore.java @@ -601,14 +601,27 @@ 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; + } + /** * 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; } @@ -631,6 +644,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( @@ -788,11 +805,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; } @@ -816,7 +835,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/WifiStateMachine.java b/service/java/com/android/server/wifi/WifiStateMachine.java index 9d8a66f2d..0c7e987ee 100644 --- a/service/java/com/android/server/wifi/WifiStateMachine.java +++ b/service/java/com/android/server/wifi/WifiStateMachine.java @@ -1026,7 +1026,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()); -- cgit v1.2.3 From 989265e3f6ec0cf4cdfc5b58e60db684827bf4b5 Mon Sep 17 00:00:00 2001 From: Svetoslav Ganov Date: Tue, 26 Jul 2016 18:32:26 -0700 Subject: Add WiFi toggle prompts - wifi If permission review is enabled toggling WiFi on or off results in a user prompt to collect a consent. This applies only to legacy apps, i.e. ones that don't support runtime permissions as they target SDK 22. bug:28715749 Change-Id: Ie60ae91bd8e9c67a3e14a2820055234f669df1df --- .../com/android/server/wifi/WifiServiceImpl.java | 77 ++++++++++++++++++++-- 1 file changed, 73 insertions(+), 4 deletions(-) diff --git a/service/java/com/android/server/wifi/WifiServiceImpl.java b/service/java/com/android/server/wifi/WifiServiceImpl.java index 740ef6e54..d4ad0a7e0 100644 --- a/service/java/com/android/server/wifi/WifiServiceImpl.java +++ b/service/java/com/android/server/wifi/WifiServiceImpl.java @@ -36,6 +36,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; @@ -70,6 +71,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; @@ -160,6 +162,8 @@ public class WifiServiceImpl extends IWifiManager.Stub { */ private AsyncChannel mWifiStateMachineChannel; + private final boolean mPermissionReviewRequired; + /** * Handles client connections */ @@ -348,6 +352,10 @@ public class WifiServiceImpl extends IWifiManager.Stub { mSettingsStore, mWifiLockManager, wifiThread.getLooper(), mFacade); // Set the WifiController for WifiLastResortWatchdog mWifiInjector.getWifiLastResortWatchdog().setWifiController(mWifiController); + + mPermissionReviewRequired = Build.PERMISSIONS_REVIEW_REQUIRED + || context.getResources().getBoolean( + com.android.internal.R.bool.config_permissionReviewRequired); } @@ -408,7 +416,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) { @@ -547,7 +561,8 @@ 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()); @@ -556,7 +571,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)) { @@ -567,6 +581,26 @@ public class WifiServiceImpl extends IWifiManager.Stub { Binder.restoreCallingIdentity(ident); } + + if (mPermissionReviewRequired) { + final int wiFiEnabledState = getWifiEnabledState(); + if (enable) { + if (wiFiEnabledState == WifiManager.WIFI_STATE_DISABLING + || wiFiEnabledState == WifiManager.WIFI_STATE_DISABLED) { + if (startConsentUiIfNeeded(packageName, Binder.getCallingUid(), + WifiManager.ACTION_REQUEST_ENABLE)) { + return true; + } + } + } else if (wiFiEnabledState == WifiManager.WIFI_STATE_ENABLING + || wiFiEnabledState == WifiManager.WIFI_STATE_ENABLED) { + if (startConsentUiIfNeeded(packageName, Binder.getCallingUid(), + WifiManager.ACTION_REQUEST_DISABLE)) { + return true; + } + } + } + mWifiController.sendMessage(CMD_WIFI_TOGGLED); return true; } @@ -1384,6 +1418,37 @@ public class WifiServiceImpl extends IWifiManager.Stub { } }; + private boolean startConsentUiIfNeeded(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); + } + + // Legacy apps in permission review mode trigger a user prompt + if (applicationInfo.targetSdkVersion < Build.VERSION_CODES.M) { + 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()); + } + return false; + } + /** * Observes settings changes to scan always mode. */ @@ -1735,7 +1800,11 @@ public class WifiServiceImpl extends IWifiManager.Stub { if (!mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_WIFI)) { // Enable wifi - setWifiEnabled(true); + try { + setWifiEnabled(mContext.getOpPackageName(), true); + } catch (RemoteException e) { + /* ignore - local call */ + } // Delete all Wifi SSIDs List networks = getConfiguredNetworks(); if (networks != null) { -- cgit v1.2.3 From e22b68960966645a77cb71042879a4ab0d9bd638 Mon Sep 17 00:00:00 2001 From: pkanwar Date: Wed, 23 Nov 2016 11:16:26 -0800 Subject: DO NOT MERGE: Allow Carriers to specify Wifi Networks. Added a new evaulator for Carrier networks. Added functionality to read Carrier networks from Carrier Config. Bug: 31003437 Test: Added new tests, regression tests passed (frameworks-wifi)Allow Carriers to specify Wifi Networks. Change-Id: I226fb716a2a2883a8b2630c0d4e8cd51636b1089 --- .../server/wifi/WifiQualifiedNetworkSelector.java | 202 ++++++++++++++++++++- .../wifi/WifiQualifiedNetworkSelectorTest.java | 151 +++++++++++++++ 2 files changed, 349 insertions(+), 4 deletions(-) diff --git a/service/java/com/android/server/wifi/WifiQualifiedNetworkSelector.java b/service/java/com/android/server/wifi/WifiQualifiedNetworkSelector.java index 1ddf6ebcb..a612cbba1 100644 --- a/service/java/com/android/server/wifi/WifiQualifiedNetworkSelector.java +++ b/service/java/com/android/server/wifi/WifiQualifiedNetworkSelector.java @@ -17,7 +17,10 @@ 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; @@ -25,7 +28,10 @@ import android.net.wifi.ScanResult; import android.net.wifi.WifiConfiguration; 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; @@ -38,6 +44,8 @@ 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; @@ -109,6 +117,8 @@ public class WifiQualifiedNetworkSelector { private int mUserPreferedBand = WifiManager.WIFI_FREQUENCY_BAND_AUTO; private Map mBssidBlacklist = new HashMap(); + private List mCarrierConfiguredNetworks = new ArrayList(); + private CarrierConfigManager mCarrierConfigManager; /** * class save the blacklist status of a given BSSID @@ -192,6 +202,50 @@ public class WifiQualifiedNetworkSelector { mNoIntnetPenalty = (mWifiConfigManager.mThresholdSaturatedRssi24.get() + mRssiScoreOffset) * mRssiScoreSlope + mWifiConfigManager.mBandAward5Ghz.get() + mWifiConfigManager.mCurrentNetworkBoost.get() + mSameBssidAward + mSecurityAward; + mCarrierConfigManager = (CarrierConfigManager) + context.getSystemService(Context.CARRIER_CONFIG_SERVICE); + + final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + localLog("mBroadcastReceiver: onReceive " + intent.getAction()); + PersistableBundle b = mCarrierConfigManager.getConfig(); + String[] mWifiArray = + b.getStringArray(CarrierConfigManager.KEY_CARRIER_WIFI_STRING_ARRAY); + WifiConfiguration wifiConfig; + if (mWifiArray == null) { + return; + } + + for (String config : mWifiArray) { + String[] wc = config.split("\\|"); + wifiConfig = new WifiConfiguration(); + try { + byte[] decodedBytes = Base64.decode(wc[0], Base64.DEFAULT); + String ssid = new String(decodedBytes); + wifiConfig.SSID = "\"" + ssid + "\""; + } catch (IllegalArgumentException ex) { + localLog("mBroadcaseReceiver: Could not decode base64 string"); + continue; + } + try { + int s = Integer.parseInt(wc[1]); + wifiConfig.allowedKeyManagement.set(s); + } catch (NumberFormatException e) { + localLog("mBroadcastReceiver: not an integer" + wc[1]); + } + mCarrierConfiguredNetworks.add(wifiConfig); + localLog("mBroadcastReceiver: onReceive networks:" + wifiConfig.SSID); + } + } + }; + context.registerReceiver(mBroadcastReceiver, new IntentFilter( + CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED)); + } + + @VisibleForTesting + public void setCarrierConfiguredNetworks(List carrierConfiguredNetworks) { + mCarrierConfiguredNetworks = carrierConfiguredNetworks; } void enableVerboseLogging(int verbose) { @@ -239,7 +293,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; @@ -583,6 +637,16 @@ public class WifiQualifiedNetworkSelector { return status == null ? false : status.mIsBlacklisted; } + private boolean isCarrierNetwork(ScanResult scanResult) { + String ssid = "\"" + scanResult.SSID + "\""; + for (WifiConfiguration config : mCarrierConfiguredNetworks) { + if (config.SSID.equals(ssid)) { + return true; + } + } + return 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 @@ -606,7 +670,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 scanDetails, boolean isLinkDebouncing, boolean isConnected, boolean isDisconnected, boolean isSupplicantTransient) { @@ -633,8 +697,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); @@ -733,10 +800,21 @@ 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) { + localLog("Network is a ephemeral network..."); if (isUntrustedConnectionsAllowed) { Integer netScore = getNetworkScore(scanResult, false); - if (netScore != null - && !mWifiConfigManager.wasEphemeralNetworkDeleted( + if (netScore == null) { + localLog("Checking the carrierScoreEvaluator for candidates..."); + // Evaluate the carrier network as a possible candidate. + if (!mCarrierConfiguredNetworks.isEmpty() && isCarrierNetwork(scanResult)) { + carrierScoreEvaluator.evalCarrierCandidate(scanResult, + getCarrierScore(scanResult, mCurrentConnectedNetwork, + (mCurrentBssid == null ? false : + mCurrentBssid.equals(scanResult.BSSID)))); + } + + } + else if (!mWifiConfigManager.wasEphemeralNetworkDeleted( ScanDetailUtil.createQuotedSSID(scanResult.SSID))) { externalScoreEvaluator.evalUntrustedCandidate(netScore, scanResult); // scanDetail is for available ephemeral network @@ -871,6 +949,14 @@ public class WifiQualifiedNetworkSelector { } } + if (scanResultCandidate == null) { + networkCandidate = getCarrierScoreCandidate(carrierScoreEvaluator); + localLog("Carrier candidate::" + networkCandidate); + if (networkCandidate != null) { + scanResultCandidate = networkCandidate.getNetworkSelectionStatus().getCandidate(); + } + } + if (scanResultCandidate == null) { localLog("Can not find any suitable candidates"); return null; @@ -955,6 +1041,32 @@ public class WifiQualifiedNetworkSelector { return networkCandidate; } + /** + * Returns the best candidate network according to the given CarrierScoreEvaluator. + */ + @Nullable + WifiConfiguration getCarrierScoreCandidate(CarrierScoreEvaluator scoreEvaluator) { + WifiConfiguration networkCandidate = null; + + ScanResult untrustedScanResultCandidate = scoreEvaluator.getScanResultCandidate(); + if (untrustedScanResultCandidate == null) { + return null; + } + WifiConfiguration unTrustedNetworkCandidate = + mWifiConfigManager.wifiConfigurationFromScanResult( + untrustedScanResultCandidate); + // Mark this config as ephemeral so it isn't persisted. + unTrustedNetworkCandidate.ephemeral = true; + mWifiConfigManager.saveNetwork(unTrustedNetworkCandidate, WifiConfiguration.UNKNOWN_UID); + localLog(String.format("new carrier candidate %s network ID:%d, ", + toScanId(untrustedScanResultCandidate), unTrustedNetworkCandidate.networkId)); + + unTrustedNetworkCandidate.getNetworkSelectionStatus() + .setCandidate(untrustedScanResultCandidate); + networkCandidate = unTrustedNetworkCandidate; + return networkCandidate; + } + /** * Returns the available external network score or NULL if no score is available. * @@ -972,6 +1084,43 @@ public class WifiQualifiedNetworkSelector { return null; } + /** + * 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. */ @@ -1061,4 +1210,49 @@ 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 WifiConfiguration mSavedConfig; + 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; + } + + WifiConfiguration getSavedConfig() { + return mSavedConfig; + } + + private void localLog(String log) { + if (mDbg) { + mLocalLog.log(log); + } + } + } } diff --git a/tests/wifitests/src/com/android/server/wifi/WifiQualifiedNetworkSelectorTest.java b/tests/wifitests/src/com/android/server/wifi/WifiQualifiedNetworkSelectorTest.java index 49343644a..957e8c24c 100644 --- a/tests/wifitests/src/com/android/server/wifi/WifiQualifiedNetworkSelectorTest.java +++ b/tests/wifitests/src/com/android/server/wifi/WifiQualifiedNetworkSelectorTest.java @@ -80,6 +80,23 @@ public class WifiQualifiedNetworkSelectorTest { mWifiQualifiedNetworkSelector.setUserPreferredBand(1); mWifiQualifiedNetworkSelector.setWifiNetworkScoreCache(mScoreCache); when(mClock.elapsedRealtime()).thenReturn(SystemClock.elapsedRealtime()); + + //setup Carrier Networks + WifiConfiguration wifiConfig = new WifiConfiguration(); + wifiConfig.SSID = "\"TEST1\""; + wifiConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP); + mCarrierConfiguredNetworks.add(wifiConfig); + + WifiConfiguration wifiConfig1 = new WifiConfiguration(); + wifiConfig1.SSID = "\"TEST2\""; + wifiConfig1.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP); + mCarrierConfiguredNetworks.add(wifiConfig1); + + WifiConfiguration wifiConfig2 = new WifiConfiguration(); + wifiConfig2.SSID = "\"TEST3\""; + wifiConfig2.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP); + mCarrierConfiguredNetworks.add(wifiConfig2); + mWifiQualifiedNetworkSelector.setCarrierConfiguredNetworks(mCarrierConfiguredNetworks); } @After @@ -99,6 +116,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 mCarrierConfiguredNetworks = new ArrayList(); private List getScanDetails(String[] ssids, String[] bssids, int[] frequencies, String[] caps, int[] levels) { @@ -2370,6 +2388,7 @@ public class WifiQualifiedNetworkSelectorTest { 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); @@ -2388,4 +2407,136 @@ public class WifiQualifiedNetworkSelectorTest { false, scanDetails, false, true, false, false); assertEquals("Expect no network selection", null, candidate); } + + /** + * 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 scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels); + + WifiConfiguration[] savedConfigs = generateWifiConfigurations(ssids, security); + prepareConfigStore(savedConfigs); + + ScanResult chosenScanResult = scanDetails.get(1).getScanResult(); + WifiConfiguration unTrustedNetworkCandidate = mock(WifiConfiguration.class); + unTrustedNetworkCandidate.SSID = null; + unTrustedNetworkCandidate.networkId = WifiConfiguration.INVALID_NETWORK_ID; + when(mWifiConfigManager.updateSavedNetworkWithNewScanDetail(scanDetails.get(1), + false)).thenReturn(null); + when(mWifiConfigManager + .wifiConfigurationFromScanResult(scanDetails.get(1).getScanResult())) + .thenReturn(unTrustedNetworkCandidate); + WifiConfiguration.NetworkSelectionStatus selectionStatus = + mock(WifiConfiguration.NetworkSelectionStatus.class); + when(unTrustedNetworkCandidate.getNetworkSelectionStatus()).thenReturn(selectionStatus); + when(selectionStatus.getCandidate()).thenReturn(chosenScanResult); + + WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, + true, scanDetails, false, false, true, false); + assertSame(unTrustedNetworkCandidate, candidate); + } + + /** + * 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 scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels); + ScanResult chosenScanResult = scanDetails.get(1).getScanResult(); + WifiConfiguration unTrustedNetworkCandidate = mock(WifiConfiguration.class); + unTrustedNetworkCandidate.SSID = null; + unTrustedNetworkCandidate.networkId = WifiConfiguration.INVALID_NETWORK_ID; + when(mWifiConfigManager.updateSavedNetworkWithNewScanDetail(scanDetails.get(1), + false)).thenReturn(null); + when(mWifiConfigManager + .wifiConfigurationFromScanResult(scanDetails.get(1).getScanResult())) + .thenReturn(unTrustedNetworkCandidate); + WifiConfiguration.NetworkSelectionStatus selectionStatus = + mock(WifiConfiguration.NetworkSelectionStatus.class); + when(unTrustedNetworkCandidate.getNetworkSelectionStatus()).thenReturn(selectionStatus); + when(selectionStatus.getCandidate()).thenReturn(chosenScanResult); + + WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, + true, scanDetails, false, false, true, false); + assertSame(unTrustedNetworkCandidate, candidate); + } + + /** + * 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 scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels); + WifiConfiguration[] savedConfigs = generateWifiConfigurations(ssids, security); + prepareConfigStore(savedConfigs); + + ScanResult chosenScanResult = scanDetails.get(0).getScanResult(); + WifiConfiguration unTrustedNetworkCandidate = mock(WifiConfiguration.class); + unTrustedNetworkCandidate.SSID = null; + unTrustedNetworkCandidate.networkId = WifiConfiguration.INVALID_NETWORK_ID; + + when(mWifiInfo.getNetworkId()).thenReturn(0); + when(mWifiInfo.getBSSID()).thenReturn(bssids[0]); + when(mWifiConfigManager.updateSavedNetworkWithNewScanDetail(scanDetails.get(0), + true)).thenReturn(null); + when(mWifiConfigManager + .wifiConfigurationFromScanResult(scanDetails.get(0).getScanResult())) + .thenReturn(unTrustedNetworkCandidate); + WifiConfiguration.NetworkSelectionStatus selectionStatus = + mock(WifiConfiguration.NetworkSelectionStatus.class); + when(unTrustedNetworkCandidate.getNetworkSelectionStatus()).thenReturn(selectionStatus); + when(selectionStatus.getCandidate()).thenReturn(chosenScanResult); + + WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, + true, scanDetails, false, true, false, false); + assertSame(unTrustedNetworkCandidate, candidate); + } + + /** + * 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 scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels); + + List nullCarrierConfiguredNetworks = new ArrayList(); + mWifiQualifiedNetworkSelector.setCarrierConfiguredNetworks(nullCarrierConfiguredNetworks); + + WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, + true, scanDetails, false, false, true, false); + assertEquals("Expect no network selection", null, candidate); + } } -- cgit v1.2.3 From ef31a2f1ce9d98e55641c8529aec14b9df0eed5b Mon Sep 17 00:00:00 2001 From: Roshan Pius Date: Wed, 7 Dec 2016 07:35:57 -0800 Subject: DO NOT MERGE: WifiConfigStore: Remove config validity check This was added as a part of https://partner-android-review.googlesource.com/#/c/216033/. Its not clear why this is needed since this validity method was intended to be used only for network configurations received from WifiManager API's. Bug:33399220 Test: Manual tests Change-Id: Ie5bbb3ea5d97e45950e5cb374af402c2b8b9716f --- service/java/com/android/server/wifi/WifiConfigStore.java | 7 ------- 1 file changed, 7 deletions(-) diff --git a/service/java/com/android/server/wifi/WifiConfigStore.java b/service/java/com/android/server/wifi/WifiConfigStore.java index cfed460cb..beb3373d2 100644 --- a/service/java/com/android/server/wifi/WifiConfigStore.java +++ b/service/java/com/android/server/wifi/WifiConfigStore.java @@ -421,13 +421,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); -- cgit v1.2.3 From cbd7a1b2a948c32a7b37057eb2888de3a6d300c0 Mon Sep 17 00:00:00 2001 From: Roshan Pius Date: Wed, 7 Dec 2016 07:35:57 -0800 Subject: DO NOT MERGE: WifiConfigStore: Remove config validity check This was added as a part of https://partner-android-review.googlesource.com/#/c/216033/. Its not clear why this is needed since this validity method was intended to be used only for network configurations received from WifiManager API's. Bug:33399220 Test: Manual tests Change-Id: Ie5bbb3ea5d97e45950e5cb374af402c2b8b9716f (cherry picked from commit ef31a2f1ce9d98e55641c8529aec14b9df0eed5b) --- service/java/com/android/server/wifi/WifiConfigStore.java | 7 ------- 1 file changed, 7 deletions(-) diff --git a/service/java/com/android/server/wifi/WifiConfigStore.java b/service/java/com/android/server/wifi/WifiConfigStore.java index cfed460cb..beb3373d2 100644 --- a/service/java/com/android/server/wifi/WifiConfigStore.java +++ b/service/java/com/android/server/wifi/WifiConfigStore.java @@ -421,13 +421,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); -- cgit v1.2.3 From 6126ecd658387dd5d3d3337d7e0119ffa1d75eba Mon Sep 17 00:00:00 2001 From: Robin Lee Date: Thu, 1 Dec 2016 20:44:57 +0000 Subject: Send CMD_DISCONNECT after removing app/user configs DO NOT MERGE Otherwise they might linger in wpa_supplicant longer than they were supposed to. This is already done by every other callsite for removing networks which might still be in use. Test: runtest -x tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java Bug: 32660379 Change-Id: I45b0bcc87129be02bcce940f07f7c48543207bf0 (cherry-picked from commit 1fe1065da82165183fa057ddbbd2e33bc5708c1b) --- .../com/android/server/wifi/WifiConfigManager.java | 55 ++++++++++++---------- .../com/android/server/wifi/WifiStateMachine.java | 17 ++++++- 2 files changed, 45 insertions(+), 27 deletions(-) diff --git a/service/java/com/android/server/wifi/WifiConfigManager.java b/service/java/com/android/server/wifi/WifiConfigManager.java index 407773ce9..8e990ce08 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; @@ -1231,52 +1232,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 removeNetworksForApp(ApplicationInfo app) { if (app == null || app.packageName == null) { - return false; + return Collections.emptySet(); } - boolean success = true; - - WifiConfiguration [] copiedConfigs = - mConfiguredNetworks.valuesForCurrentUser().toArray(new WifiConfiguration[0]); + Log.d(TAG, "Remove all networks for app " + app); + Set 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 removeNetworksForUser(int userId) { + Log.d(TAG, "Remove all networks for user " + userId); + Set 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; } /** diff --git a/service/java/com/android/server/wifi/WifiStateMachine.java b/service/java/com/android/server/wifi/WifiStateMachine.java index 0c7e987ee..cba03324e 100644 --- a/service/java/com/android/server/wifi/WifiStateMachine.java +++ b/service/java/com/android/server/wifi/WifiStateMachine.java @@ -5394,6 +5394,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss String bssid; String ssid; NetworkUpdateResult result; + Set removedNetworkIds; logStateAndMessage(message, this); switch (message.what) { @@ -5884,10 +5885,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 -- cgit v1.2.3 From de3de10eec061d39c5691bc1ba7556d22a6d2ecb Mon Sep 17 00:00:00 2001 From: Peter Qiu Date: Mon, 12 Dec 2016 13:56:48 -0800 Subject: configparse: do not delete passpoint configuration file It is the caller's responsibility for deleting configuration files. This avoids the ConfigBuilder from deleting arbitrary files (specified by URI) pass-in by the callers. Bug: 33178389 Test: Verify Passpoint Configuration installation works using Shamu Change-Id: I54803dc711ede98a1ec1259077522032c543dca1 --- service/java/com/android/server/wifi/configparse/ConfigBuilder.java | 6 ------ 1 file changed, 6 deletions(-) diff --git a/service/java/com/android/server/wifi/configparse/ConfigBuilder.java b/service/java/com/android/server/wifi/configparse/ConfigBuilder.java index e8e5e6a18..602b120cf 100644 --- a/service/java/com/android/server/wifi/configparse/ConfigBuilder.java +++ b/service/java/com/android/server/wifi/configparse/ConfigBuilder.java @@ -55,8 +55,6 @@ public class ConfigBuilder { byte[] b64 = Base64.decode(new String(data, StandardCharsets.ISO_8859_1), Base64.DEFAULT); Log.d(TAG, "Decoded: " + b64.length + " bytes."); - dropFile(Uri.parse(uriString), context); - MIMEContainer mimeContainer = new MIMEContainer(new LineNumberReader( new InputStreamReader(new ByteArrayInputStream(b64), StandardCharsets.ISO_8859_1)), @@ -80,10 +78,6 @@ public class ConfigBuilder { return parse(inner, context); } - private static void dropFile(Uri uri, Context context) { - context.getContentResolver().delete(uri, null, null); - } - private static WifiConfiguration parse(MIMEContainer root, Context context) throws IOException, GeneralSecurityException, SAXException { -- cgit v1.2.3 From db144d481502fafec1c9249bf29628d3a157298a Mon Sep 17 00:00:00 2001 From: Roshan Pius Date: Thu, 1 Dec 2016 15:40:22 -0800 Subject: DO NOT MERGE: WifiStateMachine: Add null check in CMD_AUTO_ROAM The crash reported by the user seems to have occured as the user was turning off/on wifi. The networkID selected by WifiConnectivityManager may be invalid by the time this message is processed by WifiStateMachine. So, add an explicit null check to abort the roam request. Bug: 33106930 Test: Will send for regression tests. Change-Id: I992a35e099d7af922da046107fa8e41052b5d2c1 --- service/java/com/android/server/wifi/WifiStateMachine.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/service/java/com/android/server/wifi/WifiStateMachine.java b/service/java/com/android/server/wifi/WifiStateMachine.java index 0c7e987ee..f325bed29 100644 --- a/service/java/com/android/server/wifi/WifiStateMachine.java +++ b/service/java/com/android/server/wifi/WifiStateMachine.java @@ -7270,6 +7270,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); -- cgit v1.2.3 From 3fb203353288aa65e768c5e52e9f17af231c415d Mon Sep 17 00:00:00 2001 From: Roshan Pius Date: Tue, 22 Nov 2016 14:16:38 -0800 Subject: DO NOT MERGE: WifiConfigManager: Ignore disabled networks in PNO list These networks are not connectable even if they're detected by PNO scans. So, ignore them in the PNO list. Bug: 33055484 Bug: 33606172 Test: Integration tests Change-Id: I3a33e0444639969195506321f630430520bbfcd5 (cherry picked from commit eb77c40b3d17153fe91ca1691aaf2ad16f3f7267) --- .../com/android/server/wifi/WifiConfigManager.java | 9 +++++++++ .../com/android/server/wifi/WifiConfigManagerTest.java | 18 ++++++++++++------ 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/service/java/com/android/server/wifi/WifiConfigManager.java b/service/java/com/android/server/wifi/WifiConfigManager.java index 4a27fef97..ed38839cc 100644 --- a/service/java/com/android/server/wifi/WifiConfigManager.java +++ b/service/java/com/android/server/wifi/WifiConfigManager.java @@ -94,6 +94,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; @@ -1123,6 +1124,14 @@ public class WifiConfigManager { ArrayList pnoList = new ArrayList<>(); ArrayList wifiConfigurations = new ArrayList<>(mConfiguredNetworks.valuesForCurrentUser()); + // Remove any permanently disabled networks. + Iterator 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. 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()); } -- cgit v1.2.3 From 054ddcd931164dcb6ce42a5a981748f89e6744e1 Mon Sep 17 00:00:00 2001 From: Ivan Podogov Date: Mon, 5 Dec 2016 16:47:34 +0000 Subject: In permission review mode, always request user's consent to toggle WiFi. Bug: 33155556 Change-Id: I41d9adb916c12327643d59fd05a50d097800e2ac --- .../com/android/server/wifi/WifiServiceImpl.java | 23 ++++++++++------------ 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/service/java/com/android/server/wifi/WifiServiceImpl.java b/service/java/com/android/server/wifi/WifiServiceImpl.java index d4ad0a7e0..2eb100217 100644 --- a/service/java/com/android/server/wifi/WifiServiceImpl.java +++ b/service/java/com/android/server/wifi/WifiServiceImpl.java @@ -587,14 +587,14 @@ public class WifiServiceImpl extends IWifiManager.Stub { if (enable) { if (wiFiEnabledState == WifiManager.WIFI_STATE_DISABLING || wiFiEnabledState == WifiManager.WIFI_STATE_DISABLED) { - if (startConsentUiIfNeeded(packageName, Binder.getCallingUid(), + if (startConsentUi(packageName, Binder.getCallingUid(), WifiManager.ACTION_REQUEST_ENABLE)) { return true; } } } else if (wiFiEnabledState == WifiManager.WIFI_STATE_ENABLING || wiFiEnabledState == WifiManager.WIFI_STATE_ENABLED) { - if (startConsentUiIfNeeded(packageName, Binder.getCallingUid(), + if (startConsentUi(packageName, Binder.getCallingUid(), WifiManager.ACTION_REQUEST_DISABLE)) { return true; } @@ -1418,7 +1418,7 @@ public class WifiServiceImpl extends IWifiManager.Stub { } }; - private boolean startConsentUiIfNeeded(String packageName, + private boolean startConsentUi(String packageName, int callingUid, String intentAction) throws RemoteException { if (UserHandle.getAppId(callingUid) == Process.SYSTEM_UID) { return false; @@ -1434,19 +1434,16 @@ public class WifiServiceImpl extends IWifiManager.Stub { + " not in uid " + callingUid); } - // Legacy apps in permission review mode trigger a user prompt - if (applicationInfo.targetSdkVersion < Build.VERSION_CODES.M) { - 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; - } + // 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()); } - return false; } /** -- cgit v1.2.3 From 14145984773a3ffb992723045dd6d829c6328b83 Mon Sep 17 00:00:00 2001 From: pkanwar Date: Sun, 18 Dec 2016 21:18:23 -0800 Subject: DO NOT MERGE: Allow Carriers to specify Wifi Networks. Added support for Carrier networks. Added functionality to read Carrier networks from Carrier Config. Bug: 31003437 Test: Added new tests, regression tests passed (frameworks-wifi). Change-Id: I9c3c03e2ab4a459898bec125f9dea8f96977e04f --- .../com/android/server/wifi/WifiConfigManager.java | 29 +++ .../server/wifi/WifiQualifiedNetworkSelector.java | 210 ++++++++++++--------- .../wifi/WifiQualifiedNetworkSelectorTest.java | 189 ++++++++++++++----- 3 files changed, 296 insertions(+), 132 deletions(-) diff --git a/service/java/com/android/server/wifi/WifiConfigManager.java b/service/java/com/android/server/wifi/WifiConfigManager.java index 8e990ce08..84c87d96b 100644 --- a/service/java/com/android/server/wifi/WifiConfigManager.java +++ b/service/java/com/android/server/wifi/WifiConfigManager.java @@ -3190,6 +3190,35 @@ public class WifiConfigManager { return !isLockdownFeatureEnabled && checkConfigOverridePermission(uid); } + /** + * 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) { + // Mark this config as ephemeral so it isn't persisted. + config.ephemeral = true; + 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. */ diff --git a/service/java/com/android/server/wifi/WifiQualifiedNetworkSelector.java b/service/java/com/android/server/wifi/WifiQualifiedNetworkSelector.java index a612cbba1..33ce3cef4 100644 --- a/service/java/com/android/server/wifi/WifiQualifiedNetworkSelector.java +++ b/service/java/com/android/server/wifi/WifiQualifiedNetworkSelector.java @@ -26,6 +26,7 @@ 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; @@ -78,6 +79,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 @@ -118,7 +123,7 @@ public class WifiQualifiedNetworkSelector { private Map mBssidBlacklist = new HashMap(); private List mCarrierConfiguredNetworks = new ArrayList(); - private CarrierConfigManager mCarrierConfigManager; + private Context mContext; /** * class save the blacklist status of a given BSSID @@ -136,6 +141,11 @@ public class WifiQualifiedNetworkSelector { } } + @VisibleForTesting + public void setCarrierConfiguredNetworks(List carrierConfiguredNetworks) { + mCarrierConfiguredNetworks = carrierConfiguredNetworks; + } + private void localLoge(String log) { mLocalLog.log(log); } @@ -176,6 +186,7 @@ public class WifiQualifiedNetworkSelector { mWifiConfigManager = configureStore; mWifiInfo = wifiInfo; mClock = clock; + mContext = context; mScoreManager = (NetworkScoreManager) context.getSystemService(Context.NETWORK_SCORE_SERVICE); if (mScoreManager != null) { @@ -202,52 +213,70 @@ public class WifiQualifiedNetworkSelector { mNoIntnetPenalty = (mWifiConfigManager.mThresholdSaturatedRssi24.get() + mRssiScoreOffset) * mRssiScoreSlope + mWifiConfigManager.mBandAward5Ghz.get() + mWifiConfigManager.mCurrentNetworkBoost.get() + mSameBssidAward + mSecurityAward; - mCarrierConfigManager = (CarrierConfigManager) - context.getSystemService(Context.CARRIER_CONFIG_SERVICE); - - final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - localLog("mBroadcastReceiver: onReceive " + intent.getAction()); - PersistableBundle b = mCarrierConfigManager.getConfig(); - String[] mWifiArray = - b.getStringArray(CarrierConfigManager.KEY_CARRIER_WIFI_STRING_ARRAY); - WifiConfiguration wifiConfig; - if (mWifiArray == null) { - return; - } - for (String config : mWifiArray) { - String[] wc = config.split("\\|"); - wifiConfig = new WifiConfiguration(); - try { - byte[] decodedBytes = Base64.decode(wc[0], Base64.DEFAULT); - String ssid = new String(decodedBytes); - wifiConfig.SSID = "\"" + ssid + "\""; - } catch (IllegalArgumentException ex) { - localLog("mBroadcaseReceiver: Could not decode base64 string"); - continue; - } - try { - int s = Integer.parseInt(wc[1]); - wifiConfig.allowedKeyManagement.set(s); - } catch (NumberFormatException e) { - localLog("mBroadcastReceiver: not an integer" + wc[1]); - } - mCarrierConfiguredNetworks.add(wifiConfig); - localLog("mBroadcastReceiver: onReceive networks:" + wifiConfig.SSID); - } - } - }; context.registerReceiver(mBroadcastReceiver, new IntentFilter( CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED)); } @VisibleForTesting - public void setCarrierConfiguredNetworks(List carrierConfiguredNetworks) { - mCarrierConfiguredNetworks = carrierConfiguredNetworks; + public List parseCarrierSuppliedWifiInfo(String[] wifiArray) { + List carrierConfiguredNetworks = new ArrayList(); + 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); + } + }; + void enableVerboseLogging(int verbose) { mDbg = verbose > 0 || FORCE_DEBUG; } @@ -638,13 +667,8 @@ public class WifiQualifiedNetworkSelector { } private boolean isCarrierNetwork(ScanResult scanResult) { - String ssid = "\"" + scanResult.SSID + "\""; - for (WifiConfiguration config : mCarrierConfiguredNetworks) { - if (config.SSID.equals(ssid)) { - return true; - } - } - return false; + return (getMatchingConfigForEAPNetworks(scanResult, + mCarrierConfiguredNetworks) != null ? true : false); } /** @@ -800,24 +824,25 @@ 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) { - localLog("Network is a ephemeral network..."); - if (isUntrustedConnectionsAllowed) { - Integer netScore = getNetworkScore(scanResult, false); - if (netScore == null) { - localLog("Checking the carrierScoreEvaluator for candidates..."); - // Evaluate the carrier network as a possible candidate. - if (!mCarrierConfiguredNetworks.isEmpty() && isCarrierNetwork(scanResult)) { - carrierScoreEvaluator.evalCarrierCandidate(scanResult, - getCarrierScore(scanResult, mCurrentConnectedNetwork, - (mCurrentBssid == null ? false : - mCurrentBssid.equals(scanResult.BSSID)))); + 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)); } - - } - else if (!mWifiConfigManager.wasEphemeralNetworkDeleted( - ScanDetailUtil.createQuotedSSID(scanResult.SSID))) { - externalScoreEvaluator.evalUntrustedCandidate(netScore, scanResult); - // scanDetail is for available ephemeral network + // Evaluate the carrier network as a possible candidate. + // todo need to add flag isCarrierConnectionsAllowed, config in settings. + } else if (!mCarrierConfiguredNetworks.isEmpty() && + isCarrierNetwork(scanResult)) { + 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)); } @@ -953,7 +978,8 @@ public class WifiQualifiedNetworkSelector { networkCandidate = getCarrierScoreCandidate(carrierScoreEvaluator); localLog("Carrier candidate::" + networkCandidate); if (networkCandidate != null) { - scanResultCandidate = networkCandidate.getNetworkSelectionStatus().getCandidate(); + scanResultCandidate = + mWifiConfigManager.getScanResultCandidate(networkCandidate); } } @@ -1046,25 +1072,22 @@ public class WifiQualifiedNetworkSelector { */ @Nullable WifiConfiguration getCarrierScoreCandidate(CarrierScoreEvaluator scoreEvaluator) { - WifiConfiguration networkCandidate = null; - ScanResult untrustedScanResultCandidate = scoreEvaluator.getScanResultCandidate(); - if (untrustedScanResultCandidate == null) { + ScanResult untrustedCarrierScanResult = scoreEvaluator.getScanResultCandidate(); + if (untrustedCarrierScanResult == null) { return null; } - WifiConfiguration unTrustedNetworkCandidate = - mWifiConfigManager.wifiConfigurationFromScanResult( - untrustedScanResultCandidate); - // Mark this config as ephemeral so it isn't persisted. - unTrustedNetworkCandidate.ephemeral = true; - mWifiConfigManager.saveNetwork(unTrustedNetworkCandidate, WifiConfiguration.UNKNOWN_UID); - localLog(String.format("new carrier candidate %s network ID:%d, ", - toScanId(untrustedScanResultCandidate), unTrustedNetworkCandidate.networkId)); - - unTrustedNetworkCandidate.getNetworkSelectionStatus() - .setCandidate(untrustedScanResultCandidate); - networkCandidate = unTrustedNetworkCandidate; - return networkCandidate; + + WifiConfiguration untrustedCandidateConfig = getMatchingConfigForEAPNetworks( + untrustedCarrierScanResult, mCarrierConfiguredNetworks); + + if (untrustedCandidateConfig == null) { + return null; + } + + mWifiConfigManager.saveNetworkAndSetCandidate( + untrustedCandidateConfig, untrustedCarrierScanResult); + return untrustedCandidateConfig; } /** @@ -1217,7 +1240,6 @@ public class WifiQualifiedNetworkSelector { static class CarrierScoreEvaluator { // Always set to the best known candidate private int mHighScore = WifiNetworkScoreCache.INVALID_NETWORK_SCORE; - private WifiConfiguration mSavedConfig; private ScanResult mScanResultCandidate; private final LocalLog mLocalLog; private final boolean mDbg; @@ -1245,14 +1267,32 @@ public class WifiQualifiedNetworkSelector { return mScanResultCandidate; } - WifiConfiguration getSavedConfig() { - return mSavedConfig; - } - private void localLog(String log) { if (mDbg) { mLocalLog.log(log); } } } + + private WifiConfiguration getMatchingConfigForEAPNetworks( + ScanResult scanResult, List 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/tests/wifitests/src/com/android/server/wifi/WifiQualifiedNetworkSelectorTest.java b/tests/wifitests/src/com/android/server/wifi/WifiQualifiedNetworkSelectorTest.java index 957e8c24c..3c2d31fdf 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,8 +44,10 @@ 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; @@ -82,19 +87,27 @@ public class WifiQualifiedNetworkSelectorTest { 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); } @@ -2423,29 +2436,21 @@ public class WifiQualifiedNetworkSelectorTest { int[] security = {SECURITY_PSK, SECURITY_PSK}; List scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels); - - WifiConfiguration[] savedConfigs = generateWifiConfigurations(ssids, security); - prepareConfigStore(savedConfigs); - ScanResult chosenScanResult = scanDetails.get(1).getScanResult(); - WifiConfiguration unTrustedNetworkCandidate = mock(WifiConfiguration.class); - unTrustedNetworkCandidate.SSID = null; - unTrustedNetworkCandidate.networkId = WifiConfiguration.INVALID_NETWORK_ID; - when(mWifiConfigManager.updateSavedNetworkWithNewScanDetail(scanDetails.get(1), - false)).thenReturn(null); - when(mWifiConfigManager - .wifiConfigurationFromScanResult(scanDetails.get(1).getScanResult())) - .thenReturn(unTrustedNetworkCandidate); - WifiConfiguration.NetworkSelectionStatus selectionStatus = - mock(WifiConfiguration.NetworkSelectionStatus.class); - when(unTrustedNetworkCandidate.getNetworkSelectionStatus()).thenReturn(selectionStatus); - when(selectionStatus.getCandidate()).thenReturn(chosenScanResult); + 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( + mCarrierConfiguredNetworks.get(1))).thenReturn(chosenScanResult); WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, - true, scanDetails, false, false, true, false); - assertSame(unTrustedNetworkCandidate, candidate); + false, scanDetails, false, false, true, false); + + assertTrue(candidate.SSID.contains(chosenScanResult.SSID)); } + /** * Case #50 Choose 5G over 2G. */ @@ -2460,22 +2465,16 @@ public class WifiQualifiedNetworkSelectorTest { List scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels); ScanResult chosenScanResult = scanDetails.get(1).getScanResult(); - WifiConfiguration unTrustedNetworkCandidate = mock(WifiConfiguration.class); - unTrustedNetworkCandidate.SSID = null; - unTrustedNetworkCandidate.networkId = WifiConfiguration.INVALID_NETWORK_ID; - when(mWifiConfigManager.updateSavedNetworkWithNewScanDetail(scanDetails.get(1), - false)).thenReturn(null); - when(mWifiConfigManager - .wifiConfigurationFromScanResult(scanDetails.get(1).getScanResult())) - .thenReturn(unTrustedNetworkCandidate); - WifiConfiguration.NetworkSelectionStatus selectionStatus = - mock(WifiConfiguration.NetworkSelectionStatus.class); - when(unTrustedNetworkCandidate.getNetworkSelectionStatus()).thenReturn(selectionStatus); - when(selectionStatus.getCandidate()).thenReturn(chosenScanResult); + 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( + mCarrierConfiguredNetworks.get(1))).thenReturn(chosenScanResult); WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, - true, scanDetails, false, false, true, false); - assertSame(unTrustedNetworkCandidate, candidate); + false, scanDetails, false, false, true, false); + assertTrue(candidate.SSID.contains(chosenScanResult.SSID)); } /** @@ -2496,25 +2495,18 @@ public class WifiQualifiedNetworkSelectorTest { prepareConfigStore(savedConfigs); ScanResult chosenScanResult = scanDetails.get(0).getScanResult(); - WifiConfiguration unTrustedNetworkCandidate = mock(WifiConfiguration.class); - unTrustedNetworkCandidate.SSID = null; - unTrustedNetworkCandidate.networkId = WifiConfiguration.INVALID_NETWORK_ID; - + 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( + mCarrierConfiguredNetworks.get(0))).thenReturn(chosenScanResult); when(mWifiInfo.getNetworkId()).thenReturn(0); when(mWifiInfo.getBSSID()).thenReturn(bssids[0]); - when(mWifiConfigManager.updateSavedNetworkWithNewScanDetail(scanDetails.get(0), - true)).thenReturn(null); - when(mWifiConfigManager - .wifiConfigurationFromScanResult(scanDetails.get(0).getScanResult())) - .thenReturn(unTrustedNetworkCandidate); - WifiConfiguration.NetworkSelectionStatus selectionStatus = - mock(WifiConfiguration.NetworkSelectionStatus.class); - when(unTrustedNetworkCandidate.getNetworkSelectionStatus()).thenReturn(selectionStatus); - when(selectionStatus.getCandidate()).thenReturn(chosenScanResult); WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, - true, scanDetails, false, true, false, false); - assertSame(unTrustedNetworkCandidate, candidate); + false, scanDetails, false, true, false, false); + assertTrue(candidate.SSID.contains(chosenScanResult.SSID)); } /** @@ -2539,4 +2531,107 @@ public class WifiQualifiedNetworkSelectorTest { 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 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 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 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 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 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 configList = + mWifiQualifiedNetworkSelector.parseCarrierSuppliedWifiInfo(wifiArray); + assertEquals("Expect right network", configList.get(0).SSID, "\"Wifi Extra\""); + assertEquals("Expect right network", configList.get(2).SSID, "\"Google-Guest\""); + } } -- cgit v1.2.3 From 843ee4e8b0b3332e6f7403fe3d8346cbb991f9b8 Mon Sep 17 00:00:00 2001 From: pkanwar Date: Tue, 20 Dec 2016 14:24:27 -0800 Subject: DO NOT MERGE: Fix bug in WifiStateMachine for EAP-SIM. WifiStateMachine was not looking for the right keys. Add condition to look for WPA_EAP, in addition to IEEE8021X. Bug:31003437 Change-Id: Icc72644de77927a23c2ad5a4fbea640ba392e9ae --- service/java/com/android/server/wifi/WifiStateMachine.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/service/java/com/android/server/wifi/WifiStateMachine.java b/service/java/com/android/server/wifi/WifiStateMachine.java index 0bddb6c8f..45e039e80 100644 --- a/service/java/com/android/server/wifi/WifiStateMachine.java +++ b/service/java/com/android/server/wifi/WifiStateMachine.java @@ -5689,8 +5689,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) { @@ -5840,7 +5842,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); -- cgit v1.2.3 From 68b8c4c1ccdd9fec67a96a2a4e8df284ce15bb7e Mon Sep 17 00:00:00 2001 From: pkanwar Date: Tue, 20 Dec 2016 15:27:26 -0800 Subject: DO NOT MERGE: Add API to indicate carrier networks. Bug: 31003437 Change-Id: I4a5374b59d08fd8ec8ffbff007764e3f277f79df --- .../com/android/server/wifi/WifiConfigManager.java | 22 +++++++++++++++ .../server/wifi/WifiQualifiedNetworkSelector.java | 3 +++ .../com/android/server/wifi/WifiServiceImpl.java | 15 +++++++++++ .../com/android/server/wifi/WifiStateMachine.java | 31 ++++++++++++++++++++++ 4 files changed, 71 insertions(+) diff --git a/service/java/com/android/server/wifi/WifiConfigManager.java b/service/java/com/android/server/wifi/WifiConfigManager.java index 84c87d96b..774d75ec7 100644 --- a/service/java/com/android/server/wifi/WifiConfigManager.java +++ b/service/java/com/android/server/wifi/WifiConfigManager.java @@ -259,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; @@ -487,6 +493,22 @@ public class WifiConfigManager { return getSavedNetworks(null); } + /** + * 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. diff --git a/service/java/com/android/server/wifi/WifiQualifiedNetworkSelector.java b/service/java/com/android/server/wifi/WifiQualifiedNetworkSelector.java index 33ce3cef4..4f63a5bbd 100644 --- a/service/java/com/android/server/wifi/WifiQualifiedNetworkSelector.java +++ b/service/java/com/android/server/wifi/WifiQualifiedNetworkSelector.java @@ -274,6 +274,9 @@ public class WifiQualifiedNetworkSelector { return; } mCarrierConfiguredNetworks = parseCarrierSuppliedWifiInfo(wifiArray); + boolean hasCarrierNetworks = (mCarrierConfiguredNetworks == null || + mCarrierConfiguredNetworks.size() == 0) ? false : true; + mWifiConfigManager.setHasCarrierNetworks(hasCarrierNetworks); } }; diff --git a/service/java/com/android/server/wifi/WifiServiceImpl.java b/service/java/com/android/server/wifi/WifiServiceImpl.java index d4ad0a7e0..32491e7e8 100644 --- a/service/java/com/android/server/wifi/WifiServiceImpl.java +++ b/service/java/com/android/server/wifi/WifiServiceImpl.java @@ -833,6 +833,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 diff --git a/service/java/com/android/server/wifi/WifiStateMachine.java b/service/java/com/android/server/wifi/WifiStateMachine.java index 0bddb6c8f..6a5d606fb 100644 --- a/service/java/com/android/server/wifi/WifiStateMachine.java +++ b/service/java/com/android/server/wifi/WifiStateMachine.java @@ -626,6 +626,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; @@ -2019,6 +2021,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 = (boolean) resultMsg.obj; + resultMsg.recycle(); + return result; + } + public List syncGetPrivilegedConfiguredNetwork(AsyncChannel channel) { Message resultMsg = channel.sendMessageSynchronously( CMD_GET_PRIVILEGED_CONFIGURED_NETWORKS); @@ -2787,6 +2804,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)); @@ -4079,6 +4103,9 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss case CMD_GET_CONFIGURED_NETWORKS: replyToMessage(message, message.what, (List) 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) null); break; @@ -5676,6 +5703,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; -- cgit v1.2.3 From 392506310ec5bf00d9908bebef4ed0a90c0150e5 Mon Sep 17 00:00:00 2001 From: Rebecca Silberstein Date: Wed, 4 Jan 2017 23:00:22 -0800 Subject: [DO NOT MERGE] WifiStateMachine: prevent erroneous wifi toggle The icon for wifi toggles on/off quickly when transitioning between states if location scans are enabled. This is due to two errors: 1 - WifiStateMachine sends the wifi enabled broadcast before wifi has entered client mode. 2 - WifiStateMachine assumes it is entering client mode if it has not been told otherwise. This CL works around the assumptions in WifiStateMachine and avoids sending the wifi enabled broadcast when it should be going in to scan mode and not client mode. Bug: 28336982 Test: verified state transitions manually Test: runtest frameworks-wifi Change-Id: I5e34ee4f0ef90668ecc97f5d6d726444fd08ffb3 --- .../com/android/server/wifi/WifiController.java | 4 +++- .../com/android/server/wifi/WifiStateMachine.java | 22 +++++++++++++++------- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/service/java/com/android/server/wifi/WifiController.java b/service/java/com/android/server/wifi/WifiController.java index bfbf44906..67a7a423e 100644 --- a/service/java/com/android/server/wifi/WifiController.java +++ b/service/java/com/android/server/wifi/WifiController.java @@ -581,8 +581,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/WifiStateMachine.java b/service/java/com/android/server/wifi/WifiStateMachine.java index 9cc26b108..73780b8b7 100644 --- a/service/java/com/android/server/wifi/WifiStateMachine.java +++ b/service/java/com/android/server/wifi/WifiStateMachine.java @@ -4459,7 +4459,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 */ @@ -4517,10 +4517,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); @@ -5392,18 +5388,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); -- cgit v1.2.3 From d84ac6ab3451b32aaedc2b497a57c700088d6f6d Mon Sep 17 00:00:00 2001 From: Paul Stewart Date: Thu, 5 Jan 2017 12:26:44 -0800 Subject: DO NOT MERGE: Fix null dereference in carrier networks WifiStateMachine can respond to CMD_HAS_CARRIER_CONFIGURED_NETWORKS with a null object if it is not in a state to handle this. Therefore syncHasCarrierConfiguredNetworks must check for null before attempting to cast the result object back to boolean. Bug: 34050164 Test: Compile Change-Id: I21b80ef3989ca2d6a09784f9c9a44f4af19b5850 --- service/java/com/android/server/wifi/WifiStateMachine.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service/java/com/android/server/wifi/WifiStateMachine.java b/service/java/com/android/server/wifi/WifiStateMachine.java index 9cc26b108..d5e9d02ba 100644 --- a/service/java/com/android/server/wifi/WifiStateMachine.java +++ b/service/java/com/android/server/wifi/WifiStateMachine.java @@ -2031,7 +2031,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss int uuid, AsyncChannel channel) { Message resultMsg = channel.sendMessageSynchronously( CMD_HAS_CARRIER_CONFIGURED_NETWORKS, uuid); - boolean result = (boolean) resultMsg.obj; + boolean result = resultMsg.obj != null && (boolean) resultMsg.obj; resultMsg.recycle(); return result; } -- cgit v1.2.3 From 82c1e5cda881e7c9c6074f1769e002945e508d65 Mon Sep 17 00:00:00 2001 From: Roshan Pius Date: Tue, 10 Jan 2017 08:21:35 -0800 Subject: DO NOT MERGE: WifiConfigStore: Strip out FT flags in WifiConfiguration The FT flags are added dynamically to wpa_supplicant. These are not exposed in the public API's and hence should not be returned in the configs retrieved by apps. So, strip out the FT flags when reading network configuration from wpa_supplicant. Bug: 34095472 Test: Will send for regression testing. Change-Id: I0d49fb3c98e49207f2faf30d54493f1147924e3b --- service/java/com/android/server/wifi/WifiConfigStore.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/service/java/com/android/server/wifi/WifiConfigStore.java b/service/java/com/android/server/wifi/WifiConfigStore.java index beb3373d2..e4aef24c6 100644 --- a/service/java/com/android/server/wifi/WifiConfigStore.java +++ b/service/java/com/android/server/wifi/WifiConfigStore.java @@ -341,6 +341,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); @@ -605,6 +607,13 @@ public class WifiConfigStore { 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. * -- cgit v1.2.3 From ab9a573e3138911e08d037a6996297be30be20bc Mon Sep 17 00:00:00 2001 From: pkanwar Date: Mon, 26 Dec 2016 09:57:50 -0800 Subject: DO NOT MERGE ANYWHERE: Connect to Carrier networks if enabled in Settings. After this change the WifiQualifiedSelector will only connect to Carrier networks if enabled in the Settings. Provided a method in WifiConfigManager that will be used to decide if we try connecing to the Carrier network. BUG: 30760683 Change-Id: I5c6841f784bd82f3811837331d3dd0c795da7688 --- .../com/android/server/wifi/WifiConfigManager.java | 9 +++++++ .../server/wifi/WifiQualifiedNetworkSelector.java | 6 ++++- .../wifi/WifiQualifiedNetworkSelectorTest.java | 31 ++++++++++++++++++++++ 3 files changed, 45 insertions(+), 1 deletion(-) diff --git a/service/java/com/android/server/wifi/WifiConfigManager.java b/service/java/com/android/server/wifi/WifiConfigManager.java index 774d75ec7..32a4113e9 100644 --- a/service/java/com/android/server/wifi/WifiConfigManager.java +++ b/service/java/com/android/server/wifi/WifiConfigManager.java @@ -3318,4 +3318,13 @@ public class WifiConfigManager { 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/WifiQualifiedNetworkSelector.java b/service/java/com/android/server/wifi/WifiQualifiedNetworkSelector.java index 4f63a5bbd..a135e0b76 100644 --- a/service/java/com/android/server/wifi/WifiQualifiedNetworkSelector.java +++ b/service/java/com/android/server/wifi/WifiQualifiedNetworkSelector.java @@ -748,6 +748,9 @@ public class WifiQualifiedNetworkSelector { ArrayList unscoredNetworks = new ArrayList(); boolean scanResultsHaveCurrentBssid = false; + localLog("isCarrierNetworkEnabledByUser: " + + mWifiConfigManager.getIsCarrierNetworkEnabledByUser()); + //iterate all scan results and find the best candidate with the highest score for (ScanDetail scanDetail : mScanDetails) { ScanResult scanResult = scanDetail.getScanResult(); @@ -840,7 +843,8 @@ public class WifiQualifiedNetworkSelector { // Evaluate the carrier network as a possible candidate. // todo need to add flag isCarrierConnectionsAllowed, config in settings. } else if (!mCarrierConfiguredNetworks.isEmpty() && - isCarrierNetwork(scanResult)) { + isCarrierNetwork(scanResult) && + mWifiConfigManager.getIsCarrierNetworkEnabledByUser()) { localLog("Checking the carrierScoreEvaluator for candidates..."); carrierScoreEvaluator.evalCarrierCandidate(scanResult, getCarrierScore(scanResult, mCurrentConnectedNetwork, diff --git a/tests/wifitests/src/com/android/server/wifi/WifiQualifiedNetworkSelectorTest.java b/tests/wifitests/src/com/android/server/wifi/WifiQualifiedNetworkSelectorTest.java index 3c2d31fdf..86f72984a 100644 --- a/tests/wifitests/src/com/android/server/wifi/WifiQualifiedNetworkSelectorTest.java +++ b/tests/wifitests/src/com/android/server/wifi/WifiQualifiedNetworkSelectorTest.java @@ -2443,6 +2443,7 @@ public class WifiQualifiedNetworkSelectorTest { any(ScanResult.class))).then(AdditionalAnswers.returnsFirstArg()); when(mWifiConfigManager.getScanResultCandidate( mCarrierConfiguredNetworks.get(1))).thenReturn(chosenScanResult); + when(mWifiConfigManager.getIsCarrierNetworkEnabledByUser()).thenReturn(true); WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, false, scanDetails, false, false, true, false); @@ -2471,6 +2472,7 @@ public class WifiQualifiedNetworkSelectorTest { any(ScanResult.class))).then(AdditionalAnswers.returnsFirstArg()); when(mWifiConfigManager.getScanResultCandidate( mCarrierConfiguredNetworks.get(1))).thenReturn(chosenScanResult); + when(mWifiConfigManager.getIsCarrierNetworkEnabledByUser()).thenReturn(true); WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, false, scanDetails, false, false, true, false); @@ -2503,6 +2505,7 @@ public class WifiQualifiedNetworkSelectorTest { mCarrierConfiguredNetworks.get(0))).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); @@ -2526,6 +2529,7 @@ public class WifiQualifiedNetworkSelectorTest { List nullCarrierConfiguredNetworks = new ArrayList(); mWifiQualifiedNetworkSelector.setCarrierConfiguredNetworks(nullCarrierConfiguredNetworks); + when(mWifiConfigManager.getIsCarrierNetworkEnabledByUser()).thenReturn(true); WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, true, scanDetails, false, false, true, false); @@ -2634,4 +2638,31 @@ public class WifiQualifiedNetworkSelectorTest { 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 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( + mCarrierConfiguredNetworks.get(1))).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); + } } -- cgit v1.2.3 From 936d25cfe7a682337e9a9c39412650c9ae3ff312 Mon Sep 17 00:00:00 2001 From: pkanwar Date: Thu, 12 Jan 2017 19:07:41 -0800 Subject: DO NOT MERGE: Fix to maintain the Carrier Network connection. Added isCarrierNetwork param in WifiConfiguration, which is then used in WifiStateMachine. After this change, the connection to Carrier Network should be maintained. BUG: 30760683 Change-Id: Ie6df849182aafc018e336631c502ff7749bfdc35 --- service/java/com/android/server/wifi/WifiConfigManager.java | 3 +-- .../java/com/android/server/wifi/WifiQualifiedNetworkSelector.java | 5 +++++ service/java/com/android/server/wifi/WifiStateMachine.java | 4 +++- .../com/android/server/wifi/WifiQualifiedNetworkSelectorTest.java | 3 ++- 4 files changed, 11 insertions(+), 4 deletions(-) diff --git a/service/java/com/android/server/wifi/WifiConfigManager.java b/service/java/com/android/server/wifi/WifiConfigManager.java index 32a4113e9..5eff02ee6 100644 --- a/service/java/com/android/server/wifi/WifiConfigManager.java +++ b/service/java/com/android/server/wifi/WifiConfigManager.java @@ -2032,6 +2032,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) @@ -3220,8 +3221,6 @@ public class WifiConfigManager { */ public WifiConfiguration saveNetworkAndSetCandidate(WifiConfiguration config, ScanResult scanResult) { - // Mark this config as ephemeral so it isn't persisted. - config.ephemeral = true; saveNetwork(config, WifiConfiguration.UNKNOWN_UID); config.getNetworkSelectionStatus().setCandidate(scanResult); diff --git a/service/java/com/android/server/wifi/WifiQualifiedNetworkSelector.java b/service/java/com/android/server/wifi/WifiQualifiedNetworkSelector.java index a135e0b76..3cc471ac3 100644 --- a/service/java/com/android/server/wifi/WifiQualifiedNetworkSelector.java +++ b/service/java/com/android/server/wifi/WifiQualifiedNetworkSelector.java @@ -1092,6 +1092,11 @@ public class WifiQualifiedNetworkSelector { return null; } + // Mark this config as ephemeral so it isn't persisted. + untrustedCandidateConfig.ephemeral = true; + // Mark this config as a Carrier Network. + untrustedCandidateConfig.isCarrierNetwork = true; + mWifiConfigManager.saveNetworkAndSetCandidate( untrustedCandidateConfig, untrustedCarrierScanResult); return untrustedCandidateConfig; diff --git a/service/java/com/android/server/wifi/WifiStateMachine.java b/service/java/com/android/server/wifi/WifiStateMachine.java index 4b2496213..89aabcf3e 100644 --- a/service/java/com/android/server/wifi/WifiStateMachine.java +++ b/service/java/com/android/server/wifi/WifiStateMachine.java @@ -6349,7 +6349,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 { diff --git a/tests/wifitests/src/com/android/server/wifi/WifiQualifiedNetworkSelectorTest.java b/tests/wifitests/src/com/android/server/wifi/WifiQualifiedNetworkSelectorTest.java index 86f72984a..9f29a55cc 100644 --- a/tests/wifitests/src/com/android/server/wifi/WifiQualifiedNetworkSelectorTest.java +++ b/tests/wifitests/src/com/android/server/wifi/WifiQualifiedNetworkSelectorTest.java @@ -2447,7 +2447,8 @@ public class WifiQualifiedNetworkSelectorTest { WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, false, scanDetails, false, false, true, false); - + assertTrue(candidate.isCarrierNetwork); + assertTrue(candidate.ephemeral); assertTrue(candidate.SSID.contains(chosenScanResult.SSID)); } -- cgit v1.2.3 From 3112931546f051366df4fd15bd3236f11875a915 Mon Sep 17 00:00:00 2001 From: pkanwar Date: Sun, 15 Jan 2017 09:39:35 -0800 Subject: DO NOT MERGE: Fix to enable reconnecting to a Carrier network. We now generate a new Config for each connection attempt. BUG: 30760683 Change-Id: I88393ecc2964e299e80f6f2802dd85a142e1f473 --- .../server/wifi/WifiQualifiedNetworkSelector.java | 11 +++--- .../wifi/WifiQualifiedNetworkSelectorTest.java | 42 +++++++++++++++------- 2 files changed, 36 insertions(+), 17 deletions(-) diff --git a/service/java/com/android/server/wifi/WifiQualifiedNetworkSelector.java b/service/java/com/android/server/wifi/WifiQualifiedNetworkSelector.java index 3cc471ac3..1e7560346 100644 --- a/service/java/com/android/server/wifi/WifiQualifiedNetworkSelector.java +++ b/service/java/com/android/server/wifi/WifiQualifiedNetworkSelector.java @@ -1092,14 +1092,17 @@ public class WifiQualifiedNetworkSelector { return null; } + WifiConfiguration newUntrustedCandidateConfig = + new WifiConfiguration(untrustedCandidateConfig); + // Mark this config as ephemeral so it isn't persisted. - untrustedCandidateConfig.ephemeral = true; + newUntrustedCandidateConfig.ephemeral = true; // Mark this config as a Carrier Network. - untrustedCandidateConfig.isCarrierNetwork = true; + newUntrustedCandidateConfig.isCarrierNetwork = true; mWifiConfigManager.saveNetworkAndSetCandidate( - untrustedCandidateConfig, untrustedCarrierScanResult); - return untrustedCandidateConfig; + newUntrustedCandidateConfig, untrustedCarrierScanResult); + return newUntrustedCandidateConfig; } /** diff --git a/tests/wifitests/src/com/android/server/wifi/WifiQualifiedNetworkSelectorTest.java b/tests/wifitests/src/com/android/server/wifi/WifiQualifiedNetworkSelectorTest.java index 9f29a55cc..c97618d6a 100644 --- a/tests/wifitests/src/com/android/server/wifi/WifiQualifiedNetworkSelectorTest.java +++ b/tests/wifitests/src/com/android/server/wifi/WifiQualifiedNetworkSelectorTest.java @@ -2421,6 +2421,23 @@ public class WifiQualifiedNetworkSelectorTest { 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. @@ -2441,15 +2458,13 @@ public class WifiQualifiedNetworkSelectorTest { any(Boolean.class))).thenReturn(null); when(mWifiConfigManager.saveNetworkAndSetCandidate(any(WifiConfiguration.class), any(ScanResult.class))).then(AdditionalAnswers.returnsFirstArg()); - when(mWifiConfigManager.getScanResultCandidate( - mCarrierConfiguredNetworks.get(1))).thenReturn(chosenScanResult); + 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(candidate.isCarrierNetwork); - assertTrue(candidate.ephemeral); - assertTrue(candidate.SSID.contains(chosenScanResult.SSID)); + assertTrue(compareCarrierConfigs(candidate, mCarrierConfiguredNetworks.get(1))); } @@ -2471,13 +2486,13 @@ public class WifiQualifiedNetworkSelectorTest { any(Boolean.class))).thenReturn(null); when(mWifiConfigManager.saveNetworkAndSetCandidate(any(WifiConfiguration.class), any(ScanResult.class))).then(AdditionalAnswers.returnsFirstArg()); - when(mWifiConfigManager.getScanResultCandidate( - mCarrierConfiguredNetworks.get(1))).thenReturn(chosenScanResult); + 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(candidate.SSID.contains(chosenScanResult.SSID)); + assertTrue(compareCarrierConfigs(candidate, mCarrierConfiguredNetworks.get(1))); } /** @@ -2502,15 +2517,16 @@ public class WifiQualifiedNetworkSelectorTest { any(Boolean.class))).thenReturn(null); when(mWifiConfigManager.saveNetworkAndSetCandidate(any(WifiConfiguration.class), any(ScanResult.class))).then(AdditionalAnswers.returnsFirstArg()); - when(mWifiConfigManager.getScanResultCandidate( - mCarrierConfiguredNetworks.get(0))).thenReturn(chosenScanResult); + 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(candidate.SSID.contains(chosenScanResult.SSID)); + + assertTrue(compareCarrierConfigs(candidate, mCarrierConfiguredNetworks.get(0))); } /** @@ -2658,8 +2674,8 @@ public class WifiQualifiedNetworkSelectorTest { any(Boolean.class))).thenReturn(null); when(mWifiConfigManager.saveNetworkAndSetCandidate(any(WifiConfiguration.class), any(ScanResult.class))).then(AdditionalAnswers.returnsFirstArg()); - when(mWifiConfigManager.getScanResultCandidate( - mCarrierConfiguredNetworks.get(1))).thenReturn(chosenScanResult); + when(mWifiConfigManager.getScanResultCandidate(any(WifiConfiguration.class))) + .thenReturn(chosenScanResult); when(mWifiConfigManager.getIsCarrierNetworkEnabledByUser()).thenReturn(false); WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false, -- cgit v1.2.3