Merge "conman:  Experiment to prevent joining the WLAN on 2.4 GHz."
diff --git a/conman/connection_manager.py b/conman/connection_manager.py
index e7ab9af..a312b2c 100755
--- a/conman/connection_manager.py
+++ b/conman/connection_manager.py
@@ -19,11 +19,15 @@
 import pyinotify
 
 import cycler
+import experiment
 import interface
 import iw
 import status
 
 
+experiment.register('WifiNo2GClient')
+
+
 class FileChangeHandler(pyinotify.ProcessEvent):
   """Connects pyinotify events to ConnectionManager."""
 
@@ -135,11 +139,24 @@
 
   def start_client(self):
     """Join the WLAN as a client."""
+    if experiment.enabled('WifiNo2GClient') and self.band == '2.4':
+      logging.debug('WifiNo2GClient enabled; not starting 2.4 GHz client.')
+      return
+
     up = self.client_up
     if up:
       logging.debug('Wifi client already started on %s GHz', self.band)
       return
 
+    if self._actually_start_client():
+      self._post_start_client()
+
+  def _actually_start_client(self):
+    """Actually run wifi setclient.
+
+    Returns:
+      Whether the command succeeded.
+    """
     command = self.WIFI_SETCLIENT + ['--ssid', self.ssid, '--band', self.band]
     env = dict(os.environ)
     if self.passphrase:
@@ -149,8 +166,11 @@
       subprocess.check_output(command, stderr=subprocess.STDOUT, env=env)
     except subprocess.CalledProcessError as e:
       logging.error('Failed to start wifi client: %s', e.output)
-      return
+      return False
 
+    return True
+
+  def _post_start_client(self):
     self._status.connected_to_wlan = True
     logging.info('Started wifi client on %s GHz', self.band)
     self.wifi.attach_wpa_control(self._wpa_control_interface)
diff --git a/conman/connection_manager_test.py b/conman/connection_manager_test.py
index 5e5911c..db8855d 100755
--- a/conman/connection_manager_test.py
+++ b/conman/connection_manager_test.py
@@ -9,6 +9,7 @@
 import time
 
 import connection_manager
+import experiment_testutils
 import interface_test
 import iw
 import status
@@ -180,22 +181,23 @@
   WIFI_SETCLIENT = ['echo', 'setclient']
   WIFI_STOPCLIENT = ['echo', 'stopclient']
 
-  def start_client(self):
-    client_was_up = self.client_up
-    was_attached = self.wifi.attached()
+  def _actually_start_client(self):
+    self.client_was_up = self.client_up
+    self.was_attached = self.wifi.attached()
     self.wifi._secure_testonly = True
     # Do this before calling the super method so that the attach call at the end
     # succeeds.
-    if not client_was_up and not was_attached:
+    if not self.client_was_up and not self.was_attached:
       self.wifi._initial_ssid_testonly = self.ssid
       self.wifi.start_wpa_supplicant_testonly(self._wpa_control_interface)
 
-    super(WLANConfiguration, self).start_client()
+    return True
 
-    if not client_was_up:
+  def _post_start_client(self):
+    if not self.client_was_up:
       self.wifi.set_connection_check_result('succeed')
 
-      if was_attached:
+      if self.was_attached:
         self.wifi._wpa_control.ssid_testonly = self.ssid
         self.wifi._wpa_control.secure_testonly = True
         self.wifi.add_connected_event()
@@ -1168,5 +1170,29 @@
                 in c._binwifi_commands)
 
 
+@wvtest.wvtest
+@connection_manager_test(WIFI_SHOW_OUTPUT_MARVELL8897)
+def connection_manager_conman_no_2g_wlan(c):
+  unused_raii = experiment_testutils.MakeExperimentDirs()
+
+  # First, establish that we connect on 2.4 without the experiment, to make sure
+  # this test doesn't spuriously pass.
+  c.write_wlan_config('2.4', 'my ssid', 'my psk')
+  c.run_once()
+  wvtest.WVPASS(c.client_up('2.4'))
+
+  # Now, force a disconnect by deleting the config.
+  c.delete_wlan_config('2.4')
+  c.run_once()
+  wvtest.WVFAIL(c.client_up('2.4'))
+
+  # Now enable the experiment, recreate the config, and make sure we don't
+  # connect.
+  experiment_testutils.enable('WifiNo2GClient')
+  c.write_wlan_config('2.4', 'my ssid', 'my psk')
+  c.run_once()
+  wvtest.WVFAIL(c.client_up('2.4'))
+
+
 if __name__ == '__main__':
   wvtest.wvtest_main()