diff options
9 files changed, 129 insertions, 52 deletions
diff --git a/service/java/com/android/server/wifi/ConfigurationMap.java b/service/java/com/android/server/wifi/ConfigurationMap.java index 376e8e606..a94ff0dff 100644 --- a/service/java/com/android/server/wifi/ConfigurationMap.java +++ b/service/java/com/android/server/wifi/ConfigurationMap.java @@ -8,9 +8,11 @@ import android.os.UserManager; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Set; public class ConfigurationMap { private final Map<Integer, WifiConfiguration> mPerID = new HashMap<>(); @@ -18,6 +20,11 @@ public class ConfigurationMap { private final Map<Integer, WifiConfiguration> mPerIDForCurrentUser = new HashMap<>(); private final Map<String, WifiConfiguration> mPerFQDNForCurrentUser = new HashMap<>(); + /** + * List of all hidden networks in the current user's configuration. + * Use this list as a param for directed scanning . + */ + private final Set<Integer> mHiddenNetworkIdsForCurrentUser = new HashSet<>(); private final UserManager mUserManager; @@ -37,6 +44,9 @@ public class ConfigurationMap { if (config.FQDN != null && config.FQDN.length() > 0) { mPerFQDNForCurrentUser.put(config.FQDN, config); } + if (config.hiddenSSID) { + mHiddenNetworkIdsForCurrentUser.add(config.networkId); + } } return current; } @@ -57,6 +67,7 @@ public class ConfigurationMap { break; } } + mHiddenNetworkIdsForCurrentUser.remove(netID); return config; } @@ -65,6 +76,7 @@ public class ConfigurationMap { mPerConfigKey.clear(); mPerIDForCurrentUser.clear(); mPerFQDNForCurrentUser.clear(); + mHiddenNetworkIdsForCurrentUser.clear(); } /** @@ -78,6 +90,7 @@ public class ConfigurationMap { public List<WifiConfiguration> handleUserSwitch(int userId) { mPerIDForCurrentUser.clear(); mPerFQDNForCurrentUser.clear(); + mHiddenNetworkIdsForCurrentUser.clear(); final List<UserInfo> previousUserProfiles = mUserManager.getProfiles(mCurrentUserId); mCurrentUserId = userId; @@ -91,6 +104,9 @@ public class ConfigurationMap { if (config.FQDN != null && config.FQDN.length() > 0) { mPerFQDNForCurrentUser.put(config.FQDN, config); } + if (config.hiddenSSID) { + mHiddenNetworkIdsForCurrentUser.add(config.networkId); + } } else if (WifiConfigurationUtil.isVisibleToAnyProfile(config, previousUserProfiles)) { hiddenConfigurations.add(config); } @@ -162,4 +178,8 @@ public class ConfigurationMap { public Collection<WifiConfiguration> valuesForCurrentUser() { return mPerIDForCurrentUser.values(); } + + public Set<Integer> getHiddenNetworkIdsForCurrentUser() { + return mHiddenNetworkIdsForCurrentUser; + } } diff --git a/service/java/com/android/server/wifi/HalWifiScannerImpl.java b/service/java/com/android/server/wifi/HalWifiScannerImpl.java index 90a54f09f..c7fbbd6c5 100644 --- a/service/java/com/android/server/wifi/HalWifiScannerImpl.java +++ b/service/java/com/android/server/wifi/HalWifiScannerImpl.java @@ -113,7 +113,8 @@ public class HalWifiScannerImpl extends WifiScannerImpl implements Handler.Callb mSingleScanEventHandler = eventHandler; Set<Integer> freqs = scanChannels.getSupplicantScanFreqs(); - if (!mWifiNative.scan(freqs)) { + // TODO(rpius): Need to plumb in the hiddessid network list via Scanner. + if (!mWifiNative.scan(freqs, null)) { Log.e(TAG, "Failed to start scan, freqs=" + freqs); // indicate scan failure async mEventHandler.post(new Runnable() { diff --git a/service/java/com/android/server/wifi/SupplicantWifiScannerImpl.java b/service/java/com/android/server/wifi/SupplicantWifiScannerImpl.java index 90413ff85..35209f578 100644 --- a/service/java/com/android/server/wifi/SupplicantWifiScannerImpl.java +++ b/service/java/com/android/server/wifi/SupplicantWifiScannerImpl.java @@ -345,7 +345,8 @@ public class SupplicantWifiScannerImpl extends WifiScannerImpl implements Handle if (!allFreqs.isEmpty()) { Set<Integer> freqs = allFreqs.getSupplicantScanFreqs(); - boolean success = mWifiNative.scan(freqs); + // TODO(rpius): Need to plumb in the hidden ssid network list via Scanner. + boolean success = mWifiNative.scan(freqs, null); if (success) { // TODO handle scan timeout Log.d(TAG, "Starting wifi scan for freqs=" + freqs diff --git a/service/java/com/android/server/wifi/WifiConfigManager.java b/service/java/com/android/server/wifi/WifiConfigManager.java index f3863cd3b..4f3109dd6 100644 --- a/service/java/com/android/server/wifi/WifiConfigManager.java +++ b/service/java/com/android/server/wifi/WifiConfigManager.java @@ -94,9 +94,9 @@ import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.ConcurrentHashMap; import java.util.regex.Pattern; import java.util.zip.CRC32; import java.util.zip.Checksum; @@ -631,6 +631,14 @@ public class WifiConfigManager { } /** + * Fetch the list of networkId's which are hidden in current user's configuration. + * @return List of networkIds + */ + public Set<Integer> getHiddenConfiguredNetworkIds() { + return mConfiguredNetworks.getHiddenNetworkIdsForCurrentUser(); + } + + /** * Find matching network for this scanResult */ WifiConfiguration getMatchingConfig(ScanResult scanResult) { diff --git a/service/java/com/android/server/wifi/WifiNative.java b/service/java/com/android/server/wifi/WifiNative.java index a19bee32c..6b9683150 100644 --- a/service/java/com/android/server/wifi/WifiNative.java +++ b/service/java/com/android/server/wifi/WifiNative.java @@ -326,36 +326,51 @@ public class WifiNative { return doStringCommand("GET_CAPABILITY freq"); } + /** + * Create a comma separate string from integer set. + * @param values List of integers. + * @return comma separated string. + */ + private static String createCSVStringFromIntegerSet(Set<Integer> values) { + StringBuilder list = new StringBuilder(); + boolean first = true; + for (Integer value : values) { + if (!first) { + list.append(","); + } + list.append(value); + first = false; + } + return list.toString(); + } /** * Start a scan using wpa_supplicant for the given frequencies. - * If freqs is null then all supported channels are scanned. + * @param freqs list of frequencies to scan for, if null scan all supported channels. + * @param hiddenNetworkIds List of hidden networks to be scanned for. */ - public boolean scan(Set<Integer> freqs) { - if (freqs == null) { - return scanFrequencyList(null); - } else if (freqs.size() != 0) { - StringBuilder freqList = new StringBuilder(); - boolean first = true; - for (Integer freq : freqs) { - if (!first) { - freqList.append(","); - } - freqList.append(freq.toString()); - first = false; - } - return scanFrequencyList(freqList.toString()); - } else { - return false; + public boolean scan(Set<Integer> freqs, Set<Integer> hiddenNetworkIds) { + String freqList = null; + String hiddenNetworkIdList = null; + if (freqs != null && freqs.size() != 0) { + freqList = createCSVStringFromIntegerSet(freqs); } + if (hiddenNetworkIds != null && hiddenNetworkIds.size() != 0) { + hiddenNetworkIdList = createCSVStringFromIntegerSet(hiddenNetworkIds); + } + return scanWithParams(freqList, hiddenNetworkIdList); } - private boolean scanFrequencyList(String freqList) { - if (freqList == null) { - return doBooleanCommand("SCAN TYPE=ONLY"); - } else { - return doBooleanCommand("SCAN TYPE=ONLY freq=" + freqList); + private boolean scanWithParams(String freqList, String hiddenNetworkIdList) { + StringBuilder scanCommand = new StringBuilder(); + scanCommand.append("SCAN TYPE=ONLY"); + if (freqList != null) { + scanCommand.append(" freq=" + freqList); + } + if (hiddenNetworkIdList != null) { + scanCommand.append(" scan_id=" + hiddenNetworkIdList); } + return doBooleanCommand(scanCommand.toString()); } /* Does a graceful shutdown of supplicant. Is a common stop function for both p2p and sta. diff --git a/service/java/com/android/server/wifi/WifiStateMachine.java b/service/java/com/android/server/wifi/WifiStateMachine.java index 6804b4295..2ce51114b 100644 --- a/service/java/com/android/server/wifi/WifiStateMachine.java +++ b/service/java/com/android/server/wifi/WifiStateMachine.java @@ -2017,8 +2017,11 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno } } + // Retrieve the list of hidden networkId's to scan for. + Set<Integer> hiddenNetworkIds = mWifiConfigManager.getHiddenConfiguredNetworkIds(); + // call wifi native to start the scan - if (startScanNative(freqs)) { + if (startScanNative(freqs, hiddenNetworkIds)) { // only count battery consumption if scan request is accepted noteScanStart(message.arg1, workSource); // a full scan covers everything, clearing scan request buffer @@ -2072,8 +2075,8 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno /** * return true iff scan request is accepted */ - private boolean startScanNative(Set<Integer> freqs) { - if (mWifiNative.scan(freqs)) { + private boolean startScanNative(Set<Integer> freqs, Set<Integer> hiddenNetworkIds) { + if (mWifiNative.scan(freqs, hiddenNetworkIds)) { mIsScanOngoing = true; mIsFullScanOngoing = (freqs == null); lastScanFreqs = freqs; @@ -7267,8 +7270,12 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno //if (DBG) { logd("starting scan for " + config.configKey() + " with " + freqs); //} + Set<Integer> hiddenNetworkIds = new HashSet<>(); + if (config.hiddenSSID) { + hiddenNetworkIds.add(config.networkId); + } // Call wifi native to start the scan - if (startScanNative(freqs)) { + if (startScanNative(freqs, hiddenNetworkIds)) { // Only count battery consumption if scan request is accepted noteScanStart(SCAN_ALARM_SOURCE, null); messageHandlingStatus = MESSAGE_HANDLING_STATUS_OK; diff --git a/tests/wifitests/src/com/android/server/wifi/BaseWifiScannerImplTest.java b/tests/wifitests/src/com/android/server/wifi/BaseWifiScannerImplTest.java index d3f25b452..9f65f44ec 100644 --- a/tests/wifitests/src/com/android/server/wifi/BaseWifiScannerImplTest.java +++ b/tests/wifitests/src/com/android/server/wifi/BaseWifiScannerImplTest.java @@ -148,7 +148,7 @@ public abstract class BaseWifiScannerImplTest { WifiNative.ScanEventHandler eventHandler2 = mock(WifiNative.ScanEventHandler.class); // scan start succeeds - when(mWifiNative.scan(any(Set.class))).thenReturn(true); + when(mWifiNative.scan(any(Set.class), any(Set.class))).thenReturn(true); assertTrue(mScanner.startSingleScan(settings, eventHandler)); assertFalse("second scan while first scan running should fail immediately", @@ -172,7 +172,7 @@ public abstract class BaseWifiScannerImplTest { InOrder order = inOrder(eventHandler, mWifiNative); // scan fails - when(mWifiNative.scan(any(Set.class))).thenReturn(false); + when(mWifiNative.scan(any(Set.class), any(Set.class))).thenReturn(false); // start scan assertTrue(mScanner.startSingleScan(settings, eventHandler)); @@ -222,7 +222,7 @@ public abstract class BaseWifiScannerImplTest { InOrder order = inOrder(eventHandler, mWifiNative); // scans succeed - when(mWifiNative.scan(any(Set.class))).thenReturn(true); + when(mWifiNative.scan(any(Set.class), any(Set.class))).thenReturn(true); // start first scan assertTrue(mScanner.startSingleScan(settings, eventHandler)); @@ -268,7 +268,7 @@ public abstract class BaseWifiScannerImplTest { InOrder order = inOrder(eventHandler, mWifiNative); // scan succeeds - when(mWifiNative.scan(any(Set.class))).thenReturn(true); + when(mWifiNative.scan(any(Set.class), any(Set.class))).thenReturn(true); // start scan assertTrue(mScanner.startSingleScan(settings, eventHandler)); @@ -281,7 +281,7 @@ public abstract class BaseWifiScannerImplTest { protected void expectSuccessfulSingleScan(InOrder order, WifiNative.ScanEventHandler eventHandler, Set<Integer> expectedScan, ScanResults results, boolean expectFullResults) { - order.verify(mWifiNative).scan(eq(expectedScan)); + order.verify(mWifiNative).scan(eq(expectedScan), any(Set.class)); when(mWifiNative.getScanResults()).thenReturn(results.getScanDetailArrayList()); diff --git a/tests/wifitests/src/com/android/server/wifi/SupplicantWifiScannerTest.java b/tests/wifitests/src/com/android/server/wifi/SupplicantWifiScannerTest.java index 3e0aade33..16f169ade 100644 --- a/tests/wifitests/src/com/android/server/wifi/SupplicantWifiScannerTest.java +++ b/tests/wifitests/src/com/android/server/wifi/SupplicantWifiScannerTest.java @@ -329,7 +329,7 @@ public class SupplicantWifiScannerTest extends BaseWifiScannerImplTest { InOrder order = inOrder(eventHandler, mWifiNative); // All scans fail - when(mWifiNative.scan(any(Set.class))).thenReturn(false); + when(mWifiNative.scan(any(Set.class), any(Set.class))).thenReturn(false); // Start scan mScanner.startBatchedScan(settings, eventHandler); @@ -337,7 +337,7 @@ public class SupplicantWifiScannerTest extends BaseWifiScannerImplTest { assertEquals("alarm for next period", 1, mAlarmManager.getPendingCount()); expectFailedScanStart(order, eventHandler, - expectedBandScanFreqs(WifiScanner.WIFI_BAND_24_GHZ)); + expectedBandScanFreqs(WifiScanner.WIFI_BAND_24_GHZ), null); // Fire alarm to start next scan dispatchOnlyAlarm(); @@ -345,7 +345,7 @@ public class SupplicantWifiScannerTest extends BaseWifiScannerImplTest { assertEquals("alarm for next period", 1, mAlarmManager.getPendingCount()); expectFailedScanStart(order, eventHandler, - expectedBandScanFreqs(WifiScanner.WIFI_BAND_24_GHZ)); + expectedBandScanFreqs(WifiScanner.WIFI_BAND_24_GHZ), null); verifyNoMoreInteractions(eventHandler); } @@ -364,7 +364,7 @@ public class SupplicantWifiScannerTest extends BaseWifiScannerImplTest { InOrder order = inOrder(eventHandler, mWifiNative); // All scan starts succeed - when(mWifiNative.scan(any(Set.class))).thenReturn(true); + when(mWifiNative.scan(any(Set.class), any(Set.class))).thenReturn(true); // Start scan mScanner.startBatchedScan(settings, eventHandler); @@ -372,7 +372,7 @@ public class SupplicantWifiScannerTest extends BaseWifiScannerImplTest { assertEquals("alarm for next period", 1, mAlarmManager.getPendingCount()); expectFailedEventScan(order, eventHandler, - expectedBandScanFreqs(WifiScanner.WIFI_BAND_24_GHZ)); + expectedBandScanFreqs(WifiScanner.WIFI_BAND_24_GHZ), null); // Fire alarm to start next scan dispatchOnlyAlarm(); @@ -380,7 +380,7 @@ public class SupplicantWifiScannerTest extends BaseWifiScannerImplTest { assertEquals("alarm for next period", 1, mAlarmManager.getPendingCount()); expectFailedEventScan(order, eventHandler, - expectedBandScanFreqs(WifiScanner.WIFI_BAND_24_GHZ)); + expectedBandScanFreqs(WifiScanner.WIFI_BAND_24_GHZ), null); verifyNoMoreInteractions(eventHandler); } @@ -411,7 +411,7 @@ public class SupplicantWifiScannerTest extends BaseWifiScannerImplTest { InOrder order = inOrder(eventHandler, mWifiNative); // All scan starts succeed - when(mWifiNative.scan(any(Set.class))).thenReturn(true); + when(mWifiNative.scan(any(Set.class), any(Set.class))).thenReturn(true); // Start scan mScanner.startBatchedScan(settings, eventHandler); @@ -466,7 +466,7 @@ public class SupplicantWifiScannerTest extends BaseWifiScannerImplTest { InOrder order = inOrder(eventHandler, mWifiNative); // All scan starts succeed - when(mWifiNative.scan(any(Set.class))).thenReturn(true); + when(mWifiNative.scan(any(Set.class), any(Set.class))).thenReturn(true); // Start scan mScanner.startBatchedScan(settings, eventHandler); @@ -476,7 +476,7 @@ public class SupplicantWifiScannerTest extends BaseWifiScannerImplTest { // alarm for next period assertEquals(1, mAlarmManager.getPendingCount()); - order.verify(mWifiNative).scan(eq(expectedPeriods[0].getScanFreqs())); + order.verify(mWifiNative).scan(eq(expectedPeriods[0].getScanFreqs()), any(Set.class)); mScanner.pauseBatchedScan(); @@ -542,7 +542,7 @@ public class SupplicantWifiScannerTest extends BaseWifiScannerImplTest { InOrder order = inOrder(eventHandler, mWifiNative); // All scan starts succeed - when(mWifiNative.scan(any(Set.class))).thenReturn(true); + when(mWifiNative.scan(any(Set.class), any(Set.class))).thenReturn(true); // Start scan mScanner.startBatchedScan(settings, eventHandler); @@ -581,7 +581,7 @@ public class SupplicantWifiScannerTest extends BaseWifiScannerImplTest { InOrder order = inOrder(eventHandler, mWifiNative); // All scans succeed - when(mWifiNative.scan(any(Set.class))).thenReturn(true); + when(mWifiNative.scan(any(Set.class), any(Set.class))).thenReturn(true); // Start scan mScanner.startBatchedScan(settings, eventHandler); @@ -641,7 +641,7 @@ public class SupplicantWifiScannerTest extends BaseWifiScannerImplTest { ArrayList<ScanDetail> nativeResults, WifiScanner.ScanData[] expectedScanResults, ScanResult[] fullResults, int periodId) { // Verify scan started - order.verify(mWifiNative).scan(eq(scanFreqs)); + order.verify(mWifiNative).scan(eq(scanFreqs), any(Set.class)); // Setup scan results when(mWifiNative.getScanResults()).thenReturn(nativeResults); @@ -665,17 +665,17 @@ public class SupplicantWifiScannerTest extends BaseWifiScannerImplTest { } private void expectFailedScanStart(InOrder order, WifiNative.ScanEventHandler eventHandler, - Set<Integer> scanFreqs) { + Set<Integer> scanFreqs, Set<Integer> networkIds) { // Verify scan started - order.verify(mWifiNative).scan(eq(scanFreqs)); + order.verify(mWifiNative).scan(eq(scanFreqs), eq(networkIds)); // TODO: verify failure event } private void expectFailedEventScan(InOrder order, WifiNative.ScanEventHandler eventHandler, - Set<Integer> scanFreqs) { + Set<Integer> scanFreqs, Set<Integer> networkIds) { // Verify scan started - order.verify(mWifiNative).scan(eq(scanFreqs)); + order.verify(mWifiNative).scan(eq(scanFreqs), eq(networkIds)); // Notify scan has failed mWifiMonitor.sendMessage(mWifiNative.getInterfaceName(), WifiMonitor.SCAN_FAILED_EVENT); diff --git a/tests/wifitests/src/com/android/server/wifi/WifiStateMachineTest.java b/tests/wifitests/src/com/android/server/wifi/WifiStateMachineTest.java index af19a3829..f868c522b 100644 --- a/tests/wifitests/src/com/android/server/wifi/WifiStateMachineTest.java +++ b/tests/wifitests/src/com/android/server/wifi/WifiStateMachineTest.java @@ -82,7 +82,6 @@ import org.junit.After; import org.junit.Before; import org.junit.Test; import org.mockito.Mock; -import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import java.io.ByteArrayOutputStream; @@ -466,6 +465,10 @@ public class WifiStateMachineTest { } private void addNetworkAndVerifySuccess() throws Exception { + addNetworkAndVerifySuccess(false); + } + + private void addNetworkAndVerifySuccess(boolean isHidden) throws Exception { loadComponents(); final HashMap<String, String> nameToValue = new HashMap<String, String>(); @@ -518,12 +521,16 @@ public class WifiStateMachineTest { WifiConfiguration config = new WifiConfiguration(); config.SSID = sSSID; config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); + config.hiddenSSID = isHidden; mLooper.startAutoDispatch(); mWsm.syncAddOrUpdateNetwork(mWsmAsyncChannel, config); mLooper.stopAutoDispatch(); verify(mWifiNative).addNetwork(); verify(mWifiNative).setNetworkVariable(0, "ssid", sHexSSID); + if (isHidden) { + verify(mWifiNative).setNetworkVariable(0, "scan_ssid", Integer.toString(1)); + } mLooper.startAutoDispatch(); List<WifiConfiguration> configs = mWsm.syncGetConfiguredNetworks(-1, mWsmAsyncChannel); @@ -744,7 +751,25 @@ public class WifiStateMachineTest { mWsm.startScan(-1, 0, null, null); mLooper.dispatchAll(); - verify(mWifiNative).scan(null); + verify(mWifiNative).scan(null, mWifiConfigManager.getHiddenConfiguredNetworkIds()); + + when(mWifiNative.getScanResults()).thenReturn(getMockScanResults()); + mWsm.sendMessage(WifiMonitor.SCAN_RESULTS_EVENT); + mLooper.dispatchAll(); + + List<ScanResult> results = mWsm.syncGetScanResultsList(); + assertEquals(8, results.size()); + } + + @Test + public void scanWithHiddenNetwork() throws Exception { + addNetworkAndVerifySuccess(true); + + mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); + mWsm.startScan(-1, 0, null, null); + mLooper.dispatchAll(); + + verify(mWifiNative).scan(null, mWifiConfigManager.getHiddenConfiguredNetworkIds()); when(mWifiNative.getScanResults()).thenReturn(getMockScanResults()); mWsm.sendMessage(WifiMonitor.SCAN_RESULTS_EVENT); |