Merge "[NetworkSuggestion] add hidden network from network suggestion" into qt-qpr1-dev
diff --git a/service/java/com/android/server/wifi/ScanRequestProxy.java b/service/java/com/android/server/wifi/ScanRequestProxy.java
index efbb7b6..a467844 100644
--- a/service/java/com/android/server/wifi/ScanRequestProxy.java
+++ b/service/java/com/android/server/wifi/ScanRequestProxy.java
@@ -484,11 +484,14 @@
         settings.reportEvents = WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN
                 | WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT;
         if (mScanningForHiddenNetworksEnabled) {
-            // retrieve the list of hidden network SSIDs to scan for, if enabled.
+            // retrieve the list of hidden network SSIDs from saved network to scan for, if enabled.
             List<WifiScanner.ScanSettings.HiddenNetwork> hiddenNetworkList =
-                    mWifiConfigManager.retrieveHiddenNetworkList();
+                    new ArrayList<>(mWifiConfigManager.retrieveHiddenNetworkList());
+            // retrieve the list of hidden network SSIDs from Network suggestion to scan for.
+            hiddenNetworkList.addAll(
+                    mWifiInjector.getWifiNetworkSuggestionsManager().retrieveHiddenNetworkList());
             settings.hiddenNetworks = hiddenNetworkList.toArray(
-                    new WifiScanner.ScanSettings.HiddenNetwork[hiddenNetworkList.size()]);
+                    new WifiScanner.ScanSettings.HiddenNetwork[0]);
         }
         mWifiScanner.startScan(settings, new ScanRequestProxyScanListener(), workSource);
         return true;
diff --git a/service/java/com/android/server/wifi/WifiConfigManager.java b/service/java/com/android/server/wifi/WifiConfigManager.java
index b218934..683ace4 100644
--- a/service/java/com/android/server/wifi/WifiConfigManager.java
+++ b/service/java/com/android/server/wifi/WifiConfigManager.java
@@ -2685,7 +2685,7 @@
     }
 
     /**
-     * Retrieves a list of all the saved hidden networks for scans.
+     * Retrieves a list of all the saved hidden networks for scans
      *
      * Hidden network list sent to the firmware has limited size. If there are a lot of saved
      * networks, this list will be truncated and we might end up not sending the networks
@@ -2698,19 +2698,12 @@
     public List<WifiScanner.ScanSettings.HiddenNetwork> retrieveHiddenNetworkList() {
         List<WifiScanner.ScanSettings.HiddenNetwork> hiddenList = new ArrayList<>();
         List<WifiConfiguration> networks = new ArrayList<>(getInternalConfiguredNetworks());
-        // Remove any permanently disabled networks or non hidden networks.
-        Iterator<WifiConfiguration> iter = networks.iterator();
-        while (iter.hasNext()) {
-            WifiConfiguration config = iter.next();
-            if (!config.hiddenSSID) {
-                iter.remove();
-            }
-        }
-        Collections.sort(networks, sScanListComparator);
+        // Remove any non hidden networks.
+        networks.removeIf(config -> !config.hiddenSSID);
+        networks.sort(sScanListComparator);
         // The most frequently connected network has the highest priority now.
         for (WifiConfiguration config : networks) {
-            hiddenList.add(
-                    new WifiScanner.ScanSettings.HiddenNetwork(config.SSID));
+            hiddenList.add(new WifiScanner.ScanSettings.HiddenNetwork(config.SSID));
         }
         return hiddenList;
     }
diff --git a/service/java/com/android/server/wifi/WifiConnectivityManager.java b/service/java/com/android/server/wifi/WifiConnectivityManager.java
index 7411422..2e4b5c8 100644
--- a/service/java/com/android/server/wifi/WifiConnectivityManager.java
+++ b/service/java/com/android/server/wifi/WifiConnectivityManager.java
@@ -916,11 +916,14 @@
         settings.reportEvents = WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT
                             | WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN;
         settings.numBssidsPerScan = 0;
-
+        // retrieve the list of hidden network SSIDs from saved network to scan for
         List<ScanSettings.HiddenNetwork> hiddenNetworkList =
-                mConfigManager.retrieveHiddenNetworkList();
+                new ArrayList<>(mConfigManager.retrieveHiddenNetworkList());
+        // retrieve the list of hidden network SSIDs from Network suggestion to scan for
+        hiddenNetworkList.addAll(
+                mWifiInjector.getWifiNetworkSuggestionsManager().retrieveHiddenNetworkList());
         settings.hiddenNetworks =
-                hiddenNetworkList.toArray(new ScanSettings.HiddenNetwork[hiddenNetworkList.size()]);
+                hiddenNetworkList.toArray(new ScanSettings.HiddenNetwork[0]);
 
         SingleScanListener singleScanListener =
                 new SingleScanListener(isFullBandScan);
diff --git a/service/java/com/android/server/wifi/WifiNetworkSuggestionsManager.java b/service/java/com/android/server/wifi/WifiNetworkSuggestionsManager.java
index 5ed0b7b..c30d78a 100644
--- a/service/java/com/android/server/wifi/WifiNetworkSuggestionsManager.java
+++ b/service/java/com/android/server/wifi/WifiNetworkSuggestionsManager.java
@@ -37,6 +37,7 @@
 import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiManager;
 import android.net.wifi.WifiNetworkSuggestion;
+import android.net.wifi.WifiScanner;
 import android.os.Handler;
 import android.os.UserHandle;
 import android.text.TextUtils;
@@ -51,6 +52,7 @@
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
@@ -90,6 +92,10 @@
     @VisibleForTesting
     public static final String EXTRA_UID =
             "com.android.server.wifi.extra.NetworkSuggestion.UID";
+    /**
+     * Limit number of hidden networks attach to scan
+     */
+    private static final int NUMBER_OF_HIDDEN_NETWORK_FOR_ONE_SCAN = 100;
 
     private final Context mContext;
     private final Resources mResources;
