Implement update_engine weave commands

The new WeaveServiceInterface abstracs the registration and interaction
with weave whenever present. The compilation and usage of weave is
based on the BRILLO_USE_WEAVE flag.

When enabled, update_engine registers the "_updater" component with
methods to force-check for an update and change channels.

Bug: 24386758
Bug: 24386768
Test: Deployed on edison, weave commands and state available online.

Change-Id: Ic49111772e123b8a2b1971da92fe65785f186ccd
diff --git a/Android.mk b/Android.mk
index 252ffcf..775bdc2 100644
--- a/Android.mk
+++ b/Android.mk
@@ -21,12 +21,14 @@
 BRILLO_USE_HWID_OVERRIDE ?= 0
 BRILLO_USE_MTD ?= 0
 BRILLO_USE_POWER_MANAGEMENT ?= 0
+BRILLO_USE_WEAVE ?= 0
 
 ue_common_cflags := \
     -DUSE_DBUS=$(BRILLO_USE_DBUS) \
     -DUSE_HWID_OVERRIDE=$(BRILLO_USE_HWID_OVERRIDE) \
     -DUSE_MTD=$(BRILLO_USE_MTD) \
     -DUSE_POWER_MANAGEMENT=$(BRILLO_USE_POWER_MANAGEMENT) \
+    -DUSE_WEAVE=$(BRILLO_USE_WEAVE) \
     -D_FILE_OFFSET_BITS=64 \
     -D_POSIX_C_SOURCE=199309L \
     -Wa,--noexecstack \
@@ -247,6 +249,10 @@
     libcutils \
     $(ue_libpayload_consumer_exported_shared_libraries) \
     $(ue_update_metadata_protos_exported_shared_libraries)
+ifeq ($(BRILLO_USE_WEAVE),1)
+ue_libupdate_engine_exported_shared_libraries += \
+    libweaved
+endif  # BRILLO_USE_WEAVE == 1
 
 include $(CLEAR_VARS)
 LOCAL_MODULE := libupdate_engine
@@ -308,7 +314,12 @@
     update_manager/real_updater_provider.cc \
     update_manager/state_factory.cc \
     update_manager/update_manager.cc \
-    update_status_utils.cc
+    update_status_utils.cc \
+    weave_service_factory.cc
+ifeq ($(BRILLO_USE_WEAVE),1)
+LOCAL_SRC_FILES += \
+    weave_service.cc
+endif  # BRILLO_USE_WEAVE == 1
 include $(BUILD_STATIC_LIBRARY)
 
 endif  # BRILLO_USE_DBUS == 1
@@ -322,6 +333,9 @@
 LOCAL_REQUIRED_MODULES := \
     bspatch \
     cacerts_google
+ifeq ($(BRILLO_USE_WEAVE),1)
+LOCAL_REQUIRED_MODULES += updater.json
+endif  # BRILLO_USE_WEAVE == 1
 LOCAL_CPP_EXTENSION := .cc
 LOCAL_CLANG := true
 LOCAL_CFLAGS := $(ue_common_cflags)
@@ -561,6 +575,15 @@
 
 endif  # BRILLO_USE_DBUS == 1
 
+# Weave schema files
+# ========================================================
+include $(CLEAR_VARS)
+LOCAL_MODULE := updater.json
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/weaved/traits
+LOCAL_SRC_FILES := weaved/traits/$(LOCAL_MODULE)
+include $(BUILD_PREBUILT)
+
 # Update payload signing public key.
 # ========================================================
 include $(CLEAR_VARS)
diff --git a/fake_system_state.h b/fake_system_state.h
index 75ef315..12d9239 100644
--- a/fake_system_state.h
+++ b/fake_system_state.h
@@ -85,6 +85,8 @@
     return update_attempter_;
   }
 
+  inline WeaveServiceInterface* weave_service() override { return nullptr; }
+
   inline OmahaRequestParams* request_params() override {
     return request_params_;
   }
diff --git a/real_system_state.cc b/real_system_state.cc
index 3a90292..ffb2193 100644
--- a/real_system_state.cc
+++ b/real_system_state.cc
@@ -16,6 +16,8 @@
 
 #include "update_engine/real_system_state.h"
 
+#include <string>
+
 #include <base/files/file_util.h>
 #include <base/time/time.h>
 #include <brillo/make_unique_ptr.h>
@@ -26,11 +28,13 @@
 #include "update_engine/common/hardware.h"
 #include "update_engine/common/utils.h"
 #include "update_engine/update_manager/state_factory.h"
