update_engine: client waits for the service to be ready.

In some test scenarios we re-start the update_engine daemon and then run
update_engine_client right away. In those cases, we need to wait for
update_engine daemon to register the D-Bus service before we can talk
to it.

This patch waits up to 10 seconds for the update_engine daemon to be ready.

BUG=chromium:506053
TEST=stop update-engine ; /tmp/update_engine_client -status
TEST=restart update-engine ; /tmp/update_engine_client -status

Change-Id: Ia1496d2f849c12ff341b901237e5cbb13ef046dd
Reviewed-on: https://chromium-review.googlesource.com/282747
Reviewed-by: Alex Vakulenko <avakulenko@chromium.org>
Commit-Queue: Alex Deymo <deymo@chromium.org>
Trybot-Ready: Alex Deymo <deymo@chromium.org>
Tested-by: Alex Deymo <deymo@chromium.org>
diff --git a/update_engine_client.cc b/update_engine_client.cc
index 01946e7..d0fee7a 100644
--- a/update_engine_client.cc
+++ b/update_engine_client.cc
@@ -42,19 +42,29 @@
       return ret;
     if (!InitProxy())
       return 1;
-    ret = ProcessFlags();
-    if (ret != kContinueRunning) {
-      base::MessageLoop::current()->PostTask(
-          FROM_HERE,
-          base::Bind(&UpdateEngineClient::QuitWithExitCode,
-                     base::Unretained(this), ret));
-    }
+    // Wait for the UpdateEngine to be available or timeout.
+    proxy_->GetObjectProxy()->WaitForServiceToBeAvailable(
+        base::Bind(&UpdateEngineClient::OnServiceAvailable,
+                   base::Unretained(this)));
+    base::MessageLoop::current()->PostDelayedTask(
+        FROM_HERE,
+        base::Bind(&UpdateEngineClient::OnServiceAvailableTimeout,
+                   base::Unretained(this)),
+        base::TimeDelta::FromSeconds(10));
     return EX_OK;
   }
 
  private:
   bool InitProxy();
 
+  // Callback called when the UpdateEngine service becomes available.
+  void OnServiceAvailable(bool service_is_available);
+
+  // Callback called when the UpdateEngine service doesn't become available
+  // after a timeout.
+  void OnServiceAvailableTimeout();
+
+
   // Callback called when a StatusUpdate signal is received.
   void OnStatusUpdateSignal(int64_t last_checked_time,
                             double progress,
@@ -152,10 +162,12 @@
   int argc_;
   char** argv_;
 
+  // Tell whether the UpdateEngine service is available after startup.
+  bool service_is_available_{false};
+
   DISALLOW_COPY_AND_ASSIGN(UpdateEngineClient);
 };
 
-
 bool UpdateEngineClient::InitProxy() {
   proxy_.reset(new org::chromium::UpdateEngineInterfaceProxy(bus_));
 
@@ -166,6 +178,25 @@
   return true;
 }
 
+void UpdateEngineClient::OnServiceAvailable(bool service_is_available) {
+  service_is_available_ = service_is_available;
+  if (!service_is_available) {
+    LOG(ERROR) << "UpdateEngineService not available.";
+    QuitWithExitCode(-1);
+  }
+  int ret = ProcessFlags();
+  if (ret != kContinueRunning)
+    QuitWithExitCode(ret);
+}
+
+void UpdateEngineClient::OnServiceAvailableTimeout() {
+  if (!service_is_available_) {
+    LOG(ERROR) << "Waiting for UpdateEngineService timeout. Is update_engine "
+                  "daemon running?";
+    QuitWithExitCode(-1);
+  }
+}
+
 void UpdateEngineClient::OnStatusUpdateSignal(
     int64_t last_checked_time,
     double progress,