@@ -922,6 +928,28 @@
     }
 
     /**
+     * Get hidden network from active network suggestions.
+     * Todo(): Now limit by a fixed number, maybe we can try rotation?
+     * @return set of WifiConfigurations
+     */
+    public List<WifiScanner.ScanSettings.HiddenNetwork> retrieveHiddenNetworkList() {
+        List<WifiScanner.ScanSettings.HiddenNetwork> hiddenNetworks = new ArrayList<>();
+        for (PerAppInfo appInfo : mActiveNetworkSuggestionsPerApp.values()) {
+            if (!appInfo.hasUserApproved) continue;
+            for (ExtendedWifiNetworkSuggestion ewns : appInfo.extNetworkSuggestions) {
+                if (!ewns.wns.wifiConfiguration.hiddenSSID) continue;
+                hiddenNetworks.add(
+                        new WifiScanner.ScanSettings.HiddenNetwork(
+                                ewns.wns.wifiConfiguration.SSID));
+                if (hiddenNetworks.size() >= NUMBER_OF_HIDDEN_NETWORK_FOR_ONE_SCAN) {
+                    return hiddenNetworks;
+                }
+            }
+        }
+        return hiddenNetworks;
+    }
+
+    /**
      * Helper method to send the post connection broadcast to specified package.
      */
     private void sendPostConnectionBroadcast(
diff --git a/tests/wifitests/src/com/android/server/wifi/ScanRequestProxyTest.java b/tests/wifitests/src/com/android/server/wifi/ScanRequestProxyTest.java
index 9857898..38e2eaf 100644
--- a/tests/wifitests/src/com/android/server/wifi/ScanRequestProxyTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/ScanRequestProxyTest.java
@@ -66,6 +66,11 @@
                 add(new WifiScanner.ScanSettings.HiddenNetwork("test_ssid_2"));
 
             }};
+    private static final List<WifiScanner.ScanSettings.HiddenNetwork> TEST_HIDDEN_NETWORKS_LIST_NS =
+            new ArrayList<WifiScanner.ScanSettings.HiddenNetwork>() {{
+                add(new WifiScanner.ScanSettings.HiddenNetwork("test_ssid_3"));
+                add(new WifiScanner.ScanSettings.HiddenNetwork("test_ssid_4"));
+            }};
 
     @Mock private Context mContext;
     @Mock private AppOpsManager mAppOps;
@@ -77,6 +82,8 @@
     @Mock private WifiMetrics mWifiMetrics;
     @Mock private Clock mClock;
     @Mock private FrameworkFacade mFrameworkFacade;
+    @Mock private WifiNetworkSuggestionsManager mWifiNetworkSuggestionsManager;
+
     private ArgumentCaptor<WorkSource> mWorkSourceArgumentCaptor =
             ArgumentCaptor.forClass(WorkSource.class);
     private ArgumentCaptor<WifiScanner.ScanSettings> mScanSettingsArgumentCaptor =
@@ -98,7 +105,11 @@
         MockitoAnnotations.initMocks(this);
 
         when(mWifiInjector.getWifiScanner()).thenReturn(mWifiScanner);
