Refactor daemon state and service async notification.
am: fa78f14d81

* commit 'fa78f14d818e8e0b8ed5d05ebc389bf833342e7a':
  Refactor daemon state and service async notification.
diff --git a/Android.mk b/Android.mk
index fe03b24..04ecfe5 100644
--- a/Android.mk
+++ b/Android.mk
@@ -224,7 +224,7 @@
 LOCAL_SRC_FILES := $(ue_libpayload_consumer_src_files)
 include $(BUILD_STATIC_LIBRARY)
 
-ifeq ($(local_use_dbus),1)
+ifdef BRILLO
 
 # libupdate_engine (type: static_library)
 # ========================================================
@@ -337,7 +337,7 @@
 LOCAL_SRC_FILES += \
     binder_bindings/android/brillo/IUpdateEngine.aidl \
     binder_bindings/android/brillo/IUpdateEngineStatusCallback.aidl \
-    binder_service.cc \
+    binder_service_brillo.cc \
     parcelable_update_engine_status.cc
 endif  # local_use_binder == 1
 ifeq ($(local_use_weave),1)
@@ -346,7 +346,50 @@
 endif  # local_use_weave == 1
 include $(BUILD_STATIC_LIBRARY)
 
-endif  # local_use_dbus == 1
+else  # !defined(BRILLO)
+
+ifneq ($(local_use_binder),1)
+$(error USE_BINDER is disabled but is required in non-Brillo devices.)
+endif  # local_use_binder == 1
+
+# libupdate_engine_android (type: static_library)
+# ========================================================
+# The main daemon static_library used in Android (non-Brillo). This only has a
+# loop to apply payloads provided by the upper layer via a Binder interface.
+ue_libupdate_engine_android_exported_static_libraries := \
+    libpayload_consumer \
+    $(ue_libpayload_consumer_exported_static_libraries)
+ue_libupdate_engine_android_exported_shared_libraries := \
+    $(ue_libpayload_consumer_exported_shared_libraries) \
+    libbinder \
+    libbinderwrapper \
+    libbrillo-binder \
+    libutils
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := libupdate_engine_android
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_CLANG := true
+LOCAL_CFLAGS := $(ue_common_cflags)
+LOCAL_CPPFLAGS := $(ue_common_cppflags)
+LOCAL_LDFLAGS := $(ue_common_ldflags)
+LOCAL_C_INCLUDES :=  $(ue_common_c_includes)
+LOCAL_STATIC_LIBRARIES := \
+    $(ue_libupdate_engine_android_exported_static_libraries:-host=)
+LOCAL_SHARED_LIBRARIES += \
+    $(ue_common_shared_libraries) \
+    $(ue_libupdate_engine_android_exported_shared_libraries:-host=)
+LOCAL_AIDL_INCLUDES := $(LOCAL_PATH)/binder_bindings
+LOCAL_SRC_FILES += \
+    binder_bindings/android/os/IUpdateEngine.aidl \
+    binder_bindings/android/os/IUpdateEngineCallback.aidl \
+    binder_service_android.cc \
+    daemon.cc \
+    daemon_state_android.cc
+include $(BUILD_STATIC_LIBRARY)
+
+endif  # !defined(BRILLO)
 
 # update_engine (type: executable)
 # ========================================================
@@ -381,28 +424,12 @@
 LOCAL_SHARED_LIBRARIES += \
     $(ue_libupdate_engine_exported_shared_libraries:-host=)
 else  # !defined(BRILLO)
-LOCAL_AIDL_INCLUDES := $(LOCAL_PATH)/binder_bindings
 LOCAL_STATIC_LIBRARIES := \
-    libpayload_consumer \
-    $(ue_libpayload_consumer_exported_static_libraries:-host=)
+    libupdate_engine_android \
+    $(ue_libupdate_engine_android_exported_static_libraries:-host=)
 LOCAL_SHARED_LIBRARIES += \
-    $(ue_libpayload_consumer_exported_shared_libraries:-host=) \
-    libbinder \
-    libbrillo-binder \
-    libutils
-LOCAL_SRC_FILES += \
-    binder_bindings/android/os/IUpdateEngine.aidl \
-    binder_bindings/android/os/IUpdateEngineCallback.aidl \
-    binder_service_android.cc \
-    daemon.cc
-endif  # defined(BRILLO)
-
-ifeq ($(local_use_binder),1)
-LOCAL_SHARED_LIBRARIES += \
-    libbinder \
-    libbinderwrapper \
-    libutils
-endif  # local_use_binder == 1
+    $(ue_libupdate_engine_android_exported_shared_libraries:-host=)
+endif  # !defined(BRILLO)
 
 LOCAL_INIT_RC := update_engine.rc
 include $(BUILD_EXECUTABLE)
