Merge "Add WifiShortAggTimeout and WifiNoAggTimeout experiments."
diff --git a/conman/connection_manager.py b/conman/connection_manager.py
index 93d1bef..829fda4 100755
--- a/conman/connection_manager.py
+++ b/conman/connection_manager.py
@@ -97,7 +97,7 @@
     self.stop_client()
 
     try:
-      subprocess.check_call(self.command, stderr=subprocess.STDOUT)
+      subprocess.check_output(self.command, stderr=subprocess.STDOUT)
       self.access_point_up = True
       logging.debug('Started %s GHz AP', self.band)
     except subprocess.CalledProcessError as e:
@@ -112,7 +112,7 @@
       command += ['--interface_suffix', self.interface_suffix]
 
     try:
-      subprocess.check_call(command, stderr=subprocess.STDOUT)
+      subprocess.check_output(command, stderr=subprocess.STDOUT)
       self.access_point_up = False
       logging.debug('Stopped %s GHz AP', self.band)
     except subprocess.CalledProcessError as e:
@@ -132,7 +132,7 @@
     if self.passphrase:
       env['WIFI_CLIENT_PSK'] = self.passphrase
     try:
-      subprocess.check_call(command, stderr=subprocess.STDOUT, env=env)
+      subprocess.check_output(command, stderr=subprocess.STDOUT, env=env)
       self.client_up = True
       logging.info('Started wifi client on %s GHz', self.band)
     except subprocess.CalledProcessError as e:
@@ -146,7 +146,7 @@
     self.wifi.detach_wpa_control()
 
     try:
-      subprocess.check_call(self.WIFI_STOPCLIENT + ['-b', self.band],
+      subprocess.check_output(self.WIFI_STOPCLIENT + ['-b', self.band],
                             stderr=subprocess.STDOUT)
       self.client_up = False
       logging.debug('Stopped wifi client on %s GHz', self.band)
@@ -221,23 +221,6 @@
         os.makedirs(directory)
         logging.info('Created monitored directory: %s', directory)
 
-    # It is very important that we know whether ethernet is up.  So if the
-    # ethernet file doesn't exist for any reason when conman starts, check
-    # explicitly.
-    if os.path.exists(os.path.join(self._interface_status_dir,
-                                   self.ETHERNET_STATUS_FILE)):
-      self._process_file(self._interface_status_dir, self.ETHERNET_STATUS_FILE)
-    else:
-      ethernet_up = self.is_ethernet_up()
-      self.bridge.ethernet = ethernet_up
-      self.ifplugd_action('eth0', ethernet_up)
-
-    for path, prefix in ((self._moca_status_dir, self.MOCA_NODE_FILE_PREFIX),
-                         (self._status_dir, self.COMMAND_FILE_PREFIX),
-                         (self._status_dir, self.GATEWAY_FILE_PREFIX)):
-      for filepath in glob.glob(os.path.join(path, prefix + '*')):
-        self._process_file(path, os.path.split(filepath)[-1])
-
     wm = pyinotify.WatchManager()
     wm.add_watch(self._status_dir,
                  pyinotify.IN_CLOSE_WRITE | pyinotify.IN_MOVED_TO |
@@ -248,6 +231,27 @@
                  pyinotify.IN_CLOSE_WRITE | pyinotify.IN_MOVED_TO)
     self.notifier = pyinotify.Notifier(wm, FileChangeHandler(self), timeout=0)
 
+    # If the ethernet file doesn't exist for any reason when conman starts,
+    # check explicitly and run ifplugd.action to create the file.
+    if not os.path.exists(os.path.join(self._interface_status_dir,
+                                       self.ETHERNET_STATUS_FILE)):
+      ethernet_up = self.is_ethernet_up()
+      self.bridge.ethernet = ethernet_up
+      self.ifplugd_action('eth0', ethernet_up)
+
+    for path, prefix in ((self._status_dir, self.GATEWAY_FILE_PREFIX),
+                         (self._interface_status_dir, ''),
+                         (self._moca_status_dir, self.MOCA_NODE_FILE_PREFIX),
+                         (self._status_dir, self.COMMAND_FILE_PREFIX)):
+      for filepath in glob.glob(os.path.join(path, prefix + '*')):
+        self._process_file(path, os.path.split(filepath)[-1])
+
+    # Now that we've ready any existing state, it's okay to let interfaces touch
+    # the routing table.
+    for ifc in [self.bridge] + self.wifi:
+      ifc.initialize()
+      logging.debug('%s initialized', ifc.name)
+
     self._interface_update_counter = 0
     self._try_wlan_after = {'5': 0, '2.4': 0}
 
diff --git a/conman/interface.py b/conman/interface.py
index d814950..0a26959 100755
--- a/conman/interface.py
+++ b/conman/interface.py
@@ -38,6 +38,9 @@
     self._gateway_ip = None
     self.metric = metric
 
+    # Until this is set True, the routing table will not be touched.
+    self._initialized = False
+
   def _connection_check(self, check_acs):
     """Check this interface's connection status.
 
@@ -47,11 +50,17 @@
     Returns:
       Whether the connection is working.
     """
+    # 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 '')
+      return None
+
     if not self.links:
       logging.debug('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)
+    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)
@@ -160,6 +169,14 @@
     return result
 
   def _ip_route(self, *args):
+    if not self._initialized:
+      logging.debug('Not initialized, not running %s %s',
+                    ' '.join(self.IP_ROUTE), ' '.join(args))
+      return ''
+
+    return self._really_ip_route(*args)
+
+  def _really_ip_route(self, *args):
     try:
       logging.debug('%s calling ip route %s', self.name, ' '.join(args))
       return subprocess.check_output(self.IP_ROUTE + list(args))
@@ -236,6 +253,15 @@
     elif maybe_had_access and not has_access:
       self.delete_route()
 
+  def initialize(self):
+    """Tell the interface it has its initial state.
+
+    Until this is called, the interface won't run connection checks or touch the
+    routing table.
+    """
+    self._initialized = True
+    self.update_routes()
+
 
 class Bridge(Interface):
   """Represents the wired bridge."""
diff --git a/conman/interface_test.py b/conman/interface_test.py
index 9905fea..6368a83 100755
--- a/conman/interface_test.py
+++ b/conman/interface_test.py
@@ -30,7 +30,7 @@
     else:
       raise ValueError('Invalid fake connection_check script.')
 
-  def _ip_route(self, *args):
+  def _really_ip_route(self, *args):
     if not args:
       return '\n'.join(self.routing_table.values() +
                        ['1.2.3.4/24 dev %s proto kernel scope link' % self.name,
@@ -145,6 +145,11 @@
 
   b.add_moca_station(0)
   b.set_gateway_ip('192.168.1.1')
+  # Everything should fail because the interface is not initialized.
+  wvtest.WVFAIL(b.acs())
+  wvtest.WVFAIL(b.internet())
+  wvtest.WVFAIL(b.current_route())
+  b.initialize()
   wvtest.WVPASS(b.acs())
   wvtest.WVPASS(b.internet())
   wvtest.WVPASS(b.current_route())
@@ -183,6 +188,7 @@
   """Test Wifi."""
   w = Wifi('wcli0', '21')
   w.set_connection_check_result('succeed')
+  w.initialize()
 
   try:
     wpa_path = tempfile.mkdtemp()
diff --git a/sysmgr/utest/test_fan.cc b/sysmgr/utest/test_fan.cc
index b2044b3..fe228d3 100644
--- a/sysmgr/utest/test_fan.cc
+++ b/sysmgr/utest/test_fan.cc
@@ -44,7 +44,10 @@
     bruno_base::LogMessage::LogToDebug(bruno_base::LS_INFO);
   }
 
-  bruno_platform_peripheral::FanControl fan_control(NULL);
+  bruno_platform_peripheral::Platform platform(
+      "Unknown", bruno_platform_peripheral::BRUNO_UNKNOWN, false, false);
+  platform.Init();
+  bruno_platform_peripheral::FanControl fan_control(&platform);
 
   fan_control.Init(NULL);
   uint16_t fan_speed;