+        when(mWifiInjector.getWifiNetworkSuggestionsManager())
+                .thenReturn(mWifiNetworkSuggestionsManager);
         when(mWifiConfigManager.retrieveHiddenNetworkList()).thenReturn(TEST_HIDDEN_NETWORKS_LIST);
+        when(mWifiNetworkSuggestionsManager.retrieveHiddenNetworkList())
+                .thenReturn(TEST_HIDDEN_NETWORKS_LIST_NS);
         doNothing().when(mWifiScanner).registerScanListener(
                 mGlobalScanListenerArgumentCaptor.capture());
         doNothing().when(mWifiScanner).startScan(
@@ -106,7 +117,8 @@
                 mScanRequestListenerArgumentCaptor.capture(),
                 mWorkSourceArgumentCaptor.capture());
 
-        mInOrder = inOrder(mWifiScanner, mWifiConfigManager, mContext);
+        mInOrder = inOrder(mWifiScanner, mWifiConfigManager,
+                mContext, mWifiNetworkSuggestionsManager);
         mTestScanDatas1 =
                 ScanTestUtil.createScanDatas(new int[][]{{ 2417, 2427, 5180, 5170 }},
                         new int[]{0},
@@ -205,8 +217,8 @@
         mInOrder.verify(mWifiScanner).registerScanListener(any());
         mInOrder.verify(mWifiScanner).startScan(any(), any(), any());
 
-        assertTrue(mWorkSourceArgumentCaptor.getValue().equals(
-                new WorkSource(TEST_UID, TEST_PACKAGE_NAME_1)));
+        assertEquals(mWorkSourceArgumentCaptor.getValue(),
+                new WorkSource(TEST_UID, TEST_PACKAGE_NAME_1));
         validateScanSettings(mScanSettingsArgumentCaptor.getValue(), false, true);
     }
 
@@ -222,10 +234,11 @@
 
         assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_1));
         mInOrder.verify(mWifiConfigManager, never()).retrieveHiddenNetworkList();
+        mInOrder.verify(mWifiNetworkSuggestionsManager, never()).retrieveHiddenNetworkList();
         mInOrder.verify(mWifiScanner).startScan(any(), any(), any());
 
-        assertTrue(mWorkSourceArgumentCaptor.getValue().equals(
-                new WorkSource(TEST_UID, TEST_PACKAGE_NAME_1)));
+        assertEquals(mWorkSourceArgumentCaptor.getValue(),
+                new WorkSource(TEST_UID, TEST_PACKAGE_NAME_1));
         validateScanSettings(mScanSettingsArgumentCaptor.getValue(), false);
 
         verify(mWifiMetrics).incrementExternalAppOneshotScanRequestsCount();
@@ -242,11 +255,13 @@
         validateScanAvailableBroadcastSent(true);
 
         assertTrue(mScanRequestProxy.startScan(TEST_UID, TEST_PACKAGE_NAME_1));
+
         mInOrder.verify(mWifiConfigManager).retrieveHiddenNetworkList();
+        mInOrder.verify(mWifiNetworkSuggestionsManager).retrieveHiddenNetworkList();
         mInOrder.verify(mWifiScanner).startScan(any(), any(), any());
 
-        assertTrue(mWorkSourceArgumentCaptor.getValue().equals(
-                new WorkSource(TEST_UID, TEST_PACKAGE_NAME_1)));
+        assertEquals(mWorkSourceArgumentCaptor.getValue(),
+                new WorkSource(TEST_UID, TEST_PACKAGE_NAME_1));
         validateScanSettings(mScanSettingsArgumentCaptor.getValue(), true);
 
         verify(mWifiMetrics).incrementExternalAppOneshotScanRequestsCount();
@@ -860,12 +875,15 @@
         }
         assertEquals(WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN
                 | WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT, scanSettings.reportEvents);