diff --git a/binder_service.cc b/binder_service.cc
deleted file mode 100644
index 07ff22d..0000000
--- a/binder_service.cc
+++ /dev/null
@@ -1,212 +0,0 @@
-//
-// Copyright (C) 2015 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-#include "update_engine/binder_service.h"
-
-#include <base/bind.h>
-
-#include <binderwrapper/binder_wrapper.h>
-
-#include <utils/String16.h>
-#include <utils/StrongPointer.h>
-
-using android::String16;
-using android::String8;
-using android::binder::Status;
-using android::brillo::IUpdateEngineStatusCallback;
-using android::brillo::ParcelableUpdateEngineStatus;
-using android::sp;
-using brillo::ErrorPtr;
-using std::string;
-
-namespace chromeos_update_engine {
-
-namespace {
-string NormalString(const String16& in) {
-  return string{String8{in}.string()};
-}
-
-Status ToStatus(ErrorPtr* error) {
-  return Status::fromServiceSpecificError(
-      1, String8{error->get()->GetMessage().c_str()});
-}
-}  // namespace
-
-template<typename... Parameters, typename... Arguments>
-Status BinderUpdateEngineService::CallCommonHandler(
-    bool (UpdateEngineService::*Handler)(ErrorPtr*, Parameters...),
-    Arguments... arguments) {
-  ErrorPtr error;
-  if (((common_.get())->*Handler)(&error, arguments...)) return Status::ok();
-  return ToStatus(&error);
-}
-
-Status BinderUpdateEngineService::AttemptUpdate(const String16& app_version,
-                                                const String16& omaha_url,
-                                                int flags) {
-  return CallCommonHandler(
-      &UpdateEngineService::AttemptUpdate, NormalString(app_version),
-      NormalString(omaha_url), flags);
-}
-
-Status BinderUpdateEngineService::AttemptRollback(bool powerwash) {
-  return CallCommonHandler(&UpdateEngineService::AttemptRollback, powerwash);
-}
-
-Status BinderUpdateEngineService::CanRollback(bool* out_can_rollback) {
-  return CallCommonHandler(&UpdateEngineService::CanRollback,
-                           out_can_rollback);
-}
-
-Status BinderUpdateEngineService::ResetStatus() {
-  return CallCommonHandler(&UpdateEngineService::ResetStatus);
-}
-
-Status BinderUpdateEngineService::GetStatus(
-    ParcelableUpdateEngineStatus* status) {
-  string current_op;
-  string new_version;
-
-  auto ret = CallCommonHandler(&UpdateEngineService::GetStatus,
-                      &status->last_checked_time_,
-                      &status->progress_,
-                      &current_op,
-                      &new_version,
-                      &status->new_size_);
-
-  if (ret.isOk()) {
-    status->current_operation_ = String16{current_op.c_str()};
-    status->new_version_ = String16{new_version.c_str()};
-  }
-
-  return ret;
-}
-
-Status BinderUpdateEngineService::RebootIfNeeded() {
-  return CallCommonHandler(&UpdateEngineService::RebootIfNeeded);
-}
-
-Status BinderUpdateEngineService::SetChannel(const String16& target_channel,
-                                             bool powerwash) {
-  return CallCommonHandler(&UpdateEngineService::SetChannel,
-                           NormalString(target_channel), powerwash);
-}
-
-Status BinderUpdateEngineService::GetChannel(bool get_current_channel,
-                                             String16* out_channel) {
-  string channel_string;
-  auto ret = CallCommonHandler(&UpdateEngineService::GetChannel,
-                               get_current_channel,
-                               &channel_string);
-
-  *out_channel = String16(channel_string.c_str());
-  return ret;
-}
-
-Status BinderUpdateEngineService::SetP2PUpdatePermission(bool enabled) {
-  return CallCommonHandler(&UpdateEngineService::SetP2PUpdatePermission,
-                           enabled);
-}
-
-Status BinderUpdateEngineService::GetP2PUpdatePermission(
-    bool* out_p2p_permission) {
-  return CallCommonHandler(&UpdateEngineService::GetP2PUpdatePermission,
-                           out_p2p_permission);
-}
-
-Status BinderUpdateEngineService::SetUpdateOverCellularPermission(
-    bool enabled) {
-  return CallCommonHandler(
-      &UpdateEngineService::SetUpdateOverCellularPermission, enabled);
-}
-
-Status BinderUpdateEngineService::GetUpdateOverCellularPermission(
-    bool* out_cellular_permission) {
-  return CallCommonHandler(
-      &UpdateEngineService::GetUpdateOverCellularPermission,
-      out_cellular_permission);
-}
-
-Status BinderUpdateEngineService::GetDurationSinceUpdate(
-    int64_t* out_duration) {
-  return CallCommonHandler(&UpdateEngineService::GetDurationSinceUpdate,
-                           out_duration);
-}
-
-Status BinderUpdateEngineService::GetPrevVersion(String16* out_prev_version) {
-  string version_string;
-  auto ret = CallCommonHandler(&UpdateEngineService::GetPrevVersion,
-                               &version_string);
-
-  *out_prev_version = String16(version_string.c_str());
-  return ret;
-}
-
-Status BinderUpdateEngineService::GetRollbackPartition(
-    String16* out_rollback_partition) {
-  string partition_string;
-  auto ret = CallCommonHandler(&UpdateEngineService::GetRollbackPartition,
-                               &partition_string);
-
-  if (ret.isOk()) {
-    *out_rollback_partition = String16(partition_string.c_str());
-  }
-
-  return ret;
-}
-
-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_android.cc b/binder_service_android.cc
index c512697..144836a 100644
--- a/binder_service_android.cc
+++ b/binder_service_android.cc
@@ -24,6 +24,20 @@
 
 namespace chromeos_update_engine {
 
+BinderUpdateEngineAndroidService::BinderUpdateEngineAndroidService(
+    DaemonStateAndroid* /* daemon_state */) {
+  // TODO(deymo): Hook this interface calls to the daemon_state.
+}
+
+void BinderUpdateEngineAndroidService::SendStatusUpdate(
+    int64_t last_checked_time,
+    double progress,
+    update_engine::UpdateStatus status,
+    const std::string& new_version,
+    int64_t new_size) {
+  // TODO(deymo): Notify registered callers.
+}
+
 Status BinderUpdateEngineAndroidService::bind(
     const sp<IUpdateEngineCallback>& callback,
     bool* return_value) {
diff --git a/binder_service_android.h b/binder_service_android.h
index 224ab07..2fb9ca1 100644
--- a/binder_service_android.h
+++ b/binder_service_android.h
@@ -25,14 +25,32 @@
 
 #include "android/os/BnUpdateEngine.h"
 #include "android/os/IUpdateEngineCallback.h"
+#include "update_engine/daemon_state_android.h"
+#include "update_engine/service_observer_interface.h"
 
 namespace chromeos_update_engine {
 
-class BinderUpdateEngineAndroidService : public android::os::BnUpdateEngine {
+class BinderUpdateEngineAndroidService : public android::os::BnUpdateEngine,
+                                         public ServiceObserverInterface {
  public:
-  BinderUpdateEngineAndroidService() = default;
+  BinderUpdateEngineAndroidService(DaemonStateAndroid* daemon_state);
   ~BinderUpdateEngineAndroidService() override = default;
 
+  const char* ServiceName() const {
+    return "android.os.UpdateEngineService";
+  }
+
+  // ServiceObserverInterface overrides.
+  void SendStatusUpdate(int64_t last_checked_time,
+                        double progress,
+                        update_engine::UpdateStatus status,
+                        const std::string& new_version,
+                        int64_t new_size) override;
+
+  // Channel tracking changes are ignored.
+  void SendChannelChangeUpdate(const std::string& tracking_channel) override {}
+
+  // android::os::BnUpdateEngine overrides.
   android::binder::Status applyPayload(
       const android::String16& url,
       const std::vector<android::String16>& header_kv_pairs) override;
diff --git a/binder_service_brillo.cc b/binder_service_brillo.cc
new file mode 100644
index 0000000..45ac343
--- /dev/null
+++ b/binder_service_brillo.cc
@@ -0,0 +1,221 @@
+//
+// Copyright (C) 2015 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "update_engine/binder_service_brillo.h"
+
+#include <base/bind.h>
+
+#include <binderwrapper/binder_wrapper.h>
+
+#include <utils/String16.h>
+#include <utils/StrongPointer.h>
+
+#include "update_engine/update_status_utils.h"
+
+using android::String16;
+using android::String8;
+using android::binder::Status;
+using android::brillo::IUpdateEngineStatusCallback;
+using android::brillo::ParcelableUpdateEngineStatus;
+using android::sp;
+using brillo::ErrorPtr;
+using std::string;
+
+namespace chromeos_update_engine {
+
+namespace {
+string NormalString(const String16& in) {
+  return string{String8{in}.string()};
+}
+
+Status ToStatus(ErrorPtr* error) {
+  return Status::fromServiceSpecificError(
+      1, String8{error->get()->GetMessage().c_str()});
+}
+}  // namespace
+
+template <typename... Parameters, typename... Arguments>
+Status BinderUpdateEngineBrilloService::CallCommonHandler(
+    bool (UpdateEngineService::*Handler)(ErrorPtr*, Parameters...),
+    Arguments... arguments) {
+  ErrorPtr error;
+  if (((common_.get())->*Handler)(&error, arguments...))
+    return Status::ok();
+  return ToStatus(&error);
+}
+
+Status BinderUpdateEngineBrilloService::AttemptUpdate(
+    const String16& app_version, const String16& omaha_url, int flags) {
+  return CallCommonHandler(&UpdateEngineService::AttemptUpdate,
+                           NormalString(app_version),
+                           NormalString(omaha_url),
+                           flags);
+}
+
+Status BinderUpdateEngineBrilloService::AttemptRollback(bool powerwash) {
+  return CallCommonHandler(&UpdateEngineService::AttemptRollback, powerwash);
+}
+
+Status BinderUpdateEngineBrilloService::CanRollback(bool* out_can_rollback) {
+  return CallCommonHandler(&UpdateEngineService::CanRollback, out_can_rollback);
+}
+
+Status BinderUpdateEngineBrilloService::ResetStatus() {
+  return CallCommonHandler(&UpdateEngineService::ResetStatus);
+}
+
+Status BinderUpdateEngineBrilloService::GetStatus(
+    ParcelableUpdateEngineStatus* status) {
+  string current_op;
+  string new_version;
+
+  auto ret = CallCommonHandler(&UpdateEngineService::GetStatus,
+                               &status->last_checked_time_,
+                               &status->progress_,
+                               &current_op,
+                               &new_version,
+                               &status->new_size_);
+
+  if (ret.isOk()) {
+    status->current_operation_ = String16{current_op.c_str()};
+    status->new_version_ = String16{new_version.c_str()};
+  }
+
+  return ret;
+}
+
+Status BinderUpdateEngineBrilloService::RebootIfNeeded() {
+  return CallCommonHandler(&UpdateEngineService::RebootIfNeeded);
+}
+
+Status BinderUpdateEngineBrilloService::SetChannel(
+    const String16& target_channel, bool powerwash) {
+  return CallCommonHandler(&UpdateEngineService::SetChannel,
+                           NormalString(target_channel),
+                           powerwash);
+}
+
+Status BinderUpdateEngineBrilloService::GetChannel(bool get_current_channel,
+                                                   String16* out_channel) {
+  string channel_string;
+  auto ret = CallCommonHandler(
+      &UpdateEngineService::GetChannel, get_current_channel, &channel_string);
+
+  *out_channel = String16(channel_string.c_str());
+  return ret;
+}
+
+Status BinderUpdateEngineBrilloService::SetP2PUpdatePermission(bool enabled) {
+  return CallCommonHandler(&UpdateEngineService::SetP2PUpdatePermission,
+                           enabled);
+}
+
+Status BinderUpdateEngineBrilloService::GetP2PUpdatePermission(
+    bool* out_p2p_permission) {
+  return CallCommonHandler(&UpdateEngineService::GetP2PUpdatePermission,
+                           out_p2p_permission);
+}
+
+Status BinderUpdateEngineBrilloService::SetUpdateOverCellularPermission(
+    bool enabled) {
+  return CallCommonHandler(
+      &UpdateEngineService::SetUpdateOverCellularPermission, enabled);
+}
+
+Status BinderUpdateEngineBrilloService::GetUpdateOverCellularPermission(
+    bool* out_cellular_permission) {
+  return CallCommonHandler(
+      &UpdateEngineService::GetUpdateOverCellularPermission,
+      out_cellular_permission);
+}
+
+Status BinderUpdateEngineBrilloService::GetDurationSinceUpdate(
+    int64_t* out_duration) {
+  return CallCommonHandler(&UpdateEngineService::GetDurationSinceUpdate,
+                           out_duration);
+}
+
+Status BinderUpdateEngineBrilloService::GetPrevVersion(
+    String16* out_prev_version) {
+  string version_string;
+  auto ret =
+      CallCommonHandler(&UpdateEngineService::GetPrevVersion, &version_string);
+
+  *out_prev_version = String16(version_string.c_str());
+  return ret;
+}
+
+Status BinderUpdateEngineBrilloService::GetRollbackPartition(
+    String16* out_rollback_partition) {
+  string partition_string;
+  auto ret = CallCommonHandler(&UpdateEngineService::GetRollbackPartition,
+                               &partition_string);
+
+  if (ret.isOk()) {
+    *out_rollback_partition = String16(partition_string.c_str());
+  }
+
+  return ret;
+}
+
+Status BinderUpdateEngineBrilloService::RegisterStatusCallback(
+    const sp<IUpdateEngineStatusCallback>& callback) {
+  callbacks_.emplace_back(callback);
+
+  auto binder_wrapper = android::BinderWrapper::Get();
+
+  binder_wrapper->RegisterForDeathNotifications(
+      IUpdateEngineStatusCallback::asBinder(callback),
+      base::Bind(&BinderUpdateEngineBrilloService::UnregisterStatusCallback,
+                 base::Unretained(this),
+                 base::Unretained(callback.get())));
+
+  return Status::ok();
+}
+
+void BinderUpdateEngineBrilloService::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 BinderUpdateEngineBrilloService::SendStatusUpdate(
+    int64_t last_checked_time,
+    double progress,
+    update_engine::UpdateStatus status,
+    const string& new_version,
+    int64_t new_size) {
+  const string str_status = UpdateStatusToString(status);
+  for (auto& callback : callbacks_) {
+    callback->HandleStatusUpdate(last_checked_time,
+                                 progress,
+                                 String16{str_status.c_str()},
+                                 String16{new_version.c_str()},
+                                 new_size);
+  }
+}
+
+}  // namespace chromeos_update_engine
diff --git a/binder_service.h b/binder_service_brillo.h
similarity index 75%
rename from binder_service.h
rename to binder_service_brillo.h
index b9b2ea5..99aa76b 100644
--- a/binder_service.h
+++ b/binder_service_brillo.h
@@ -14,8 +14,8 @@
 // limitations under the License.
 //
 
-#ifndef UPDATE_ENGINE_BINDER_SERVICE_H_
-#define UPDATE_ENGINE_BINDER_SERVICE_H_
+#ifndef UPDATE_ENGINE_BINDER_SERVICE_BRILLO_H_
+#define UPDATE_ENGINE_BINDER_SERVICE_BRILLO_H_
 
 #include <utils/Errors.h>
 
@@ -25,21 +25,32 @@
 
 #include "update_engine/common_service.h"
 #include "update_engine/parcelable_update_engine_status.h"
+#include "update_engine/service_observer_interface.h"
 
 #include "android/brillo/BnUpdateEngine.h"
 #include "android/brillo/IUpdateEngineStatusCallback.h"
 
 namespace chromeos_update_engine {
 
-class BinderUpdateEngineService : public android::brillo::BnUpdateEngine {
+class BinderUpdateEngineBrilloService : public android::brillo::BnUpdateEngine,
+                                        public ServiceObserverInterface {
  public:
-  BinderUpdateEngineService(SystemState* system_state)
+  BinderUpdateEngineBrilloService(SystemState* system_state)
       : common_(new UpdateEngineService(system_state)) {}
-  virtual ~BinderUpdateEngineService() = default;
+  virtual ~BinderUpdateEngineBrilloService() = 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);
+  const char* ServiceName() const {
+    return "android.brillo.UpdateEngineService";
+  }
+
+  // ServiceObserverInterface overrides.
+  void SendStatusUpdate(int64_t last_checked_time,
+                        double progress,
+                        update_engine::UpdateStatus status,
+                        const std::string& new_version,
+                        int64_t new_size) override;
+  // Channel tracking changes are ignored.
+  void SendChannelChangeUpdate(const std::string& tracking_channel) override {}
 
   // android::brillo::BnUpdateEngine overrides.
   android::binder::Status AttemptUpdate(const android::String16& app_version,
@@ -74,7 +85,7 @@
 
  private:
   // Generic function for dispatching to the common service.
-  template<typename... Parameters, typename... Arguments>
+  template <typename... Parameters, typename... Arguments>
   android::binder::Status CallCommonHandler(
       bool (UpdateEngineService::*Handler)(brillo::ErrorPtr*, Parameters...),
       Arguments... arguments);
@@ -87,8 +98,8 @@
 
   std::vector<android::sp<android::brillo::IUpdateEngineStatusCallback>>
       callbacks_;
-};  // class BinderService
+};
 
 }  // namespace chromeos_update_engine
 
-#endif  // UPDATE_ENGINE_BINDER_SERVICE_H_
+#endif  // UPDATE_ENGINE_BINDER_SERVICE_BRILLO_H_
diff --git a/common_service.cc b/common_service.cc
index 77bdf7c..3c77c93 100644
--- a/common_service.cc
+++ b/common_service.cc
@@ -172,8 +172,7 @@
     return false;
   }
   // Update the weave state because updated the target channel.
-  if (system_state_->weave_service())
-    system_state_->weave_service()->UpdateWeaveState();
+  system_state_->update_attempter()->BroadcastChannel();
   return true;
 }
 
diff --git a/daemon.cc b/daemon.cc
index ece151c..27000d5 100644
--- a/daemon.cc
+++ b/daemon.cc
@@ -26,14 +26,16 @@
 #endif  // USE_WEAVE || USE_BINDER
 
 #if defined(__BRILLO__) || defined(__CHROMEOS__)
-#include "update_engine/update_attempter.h"
+#include "update_engine/real_system_state.h"
+#else  // !(defined(__BRILLO__) || defined(__CHROMEOS__))
+#include "update_engine/daemon_state_android.h"
 #endif  // defined(__BRILLO__) || defined(__CHROMEOS__)
 
 #if USE_DBUS
 namespace {
 const int kDBusSystemMaxWaitSeconds = 2 * 60;
 }  // namespace
-#endif // USE_DBUS
+#endif  // USE_DBUS
 
 namespace chromeos_update_engine {
 
@@ -65,52 +67,51 @@
   }
 
   CHECK(bus->SetUpAsyncOperations());
-#endif // USE_DBUS
+#endif  // USE_DBUS
 
 #if defined(__BRILLO__) || defined(__CHROMEOS__)
   // Initialize update engine global state but continue if something fails.
-  real_system_state_.reset(new RealSystemState(bus));
-  LOG_IF(ERROR, !real_system_state_->Initialize())
+  // TODO(deymo): Move the daemon_state_ initialization to a factory method
+  // avoiding the explicit re-usage of the |bus| instance, shared between
+  // D-Bus service and D-Bus client calls.
+  RealSystemState* real_system_state = new RealSystemState(bus);
+  daemon_state_.reset(real_system_state);
+  LOG_IF(ERROR, !real_system_state->Initialize())
       << "Failed to initialize system state.";
-  UpdateAttempter* update_attempter = real_system_state_->update_attempter();
-  CHECK(update_attempter);
 #else  // !(defined(__BRILLO__) || defined(__CHROMEOS__))
-  //TODO(deymo): Initialize non-Brillo state.
-#endif // defined(__BRILLO__) || defined(__CHROMEOS__)
+  DaemonStateAndroid* daemon_state_android = new DaemonStateAndroid();
+  daemon_state_.reset(daemon_state_android);
+  LOG_IF(ERROR, !daemon_state_android->Initialize())
+      << "Failed to initialize system state.";
+#endif  // defined(__BRILLO__) || defined(__CHROMEOS__)
 
 #if USE_BINDER
   // Create the Binder Service.
 #if defined(__BRILLO__) || defined(__CHROMEOS__)
-  service_ = new BinderUpdateEngineService{real_system_state_.get()};
+  binder_service_ = new BinderUpdateEngineBrilloService{real_system_state};
 #else  // !(defined(__BRILLO__) || defined(__CHROMEOS__))
-  service_ = new BinderUpdateEngineAndroidService{};
-#endif // defined(__BRILLO__) || defined(__CHROMEOS__)
+  binder_service_ = new BinderUpdateEngineAndroidService{daemon_state_android};
+#endif  // defined(__BRILLO__) || defined(__CHROMEOS__)
   auto binder_wrapper = android::BinderWrapper::Get();
-  if (!binder_wrapper->RegisterService("android.brillo.UpdateEngineService",
-                                       service_)) {
+  if (!binder_wrapper->RegisterService(binder_service_->ServiceName(),
+                                       binder_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__)
+  daemon_state_->AddObserver(binder_service_.get());
 #endif  // USE_BINDER
 
 #if USE_DBUS
   // Create the DBus service.
-  dbus_adaptor_.reset(new UpdateEngineAdaptor(real_system_state_.get(), bus));
-  update_attempter->set_dbus_adaptor(dbus_adaptor_.get());
+  dbus_adaptor_.reset(new UpdateEngineAdaptor(real_system_state, bus));
+  daemon_state_->AddObserver(dbus_adaptor_.get());
 
   dbus_adaptor_->RegisterAsync(base::Bind(&UpdateEngineDaemon::OnDBusRegistered,
                                           base::Unretained(this)));
   LOG(INFO) << "Waiting for DBus object to be registered.";
 #else  // !USE_DBUS
-#if defined(__BRILLO__) || defined(__CHROMEOS__)
-  real_system_state_->StartUpdater();
-#else  // !(defined(__BRILLO__) || defined(__CHROMEOS__))
-  // TODO(deymo): Start non-Brillo service.
-#endif // defined(__BRILLO__) || defined(__CHROMEOS__)
-#endif // USE_DBUS
+  daemon_state_->StartUpdater();
+#endif  // USE_DBUS
   return EX_OK;
 }
 
@@ -131,7 +132,7 @@
     QuitWithExitCode(1);
     return;
   }
-  real_system_state_->StartUpdater();
+  daemon_state_->StartUpdater();
 }
 #endif  // USE_DBUS
 
diff --git a/daemon.h b/daemon.h
index 32437cb..8323e56 100644
--- a/daemon.h
+++ b/daemon.h
@@ -30,18 +30,16 @@
 
 #if USE_BINDER
 #if defined(__BRILLO__) || defined(__CHROMEOS__)
-#include "update_engine/binder_service.h"
+#include "update_engine/binder_service_brillo.h"
 #else  // !(defined(__BRILLO__) || defined(__CHROMEOS__))
 #include "update_engine/binder_service_android.h"
 #endif  // defined(__BRILLO__) || defined(__CHROMEOS__)
 #endif  // USE_BINDER
 #include "update_engine/common/subprocess.h"
+#include "update_engine/daemon_state_interface.h"
 #if USE_DBUS
 #include "update_engine/dbus_service.h"
 #endif  // USE_DBUS
-#if defined(__BRILLO__) || defined(__CHROMEOS__)
-#include "update_engine/real_system_state.h"
-#endif  // defined(__BRILLO__) || defined(__CHROMEOS__)
 
 namespace chromeos_update_engine {
 
@@ -75,18 +73,15 @@
 
 #if USE_BINDER
 #if defined(__BRILLO__) || defined(__CHROMEOS__)
-  android::sp<BinderUpdateEngineService> service_;
+  android::sp<BinderUpdateEngineBrilloService> binder_service_;
 #else  // !(defined(__BRILLO__) || defined(__CHROMEOS__))
-  android::sp<BinderUpdateEngineAndroidService> service_;
+  android::sp<BinderUpdateEngineAndroidService> binder_service_;
 #endif  // defined(__BRILLO__) || defined(__CHROMEOS__)
 #endif  // USE_BINDER
 
-#if defined(__BRILLO__) || defined(__CHROMEOS__)
-  // The RealSystemState uses the previous classes so it should be defined last.
-  std::unique_ptr<RealSystemState> real_system_state_;
-#else  // !(defined(__BRILLO__) || defined(__CHROMEOS__))
-  //TODO(deymo): Define non-Brillo state.
-#endif  // defined(__BRILLO__) || defined(__CHROMEOS__)
+  // The daemon state with all the required daemon classes for the configured
+  // platform.
+  std::unique_ptr<DaemonStateInterface> daemon_state_;
 
   DISALLOW_COPY_AND_ASSIGN(UpdateEngineDaemon);
 };
diff --git a/daemon_state_android.cc b/daemon_state_android.cc
new file mode 100644
index 0000000..3e89ad0
--- /dev/null
+++ b/daemon_state_android.cc
@@ -0,0 +1,38 @@
+//
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "update_engine/daemon_state_android.h"
+
+namespace chromeos_update_engine {
+
+bool DaemonStateAndroid::Initialize() {
+  // TODO(deymo): Implement the Android updater state.
+  return true;
+}
+
+bool DaemonStateAndroid::StartUpdater() {
+  return true;
+}
+
+void DaemonStateAndroid::AddObserver(ServiceObserverInterface* observer) {
+  service_observers_.insert(observer);
+}
+
+void DaemonStateAndroid::RemoveObserver(ServiceObserverInterface* observer) {
+  service_observers_.erase(observer);
+}
+
+}  // namespace chromeos_update_engine
diff --git a/daemon_state_android.h b/daemon_state_android.h
new file mode 100644
index 0000000..2b8926c
--- /dev/null
+++ b/daemon_state_android.h
@@ -0,0 +1,44 @@
+//
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef UPDATE_ENGINE_DAEMON_STATE_ANDROID_H_
+#define UPDATE_ENGINE_DAEMON_STATE_ANDROID_H_
+
+#include <set>
+
+#include "update_engine/daemon_state_interface.h"
+#include "update_engine/service_observer_interface.h"
+
+namespace chromeos_update_engine {
+
+class DaemonStateAndroid : public DaemonStateInterface {
+ public:
+  DaemonStateAndroid() = default;
+
+  bool Initialize();
+
+  // DaemonStateInterface overrides.
+  bool StartUpdater() override;
+  void AddObserver(ServiceObserverInterface* observer) override;
+  void RemoveObserver(ServiceObserverInterface* observer) override;
+
+ protected:
+  std::set<ServiceObserverInterface*> service_observers_;
+};
+
+}  // namespace chromeos_update_engine
+
+#endif  // UPDATE_ENGINE_DAEMON_STATE_ANDROID_H_
diff --git a/daemon_state_interface.h b/daemon_state_interface.h
new file mode 100644
index 0000000..a0944aa
--- /dev/null
+++ b/daemon_state_interface.h
@@ -0,0 +1,45 @@
+//
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef UPDATE_ENGINE_DAEMON_STATE_INTERFACE_H_
+#define UPDATE_ENGINE_DAEMON_STATE_INTERFACE_H_
+
+#include "update_engine/service_observer_interface.h"
+
+#include <memory>
+
+namespace chromeos_update_engine {
+
+class DaemonStateInterface {
+ public:
+  virtual ~DaemonStateInterface() = default;
+
+  // Start the daemon loop. Should be called only once to start the daemon's
+  // main functionality.
+  virtual bool StartUpdater() = 0;
+
+  // Add and remove an observer. All the registered observers will be called
+  // whenever there's a new status to update.
+  virtual void AddObserver(ServiceObserverInterface* observer) = 0;
+  virtual void RemoveObserver(ServiceObserverInterface* observer) = 0;
+
+ protected:
+  DaemonStateInterface() = default;
+};
+
+}  // namespace chromeos_update_engine
+
+#endif  // UPDATE_ENGINE_DAEMON_STATE_INTERFACE_H_
diff --git a/dbus_service.cc b/dbus_service.cc
index 81a6efd..0ab0ac0 100644
--- a/dbus_service.cc
+++ b/dbus_service.cc
@@ -15,13 +15,15 @@
 //
 
 #include "update_engine/dbus_service.h"
+
 #include "update_engine/dbus-constants.h"
+#include "update_engine/update_status_utils.h"
 
 namespace chromeos_update_engine {
 
 using brillo::ErrorPtr;
-using std::string;
 using chromeos_update_engine::UpdateEngineService;
+using std::string;
 
 DBusUpdateEngineService::DBusUpdateEngineService(SystemState* system_state)
     : common_(new UpdateEngineService{system_state}) {
@@ -150,4 +152,14 @@
                                         dbus::Bus::REQUIRE_PRIMARY);
 }
 
+void UpdateEngineAdaptor::SendStatusUpdate(int64_t last_checked_time,
+                                           double progress,
+                                           update_engine::UpdateStatus status,
+                                           const string& new_version,
+                                           int64_t new_size) {
+  const string str_status = UpdateStatusToString(status);
+  SendStatusUpdateSignal(
+      last_checked_time, progress, str_status, new_version, new_size);
+}
+
 }  // namespace chromeos_update_engine
diff --git a/dbus_service.h b/dbus_service.h
index eb05a11..fe250c8 100644
--- a/dbus_service.h
+++ b/dbus_service.h
@@ -25,6 +25,7 @@
 #include <brillo/errors/error.h>
 
 #include "update_engine/common_service.h"
+#include "update_engine/service_observer_interface.h"
 #include "update_engine/update_attempter.h"
 
 #include "dbus_bindings/org.chromium.UpdateEngineInterface.h"
@@ -135,7 +136,8 @@
 // The UpdateEngineAdaptor class runs the UpdateEngineInterface in the fixed
 // object path, without an ObjectManager notifying the interfaces, since it is
 // all static and clients don't expect it to be implemented.
-class UpdateEngineAdaptor : public org::chromium::UpdateEngineInterfaceAdaptor {
+class UpdateEngineAdaptor : public org::chromium::UpdateEngineInterfaceAdaptor,
+                            public ServiceObserverInterface {
  public:
   UpdateEngineAdaptor(SystemState* system_state,
                       const scoped_refptr<dbus::Bus>& bus);
@@ -150,6 +152,16 @@
   // succeeded.
   bool RequestOwnership();
 
+  // ServiceObserverInterface overrides.
+  void SendStatusUpdate(int64_t last_checked_time,
+                        double progress,
+                        update_engine::UpdateStatus status,
+                        const std::string& new_version,
+                        int64_t new_size) override;
+
+  // Channel tracking changes are ignored.
+  void SendChannelChangeUpdate(const std::string& tracking_channel) override {}
+
  private:
   scoped_refptr<dbus::Bus> bus_;
   DBusUpdateEngineService dbus_service_;
diff --git a/real_system_state.cc b/real_system_state.cc
index f415b90..bb697f6 100644
--- a/real_system_state.cc
+++ b/real_system_state.cc
@@ -49,7 +49,7 @@
   // Prevent any DBus communication from UpdateAttempter when shutting down the
   // daemon.
   if (update_attempter_)
-    update_attempter_->set_dbus_adaptor(nullptr);
+    update_attempter_->ClearObservers();
 }
 
 bool RealSystemState::Initialize() {
@@ -137,6 +137,8 @@
   update_attempter_->Init();
 
   weave_service_ = ConstructWeaveService(update_attempter_.get());
+  if (weave_service_)
+    update_attempter_->AddObserver(weave_service_.get());
 
   // Initialize the Update Manager using the default state factory.
   chromeos_update_manager::State* um_state =
@@ -165,7 +167,7 @@
   return true;
 }
 
-void RealSystemState::StartUpdater() {
+bool RealSystemState::StartUpdater() {
   // Initiate update checks.
   update_attempter_->ScheduleUpdates();
 
@@ -186,6 +188,17 @@
   MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
       &UpdateAttempter::UpdateEngineStarted,
       base::Unretained(update_attempter_.get())));
+  return true;
+}
+
+void RealSystemState::AddObserver(ServiceObserverInterface* observer) {
+  CHECK(update_attempter_.get());
+  update_attempter_->AddObserver(observer);
+}
+
+void RealSystemState::RemoveObserver(ServiceObserverInterface* observer) {
+  CHECK(update_attempter_.get());
+  update_attempter_->RemoveObserver(observer);
 }
 
 }  // namespace chromeos_update_engine
diff --git a/real_system_state.h b/real_system_state.h
index f65f706..071e3e0 100644
--- a/real_system_state.h
+++ b/real_system_state.h
@@ -33,6 +33,7 @@
 #include "update_engine/common/hardware_interface.h"
 #include "update_engine/common/prefs.h"
 #include "update_engine/connection_manager.h"
+#include "update_engine/daemon_state_interface.h"
 #include "update_engine/p2p_manager.h"
 #include "update_engine/payload_state.h"
 #include "update_engine/shill_proxy.h"
@@ -44,7 +45,7 @@
 
 // A real implementation of the SystemStateInterface which is
 // used by the actual product code.
-class RealSystemState : public SystemState {
+class RealSystemState : public SystemState, public DaemonStateInterface {
  public:
   // Constructs all system objects that do not require separate initialization;
   // see Initialize() below for the remaining ones.
@@ -55,10 +56,15 @@
   // separately from construction. Returns |true| on success.
   bool Initialize();
 
+  // DaemonStateInterface overrides.
   // Start the periodic update attempts. Must be called at the beginning of the
   // program to start the periodic update check process.
-  void StartUpdater();
+  bool StartUpdater() override;
 
+  void AddObserver(ServiceObserverInterface* observer) override;
+  void RemoveObserver(ServiceObserverInterface* observer) override;
+
+  // SystemState overrides.
   inline void set_device_policy(
       const policy::DevicePolicy* device_policy) override {
     device_policy_ = device_policy;
diff --git a/service_observer_interface.h b/service_observer_interface.h
new file mode 100644
index 0000000..73d8350
--- /dev/null
+++ b/service_observer_interface.h
@@ -0,0 +1,48 @@
+//
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef UPDATE_ENGINE_SERVICE_OBSERVER_INTERFACE_H_
+#define UPDATE_ENGINE_SERVICE_OBSERVER_INTERFACE_H_
+
+#include <memory>
+#include <string>
+
+#include "update_engine/client_library/include/update_engine/update_status.h"
+
+namespace chromeos_update_engine {
+
+class ServiceObserverInterface {
+ public:
+  virtual ~ServiceObserverInterface() = default;
+
+  // Called whenever the value of these parameters changes. For |progress|
+  // value changes, this method will be called only if it changes significantly.
+  virtual void SendStatusUpdate(int64_t last_checked_time,
+                                double progress,
+                                update_engine::UpdateStatus status,
+                                const std::string& new_version,
+                                int64_t new_size) = 0;
+
+  // Called whenever the channel we are tracking changes.
+  virtual void SendChannelChangeUpdate(const std::string& tracking_channel) = 0;
+
+ protected:
+  ServiceObserverInterface() = default;
+};
+
+}  // namespace chromeos_update_engine
+
+#endif  // UPDATE_ENGINE_SERVICE_OBSERVER_INTERFACE_H_
diff --git a/update_attempter.cc b/update_attempter.cc
index d0c20d0..4e0b997 100644
--- a/update_attempter.cc
+++ b/update_attempter.cc
@@ -405,9 +405,8 @@
                                                  &error_message)) {
       LOG(ERROR) << "Setting the channel failed: " << error_message;
     }
-    // Update the weave state because updated the target channel.
-    if (system_state_->weave_service())
-      system_state_->weave_service()->UpdateWeaveState();
+    // Notify observers the target channel change.
+    BroadcastChannel();
 
     // Since this is the beginning of a new attempt, update the download
     // channel. The download channel won't be updated until the next attempt,
@@ -1105,9 +1104,8 @@
                          error_message);
     return false;
   }
