autotest: Adds wait_for_service_state to ShillProxy.

The new autotest framework needs the ability to wait for a service to
achieve a state from a list of states.  This CL provides such a
capability.

BUG=chromium:258664
TEST=autotest
CQ-DEPEND=If6ea0a4de2a8e90ca30df4904551ebc85a9694c1

Change-Id: Id3f34443d69e8c56e7ca885f3ac6ebe1eeb2ba47
Reviewed-on: https://gerrit.chromium.org/gerrit/61353
Reviewed-by: Christopher Wiley <wiley@chromium.org>
Commit-Queue: Wade Guthrie <wdg@chromium.org>
Reviewed-by: Wade Guthrie <wdg@chromium.org>
Tested-by: Wade Guthrie <wdg@chromium.org>
diff --git a/test-scripts/shill_proxy.py b/test-scripts/shill_proxy.py
index cd3d069..8951a42 100644
--- a/test-scripts/shill_proxy.py
+++ b/test-scripts/shill_proxy.py
@@ -220,7 +220,7 @@
                 break
             time.sleep(self.POLLING_INTERVAL_SECONDS)
         duration = time.time() - start_time
-        return (successful, self.dbus2primitive(value), duration)
+        return successful, self.dbus2primitive(value), duration
 
 
     @property
diff --git a/test-scripts/wifi_proxy.py b/test-scripts/wifi_proxy.py
index df20083..5467ef9 100644
--- a/test-scripts/wifi_proxy.py
+++ b/test-scripts/wifi_proxy.py
@@ -240,3 +240,44 @@
             else:
                 device.SetProperty(k, type_cast(value))
         return True
+
+
+    def wait_for_service_states(self, ssid, states, timeout_seconds):
+        """Wait for a service (ssid) to achieve one of a number of states.
+
+        @param ssid string name of network for whose state we're waiting.
+        @param states tuple states for which to wait.
+        @param timeout_seconds seconds to wait for property to be achieved
+        @return tuple(successful, final_value, duration)
+            where successful is True iff we saw one of |states|, final_value
+            is the final state we saw, and duration is how long we waited to
+            see that value.
+
+        """
+        discovery_params = {self.SERVICE_PROPERTY_TYPE: 'wifi',
+                            self.SERVICE_PROPERTY_NAME: ssid}
+        start_time = time.time()
+        service_object = None
+        while not service_object:
+            try:
+                service_path = self.manager.FindMatchingService(
+                        discovery_params)
+                service_object = self.get_dbus_object(self.DBUS_TYPE_SERVICE,
+                                                      service_path)
+            except dbus.exceptions.DBusException, e:
+                if e.get_dbus_message() == 'Matching service was not found':
+                    time.sleep(self.POLLING_INTERVAL_SECONDS)
+                else:
+                    logging.error('Caught an error while discovering: %s',
+                                  e.get_dbus_message())
+                    return False, 'unknown', timeout_seconds
+
+                if time.time() - start_time >= timeout_seconds:
+                    logging.error('Timed out waiting for %s states' % ssid)
+                    return False, 'unknown', timeout_seconds
+
+        return self.wait_for_property_in(
+                service_object,
+                self.SERVICE_PROPERTY_STATE,
+                states,
+                timeout_seconds - (time.time() - start_time))