+        List<WifiScanner.ScanSettings.HiddenNetwork> hiddenNetworkList =
+                new ArrayList<>();
+        hiddenNetworkList.addAll(TEST_HIDDEN_NETWORKS_LIST);
+        hiddenNetworkList.addAll(TEST_HIDDEN_NETWORKS_LIST_NS);
         if (expectHiddenNetworks) {
             assertNotNull(scanSettings.hiddenNetworks);
-            assertEquals(TEST_HIDDEN_NETWORKS_LIST.size(), scanSettings.hiddenNetworks.length);
+            assertEquals(hiddenNetworkList.size(), scanSettings.hiddenNetworks.length);
             for (int i = 0; i < scanSettings.hiddenNetworks.length; i++) {
-                validateHiddenNetworkInList(scanSettings.hiddenNetworks[i],
-                        TEST_HIDDEN_NETWORKS_LIST);
+                validateHiddenNetworkInList(scanSettings.hiddenNetworks[i], hiddenNetworkList);
             }
         } else {
             assertNull(scanSettings.hiddenNetworks);
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiConnectivityManagerTest.java b/tests/wifitests/src/com/android/server/wifi/WifiConnectivityManagerTest.java
index 7f6c1bc..c1686b4 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiConnectivityManagerTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiConnectivityManagerTest.java
@@ -96,6 +96,10 @@
         mWifiConnectivityHelper = mockWifiConnectivityHelper();
         mWifiNS = mockWifiNetworkSelector();
         when(mWifiInjector.getWifiScanner()).thenReturn(mWifiScanner);
+        when(mWifiInjector.getWifiNetworkSuggestionsManager())
+                .thenReturn(mWifiNetworkSuggestionsManager);
+        when(mWifiNetworkSuggestionsManager.retrieveHiddenNetworkList())
+                .thenReturn(new ArrayList<>());
         mWifiConnectivityManager = createConnectivityManager();
         verify(mWifiConfigManager).setOnSavedNetworkUpdateListener(anyObject());
         mWifiConnectivityManager.setTrustedConnectionAllowed(true);
@@ -140,6 +144,7 @@
     @Mock private CarrierNetworkConfig mCarrierNetworkConfig;
     @Mock private WifiMetrics mWifiMetrics;
     @Mock private WifiNetworkScoreCache mScoreCache;
+    @Mock private WifiNetworkSuggestionsManager mWifiNetworkSuggestionsManager;
     @Captor ArgumentCaptor<ScanResult> mCandidateScanResultCaptor;
     @Captor ArgumentCaptor<ArrayList<String>> mBssidBlacklistCaptor;
     @Captor ArgumentCaptor<ArrayList<String>> mSsidWhitelistCaptor;
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiNetworkSuggestionsManagerTest.java b/tests/wifitests/src/com/android/server/wifi/WifiNetworkSuggestionsManagerTest.java
index 97a1833..d0d7925 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiNetworkSuggestionsManagerTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiNetworkSuggestionsManagerTest.java
@@ -48,6 +48,7 @@
 import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiManager;
 import android.net.wifi.WifiNetworkSuggestion;
+import android.net.wifi.WifiScanner;
 import android.os.Handler;
 import android.os.UserHandle;
 import android.os.test.TestLooper;
@@ -2009,6 +2010,44 @@
     }
 
     /**
+     * Verify get hidden networks from All user approve network suggestions
+     */
+    @Test
+    public void testGetHiddenNetworks() {
+
+        WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion(
+                WifiConfigurationTestUtil.createOpenNetwork(), true, false, TEST_UID_1,
+                TEST_PACKAGE_1);
+        WifiNetworkSuggestion hiddenNetworkSuggestion1 = new WifiNetworkSuggestion(
+                WifiConfigurationTestUtil.createPskHiddenNetwork(), true, false, TEST_UID_1,
+                TEST_PACKAGE_1);
+        WifiNetworkSuggestion hiddenNetworkSuggestion2 = new WifiNetworkSuggestion(
+                WifiConfigurationTestUtil.createPskHiddenNetwork(), true, false, TEST_UID_2,
+                TEST_PACKAGE_2);
+        List<WifiNetworkSuggestion> networkSuggestionList1 =
+                new ArrayList<WifiNetworkSuggestion>() {{
+                    add(networkSuggestion);
+                    add(hiddenNetworkSuggestion1);
+                }};
+        List<WifiNetworkSuggestion> networkSuggestionList2 =
+                new ArrayList<WifiNetworkSuggestion>() {{
+                    add(hiddenNetworkSuggestion2);
+                }};
+        assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
+                mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_UID_1,
+                        TEST_PACKAGE_1));
+        assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
+                mWifiNetworkSuggestionsManager.add(networkSuggestionList2, TEST_UID_2,
+                        TEST_PACKAGE_2));
+        mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_1);
+        mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(false, TEST_PACKAGE_2);
+        List<WifiScanner.ScanSettings.HiddenNetwork> hiddenNetworks =
+                mWifiNetworkSuggestionsManager.retrieveHiddenNetworkList();
+        assertEquals(1, hiddenNetworks.size());
+        assertEquals(hiddenNetworkSuggestion1.wifiConfiguration.SSID, hiddenNetworks.get(0).ssid);
+    }
+
+    /**
      * Creates a scan detail corresponding to the provided network values.
      */
     private ScanDetail createScanDetailForNetwork(WifiConfiguration configuration) {