-  // Update the weave state because updated the target channel.
-  if (system_state_->weave_service())
-    system_state_->weave_service()->UpdateWeaveState();
+  // Notify observers the target channel change.
+  BroadcastChannel();
   return true;
 }
 
@@ -1214,25 +1212,21 @@
 }
 
 void UpdateAttempter::BroadcastStatus() {
-  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;
+  for (const auto& observer : service_observers_) {
+    observer->SendStatusUpdate(last_checked_time_,
+                               download_progress_,
+                               status_,
+                               new_version_,
+                               new_payload_size_);
+  }
   last_notify_time_ = TimeTicks::Now();
-  dbus_adaptor_->SendStatusUpdateSignal(
-      last_checked_time_,
-      download_progress_,
-      UpdateStatusToString(status_),
-      new_version_.c_str(),
-      new_payload_size_);
+}
+
+void UpdateAttempter::BroadcastChannel() {
+  for (const auto& observer : service_observers_) {
+    observer->SendChannelChangeUpdate(
+        system_state_->request_params()->target_channel());
+  }
 }
 
 uint32_t UpdateAttempter::GetErrorCodeFlags()  {
diff --git a/update_attempter.h b/update_attempter.h
index 2401d60..2f53869 100644
--- a/update_attempter.h
+++ b/update_attempter.h
@@ -20,6 +20,7 @@
 #include <time.h>
 
 #include <memory>
+#include <set>
 #include <string>
 #include <utility>
 #include <vector>
@@ -28,10 +29,6 @@
 #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"
@@ -42,6 +39,7 @@
 #include "update_engine/omaha_response_handler_action.h"
 #include "update_engine/payload_consumer/download_action.h"
 #include "update_engine/proxy_resolver.h"
+#include "update_engine/service_observer_interface.h"
 #include "update_engine/system_state.h"
 #include "update_engine/update_manager/policy.h"
 #include "update_engine/update_manager/update_manager.h"
@@ -138,16 +136,6 @@
   int http_response_code() const { return http_response_code_; }
   void set_http_response_code(int code) { http_response_code_ = code; }
 
-  void set_dbus_adaptor(UpdateEngineAdaptor* dbus_adaptor) {
-    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.
@@ -184,9 +172,12 @@
 
   void DownloadComplete() override;
 
-  // Broadcasts the current status over D-Bus.
+  // Broadcasts the current status to all observers.
   void BroadcastStatus();
 
+  // Broadcasts the current tracking channel to all observers.
+  void BroadcastChannel();
+
   // Returns the special flags to be added to ErrorCode values based on the
   // parameters used in the current update attempt.
   uint32_t GetErrorCodeFlags();
@@ -239,6 +230,17 @@
   // 'cros flash' to function properly).
   virtual bool IsAnyUpdateSourceAllowed();
 
+  // Add and remove a service observer.
+  void AddObserver(ServiceObserverInterface* observer) {
+    service_observers_.insert(observer);
+  }
+  void RemoveObserver(ServiceObserverInterface* observer) {
+    service_observers_.erase(observer);
+  }
+
+  // Remove all the observers.
+  void ClearObservers() { service_observers_.clear(); }
+
  private:
   // Update server URL for automated lab test.
   static const char* const kTestUpdateUrl;
@@ -421,15 +423,8 @@
   // Pointer to the certificate checker instance to use.
   CertificateChecker* cert_checker_;
 
-  // If non-null, this UpdateAttempter will send status updates over this
-  // 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
+  // The list of services observing changes in the updater.
+  std::set<ServiceObserverInterface*> service_observers_;
 
   // Pointer to the OmahaResponseHandlerAction in the actions_ vector.
   std::shared_ptr<OmahaResponseHandlerAction> response_handler_action_;
diff --git a/weave_service.cc b/weave_service.cc
index c6a67f2..b8ac174 100644
--- a/weave_service.cc
+++ b/weave_service.cc
@@ -62,6 +62,20 @@
   UpdateWeaveState();
 }
 
+void WeaveService::SendStatusUpdate(int64_t /* last_checked_time */,
+                                    double /* progress */,
+                                    update_engine::UpdateStatus /* status */,
+                                    const string& /* new_version */,
+                                    int64_t /* new_size */) {
+  // We query the Weave
+  UpdateWeaveState();
+}
+
+void WeaveService::SendChannelChangeUpdate(
+    const string& /* tracking_channel */) {
+  UpdateWeaveState();
+}
+
 void WeaveService::UpdateWeaveState() {
   auto weave_service = weave_service_.lock();
   if (!weave_service || !delegate_)
diff --git a/weave_service.h b/weave_service.h
index 914777e..b1068e7 100644
--- a/weave_service.h
+++ b/weave_service.h
@@ -18,6 +18,7 @@
 #define UPDATE_ENGINE_WEAVE_SERVICE_H_
 
 #include <memory>
+#include <string>
 
 #include <base/memory/weak_ptr.h>
 #include <libweaved/command.h>
@@ -34,10 +35,18 @@
 
   bool Init(DelegateInterface* delegate);
 
-  // WeaveServiceInterface override.
-  void UpdateWeaveState() override;
+  // ServiceObserverInterface overrides.
+  void SendStatusUpdate(int64_t last_checked_time,
+                        double progress,
+                        update_engine::UpdateStatus status,
+                        const std::string& new_version,
+                        int64_t new_size) override;
+  void SendChannelChangeUpdate(const std::string& tracking_channel) override;
 
  private:
+  // Force a weave update.
+  void UpdateWeaveState();
+
   void OnWeaveServiceConnected(const std::weak_ptr<weaved::Service>& service);
 
   // Weave command handlers. These are called from the message loop whenever a
diff --git a/weave_service_interface.h b/weave_service_interface.h
index baaa9db..a7e603e 100644
--- a/weave_service_interface.h
+++ b/weave_service_interface.h
@@ -22,6 +22,7 @@
 #include <brillo/errors/error.h>
 
 #include "update_engine/client_library/include/update_engine/update_status.h"
+#include "update_engine/service_observer_interface.h"
 
 namespace chromeos_update_engine {
 
@@ -30,7 +31,7 @@
 // registration with weaved and the connection, the actual work to handle the
 // commands is implemented by the DelegateInterface, which will be called from
 // this class.
-class WeaveServiceInterface {
+class WeaveServiceInterface : public ServiceObserverInterface {
  public:
   // The delegate class that actually handles the command execution from
   class DelegateInterface {
@@ -52,9 +53,6 @@
 
   virtual ~WeaveServiceInterface() = default;
 
-  // Force a weave state update.
-  virtual void UpdateWeaveState() = 0;
-
  protected:
   WeaveServiceInterface() = default;
 };