Make client use binder interface on brillo

TEST=Verified status and update commands
Bug: 25908638

Change-Id: I7994de41001b4e116bffa539f23f1344ab1deae9
diff --git a/Android.mk b/Android.mk
index aa3b9ee..892de7b 100644
--- a/Android.mk
+++ b/Android.mk
@@ -426,9 +426,7 @@
 LOCAL_STATIC_LIBRARIES := update_engine_client-dbus-proxies
 LOCAL_SHARED_LIBRARIES := \
     $(ue_common_shared_libraries) \
-    libdbus \
-    libbrillo-dbus \
-    libchrome-dbus \
+    libutils \
     libupdate_engine_client
 LOCAL_SRC_FILES := \
     update_engine_client.cc
@@ -605,6 +603,7 @@
 LOCAL_AIDL_INCLUDES := $(LOCAL_PATH)/binder_bindings
 LOCAL_SHARED_LIBRARIES += \
     libbinder \
+    libbrillo-binder \
     libutils
 LOCAL_SRC_FILES += \
     binder_bindings/android/brillo/IUpdateEngine.aidl \
diff --git a/binder_service.cc b/binder_service.cc
index 19acf6e..07ff22d 100644
--- a/binder_service.cc
+++ b/binder_service.cc
@@ -16,6 +16,10 @@
 
 #include "update_engine/binder_service.h"
 
+#include <base/bind.h>
+
+#include <binderwrapper/binder_wrapper.h>
+
 #include <utils/String16.h>
 #include <utils/StrongPointer.h>
 
@@ -166,7 +170,43 @@
 
 Status BinderUpdateEngineService::RegisterStatusCallback(
     const sp<IUpdateEngineStatusCallback>& callback) {
+  callbacks_.emplace_back(callback);
+
+  auto binder_wrapper = android::BinderWrapper::Get();
+
+  binder_wrapper->RegisterForDeathNotifications(
+      IUpdateEngineStatusCallback::asBinder(callback),
+      base::Bind(&BinderUpdateEngineService::UnregisterStatusCallback,
+                 base::Unretained(this), base::Unretained(callback.get())));
+
   return Status::ok();
 }
 
+void BinderUpdateEngineService::UnregisterStatusCallback(
+    IUpdateEngineStatusCallback* callback) {
+  auto it = callbacks_.begin();
+
+  for (; it != callbacks_.end() && it->get() != callback; it++)
+    ;
+
+  if (it == callbacks_.end()) {
+    LOG(ERROR) << "Got death notification for unknown callback.";
+    return;
+  }
+
+  LOG(INFO) << "Erasing orphan callback";
+  callbacks_.erase(it);
+}
+
+void BinderUpdateEngineService::SendStatusUpdate(
+    int64_t in_last_checked_time, double in_progress,
+    const std::string& in_current_operation, const std::string& in_new_version,
+    int64_t in_new_size) {
+  for (auto& callback : callbacks_) {
+    callback->HandleStatusUpdate(in_last_checked_time, in_progress,
+                                 String16{in_current_operation.c_str()},
+                                 String16{in_new_version.c_str()}, in_new_size);
+  }
+}
+
 }  // namespace chromeos_update_engine
diff --git a/binder_service.h b/binder_service.h
index ddbd147..b9b2ea5 100644
--- a/binder_service.h
+++ b/binder_service.h
@@ -19,6 +19,10 @@
 
 #include <utils/Errors.h>
 
+#include <vector>
+
+#include <utils/RefBase.h>
+
 #include "update_engine/common_service.h"
 #include "update_engine/parcelable_update_engine_status.h"
 
@@ -33,6 +37,10 @@
       : common_(new UpdateEngineService(system_state)) {}
   virtual ~BinderUpdateEngineService() = default;
 
+  void SendStatusUpdate(int64_t in_last_checked_time, double in_progress,
+                        const std::string& in_current_operation,
+                        const std::string& in_new_version, int64_t in_new_size);
+
   // android::brillo::BnUpdateEngine overrides.
   android::binder::Status AttemptUpdate(const android::String16& app_version,
                                         const android::String16& omaha_url,
@@ -65,12 +73,20 @@
       override;
 
  private:
+  // Generic function for dispatching to the common service.
   template<typename... Parameters, typename... Arguments>
   android::binder::Status CallCommonHandler(
       bool (UpdateEngineService::*Handler)(brillo::ErrorPtr*, Parameters...),
       Arguments... arguments);
 
+  // To be used as a death notification handler only.
+  void UnregisterStatusCallback(
+      android::brillo::IUpdateEngineStatusCallback* callback);
+
   std::unique_ptr<UpdateEngineService> common_;
+
+  std::vector<android::sp<android::brillo::IUpdateEngineStatusCallback>>
+      callbacks_;
 };  // class BinderService
 
 }  // namespace chromeos_update_engine
