/bin/wifi: Make stop commands use all interfaces by default.

If --interface-suffix is not specified (or is set to 'ALL'), wifi stop
commands will now stop all interfaces.

To specify only the empty suffix, use --interface-suffix=NONE.

BUG=30646002

Change-Id: I2224a1d848a2a8b1c6eab659079079a7ff850f66
diff --git a/wifi/iw.py b/wifi/iw.py
index ae2a8b6..c0bbf57 100644
--- a/wifi/iw.py
+++ b/wifi/iw.py
@@ -226,14 +226,26 @@
       return interface
 
 
-def find_all_interfaces_from_phy(phy):
+def find_all_interfaces_from_phy(phy, interface_type=None):
+  """Finds the names of all interfaces on a given phy.
+
+  Args:
+    phy: The name of a phy, e.g. 'phy0'.
+    interface_type: An INTERFACE_TYPE value (optional).
+
+  Returns:
+    A list of all interfaces found.
+  """
   interfaces = []
-  for interface_type in INTERFACE_TYPE:
+  interface_types = INTERFACE_TYPE
+  if interface_type:
+    interface_types = [interface_type]
+  for interface_type in interface_types:
     pattern = re.compile(r'w%s[0-9]\w*\Z' % re.escape(interface_type))
     interfaces.extend(interface for interface
                       in dev_parsed()[phy]['interfaces']
                       if pattern.match(interface))
-  return interfaces
+  return set(interfaces)
 
 
 def find_interface_from_band(band, interface_type, interface_suffix):
@@ -254,6 +266,23 @@
   return find_interface_from_phy(phy, interface_type, interface_suffix)
 
 
