• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3.4
2#
3#   Copyright 2018 - The Android Open Source Project
4#
5#   Licensed under the Apache License, Version 2.0 (the "License");
6#   you may not use this file except in compliance with the License.
7#   You may obtain a copy of the License at
8#
9#       http://www.apache.org/licenses/LICENSE-2.0
10#
11#   Unless required by applicable law or agreed to in writing, software
12#   distributed under the License is distributed on an "AS IS" BASIS,
13#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14#   See the License for the specific language governing permissions and
15#   limitations under the License.
16
17import itertools
18import queue
19import time
20
21import acts.base_test
22import acts.signals as signals
23import acts_contrib.test_utils.wifi.wifi_test_utils as wutils
24import acts.utils
25
26from acts import asserts
27from acts.controllers.android_device import SL4A_APK_NAME
28from acts.test_decorators import test_tracker_info
29from acts_contrib.test_utils.wifi.WifiBaseTest import WifiBaseTest
30from acts_contrib.test_utils.wifi import wifi_constants
31
32WifiEnums = wutils.WifiEnums
33# EAP Macros
34EAP = WifiEnums.Eap
35EapPhase2 = WifiEnums.EapPhase2
36# Enterprise Config Macros
37Ent = WifiEnums.Enterprise
38BOINGO = 1
39ATT = 2
40# Suggestion network Macros
41Untrusted = "untrusted"
42AutoJoin = "enableAutojoin"
43# Network request Macros
44ClearCapabilities = "ClearCapabilities"
45TransportType = "TransportType"
46
47# Default timeout used for reboot, toggle WiFi and Airplane mode,
48# for the system to settle down after the operation.
49DEFAULT_TIMEOUT = 10
50PASSPOINT_TIMEOUT = 30
51
52
53class WifiNetworkSuggestionTest(WifiBaseTest):
54    """Tests for WifiNetworkSuggestion API surface.
55
56    Test Bed Requirement:
57    * one Android device
58    * Several Wi-Fi networks visible to the device, including an open Wi-Fi
59      network.
60    """
61
62    def __init__(self, configs):
63        super().__init__(configs)
64        self.enable_packet_log = True
65
66    def setup_class(self):
67        super().setup_class()
68
69        self.dut = self.android_devices[0]
70        opt_param = [
71            "open_network", "reference_networks", "hidden_networks",
72            "radius_conf_2g", "radius_conf_5g", "ca_cert", "eap_identity",
73            "eap_password", "passpoint_networks", "domain_suffix_match",
74            "wifi6_models", "google_pixel_watch_models"
75        ]
76        self.unpack_userparams(opt_param_names=opt_param, )
77
78        if "AccessPoint" in self.user_params:
79            self.legacy_configure_ap_and_start(
80                wpa_network=True,
81                ent_network=True,
82                radius_conf_2g=self.radius_conf_2g,
83                radius_conf_5g=self.radius_conf_5g,
84            )
85        elif "OpenWrtAP" in self.user_params:
86            self.configure_openwrt_ap_and_start(
87                open_network=True,
88                wpa_network=True,
89            )
90        if hasattr(self, "reference_networks") and \
91            isinstance(self.reference_networks, list):
92            self.wpa_psk_2g = self.reference_networks[0]["2g"]
93            self.wpa_psk_5g = self.reference_networks[0]["5g"]
94        if hasattr(self, "open_network") and isinstance(
95                self.open_network, list):
96            self.open_2g = self.open_network[0]["2g"]
97            self.open_5g = self.open_network[0]["5g"]
98        if hasattr(self, "hidden_networks") and \
99            isinstance(self.hidden_networks, list):
100            self.hidden_network = self.hidden_networks[0]
101        if hasattr(self, "passpoint_networks"):
102            self.passpoint_network = self.passpoint_networks[BOINGO]
103            self.passpoint_network[WifiEnums.SSID_KEY] = \
104                self.passpoint_networks[BOINGO][WifiEnums.SSID_KEY][0]
105        self.dut.droid.wifiRemoveNetworkSuggestions([])
106        if "google_pixel_watch_models" in self.user_params:
107            if not self.dut.model in \
108                self.user_params["google_pixel_watch_models"]:
109                self.dut.adb.shell(
110                    "pm disable com.google.android.apps.carrier.carrierwifi",
111                    ignore_status=True)
112
113    def setup_test(self):
114        super().setup_test()
115        self.dut.droid.wakeLockAcquireBright()
116        self.dut.droid.wakeUpNow()
117        self.dut.unlock_screen()
118        self.clear_user_disabled_networks()
119        wutils.wifi_toggle_state(self.dut, True)
120        self.dut.ed.clear_all_events()
121        self.clear_carrier_approved(
122            str(self.dut.droid.telephonyGetSimCarrierId()))
123        if "_ent_" in self.test_name:
124            if "OpenWrtAP" in self.user_params:
125                self.access_points[0].close()
126                self.configure_openwrt_ap_and_start(
127                    ent_network=True,
128                    radius_conf_2g=self.radius_conf_2g,
129                    radius_conf_5g=self.radius_conf_5g,
130                )
131            self.ent_network_2g = self.ent_networks[0]["2g"]
132            self.ent_network_5g = self.ent_networks[0]["5g"]
133
134    def teardown_test(self):
135        super().teardown_test()
136        self.dut.droid.wakeLockRelease()
137        self.dut.droid.goToSleepNow()
138        self.dut.droid.wifiRemoveNetworkSuggestions([])
139        self.dut.droid.wifiDisconnect()
140        wutils.reset_wifi(self.dut)
141        wutils.wifi_toggle_state(self.dut, False)
142        self.dut.ed.clear_all_events()
143        self.clear_carrier_approved(
144            str(self.dut.droid.telephonyGetSimCarrierId()))
145
146    def teardown_class(self):
147        if "google_pixel_watch_models" in self.user_params:
148            if not self.dut.model in \
149                self.user_params["google_pixel_watch_models"]:
150                self.dut.adb.shell(
151                    "pm enable com.google.android.apps.carrier.carrierwifi")
152        if "AccessPoint" in self.user_params:
153            del self.user_params["reference_networks"]
154            del self.user_params["open_network"]
155
156    """Helper Functions"""
157
158    def set_approved(self, approved):
159        self.dut.log.debug("Setting suggestions from sl4a app " +
160                           "approved" if approved else "not approved")
161        self.dut.adb.shell("cmd wifi network-suggestions-set-user-approved" +
162                           " " + SL4A_APK_NAME + " " +
163                           ("yes" if approved else "no"))
164
165    def is_approved(self):
166        is_approved_str = self.dut.adb.shell(
167            "cmd wifi network-suggestions-has-user-approved" + " " +
168            SL4A_APK_NAME)
169        return True if (is_approved_str == "yes") else False
170
171    def set_carrier_approved(self, carrier_id, approved):
172        self.dut.log.debug(
173            ("Setting IMSI protection exemption for carrier: " + carrier_id +
174             "approved" if approved else "not approved"))
175        self.dut.adb.shell(
176            "cmd wifi imsi-protection-exemption-set-user-approved-for-carrier"
177            + " " + carrier_id + " " + ("yes" if approved else "no"))
178
179    def is_carrier_approved(self, carrier_id):
180        is_approved_str = self.dut.adb.shell(
181            "cmd wifi imsi-protection-exemption-has-user-approved-for-carrier"
182            + " " + carrier_id)
183        return True if (is_approved_str == "yes") else False
184
185    def clear_carrier_approved(self, carrier_id):
186        self.dut.adb.shell(
187            "cmd wifi imsi-protection-exemption-clear-user-approved-for-carrier"
188            + " " + carrier_id)
189
190    def clear_user_disabled_networks(self):
191        self.dut.log.debug("Clearing user disabled networks")
192        self.dut.adb.shell("cmd wifi clear-user-disabled-networks")
193
194    def add_suggestions_and_ensure_connection(
195            self, network_suggestions, expected_ssid,
196            expect_post_connection_broadcast):
197        if expect_post_connection_broadcast is not None:
198            self.dut.droid.wifiStartTrackingNetworkSuggestionStateChange()
199
200        self.dut.log.info("Adding network suggestions")
201        asserts.assert_true(
202            self.dut.droid.wifiAddNetworkSuggestions(network_suggestions),
203            "Failed to add suggestions")
204        # Enable suggestions by the app.
205        self.dut.log.debug("Enabling suggestions from test")
206        self.set_approved(True)
207        wutils.start_wifi_connection_scan_and_return_status(self.dut)
208        # if suggestion is passpoint wait longer for connection.
209        if "profile" in network_suggestions:
210            time.sleep(PASSPOINT_TIMEOUT)
211        wutils.wait_for_connect(self.dut, expected_ssid)
212
213        if expect_post_connection_broadcast is None:
214            return
215
216        # Check if we expected to get the broadcast.
217        try:
218            event = self.dut.ed.pop_event(
219                wifi_constants.WIFI_NETWORK_SUGGESTION_POST_CONNECTION, 60)
220        except queue.Empty:
221            if expect_post_connection_broadcast:
222                raise signals.TestFailure(
223                    "Did not receive post connection broadcast")
224        else:
225            if not expect_post_connection_broadcast:
226                raise signals.TestFailure("Received post connection broadcast")
227        finally:
228            self.dut.droid.wifiStopTrackingNetworkSuggestionStateChange()
229        self.dut.ed.clear_all_events()
230
231    def remove_suggestions_disconnect_and_ensure_no_connection_back(
232            self, network_suggestions, expected_ssid):
233        # Remove suggestion trigger disconnect and wait for the disconnect.
234        self.dut.log.info("Removing network suggestions")
235        asserts.assert_true(
236            self.dut.droid.wifiRemoveNetworkSuggestions(network_suggestions),
237            "Failed to remove suggestions")
238        wutils.wait_for_disconnect(self.dut)
239        self.dut.ed.clear_all_events()
240
241        # Now ensure that we didn't connect back.
242        asserts.assert_false(
243            wutils.wait_for_connect(self.dut,
244                                    expected_ssid,
245                                    assert_on_fail=False),
246            "Device should not connect back")
247
248    def _test_connect_to_wifi_network_reboot_config_store(
249            self, network_suggestions, wifi_network):
250        """ Test network suggestion with reboot config store
251
252        Args:
253        1. network_suggestions: network suggestions in list to add to the device.
254        2. wifi_network: expected wifi network to connect to
255        """
256
257        self.add_suggestions_and_ensure_connection(
258            network_suggestions, wifi_network[WifiEnums.SSID_KEY], None)
259        wutils.verify_11ax_wifi_connection(self.dut, self.wifi6_models,
260                                           "wifi6_ap" in self.user_params)
261
262        # Reboot and wait for connection back to the same suggestion.
263        self.dut.reboot()
264        time.sleep(DEFAULT_TIMEOUT)
265
266        if "google_pixel_watch_models" in self.user_params:
267            if self.dut.model in \
268                self.user_params["google_pixel_watch_models"]:
269                self.dut.unlock_screen()
270
271        wutils.wait_for_connect(self.dut, wifi_network[WifiEnums.SSID_KEY])
272        wutils.verify_11ax_wifi_connection(self.dut, self.wifi6_models,
273                                           "wifi6_ap" in self.user_params)
274
275        self.remove_suggestions_disconnect_and_ensure_no_connection_back(
276            network_suggestions, wifi_network[WifiEnums.SSID_KEY])
277
278        # Reboot with empty suggestion, verify user approval is kept.
279        self.dut.reboot()
280        time.sleep(DEFAULT_TIMEOUT)
281        asserts.assert_true(self.is_approved(), "User approval should be kept")
282
283    @test_tracker_info(uuid="bda8ed20-4382-4380-831a-64cf77eca108")
284    def test_connect_to_wpa_psk_2g(self):
285        """ Adds a network suggestion and ensure that the device connected.
286
287        Steps:
288        1. Send a network suggestion to the device.
289        2. Wait for the device to connect to it.
290        3. Ensure that we did not receive the post connection broadcast
291           (isAppInteractionRequired = False).
292        4. Remove the suggestions and ensure the device does not connect back.
293        """
294        self.add_suggestions_and_ensure_connection(
295            [self.wpa_psk_2g], self.wpa_psk_2g[WifiEnums.SSID_KEY], False)
296
297        self.remove_suggestions_disconnect_and_ensure_no_connection_back(
298            [self.wpa_psk_2g], self.wpa_psk_2g[WifiEnums.SSID_KEY])
299
300    @test_tracker_info(uuid="b2df6ebe-9c5b-4e84-906a-e76f96fcef56")
301    def test_connect_to_wpa_psk_2g_with_screen_off(self):
302        """ Adds a network suggestion and ensure that the device connected
303        when the screen is off.
304
305        Steps:
306        1. Send an invalid suggestion to the device (Needed for PNO scan to start).
307        2. Toggle screen off.
308        3. Send a valid network suggestion to the device.
309        4. Wait for the device to connect to it.
310        5. Ensure that we did not receive the post connection broadcast
311           (isAppInteractionRequired = False).
312        6. Remove the suggestions and ensure the device does not connect back.
313        """
314        invalid_suggestion = self.wpa_psk_5g
315        network_ssid = invalid_suggestion.pop(WifiEnums.SSID_KEY)
316        invalid_suggestion[WifiEnums.SSID_KEY] = network_ssid + "blah"
317
318        self.dut.log.info("Adding invalid suggestions")
319        asserts.assert_true(
320            self.dut.droid.wifiAddNetworkSuggestions([invalid_suggestion]),
321            "Failed to add suggestions")
322
323        # Approve suggestions by the app.
324        self.set_approved(True)
325
326        # Turn screen off to ensure PNO kicks-in.
327        self.dut.droid.wakeLockRelease()
328        self.dut.droid.goToSleepNow()
329        time.sleep(10)
330
331        # Add valid suggestions & ensure we restart PNO and connect to it.
332        self.add_suggestions_and_ensure_connection(
333            [self.wpa_psk_2g], self.wpa_psk_2g[WifiEnums.SSID_KEY], False)
334
335        self.remove_suggestions_disconnect_and_ensure_no_connection_back(
336            [self.wpa_psk_2g], self.wpa_psk_2g[WifiEnums.SSID_KEY])
337
338    @test_tracker_info(uuid="f18bf994-ef3b-45d6-aba0-dd6338b07979")
339    def test_connect_to_wpa_psk_2g_modify_meteredness(self):
340        """ Adds a network suggestion and ensure that the device connected.
341        Change the meteredness of the network after the connection.
342
343        Steps:
344        1. Send a network suggestion to the device.
345        2. Wait for the device to connect to it.
346        3. Ensure that we did not receive the post connection broadcast
347           (isAppInteractionRequired = False).
348        4. Mark the network suggestion metered.
349        5. Ensure that the device disconnected and reconnected back to the
350           suggestion.
351        6. Mark the network suggestion unmetered.
352        7. Ensure that the device did not disconnect.
353        8. Remove the suggestions and ensure the device does not connect back.
354        """
355        self.add_suggestions_and_ensure_connection(
356            [self.wpa_psk_2g], self.wpa_psk_2g[WifiEnums.SSID_KEY], False)
357
358        mod_suggestion = self.wpa_psk_2g
359
360        # Mark the network metered.
361        self.dut.log.debug("Marking suggestion as metered")
362        mod_suggestion[WifiEnums.IS_SUGGESTION_METERED] = True
363        asserts.assert_true(
364            self.dut.droid.wifiAddNetworkSuggestions([mod_suggestion]),
365            "Failed to add suggestions")
366        # Wait for disconnect.
367        wutils.wait_for_disconnect(self.dut)
368        self.dut.log.info("Disconnected from network %s", mod_suggestion)
369        self.dut.ed.clear_all_events()
370        # Wait for reconnect.
371        wutils.wait_for_connect(self.dut, mod_suggestion[WifiEnums.SSID_KEY])
372
373        # Mark the network unmetered.
374        self.dut.log.debug("Marking suggestion as unmetered")
375        mod_suggestion[WifiEnums.IS_SUGGESTION_METERED] = False
376        asserts.assert_true(
377            self.dut.droid.wifiAddNetworkSuggestions([mod_suggestion]),
378            "Failed to add suggestions")
379        # Ensure there is no disconnect.
380        wutils.ensure_no_disconnect(self.dut)
381        self.dut.ed.clear_all_events()
382
383        self.remove_suggestions_disconnect_and_ensure_no_connection_back(
384            [mod_suggestion], mod_suggestion[WifiEnums.SSID_KEY])
385
386    @test_tracker_info(uuid="f54bc250-d9e9-4f00-8b5b-b866e8550b43")
387    def test_connect_to_highest_priority(self):
388        """
389        Adds network suggestions and ensures that device connects to
390        the suggestion with the highest priority.
391
392        Steps:
393        1. Send 2 network suggestions to the device (with different priorities).
394        2. Wait for the device to connect to the network with the highest
395           priority.
396        3. In-place modify network suggestions with priorities reversed
397        4. Restart wifi, wait for the device to connect to the network with the highest
398           priority.
399        5. Re-add the suggestions with the priorities reversed again.
400        6. Again wait for the device to connect to the network with the highest
401           priority.
402        """
403        network_suggestion_2g = self.wpa_psk_2g
404        network_suggestion_5g = self.wpa_psk_5g
405
406        # Add suggestions & wait for the connection event.
407        network_suggestion_2g[WifiEnums.PRIORITY] = 5
408        network_suggestion_5g[WifiEnums.PRIORITY] = 2
409        self.add_suggestions_and_ensure_connection(
410            [network_suggestion_2g, network_suggestion_5g],
411            self.wpa_psk_2g[WifiEnums.SSID_KEY], None)
412
413        # In-place modify Reverse the priority, should be no disconnect
414        network_suggestion_2g[WifiEnums.PRIORITY] = 2
415        network_suggestion_5g[WifiEnums.PRIORITY] = 5
416        self.dut.log.info("Modifying network suggestions")
417        asserts.assert_true(
418            self.dut.droid.wifiAddNetworkSuggestions(
419                [network_suggestion_2g, network_suggestion_5g]),
420            "Failed to add suggestions")
421        wutils.ensure_no_disconnect(self.dut)
422
423        # Disable and re-enable wifi, should connect to higher priority
424        wutils.wifi_toggle_state(self.dut, False)
425        time.sleep(DEFAULT_TIMEOUT)
426        wutils.wifi_toggle_state(self.dut, True)
427        wutils.start_wifi_connection_scan_and_return_status(self.dut)
428        wutils.wait_for_connect(self.dut, self.wpa_psk_5g[WifiEnums.SSID_KEY])
429
430        self.remove_suggestions_disconnect_and_ensure_no_connection_back(
431            [], self.wpa_psk_5g[WifiEnums.SSID_KEY])
432
433        # Reverse the priority.
434        # Add suggestions & wait for the connection event.
435        network_suggestion_2g[WifiEnums.PRIORITY] = 5
436        network_suggestion_5g[WifiEnums.PRIORITY] = 2
437        self.add_suggestions_and_ensure_connection(
438            [network_suggestion_2g, network_suggestion_5g],
439            self.wpa_psk_2g[WifiEnums.SSID_KEY], None)
440
441    @test_tracker_info(uuid="b1d27eea-23c8-4c4f-b944-ef118e4cc35f")
442    def test_connect_to_wpa_psk_2g_with_post_connection_broadcast(self):
443        """ Adds a network suggestion and ensure that the device connected.
444
445        Steps:
446        1. Send a network suggestion to the device with
447           isAppInteractionRequired set.
448        2. Wait for the device to connect to it.
449        3. Ensure that we did receive the post connection broadcast
450           (isAppInteractionRequired = True).
451        4. Remove the suggestions and ensure the device does not connect back.
452        """
453        network_suggestion = self.wpa_psk_2g
454        network_suggestion[WifiEnums.IS_APP_INTERACTION_REQUIRED] = True
455        self.add_suggestions_and_ensure_connection(
456            [network_suggestion], self.wpa_psk_2g[WifiEnums.SSID_KEY], True)
457        self.remove_suggestions_disconnect_and_ensure_no_connection_back(
458            [self.wpa_psk_2g], self.wpa_psk_2g[WifiEnums.SSID_KEY])
459
460    @test_tracker_info(uuid="a036a24d-29c0-456d-ae6a-afdde34da710")
461    def test_connect_to_wpa_psk_5g_reboot_config_store(self):
462        """
463        Adds a network suggestion and ensure that the device connects to it
464        after reboot.
465
466        Steps:
467        1. Send a network suggestion to the device.
468        2. Wait for the device to connect to it.
469        3. Ensure that we did not receive the post connection broadcast
470           (isAppInteractionRequired = False).
471        4. Reboot the device.
472        5. Wait for the device to connect to back to it.
473        6. Remove the suggestions and ensure the device does not connect back.
474        7. Reboot the device again, ensure user approval is kept
475        """
476        self._test_connect_to_wifi_network_reboot_config_store(
477            [self.wpa_psk_5g], self.wpa_psk_5g)
478
479    @test_tracker_info(uuid="61649a2b-0f00-4272-9b9b-40ad5944da31")
480    def test_connect_to_wpa_ent_config_aka_reboot_config_store(self):
481        """
482        Adds a network suggestion and ensure that the device connects to it
483        after reboot.
484
485        Steps:
486        1. Send a Enterprise AKA network suggestion to the device.
487        2. Wait for the device to connect to it.
488        3. Ensure that we did not receive the post connection broadcast.
489        4. Reboot the device.
490        5. Wait for the device to connect to the wifi network.
491        6. Remove suggestions and ensure device doesn't connect back to it.
492        7. Reboot the device again, ensure user approval is kept
493        """
494        self.config_aka = {
495            Ent.EAP: int(EAP.AKA),
496            WifiEnums.SSID_KEY: self.ent_network_2g[WifiEnums.SSID_KEY],
497            "carrierId": str(self.dut.droid.telephonyGetSimCarrierId()),
498        }
499        if "carrierId" in self.config_aka:
500            self.set_carrier_approved(self.config_aka["carrierId"], True)
501        self._test_connect_to_wifi_network_reboot_config_store(
502            [self.config_aka], self.ent_network_2g)
503        if "carrierId" in self.config_aka:
504            self.clear_carrier_approved(self.config_aka["carrierId"])
505
506    @test_tracker_info(uuid="98b2d40a-acb4-4a2f-aba1-b069e2a1d09d")
507    def test_connect_to_wpa_ent_config_ttls_pap_reboot_config_store(self):
508        """
509        Adds a network suggestion and ensure that the device connects to it
510        after reboot.
511
512        Steps:
513        1. Send a Enterprise TTLS PAP network suggestion to the device.
514        2. Wait for the device to connect to it.
515        3. Ensure that we did not receive the post connection broadcast.
516        4. Reboot the device.
517        5. Wait for the device to connect to the wifi network.
518        6. Remove suggestions and ensure device doesn't connect back to it.
519        7. Reboot the device again, ensure user approval is kept
520        """
521        self.config_ttls = {
522            Ent.EAP: int(EAP.TTLS),
523            Ent.CA_CERT: self.ca_cert,
524            Ent.IDENTITY: self.eap_identity,
525            Ent.PASSWORD: self.eap_password,
526            Ent.PHASE2: int(EapPhase2.MSCHAPV2),
527            WifiEnums.SSID_KEY: self.ent_network_2g[WifiEnums.SSID_KEY],
528            Ent.DOM_SUFFIX_MATCH: self.domain_suffix_match,
529        }
530        config = dict(self.config_ttls)
531        config[WifiEnums.Enterprise.PHASE2] = WifiEnums.EapPhase2.PAP.value
532
533        self._test_connect_to_wifi_network_reboot_config_store(
534            [config], self.ent_network_2g)
535
536    @test_tracker_info(uuid="554b5861-22d0-4922-a5f4-712b4cf564eb")
537    def test_fail_to_connect_to_wpa_psk_5g_when_not_approved(self):
538        """
539        Adds a network suggestion and ensure that the device does not
540        connect to it until we approve the app.
541
542        Steps:
543        1. Send a network suggestion to the device with the app not approved.
544        2. Ensure the network is present in scan results, but we don't connect
545           to it.
546        3. Now approve the app.
547        4. Wait for the device to connect to it.
548        """
549        self.dut.log.info("Adding network suggestions")
550        asserts.assert_true(
551            self.dut.droid.wifiAddNetworkSuggestions([self.wpa_psk_5g]),
552            "Failed to add suggestions")
553
554        # Disable suggestions by the app.
555        self.set_approved(False)
556
557        # Ensure the app is not approved.
558        asserts.assert_false(self.is_approved(),
559                             "Suggestions should be disabled")
560
561        # Start a new scan to trigger auto-join.
562        wutils.start_wifi_connection_scan_and_ensure_network_found(
563            self.dut, self.wpa_psk_5g[WifiEnums.SSID_KEY])
564
565        # Ensure we don't connect to the network.
566        asserts.assert_false(
567            wutils.wait_for_connect(self.dut,
568                                    self.wpa_psk_5g[WifiEnums.SSID_KEY],
569                                    assert_on_fail=False),
570            "Should not connect to network suggestions from unapproved app")
571
572        self.dut.log.info("Enabling suggestions from test")
573        # Now Enable suggestions by the app & ensure we connect to the network.
574        self.set_approved(True)
575
576        # Ensure the app is approved.
577        asserts.assert_true(self.is_approved(),
578                            "Suggestions should be enabled")
579
580        # Start a new scan to trigger auto-join.
581        wutils.start_wifi_connection_scan_and_ensure_network_found(
582            self.dut, self.wpa_psk_5g[WifiEnums.SSID_KEY])
583
584        wutils.wait_for_connect(self.dut, self.wpa_psk_5g[WifiEnums.SSID_KEY])
585
586    @test_tracker_info(uuid="98400dea-776e-4a0a-9024-18845b27331c")
587    def test_fail_to_connect_to_wpa_psk_2g_after_user_forgot_network(self):
588        """
589        Adds a network suggestion and ensures that the device does not
590        connect to it after the user forgot the network previously.
591
592        Steps:
593        1. Send a network suggestion to the device with
594           isAppInteractionRequired set.
595        2. Wait for the device to connect to it.
596        3. Ensure that we did receive the post connection broadcast
597           (isAppInteractionRequired = True).
598        4. Simulate user forgetting the network and the device does not
599           connecting back even though the suggestion is active from the app.
600        """
601        network_suggestion = self.wpa_psk_2g
602        network_suggestion[WifiEnums.IS_APP_INTERACTION_REQUIRED] = True
603        self.add_suggestions_and_ensure_connection(
604            [network_suggestion], self.wpa_psk_2g[WifiEnums.SSID_KEY], True)
605
606        # Simulate user disconnect the network.
607        self.dut.droid.wifiUserDisconnectNetwork(
608            self.wpa_psk_2g[WifiEnums.SSID_KEY])
609        wutils.wait_for_disconnect(self.dut)
610        self.dut.log.info("Disconnected from network %s", self.wpa_psk_2g)
611        self.dut.ed.clear_all_events()
612
613        # Now ensure that we don't connect back even though the suggestion
614        # is still active.
615        asserts.assert_false(
616            wutils.wait_for_connect(self.dut,
617                                    self.wpa_psk_2g[WifiEnums.SSID_KEY],
618                                    assert_on_fail=False),
619            "Device should not connect back")
620
621    @test_tracker_info(uuid="93c86b05-fa56-4d79-ad27-009a16f691b1")
622    def test_connect_to_hidden_network(self):
623        """
624        Adds a network suggestion with hidden SSID config, ensure device can scan
625        and connect to this network.
626
627        Steps:
628        1. Send a hidden network suggestion to the device.
629        2. Wait for the device to connect to it.
630        3. Ensure that we did not receive the post connection broadcast
631           (isAppInteractionRequired = False).
632        4. Remove the suggestions and ensure the device does not connect back.
633        """
634        asserts.skip_if(not hasattr(self, "hidden_networks"),
635                        "No hidden networks, skip this test")
636
637        network_suggestion = self.hidden_network
638        self.add_suggestions_and_ensure_connection(
639            [network_suggestion], network_suggestion[WifiEnums.SSID_KEY],
640            False)
641        self.remove_suggestions_disconnect_and_ensure_no_connection_back(
642            [network_suggestion], network_suggestion[WifiEnums.SSID_KEY])
643
644    @test_tracker_info(uuid="806dff14-7543-482b-bd0a-598de59374b3")
645    def test_connect_to_passpoint_network_with_post_connection_broadcast(self):
646        """ Adds a passpoint network suggestion and ensure that the device connected.
647
648        Steps:
649        1. Send a network suggestion to the device.
650        2. Wait for the device to connect to it.
651        3. Ensure that we did receive the post connection broadcast
652               (isAppInteractionRequired = true).
653        4. Remove the suggestions and ensure the device does not connect back.
654        """
655        asserts.skip_if(not hasattr(self, "passpoint_networks"),
656                        "No passpoint networks, skip this test")
657        passpoint_config = self.passpoint_network
658        passpoint_config[WifiEnums.IS_APP_INTERACTION_REQUIRED] = True
659        if "carrierId" in passpoint_config:
660            self.set_carrier_approved(passpoint_config["carrierId"], True)
661        self.add_suggestions_and_ensure_connection(
662            [passpoint_config], passpoint_config[WifiEnums.SSID_KEY], True)
663        self.remove_suggestions_disconnect_and_ensure_no_connection_back(
664            [passpoint_config], passpoint_config[WifiEnums.SSID_KEY])
665        if "carrierId" in passpoint_config:
666            self.clear_carrier_approved(passpoint_config["carrierId"])
667
668    @test_tracker_info(uuid="159b8b8c-fb00-4d4e-a29f-606881dcbf44")
669    def test_connect_to_passpoint_network_reboot_config_store(self):
670        """
671        Adds a passpoint network suggestion and ensure that the device connects to it
672        after reboot.
673
674        Steps:
675        1. Send a network suggestion to the device.
676        2. Wait for the device to connect to it.
677        3. Ensure that we did not receive the post connection broadcast
678           (isAppInteractionRequired = False).
679        4. Reboot the device.
680        5. Wait for the device to connect to back to it.
681        6. Remove the suggestions and ensure the device does not connect back.
682        7. Reboot the device again, ensure user approval is kept
683        """
684        asserts.skip_if(not hasattr(self, "passpoint_networks"),
685                        "No passpoint networks, skip this test")
686        passpoint_config = self.passpoint_network
687        if "carrierId" in passpoint_config:
688            self.set_carrier_approved(passpoint_config["carrierId"], True)
689        self._test_connect_to_wifi_network_reboot_config_store(
690            [passpoint_config], passpoint_config)
691        if "carrierId" in passpoint_config:
692            self.clear_carrier_approved(passpoint_config["carrierId"])
693
694    @test_tracker_info(uuid="34f3d28a-bedf-43fe-a12d-2cfadf6bc6eb")
695    def test_fail_to_connect_to_passpoint_network_when_not_approved(self):
696        """
697        Adds a passpoint network suggestion and ensure that the device does not
698        connect to it until we approve the app.
699
700        Steps:
701        1. Send a network suggestion to the device with the app not approved.
702        2. Ensure the network is present in scan results, but we don't connect
703           to it.
704        3. Now approve the app.
705        4. Wait for the device to connect to it.
706        """
707        asserts.skip_if(not hasattr(self, "passpoint_networks"),
708                        "No passpoint networks, skip this test")
709        passpoint_config = self.passpoint_network
710        if "carrierId" in passpoint_config:
711            self.set_carrier_approved(passpoint_config["carrierId"], True)
712        self.dut.log.info("Adding network suggestions")
713        asserts.assert_true(
714            self.dut.droid.wifiAddNetworkSuggestions([passpoint_config]),
715            "Failed to add suggestions")
716
717        # Disable suggestions by the app.
718        self.set_approved(False)
719
720        # Ensure the app is not approved.
721        asserts.assert_false(self.is_approved(),
722                             "Suggestions should be disabled")
723
724        # Start a new scan to trigger auto-join.
725        wutils.start_wifi_connection_scan_and_ensure_network_found(
726            self.dut, passpoint_config[WifiEnums.SSID_KEY])
727
728        # Ensure we don't connect to the network.
729        asserts.assert_false(
730            wutils.wait_for_connect(self.dut,
731                                    passpoint_config[WifiEnums.SSID_KEY],
732                                    assert_on_fail=False),
733            "Should not connect to network suggestions from unapproved app")
734
735        self.dut.log.info("Enabling suggestions from test")
736        # Now Enable suggestions by the app & ensure we connect to the network.
737        self.set_approved(True)
738
739        # Ensure the app is approved.
740        asserts.assert_true(self.is_approved(),
741                            "Suggestions should be enabled")
742
743        # Start a new scan to trigger auto-join.
744        wutils.start_wifi_connection_scan_and_ensure_network_found(
745            self.dut, passpoint_config[WifiEnums.SSID_KEY])
746        time.sleep(PASSPOINT_TIMEOUT)
747        wutils.wait_for_connect(self.dut, passpoint_config[WifiEnums.SSID_KEY])
748        if "carrierId" in passpoint_config:
749            self.clear_carrier_approved(passpoint_config["carrierId"])
750
751    @test_tracker_info(uuid="cf624cda-4d25-42f1-80eb-6c717fb08338")
752    def test_fail_to_connect_to_passpoint_network_when_imsi_protection_exemption_not_approved(
753            self):
754        """
755        Adds a passpoint network suggestion using SIM credential without IMSI privacy protection.
756        Before user approves the exemption, ensure that the device does noconnect to it until we
757        approve the carrier exemption.
758
759        Steps:
760        1. Send a network suggestion to the device with IMSI protection exemption not approved.
761        2. Ensure the network is present in scan results, but we don't connect
762           to it.
763        3. Now approve the carrier.
764        4. Wait for the device to connect to it.
765        """
766        asserts.skip_if(not hasattr(self, "passpoint_networks"),
767                        "No passpoint networks, skip this test")
768        passpoint_config = self.passpoint_networks[ATT]
769        passpoint_config[WifiEnums.SSID_KEY] = self.passpoint_networks[ATT][
770            WifiEnums.SSID_KEY][0]
771        asserts.skip_if("carrierId" not in passpoint_config,
772                        "Not a SIM based passpoint network, skip this test")
773
774        # Ensure the carrier is not approved.
775        asserts.assert_false(
776            self.is_carrier_approved(passpoint_config["carrierId"]),
777            "Carrier shouldn't be approved")
778
779        self.dut.log.info("Adding network suggestions")
780        asserts.assert_true(
781            self.dut.droid.wifiAddNetworkSuggestions([passpoint_config]),
782            "Failed to add suggestions")
783
784        # Start a new scan to trigger auto-join.
785        wutils.start_wifi_connection_scan_and_ensure_network_found(
786            self.dut, passpoint_config[WifiEnums.SSID_KEY])
787
788        # Ensure we don't connect to the network.
789        asserts.assert_false(
790            wutils.wait_for_connect(self.dut,
791                                    passpoint_config[WifiEnums.SSID_KEY],
792                                    assert_on_fail=False),
793            "Should not connect to network suggestions from unapproved app")
794
795        self.dut.log.info("Enabling suggestions from test")
796        # Now approve IMSI protection exemption by carrier & ensure we connect to the network.
797        self.set_carrier_approved(passpoint_config["carrierId"], True)
798
799        # Ensure the carrier is approved.
800        asserts.assert_true(
801            self.is_carrier_approved(passpoint_config["carrierId"]),
802            "Carrier should be approved")
803
804        # Start a new scan to trigger auto-join.
805        wutils.start_wifi_connection_scan_and_ensure_network_found(
806            self.dut, passpoint_config[WifiEnums.SSID_KEY])
807        time.sleep(PASSPOINT_TIMEOUT)
808        wutils.wait_for_connect(self.dut, passpoint_config[WifiEnums.SSID_KEY])
809        self.clear_carrier_approved(passpoint_config["carrierId"])
810
811    @test_tracker_info(uuid="e35f99c8-78a4-4b96-9258-f9834b6ddd33")
812    def test_initial_auto_join_on_network_suggestion(self):
813        """
814        Add a network suggestion with enableAutojoin bit set to false, ensure the device doesn't
815        auto connect to this network
816
817        Steps:
818        1. Create a network suggestion.
819        2. Set EnableAutojoin to false.
820        3. Add this suggestion
821        4. Ensure device doesn't connect to his network
822        """
823        network_suggestion = self.wpa_psk_5g
824        # Set suggestion auto join initial to false.
825        network_suggestion[AutoJoin] = False
826        self.dut.log.info("Adding network suggestions")
827        asserts.assert_true(
828            self.dut.droid.wifiAddNetworkSuggestions([network_suggestion]),
829            "Failed to add suggestions")
830        # Enable suggestions by the app.
831        self.dut.log.debug("Enabling suggestions from test")
832        self.set_approved(True)
833        wutils.start_wifi_connection_scan_and_return_status(self.dut)
834        asserts.assert_false(
835            wutils.wait_for_connect(self.dut,
836                                    network_suggestion[WifiEnums.SSID_KEY],
837                                    assert_on_fail=False),
838            "Device should not connect.")
839
840    @test_tracker_info(uuid="ff4e451f-a380-4ff5-a5c2-dd9b1633d5e5")
841    def test_user_override_auto_join_on_network_suggestion(self):
842        """
843        Add a network suggestion, user change the auto join to false, ensure the device doesn't
844        auto connect to this network
845
846        Steps:
847        1. Create a network suggestion.
848        2. Add this suggestion, and ensure we connect to this network
849        3. Simulate user change the auto join to false.
850        4. Toggle the Wifi off and on
851        4. Ensure device doesn't connect to his network
852        """
853        network_suggestion = self.wpa_psk_5g
854        self.add_suggestions_and_ensure_connection(
855            [network_suggestion], network_suggestion[WifiEnums.SSID_KEY],
856            False)
857        wifi_info = self.dut.droid.wifiGetConnectionInfo()
858        self.dut.log.info(wifi_info)
859        network_id = wifi_info[WifiEnums.NETID_KEY]
860        # Simulate user disable auto join through Settings.
861        self.dut.log.info("Disable auto join on suggestion")
862        self.dut.droid.wifiEnableAutojoin(network_id, False)
863        wutils.wifi_toggle_state(self.dut, False)
864        wutils.wifi_toggle_state(self.dut, True)
865        asserts.assert_false(
866            wutils.wait_for_connect(self.dut,
867                                    network_suggestion[WifiEnums.SSID_KEY],
868                                    assert_on_fail=False),
869            "Device should not connect.")
870
871    @test_tracker_info(uuid="32201b1c-76a0-46dc-9983-2cd24312a783")
872    def test_untrusted_suggestion_without_untrusted_request(self):
873        """
874        Add an untrusted network suggestion, when no untrusted request, will not connect to it.
875        Steps:
876        1. Create a untrusted network suggestion.
877        2. Add this suggestion, and ensure device do not connect to this network
878        3. Request untrusted network and ensure device connect to this network
879        """
880        network_suggestion = self.open_5g
881        network_suggestion[Untrusted] = True
882        self.dut.log.info("Adding network suggestions")
883        asserts.assert_true(
884            self.dut.droid.wifiAddNetworkSuggestions([network_suggestion]),
885            "Failed to add suggestions")
886        # Start a new scan to trigger auto-join.
887        wutils.start_wifi_connection_scan_and_ensure_network_found(
888            self.dut, network_suggestion[WifiEnums.SSID_KEY])
889
890        # Ensure we don't connect to the network.
891        asserts.assert_false(
892            wutils.wait_for_connect(self.dut,
893                                    network_suggestion[WifiEnums.SSID_KEY],
894                                    assert_on_fail=False),
895            "Should not connect to untrusted network suggestions with no request"
896        )
897        network_request = {ClearCapabilities: True, TransportType: 1}
898        req_key = self.dut.droid.connectivityRequestNetwork(network_request)
899
900        # Start a new scan to trigger auto-join.
901        wutils.start_wifi_connection_scan_and_ensure_network_found(
902            self.dut, network_suggestion[WifiEnums.SSID_KEY])
903
904        wutils.wait_for_connect(self.dut,
905                                network_suggestion[WifiEnums.SSID_KEY],
906                                assert_on_fail=False)
907
908        self.dut.droid.connectivityUnregisterNetworkCallback(req_key)
909