diff --git a/client_library/client_binder.cc b/client_library/client_binder.cc
index b3bd3e7..969c5e9 100644
--- a/client_library/client_binder.cc
+++ b/client_library/client_binder.cc
@@ -19,7 +19,6 @@
 #include <binder/IServiceManager.h>
 
 #include <base/message_loop/message_loop.h>
-#include <utils/String16.h>
 #include <utils/String8.h>
 
 #include "update_engine/parcelable_update_engine_status.h"
@@ -29,6 +28,7 @@
 using android::String16;
 using android::String8;
 using android::brillo::ParcelableUpdateEngineStatus;
+using android::binder::Status;
 using android::getService;
 using chromeos_update_engine::StringToUpdateStatus;
 using std::string;
@@ -37,6 +37,8 @@
 namespace internal {
 
 bool BinderUpdateEngineClient::Init() {
+  if (!binder_watcher_.Init()) return false;
+
   return getService(String16{"android.brillo.UpdateEngineService"},
       &service_) == OK;
 }
@@ -123,8 +125,36 @@
   return service_->ResetStatus().isOk();
 }
 
-void BinderUpdateEngineClient::RegisterStatusUpdateHandler(
+Status BinderUpdateEngineClient::StatusUpdateCallback::HandleStatusUpdate(
+    int64_t last_checked_time,
+    double progress,
+    const String16& current_operation,
+    const String16& new_version,
+    int64_t new_size) {
+  UpdateStatus update_status;
+
+  StringToUpdateStatus(String8{current_operation}.string(), &update_status);
+
+  for (auto& handler : client_->handlers_) {
+    handler->HandleStatusUpdate(last_checked_time, progress, update_status,
+                                String8{new_version}.string(), new_size);
+  }
+
+  return Status::ok();
+}
+
+bool BinderUpdateEngineClient::RegisterStatusUpdateHandler(
     StatusUpdateHandler* handler) {
+  if (!status_callback_.get()) {
+    status_callback_ =
+        new BinderUpdateEngineClient::StatusUpdateCallback(this);
+    if (!service_->RegisterStatusCallback(status_callback_).isOk()) {
+      return false;
+    }
+  }
+
+  handlers_.push_back(handler);
+  return true;
 }
 
 bool BinderUpdateEngineClient::SetTargetChannel(const string& in_target_channel,
diff --git a/client_library/client_binder.h b/client_library/client_binder.h
index 22d1cf0..744b238 100644
--- a/client_library/client_binder.h
+++ b/client_library/client_binder.h
@@ -20,11 +20,17 @@
 #include <cstdint>
 #include <memory>
 #include <string>
+#include <vector>
 
 #include <base/macros.h>
 #include <utils/StrongPointer.h>
+#include <utils/String16.h>
+
+#include <brillo/binder_watcher.h>
 
 #include "android/brillo/IUpdateEngine.h"
+#include "android/brillo/BnUpdateEngineStatusCallback.h"
+
 
 #include "update_engine/client_library/include/update_engine/client.h"
 
@@ -71,10 +77,29 @@
 
   bool GetChannel(std::string* out_channel) const override;
 
-  void RegisterStatusUpdateHandler(StatusUpdateHandler* handler) override;
+  bool RegisterStatusUpdateHandler(StatusUpdateHandler* handler) override;
 
  private:
+  class StatusUpdateCallback :
+      public android::brillo::BnUpdateEngineStatusCallback {
+   public:
+    StatusUpdateCallback(BinderUpdateEngineClient* client) : client_(client) {}
+
+    android::binder::Status HandleStatusUpdate(
+        int64_t last_checked_time,
+        double progress,
+        const android::String16& current_operation,
+        const android::String16& new_version,
+        int64_t new_size) override;
+
+   private:
+    BinderUpdateEngineClient* client_;
+  };
+
   android::sp<android::brillo::IUpdateEngine> service_;
+  android::sp<android::brillo::IUpdateEngineStatusCallback> status_callback_;
+  std::vector<update_engine::StatusUpdateHandler*> handlers_;
+  brillo::BinderWatcher binder_watcher_;
 
   DISALLOW_COPY_AND_ASSIGN(BinderUpdateEngineClient);
 };  // class BinderUpdateEngineClient
diff --git a/client_library/client_dbus.cc b/client_library/client_dbus.cc
index 0d02936..d9b4a05 100644
--- a/client_library/client_dbus.cc
+++ b/client_library/client_dbus.cc
@@ -159,20 +159,20 @@
       last_checked_time, progress, status, new_version, new_size);
 }
 
