Merge "conman:  Maintain /tmp/hosts."
diff --git a/conman/connection_manager.py b/conman/connection_manager.py
index 5abadd3..7ff526a 100755
--- a/conman/connection_manager.py
+++ b/conman/connection_manager.py
@@ -97,7 +97,7 @@
       raise ValueError('Command file does not specify SSID')
 
     if self.wifi.initial_ssid == self.ssid:
-      logging.debug('Connected to WLAN at startup')
+      logging.info('Connected to WLAN at startup')
 
   @property
   def client_up(self):
@@ -121,7 +121,7 @@
     try:
       subprocess.check_output(self.command, stderr=subprocess.STDOUT)
       self.access_point_up = True
-      logging.debug('Started %s GHz AP', self.band)
+      logging.info('Started %s GHz AP', self.band)
     except subprocess.CalledProcessError as e:
       logging.error('Failed to start access point: %s', e.output)
 
@@ -136,7 +136,7 @@
     try:
       subprocess.check_output(command, stderr=subprocess.STDOUT)
       self.access_point_up = False
-      logging.debug('Stopped %s GHz AP', self.band)
+      logging.info('Stopped %s GHz AP', self.band)
     except subprocess.CalledProcessError as e:
       logging.error('Failed to stop access point: %s', e.output)
       return
@@ -144,7 +144,7 @@
   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.')
+      logging.info('WifiNo2GClient enabled; not starting 2.4 GHz client.')
       return
 
     up = self.client_up
@@ -191,7 +191,7 @@
                               stderr=subprocess.STDOUT)
       # TODO(rofrankel): Make this work for dual-radio devices.
       self._status.connected_to_wlan = False
-      logging.debug('Stopped wifi client on %s GHz', self.band)
+      logging.info('Stopped wifi client on %s GHz', self.band)
     except subprocess.CalledProcessError as e:
       logging.error('Failed to stop wifi client: %s', e.output)
 
@@ -322,7 +322,7 @@
     # the routing table.
     for ifc in [self.bridge] + self.wifi:
       ifc.initialize()
-      logging.debug('%s initialized', ifc.name)
+      logging.info('%s initialized', ifc.name)
 
     self._interface_update_counter = 0
     self._try_wlan_after = {'5': 0, '2.4': 0}
@@ -453,7 +453,7 @@
       if self._connected_to_wlan(wifi):
         self._status.connected_to_wlan = True
         logging.debug('Connected to WLAN on %s, nothing else to do.', wifi.name)
-        return
+        break
 
       # This interface is not connected to the WLAN, so scan for potential
       # routes to the ACS for provisioning.
@@ -471,10 +471,10 @@
       for band in wifi.bands:
         wlan_configuration = self._wlan_configuration.get(band, None)
         if wlan_configuration and time.time() > self._try_wlan_after[band]:
-          logging.debug('Trying to join WLAN on %s.', wifi.name)
+          logging.info('Trying to join WLAN on %s.', wifi.name)
           wlan_configuration.start_client()
           if self._connected_to_wlan(wifi):
-            logging.debug('Joined WLAN on %s.', wifi.name)
+            logging.info('Joined WLAN on %s.', wifi.name)
             self._status.connected_to_wlan = True
             self._try_wlan_after[band] = 0
             break
@@ -640,7 +640,7 @@
       if filename == self.ETHERNET_STATUS_FILE:
         try:
           self.bridge.ethernet = bool(int(contents))
-          logging.debug('Ethernet %s', 'up' if self.bridge.ethernet else 'down')
+          logging.info('Ethernet %s', 'up' if self.bridge.ethernet else 'down')
         except ValueError:
           logging.error('Status file contents should be 0 or 1, not %s',
                         contents)
@@ -663,7 +663,7 @@
           wifi = self.wifi_for_band(band)
           if wifi and band in self._wlan_configuration:
             self._wlan_configuration[band].access_point = True
-          logging.debug('AP enabled for %s GHz', band)
+          logging.info('AP enabled for %s GHz', band)
 
     elif path == self._tmp_dir:
       if filename.startswith(self.GATEWAY_FILE_PREFIX):
@@ -671,8 +671,8 @@
         ifc = self.interface_by_name(interface_name)
         if ifc:
           ifc.set_gateway_ip(contents)
-          logging.debug('Received gateway %r for interface %s', contents,
-                        ifc.name)
+          logging.info('Received gateway %r for interface %s', contents,
+                       ifc.name)
 
     elif path == self._moca_tmp_dir:
       match = re.match(r'^%s\d+$' % self.MOCA_NODE_FILE_PREFIX, filename)
@@ -746,8 +746,8 @@
     last_successful_bss_info = getattr(wifi, 'last_successful_bss_info', None)
     bss_info = last_successful_bss_info or wifi.cycler.next()
     if bss_info is not None:
-      logging.debug('Attempting to connect to SSID %s for provisioning',
-                    bss_info.ssid)
+      logging.info('Attempting to connect to SSID %s for provisioning',
+                   bss_info.ssid)
       self._status.trying_open = True
       connected = self._try_bssid(wifi, bss_info)
       if connected:
@@ -798,7 +798,7 @@
         wlan_configuration.access_point = os.path.exists(ap_file)
       self._wlan_configuration[band] = wlan_configuration
       self._status.have_config = True
-      logging.debug('Updated WLAN configuration for %s GHz', band)
+      logging.info('Updated WLAN configuration for %s GHz', band)
       self._update_access_point(wlan_configuration)
 
   def _update_access_point(self, wlan_configuration):
@@ -853,7 +853,7 @@
                             stderr=subprocess.STDOUT)
 
   def _try_upload_logs(self):
-    logging.debug('Attempting to upload logs')
+    logging.info('Attempting to upload logs')
     if subprocess.call(self.UPLOAD_LOGS_AND_WAIT) != 0:
       logging.error('Failed to upload logs')
 
diff --git a/conman/connection_manager_test.py b/conman/connection_manager_test.py
index 1a71f5c..26b3694 100755
--- a/conman/connection_manager_test.py
+++ b/conman/connection_manager_test.py
@@ -733,6 +733,8 @@
   wvtest.WVPASS(c.has_status_files([status.P.CONNECTED_TO_OPEN]))
   wvtest.WVPASSEQ(c.last_provisioning_attempt.ssid, 's3')
   wvtest.WVPASSEQ(c.last_provisioning_attempt.bssid, 'ff:ee:dd:cc:bb:aa')
+  # The log upload happens on the next main loop after joining s3.
+  c.run_once()
   wvtest.WVPASSEQ(c.log_upload_count, 2)
 
   # Now, recreate the same WLAN configuration, which should be connected to.
@@ -806,6 +808,7 @@
   wvtest.WVPASS(c.acs())
   # Make sure we didn't scan on `band`.
   wvtest.WVPASSEQ(scan_count_for_band, c.wifi_for_band(band).wifi_scan_counter)
+  c.run_once()
   wvtest.WVPASSEQ(c.log_upload_count, 3)
 
   # Now re-create the WLAN config, connect to the WLAN, and make sure that s3 is
@@ -849,6 +852,7 @@
     c.run_once()
   s2_bss = iw.BssInfo('01:23:45:67:89:ab', 's2')
   wvtest.WVPASSEQ(c.wifi_for_band(band).last_successful_bss_info, s2_bss)
+  c.run_once()
   wvtest.WVPASSEQ(c.log_upload_count, 4)
 
   c.s2_fail = True
@@ -1002,6 +1006,7 @@
   wvtest.WVFAIL(c.bridge.current_route())
   wvtest.WVPASS(c.wifi_for_band('2.4').current_route())
   wvtest.WVFAIL(c.wifi_for_band('5').current_route())
+  c.run_once()
   wvtest.WVPASSEQ(c.log_upload_count, 1)
 
 
@@ -1095,6 +1100,7 @@
   wvtest.WVFAIL(c.bridge.current_route())
   wvtest.WVPASS(c.wifi_for_band('2.4').current_route())
   wvtest.WVPASS(c.wifi_for_band('5').current_route())
+  c.run_once()
   wvtest.WVPASSEQ(c.log_upload_count, 1)
 
 