+def find_all_interfaces_from_band(band, interface_type=None):
+  """Finds the names of all interface on a given band.
+
+  Args:
+    band: The band for which you want the interface.
+    interface_type: An INTERFACE_TYPE value (optional).
+
+  Returns:
+    A list of all interfaces found.
+  """
+  phy = find_phy(band, 'auto')
+  if phy is None:
+    return []
+
+  return find_all_interfaces_from_phy(phy, interface_type)
+
+
 def find_width_and_channel(interface):
   """Finds the width and channel being used by a given interface.
 
diff --git a/wifi/iw_test.py b/wifi/iw_test.py
index 4a7ef4c..2293954 100755
--- a/wifi/iw_test.py
+++ b/wifi/iw_test.py
@@ -514,6 +514,19 @@
 
 
 @wvtest.wvtest
+def find_all_interfaces_from_phy_test():
+  wvtest.WVPASSEQ(set(['wlan0', 'wlan0_portal', 'wcli0']),
+                  iw.find_all_interfaces_from_phy('phy0'))
+  wvtest.WVPASSEQ(set(['wlan0', 'wlan0_portal']),
+                  iw.find_all_interfaces_from_phy('phy0', iw.INTERFACE_TYPE.ap))
+  wvtest.WVPASSEQ(set(['wcli0']),
+                  iw.find_all_interfaces_from_phy('phy0',
+                                                  iw.INTERFACE_TYPE.client))
+  wvtest.WVPASSEQ(set(['wlan1', 'wlan1_portal']),
+                  iw.find_all_interfaces_from_phy('phy1'))
+
+
+@wvtest.wvtest
 def find_interface_from_band_test():
   wvtest.WVPASSEQ('wlan0',
                   iw.find_interface_from_band('2.4', iw.INTERFACE_TYPE.ap, ''))
@@ -529,6 +542,19 @@
 
 
 @wvtest.wvtest
+def find_all_interfaces_from_band_test():
+  wvtest.WVPASSEQ(set(['wlan0', 'wlan0_portal', 'wcli0']),
+                  iw.find_all_interfaces_from_band('2.4'))
+  wvtest.WVPASSEQ(set(['wlan0', 'wlan0_portal']),
+                  iw.find_all_interfaces_from_band('2.4', iw.INTERFACE_TYPE.ap))
+  wvtest.WVPASSEQ(set(['wcli0']),
+                  iw.find_all_interfaces_from_band('2.4',
+                                                   iw.INTERFACE_TYPE.client))
+  wvtest.WVPASSEQ(set(['wlan1', 'wlan1_portal']),
+                  iw.find_all_interfaces_from_band('5'))
+
+
+@wvtest.wvtest
 def info_parsed_test():
   wvtest.WVPASSEQ({
       'wdev': '0x3',
diff --git a/wifi/wifi.py b/wifi/wifi.py
index 8797633..142010c 100755
--- a/wifi/wifi.py
+++ b/wifi/wifi.py
@@ -50,7 +50,7 @@
 X,extra-short-timeouts            Use shorter key rotations; 1=rotate PTK, 2=rotate often
 Y,yottasecond-timeouts            Don't rotate any keys: PTK, GTK, or GMK
 P,persist                         For set commands, persist options so we can restore them with 'wifi restore'.  For stop commands, remove persisted options.
-S,interface-suffix=               Interface suffix []
+S,interface-suffix=               Interface suffix (defaults to ALL for stop commands; use NONE to specify no suffix) []
 lock-timeout=                     How long, in seconds, to wait for another /bin/wifi process to finish before giving up. [60]
 scan-ap-force                     (Scan only) scan when in AP mode
 scan-passive                      (Scan only) do not probe, scan passively
@@ -381,18 +381,25 @@
     if band == '5' and quantenna.stop_ap_wifi(opt):
       continue
 
-    interface = iw.find_interface_from_band(
-        band, iw.INTERFACE_TYPE.ap, opt.interface_suffix)
-    if interface is None:
-      utils.log('No AP interface for %s GHz; nothing to stop', band)
+    interfaces = []
+    if opt.interface_suffix == 'ALL':
+      interfaces = iw.find_all_interfaces_from_band(band, iw.INTERFACE_TYPE.ap)
+    else:
+      interface = iw.find_interface_from_band(
+          band, iw.INTERFACE_TYPE.ap, opt.interface_suffix)
+      if interface:
+        interfaces = [interface]
+    if not interfaces:
+      utils.log('No AP interfaces for %s GHz; nothing to stop', band)
       continue
 
-    if _stop_hostapd(interface):
-      if opt.persist:
-        persist.delete_options('hostapd', band)
-    else:
-      utils.log('Failed to stop hostapd on interface %s', interface)
-      success = False
+    for interface in interfaces:
+      if _stop_hostapd(interface):
+        if opt.persist:
+          persist.delete_options('hostapd', band)
+      else:
+        utils.log('Failed to stop hostapd on interface %s', interface)
+        success = False
 
   return success
 
@@ -989,18 +996,26 @@
     if band == '5' and quantenna.stop_client_wifi(opt):
       continue
 
-    interface = iw.find_interface_from_band(
-        band, iw.INTERFACE_TYPE.client, opt.interface_suffix)
-    if interface is None:
-      utils.log('No client interface for %s GHz; nothing to stop', band)
+    interfaces = []
+    if opt.interface_suffix == 'ALL':
+      interfaces = iw.find_all_interfaces_from_band(
+          band, iw.INTERFACE_TYPE.client)
+    else:
+      interface = iw.find_interface_from_band(
+          band, iw.INTERFACE_TYPE.client, opt.interface_suffix)
+      if interface:
+        interfaces = [interface]
+    if not interfaces:
+      utils.log('No client interfaces for %s GHz; nothing to stop', band)
       continue
 
-    if _stop_wpa_supplicant(interface):
-      if opt.persist:
-        persist.delete_options('wpa_supplicant', band)
-    else:
-      utils.log('Failed to stop wpa_supplicant on interface %s', interface)
-      success = False
+    for interface in interfaces:
+      if _stop_wpa_supplicant(interface):
+        if opt.persist:
+          persist.delete_options('wpa_supplicant', band)
+      else:
+        utils.log('Failed to stop wpa_supplicant on interface %s', interface)
+        success = False
 
   return success
 
@@ -1044,10 +1059,18 @@
     parser.fatal('Must specify a command (see usage for details).')
     return 1
 
+  command = extra[0]
+
   # set and setclient have a different default for -b.
-  if extra[0].startswith('set') and ' ' in opt.band:
+  if command.startswith('set') and ' ' in opt.band:
     opt.band = '2.4'
 
+  if command == 'off' or command.startswith('stop'):
+    if not opt.interface_suffix:
+      opt.interface_suffix = 'ALL'
+    elif opt.interface_suffix == 'NONE':
+      opt.interface_suffix = ''
+
   try:
     function = {
         'set': set_wifi,