+#include "update_engine/weave_service_factory.h"
 
 namespace chromeos_update_engine {
 
 RealSystemState::RealSystemState(const scoped_refptr<dbus::Bus>& bus)
-    : debugd_proxy_(bus),
+    : bus_(bus),
+      debugd_proxy_(bus),
       power_manager_proxy_(bus),
       session_manager_proxy_(bus),
       shill_proxy_(bus),
@@ -121,6 +125,8 @@
                           &debugd_proxy_));
   update_attempter_->Init();
 
+  weave_service_ = ConstructWeaveService(bus_, update_attempter_.get());
+
   // Initialize the Update Manager using the default state factory.
   chromeos_update_manager::State* um_state =
       chromeos_update_manager::DefaultStateFactory(
diff --git a/real_system_state.h b/real_system_state.h
index 8ca1abc..d7ee712 100644
--- a/real_system_state.h
+++ b/real_system_state.h
@@ -38,6 +38,7 @@
 #include "update_engine/shill_proxy.h"
 #include "update_engine/update_attempter.h"
 #include "update_engine/update_manager/update_manager.h"
+#include "update_engine/weave_service_interface.h"
 
 namespace chromeos_update_engine {
 
@@ -92,6 +93,10 @@
     return update_attempter_.get();
   }
 
+  inline WeaveServiceInterface* weave_service() override {
+    return weave_service_.get();
+  }
+
   inline OmahaRequestParams* request_params() override {
     return &request_params_;
   }
@@ -110,6 +115,9 @@
   inline bool system_rebooted() override { return system_rebooted_; }
 
  private:
+  // Reference to the DBus bus.
+  scoped_refptr<dbus::Bus> bus_;
+
   // Real DBus proxies using the DBus connection.
   org::chromium::debugdProxy debugd_proxy_;
   org::chromium::PowerManagerProxy power_manager_proxy_;
@@ -158,6 +166,8 @@
 
   std::unique_ptr<P2PManager> p2p_manager_;
 
+  std::unique_ptr<WeaveServiceInterface> weave_service_;
+
   std::unique_ptr<chromeos_update_manager::UpdateManager> update_manager_;
 
   policy::PolicyProvider policy_provider_;
diff --git a/system_state.h b/system_state.h
index 2ba0272..7923217 100644
--- a/system_state.h
+++ b/system_state.h
@@ -51,6 +51,7 @@
 class PayloadStateInterface;
 class PrefsInterface;
 class UpdateAttempter;
+class WeaveServiceInterface;
 
 // An interface to global system context, including platform resources,
 // the current state of the system, high-level objects whose lifetime is same
@@ -98,6 +99,9 @@
   // Returns a pointer to the update attempter object.
   virtual UpdateAttempter* update_attempter() = 0;
 
+  // Returns a pointer to the WeaveServiceInterface class or nullptr if none.
+  virtual WeaveServiceInterface* weave_service() = 0;
+
   // Returns a pointer to the object that stores the parameters that are
   // common to all Omaha requests.
   virtual OmahaRequestParams* request_params() = 0;
diff --git a/update_attempter.cc b/update_attempter.cc
index 5704731..bc06502 100644
--- a/update_attempter.cc
+++ b/update_attempter.cc
@@ -762,7 +762,7 @@
   }
 
   vector<BootControlInterface::Slot> bootable_slots;