diff --git a/conman/interface.py b/conman/interface.py
index 8461f19..87a080f 100755
--- a/conman/interface.py
+++ b/conman/interface.py
@@ -58,18 +58,18 @@
     """
     # Until initialized, we want to act as if the interface is down.
     if not self._initialized:
-      logging.debug('%s not initialized; not running connection_check%s',
-                    self.name, ' (ACS)' if check_acs else '')
+      logging.info('%s not initialized; not running connection_check%s',
+                   self.name, ' (ACS)' if check_acs else '')
       return None
 
     if not self.links:
-      logging.debug('Connection check for %s failed due to no links', self.name)
+      logging.info('Connection check for %s failed due to no links', self.name)
       return False
 
     logging.debug('Gateway IP for %s is %s', self.name, self._gateway_ip)
     if self._gateway_ip is None:
-      logging.debug('Connection check for %s failed due to no gateway IP',
-                    self.name)
+      logging.info('Connection check%s for %s failed due to no gateway IP',
+                   ' (ACS)' if check_acs else '', self.name)
       return False
 
     # Temporarily add a route to make sure the connection check can be run.
@@ -91,10 +91,10 @@
 
     with open(os.devnull, 'w') as devnull:
       result = subprocess.call(cmd, stdout=devnull, stderr=devnull) == 0
-      logging.debug('Connection check%s for %s %s',
-                    ' (ACS)' if check_acs else '',
-                    self.name,
-                    'passed' if result else 'failed')
+      logging.info('Connection check%s for %s %s',
+                   ' (ACS)' if check_acs else '',
+                   self.name,
+                   'passed' if result else 'failed')
 
     # Delete the temporary route.
     if added_temporary_route:
@@ -176,8 +176,8 @@
 
   def _ip_route(self, *args):
     if not self._initialized:
-      logging.debug('Not initialized, not running %s %s',
-                    ' '.join(self.IP_ROUTE), ' '.join(args))
+      logging.info('Not initialized, not running %s %s',
+                   ' '.join(self.IP_ROUTE), ' '.join(args))
       return ''
 
     return self._really_ip_route(*args)
@@ -204,7 +204,7 @@
     return match and match.group('IP') or None
 
   def set_gateway_ip(self, gateway_ip):
-    logging.debug('New gateway IP %s for %s', gateway_ip, self.name)
+    logging.info('New gateway IP %s for %s', gateway_ip, self.name)
     self._gateway_ip = gateway_ip
     self.update_routes()
 
@@ -216,10 +216,10 @@
     had_links = bool(self.links)
 
     if is_up:
-      logging.debug('%s gained link %s', self.name, link)
+      logging.info('%s gained link %s', self.name, link)
       self.links.add(link)
     else:
-      logging.debug('%s lost link %s', self.name, link)
+      logging.info('%s lost link %s', self.name, link)
       self.links.remove(link)
 
     # If a link goes away, we may have lost access to something but not gained
@@ -332,9 +332,9 @@
     failure_s = self._acs_session_failure_s()
     if (experiment.enabled('WifiSimulateWireless')
         and failure_s < MAX_ACS_FAILURE_S):
-      logging.debug('WifiSimulateWireless: failing bridge connection check (no '
-                    'ACS contact for %d seconds, max %d seconds)',
-                    failure_s, MAX_ACS_FAILURE_S)
+      logging.info('WifiSimulateWireless: failing bridge connection check%s '
+                   '(no ACS contact for %d seconds, max %d seconds)',
+                   ' (ACS)' if check_acs else '', failure_s, MAX_ACS_FAILURE_S)
       return False
 
     return super(Bridge, self)._connection_check(check_acs)
diff --git a/wifi/autochannel.py b/wifi/autochannel.py
index 51b4d00..c669c9a 100644
--- a/wifi/autochannel.py
+++ b/wifi/autochannel.py
@@ -65,6 +65,12 @@
                      % (band, autotype, width))
 
 
+def get_all_frequencies(band):
+  """Get all 802.11 frequencies for the given band."""
+  return get_permitted_frequencies(band, 'OVERLAP' if band == '2.4' else 'ANY',
+                                   '20').split()
+
+
 def scan(interface, band, autotype, width):
   """Do an autochannel scan and return the recommended channel.
 
diff --git a/wifi/autochannel_test.py b/wifi/autochannel_test.py
index a53725f..7198cb5 100755
--- a/wifi/autochannel_test.py
+++ b/wifi/autochannel_test.py
@@ -22,5 +22,17 @@
     wvtest.WVEXCEPT(ValueError, autochannel.get_permitted_frequencies, *case)
 
 
+@wvtest.wvtest
+def get_all_frequencies_test():
+  wvtest.WVPASSEQ(['2412', '2417', '2422', '2427', '2432', '2437', '2442',
+                   '2447', '2452', '2457', '2462'],
+                  autochannel.get_all_frequencies('2.4'))
+
+  wvtest.WVPASSEQ(['5180', '5200', '5220', '5240', '5745', '5765', '5785',
+                   '5805', '5825', '5260', '5280', '5300', '5320', '5500',
+                   '5520', '5540', '5560', '5580', '5660', '5680', '5700'],
+                  autochannel.get_all_frequencies('5'))
+
+
 if __name__ == '__main__':
   wvtest.wvtest_main()
diff --git a/wifi/configs.py b/wifi/configs.py
index 3377a08..743fe10 100644
--- a/wifi/configs.py
+++ b/wifi/configs.py
@@ -6,6 +6,8 @@
 
 import Crypto.Protocol.KDF
 
+# pylint: disable=g-bad-import-order
+import autochannel
 import experiment
 import utils
 
@@ -373,10 +375,13 @@
                                utils.validate_and_sanitize_bssid(opt.bssid))
   network_block = make_network_block(network_block_lines)
 
