From 985901cea5d3ce2a534ffd7fff485abb2411de61 Mon Sep 17 00:00:00 2001 From: Nate Jiang Date: Mon, 15 Jul 2019 12:03:52 -0700 Subject: [WifiNetworkFactory] Trim user approval list per App Add capacity limit of APs for each App, remove least recently used ones when capacity is exceeded. Bug: 137129535 Test: atest android.net.wifi Test: atest com.android.server.wifi Change-Id: I5c1b7fa9c6ccc35e63f96c49e645bdb4ee7a5b77 --- .../server/wifi/WifiNetworkFactoryTest.java | 161 +++++++++++++++++++++ 1 file changed, 161 insertions(+) (limited to 'tests') diff --git a/tests/wifitests/src/com/android/server/wifi/WifiNetworkFactoryTest.java b/tests/wifitests/src/com/android/server/wifi/WifiNetworkFactoryTest.java index d4e6594c8..968527a8d 100644 --- a/tests/wifitests/src/com/android/server/wifi/WifiNetworkFactoryTest.java +++ b/tests/wifitests/src/com/android/server/wifi/WifiNetworkFactoryTest.java @@ -61,8 +61,10 @@ import android.os.WorkSource; import android.os.test.TestLooper; import android.test.suitebuilder.annotation.SmallTest; import android.util.Pair; +import android.util.Xml; import com.android.internal.util.AsyncChannel; +import com.android.internal.util.FastXmlSerializer; import com.android.server.wifi.WifiNetworkFactory.AccessPoint; import com.android.server.wifi.nano.WifiMetricsProto; import com.android.server.wifi.util.ScanResultUtil; @@ -76,9 +78,15 @@ import org.mockito.ArgumentMatcher; import org.mockito.InOrder; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlSerializer; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -146,6 +154,7 @@ public class WifiNetworkFactoryTest { private WifiNetworkFactory mWifiNetworkFactory; private NetworkRequestStoreData.DataSource mDataSource; + private NetworkRequestStoreData mNetworkRequestStoreData; /** * Setup the mocks. @@ -185,6 +194,7 @@ public class WifiNetworkFactoryTest { verify(mWifiInjector).makeNetworkRequestStoreData(dataSourceArgumentCaptor.capture()); mDataSource = dataSourceArgumentCaptor.getValue(); assertNotNull(mDataSource); + mNetworkRequestStoreData = new NetworkRequestStoreData(mDataSource); // Register and establish full connection to connectivity manager. mWifiNetworkFactory.register(); @@ -1082,6 +1092,73 @@ public class WifiNetworkFactoryTest { assertEquals(TEST_NETWORK_ID_1, message.arg1); } + /** + * Verify when number of user approved access points exceed the capacity, framework should trim + * the Set by removing the least recently used elements. + */ + @Test + public void testNetworkSpecifierHandleUserSelectionConnectToNetworkExceedApprovedListCapacity() + throws Exception { + int userApproveAccessPointCapacity = mWifiNetworkFactory.NUM_OF_ACCESS_POINT_LIMIT_PER_APP; + int numOfApPerSsid = userApproveAccessPointCapacity / 2 + 1; + String[] testIds = new String[]{TEST_SSID_1, TEST_SSID_2}; + + // Setup up scan data + setupScanDataSameSsidWithDiffBssid(SCAN_RESULT_TYPE_WPA_PSK, numOfApPerSsid, testIds); + + // Setup network specifier for WPA-PSK networks. + PatternMatcher ssidPatternMatch = + new PatternMatcher(TEST_SSID_1, PatternMatcher.PATTERN_PREFIX); + Pair bssidPatternMatch = + Pair.create(MacAddress.ALL_ZEROS_ADDRESS, MacAddress.ALL_ZEROS_ADDRESS); + WifiConfiguration wifiConfiguration = WifiConfigurationTestUtil.createPskNetwork(); + wifiConfiguration.preSharedKey = TEST_WPA_PRESHARED_KEY; + WifiNetworkSpecifier specifier = new WifiNetworkSpecifier( + ssidPatternMatch, bssidPatternMatch, wifiConfiguration, TEST_UID_1, + TEST_PACKAGE_NAME_1); + + // request network, trigger scan and get matched set. + mNetworkRequest.networkCapabilities.setNetworkSpecifier(specifier); + mWifiNetworkFactory.needNetworkFor(mNetworkRequest, 0); + + mWifiNetworkFactory.addCallback(mAppBinder, mNetworkRequestMatchCallback, + TEST_CALLBACK_IDENTIFIER); + verify(mNetworkRequestMatchCallback).onUserSelectionCallbackRegistration( + mNetworkRequestUserSelectionCallback.capture()); + + verifyPeriodicScans(0, PERIODIC_SCAN_INTERVAL_MS); + + INetworkRequestUserSelectionCallback networkRequestUserSelectionCallback = + mNetworkRequestUserSelectionCallback.getValue(); + assertNotNull(networkRequestUserSelectionCallback); + + // Now trigger user selection to one of the network. + mSelectedNetwork = WifiConfigurationTestUtil.createPskNetwork(); + mSelectedNetwork.SSID = "\"" + mTestScanDatas[0].getResults()[0].SSID + "\""; + networkRequestUserSelectionCallback.select(mSelectedNetwork); + mLooper.dispatchAll(); + + // Verifier num of Approved access points. + assertEquals(mWifiNetworkFactory.mUserApprovedAccessPointMap + .get(TEST_PACKAGE_NAME_1).size(), numOfApPerSsid); + + // Now trigger user selection to another network with different SSID. + mSelectedNetwork = WifiConfigurationTestUtil.createPskNetwork(); + mSelectedNetwork.SSID = "\"" + mTestScanDatas[0].getResults()[numOfApPerSsid].SSID + "\""; + networkRequestUserSelectionCallback.select(mSelectedNetwork); + mLooper.dispatchAll(); + + // Verify triggered trim when user Approved Access Points exceed capacity. + Set userApprovedAccessPoints = mWifiNetworkFactory.mUserApprovedAccessPointMap + .get(TEST_PACKAGE_NAME_1); + assertEquals(userApprovedAccessPoints.size(), userApproveAccessPointCapacity); + long numOfSsid1Aps = userApprovedAccessPoints + .stream() + .filter(a->a.ssid.equals(TEST_SSID_1)) + .count(); + assertEquals(numOfSsid1Aps, userApproveAccessPointCapacity - numOfApPerSsid); + } + /** * Verify handling of user selection to trigger connection to an existing saved network. */ @@ -2322,6 +2399,35 @@ public class WifiNetworkFactoryTest { verify(mClientModeImpl).sendMessage(any()); } + /** + * Verify the config store save and load could preserve the elements order. + */ + @Test + public void testStoteConfigSaveAndLoadPreserveOrder() throws Exception { + LinkedHashSet approvedApSet = new LinkedHashSet<>(); + approvedApSet.add(new AccessPoint(TEST_SSID_1, + MacAddress.fromString(TEST_BSSID_1), WifiConfiguration.SECURITY_TYPE_PSK)); + approvedApSet.add(new AccessPoint(TEST_SSID_2, + MacAddress.fromString(TEST_BSSID_2), WifiConfiguration.SECURITY_TYPE_PSK)); + approvedApSet.add(new AccessPoint(TEST_SSID_3, + MacAddress.fromString(TEST_BSSID_3), WifiConfiguration.SECURITY_TYPE_PSK)); + approvedApSet.add(new AccessPoint(TEST_SSID_4, + MacAddress.fromString(TEST_BSSID_4), WifiConfiguration.SECURITY_TYPE_PSK)); + mWifiNetworkFactory.mUserApprovedAccessPointMap.put(TEST_PACKAGE_NAME_1, + new LinkedHashSet<>(approvedApSet)); + // Save config. + byte[] xmlData = serializeData(); + mWifiNetworkFactory.mUserApprovedAccessPointMap.clear(); + // Load config. + deserializeData(xmlData); + + LinkedHashSet storedApSet = mWifiNetworkFactory + .mUserApprovedAccessPointMap.get(TEST_PACKAGE_NAME_1); + // Check load config success and order preserved. + assertNotNull(storedApSet); + assertArrayEquals(approvedApSet.toArray(), storedApSet.toArray()); + } + private Messenger sendNetworkRequestAndSetupForConnectionStatus() throws RemoteException { return sendNetworkRequestAndSetupForConnectionStatus(TEST_SSID_1); } @@ -2621,4 +2727,59 @@ public class WifiNetworkFactoryTest { expectedWifiConfiguration.fromWifiNetworkSpecifier = true; WifiConfigurationTestUtil.assertConfigurationEqual(expectedWifiConfiguration, network); } + + /** + * Create a test scan data for target SSID list with specified number and encryption type + * @param scanResultType network encryption type + * @param nums Number of results with different BSSIDs for one SSID + * @param ssids target SSID list + */ + private void setupScanDataSameSsidWithDiffBssid(int scanResultType, int nums, String[] ssids) { + String baseBssid = "11:34:56:78:90:"; + int[] freq = new int[nums * ssids.length]; + for (int i = 0; i < nums; i++) { + freq[i] = 2417 + i; + } + mTestScanDatas = ScanTestUtil.createScanDatas(new int[][]{ freq }); + assertEquals(1, mTestScanDatas.length); + ScanResult[] scanResults = mTestScanDatas[0].getResults(); + assertEquals(nums * ssids.length, scanResults.length); + String caps = getScanResultCapsForType(scanResultType); + for (int i = 0; i < ssids.length; i++) { + for (int j = i * nums; j < (i + 1) * nums; j++) { + scanResults[j].SSID = ssids[i]; + scanResults[j].BSSID = baseBssid + Integer.toHexString(16 + j); + scanResults[j].capabilities = caps; + scanResults[j].level = -45; + } + } + } + + /** + * Helper function for serializing configuration data to a XML block. + * + * @return byte[] of the XML data + * @throws Exception + */ + private byte[] serializeData() throws Exception { + final XmlSerializer out = new FastXmlSerializer(); + final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + out.setOutput(outputStream, StandardCharsets.UTF_8.name()); + mNetworkRequestStoreData.serializeData(out); + out.flush(); + return outputStream.toByteArray(); + } + + /** + * Helper function for parsing configuration data from a XML block. + * + * @param data XML data to parse from + * @throws Exception + */ + private void deserializeData(byte[] data) throws Exception { + final XmlPullParser in = Xml.newPullParser(); + final ByteArrayInputStream inputStream = new ByteArrayInputStream(data); + in.setInput(inputStream, StandardCharsets.UTF_8.name()); + mNetworkRequestStoreData.deserializeData(in, in.getDepth()); + } } -- cgit v1.2.3