-  for(BootControlInterface::Slot slot = 0; slot < num_slots; slot++) {
+  for (BootControlInterface::Slot slot = 0; slot < num_slots; slot++) {
     if (slot != current_slot &&
         system_state_->boot_control()->IsSlotBootable(slot)) {
       LOG(INFO) << "Found bootable slot "
@@ -1083,6 +1083,42 @@
   system_state_->payload_state()->DownloadComplete();
 }
 
+bool UpdateAttempter::OnCheckForUpdates(brillo::ErrorPtr* error) {
+  CheckForUpdate(
+      "" /* app_version */, "" /* omaha_url */, true /* interactive */);
+  return true;
+}
+
+bool UpdateAttempter::OnTrackChannel(const string& channel,
+                                     brillo::ErrorPtr* error) {
+  LOG(INFO) << "Setting destination channel to: " << channel;
+  string error_message;
+  if (!system_state_->request_params()->SetTargetChannel(
+          channel, false /* powerwash_allowed */, &error_message)) {
+    brillo::Error::AddTo(error,
+                         FROM_HERE,
+                         brillo::errors::dbus::kDomain,
+                         "_set_target_error",
+                         error_message);
+    return false;
+  }
+  return true;
+}
+
+bool UpdateAttempter::GetWeaveState(int64_t* last_checked_time,
+                                    double* progress,
+                                    UpdateStatus* update_status,
+                                    string* current_channel,
+                                    string* tracking_channel) {
+  *last_checked_time = last_checked_time_;
+  *progress = download_progress_;
+  *update_status = status_;
+  OmahaRequestParams* rp = system_state_->request_params();
+  *current_channel = rp->current_channel();
+  *tracking_channel = rp->target_channel();
+  return true;
+}
+
 bool UpdateAttempter::ResetStatus() {
   LOG(INFO) << "Attempting to reset state from "
             << UpdateStatusToString(status_) << " to UpdateStatus::IDLE";
@@ -1172,6 +1208,9 @@
 }
 
 void UpdateAttempter::BroadcastStatus() {
+  if (system_state_->weave_service())
+    system_state_->weave_service()->UpdateWeaveState();
+
   if (!dbus_adaptor_)
     return;
   last_notify_time_ = TimeTicks::Now();
diff --git a/update_attempter.h b/update_attempter.h
index cfe3e32..3a2c30d 100644
--- a/update_attempter.h
+++ b/update_attempter.h
@@ -41,6 +41,7 @@
 #include "update_engine/system_state.h"
 #include "update_engine/update_manager/policy.h"
 #include "update_engine/update_manager/update_manager.h"
+#include "update_engine/weave_service_interface.h"
 
 class MetricsLibraryInterface;
 
@@ -54,7 +55,8 @@
 
 class UpdateAttempter : public ActionProcessorDelegate,
                         public DownloadActionDelegate,
-                        public CertificateChecker::Observer {
+                        public CertificateChecker::Observer,
+                        public WeaveServiceInterface::DelegateInterface {
  public:
   using UpdateStatus = update_engine::UpdateStatus;
   static const int kMaxDeltaUpdateFailures;
@@ -93,6 +95,16 @@
                        AbstractAction* action,
                        ErrorCode code) override;
 
+  // WeaveServiceInterface::DelegateInterface overrides.
+  bool OnCheckForUpdates(brillo::ErrorPtr* error) override;
+  bool OnTrackChannel(const std::string& channel,
+                      brillo::ErrorPtr* error) override;
+  bool GetWeaveState(int64_t* last_checked_time,
+                     double* progress,
+                     UpdateStatus* update_status,
+                     std::string* current_channel,
+                     std::string* tracking_channel) override;
+
   // Resets the current state to UPDATE_STATUS_IDLE.
   // Used by update_engine_client for restarting a new update without
   // having to reboot once the previous update has reached
diff --git a/update_engine.gyp b/update_engine.gyp
index 01d691d..5490a2a 100644
--- a/update_engine.gyp
+++ b/update_engine.gyp
@@ -27,6 +27,7 @@
       'USE_hwid_override%': '0',
       'USE_mtd%': '0',
       'USE_power_management%': '0',
+      'USE_buffet%': '0',
     },
     'cflags': [
       '-g',
@@ -50,6 +51,7 @@
       'USE_HWID_OVERRIDE=<(USE_hwid_override)',
       'USE_MTD=<(USE_mtd)',
       'USE_POWER_MANAGEMENT=<(USE_power_management)',
+      'USE_WEAVE=<(USE_buffet)',
     ],
     'include_dirs': [
       # We need this include dir because we include all the local code as
@@ -272,6 +274,19 @@
         'update_manager/state_factory.cc',
         'update_manager/update_manager.cc',
         'update_status_utils.cc',
+        'weave_service_factory.cc',
+      ],
+      'conditions': [
+        ['USE_buffet == 1', {
+          'sources': [
+            'weave_service.cc',
+          ],
+          'variables': {
+            'exported_deps': [
+              'libweave-<(libbase_ver)',
+            ],
+          },
+        }],
       ],
     },
     # update_engine daemon.
diff --git a/update_status_utils.cc b/update_status_utils.cc
index ff039b8..9685853 100644
--- a/update_status_utils.cc
+++ b/update_status_utils.cc
@@ -20,6 +20,21 @@
 
 using update_engine::UpdateStatus;
 
+namespace {
+
+const char kWeaveStatusIdle[] = "idle";
+const char kWeaveStatusCheckingForUpdate[] = "checkingForUpdate";
+const char kWeaveStatusUpdateAvailable[] = "updateAvailable";
+const char kWeaveStatusDownloading[] = "downloading";
+const char kWeaveStatusVerifying[] = "verifying";
+const char kWeaveStatusFinalizing[] = "finalizing";
+const char kWeaveStatusUpdatedNeedReboot[] = "updatedNeedReboot";
+const char kWeaveStatusReportingErrorEvent[] = "reportingErrorEvent";
+const char kWeaveStatusAttemptingRollback[] = "attemptingRollback";
+const char kWeaveStatusDisabled[] = "disabled";
+
+}  // namespace
+
 namespace chromeos_update_engine {
 
 const char* UpdateStatusToString(const UpdateStatus& status) {
@@ -50,6 +65,34 @@
   return nullptr;
 }
 
+const char* UpdateStatusToWeaveStatus(const UpdateStatus& status) {
+  switch (status) {
+    case UpdateStatus::IDLE:
+      return kWeaveStatusIdle;
+    case UpdateStatus::CHECKING_FOR_UPDATE:
+      return kWeaveStatusCheckingForUpdate;
+    case UpdateStatus::UPDATE_AVAILABLE:
+      return kWeaveStatusUpdateAvailable;
+    case UpdateStatus::DOWNLOADING:
+      return kWeaveStatusDownloading;
+    case UpdateStatus::VERIFYING:
+      return kWeaveStatusVerifying;
+    case UpdateStatus::FINALIZING:
+      return kWeaveStatusFinalizing;
+    case UpdateStatus::UPDATED_NEED_REBOOT:
+      return kWeaveStatusUpdatedNeedReboot;
+    case UpdateStatus::REPORTING_ERROR_EVENT:
+      return kWeaveStatusReportingErrorEvent;
+    case UpdateStatus::ATTEMPTING_ROLLBACK:
+      return kWeaveStatusAttemptingRollback;
+    case UpdateStatus::DISABLED:
+      return kWeaveStatusDisabled;
+  }
+
+  NOTREACHED();
+  return nullptr;
+}
+
 bool StringToUpdateStatus(const std::string& s,
                           UpdateStatus* status) {
   if (s == update_engine::kUpdateStatusIdle) {
diff --git a/update_status_utils.h b/update_status_utils.h
index 30ae53b..9d85144 100644
--- a/update_status_utils.h
+++ b/update_status_utils.h
@@ -25,6 +25,10 @@
 
 const char* UpdateStatusToString(const update_engine::UpdateStatus& status);
 
+// Convert the UpdateStatus |status| to the string reported in the weave status.
+const char* UpdateStatusToWeaveStatus(
+    const update_engine::UpdateStatus& status);
+
 bool StringToUpdateStatus(const std::string& update_status_as_string,
                           update_engine::UpdateStatus* status);
 
diff --git a/weave_service.cc b/weave_service.cc
new file mode 100644
index 0000000..367359a
--- /dev/null
+++ b/weave_service.cc
@@ -0,0 +1,119 @@
+//
+// 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/weave_service.h"
+
+#include <cmath>
+#include <string>
+
+#include <base/bind.h>
+#include <base/values.h>
+#include <brillo/errors/error.h>
+
+#include "update_engine/update_status_utils.h"
+
+using std::string;
+
+namespace {
+
+const char kWeaveComponent[] = "updater";
+
+}  // namespace
+
+namespace chromeos_update_engine {
+
+bool WeaveService::Init(scoped_refptr<dbus::Bus> bus,
+                        DelegateInterface* delegate) {
+  delegate_ = delegate;
+  device_ = weaved::Device::CreateInstance(
+      bus, base::Bind(&WeaveService::UpdateWeaveState, base::Unretained(this)));
+  device_->AddComponent(kWeaveComponent, {"_updater"});
+  device_->AddCommandHandler(
+      kWeaveComponent,
+      "_updater.checkForUpdates",
+      base::Bind(&WeaveService::OnCheckForUpdates, base::Unretained(this)));
+  device_->AddCommandHandler(
+      kWeaveComponent,
+      "_updater.trackChannel",
+      base::Bind(&WeaveService::OnTrackChannel, base::Unretained(this)));
+
+  return true;
+}
+
+void WeaveService::UpdateWeaveState() {
+  if (!device_ || !delegate_)
+    return;
+
+  int64_t last_checked_time;
+  double progress;
+  update_engine::UpdateStatus update_status;
+  string current_channel;
+  string tracking_channel;
+
+  if (!delegate_->GetWeaveState(&last_checked_time,
+                                &progress,
+                                &update_status,
+                                &current_channel,
+                                &tracking_channel))
+    return;
+
+  // Round to progress to 1% (0.01) to avoid excessive and meaningless state
+  // changes.
+  progress = std::floor(progress * 100.) / 100.;
+
+  brillo::VariantDictionary state{
+      {"_updater.currentChannel", current_channel},
+      {"_updater.trackingChannel", tracking_channel},
+      {"_updater.status", UpdateStatusToWeaveStatus(update_status)},
+      {"_updater.progress", progress},
+      {"_updater.lastUpdateCheckTimestamp",
+       static_cast<double>(last_checked_time)},
+  };
+
+  if (!device_->SetStateProperties(kWeaveComponent, state, nullptr)) {
+    LOG(ERROR) << "Failed to update _updater state.";
+  }
+}
+
+void WeaveService::OnCheckForUpdates(
+    const std::weak_ptr<weaved::Command>& cmd) {
+  auto command = cmd.lock();
+  if (!command)
+    return;
+
+  brillo::ErrorPtr error;
+  if (!delegate_->OnCheckForUpdates(&error)) {
+    command->Abort(error->GetCode(), error->GetMessage(), nullptr);
+    return;
+  }
+  command->Complete({}, nullptr);
+}
+
+void WeaveService::OnTrackChannel(const std::weak_ptr<weaved::Command>& cmd) {
+  auto command = cmd.lock();
+  if (!command)
+    return;
+
+  string channel = command->GetParameter<string>("channel");
+  brillo::ErrorPtr error;
+  if (!delegate_->OnTrackChannel(channel, &error)) {
+    command->Abort(error->GetCode(), error->GetMessage(), nullptr);
+    return;
+  }
+  command->Complete({}, nullptr);
+}
+
+}  // namespace chromeos_update_engine
diff --git a/weave_service.h b/weave_service.h
new file mode 100644
index 0000000..6790d54
--- /dev/null
+++ b/weave_service.h
@@ -0,0 +1,53 @@
+//
+// 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.
+//
+
+#ifndef UPDATE_ENGINE_WEAVE_SERVICE_H_
+#define UPDATE_ENGINE_WEAVE_SERVICE_H_
+
+#include <memory>
+
+#include <dbus/bus.h>
+#include <libweaved/command.h>
+#include <libweaved/device.h>
+
+#include "update_engine/weave_service_interface.h"
+
+namespace chromeos_update_engine {
+
+class WeaveService : public WeaveServiceInterface {
+ public:
+  WeaveService() = default;
+  ~WeaveService() override = default;
+
+  bool Init(scoped_refptr<dbus::Bus> bus, DelegateInterface* delegate);
+
+  // WeaveServiceInterface override.
+  void UpdateWeaveState() override;
+
+ private:
+  // Weave command handlers. These are called from the message loop whenever a
+  // command is received and dispatch the synchronous call to the |delegate_|.
+  void OnCheckForUpdates(const std::weak_ptr<weaved::Command>& cmd);
+  void OnTrackChannel(const std::weak_ptr<weaved::Command>& cmd);
+
+  WeaveServiceInterface::DelegateInterface* delegate_{nullptr};
+
+  std::unique_ptr<weaved::Device> device_;
+};
+
+}  // namespace chromeos_update_engine
+
+#endif  // UPDATE_ENGINE_WEAVE_SERVICE_H_
diff --git a/weave_service_factory.cc b/weave_service_factory.cc
new file mode 100644
index 0000000..793e906
--- /dev/null
+++ b/weave_service_factory.cc
@@ -0,0 +1,41 @@
+//
+// 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/weave_service_factory.h"
+
+#if USE_WEAVE
+#include "update_engine/weave_service.h"
+#endif
+
+namespace chromeos_update_engine {
+
+std::unique_ptr<WeaveServiceInterface> ConstructWeaveService(
+    const scoped_refptr<dbus::Bus>& bus,
+    WeaveServiceInterface::DelegateInterface* delegate) {
+  std::unique_ptr<WeaveServiceInterface> result;
+  if (!delegate || !bus.get())
+    return result;
+
+#if USE_WEAVE
+  WeaveService* weave_service = new WeaveService();
+  result.reset(weave_service);
+  if (!weave_service->Init(bus, delegate))
+    result.reset();
+#endif
+  return result;
+}
+
+}  // namespace chromeos_update_engine
diff --git a/weave_service_factory.h b/weave_service_factory.h
new file mode 100644
index 0000000..b32e0b7
--- /dev/null
+++ b/weave_service_factory.h
@@ -0,0 +1,37 @@
+//
+// 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.
+//
+
+#ifndef UPDATE_ENGINE_WEAVE_SERVICE_FACTORY_H_
+#define UPDATE_ENGINE_WEAVE_SERVICE_FACTORY_H_
+
+#include <memory>
+
+#include <base/memory/ref_counted.h>
+#include <dbus/bus.h>
+
+#include "update_engine/weave_service_interface.h"
+
+namespace chromeos_update_engine {
+
+// Create a new WeaveServiceInterface instance. In case of error or when weaved
+// is disabled, returns an empty pointer.
+std::unique_ptr<WeaveServiceInterface> ConstructWeaveService(
+    const scoped_refptr<dbus::Bus>& bus,
+    WeaveServiceInterface::DelegateInterface* delegate);
+
+}  // namespace chromeos_update_engine
+
+#endif  // UPDATE_ENGINE_WEAVE_SERVICE_FACTORY_H_
diff --git a/weave_service_interface.h b/weave_service_interface.h
new file mode 100644
index 0000000..baaa9db
--- /dev/null
+++ b/weave_service_interface.h
@@ -0,0 +1,64 @@
+//
+// 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.
+//
+
+#ifndef UPDATE_ENGINE_WEAVE_SERVICE_INTERFACE_H_
+#define UPDATE_ENGINE_WEAVE_SERVICE_INTERFACE_H_
+
+#include <string>
+
+#include <brillo/errors/error.h>
+
+#include "update_engine/client_library/include/update_engine/update_status.h"
+
+namespace chromeos_update_engine {
+
+// A WeaveServiceInterface instance allows to register the daemon with weaved,
+// handle commands and update the weave status. This class only handles the
+// 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 {
+ public:
+  // The delegate class that actually handles the command execution from
+  class DelegateInterface {
+   public:
+    virtual ~DelegateInterface() = default;
+
+    virtual bool OnCheckForUpdates(brillo::ErrorPtr* error) = 0;
+
+    virtual bool OnTrackChannel(const std::string& channel,
+                                brillo::ErrorPtr* error) = 0;
+
+    // Return the current status.
+    virtual bool GetWeaveState(int64_t* last_checked_time,
+                               double* progress,
+                               update_engine::UpdateStatus* update_status,
+                               std::string* current_channel,
+                               std::string* tracking_channel) = 0;
+  };
+
+  virtual ~WeaveServiceInterface() = default;
+
+  // Force a weave state update.
+  virtual void UpdateWeaveState() = 0;
+
+ protected:
+  WeaveServiceInterface() = default;
+};
+
+}  // namespace chromeos_update_engine
+
+#endif  // UPDATE_ENGINE_WEAVE_SERVICE_INTERFACE_H_
diff --git a/weaved/traits/updater.json b/weaved/traits/updater.json
new file mode 100644
index 0000000..52b1a55
--- /dev/null
+++ b/weaved/traits/updater.json
@@ -0,0 +1,52 @@
+{
+  "_updater": {
+    "commands": {
+      "checkForUpdates": {
+        "minimalRole": "manager",
+        "parameters": {}
+      },
+      "trackChannel": {
+        "minimalRole": "manager",
+        "parameters": {
+          "channel": {
+            "type": "string",
+            "enum": ["stable-channel", "beta-channel", "dev-channel", "canary-channel"]
+          }
+        }
+      }
+    },
+    "state": {
+      "currentChannel": {
+        "type": "string",
+        "enum": ["stable-channel", "beta-channel", "dev-channel", "canary-channel"]
+      },
+      "trackingChannel": {
+        "type": "string",
+        "enum": ["stable-channel", "beta-channel", "dev-channel", "canary-channel"]
+      },
+      "status": {
+        "type": "string",
+        "enum": [
+          "idle",
+          "checkingForUpdate",
+          "updateAvailable",
+          "downloading",
+          "verifying",
+          "finalizing",
+          "updatedNeedReboot",
+          "reportingErrorEvent",
+          "attemptingRollback",
+          "disabled"
+        ]
+      },
+      "progress": {
+        "type": "number",
+        "minimum": 0,
+        "maximum": 1
+      },
+      "lastUpdateCheckTimestamp": {
+        "type": "number"
+      }
+    }
+  }
+}