+  freq_list = ','.join(autochannel.get_all_frequencies(opt.band))
+
   lines = [
       'ctrl_interface=/var/run/wpa_supplicant',
       'ap_scan=1',
       'autoscan=exponential:1:30',
+      'freq_list=' + freq_list,
       network_block
   ]
   return '\n'.join(lines)
diff --git a/wifi/configs_test.py b/wifi/configs_test.py
index ab5d6c7..64e05c6 100755
--- a/wifi/configs_test.py
+++ b/wifi/configs_test.py
@@ -10,27 +10,36 @@
 from wvtest import wvtest
 
 
+_FREQ_LIST = {
+    '2.4': '2412,2417,2422,2427,2432,2437,2442,2447,2452,2457,2462',
+    '5': ('5180,5200,5220,5240,5745,5765,5785,5805,5825,5260,5280,5300,5320,'
+          '5500,5520,5540,5560,5580,5660,5680,5700'),
+}
+
+
 _WPA_SUPPLICANT_CONFIG = """ctrl_interface=/var/run/wpa_supplicant
 ap_scan=1
 autoscan=exponential:1:30
-network={
+freq_list={freq_list}
+network={{
 \tssid="some ssid"
 \t#psk="some passphrase"
 \tpsk=41821f7ca3ea5d85beea7644ed7e0fefebd654177fa06c26fbdfdc3c599a317f
 \tscan_ssid=1
-}
+}}
 """
 
 _WPA_SUPPLICANT_CONFIG_BSSID = """ctrl_interface=/var/run/wpa_supplicant
 ap_scan=1
 autoscan=exponential:1:30
-network={
+freq_list={freq_list}
+network={{
 \tssid="some ssid"
 \t#psk="some passphrase"
 \tpsk=41821f7ca3ea5d85beea7644ed7e0fefebd654177fa06c26fbdfdc3c599a317f
 \tscan_ssid=1
 \tbssid=12:34:56:78:90:ab
-}
+}}
 """
 
 # pylint: disable=g-backslash-continuation
@@ -38,12 +47,13 @@
 """ctrl_interface=/var/run/wpa_supplicant
 ap_scan=1
 autoscan=exponential:1:30
-network={
+freq_list={freq_list}
+network={{
 \tssid="some ssid"
 \tkey_mgmt=NONE
 \tscan_ssid=1
 \tbssid=12:34:56:78:90:ab
-}
+}}
 """
 
 
@@ -54,24 +64,30 @@
         "Can't test generate_wpa_supplicant_config without wpa_passphrase.")
     return
 
-  opt = FakeOptDict()
-  config = configs.generate_wpa_supplicant_config(
-      'some ssid', 'some passphrase', opt)
-  wvtest.WVPASSEQ(_WPA_SUPPLICANT_CONFIG, config)
+  for band in ('2.4', '5'):
+    opt = FakeOptDict()
+    opt.band = band
+    got = configs.generate_wpa_supplicant_config(
+        'some ssid', 'some passphrase', opt)
+    want = _WPA_SUPPLICANT_CONFIG.format(freq_list=_FREQ_LIST[band])
+    wvtest.WVPASSEQ(want, got)
 
-  opt.bssid = 'TotallyNotValid'
-  wvtest.WVEXCEPT(utils.BinWifiException,
-                  configs.generate_wpa_supplicant_config,
-                  'some ssid', 'some passphrase', opt)
+    opt.bssid = 'TotallyNotValid'
+    wvtest.WVEXCEPT(utils.BinWifiException,
+                    configs.generate_wpa_supplicant_config,
+                    'some ssid', 'some passphrase', opt)
 
-  opt.bssid = '12:34:56:78:90:Ab'
-  config = configs.generate_wpa_supplicant_config(
-      'some ssid', 'some passphrase', opt)
-  wvtest.WVPASSEQ(_WPA_SUPPLICANT_CONFIG_BSSID, config)
+    opt.bssid = '12:34:56:78:90:Ab'
+    got = configs.generate_wpa_supplicant_config(
+        'some ssid', 'some passphrase', opt)
+    want = _WPA_SUPPLICANT_CONFIG_BSSID.format(freq_list=_FREQ_LIST[band])
+    wvtest.WVPASSEQ(want, got)
 
-  config = configs.generate_wpa_supplicant_config(
-      'some ssid', None, opt)
-  wvtest.WVPASSEQ(_WPA_SUPPLICANT_CONFIG_BSSID_UNSECURED, config)
+    got = configs.generate_wpa_supplicant_config(
+        'some ssid', None, opt)
+    want = _WPA_SUPPLICANT_CONFIG_BSSID_UNSECURED.format(
+        freq_list=_FREQ_LIST[band])
+    wvtest.WVPASSEQ(want, got)
 
 
 _PHY_INFO = """Wiphy phy0