-void DBusUpdateEngineClient::RegisterStatusUpdateHandler(
+bool DBusUpdateEngineClient::RegisterStatusUpdateHandler(
     StatusUpdateHandler* handler) {
   if (!base::MessageLoopForIO::current()) {
     LOG(FATAL) << "Cannot get UpdateEngineClient outside of message loop.";
-    return;
+    return false;
   }
 
   proxy_->RegisterStatusUpdateSignalHandler(
       base::Bind(&DBusUpdateEngineClient::RunStatusUpdateHandler,
-                 base::Unretained(this),
-                 base::Unretained(handler)),
+                 base::Unretained(this), base::Unretained(handler)),
       base::Bind(&DBusUpdateEngineClient::StatusUpdateHandlerRegistered,
-                 base::Unretained(this),
-                 base::Unretained(handler)));
+                 base::Unretained(this), base::Unretained(handler)));
+
+  return true;
 }
 
 bool DBusUpdateEngineClient::SetTargetChannel(const string& in_target_channel,
diff --git a/client_library/client_dbus.h b/client_library/client_dbus.h
index 3590a21..e6bbe36 100644
--- a/client_library/client_dbus.h
+++ b/client_library/client_dbus.h
@@ -69,7 +69,7 @@
 
   bool GetChannel(std::string* out_channel) const override;
 
-  void RegisterStatusUpdateHandler(StatusUpdateHandler* handler) override;
+  bool RegisterStatusUpdateHandler(StatusUpdateHandler* handler) override;
 
  private:
   std::unique_ptr<org::chromium::UpdateEngineInterfaceProxy> proxy_;
diff --git a/client_library/include/update_engine/client.h b/client_library/include/update_engine/client.h
index 8bfb631..f2af453 100644
--- a/client_library/include/update_engine/client.h
+++ b/client_library/include/update_engine/client.h
@@ -106,7 +106,7 @@
   // not be registered. Otherwise its HandleStatusUpdate method will be called
   // every time update_engine's status changes. Will always report the status
   // on registration to prevent race conditions.
-  virtual void RegisterStatusUpdateHandler(StatusUpdateHandler* handler) = 0;
+  virtual bool RegisterStatusUpdateHandler(StatusUpdateHandler* handler) = 0;
 
  protected:
   // Use CreateInstance().
diff --git a/daemon.cc b/daemon.cc
index 3f88a84..ece151c 100644
--- a/daemon.cc
+++ b/daemon.cc
@@ -90,6 +90,10 @@
                                        service_)) {
     LOG(ERROR) << "Failed to register binder service.";
   }
+
+#if defined(__BRILLO__) || defined(__CHROMEOS__)
+  update_attempter->set_binder_service(service_.get());
+#endif // defined(__BRILLO__) || defined(__CHROMEOS__)
 #endif  // USE_BINDER
 
 #if USE_DBUS
diff --git a/update_attempter.cc b/update_attempter.cc
index 9b68c44..d0c20d0 100644
--- a/update_attempter.cc
+++ b/update_attempter.cc
@@ -1217,6 +1217,13 @@
   if (system_state_->weave_service())
     system_state_->weave_service()->UpdateWeaveState();
 
+#if USE_BINDER
+  if (binder_service_)
+    binder_service_->SendStatusUpdate(last_checked_time_, download_progress_,
+                                      UpdateStatusToString(status_),
+                                      new_version_.c_str(), new_payload_size_);
+#endif  // USE_BINDER
+
   if (!dbus_adaptor_)
     return;
   last_notify_time_ = TimeTicks::Now();
diff --git a/update_attempter.h b/update_attempter.h
index 3a2c30d..2401d60 100644
--- a/update_attempter.h
+++ b/update_attempter.h
@@ -28,6 +28,10 @@
 #include <base/time/time.h>
 #include <gtest/gtest_prod.h>  // for FRIEND_TEST
 
+#if USE_BINDER
+#include "update_engine/binder_service.h"
+#endif  // USE_BINDER
+
 #include "debugd/dbus-proxies.h"
 #include "update_engine/chrome_browser_proxy_resolver.h"
 #include "update_engine/client_library/include/update_engine/update_status.h"
@@ -138,6 +142,12 @@
     dbus_adaptor_ = dbus_adaptor;
   }
 
+#if USE_BINDER
+  void set_binder_service(BinderUpdateEngineService* service) {
+    binder_service_ = service;
+  }
+#endif
+
   // This is the internal entry point for going through an
   // update. If the current status is idle invokes Update.
   // This is called by the DBus implementation.
@@ -415,6 +425,12 @@
   // dbus service.
   UpdateEngineAdaptor* dbus_adaptor_ = nullptr;
 
+#if USE_BINDER
+  // If non-null, this UpdateAttempter will send status updates over this
+  // binder interface.
+  BinderUpdateEngineService* binder_service_ = nullptr;
+#endif  // USE_BINDER
+
   // Pointer to the OmahaResponseHandlerAction in the actions_ vector.
   std::shared_ptr<OmahaResponseHandlerAction> response_handler_action_;