Merge branch 'cros/upstream' into 'cros/master'

Fixed:
	connection_manager_interface.h: remove line 53-56
	fix the assert in common/http_fetcher_unittest.cc:637

BUG=none
TEST=sent squashed merge to buildbots and HWtest was success.

Change-Id: I15037921592a2b7a4dd76dff71417d03caf97cf6
diff --git a/.gitignore b/.gitignore
index d6dd317..ced5927 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,3 +9,4 @@
 /update_engine.dbusserver.h
 /update_engine_client
 /update_engine_unittests
+*.pyc
diff --git a/Android.mk b/Android.mk
index 0da1b90..a7e6836 100644
--- a/Android.mk
+++ b/Android.mk
@@ -20,25 +20,22 @@
 # by setting BRILLO_USE_* values. Note that we define local variables like
 # local_use_* to prevent leaking our default setting for other packages.
 local_use_binder := $(if $(BRILLO_USE_BINDER),$(BRILLO_USE_BINDER),1)
-local_use_dbus := $(if $(BRILLO_USE_DBUS),$(BRILLO_USE_DBUS),0)
 local_use_hwid_override := \
     $(if $(BRILLO_USE_HWID_OVERRIDE),$(BRILLO_USE_HWID_OVERRIDE),0)
 # "libcros" gates the LibCrosService exposed by the Chrome OS' chrome browser to
 # the system layer.
 local_use_libcros := $(if $(BRILLO_USE_LIBCROS),$(BRILLO_USE_LIBCROS),0)
 local_use_mtd := $(if $(BRILLO_USE_MTD),$(BRILLO_USE_MTD),0)
-local_use_power_management := \
-    $(if $(BRILLO_USE_POWER_MANAGEMENT),$(BRILLO_USE_POWER_MANAGEMENT),0)
-local_use_weave := $(if $(BRILLO_USE_WEAVE),$(BRILLO_USE_WEAVE),0)
+
+# IoT devices use Omaha for updates.
+local_use_omaha := $(if $(filter true,$(PRODUCT_IOT)),1,0)
 
 ue_common_cflags := \
     -DUSE_BINDER=$(local_use_binder) \
-    -DUSE_DBUS=$(local_use_dbus) \
     -DUSE_HWID_OVERRIDE=$(local_use_hwid_override) \
     -DUSE_LIBCROS=$(local_use_libcros) \
     -DUSE_MTD=$(local_use_mtd) \
-    -DUSE_POWER_MANAGEMENT=$(local_use_power_management) \
-    -DUSE_WEAVE=$(local_use_weave) \
+    -DUSE_OMAHA=$(local_use_omaha) \
     -D_FILE_OFFSET_BITS=64 \
     -D_POSIX_C_SOURCE=199309L \
     -Wa,--noexecstack \
@@ -53,34 +50,18 @@
     -fvisibility=hidden
 ue_common_cppflags := \
     -Wnon-virtual-dtor \
-    -fno-strict-aliasing \
-    -std=gnu++11
+    -fno-strict-aliasing
 ue_common_ldflags := \
     -Wl,--gc-sections
 ue_common_c_includes := \
     $(LOCAL_PATH)/client_library/include \
-    external/gtest/include \
     system
 ue_common_shared_libraries := \
-    libbrillo \
-    libbrillo-http \
     libbrillo-stream \
+    libbrillo \
     libchrome
-
-ifeq ($(local_use_dbus),1)
-
-# update_engine_client-dbus-proxies (from generate-dbus-proxies.gypi)
-# ========================================================
-include $(CLEAR_VARS)
-LOCAL_MODULE := update_engine_client-dbus-proxies
-LOCAL_MODULE_CLASS := STATIC_LIBRARIES
-LOCAL_SRC_FILES := \
-    dbus_bindings/dbus-service-config.json \
-    dbus_bindings/org.chromium.UpdateEngineInterface.dbus-xml
-LOCAL_DBUS_PROXY_PREFIX := update_engine
-include $(BUILD_STATIC_LIBRARY)
-
-endif  # local_use_dbus == 1
+ue_common_static_libraries := \
+    libgtest_prod \
 
 # update_metadata-protos (type: static_library)
 # ========================================================
@@ -112,59 +93,31 @@
 LOCAL_SRC_FILES := $(ue_update_metadata_protos_src_files)
 include $(BUILD_STATIC_LIBRARY)
 
-ifeq ($(local_use_dbus),1)
-
-# update_engine-dbus-adaptor (from generate-dbus-adaptors.gypi)
-# ========================================================
-# Chrome D-Bus bindings.
-include $(CLEAR_VARS)
-LOCAL_MODULE := update_engine-dbus-adaptor
-LOCAL_MODULE_CLASS := STATIC_LIBRARIES
-LOCAL_SRC_FILES := \
-    dbus_bindings/org.chromium.UpdateEngineInterface.dbus-xml
-include $(BUILD_STATIC_LIBRARY)
-
-# update_engine-dbus-libcros-client (from generate-dbus-proxies.gypi)
-# ========================================================
-include $(CLEAR_VARS)
-LOCAL_MODULE := update_engine-dbus-libcros-client
-LOCAL_MODULE_CLASS := STATIC_LIBRARIES
-LOCAL_SRC_FILES := \
-    dbus_bindings/org.chromium.LibCrosService.dbus-xml
-LOCAL_DBUS_PROXY_PREFIX := libcros
-include $(BUILD_STATIC_LIBRARY)
-
-endif  # local_use_dbus == 1
-
 # libpayload_consumer (type: static_library)
 # ========================================================
 # The payload application component and common dependencies.
 ue_libpayload_consumer_exported_static_libraries := \
     update_metadata-protos \
-    libxz-host \
+    libxz \
     libbz \
-    libimgpatch \
-    libz \
+    libbspatch \
     $(ue_update_metadata_protos_exported_static_libraries)
 ue_libpayload_consumer_exported_shared_libraries := \
-    libcrypto-host \
-    libcurl-host \
-    libssl-host \
+    libcrypto \
     $(ue_update_metadata_protos_exported_shared_libraries)
 
 ue_libpayload_consumer_src_files := \
     common/action_processor.cc \
     common/boot_control_stub.cc \
-    common/certificate_checker.cc \
     common/clock.cc \
     common/constants.cc \
     common/cpu_limiter.cc \
     common/error_code_utils.cc \
+    common/file_fetcher.cc \
     common/hash_calculator.cc \
     common/http_common.cc \
     common/http_fetcher.cc \
     common/hwid_override.cc \
-    common/libcurl_http_fetcher.cc \
     common/multi_range_http_fetcher.cc \
     common/platform_constants_android.cc \
     common/prefs.cc \
@@ -198,6 +151,7 @@
     $(ue_common_c_includes)
 LOCAL_STATIC_LIBRARIES := \
     update_metadata-protos \
+    $(ue_common_static_libraries) \
     $(ue_libpayload_consumer_exported_static_libraries) \
     $(ue_update_metadata_protos_exported_static_libraries)
 LOCAL_SHARED_LIBRARIES := \
@@ -221,6 +175,7 @@
     $(ue_common_c_includes)
 LOCAL_STATIC_LIBRARIES := \
     update_metadata-protos \
+    $(ue_common_static_libraries) \
     $(ue_libpayload_consumer_exported_static_libraries:-host=) \
     $(ue_update_metadata_protos_exported_static_libraries)
 LOCAL_SHARED_LIBRARIES := \
@@ -230,37 +185,70 @@
 LOCAL_SRC_FILES := $(ue_libpayload_consumer_src_files)
 include $(BUILD_STATIC_LIBRARY)
 
-ifdef BRILLO
+# libupdate_engine_boot_control (type: static_library)
+# ========================================================
+# A BootControl class implementation using Android's HIDL boot_control HAL.
+ue_libupdate_engine_boot_control_exported_static_libraries := \
+    update_metadata-protos \
+    $(ue_update_metadata_protos_exported_static_libraries)
+
+ue_libupdate_engine_boot_control_exported_shared_libraries := \
+    libhwbinder \
+    libhidlbase \
+    libutils \
+    android.hardware.boot@1.0 \
+    $(ue_update_metadata_protos_exported_shared_libraries)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := libupdate_engine_boot_control
+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) \
+    bootable/recovery
+LOCAL_STATIC_LIBRARIES := \
+    $(ue_common_static_libraries) \
+    $(ue_libupdate_engine_boot_control_exported_static_libraries)
+LOCAL_SHARED_LIBRARIES := \
+    $(ue_common_shared_libraries) \
+    $(ue_libupdate_engine_boot_control_exported_shared_libraries)
+LOCAL_SRC_FILES := \
+    boot_control_android.cc
+include $(BUILD_STATIC_LIBRARY)
+
+ifeq ($(local_use_omaha),1)
 
 # libupdate_engine (type: static_library)
 # ========================================================
 # The main daemon static_library with all the code used to check for updates
 # with Omaha and expose a DBus daemon.
 ue_libupdate_engine_exported_c_includes := \
-    $(LOCAL_PATH)/include \
     external/cros/system_api/dbus
 ue_libupdate_engine_exported_static_libraries := \
     libpayload_consumer \
     update_metadata-protos \
-    update_engine-dbus-adaptor \
-    update_engine-dbus-libcros-client \
-    update_engine_client-dbus-proxies \
     libbz \
     libfs_mgr \
+    libbase \
+    liblog \
     $(ue_libpayload_consumer_exported_static_libraries) \
-    $(ue_update_metadata_protos_exported_static_libraries)
+    $(ue_update_metadata_protos_exported_static_libraries) \
+    libupdate_engine_boot_control \
+    $(ue_libupdate_engine_boot_control_exported_static_libraries)
 ue_libupdate_engine_exported_shared_libraries := \
-    libdbus \
-    libbrillo-dbus \
-    libchrome-dbus \
     libmetrics \
-    libshill-client \
     libexpat \
     libbrillo-policy \
-    libhardware \
+    libcurl \
     libcutils \
+    libssl \
     $(ue_libpayload_consumer_exported_shared_libraries) \
-    $(ue_update_metadata_protos_exported_shared_libraries)
+    $(ue_update_metadata_protos_exported_shared_libraries) \
+    $(ue_libupdate_engine_boot_control_exported_shared_libraries)
 ifeq ($(local_use_binder),1)
 ue_libupdate_engine_exported_shared_libraries += \
     libbinder \
@@ -268,12 +256,6 @@
     libbrillo-binder \
     libutils
 endif  # local_use_binder == 1
-ifeq ($(local_use_weave),1)
-ue_libupdate_engine_exported_shared_libraries += \
-    libbinderwrapper \
-    libbrillo-binder \
-    libweaved
-endif  # local_use_weave == 1
 
 include $(CLEAR_VARS)
 LOCAL_MODULE := libupdate_engine
@@ -286,13 +268,12 @@
 LOCAL_LDFLAGS := $(ue_common_ldflags)
 LOCAL_C_INCLUDES := \
     $(ue_common_c_includes) \
-    $(ue_libupdate_engine_exported_c_includes)
+    $(ue_libupdate_engine_exported_c_includes) \
+    bootable/recovery
 LOCAL_STATIC_LIBRARIES := \
     libpayload_consumer \
     update_metadata-protos \
-    update_engine-dbus-adaptor \
-    update_engine-dbus-libcros-client \
-    update_engine_client-dbus-proxies \
+    $(ue_common_static_libraries) \
     $(ue_libupdate_engine_exported_static_libraries:-host=) \
     $(ue_libpayload_consumer_exported_static_libraries:-host=) \
     $(ue_update_metadata_protos_exported_static_libraries)
@@ -302,14 +283,14 @@
     $(ue_libpayload_consumer_exported_shared_libraries:-host=) \
     $(ue_update_metadata_protos_exported_shared_libraries)
 LOCAL_SRC_FILES := \
-    boot_control_android.cc \
+    certificate_checker.cc \
     common_service.cc \
-    connection_manager.cc \
+    connection_manager_android.cc \
+    connection_utils.cc \
     daemon.cc \
-    dbus_service.cc \
     hardware_android.cc \
     image_properties_android.cc \
-    libcros_proxy.cc \
+    libcurl_http_fetcher.cc \
     metrics.cc \
     metrics_utils.cc \
     omaha_request_action.cc \
@@ -318,9 +299,9 @@
     omaha_utils.cc \
     p2p_manager.cc \
     payload_state.cc \
+    power_manager_android.cc \
     proxy_resolver.cc \
     real_system_state.cc \
-    shill_proxy.cc \
     update_attempter.cc \
     update_manager/boxed_value.cc \
     update_manager/chromeos_policy.cc \
@@ -330,14 +311,13 @@
     update_manager/real_config_provider.cc \
     update_manager/real_device_policy_provider.cc \
     update_manager/real_random_provider.cc \
-    update_manager/real_shill_provider.cc \
     update_manager/real_system_provider.cc \
     update_manager/real_time_provider.cc \
     update_manager/real_updater_provider.cc \
     update_manager/state_factory.cc \
     update_manager/update_manager.cc \
     update_status_utils.cc \
-    weave_service_factory.cc
+    utils_android.cc
 ifeq ($(local_use_binder),1)
 LOCAL_AIDL_INCLUDES += $(LOCAL_PATH)/binder_bindings
 LOCAL_SRC_FILES += \
@@ -346,17 +326,13 @@
     binder_service_brillo.cc \
     parcelable_update_engine_status.cc
 endif  # local_use_binder == 1
-ifeq ($(local_use_weave),1)
-LOCAL_SRC_FILES += \
-    weave_service.cc
-endif  # local_use_weave == 1
 ifeq ($(local_use_libcros),1)
 LOCAL_SRC_FILES += \
     chrome_browser_proxy_resolver.cc
 endif  # local_use_libcros == 1
 include $(BUILD_STATIC_LIBRARY)
 
-else  # !defined(BRILLO)
+else  # local_use_omaha == 1
 
 ifneq ($(local_use_binder),1)
 $(error USE_BINDER is disabled but is required in non-Brillo devices.)
@@ -369,14 +345,21 @@
 ue_libupdate_engine_android_exported_static_libraries := \
     libpayload_consumer \
     libfs_mgr \
-    $(ue_libpayload_consumer_exported_static_libraries)
+    libbase \
+    liblog \
+    $(ue_libpayload_consumer_exported_static_libraries) \
+    libupdate_engine_boot_control \
+    $(ue_libupdate_engine_boot_control_exported_static_libraries)
 ue_libupdate_engine_android_exported_shared_libraries := \
     $(ue_libpayload_consumer_exported_shared_libraries) \
+    $(ue_libupdate_engine_boot_control_exported_shared_libraries) \
+    libandroid_net \
     libbinder \
     libbinderwrapper \
     libbrillo-binder \
     libcutils \
-    libhardware \
+    libcurl \
+    libssl \
     libutils
 
 include $(CLEAR_VARS)
@@ -387,12 +370,15 @@
 LOCAL_CFLAGS := $(ue_common_cflags)
 LOCAL_CPPFLAGS := $(ue_common_cppflags)
 LOCAL_LDFLAGS := $(ue_common_ldflags)
-LOCAL_C_INCLUDES :=  $(ue_common_c_includes)
+LOCAL_C_INCLUDES := \
+    $(ue_common_c_includes) \
+    bootable/recovery
 #TODO(deymo): Remove external/cros/system_api/dbus once the strings are moved
 # out of the DBus interface.
 LOCAL_C_INCLUDES += \
     external/cros/system_api/dbus
 LOCAL_STATIC_LIBRARIES := \
+    $(ue_common_static_libraries) \
     $(ue_libupdate_engine_android_exported_static_libraries:-host=)
 LOCAL_SHARED_LIBRARIES += \
     $(ue_common_shared_libraries) \
@@ -402,16 +388,19 @@
     binder_bindings/android/os/IUpdateEngine.aidl \
     binder_bindings/android/os/IUpdateEngineCallback.aidl \
     binder_service_android.cc \
-    boot_control_android.cc \
+    certificate_checker.cc \
     daemon.cc \
     daemon_state_android.cc \
     hardware_android.cc \
+    libcurl_http_fetcher.cc \
+    network_selector_android.cc \
     proxy_resolver.cc \
     update_attempter_android.cc \
-    update_status_utils.cc
+    update_status_utils.cc \
+    utils_android.cc
 include $(BUILD_STATIC_LIBRARY)
 
-endif  # !defined(BRILLO)
+endif  # local_use_omaha == 1
 
 # update_engine (type: executable)
 # ========================================================
@@ -420,11 +409,7 @@
 LOCAL_MODULE := update_engine
 LOCAL_MODULE_CLASS := EXECUTABLES
 LOCAL_REQUIRED_MODULES := \
-    bspatch \
     cacerts_google
-ifeq ($(local_use_weave),1)
-LOCAL_REQUIRED_MODULES += updater.json
-endif  # local_use_weave == 1
 LOCAL_CPP_EXTENSION := .cc
 LOCAL_CLANG := true
 LOCAL_CFLAGS := $(ue_common_cflags)
@@ -434,28 +419,108 @@
     $(ue_common_c_includes)
 LOCAL_SHARED_LIBRARIES := \
     $(ue_common_shared_libraries)
+LOCAL_STATIC_LIBRARIES := \
+    $(ue_common_static_libraries)
 LOCAL_SRC_FILES := \
     main.cc
 
-ifdef BRILLO
+ifeq ($(local_use_omaha),1)
 LOCAL_C_INCLUDES += \
     $(ue_libupdate_engine_exported_c_includes)
-LOCAL_STATIC_LIBRARIES := \
+LOCAL_STATIC_LIBRARIES += \
     libupdate_engine \
     $(ue_libupdate_engine_exported_static_libraries:-host=)
 LOCAL_SHARED_LIBRARIES += \
     $(ue_libupdate_engine_exported_shared_libraries:-host=)
-else  # !defined(BRILLO)
-LOCAL_STATIC_LIBRARIES := \
+else  # local_use_omaha == 1
+LOCAL_STATIC_LIBRARIES += \
     libupdate_engine_android \
     $(ue_libupdate_engine_android_exported_static_libraries:-host=)
 LOCAL_SHARED_LIBRARIES += \
     $(ue_libupdate_engine_android_exported_shared_libraries:-host=)
-endif  # !defined(BRILLO)
+endif  # local_use_omaha == 1
 
 LOCAL_INIT_RC := update_engine.rc
 include $(BUILD_EXECUTABLE)
 
+# update_engine_sideload (type: executable)
+# ========================================================
+# A static binary equivalent to update_engine daemon that installs an update
+# from a local file directly instead of running in the background.
+include $(CLEAR_VARS)
+LOCAL_MODULE := update_engine_sideload
+LOCAL_FORCE_STATIC_EXECUTABLE := true
+LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/sbin
+LOCAL_MODULE_CLASS := EXECUTABLES
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_CLANG := true
+LOCAL_CFLAGS := \
+    $(ue_common_cflags) \
+    -D_UE_SIDELOAD
+LOCAL_CPPFLAGS := $(ue_common_cppflags)
+LOCAL_LDFLAGS := $(ue_common_ldflags)
+LOCAL_C_INCLUDES := \
+    $(ue_common_c_includes) \
+    bootable/recovery
+#TODO(deymo): Remove external/cros/system_api/dbus once the strings are moved
+# out of the DBus interface.
+LOCAL_C_INCLUDES += \
+    external/cros/system_api/dbus
+LOCAL_SRC_FILES := \
+    boot_control_recovery.cc \
+    hardware_android.cc \
+    network_selector_stub.cc \
+    proxy_resolver.cc \
+    sideload_main.cc \
+    update_attempter_android.cc \
+    update_status_utils.cc \
+    utils_android.cc
+LOCAL_STATIC_LIBRARIES := \
+    libfs_mgr \
+    libbase \
+    liblog \
+    libpayload_consumer \
+    update_metadata-protos \
+    $(ue_common_static_libraries) \
+    $(ue_libpayload_consumer_exported_static_libraries:-host=) \
+    $(ue_update_metadata_protos_exported_static_libraries)
+# We add the static versions of the shared libraries since we are forcing this
+# binary to be a static binary, so we also need to include all the static
+# library dependencies of these static libraries.
+LOCAL_STATIC_LIBRARIES += \
+    $(ue_common_shared_libraries) \
+    libcutils \
+    liblog \
+    $(ue_libpayload_consumer_exported_shared_libraries:-host=) \
+    $(ue_update_metadata_protos_exported_shared_libraries) \
+    libevent \
+    libmodpb64 \
+    libgtest_prod
+# libchrome requires these extra LDFLAGS which are not propagated through the
+# build system.
+LOCAL_LDFLAGS += \
+    -Wl,-wrap,calloc \
+    -Wl,-wrap,free \
+    -Wl,-wrap,malloc \
+    -Wl,-wrap,memalign \
+    -Wl,-wrap,realloc
+
+ifeq ($(strip $(PRODUCT_STATIC_BOOT_CONTROL_HAL)),)
+# No static boot_control HAL defined, so no sideload support. We use a fake
+# boot_control HAL to allow compiling update_engine_sideload for test purposes.
+ifeq ($(strip $(AB_OTA_UPDATER)),true)
+$(warning No PRODUCT_STATIC_BOOT_CONTROL_HAL configured but AB_OTA_UPDATER is \
+true, no update sideload support.)
+endif  # AB_OTA_UPDATER == true
+LOCAL_SRC_FILES += \
+    boot_control_recovery_stub.cc
+else  # PRODUCT_STATIC_BOOT_CONTROL_HAL != ""
+LOCAL_STATIC_LIBRARIES += \
+    $(PRODUCT_STATIC_BOOT_CONTROL_HAL)
+endif  # PRODUCT_STATIC_BOOT_CONTROL_HAL != ""
+
+include $(BUILD_EXECUTABLE)
+
 # libupdate_engine_client (type: shared_library)
 # ========================================================
 include $(CLEAR_VARS)
@@ -464,7 +529,6 @@
     -Wall \
     -Werror \
     -Wno-unused-parameter \
-    -DUSE_DBUS=$(local_use_dbus) \
     -DUSE_BINDER=$(local_use_binder)
 LOCAL_CLANG := true
 LOCAL_CPP_EXTENSION := .cc
@@ -472,8 +536,7 @@
 LOCAL_C_INCLUDES := \
     $(LOCAL_PATH)/client_library/include \
     external/cros/system_api/dbus \
-    system \
-    external/gtest/include
+    system
 LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/client_library/include
 LOCAL_SHARED_LIBRARIES := \
     libchrome \
@@ -482,8 +545,7 @@
     client_library/client.cc \
     update_status_utils.cc
 
-# We can only compile support for one IPC mechanism. If both "binder" and "dbus"
-# are defined, we prefer binder.
+# We only support binder IPC mechanism in Android.
 ifeq ($(local_use_binder),1)
 LOCAL_AIDL_INCLUDES := $(LOCAL_PATH)/binder_bindings
 LOCAL_SHARED_LIBRARIES += \
@@ -495,14 +557,6 @@
     binder_bindings/android/brillo/IUpdateEngineStatusCallback.aidl \
     client_library/client_binder.cc \
     parcelable_update_engine_status.cc
-else  # local_use_binder != 1
-LOCAL_STATIC_LIBRARIES := \
-    update_engine_client-dbus-proxies
-LOCAL_SHARED_LIBRARIES += \
-    libchrome-dbus \
-    libbrillo-dbus
-LOCAL_SRC_FILES += \
-    client_library/client_dbus.cc
 endif  # local_use_binder == 1
 
 include $(BUILD_SHARED_LIBRARY)
@@ -520,14 +574,15 @@
 LOCAL_LDFLAGS := $(ue_common_ldflags)
 LOCAL_C_INCLUDES := $(ue_common_c_includes)
 LOCAL_SHARED_LIBRARIES := $(ue_common_shared_libraries)
-ifdef BRILLO
+LOCAL_STATIC_LIBRARIES := $(ue_common_static_libraries)
+ifeq ($(local_use_omaha),1)
 LOCAL_SHARED_LIBRARIES += \
     libupdate_engine_client
 LOCAL_SRC_FILES := \
     update_engine_client.cc \
     common/error_code_utils.cc \
     omaha_utils.cc
-else  # !defined(BRILLO)
+else  # local_use_omaha == 1
 #TODO(deymo): Remove external/cros/system_api/dbus once the strings are moved
 # out of the DBus interface.
 LOCAL_C_INCLUDES += \
@@ -544,7 +599,7 @@
     common/error_code_utils.cc \
     update_engine_client_android.cc \
     update_status_utils.cc
-endif  # !defined(BRILLO)
+endif  # local_use_omaha == 1
 include $(BUILD_EXECUTABLE)
 
 # libpayload_generator (type: static_library)
@@ -558,7 +613,7 @@
     $(ue_libpayload_consumer_exported_static_libraries) \
     $(ue_update_metadata_protos_exported_static_libraries)
 ue_libpayload_generator_exported_shared_libraries := \
-    libext2fs-host \
+    libext2fs \
     $(ue_libpayload_consumer_exported_shared_libraries) \
     $(ue_update_metadata_protos_exported_shared_libraries)
 
@@ -578,6 +633,7 @@
     payload_generator/graph_types.cc \
     payload_generator/graph_utils.cc \
     payload_generator/inplace_generator.cc \
+    payload_generator/mapfile_filesystem.cc \
     payload_generator/payload_file.cc \
     payload_generator/payload_generation_config.cc \
     payload_generator/payload_signer.cc \
@@ -601,6 +657,7 @@
     libpayload_consumer \
     update_metadata-protos \
     liblzma \
+    $(ue_common_static_libraries) \
     $(ue_libpayload_consumer_exported_static_libraries) \
     $(ue_update_metadata_protos_exported_static_libraries)
 LOCAL_SHARED_LIBRARIES := \
@@ -626,6 +683,7 @@
     libpayload_consumer \
     update_metadata-protos \
     liblzma \
+    $(ue_common_static_libraries) \
     $(ue_libpayload_consumer_exported_static_libraries:-host=) \
     $(ue_update_metadata_protos_exported_static_libraries)
 LOCAL_SHARED_LIBRARIES := \
@@ -659,6 +717,7 @@
 LOCAL_STATIC_LIBRARIES := \
     libpayload_consumer \
     libpayload_generator \
+    $(ue_common_static_libraries) \
     $(ue_libpayload_consumer_exported_static_libraries) \
     $(ue_libpayload_generator_exported_static_libraries)
 LOCAL_SHARED_LIBRARIES := \
@@ -684,6 +743,7 @@
 LOCAL_STATIC_LIBRARIES := \
     libpayload_consumer \
     libpayload_generator \
+    $(ue_common_static_libraries) \
     $(ue_libpayload_consumer_exported_static_libraries:-host=) \
     $(ue_libpayload_generator_exported_static_libraries:-host=)
 LOCAL_SHARED_LIBRARIES := \
@@ -693,10 +753,6 @@
 LOCAL_SRC_FILES := $(ue_delta_generator_src_files)
 include $(BUILD_EXECUTABLE)
 
-# TODO(deymo): Enable the unittest binaries in non-Brillo builds once the DBus
-# dependencies are removed or placed behind the USE_DBUS flag.
-ifdef BRILLO
-
 # Private and public keys for unittests.
 # ========================================================
 # Generate a module that installs a prebuilt private key and a module that
@@ -778,9 +834,6 @@
 # Test HTTP Server.
 include $(CLEAR_VARS)
 LOCAL_MODULE := test_http_server
-ifdef BRILLO
-  LOCAL_MODULE_TAGS := eng
-endif
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_NATIVE_TESTS)/update_engine_unittests
 LOCAL_MODULE_CLASS := EXECUTABLES
 LOCAL_CPP_EXTENSION := .cc
@@ -790,6 +843,7 @@
 LOCAL_LDFLAGS := $(ue_common_ldflags)
 LOCAL_C_INCLUDES := $(ue_common_c_includes)
 LOCAL_SHARED_LIBRARIES := $(ue_common_shared_libraries)
+LOCAL_STATIC_LIBRARIES := $(ue_common_static_libraries)
 LOCAL_SRC_FILES := \
     common/http_common.cc \
     test_http_server.cc
@@ -822,9 +876,6 @@
 # Test helper subprocess program.
 include $(CLEAR_VARS)
 LOCAL_MODULE := test_subprocess
-ifdef BRILLO
-  LOCAL_MODULE_TAGS := eng
-endif
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_NATIVE_TESTS)/update_engine_unittests
 LOCAL_MODULE_CLASS := EXECUTABLES
 LOCAL_CPP_EXTENSION := .cc
@@ -834,6 +885,7 @@
 LOCAL_LDFLAGS := $(ue_common_ldflags)
 LOCAL_C_INCLUDES := $(ue_common_c_includes)
 LOCAL_SHARED_LIBRARIES := $(ue_common_shared_libraries)
+LOCAL_STATIC_LIBRARIES := $(ue_common_static_libraries)
 LOCAL_SRC_FILES := test_subprocess.cc
 include $(BUILD_EXECUTABLE)
 
@@ -842,9 +894,6 @@
 # Main unittest file.
 include $(CLEAR_VARS)
 LOCAL_MODULE := update_engine_unittests
-ifdef BRILLO
-  LOCAL_MODULE_TAGS := eng
-endif
 LOCAL_REQUIRED_MODULES := \
     test_http_server \
     test_subprocess \
@@ -860,7 +909,6 @@
     ue_unittest_key2.pub.pem \
     ue_unittest_update_engine.conf \
     zlib_fingerprint
-LOCAL_MODULE_CLASS := EXECUTABLES
 LOCAL_CPP_EXTENSION := .cc
 LOCAL_CLANG := true
 LOCAL_CFLAGS := $(ue_common_cflags)
@@ -870,25 +918,23 @@
     $(ue_common_c_includes) \
     $(ue_libupdate_engine_exported_c_includes)
 LOCAL_STATIC_LIBRARIES := \
-    libupdate_engine \
     libpayload_generator \
     libbrillo-test-helpers \
     libgmock \
-    libgtest \
     libchrome_test_helpers \
-    $(ue_libupdate_engine_exported_static_libraries:-host=) \
+    $(ue_common_static_libraries) \
     $(ue_libpayload_generator_exported_static_libraries:-host=)
 LOCAL_SHARED_LIBRARIES := \
     $(ue_common_shared_libraries) \
-    $(ue_libupdate_engine_exported_shared_libraries:-host=) \
     $(ue_libpayload_generator_exported_shared_libraries:-host=)
 LOCAL_SRC_FILES := \
+    certificate_checker_unittest.cc \
     common/action_pipe_unittest.cc \
     common/action_processor_unittest.cc \
     common/action_unittest.cc \
-    common/certificate_checker_unittest.cc \
     common/cpu_limiter_unittest.cc \
     common/fake_prefs.cc \
+    common/file_fetcher_unittest.cc \
     common/hash_calculator_unittest.cc \
     common/http_fetcher_unittest.cc \
     common/hwid_override_unittest.cc \
@@ -898,20 +944,9 @@
     common/terminator_unittest.cc \
     common/test_utils.cc \
     common/utils_unittest.cc \
-    common_service_unittest.cc \
-    connection_manager_unittest.cc \
-    fake_shill_proxy.cc \
-    fake_system_state.cc \
-    metrics_utils_unittest.cc \
-    omaha_request_action_unittest.cc \
-    omaha_request_params_unittest.cc \
-    omaha_response_handler_action_unittest.cc \
-    omaha_utils_unittest.cc \
-    p2p_manager_unittest.cc \
     payload_consumer/bzip_extent_writer_unittest.cc \
     payload_consumer/delta_performer_integration_test.cc \
     payload_consumer/delta_performer_unittest.cc \
-    payload_consumer/download_action_unittest.cc \
     payload_consumer/extent_writer_unittest.cc \
     payload_consumer/file_writer_unittest.cc \
     payload_consumer/filesystem_verifier_action_unittest.cc \
@@ -929,12 +964,33 @@
     payload_generator/full_update_generator_unittest.cc \
     payload_generator/graph_utils_unittest.cc \
     payload_generator/inplace_generator_unittest.cc \
+    payload_generator/mapfile_filesystem_unittest.cc \
     payload_generator/payload_file_unittest.cc \
     payload_generator/payload_generation_config_unittest.cc \
     payload_generator/payload_signer_unittest.cc \
     payload_generator/tarjan_unittest.cc \
     payload_generator/topological_sort_unittest.cc \
     payload_generator/zip_unittest.cc \
+    proxy_resolver_unittest.cc \
+    testrunner.cc
+ifeq ($(local_use_omaha),1)
+LOCAL_C_INCLUDES += \
+    $(ue_libupdate_engine_exported_c_includes)
+LOCAL_STATIC_LIBRARIES += \
+    libupdate_engine \
+    $(ue_libupdate_engine_exported_static_libraries:-host=)
+LOCAL_SHARED_LIBRARIES += \
+    $(ue_libupdate_engine_exported_shared_libraries:-host=)
+LOCAL_SRC_FILES += \
+    common_service_unittest.cc \
+    fake_system_state.cc \
+    metrics_utils_unittest.cc \
+    omaha_request_action_unittest.cc \
+    omaha_request_params_unittest.cc \
+    omaha_response_handler_action_unittest.cc \
+    omaha_utils_unittest.cc \
+    p2p_manager_unittest.cc \
+    payload_consumer/download_action_unittest.cc \
     payload_state_unittest.cc \
     proxy_resolver_unittest.cc \
     update_attempter_unittest.cc \
@@ -945,29 +1001,24 @@
     update_manager/prng_unittest.cc \
     update_manager/real_device_policy_provider_unittest.cc \
     update_manager/real_random_provider_unittest.cc \
-    update_manager/real_shill_provider_unittest.cc \
     update_manager/real_system_provider_unittest.cc \
     update_manager/real_time_provider_unittest.cc \
     update_manager/real_updater_provider_unittest.cc \
     update_manager/umtest_utils.cc \
     update_manager/update_manager_unittest.cc \
-    update_manager/variable_unittest.cc \
-    testrunner.cc
+    update_manager/variable_unittest.cc
+else  # local_use_omaha == 1
+LOCAL_STATIC_LIBRARIES += \
+    libupdate_engine_android \
+    $(ue_libupdate_engine_android_exported_static_libraries:-host=)
+LOCAL_SHARED_LIBRARIES += \
+    $(ue_libupdate_engine_android_exported_shared_libraries:-host=)
+endif  # local_use_omaha == 1
 ifeq ($(local_use_libcros),1)
 LOCAL_SRC_FILES += \
     chrome_browser_proxy_resolver_unittest.cc
 endif  # local_use_libcros == 1
 include $(BUILD_NATIVE_TEST)
-endif  # BRILLO
-
-# 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.
 # ========================================================
diff --git a/OWNERS b/OWNERS
index fafbecc..f64bd32 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,4 +1,8 @@
 set noparent
-deymo@chromium.org
-garnold@chromium.org
-zeuthen@chromium.org
+
+# Current general maintainers:
+deymo@google.com
+senj@google.com
+
+# Chromium OS maintainers:
+benchan@google.com
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
new file mode 100644
index 0000000..706dfa8
--- /dev/null
+++ b/PREUPLOAD.cfg
@@ -0,0 +1,3 @@
+[Builtin Hooks]
+clang_format = true
+pylint = true
diff --git a/binder_bindings/android/os/IUpdateEngine.aidl b/binder_bindings/android/os/IUpdateEngine.aidl
index 4c60eed..67f828a 100644
--- a/binder_bindings/android/os/IUpdateEngine.aidl
+++ b/binder_bindings/android/os/IUpdateEngine.aidl
@@ -18,14 +18,21 @@
 
 import android.os.IUpdateEngineCallback;
 
+/** @hide */
 interface IUpdateEngine {
+  /** @hide */
   void applyPayload(String url,
                     in long payload_offset,
                     in long payload_size,
                     in String[] headerKeyValuePairs);
+  /** @hide */
   boolean bind(IUpdateEngineCallback callback);
+  /** @hide */
   void suspend();
+  /** @hide */
   void resume();
+  /** @hide */
   void cancel();
+  /** @hide */
   void resetStatus();
 }
diff --git a/binder_bindings/android/os/IUpdateEngineCallback.aidl b/binder_bindings/android/os/IUpdateEngineCallback.aidl
index 729abdd..ee15c8b 100644
--- a/binder_bindings/android/os/IUpdateEngineCallback.aidl
+++ b/binder_bindings/android/os/IUpdateEngineCallback.aidl
@@ -16,7 +16,10 @@
 
 package android.os;
 
+/** @hide */
 oneway interface IUpdateEngineCallback {
+  /** @hide */
   void onStatusUpdate(int status_code, float percentage);
+  /** @hide */
   void onPayloadApplicationComplete(int error_code);
 }
diff --git a/binder_service_android.h b/binder_service_android.h
index 47e76a7..3293c0e 100644
--- a/binder_service_android.h
+++ b/binder_service_android.h
@@ -36,7 +36,7 @@
 class BinderUpdateEngineAndroidService : public android::os::BnUpdateEngine,
                                          public ServiceObserverInterface {
  public:
-  BinderUpdateEngineAndroidService(
+  explicit BinderUpdateEngineAndroidService(
       ServiceDelegateAndroidInterface* service_delegate);
   ~BinderUpdateEngineAndroidService() override = default;
 
@@ -52,9 +52,6 @@
                         int64_t new_size) override;
   void SendPayloadApplicationComplete(ErrorCode error_code) 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,
diff --git a/binder_service_brillo.cc b/binder_service_brillo.cc
index 5e74159..14df725 100644
--- a/binder_service_brillo.cc
+++ b/binder_service_brillo.cc
@@ -151,6 +151,14 @@
       &UpdateEngineService::SetUpdateOverCellularPermission, enabled);
 }
 
+Status BinderUpdateEngineBrilloService::SetUpdateOverCellularTarget(
+    const String16& target_version,
+    int64_t target_size) {
+  return CallCommonHandler(
+      &UpdateEngineService::SetUpdateOverCellularTarget,
+      NormalString(target_version), target_size);
+}
+
 Status BinderUpdateEngineBrilloService::GetUpdateOverCellularPermission(
     bool* out_cellular_permission) {
   return CallCommonHandler(
diff --git a/binder_service_brillo.h b/binder_service_brillo.h
index fad0f8c..4cc007b 100644
--- a/binder_service_brillo.h
+++ b/binder_service_brillo.h
@@ -52,8 +52,6 @@
                         const std::string& new_version,
                         int64_t new_size) override;
   void SendPayloadApplicationComplete(ErrorCode error_code) 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,
@@ -78,6 +76,9 @@
       bool* out_p2p_permission) override;
   android::binder::Status SetUpdateOverCellularPermission(
       bool enabled) override;
+  android::binder::Status SetUpdateOverCellularTarget(
+      const android::String16& target_version,
+      int64_t target_size) override;
   android::binder::Status GetUpdateOverCellularPermission(
       bool* out_cellular_permission) override;
   android::binder::Status GetDurationSinceUpdate(
diff --git a/boot_control_android.cc b/boot_control_android.cc
index 78df37f..e3ea66d 100644
--- a/boot_control_android.cc
+++ b/boot_control_android.cc
@@ -22,34 +22,24 @@
 #include <base/strings/string_util.h>
 #include <brillo/make_unique_ptr.h>
 #include <brillo/message_loops/message_loop.h>
-#include <cutils/properties.h>
-#include <fs_mgr.h>
 
 #include "update_engine/common/utils.h"
+#include "update_engine/utils_android.h"
 
 using std::string;
 
+using android::hardware::Return;
+using android::hardware::boot::V1_0::BoolResult;
+using android::hardware::boot::V1_0::CommandResult;
+using android::hardware::boot::V1_0::IBootControl;
+using android::hardware::hidl_string;
+
 namespace {
-
-// Open the appropriate fstab file and fallback to /fstab.device if
-// that's what's being used.
-static struct fstab* OpenFSTab() {
-  char propbuf[PROPERTY_VALUE_MAX];
-  struct fstab* fstab;
-
-  property_get("ro.hardware", propbuf, "");
-  string fstab_name = string("/fstab.") + propbuf;
-  fstab = fs_mgr_read_fstab(fstab_name.c_str());
-  if (fstab != nullptr)
-    return fstab;
-
-  fstab = fs_mgr_read_fstab("/fstab.device");
-  return fstab;
+auto StoreResultCallback(CommandResult* dest) {
+  return [dest](const CommandResult& result) { *dest = result; };
 }
-
 }  // namespace
 
-
 namespace chromeos_update_engine {
 
 namespace boot_control {
@@ -66,40 +56,28 @@
 }  // namespace boot_control
 
 bool BootControlAndroid::Init() {
-  const hw_module_t* hw_module;
-  int ret;
-
-  ret = hw_get_module(BOOT_CONTROL_HARDWARE_MODULE_ID, &hw_module);
-  if (ret != 0) {
-    LOG(ERROR) << "Error loading boot_control HAL implementation.";
+  module_ = IBootControl::getService();
+  if (module_ == nullptr) {
+    LOG(ERROR) << "Error getting bootctrl HIDL module.";
     return false;
   }
 
-  module_ = reinterpret_cast<boot_control_module_t*>(const_cast<hw_module_t*>(hw_module));
-  module_->init(module_);
+  LOG(INFO) << "Loaded boot control hidl hal.";
 
-  LOG(INFO) << "Loaded boot_control HAL "
-            << "'" << hw_module->name << "' "
-            << "version " << (hw_module->module_api_version>>8) << "."
-            << (hw_module->module_api_version&0xff) << " "
-            << "authored by '" << hw_module->author << "'.";
   return true;
 }
 
 unsigned int BootControlAndroid::GetNumSlots() const {
-  return module_->getNumberSlots(module_);
+  return module_->getNumberSlots();
 }
 
 BootControlInterface::Slot BootControlAndroid::GetCurrentSlot() const {
-  return module_->getCurrentSlot(module_);
+  return module_->getCurrentSlot();
 }
 
 bool BootControlAndroid::GetPartitionDevice(const string& partition_name,
                                             Slot slot,
                                             string* device) const {
-  struct fstab* fstab;
-  struct fstab_rec* record;
-
   // We can't use fs_mgr to look up |partition_name| because fstab
   // doesn't list every slot partition (it uses the slotselect option
   // to mask the suffix).
@@ -119,20 +97,9 @@
   // of misc and then finding an entry in /dev matching the sysfs
   // entry.
 
-  fstab = OpenFSTab();
-  if (fstab == nullptr) {
-    LOG(ERROR) << "Error opening fstab file.";
+  base::FilePath misc_device;
+  if (!utils::DeviceForMountPoint("/misc", &misc_device))
     return false;
-  }
-  record = fs_mgr_get_entry_for_mount_point(fstab, "/misc");
-  if (record == nullptr) {
-    LOG(ERROR) << "Error finding /misc entry in fstab file.";
-    fs_mgr_free_fstab(fstab);
-    return false;
-  }
-
-  base::FilePath misc_device = base::FilePath(record->blk_device);
-  fs_mgr_free_fstab(fstab);
 
   if (!utils::IsSymlink(misc_device.value().c_str())) {
     LOG(ERROR) << "Device file " << misc_device.value() << " for /misc "
@@ -140,8 +107,13 @@
     return false;
   }
 
-  const char* suffix = module_->getSuffix(module_, slot);
-  if (suffix == nullptr) {
+  string suffix;
+  auto store_suffix_cb = [&suffix](hidl_string cb_suffix) {
+    suffix = cb_suffix.c_str();
+  };
+  Return<void> ret = module_->getSuffix(slot, store_suffix_cb);
+
+  if (!ret.isOk()) {
     LOG(ERROR) << "boot_control impl returned no suffix for slot "
                << SlotName(slot);
     return false;
@@ -158,42 +130,65 @@
 }
 
 bool BootControlAndroid::IsSlotBootable(Slot slot) const {
-  int ret = module_->isSlotBootable(module_, slot);
-  if (ret < 0) {
+  Return<BoolResult> ret = module_->isSlotBootable(slot);
+  if (!ret.isOk()) {
     LOG(ERROR) << "Unable to determine if slot " << SlotName(slot)
-               << " is bootable: " << strerror(-ret);
+               << " is bootable: "
+               << ret.description();
     return false;
   }
-  return ret == 1;
+  if (ret == BoolResult::INVALID_SLOT) {
+    LOG(ERROR) << "Invalid slot: " << SlotName(slot);
+    return false;
+  }
+  return ret == BoolResult::TRUE;
 }
 
 bool BootControlAndroid::MarkSlotUnbootable(Slot slot) {
-  int ret = module_->setSlotAsUnbootable(module_, slot);
-  if (ret < 0) {
-    LOG(ERROR) << "Unable to mark slot " << SlotName(slot)
-               << " as bootable: " << strerror(-ret);
+  CommandResult result;
+  auto ret = module_->setSlotAsUnbootable(slot, StoreResultCallback(&result));
+  if (!ret.isOk()) {
+    LOG(ERROR) << "Unable to call MarkSlotUnbootable for slot "
+               << SlotName(slot) << ": "
+               << ret.description();
     return false;
   }
-  return ret == 0;
+  if (!result.success) {
+    LOG(ERROR) << "Unable to mark slot " << SlotName(slot)
+               << " as unbootable: " << result.errMsg.c_str();
+  }
+  return result.success;
 }
 
 bool BootControlAndroid::SetActiveBootSlot(Slot slot) {
-  int ret = module_->setActiveBootSlot(module_, slot);
-  if (ret < 0) {
-    LOG(ERROR) << "Unable to set the active slot to slot " << SlotName(slot)
-               << ": " << strerror(-ret);
+  CommandResult result;
+  auto ret = module_->setActiveBootSlot(slot, StoreResultCallback(&result));
+  if (!ret.isOk()) {
+    LOG(ERROR) << "Unable to call SetActiveBootSlot for slot " << SlotName(slot)
+               << ": " << ret.description();
+    return false;
   }
-  return ret == 0;
+  if (!result.success) {
+    LOG(ERROR) << "Unable to set the active slot to slot " << SlotName(slot)
+               << ": " << result.errMsg.c_str();
+  }
+  return result.success;
 }
 
 bool BootControlAndroid::MarkBootSuccessfulAsync(
     base::Callback<void(bool)> callback) {
-  int ret = module_->markBootSuccessful(module_);
-  if (ret < 0) {
-    LOG(ERROR) << "Unable to mark boot successful: " << strerror(-ret);
+  CommandResult result;
+  auto ret = module_->markBootSuccessful(StoreResultCallback(&result));
+  if (!ret.isOk()) {
+    LOG(ERROR) << "Unable to call MarkBootSuccessful: "
+               << ret.description();
+    return false;
+  }
+  if (!result.success) {
+    LOG(ERROR) << "Unable to mark boot successful: " << result.errMsg.c_str();
   }
   return brillo::MessageLoop::current()->PostTask(
-             FROM_HERE, base::Bind(callback, ret == 0)) !=
+             FROM_HERE, base::Bind(callback, result.success)) !=
          brillo::MessageLoop::kTaskIdNull;
 }
 
diff --git a/boot_control_android.h b/boot_control_android.h
index a5a6255..1de0e41 100644
--- a/boot_control_android.h
+++ b/boot_control_android.h
@@ -19,8 +19,7 @@
 
 #include <string>
 
-#include <hardware/boot_control.h>
-#include <hardware/hardware.h>
+#include <android/hardware/boot/1.0/IBootControl.h>
 
 #include "update_engine/common/boot_control.h"
 
@@ -49,9 +48,7 @@
   bool MarkBootSuccessfulAsync(base::Callback<void(bool)> callback) override;
 
  private:
-  // NOTE: There is no way to release/unload HAL implementations so
-  // this is essentially leaked on object destruction.
-  boot_control_module_t* module_;
+  ::android::sp<::android::hardware::boot::V1_0::IBootControl> module_;
 
   DISALLOW_COPY_AND_ASSIGN(BootControlAndroid);
 };
diff --git a/boot_control_recovery.cc b/boot_control_recovery.cc
new file mode 100644
index 0000000..39b5ff1
--- /dev/null
+++ b/boot_control_recovery.cc
@@ -0,0 +1,182 @@
+//
+// 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/boot_control_recovery.h"
+
+#include <base/bind.h>
+#include <base/files/file_util.h>
+#include <base/logging.h>
+#include <base/strings/string_util.h>
+#include <brillo/make_unique_ptr.h>
+#include <brillo/message_loops/message_loop.h>
+
+#include "update_engine/common/utils.h"
+#include "update_engine/utils_android.h"
+
+using std::string;
+
+#ifndef _UE_SIDELOAD
+#error "BootControlRecovery should only be used for update_engine_sideload."
+#endif
+
+// When called from update_engine_sideload, we don't attempt to dynamically load
+// the right boot_control HAL, instead we use the only HAL statically linked in
+// via the PRODUCT_STATIC_BOOT_CONTROL_HAL make variable and access the module
+// struct directly.
+extern const hw_module_t HAL_MODULE_INFO_SYM;
+
+namespace chromeos_update_engine {
+
+namespace boot_control {
+
+// Factory defined in boot_control.h.
+std::unique_ptr<BootControlInterface> CreateBootControl() {
+  std::unique_ptr<BootControlRecovery> boot_control(new BootControlRecovery());
+  if (!boot_control->Init()) {
+    return nullptr;
+  }
+  return std::move(boot_control);
+}
+
+}  // namespace boot_control
+
+bool BootControlRecovery::Init() {
+  const hw_module_t* hw_module;
+  int ret;
+
+  // For update_engine_sideload, we simulate the hw_get_module() by accessing it
+  // from the current process directly.
+  hw_module = &HAL_MODULE_INFO_SYM;
+  ret = 0;
+  if (!hw_module ||
+      strcmp(BOOT_CONTROL_HARDWARE_MODULE_ID, hw_module->id) != 0) {
+    ret = -EINVAL;
+  }
+  if (ret != 0) {
+    LOG(ERROR) << "Error loading boot_control HAL implementation.";
+    return false;
+  }
+
+  module_ = reinterpret_cast<boot_control_module_t*>(
+      const_cast<hw_module_t*>(hw_module));
+  module_->init(module_);
+
+  LOG(INFO) << "Loaded boot_control HAL "
+            << "'" << hw_module->name << "' "
+            << "version " << (hw_module->module_api_version >> 8) << "."
+            << (hw_module->module_api_version & 0xff) << " "
+            << "authored by '" << hw_module->author << "'.";
+  return true;
+}
+
+unsigned int BootControlRecovery::GetNumSlots() const {
+  return module_->getNumberSlots(module_);
+}
+
+BootControlInterface::Slot BootControlRecovery::GetCurrentSlot() const {
+  return module_->getCurrentSlot(module_);
+}
+
+bool BootControlRecovery::GetPartitionDevice(const string& partition_name,
+                                             Slot slot,
+                                             string* device) const {
+  // We can't use fs_mgr to look up |partition_name| because fstab
+  // doesn't list every slot partition (it uses the slotselect option
+  // to mask the suffix).
+  //
+  // We can however assume that there's an entry for the /misc mount
+  // point and use that to get the device file for the misc
+  // partition. This helps us locate the disk that |partition_name|
+  // resides on. From there we'll assume that a by-name scheme is used
+  // so we can just replace the trailing "misc" by the given
+  // |partition_name| and suffix corresponding to |slot|, e.g.
+  //
+  //   /dev/block/platform/soc.0/7824900.sdhci/by-name/misc ->
+  //   /dev/block/platform/soc.0/7824900.sdhci/by-name/boot_a
+  //
+  // If needed, it's possible to relax the by-name assumption in the
+  // future by trawling /sys/block looking for the appropriate sibling
+  // of misc and then finding an entry in /dev matching the sysfs
+  // entry.
+
+  base::FilePath misc_device;
+  if (!utils::DeviceForMountPoint("/misc", &misc_device))
+    return false;
+
+  if (!utils::IsSymlink(misc_device.value().c_str())) {
+    LOG(ERROR) << "Device file " << misc_device.value() << " for /misc "
+               << "is not a symlink.";
+    return false;
+  }
+
+  const char* suffix = module_->getSuffix(module_, slot);
+  if (suffix == nullptr) {
+    LOG(ERROR) << "boot_control impl returned no suffix for slot "
+               << SlotName(slot);
+    return false;
+  }
+
+  base::FilePath path = misc_device.DirName().Append(partition_name + suffix);
+  if (!base::PathExists(path)) {
+    LOG(ERROR) << "Device file " << path.value() << " does not exist.";
+    return false;
+  }
+
+  *device = path.value();
+  return true;
+}
+
+bool BootControlRecovery::IsSlotBootable(Slot slot) const {
+  int ret = module_->isSlotBootable(module_, slot);
+  if (ret < 0) {
+    LOG(ERROR) << "Unable to determine if slot " << SlotName(slot)
+               << " is bootable: " << strerror(-ret);
+    return false;
+  }
+  return ret == 1;
+}
+
+bool BootControlRecovery::MarkSlotUnbootable(Slot slot) {
+  int ret = module_->setSlotAsUnbootable(module_, slot);
+  if (ret < 0) {
+    LOG(ERROR) << "Unable to mark slot " << SlotName(slot)
+               << " as bootable: " << strerror(-ret);
+    return false;
+  }
+  return ret == 0;
+}
+
+bool BootControlRecovery::SetActiveBootSlot(Slot slot) {
+  int ret = module_->setActiveBootSlot(module_, slot);
+  if (ret < 0) {
+    LOG(ERROR) << "Unable to set the active slot to slot " << SlotName(slot)
+               << ": " << strerror(-ret);
+  }
+  return ret == 0;
+}
+
+bool BootControlRecovery::MarkBootSuccessfulAsync(
+    base::Callback<void(bool)> callback) {
+  int ret = module_->markBootSuccessful(module_);
+  if (ret < 0) {
+    LOG(ERROR) << "Unable to mark boot successful: " << strerror(-ret);
+  }
+  return brillo::MessageLoop::current()->PostTask(
+             FROM_HERE, base::Bind(callback, ret == 0)) !=
+         brillo::MessageLoop::kTaskIdNull;
+}
+
+}  // namespace chromeos_update_engine
diff --git a/boot_control_recovery.h b/boot_control_recovery.h
new file mode 100644
index 0000000..3a83caa
--- /dev/null
+++ b/boot_control_recovery.h
@@ -0,0 +1,63 @@
+//
+// 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_BOOT_CONTROL_RECOVERY_H_
+#define UPDATE_ENGINE_BOOT_CONTROL_RECOVERY_H_
+
+#include <string>
+
+#include <hardware/boot_control.h>
+#include <hardware/hardware.h>
+
+#include "update_engine/common/boot_control.h"
+
+namespace chromeos_update_engine {
+
+// The Android recovery implementation of the BootControlInterface. This
+// implementation uses the legacy libhardware's boot_control HAL to access the
+// bootloader by linking against it statically. This should only be used in
+// recovery.
+class BootControlRecovery : public BootControlInterface {
+ public:
+  BootControlRecovery() = default;
+  ~BootControlRecovery() = default;
+
+  // Load boot_control HAL implementation using libhardware and
+  // initializes it. Returns false if an error occurred.
+  bool Init();
+
+  // BootControlInterface overrides.
+  unsigned int GetNumSlots() const override;
+  BootControlInterface::Slot GetCurrentSlot() const override;
+  bool GetPartitionDevice(const std::string& partition_name,
+                          BootControlInterface::Slot slot,
+                          std::string* device) const override;
+  bool IsSlotBootable(BootControlInterface::Slot slot) const override;
+  bool MarkSlotUnbootable(BootControlInterface::Slot slot) override;
+  bool SetActiveBootSlot(BootControlInterface::Slot slot) override;
+  bool MarkBootSuccessfulAsync(base::Callback<void(bool)> callback) override;
+
+ private:
+  // NOTE: There is no way to release/unload HAL implementations so
+  // this is essentially leaked on object destruction.
+  boot_control_module_t* module_;
+
+  DISALLOW_COPY_AND_ASSIGN(BootControlRecovery);
+};
+
+}  // namespace chromeos_update_engine
+
+#endif  // UPDATE_ENGINE_BOOT_CONTROL_RECOVERY_H_
diff --git a/boot_control_recovery_stub.cc b/boot_control_recovery_stub.cc
new file mode 100644
index 0000000..129c5d0
--- /dev/null
+++ b/boot_control_recovery_stub.cc
@@ -0,0 +1,21 @@
+//
+// 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 <hardware/hardware.h>
+
+hw_module_t HAL_MODULE_INFO_SYM = {
+  .id = "stub",
+};
diff --git a/common/certificate_checker.cc b/certificate_checker.cc
similarity index 98%
rename from common/certificate_checker.cc
rename to certificate_checker.cc
index 86df950..6e886e7 100644
--- a/common/certificate_checker.cc
+++ b/certificate_checker.cc
@@ -14,7 +14,7 @@
 // limitations under the License.
 //
 
-#include "update_engine/common/certificate_checker.h"
+#include "update_engine/certificate_checker.h"
 
 #include <string>
 
diff --git a/common/certificate_checker.h b/certificate_checker.h
similarity index 97%
rename from common/certificate_checker.h
rename to certificate_checker.h
index c785192..5d0b5ba 100644
--- a/common/certificate_checker.h
+++ b/certificate_checker.h
@@ -14,8 +14,8 @@
 // limitations under the License.
 //
 
-#ifndef UPDATE_ENGINE_COMMON_CERTIFICATE_CHECKER_H_
-#define UPDATE_ENGINE_COMMON_CERTIFICATE_CHECKER_H_
+#ifndef UPDATE_ENGINE_CERTIFICATE_CHECKER_H_
+#define UPDATE_ENGINE_CERTIFICATE_CHECKER_H_
 
 #include <curl/curl.h>
 #include <openssl/ssl.h>
@@ -172,4 +172,4 @@
 
 }  // namespace chromeos_update_engine
 
-#endif  // UPDATE_ENGINE_COMMON_CERTIFICATE_CHECKER_H_
+#endif  // UPDATE_ENGINE_CERTIFICATE_CHECKER_H_
diff --git a/common/certificate_checker_unittest.cc b/certificate_checker_unittest.cc
similarity index 97%
rename from common/certificate_checker_unittest.cc
rename to certificate_checker_unittest.cc
index c30acc5..20efce9 100644
--- a/common/certificate_checker_unittest.cc
+++ b/certificate_checker_unittest.cc
@@ -14,7 +14,7 @@
 // limitations under the License.
 //
 
-#include "update_engine/common/certificate_checker.h"
+#include "update_engine/certificate_checker.h"
 
 #include <string>
 
@@ -24,8 +24,8 @@
 #include <gtest/gtest.h>
 
 #include "update_engine/common/constants.h"
-#include "update_engine/common/mock_certificate_checker.h"
 #include "update_engine/common/mock_prefs.h"
+#include "update_engine/mock_certificate_checker.h"
 
 using ::testing::DoAll;
 using ::testing::Return;
diff --git a/common/constants.cc b/common/constants.cc
index 1bb4058..d6d1c6d 100644
--- a/common/constants.cc
+++ b/common/constants.cc
@@ -18,11 +18,6 @@
 
 namespace chromeos_update_engine {
 
-const char kPowerwashMarkerFile[] =
-    "/mnt/stateful_partition/factory_install_reset";
-
-const char kPowerwashCommand[] = "safe fast keepimg reason=update_engine\n";
-
 const char kPowerwashSafePrefsSubDirectory[] = "update_engine/prefs";
 
 const char kPrefsSubDirectory[] = "prefs";
@@ -95,11 +90,21 @@
 const char kPrefsUrlSwitchCount[] = "url-switch-count";
 const char kPrefsWallClockWaitPeriod[] = "wall-clock-wait-period";
 
+// These four fields are generated by scripts/brillo_update_payload.
 const char kPayloadPropertyFileSize[] = "FILE_SIZE";
 const char kPayloadPropertyFileHash[] = "FILE_HASH";
 const char kPayloadPropertyMetadataSize[] = "METADATA_SIZE";
 const char kPayloadPropertyMetadataHash[] = "METADATA_HASH";
+// The Authorization: HTTP header to be sent when downloading the payload.
 const char kPayloadPropertyAuthorization[] = "AUTHORIZATION";
+// The User-Agent HTTP header to be sent when downloading the payload.
 const char kPayloadPropertyUserAgent[] = "USER_AGENT";
+// Set "POWERWASH=1" to powerwash (factory data reset) the device after
+// applying the update.
+const char kPayloadPropertyPowerwash[] = "POWERWASH";
+// The network id to pass to android_setprocnetwork before downloading.
+// This can be used to zero-rate OTA traffic by sending it over the correct
+// network.
+const char kPayloadPropertyNetworkId[] = "NETWORK_ID";
 
 }  // namespace chromeos_update_engine
diff --git a/common/constants.h b/common/constants.h
index 208755d..c571403 100644
--- a/common/constants.h
+++ b/common/constants.h
@@ -19,13 +19,6 @@
 
 namespace chromeos_update_engine {
 
-// The name of the marker file used to trigger powerwash when post-install
-// completes successfully so that the device is powerwashed on next reboot.
-extern const char kPowerwashMarkerFile[];
-
-// The contents of the powerwash marker file.
-extern const char kPowerwashCommand[];
-
 // Directory for AU prefs that are preserved across powerwash.
 extern const char kPowerwashSafePrefsSubDirectory[];
 
@@ -102,6 +95,8 @@
 extern const char kPayloadPropertyMetadataHash[];
 extern const char kPayloadPropertyAuthorization[];
 extern const char kPayloadPropertyUserAgent[];
+extern const char kPayloadPropertyPowerwash[];
+extern const char kPayloadPropertyNetworkId[];
 
 // A download source is any combination of protocol and server (that's of
 // interest to us when looking at UMA metrics) using which we may download
diff --git a/common/fake_boot_control.h b/common/fake_boot_control.h
index 5c6c160..3eccc80 100644
--- a/common/fake_boot_control.h
+++ b/common/fake_boot_control.h
@@ -85,9 +85,9 @@
     current_slot_ = slot;
   }
 
-  void SetPartitionDevice(const std::string partition_name,
+  void SetPartitionDevice(const std::string& partition_name,
                           BootControlInterface::Slot slot,
-                          const std::string device) {
+                          const std::string& device) {
     DCHECK(slot < num_slots_);
     devices_[slot][partition_name] = device;
   }
diff --git a/common/fake_hardware.h b/common/fake_hardware.h
index 4558c8c..5d0fca3 100644
--- a/common/fake_hardware.h
+++ b/common/fake_hardware.h
@@ -41,6 +41,10 @@
 
   bool IsNormalBootMode() const override { return is_normal_boot_mode_; }
 
+  bool AreDevFeaturesEnabled() const override {
+    return are_dev_features_enabled_;
+  }
+
   bool IsOOBEEnabled() const override { return is_oobe_enabled_; }
 
   bool IsOOBEComplete(base::Time* out_time_of_oobe) const override {
@@ -57,6 +61,18 @@
 
   int GetPowerwashCount() const override { return powerwash_count_; }
 
+  bool SchedulePowerwash() override {
+    powerwash_scheduled_ = true;
+    return true;
+  }
+
+  bool CancelPowerwash() override {
+    powerwash_scheduled_ = false;
+    return true;
+  }
+
+  bool IsPowerwashScheduled() { return powerwash_scheduled_; }
+
   bool GetNonVolatileDirectory(base::FilePath* path) const override {
     return false;
   }
@@ -74,6 +90,10 @@
     is_normal_boot_mode_ = is_normal_boot_mode;
   }
 
+  void SetAreDevFeaturesEnabled(bool are_dev_features_enabled) {
+    are_dev_features_enabled_ = are_dev_features_enabled;
+  }
+
   // Sets the SetIsOOBEEnabled to |is_oobe_enabled|.
   void SetIsOOBEEnabled(bool is_oobe_enabled) {
     is_oobe_enabled_ = is_oobe_enabled;
@@ -89,15 +109,15 @@
     is_oobe_complete_ = false;
   }
 
-  void SetHardwareClass(std::string hardware_class) {
+  void SetHardwareClass(const std::string& hardware_class) {
     hardware_class_ = hardware_class;
   }
 
-  void SetFirmwareVersion(std::string firmware_version) {
+  void SetFirmwareVersion(const std::string& firmware_version) {
     firmware_version_ = firmware_version;
   }
 
-  void SetECVersion(std::string ec_version) {
+  void SetECVersion(const std::string& ec_version) {
     ec_version_ = ec_version;
   }
 
@@ -108,6 +128,7 @@
  private:
   bool is_official_build_{true};
   bool is_normal_boot_mode_{true};
+  bool are_dev_features_enabled_{false};
   bool is_oobe_enabled_{true};
   bool is_oobe_complete_{true};
   base::Time oobe_timestamp_{base::Time::FromTimeT(1169280000)}; // Jan 20, 2007
@@ -115,6 +136,7 @@
   std::string firmware_version_{"Fake Firmware v1.0.1"};
   std::string ec_version_{"Fake EC v1.0a"};
   int powerwash_count_{kPowerwashCountNotSet};
+  bool powerwash_scheduled_{false};
 
   DISALLOW_COPY_AND_ASSIGN(FakeHardware);
 };
diff --git a/common/file_fetcher.cc b/common/file_fetcher.cc
new file mode 100644
index 0000000..d0a109b
--- /dev/null
+++ b/common/file_fetcher.cc
@@ -0,0 +1,186 @@
+//
+// 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/common/file_fetcher.h"
+
+#include <algorithm>
+#include <string>
+
+#include <base/bind.h>
+#include <base/format_macros.h>
+#include <base/location.h>
+#include <base/logging.h>
+#include <base/strings/string_util.h>
+#include <base/strings/stringprintf.h>
+#include <brillo/streams/file_stream.h>
+
+#include "update_engine/common/hardware_interface.h"
+#include "update_engine/common/platform_constants.h"
+
+using std::string;
+
+namespace {
+
+size_t kReadBufferSize = 16 * 1024;
+
+}  // namespace
+
+namespace chromeos_update_engine {
+
+// static
+bool FileFetcher::SupportedUrl(const string& url) {
+  // Note that we require the file path to start with a "/".
+  return base::StartsWith(
+      url, "file:///", base::CompareCase::INSENSITIVE_ASCII);
+}
+
+FileFetcher::~FileFetcher() {
+  LOG_IF(ERROR, transfer_in_progress_)
+      << "Destroying the fetcher while a transfer is in progress.";
+  CleanUp();
+}
+
+// Begins the transfer, which must not have already been started.
+void FileFetcher::BeginTransfer(const string& url) {
+  CHECK(!transfer_in_progress_);
+
+  if (!SupportedUrl(url)) {
+    LOG(ERROR) << "Unsupported file URL: " << url;
+    // No HTTP error code when the URL is not supported.
+    http_response_code_ = 0;
+    CleanUp();
+    if (delegate_)
+      delegate_->TransferComplete(this, false);
+    return;
+  }
+
+  string file_path = url.substr(strlen("file://"));
+  stream_ =
+      brillo::FileStream::Open(base::FilePath(file_path),
+                               brillo::Stream::AccessMode::READ,
+                               brillo::FileStream::Disposition::OPEN_EXISTING,
+                               nullptr);
+
+  if (!stream_) {
+    LOG(ERROR) << "Couldn't open " << file_path;
+    http_response_code_ = kHttpResponseNotFound;
+    CleanUp();
+    if (delegate_)
+      delegate_->TransferComplete(this, false);
+    return;
+  }
+  http_response_code_ = kHttpResponseOk;
+
+  if (offset_)
+    stream_->SetPosition(offset_, nullptr);
+  bytes_copied_ = 0;
+  transfer_in_progress_ = true;
+  ScheduleRead();
+}
+
+void FileFetcher::TerminateTransfer() {
+  CleanUp();
+  if (delegate_) {
+    // Note that after the callback returns this object may be destroyed.
+    delegate_->TransferTerminated(this);
+  }
+}
+
+void FileFetcher::ScheduleRead() {
+  if (transfer_paused_ || ongoing_read_ || !transfer_in_progress_)
+    return;
+
+  buffer_.resize(kReadBufferSize);
+  size_t bytes_to_read = buffer_.size();
+  if (data_length_ >= 0) {
+    bytes_to_read = std::min(static_cast<uint64_t>(bytes_to_read),
+                             data_length_ - bytes_copied_);
+  }
+
+  if (!bytes_to_read) {
+    OnReadDoneCallback(0);
+    return;
+  }
+
+  ongoing_read_ = stream_->ReadAsync(
+      buffer_.data(),
+      bytes_to_read,
+      base::Bind(&FileFetcher::OnReadDoneCallback, base::Unretained(this)),
+      base::Bind(&FileFetcher::OnReadErrorCallback, base::Unretained(this)),
+      nullptr);
+
+  if (!ongoing_read_) {
+    LOG(ERROR) << "Unable to schedule an asynchronous read from the stream.";
+    CleanUp();
+    if (delegate_)
+      delegate_->TransferComplete(this, false);
+  }
+}
+
+void FileFetcher::OnReadDoneCallback(size_t bytes_read) {
+  ongoing_read_ = false;
+  if (bytes_read == 0) {
+    CleanUp();
+    if (delegate_)
+      delegate_->TransferComplete(this, true);
+  } else {
+    bytes_copied_ += bytes_read;
+    if (delegate_)
+      delegate_->ReceivedBytes(this, buffer_.data(), bytes_read);
+    ScheduleRead();
+  }
+}
+
+void FileFetcher::OnReadErrorCallback(const brillo::Error* error) {
+  LOG(ERROR) << "Asynchronous read failed: " << error->GetMessage();
+  CleanUp();
+  if (delegate_)
+    delegate_->TransferComplete(this, false);
+}
+
+void FileFetcher::Pause() {
+  if (transfer_paused_) {
+    LOG(ERROR) << "Fetcher already paused.";
+    return;
+  }
+  transfer_paused_ = true;
+}
+
+void FileFetcher::Unpause() {
+  if (!transfer_paused_) {
+    LOG(ERROR) << "Resume attempted when fetcher not paused.";
+    return;
+  }
+  transfer_paused_ = false;
+  ScheduleRead();
+}
+
+void FileFetcher::CleanUp() {
+  if (stream_) {
+    stream_->CancelPendingAsyncOperations();
+    stream_->CloseBlocking(nullptr);
+    stream_.reset();
+  }
+  // Destroying the |stream_| releases the callback, so we don't have any
+  // ongoing read at this point.
+  ongoing_read_ = false;
+  buffer_ = brillo::Blob();
+
+  transfer_in_progress_ = false;
+  transfer_paused_ = false;
+}
+
+}  // namespace chromeos_update_engine
diff --git a/common/file_fetcher.h b/common/file_fetcher.h
new file mode 100644
index 0000000..2368b1d
--- /dev/null
+++ b/common/file_fetcher.h
@@ -0,0 +1,119 @@
+//
+// 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_COMMON_FILE_FETCHER_H_
+#define UPDATE_ENGINE_COMMON_FILE_FETCHER_H_
+
+#include <memory>
+#include <string>
+#include <utility>
+
+#include <base/logging.h>
+#include <base/macros.h>
+#include <brillo/message_loops/message_loop.h>
+#include <brillo/streams/stream.h>
+
+#include "update_engine/common/http_fetcher.h"
+
+// This is a concrete implementation of HttpFetcher that reads files
+// asynchronously.
+
+namespace chromeos_update_engine {
+
+class FileFetcher : public HttpFetcher {
+ public:
+  // Returns whether the passed url is supported.
+  static bool SupportedUrl(const std::string& url);
+
+  FileFetcher() : HttpFetcher(nullptr) {}
+
+  // Cleans up all internal state. Does not notify delegate.
+  ~FileFetcher() override;
+
+  // HttpFetcher overrides.
+  void SetOffset(off_t offset) override { offset_ = offset; }
+  void SetLength(size_t length) override { data_length_ = length; }
+  void UnsetLength() override { SetLength(0); }
+
+  // Begins the transfer if it hasn't already begun.
+  void BeginTransfer(const std::string& url) override;
+
+  // If the transfer is in progress, aborts the transfer early. The transfer
+  // cannot be resumed.
+  void TerminateTransfer() override;
+
+  // Ignore all extra headers for files.
+  void SetHeader(const std::string& header_name,
+                 const std::string& header_value) override {};
+
+  // Suspend the asynchronous file read.
+  void Pause() override;
+
+  // Resume the suspended file read.
+  void Unpause() override;
+
+  size_t GetBytesDownloaded() override {
+    return static_cast<size_t>(bytes_copied_);
+  }
+
+  // Ignore all the time limits for files.
+  void set_low_speed_limit(int low_speed_bps, int low_speed_sec) override {}
+  void set_connect_timeout(int connect_timeout_seconds) override {}
+  void set_max_retry_count(int max_retry_count) override {}
+
+ private:
+  // Cleans up the fetcher, resetting its status to a newly constructed one.
+  void CleanUp();
+
+  // Schedule a new asynchronous read if the stream is not paused and no other
+  // read is in process. This method can be called at any point.
+  void ScheduleRead();
+
+  // Called from the main loop when a single read from |stream_| succeeds or
+  // fails, calling OnReadDoneCallback() and OnReadErrorCallback() respectively.
+  void OnReadDoneCallback(size_t bytes_read);
+  void OnReadErrorCallback(const brillo::Error* error);
+
+  // Whether the transfer was started and didn't finish yet.
+  bool transfer_in_progress_{false};
+
+  // Whether the transfer is paused.
+  bool transfer_paused_{false};
+
+  // Whether there's an ongoing asynchronous read. When this value is true, the
+  // the |buffer_| is being used by the |stream_|.
+  bool ongoing_read_{false};
+
+  // Total number of bytes copied.
+  uint64_t bytes_copied_{0};
+
+  // The offset inside the file where the read should start.
+  uint64_t offset_{0};
+
+  // The length of the data or -1 if unknown (will read until EOF).
+  int64_t data_length_{-1};
+
+  brillo::StreamPtr stream_;
+
+  // The buffer used for reading from the stream.
+  brillo::Blob buffer_;
+
+  DISALLOW_COPY_AND_ASSIGN(FileFetcher);
+};
+
+}  // namespace chromeos_update_engine
+
+#endif  // UPDATE_ENGINE_COMMON_FILE_FETCHER_H_
diff --git a/common/file_fetcher_unittest.cc b/common/file_fetcher_unittest.cc
new file mode 100644
index 0000000..9c6b0ec
--- /dev/null
+++ b/common/file_fetcher_unittest.cc
@@ -0,0 +1,37 @@
+//
+// 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/common/file_fetcher.h"
+
+#include <string>
+
+#include <gtest/gtest.h>
+
+#include "update_engine/common/test_utils.h"
+
+namespace chromeos_update_engine {
+
+class FileFetcherUnitTest : public ::testing::Test {};
+
+TEST_F(FileFetcherUnitTest, SupporterUrlsTest) {
+  EXPECT_TRUE(FileFetcher::SupportedUrl("file:///path/to/somewhere.bin"));
+  EXPECT_TRUE(FileFetcher::SupportedUrl("FILE:///I/LIKE/TO/SHOUT"));
+
+  EXPECT_FALSE(FileFetcher::SupportedUrl("file://relative"));
+  EXPECT_FALSE(FileFetcher::SupportedUrl("http:///no_http_here"));
+}
+
+}  // namespace chromeos_update_engine
diff --git a/common/hardware_interface.h b/common/hardware_interface.h
index e434cc9..316ad3d 100644
--- a/common/hardware_interface.h
+++ b/common/hardware_interface.h
@@ -44,6 +44,9 @@
   // features.
   virtual bool IsNormalBootMode() const = 0;
 
+  // Returns whether the developer features are enabled.
+  virtual bool AreDevFeaturesEnabled() const = 0;
+
   // Returns whether the device has an OOBE flow that the user must go through
   // before getting non-critical updates. Use IsOOBEComplete() to determine if
   // that flow is complete.
@@ -70,6 +73,13 @@
   // recovery don't have this value set.
   virtual int GetPowerwashCount() const = 0;
 
+  // Signals that a powerwash (stateful partition wipe) should be performed
+  // after reboot.
+  virtual bool SchedulePowerwash() = 0;
+
+  // Cancel the powerwash operation scheduled to be performed on next boot.
+  virtual bool CancelPowerwash() = 0;
+
   // Store in |path| the path to a non-volatile directory (persisted across
   // reboots) available for this daemon. In case of an error, such as no
   // directory available, returns false.
diff --git a/common/hash_calculator_unittest.cc b/common/hash_calculator_unittest.cc
index 27dbc56..436e6a7 100644
--- a/common/hash_calculator_unittest.cc
+++ b/common/hash_calculator_unittest.cc
@@ -25,7 +25,6 @@
 #include <brillo/secure_blob.h>
 #include <gtest/gtest.h>
 
-#include "update_engine/common/libcurl_http_fetcher.h"
 #include "update_engine/common/utils.h"
 
 using std::string;
diff --git a/common/http_fetcher.cc b/common/http_fetcher.cc
index bcd1ffe..73c0d48 100644
--- a/common/http_fetcher.cc
+++ b/common/http_fetcher.cc
@@ -26,10 +26,7 @@
 namespace chromeos_update_engine {
 
 HttpFetcher::~HttpFetcher() {
-  if (no_resolver_idle_id_ != MessageLoop::kTaskIdNull) {
-    MessageLoop::current()->CancelTask(no_resolver_idle_id_);
-    no_resolver_idle_id_ = MessageLoop::kTaskIdNull;
-  }
+  CancelProxyResolution();
 }
 
 void HttpFetcher::SetPostData(const void* data, size_t size,
@@ -59,23 +56,37 @@
                    base::Unretained(this)));
     return;
   }
-  proxy_resolver_->GetProxiesForUrl(url,
-      base::Bind(&HttpFetcher::ProxiesResolved, base::Unretained(this)));
+  proxy_request_ = proxy_resolver_->GetProxiesForUrl(
+      url, base::Bind(&HttpFetcher::ProxiesResolved, base::Unretained(this)));
 }
 
 void HttpFetcher::NoProxyResolverCallback() {
+  no_resolver_idle_id_ = MessageLoop::kTaskIdNull;
   ProxiesResolved(deque<string>());
 }
 
 void HttpFetcher::ProxiesResolved(const deque<string>& proxies) {
-  no_resolver_idle_id_ = MessageLoop::kTaskIdNull;
+  proxy_request_ = kProxyRequestIdNull;
   if (!proxies.empty())
     SetProxies(proxies);
-  CHECK_NE(static_cast<Closure*>(nullptr), callback_.get());
+  CHECK(callback_.get()) << "ProxiesResolved but none pending.";
   Closure* callback = callback_.release();
   // This may indirectly call back into ResolveProxiesForUrl():
   callback->Run();
   delete callback;
 }
 
+bool HttpFetcher::CancelProxyResolution() {
+  bool ret = false;
+  if (no_resolver_idle_id_ != MessageLoop::kTaskIdNull) {
+    ret = MessageLoop::current()->CancelTask(no_resolver_idle_id_);
+    no_resolver_idle_id_ = MessageLoop::kTaskIdNull;
+  }
+  if (proxy_request_ && proxy_resolver_) {
+    ret = proxy_resolver_->CancelProxyRequest(proxy_request_) || ret;
+    proxy_request_ = kProxyRequestIdNull;
+  }
+  return ret;
+}
+
 }  // namespace chromeos_update_engine
diff --git a/common/http_fetcher.h b/common/http_fetcher.h
index 61a83f0..3f7b2e8 100644
--- a/common/http_fetcher.h
+++ b/common/http_fetcher.h
@@ -133,6 +133,11 @@
   ProxyResolver* proxy_resolver() const { return proxy_resolver_; }
 
  protected:
+  // Cancels a proxy resolution in progress. The callback passed to
+  // ResolveProxiesForUrl() will not be called. Returns whether there was a
+  // pending proxy resolution to be canceled.
+  bool CancelProxyResolution();
+
   // The URL we're actively fetching from
   std::string url_;
 
@@ -169,6 +174,10 @@
   // |proxy_resolver_|.
   void NoProxyResolverCallback();
 
+  // Stores the ongoing proxy request id if there is one, otherwise
+  // kProxyRequestIdNull.
+  ProxyRequestId proxy_request_{kProxyRequestIdNull};
+
   DISALLOW_COPY_AND_ASSIGN(HttpFetcher);
 };
 
diff --git a/common/http_fetcher_unittest.cc b/common/http_fetcher_unittest.cc
index 5577b96..73110e9 100644
--- a/common/http_fetcher_unittest.cc
+++ b/common/http_fetcher_unittest.cc
@@ -42,12 +42,13 @@
 #include <gtest/gtest.h>
 
 #include "update_engine/common/fake_hardware.h"
+#include "update_engine/common/file_fetcher.h"
 #include "update_engine/common/http_common.h"
-#include "update_engine/common/libcurl_http_fetcher.h"
 #include "update_engine/common/mock_http_fetcher.h"
 #include "update_engine/common/multi_range_http_fetcher.h"
 #include "update_engine/common/test_utils.h"
 #include "update_engine/common/utils.h"
+#include "update_engine/libcurl_http_fetcher.h"
 #include "update_engine/mock_proxy_resolver.h"
 #include "update_engine/proxy_resolver.h"
 
@@ -217,6 +218,7 @@
 
   virtual bool IsMock() const = 0;
   virtual bool IsMulti() const = 0;
+  virtual bool IsHttpSupported() const = 0;
 
   virtual void IgnoreServerAborting(HttpServer* server) const {}
 
@@ -249,6 +251,7 @@
 
   bool IsMock() const override { return true; }
   bool IsMulti() const override { return false; }
+  bool IsHttpSupported() const override { return true; }
 
   HttpServer* CreateServer() override {
     return new NullHttpServer;
@@ -289,6 +292,7 @@
 
   bool IsMock() const override { return false; }
   bool IsMulti() const override { return false; }
+  bool IsHttpSupported() const override { return true; }
 
   void IgnoreServerAborting(HttpServer* server) const override {
     // Nothing to do.
@@ -324,6 +328,42 @@
   bool IsMulti() const override { return true; }
 };
 
+class FileFetcherTest : public AnyHttpFetcherTest {
+ public:
+  // Necessary to unhide the definition in the base class.
+  using AnyHttpFetcherTest::NewLargeFetcher;
+  HttpFetcher* NewLargeFetcher(ProxyResolver* /* proxy_resolver */) override {
+    return new FileFetcher();
+  }
+
+  // Necessary to unhide the definition in the base class.
+  using AnyHttpFetcherTest::NewSmallFetcher;
+  HttpFetcher* NewSmallFetcher(ProxyResolver* proxy_resolver) override {
+    return NewLargeFetcher(proxy_resolver);
+  }
+
+  string BigUrl(in_port_t port) const override {
+    return "file://" + temp_file_.path();
+  }
+  string SmallUrl(in_port_t port) const override {
+    test_utils::WriteFileString(temp_file_.path(), "small contents");
+    return "file://" + temp_file_.path();
+  }
+  string ErrorUrl(in_port_t port) const override {
+    return "file:///path/to/non-existing-file";
+  }
+
+  bool IsMock() const override { return false; }
+  bool IsMulti() const override { return false; }
+  bool IsHttpSupported() const override { return false; }
+
+  void IgnoreServerAborting(HttpServer* server) const override {}
+
+  HttpServer* CreateServer() override { return new NullHttpServer; }
+
+ private:
+  test_utils::ScopedTempFile temp_file_{"ue_file_fetcher.XXXXXX"};
+};
 
 //
 // Infrastructure for type tests of HTTP fetcher.
@@ -361,7 +401,9 @@
 // Test case types list.
 typedef ::testing::Types<LibcurlHttpFetcherTest,
                          MockHttpFetcherTest,
-                         MultiRangeHttpFetcherTest> HttpFetcherTestTypes;
+                         MultiRangeHttpFetcherTest,
+                         FileFetcherTest>
+    HttpFetcherTestTypes;
 TYPED_TEST_CASE(HttpFetcherTest, HttpFetcherTestTypes);
 
 
@@ -390,8 +432,8 @@
   }
 
   void TransferTerminated(HttpFetcher* fetcher) override {
-    ADD_FAILURE();
     times_transfer_terminated_called_++;
+    MessageLoop::current()->BreakLoop();
   }
 
   // Are we expecting an error response? (default: no)
@@ -425,6 +467,7 @@
       fetcher.get(),
       this->test_.SmallUrl(server->GetPort())));
   this->loop_.Run();
+  EXPECT_EQ(0, delegate.times_transfer_terminated_called_);
 }
 
 TYPED_TEST(HttpFetcherTest, SimpleBigTest) {
@@ -440,6 +483,7 @@
       fetcher.get(),
       this->test_.BigUrl(server->GetPort())));
   this->loop_.Run();
+  EXPECT_EQ(0, delegate.times_transfer_terminated_called_);
 }
 
 // Issue #9648: when server returns an error HTTP response, the fetcher needs to
@@ -465,17 +509,17 @@
   this->loop_.Run();
 
   // Make sure that no bytes were received.
-  CHECK_EQ(delegate.times_received_bytes_called_, 0);
-  CHECK_EQ(fetcher->GetBytesDownloaded(), static_cast<size_t>(0));
+  EXPECT_EQ(0, delegate.times_received_bytes_called_);
+  EXPECT_EQ(0U, fetcher->GetBytesDownloaded());
 
   // Make sure that transfer completion was signaled once, and no termination
   // was signaled.
-  CHECK_EQ(delegate.times_transfer_complete_called_, 1);
-  CHECK_EQ(delegate.times_transfer_terminated_called_, 0);
+  EXPECT_EQ(1, delegate.times_transfer_complete_called_);
+  EXPECT_EQ(0, delegate.times_transfer_terminated_called_);
 }
 
 TYPED_TEST(HttpFetcherTest, ExtraHeadersInRequestTest) {
-  if (this->test_.IsMock())
+  if (this->test_.IsMock() || !this->test_.IsHttpSupported())
     return;
 
   HttpFetcherTestDelegate delegate;
@@ -496,7 +540,11 @@
   int port = server.GetPort();
   ASSERT_TRUE(server.started_);
 
-  StartTransfer(fetcher.get(), LocalServerUrlForPath(port, "/echo-headers"));
+  this->loop_.PostTask(
+      FROM_HERE,
+      base::Bind(StartTransfer,
+                 fetcher.get(),
+                 LocalServerUrlForPath(port, "/echo-headers")));
   this->loop_.Run();
 
   EXPECT_NE(string::npos,
@@ -569,7 +617,7 @@
 // This test will pause the fetcher while the download is not yet started
 // because it is waiting for the proxy to be resolved.
 TYPED_TEST(HttpFetcherTest, PauseWhileResolvingProxyTest) {
-  if (this->test_.IsMock())
+  if (this->test_.IsMock() || !this->test_.IsHttpSupported())
     return;
   MockProxyResolver mock_resolver;
   unique_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher(&mock_resolver));
@@ -659,6 +707,32 @@
   this->loop_.CancelTask(task_id);
 }
 
+TYPED_TEST(HttpFetcherTest, TerminateTransferWhileResolvingProxyTest) {
+  if (this->test_.IsMock() || !this->test_.IsHttpSupported())
+    return;
+  MockProxyResolver mock_resolver;
+  unique_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher(&mock_resolver));
+
+  HttpFetcherTestDelegate delegate;
+  fetcher->set_delegate(&delegate);
+
+  EXPECT_CALL(mock_resolver, GetProxiesForUrl(_, _)).WillOnce(Return(123));
+  fetcher->BeginTransfer("http://fake_url");
+  // Run the message loop until idle. This must call the MockProxyResolver with
+  // the request.
+  while (this->loop_.RunOnce(false)) {
+  }
+  testing::Mock::VerifyAndClearExpectations(&mock_resolver);
+
+  EXPECT_CALL(mock_resolver, CancelProxyRequest(123)).WillOnce(Return(true));
+
+  // Terminate the transfer right before the proxy resolution response.
+  fetcher->TerminateTransfer();
+  EXPECT_EQ(0, delegate.times_received_bytes_called_);
+  EXPECT_EQ(0, delegate.times_transfer_complete_called_);
+  EXPECT_EQ(1, delegate.times_transfer_terminated_called_);
+}
+
 namespace {
 class FlakyHttpFetcherTestDelegate : public HttpFetcherDelegate {
  public:
@@ -679,7 +753,7 @@
 }  // namespace
 
 TYPED_TEST(HttpFetcherTest, FlakyTest) {
-  if (this->test_.IsMock())
+  if (this->test_.IsMock() || !this->test_.IsHttpSupported())
     return;
   {
     FlakyHttpFetcherTestDelegate delegate;
@@ -721,7 +795,7 @@
   ~FailureHttpFetcherTestDelegate() override {
     if (server_) {
       LOG(INFO) << "Stopping server in destructor";
-      delete server_;
+      server_.reset();
       LOG(INFO) << "server stopped";
     }
   }
@@ -730,20 +804,23 @@
                      const void* bytes, size_t length) override {
     if (server_) {
       LOG(INFO) << "Stopping server in ReceivedBytes";
-      delete server_;
+      server_.reset();
       LOG(INFO) << "server stopped";
-      server_ = nullptr;
     }
   }
   void TransferComplete(HttpFetcher* fetcher, bool successful) override {
     EXPECT_FALSE(successful);
     EXPECT_EQ(0, fetcher->http_response_code());
+    times_transfer_complete_called_++;
     MessageLoop::current()->BreakLoop();
   }
   void TransferTerminated(HttpFetcher* fetcher) override {
-    ADD_FAILURE();
+    times_transfer_terminated_called_++;
+    MessageLoop::current()->BreakLoop();
   }
-  PythonHttpServer* server_;
+  unique_ptr<PythonHttpServer> server_;
+  int times_transfer_terminated_called_{0};
+  int times_transfer_complete_called_{0};
 };
 }  // namespace
 
@@ -753,19 +830,19 @@
   // available at all.
   if (this->test_.IsMock())
     return;
-  {
-    FailureHttpFetcherTestDelegate delegate(nullptr);
-    unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
-    fetcher->set_delegate(&delegate);
+  FailureHttpFetcherTestDelegate delegate(nullptr);
+  unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
+  fetcher->set_delegate(&delegate);
 
-    this->loop_.PostTask(FROM_HERE,
-                         base::Bind(StartTransfer,
-                                    fetcher.get(),
-                                    "http://host_doesnt_exist99999999"));
-    this->loop_.Run();
+  this->loop_.PostTask(
+      FROM_HERE,
+      base::Bind(
+          StartTransfer, fetcher.get(), "http://host_doesnt_exist99999999"));
+  this->loop_.Run();
+  EXPECT_EQ(1, delegate.times_transfer_complete_called_);
+  EXPECT_EQ(0, delegate.times_transfer_terminated_called_);
 
-    // Exiting and testing happens in the delegate
-  }
+  // Exiting and testing happens in the delegate
 }
 
 TYPED_TEST(HttpFetcherTest, NoResponseTest) {
@@ -793,11 +870,14 @@
       fetcher.get(),
       LocalServerUrlForPath(port, "/hang")));
   this->loop_.Run();
+  EXPECT_EQ(1, delegate.times_transfer_complete_called_);
+  EXPECT_EQ(0, delegate.times_transfer_terminated_called_);
 
   // Check that no other callback runs in the next two seconds. That would
   // indicate a leaked callback.
   bool timeout = false;
-  auto callback = base::Bind([&timeout]{ timeout = true;});
+  auto callback = base::Bind([](bool* timeout) { *timeout = true; },
+                             base::Unretained(&timeout));
   this->loop_.PostDelayedTask(FROM_HERE, callback,
                               base::TimeDelta::FromSeconds(2));
   EXPECT_TRUE(this->loop_.RunOnce(true));
@@ -810,29 +890,78 @@
   // retries and aborts correctly.
   if (this->test_.IsMock())
     return;
-  {
-    PythonHttpServer* server = new PythonHttpServer();
-    int port = server->GetPort();
-    ASSERT_TRUE(server->started_);
+  PythonHttpServer* server = new PythonHttpServer();
+  int port = server->GetPort();
+  ASSERT_TRUE(server->started_);
 
-    // Handles destruction and claims ownership.
-    FailureHttpFetcherTestDelegate delegate(server);
-    unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
-    fetcher->set_delegate(&delegate);
+  // Handles destruction and claims ownership.
+  FailureHttpFetcherTestDelegate delegate(server);
+  unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
+  fetcher->set_delegate(&delegate);
 
-    this->loop_.PostTask(FROM_HERE, base::Bind(
-        StartTransfer,
-        fetcher.get(),
-        LocalServerUrlForPath(port,
-                              base::StringPrintf("/flaky/%d/%d/%d/%d",
-                                                 kBigLength,
-                                                 kFlakyTruncateLength,
-                                                 kFlakySleepEvery,
-                                                 kFlakySleepSecs))));
-    this->loop_.Run();
+  this->loop_.PostTask(
+      FROM_HERE,
+      base::Bind(StartTransfer,
+                 fetcher.get(),
+                 LocalServerUrlForPath(port,
+                                       base::StringPrintf("/flaky/%d/%d/%d/%d",
+                                                          kBigLength,
+                                                          kFlakyTruncateLength,
+                                                          kFlakySleepEvery,
+                                                          kFlakySleepSecs))));
+  this->loop_.Run();
+  EXPECT_EQ(1, delegate.times_transfer_complete_called_);
+  EXPECT_EQ(0, delegate.times_transfer_terminated_called_);
 
-    // Exiting and testing happens in the delegate
-  }
+  // Exiting and testing happens in the delegate
+}
+
+// Test that we can cancel a transfer while it is still trying to connect to the
+// server. This test kills the server after a few bytes are received.
+TYPED_TEST(HttpFetcherTest, TerminateTransferWhenServerDiedTest) {
+  if (this->test_.IsMock() || !this->test_.IsHttpSupported())
+    return;
+
+  PythonHttpServer* server = new PythonHttpServer();
+  int port = server->GetPort();
+  ASSERT_TRUE(server->started_);
+
+  // Handles destruction and claims ownership.
+  FailureHttpFetcherTestDelegate delegate(server);
+  unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
+  fetcher->set_delegate(&delegate);
+
+  this->loop_.PostTask(
+      FROM_HERE,
+      base::Bind(StartTransfer,
+                 fetcher.get(),
+                 LocalServerUrlForPath(port,
+                                       base::StringPrintf("/flaky/%d/%d/%d/%d",
+                                                          kBigLength,
+                                                          kFlakyTruncateLength,
+                                                          kFlakySleepEvery,
+                                                          kFlakySleepSecs))));
+  // Terminating the transfer after 3 seconds gives it a chance to contact the
+  // server and enter the retry loop.
+  this->loop_.PostDelayedTask(FROM_HERE,
+                              base::Bind(&HttpFetcher::TerminateTransfer,
+                                         base::Unretained(fetcher.get())),
+                              base::TimeDelta::FromSeconds(3));
+
+  // Exiting and testing happens in the delegate.
+  this->loop_.Run();
+  EXPECT_EQ(0, delegate.times_transfer_complete_called_);
+  EXPECT_EQ(1, delegate.times_transfer_terminated_called_);
+
+  // Check that no other callback runs in the next two seconds. That would
+  // indicate a leaked callback.
+  bool timeout = false;
+  auto callback = base::Bind([](bool* timeout) { *timeout = true; },
+                             base::Unretained(&timeout));
+  this->loop_.PostDelayedTask(
+      FROM_HERE, callback, base::TimeDelta::FromSeconds(2));
+  EXPECT_TRUE(this->loop_.RunOnce(true));
+  EXPECT_TRUE(timeout);
 }
 
 namespace {
@@ -892,7 +1021,7 @@
 }  // namespace
 
 TYPED_TEST(HttpFetcherTest, SimpleRedirectTest) {
-  if (this->test_.IsMock())
+  if (this->test_.IsMock() || !this->test_.IsHttpSupported())
     return;
 
   unique_ptr<HttpServer> server(this->test_.CreateServer());
@@ -907,7 +1036,7 @@
 }
 
 TYPED_TEST(HttpFetcherTest, MaxRedirectTest) {
-  if (this->test_.IsMock())
+  if (this->test_.IsMock() || !this->test_.IsHttpSupported())
     return;
 
   unique_ptr<HttpServer> server(this->test_.CreateServer());
@@ -923,7 +1052,7 @@
 }
 
 TYPED_TEST(HttpFetcherTest, BeyondMaxRedirectTest) {
-  if (this->test_.IsMock())
+  if (this->test_.IsMock() || !this->test_.IsHttpSupported())
     return;
 
   unique_ptr<HttpServer> server(this->test_.CreateServer());
@@ -1136,7 +1265,75 @@
             kHttpResponseUndefined);
 }
 
+namespace {
+// This HttpFetcherDelegate calls TerminateTransfer at a configurable point.
+class MultiHttpFetcherTerminateTestDelegate : public HttpFetcherDelegate {
+ public:
+  explicit MultiHttpFetcherTerminateTestDelegate(size_t terminate_trigger_bytes)
+      : terminate_trigger_bytes_(terminate_trigger_bytes) {}
 
+  void ReceivedBytes(HttpFetcher* fetcher,
+                     const void* bytes,
+                     size_t length) override {
+    LOG(INFO) << "ReceivedBytes, " << length << " bytes.";
+    EXPECT_EQ(fetcher, fetcher_.get());
+    if (bytes_downloaded_ < terminate_trigger_bytes_ &&
+        bytes_downloaded_ + length >= terminate_trigger_bytes_) {
+      MessageLoop::current()->PostTask(
+          FROM_HERE,
+          base::Bind(&HttpFetcher::TerminateTransfer,
+                     base::Unretained(fetcher_.get())));
+    }
+    bytes_downloaded_ += length;
+  }
+
+  void TransferComplete(HttpFetcher* fetcher, bool successful) override {
+    ADD_FAILURE() << "TransferComplete called but expected a failure";
+    // Destroy the fetcher (because we're allowed to).
+    fetcher_.reset(nullptr);
+    MessageLoop::current()->BreakLoop();
+  }
+
+  void TransferTerminated(HttpFetcher* fetcher) override {
+    // Destroy the fetcher (because we're allowed to).
+    fetcher_.reset(nullptr);
+    MessageLoop::current()->BreakLoop();
+  }
+
+  unique_ptr<HttpFetcher> fetcher_;
+  size_t bytes_downloaded_{0};
+  size_t terminate_trigger_bytes_;
+};
+}  // namespace
+
+TYPED_TEST(HttpFetcherTest, MultiHttpFetcherTerminateBetweenRangesTest) {
+  if (!this->test_.IsMulti())
+    return;
+  const size_t kRangeTrigger = 1000;
+  MultiHttpFetcherTerminateTestDelegate delegate(kRangeTrigger);
+
+  unique_ptr<HttpServer> server(this->test_.CreateServer());
+  ASSERT_TRUE(server->started_);
+
+  MultiRangeHttpFetcher* multi_fetcher =
+      static_cast<MultiRangeHttpFetcher*>(this->test_.NewLargeFetcher());
+  ASSERT_TRUE(multi_fetcher);
+  // Transfer ownership of the fetcher to the delegate.
+  delegate.fetcher_.reset(multi_fetcher);
+  multi_fetcher->set_delegate(&delegate);
+
+  multi_fetcher->ClearRanges();
+  multi_fetcher->AddRange(45, kRangeTrigger);
+  multi_fetcher->AddRange(2000, 100);
+
+  this->test_.fake_hardware()->SetIsOfficialBuild(false);
+
+  StartTransfer(multi_fetcher, this->test_.BigUrl(server->GetPort()));
+  MessageLoop::current()->Run();
+
+  // Check that the delegate made it to the trigger point.
+  EXPECT_EQ(kRangeTrigger, delegate.bytes_downloaded_);
+}
 
 namespace {
 class BlockedTransferTestDelegate : public HttpFetcherDelegate {
diff --git a/common/mock_hardware.h b/common/mock_hardware.h
index 826b3b3..1c4253a 100644
--- a/common/mock_hardware.h
+++ b/common/mock_hardware.h
@@ -36,6 +36,9 @@
     ON_CALL(*this, IsNormalBootMode())
       .WillByDefault(testing::Invoke(&fake_,
             &FakeHardware::IsNormalBootMode));
+    ON_CALL(*this, AreDevFeaturesEnabled())
+      .WillByDefault(testing::Invoke(&fake_,
+            &FakeHardware::AreDevFeaturesEnabled));
     ON_CALL(*this, IsOOBEEnabled())
       .WillByDefault(testing::Invoke(&fake_,
             &FakeHardware::IsOOBEEnabled));
diff --git a/common/mock_http_fetcher.cc b/common/mock_http_fetcher.cc
index d0348f1..f1ae72a 100644
--- a/common/mock_http_fetcher.cc
+++ b/common/mock_http_fetcher.cc
@@ -123,6 +123,13 @@
   extra_headers_[base::ToLowerASCII(header_name)] = header_value;
 }
 
+std::string MockHttpFetcher::GetHeader(const std::string& header_name) const {
+  const auto it = extra_headers_.find(base::ToLowerASCII(header_name));
+  if (it == extra_headers_.end())
+    return "";
+  return it->second;
+}
+
 void MockHttpFetcher::Pause() {
   CHECK(!paused_);
   paused_ = true;
diff --git a/common/mock_http_fetcher.h b/common/mock_http_fetcher.h
index e56318e..367802e 100644
--- a/common/mock_http_fetcher.h
+++ b/common/mock_http_fetcher.h
@@ -91,6 +91,10 @@
   void SetHeader(const std::string& header_name,
                  const std::string& header_value) override;
 
+  // Return the value of the header |header_name| or the empty string if not
+  // set.
+  std::string GetHeader(const std::string& header_name) const;
+
   // Suspend the mock transfer.
   void Pause() override;
 
diff --git a/common/multi_range_http_fetcher.cc b/common/multi_range_http_fetcher.cc
index 0a97b6e..e696c36 100644
--- a/common/multi_range_http_fetcher.cc
+++ b/common/multi_range_http_fetcher.cc
@@ -59,6 +59,7 @@
   terminating_ = true;
 
   if (!pending_transfer_ended_) {
+    pending_transfer_ended_ = true;
     base_fetcher_->TerminateTransfer();
   }
 }
diff --git a/common/prefs.cc b/common/prefs.cc
index a4b97d0..12d06c0 100644
--- a/common/prefs.cc
+++ b/common/prefs.cc
@@ -29,31 +29,12 @@
 
 namespace chromeos_update_engine {
 
-bool Prefs::Init(const base::FilePath& prefs_dir) {
-  prefs_dir_ = prefs_dir;
-  return true;
+bool PrefsBase::GetString(const string& key, string* value) const {
+  return storage_->GetKey(key, value);
 }
 
-bool Prefs::GetString(const string& key, string* value) const {
-  base::FilePath filename;
-  TEST_AND_RETURN_FALSE(GetFileNameForKey(key, &filename));
-  if (!base::ReadFileToString(filename, value)) {
-    LOG(INFO) << key << " not present in " << prefs_dir_.value();
-    return false;
-  }
-  return true;
-}
-
-bool Prefs::SetString(const string& key, const string& value) {
-  base::FilePath filename;
-  TEST_AND_RETURN_FALSE(GetFileNameForKey(key, &filename));
-  if (!base::DirectoryExists(filename.DirName())) {
-    // Only attempt to create the directory if it doesn't exist to avoid calls
-    // to parent directories where we might not have permission to write to.
-    TEST_AND_RETURN_FALSE(base::CreateDirectory(filename.DirName()));
-  }
-  TEST_AND_RETURN_FALSE(base::WriteFile(filename, value.data(), value.size()) ==
-                        static_cast<int>(value.size()));
+bool PrefsBase::SetString(const string& key, const string& value) {
+  TEST_AND_RETURN_FALSE(storage_->SetKey(key, value));
   const auto observers_for_key = observers_.find(key);
   if (observers_for_key != observers_.end()) {
     std::vector<ObserverInterface*> copy_observers(observers_for_key->second);
@@ -63,7 +44,7 @@
   return true;
 }
 
-bool Prefs::GetInt64(const string& key, int64_t* value) const {
+bool PrefsBase::GetInt64(const string& key, int64_t* value) const {
   string str_value;
   if (!GetString(key, &str_value))
     return false;
@@ -72,11 +53,11 @@
   return true;
 }
 
-bool Prefs::SetInt64(const string& key, const int64_t value) {
+bool PrefsBase::SetInt64(const string& key, const int64_t value) {
   return SetString(key, base::Int64ToString(value));
 }
 
-bool Prefs::GetBoolean(const string& key, bool* value) const {
+bool PrefsBase::GetBoolean(const string& key, bool* value) const {
   string str_value;
   if (!GetString(key, &str_value))
     return false;
@@ -92,20 +73,16 @@
   return false;
 }
 
-bool Prefs::SetBoolean(const string& key, const bool value) {
+bool PrefsBase::SetBoolean(const string& key, const bool value) {
   return SetString(key, value ? "true" : "false");
 }
 
-bool Prefs::Exists(const string& key) const {
-  base::FilePath filename;
-  TEST_AND_RETURN_FALSE(GetFileNameForKey(key, &filename));
-  return base::PathExists(filename);
+bool PrefsBase::Exists(const string& key) const {
+  return storage_->KeyExists(key);
 }
 
-bool Prefs::Delete(const string& key) {
-  base::FilePath filename;
-  TEST_AND_RETURN_FALSE(GetFileNameForKey(key, &filename));
-  TEST_AND_RETURN_FALSE(base::DeleteFile(filename, false));
+bool PrefsBase::Delete(const string& key) {
+  TEST_AND_RETURN_FALSE(storage_->DeleteKey(key));
   const auto observers_for_key = observers_.find(key);
   if (observers_for_key != observers_.end()) {
     std::vector<ObserverInterface*> copy_observers(observers_for_key->second);
@@ -115,11 +92,11 @@
   return true;
 }
 
-void Prefs::AddObserver(const string& key, ObserverInterface* observer) {
+void PrefsBase::AddObserver(const string& key, ObserverInterface* observer) {
   observers_[key].push_back(observer);
 }
 
-void Prefs::RemoveObserver(const string& key, ObserverInterface* observer) {
+void PrefsBase::RemoveObserver(const string& key, ObserverInterface* observer) {
   std::vector<ObserverInterface*>& observers_for_key = observers_[key];
   auto observer_it =
       std::find(observers_for_key.begin(), observers_for_key.end(), observer);
@@ -127,8 +104,55 @@
     observers_for_key.erase(observer_it);
 }
 
-bool Prefs::GetFileNameForKey(const string& key,
-                              base::FilePath* filename) const {
+// Prefs
+
+bool Prefs::Init(const base::FilePath& prefs_dir) {
+  return file_storage_.Init(prefs_dir);
+}
+
+bool Prefs::FileStorage::Init(const base::FilePath& prefs_dir) {
+  prefs_dir_ = prefs_dir;
+  return true;
+}
+
+bool Prefs::FileStorage::GetKey(const string& key, string* value) const {
+  base::FilePath filename;
+  TEST_AND_RETURN_FALSE(GetFileNameForKey(key, &filename));
+  if (!base::ReadFileToString(filename, value)) {
+    LOG(INFO) << key << " not present in " << prefs_dir_.value();
+    return false;
+  }
+  return true;
+}
+
+bool Prefs::FileStorage::SetKey(const string& key, const string& value) {
+  base::FilePath filename;
+  TEST_AND_RETURN_FALSE(GetFileNameForKey(key, &filename));
+  if (!base::DirectoryExists(filename.DirName())) {
+    // Only attempt to create the directory if it doesn't exist to avoid calls
+    // to parent directories where we might not have permission to write to.
+    TEST_AND_RETURN_FALSE(base::CreateDirectory(filename.DirName()));
+  }
+  TEST_AND_RETURN_FALSE(base::WriteFile(filename, value.data(), value.size()) ==
+                        static_cast<int>(value.size()));
+  return true;
+}
+
+bool Prefs::FileStorage::KeyExists(const string& key) const {
+  base::FilePath filename;
+  TEST_AND_RETURN_FALSE(GetFileNameForKey(key, &filename));
+  return base::PathExists(filename);
+}
+
+bool Prefs::FileStorage::DeleteKey(const string& key) {
+  base::FilePath filename;
+  TEST_AND_RETURN_FALSE(GetFileNameForKey(key, &filename));
+  TEST_AND_RETURN_FALSE(base::DeleteFile(filename, false));
+  return true;
+}
+
+bool Prefs::FileStorage::GetFileNameForKey(const string& key,
+                                           base::FilePath* filename) const {
   // Allows only non-empty keys containing [A-Za-z0-9_-].
   TEST_AND_RETURN_FALSE(!key.empty());
   for (size_t i = 0; i < key.size(); ++i) {
@@ -140,4 +164,33 @@
   return true;
 }
 
+// MemoryPrefs
+
+bool MemoryPrefs::MemoryStorage::GetKey(const string& key,
+                                        string* value) const {
+  auto it = values_.find(key);
+  if (it == values_.end())
+    return false;
+  *value = it->second;
+  return true;
+}
+
+bool MemoryPrefs::MemoryStorage::SetKey(const string& key,
+                                        const string& value) {
+  values_[key] = value;
+  return true;
+}
+
+bool MemoryPrefs::MemoryStorage::KeyExists(const string& key) const {
+  return values_.find(key) != values_.end();
+}
+
+bool MemoryPrefs::MemoryStorage::DeleteKey(const string& key) {
+  auto it = values_.find(key);
+  if (it == values_.end())
+    return false;
+  values_.erase(it);
+  return true;
+}
+
 }  // namespace chromeos_update_engine
diff --git a/common/prefs.h b/common/prefs.h
index f11abc3..0116454 100644
--- a/common/prefs.h
+++ b/common/prefs.h
@@ -28,18 +28,36 @@
 
 namespace chromeos_update_engine {
 
-// Implements a preference store by storing the value associated with
-// a key in a separate file named after the key under a preference
-// store directory.
-
-class Prefs : public PrefsInterface {
+// Implements a preference store by storing the value associated with a key
+// in a given storage passed during construction.
+class PrefsBase : public PrefsInterface {
  public:
-  Prefs() = default;
+  // Storage interface used to set and retrieve keys.
+  class StorageInterface {
+   public:
+    StorageInterface() = default;
+    virtual ~StorageInterface() = default;
 
-  // Initializes the store by associating this object with |prefs_dir|
-  // as the preference store directory. Returns true on success, false
-  // otherwise.
-  bool Init(const base::FilePath& prefs_dir);
+    // Get the key named |key| and store its value in the referenced |value|.
+    // Returns whether the operation succeeded.
+    virtual bool GetKey(const std::string& key, std::string* value) const = 0;
+
+    // Set the value of the key named |key| to |value| regardless of the
+    // previous value. Returns whether the operation succeeded.
+    virtual bool SetKey(const std::string& key, const std::string& value) = 0;
+
+    // Returns whether the key named |key| exists.
+    virtual bool KeyExists(const std::string& key) const = 0;
+
+    // Deletes the value associated with the key name |key|. Returns whether the
+    // key was deleted.
+    virtual bool DeleteKey(const std::string& key) = 0;
+
+   private:
+    DISALLOW_COPY_AND_ASSIGN(StorageInterface);
+  };
+
+  explicit PrefsBase(StorageInterface* storage) : storage_(storage) {}
 
   // PrefsInterface methods.
   bool GetString(const std::string& key, std::string* value) const override;
@@ -58,24 +76,93 @@
                       ObserverInterface* observer) override;
 
  private:
+  // The registered observers watching for changes.
+  std::map<std::string, std::vector<ObserverInterface*>> observers_;
+
+  // The concrete implementation of the storage used for the keys.
+  StorageInterface* storage_;
+
+  DISALLOW_COPY_AND_ASSIGN(PrefsBase);
+};
+
+// Implements a preference store by storing the value associated with
+// a key in a separate file named after the key under a preference
+// store directory.
+
+class Prefs : public PrefsBase {
+ public:
+  Prefs() : PrefsBase(&file_storage_) {}
+
+  // Initializes the store by associating this object with |prefs_dir|
+  // as the preference store directory. Returns true on success, false
+  // otherwise.
+  bool Init(const base::FilePath& prefs_dir);
+
+ private:
   FRIEND_TEST(PrefsTest, GetFileNameForKey);
   FRIEND_TEST(PrefsTest, GetFileNameForKeyBadCharacter);
   FRIEND_TEST(PrefsTest, GetFileNameForKeyEmpty);
 
-  // Sets |filename| to the full path to the file containing the data
-  // associated with |key|. Returns true on success, false otherwise.
-  bool GetFileNameForKey(const std::string& key,
-                         base::FilePath* filename) const;
+  class FileStorage : public PrefsBase::StorageInterface {
+   public:
+    FileStorage() = default;
 
-  // Preference store directory.
-  base::FilePath prefs_dir_;
+    bool Init(const base::FilePath& prefs_dir);
 
-  // The registered observers watching for changes.
-  std::map<std::string, std::vector<ObserverInterface*>> observers_;
+    // PrefsBase::StorageInterface overrides.
+    bool GetKey(const std::string& key, std::string* value) const override;
+    bool SetKey(const std::string& key, const std::string& value) override;
+    bool KeyExists(const std::string& key) const override;
+    bool DeleteKey(const std::string& key) override;
+
+   private:
+    FRIEND_TEST(PrefsTest, GetFileNameForKey);
+    FRIEND_TEST(PrefsTest, GetFileNameForKeyBadCharacter);
+    FRIEND_TEST(PrefsTest, GetFileNameForKeyEmpty);
+
+    // Sets |filename| to the full path to the file containing the data
+    // associated with |key|. Returns true on success, false otherwise.
+    bool GetFileNameForKey(const std::string& key,
+                           base::FilePath* filename) const;
+
+    // Preference store directory.
+    base::FilePath prefs_dir_;
+  };
+
+  // The concrete file storage implementation.
+  FileStorage file_storage_;
 
   DISALLOW_COPY_AND_ASSIGN(Prefs);
 };
 
+// Implements a preference store in memory. The stored values are lost when the
+// object is destroyed.
+
+class MemoryPrefs : public PrefsBase {
+ public:
+  MemoryPrefs() : PrefsBase(&mem_storage_) {}
+
+ private:
+  class MemoryStorage : public PrefsBase::StorageInterface {
+   public:
+    MemoryStorage() = default;
+
+    // PrefsBase::StorageInterface overrides.
+    bool GetKey(const std::string& key, std::string* value) const override;
+    bool SetKey(const std::string& key, const std::string& value) override;
+    bool KeyExists(const std::string& key) const override;
+    bool DeleteKey(const std::string& key) override;
+
+   private:
+    // The std::map holding the values in memory.
+    std::map<std::string, std::string> values_;
+  };
+
+  // The concrete memory storage implementation.
+  MemoryStorage mem_storage_;
+
+  DISALLOW_COPY_AND_ASSIGN(MemoryPrefs);
+};
 }  // namespace chromeos_update_engine
 
 #endif  // UPDATE_ENGINE_COMMON_PREFS_H_
diff --git a/common/prefs_unittest.cc b/common/prefs_unittest.cc
index 1000131..73ceb00 100644
--- a/common/prefs_unittest.cc
+++ b/common/prefs_unittest.cc
@@ -18,6 +18,7 @@
 
 #include <inttypes.h>
 
+#include <limits>
 #include <string>
 
 #include <base/files/file_util.h>
@@ -61,18 +62,18 @@
   const char kAllvalidCharsKey[] =
       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_-";
   base::FilePath path;
-  EXPECT_TRUE(prefs_.GetFileNameForKey(kAllvalidCharsKey, &path));
+  EXPECT_TRUE(prefs_.file_storage_.GetFileNameForKey(kAllvalidCharsKey, &path));
   EXPECT_EQ(prefs_dir_.Append(kAllvalidCharsKey).value(), path.value());
 }
 
 TEST_F(PrefsTest, GetFileNameForKeyBadCharacter) {
   base::FilePath path;
-  EXPECT_FALSE(prefs_.GetFileNameForKey("ABC abc", &path));
+  EXPECT_FALSE(prefs_.file_storage_.GetFileNameForKey("ABC abc", &path));
 }
 
 TEST_F(PrefsTest, GetFileNameForKeyEmpty) {
   base::FilePath path;
-  EXPECT_FALSE(prefs_.GetFileNameForKey("", &path));
+  EXPECT_FALSE(prefs_.file_storage_.GetFileNameForKey("", &path));
 }
 
 TEST_F(PrefsTest, GetString) {
@@ -337,4 +338,24 @@
   prefs_.RemoveObserver(kInvalidKey, &mock_obserser);
 }
 
+class MemoryPrefsTest : public ::testing::Test {
+ protected:
+  MemoryPrefs prefs_;
+};
+
+TEST_F(MemoryPrefsTest, BasicTest) {
+  EXPECT_FALSE(prefs_.Exists(kKey));
+  int64_t value = 0;
+  EXPECT_FALSE(prefs_.GetInt64(kKey, &value));
+
+  EXPECT_TRUE(prefs_.SetInt64(kKey, 1234));
+  EXPECT_TRUE(prefs_.Exists(kKey));
+  EXPECT_TRUE(prefs_.GetInt64(kKey, &value));
+  EXPECT_EQ(1234, value);
+
+  EXPECT_TRUE(prefs_.Delete(kKey));
+  EXPECT_FALSE(prefs_.Exists(kKey));
+  EXPECT_FALSE(prefs_.Delete(kKey));
+}
+
 }  // namespace chromeos_update_engine
diff --git a/common/subprocess.cc b/common/subprocess.cc
index 53cccff..4e6d352 100644
--- a/common/subprocess.cc
+++ b/common/subprocess.cc
@@ -213,8 +213,10 @@
   if (pid_record == subprocess_records_.end())
     return;
   pid_record->second->callback.Reset();
-  if (kill(pid, SIGTERM) != 0) {
-    PLOG(WARNING) << "Error sending SIGTERM to " << pid;
+  // We don't care about output/return code, so we use SIGKILL here to ensure it
+  // will be killed, SIGTERM might lead to leaked subprocess.
+  if (kill(pid, SIGKILL) != 0) {
+    PLOG(WARNING) << "Error sending SIGKILL to " << pid;
   }
   // Release the pid now so we don't try to kill it if Subprocess is destroyed
   // before the corresponding ChildExitedCallback() is called.
diff --git a/common/subprocess_unittest.cc b/common/subprocess_unittest.cc
index bc1a45e..cbc9a85 100644
--- a/common/subprocess_unittest.cc
+++ b/common/subprocess_unittest.cc
@@ -88,7 +88,7 @@
 void ExpectedEnvVars(int return_code, const string& output) {
   EXPECT_EQ(0, return_code);
   const std::set<string> allowed_envs = {"LD_LIBRARY_PATH", "PATH"};
-  for (string key_value : brillo::string_utils::Split(output, "\n")) {
+  for (const string& key_value : brillo::string_utils::Split(output, "\n")) {
     auto key_value_pair = brillo::string_utils::SplitAtFirst(
         key_value, "=", true);
     EXPECT_NE(allowed_envs.end(), allowed_envs.find(key_value_pair.first));
@@ -260,13 +260,13 @@
                             fifo_fd,
                             MessageLoop::WatchMode::kWatchRead,
                             false,
-                            base::Bind([fifo_fd, tag] {
+                            base::Bind([](int fifo_fd, uint32_t tag) {
                               char c;
                               EXPECT_EQ(1, HANDLE_EINTR(read(fifo_fd, &c, 1)));
                               EXPECT_EQ('X', c);
                               LOG(INFO) << "Killing tag " << tag;
                               Subprocess::Get().KillExec(tag);
-                            }));
+                            }, fifo_fd, tag));
 
   // This test would leak a callback that runs when the child process exits
   // unless we wait for it to run.
diff --git a/common/test_utils.cc b/common/test_utils.cc
index dfdc6b8..fb22c80 100644
--- a/common/test_utils.cc
+++ b/common/test_utils.cc
@@ -25,6 +25,7 @@
 #include <stdlib.h>
 #include <sys/ioctl.h>
 #include <sys/stat.h>
+#include <sys/sysmacros.h>
 #include <sys/types.h>
 #include <sys/xattr.h>
 #include <unistd.h>
diff --git a/common/test_utils.h b/common/test_utils.h
index 363801f..ba9f5f2 100644
--- a/common/test_utils.h
+++ b/common/test_utils.h
@@ -165,7 +165,7 @@
     unlinker_.reset(new ScopedPathUnlinker(path_));
   }
 
-  const std::string& path() { return path_; }
+  const std::string& path() const { return path_; }
 
  private:
   std::string path_;
diff --git a/common/utils.cc b/common/utils.cc
index dd2afea..b63b867 100644
--- a/common/utils.cc
+++ b/common/utils.cc
@@ -83,6 +83,11 @@
 // The path to the kernel's boot_id.
 const char kBootIdPath[] = "/proc/sys/kernel/random/boot_id";
 
+// A pointer to a null-terminated string containing the root directory where all
+// the temporary files should be created. If null, the system default is used
+// instead.
+const char* root_temp_dir = nullptr;
+
 // Return true if |disk_name| is an MTD or a UBI device. Note that this test is
 // simply based on the name of the device.
 bool IsMtdDeviceName(const string& disk_name) {
@@ -139,13 +144,17 @@
   }
 
   base::FilePath temp_dir;
+  if (root_temp_dir) {
+    temp_dir = base::FilePath(root_temp_dir);
+  } else {
 #ifdef __ANDROID__
-  temp_dir = base::FilePath(constants::kNonVolatileDirectory).Append("tmp");
+    temp_dir = base::FilePath(constants::kNonVolatileDirectory).Append("tmp");
+#else
+    TEST_AND_RETURN_FALSE(base::GetTempDir(&temp_dir));
+#endif  // __ANDROID__
+  }
   if (!base::PathExists(temp_dir))
     TEST_AND_RETURN_FALSE(base::CreateDirectory(temp_dir));
-#else
-  TEST_AND_RETURN_FALSE(base::GetTempDir(&temp_dir));
-#endif  // __ANDROID__
   *template_path = temp_dir.Append(path);
   return true;
 }
@@ -154,6 +163,10 @@
 
 namespace utils {
 
+void SetRootTempDir(const char* new_root_temp_dir) {
+  root_temp_dir = new_root_temp_dir;
+}
+
 string ParseECVersion(string input_line) {
   base::TrimWhitespaceASCII(input_line, base::TRIM_ALL, &input_line);
 
@@ -175,14 +188,11 @@
   return "";
 }
 
-bool WriteFile(const char* path, const void* data, int data_len) {
-  DirectFileWriter writer;
-  TEST_AND_RETURN_FALSE_ERRNO(0 == writer.Open(path,
-                                               O_WRONLY | O_CREAT | O_TRUNC,
-                                               0600));
-  ScopedFileWriterCloser closer(&writer);
-  TEST_AND_RETURN_FALSE_ERRNO(writer.Write(data, data_len));
-  return true;
+bool WriteFile(const char* path, const void* data, size_t data_len) {
+  int fd = HANDLE_EINTR(open(path, O_WRONLY | O_CREAT | O_TRUNC, 0600));
+  TEST_AND_RETURN_FALSE_ERRNO(fd >= 0);
+  ScopedFdCloser fd_closer(&fd);
+  return WriteAll(fd, data, data_len);
 }
 
 bool ReadAll(
@@ -245,7 +255,7 @@
   return true;
 }
 
-bool WriteAll(FileDescriptorPtr fd, const void* buf, size_t count) {
+bool WriteAll(const FileDescriptorPtr& fd, const void* buf, size_t count) {
   const char* c_buf = static_cast<const char*>(buf);
   ssize_t bytes_written = 0;
   while (bytes_written < static_cast<ssize_t>(count)) {
@@ -256,7 +266,7 @@
   return true;
 }
 
-bool PWriteAll(FileDescriptorPtr fd,
+bool PWriteAll(const FileDescriptorPtr& fd,
                const void* buf,
                size_t count,
                off_t offset) {
@@ -282,7 +292,7 @@
   return true;
 }
 
-bool PReadAll(FileDescriptorPtr fd, void* buf, size_t count, off_t offset,
+bool PReadAll(const FileDescriptorPtr& fd, void* buf, size_t count, off_t offset,
               ssize_t* out_bytes_read) {
   TEST_AND_RETURN_FALSE_ERRNO(fd->Seek(offset, SEEK_SET) !=
                               static_cast<off_t>(-1));
@@ -672,17 +682,53 @@
 }
 
 bool UnmountFilesystem(const string& mountpoint) {
-  for (int num_retries = 0; ; ++num_retries) {
+  int num_retries = 1;
+  for (;; ++num_retries) {
     if (umount(mountpoint.c_str()) == 0)
+      return true;
+    if (errno != EBUSY || num_retries >= kUnmountMaxNumOfRetries)
       break;
-
-    TEST_AND_RETURN_FALSE_ERRNO(errno == EBUSY &&
-                                num_retries < kUnmountMaxNumOfRetries);
     usleep(kUnmountRetryIntervalInMicroseconds);
   }
+  if (errno == EINVAL) {
+    LOG(INFO) << "Not a mountpoint: " << mountpoint;
+    return false;
+  }
+  PLOG(WARNING) << "Error unmounting " << mountpoint << " after " << num_retries
+                << " attempts. Lazy unmounting instead, error was";
+  if (umount2(mountpoint.c_str(), MNT_DETACH) != 0) {
+    PLOG(ERROR) << "Lazy unmount failed";
+    return false;
+  }
   return true;
 }
 
+bool IsMountpoint(const std::string& mountpoint) {
+  struct stat stdir, stparent;
+
+  // Check whether the passed mountpoint is a directory and the /.. is in the
+  // same device or not. If mountpoint/.. is in a different device it means that
+  // there is a filesystem mounted there. If it is not, but they both point to
+  // the same inode it basically is the special case of /.. pointing to /. This
+  // test doesn't play well with bind mount but that's out of the scope of what
+  // we want to detect here.
+  if (lstat(mountpoint.c_str(), &stdir) != 0) {
+    PLOG(ERROR) << "Error stat'ing " << mountpoint;
+    return false;
+  }
+  if (!S_ISDIR(stdir.st_mode))
+    return false;
+
+  base::FilePath parent(mountpoint);
+  parent = parent.Append("..");
+  if (lstat(parent.value().c_str(), &stparent) != 0) {
+    PLOG(ERROR) << "Error stat'ing " << parent.value();
+    return false;
+  }
+  return S_ISDIR(stparent.st_mode) &&
+         (stparent.st_dev != stdir.st_dev || stparent.st_ino == stdir.st_ino);
+}
+
 // Tries to parse the header of an ELF file to obtain a human-readable
 // description of it on the |output| string.
 static bool GetFileFormatELF(const uint8_t* buffer, size_t size,
@@ -878,35 +924,6 @@
   return base_code;
 }
 
-bool CreatePowerwashMarkerFile(const char* file_path) {
-  const char* marker_file = file_path ? file_path : kPowerwashMarkerFile;
-  bool result = utils::WriteFile(marker_file,
-                                 kPowerwashCommand,
-                                 strlen(kPowerwashCommand));
-  if (result) {
-    LOG(INFO) << "Created " << marker_file << " to powerwash on next reboot";
-  } else {
-    PLOG(ERROR) << "Error in creating powerwash marker file: " << marker_file;
-  }
-
-  return result;
-}
-
-bool DeletePowerwashMarkerFile(const char* file_path) {
-  const char* marker_file = file_path ? file_path : kPowerwashMarkerFile;
-  const base::FilePath kPowerwashMarkerPath(marker_file);
-  bool result = base::DeleteFile(kPowerwashMarkerPath, false);
-
-  if (result)
-    LOG(INFO) << "Successfully deleted the powerwash marker file : "
-              << marker_file;
-  else
-    PLOG(ERROR) << "Could not delete the powerwash marker file : "
-                << marker_file;
-
-  return result;
-}
-
 Time TimeFromStructTimespec(struct timespec *ts) {
   int64_t us = static_cast<int64_t>(ts->tv_sec) * Time::kMicrosecondsPerSecond +
       static_cast<int64_t>(ts->tv_nsec) / Time::kNanosecondsPerMicrosecond;
diff --git a/common/utils.h b/common/utils.h
index d009fbb..184e72b 100644
--- a/common/utils.h
+++ b/common/utils.h
@@ -62,15 +62,15 @@
 
 // Writes the data passed to path. The file at path will be overwritten if it
 // exists. Returns true on success, false otherwise.
-bool WriteFile(const char* path, const void* data, int data_len);
+bool WriteFile(const char* path, const void* data, size_t data_len);
 
 // Calls write() or pwrite() repeatedly until all count bytes at buf are
 // written to fd or an error occurs. Returns true on success.
 bool WriteAll(int fd, const void* buf, size_t count);
 bool PWriteAll(int fd, const void* buf, size_t count, off_t offset);
 
-bool WriteAll(FileDescriptorPtr fd, const void* buf, size_t count);
-bool PWriteAll(FileDescriptorPtr fd,
+bool WriteAll(const FileDescriptorPtr& fd, const void* buf, size_t count);
+bool PWriteAll(const FileDescriptorPtr& fd,
                const void* buf,
                size_t count,
                off_t offset);
@@ -88,7 +88,7 @@
 bool PReadAll(int fd, void* buf, size_t count, off_t offset,
               ssize_t* out_bytes_read);
 
-bool PReadAll(FileDescriptorPtr fd, void* buf, size_t count, off_t offset,
+bool PReadAll(const FileDescriptorPtr& fd, void* buf, size_t count, off_t offset,
               ssize_t* out_bytes_read);
 
 // Opens |path| for reading and appends its entire content to the container
@@ -131,6 +131,13 @@
 // only returns true if "/dev/ubi%d_0" becomes available in |timeout| seconds.
 bool TryAttachingUbiVolume(int volume_num, int timeout);
 
+// Setup the directory |new_root_temp_dir| to be used as the root directory for
+// temporary files instead of the system's default. If the directory doesn't
+// exists, it will be created when first used.
+// NOTE: The memory pointed by |new_root_temp_dir| must be available until this
+// function is called again with a different value.
+void SetRootTempDir(const char* new_root_temp_dir);
+
 // If |base_filename_template| is neither absolute (starts with "/") nor
 // explicitly relative to the current working directory (starts with "./" or
 // "../"), then it is prepended the system's temporary directory. On success,
@@ -185,6 +192,12 @@
                      const std::string& fs_mount_options);
 bool UnmountFilesystem(const std::string& mountpoint);
 
+// Return whether the passed |mountpoint| path is a directory where a filesystem
+// is mounted. Due to detection mechanism limitations, when used on directories
+// where another part of the tree was bind mounted returns true only if bind
+// mounted on top of a different filesystem (not inside the same filesystem).
+bool IsMountpoint(const std::string& mountpoint);
+
 // Returns a human-readable string with the file format based on magic constants
 // on the header of the file.
 std::string GetFileFormat(const std::string& path);
@@ -265,16 +278,6 @@
 // it'll return the same value again.
 ErrorCode GetBaseErrorCode(ErrorCode code);
 
-// Creates the powerwash marker file with the appropriate commands in it.  Uses
-// |file_path| as the path to the marker file if non-null, otherwise uses the
-// global default. Returns true if successfully created.  False otherwise.
-bool CreatePowerwashMarkerFile(const char* file_path);
-
-// Deletes the marker file used to trigger Powerwash using clobber-state.  Uses
-// |file_path| as the path to the marker file if non-null, otherwise uses the
-// global default. Returns true if successfully deleted. False otherwise.
-bool DeletePowerwashMarkerFile(const char* file_path);
-
 // Decodes the data in |base64_encoded| and stores it in a temporary
 // file. Returns false if the given data is empty, not well-formed
 // base64 or if an error occurred. If true is returned, the decoded
diff --git a/common/utils_unittest.cc b/common/utils_unittest.cc
index b5887e3..6e9a911 100644
--- a/common/utils_unittest.cc
+++ b/common/utils_unittest.cc
@@ -16,7 +16,9 @@
 
 #include "update_engine/common/utils.h"
 
+#include <fcntl.h>
 #include <stdint.h>
+#include <sys/mount.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 
@@ -50,6 +52,21 @@
   EXPECT_EQ("", utils::ParseECVersion("b=1231a fw_version a=fasd2"));
 }
 
+TEST(UtilsTest, WriteFileOpenFailure) {
+  EXPECT_FALSE(utils::WriteFile("/this/doesn't/exist", "hello", 5));
+}
+
+TEST(UtilsTest, WriteFileReadFile) {
+  base::FilePath file;
+  EXPECT_TRUE(base::CreateTemporaryFile(&file));
+  ScopedPathUnlinker unlinker(file.value());
+  EXPECT_TRUE(utils::WriteFile(file.value().c_str(), "hello", 5));
+
+  brillo::Blob readback;
+  EXPECT_TRUE(utils::ReadFile(file.value().c_str(), &readback));
+  EXPECT_EQ("hello", string(readback.begin(), readback.end()));
+}
+
 TEST(UtilsTest, ReadFileFailure) {
   brillo::Blob empty;
   EXPECT_FALSE(utils::ReadFile("/this/doesn't/exist", &empty));
@@ -441,4 +458,57 @@
   EXPECT_TRUE(BoolMacroTestHelper());
 }
 
+TEST(UtilsTest, RunAsRootUnmountFilesystemFailureTest) {
+  EXPECT_FALSE(utils::UnmountFilesystem("/path/to/non-existing-dir"));
+}
+
+TEST(UtilsTest, RunAsRootUnmountFilesystemBusyFailureTest) {
+  string tmp_image;
+  EXPECT_TRUE(utils::MakeTempFile("img.XXXXXX", &tmp_image, nullptr));
+  ScopedPathUnlinker tmp_image_unlinker(tmp_image);
+
+  EXPECT_TRUE(base::CopyFile(
+      test_utils::GetBuildArtifactsPath().Append("gen/disk_ext2_4k.img"),
+      base::FilePath(tmp_image)));
+
+  base::ScopedTempDir mnt_dir;
+  EXPECT_TRUE(mnt_dir.CreateUniqueTempDir());
+
+  string loop_dev;
+  test_utils::ScopedLoopbackDeviceBinder loop_binder(
+      tmp_image, true, &loop_dev);
+
+  EXPECT_FALSE(utils::IsMountpoint(mnt_dir.path().value()));
+  // This is the actual test part. While we hold a file descriptor open for the
+  // mounted filesystem, umount should still succeed.
+  EXPECT_TRUE(utils::MountFilesystem(
+      loop_dev, mnt_dir.path().value(), MS_RDONLY, "ext4", ""));
+  // Verify the directory is a mount point now.
+  EXPECT_TRUE(utils::IsMountpoint(mnt_dir.path().value()));
+
+  string target_file = mnt_dir.path().Append("empty-file").value();
+  int fd = HANDLE_EINTR(open(target_file.c_str(), O_RDONLY));
+  EXPECT_GE(fd, 0);
+  EXPECT_TRUE(utils::UnmountFilesystem(mnt_dir.path().value()));
+  // The filesystem should be already unmounted at this point.
+  EXPECT_FALSE(utils::IsMountpoint(mnt_dir.path().value()));
+  IGNORE_EINTR(close(fd));
+  // The filesystem was already unmounted so this call should fail.
+  EXPECT_FALSE(utils::UnmountFilesystem(mnt_dir.path().value()));
+}
+
+TEST(UtilsTest, IsMountpointTest) {
+  EXPECT_TRUE(utils::IsMountpoint("/"));
+  EXPECT_FALSE(utils::IsMountpoint("/path/to/nowhere"));
+
+  base::ScopedTempDir mnt_dir;
+  EXPECT_TRUE(mnt_dir.CreateUniqueTempDir());
+  EXPECT_FALSE(utils::IsMountpoint(mnt_dir.path().value()));
+
+  base::FilePath file;
+  EXPECT_TRUE(base::CreateTemporaryFile(&file));
+  ScopedPathUnlinker unlinker(file.value());
+  EXPECT_FALSE(utils::IsMountpoint(file.value()));
+}
+
 }  // namespace chromeos_update_engine
diff --git a/common_service.cc b/common_service.cc
index b8bc298..ee890e1 100644
--- a/common_service.cc
+++ b/common_service.cc
@@ -171,8 +171,6 @@
     LogAndSetError(error, FROM_HERE, error_message);
     return false;
   }
-  // Update the weave state because updated the target channel.
-  system_state_->update_attempter()->BroadcastChannel();
   return true;
 }
 
@@ -312,7 +310,7 @@
   if (connection_manager->IsAllowedConnectionTypesForUpdateSet()) {
     // We have device policy, so ignore the user preferences.
     *out_allowed = connection_manager->IsUpdateAllowedOver(
-        NetworkConnectionType::kCellular, NetworkTethering::kUnknown);
+        ConnectionType::kCellular, ConnectionTethering::kUnknown);
   } else {
     PrefsInterface* prefs = system_state_->prefs();
 
diff --git a/connection_manager.cc b/connection_manager.cc
index 47bd776..f0a2c92 100644
--- a/connection_manager.cc
+++ b/connection_manager.cc
@@ -27,6 +27,8 @@
 
 #include "update_engine/common/prefs.h"
 #include "update_engine/common/utils.h"
+#include "update_engine/connection_utils.h"
+#include "update_engine/shill_proxy.h"
 #include "update_engine/system_state.h"
 #include "update_engine/update_attempter.h"
 
@@ -37,48 +39,25 @@
 
 namespace chromeos_update_engine {
 
-namespace {
-
-NetworkConnectionType ParseConnectionType(const string& type_str) {
-  if (type_str == shill::kTypeEthernet) {
-    return NetworkConnectionType::kEthernet;
-  } else if (type_str == shill::kTypeWifi) {
-    return NetworkConnectionType::kWifi;
-  } else if (type_str == shill::kTypeWimax) {
-    return NetworkConnectionType::kWimax;
-  } else if (type_str == shill::kTypeBluetooth) {
-    return NetworkConnectionType::kBluetooth;
-  } else if (type_str == shill::kTypeCellular) {
-    return NetworkConnectionType::kCellular;
-  }
-  return NetworkConnectionType::kUnknown;
+namespace connection_manager {
+std::unique_ptr<ConnectionManagerInterface> CreateConnectionManager(
+    SystemState* system_state) {
+  return std::unique_ptr<ConnectionManagerInterface>(
+      new ConnectionManager(new ShillProxy(), system_state));
 }
-
-NetworkTethering ParseTethering(const string& tethering_str) {
-  if (tethering_str == shill::kTetheringNotDetectedState) {
-    return NetworkTethering::kNotDetected;
-  } else if (tethering_str == shill::kTetheringSuspectedState) {
-    return NetworkTethering::kSuspected;
-  } else if (tethering_str == shill::kTetheringConfirmedState) {
-    return NetworkTethering::kConfirmed;
-  }
-  LOG(WARNING) << "Unknown Tethering value: " << tethering_str;
-  return NetworkTethering::kUnknown;
 }
 
-}  // namespace
-
 ConnectionManager::ConnectionManager(ShillProxyInterface* shill_proxy,
                                      SystemState* system_state)
     : shill_proxy_(shill_proxy), system_state_(system_state) {}
 
-bool ConnectionManager::IsUpdateAllowedOver(NetworkConnectionType type,
-                                            NetworkTethering tethering) const {
+bool ConnectionManager::IsUpdateAllowedOver(
+    ConnectionType type, ConnectionTethering tethering) const {
   switch (type) {
-    case NetworkConnectionType::kBluetooth:
+    case ConnectionType::kBluetooth:
       return false;
 
-    case NetworkConnectionType::kCellular: {
+    case ConnectionType::kCellular: {
       set<string> allowed_types;
 
       const policy::DevicePolicy* device_policy =
@@ -118,12 +97,12 @@
     }
 
     default:
-      if (tethering == NetworkTethering::kConfirmed) {
+      if (tethering == ConnectionTethering::kConfirmed) {
         // Treat this connection as if it is a cellular connection.
         LOG(INFO) << "Current connection is confirmed tethered, using Cellular "
                      "setting.";
-        return IsUpdateAllowedOver(NetworkConnectionType::kCellular,
-                                   NetworkTethering::kUnknown);
+        return IsUpdateAllowedOver(ConnectionType::kCellular,
+                                   ConnectionTethering::kUnknown);
       }
       return true;
   }
@@ -145,29 +124,8 @@
   return true;
 }
 
-// static
-const char* ConnectionManager::StringForConnectionType(
-    NetworkConnectionType type) {
-  switch (type) {
-    case NetworkConnectionType::kEthernet:
-      return shill::kTypeEthernet;
-    case NetworkConnectionType::kWifi:
-      return shill::kTypeWifi;
-    case NetworkConnectionType::kWimax:
-      return shill::kTypeWimax;
-    case NetworkConnectionType::kBluetooth:
-      return shill::kTypeBluetooth;
-    case NetworkConnectionType::kCellular:
-      return shill::kTypeCellular;
-    case NetworkConnectionType::kUnknown:
-      return "Unknown";
-  }
-  return "Unknown";
-}
-
 bool ConnectionManager::GetConnectionProperties(
-    NetworkConnectionType* out_type,
-    NetworkTethering* out_tethering) {
+    ConnectionType* out_type, ConnectionTethering* out_tethering) {
   dbus::ObjectPath default_service_path;
   TEST_AND_RETURN_FALSE(GetDefaultServicePath(&default_service_path));
   if (!default_service_path.IsValid())
@@ -199,8 +157,8 @@
 
 bool ConnectionManager::GetServicePathProperties(
     const dbus::ObjectPath& path,
-    NetworkConnectionType* out_type,
-    NetworkTethering* out_tethering) {
+    ConnectionType* out_type,
+    ConnectionTethering* out_tethering) {
   // We create and dispose the ServiceProxyInterface on every request.
   std::unique_ptr<ServiceProxyInterface> service =
       shill_proxy_->GetServiceForPath(path);
@@ -213,18 +171,19 @@
   const auto& prop_tethering = properties.find(shill::kTetheringProperty);
   if (prop_tethering == properties.end()) {
     // Set to Unknown if not present.
-    *out_tethering = NetworkTethering::kUnknown;
+    *out_tethering = ConnectionTethering::kUnknown;
   } else {
     // If the property doesn't contain a string value, the empty string will
     // become kUnknown.
-    *out_tethering = ParseTethering(prop_tethering->second.TryGet<string>());
+    *out_tethering = connection_utils::ParseConnectionTethering(
+        prop_tethering->second.TryGet<string>());
   }
 
   // Populate the out_type property.
   const auto& prop_type = properties.find(shill::kTypeProperty);
   if (prop_type == properties.end()) {
     // Set to Unknown if not present.
-    *out_type = NetworkConnectionType::kUnknown;
+    *out_type = ConnectionType::kUnknown;
     return false;
   }
 
@@ -236,12 +195,13 @@
       LOG(ERROR) << "No PhysicalTechnology property found for a VPN"
                     " connection (service: "
                  << path.value() << "). Returning default kUnknown value.";
-      *out_type = NetworkConnectionType::kUnknown;
+      *out_type = ConnectionType::kUnknown;
     } else {
-      *out_type = ParseConnectionType(prop_physical->second.TryGet<string>());
+      *out_type = connection_utils::ParseConnectionType(
+          prop_physical->second.TryGet<string>());
     }
   } else {
-    *out_type = ParseConnectionType(type_str);
+    *out_type = connection_utils::ParseConnectionType(type_str);
   }
   return true;
 }
diff --git a/connection_manager.h b/connection_manager.h
index 6f5fab4..864985e 100644
--- a/connection_manager.h
+++ b/connection_manager.h
@@ -27,17 +27,11 @@
 
 namespace chromeos_update_engine {
 
-class SystemState;
-
 // This class implements the concrete class that talks with the connection
 // manager (shill) over DBus.
 // TODO(deymo): Remove this class and use ShillProvider from the UpdateManager.
 class ConnectionManager : public ConnectionManagerInterface {
  public:
-  // Returns the string representation corresponding to the given
-  // connection type.
-  static const char* StringForConnectionType(NetworkConnectionType type);
-
   // Constructs a new ConnectionManager object initialized with the
   // given system state.
   ConnectionManager(ShillProxyInterface* shill_proxy,
@@ -45,10 +39,10 @@
   ~ConnectionManager() override = default;
 
   // ConnectionManagerInterface overrides.
-  bool GetConnectionProperties(NetworkConnectionType* out_type,
-                               NetworkTethering* out_tethering) override;
-  bool IsUpdateAllowedOver(NetworkConnectionType type,
-                           NetworkTethering tethering) const override;
+  bool GetConnectionProperties(ConnectionType* out_type,
+                               ConnectionTethering* out_tethering) override;
+  bool IsUpdateAllowedOver(ConnectionType type,
+                           ConnectionTethering tethering) const override;
   bool IsAllowedConnectionTypesForUpdateSet() const override;
 
  private:
@@ -57,11 +51,11 @@
   bool GetDefaultServicePath(dbus::ObjectPath* out_path);
 
   bool GetServicePathProperties(const dbus::ObjectPath& path,
-                                NetworkConnectionType* out_type,
-                                NetworkTethering* out_tethering);
+                                ConnectionType* out_type,
+                                ConnectionTethering* out_tethering);
 
   // The mockable interface to access the shill DBus proxies.
-  ShillProxyInterface* shill_proxy_;
+  std::unique_ptr<ShillProxyInterface> shill_proxy_;
 
   // The global context for update_engine.
   SystemState* system_state_;
diff --git a/connection_manager_android.cc b/connection_manager_android.cc
new file mode 100644
index 0000000..c594b53
--- /dev/null
+++ b/connection_manager_android.cc
@@ -0,0 +1,42 @@
+//
+// 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/connection_manager_android.h"
+
+namespace chromeos_update_engine {
+
+namespace connection_manager {
+std::unique_ptr<ConnectionManagerInterface> CreateConnectionManager(
+    SystemState* system_state) {
+  return std::unique_ptr<ConnectionManagerInterface>(
+      new ConnectionManagerAndroid());
+}
+}
+
+bool ConnectionManagerAndroid::GetConnectionProperties(
+    ConnectionType* out_type, ConnectionTethering* out_tethering) {
+  return false;
+}
+bool ConnectionManagerAndroid::IsUpdateAllowedOver(
+    ConnectionType type, ConnectionTethering tethering) const {
+  return true;
+}
+bool ConnectionManagerAndroid::IsAllowedConnectionTypesForUpdateSet() const {
+  return false;
+}
+
+
+}  // namespace chromeos_update_engine
diff --git a/connection_manager_android.h b/connection_manager_android.h
new file mode 100644
index 0000000..006f4ea
--- /dev/null
+++ b/connection_manager_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_CONNECTION_MANAGER_ANDROID_H_
+#define UPDATE_ENGINE_CONNECTION_MANAGER_ANDROID_H_
+
+#include <base/macros.h>
+
+#include "update_engine/connection_manager_interface.h"
+
+namespace chromeos_update_engine {
+
+// TODO(senj): Remove this class and use ShillProvider from the UpdateManager.
+class ConnectionManagerAndroid : public ConnectionManagerInterface {
+ public:
+  ConnectionManagerAndroid() = default;
+  ~ConnectionManagerAndroid() override = default;
+
+  // ConnectionManagerInterface overrides.
+  bool GetConnectionProperties(ConnectionType* out_type,
+                               ConnectionTethering* out_tethering) override;
+  bool IsUpdateAllowedOver(ConnectionType type,
+                           ConnectionTethering tethering) const override;
+  bool IsAllowedConnectionTypesForUpdateSet() const override;
+
+  DISALLOW_COPY_AND_ASSIGN(ConnectionManagerAndroid);
+};
+
+}  // namespace chromeos_update_engine
+
+#endif  // UPDATE_ENGINE_CONNECTION_MANAGER_ANDROID_H_
diff --git a/connection_manager_interface.h b/connection_manager_interface.h
index 2181b5d..2faeb80 100644
--- a/connection_manager_interface.h
+++ b/connection_manager_interface.h
@@ -17,25 +17,15 @@
 #ifndef UPDATE_ENGINE_CONNECTION_MANAGER_INTERFACE_H_
 #define UPDATE_ENGINE_CONNECTION_MANAGER_INTERFACE_H_
 
+#include <memory>
+
 #include <base/macros.h>
 
+#include "update_engine/connection_utils.h"
+
 namespace chromeos_update_engine {
 
-enum class NetworkConnectionType {
-  kEthernet,
-  kWifi,
-  kWimax,
-  kBluetooth,
-  kCellular,
-  kUnknown
-};
-
-enum class NetworkTethering {
-  kNotDetected,
-  kSuspected,
-  kConfirmed,
-  kUnknown
-};
+class SystemState;
 
 // This class exposes a generic interface to the connection manager
 // (e.g FlimFlam, Shill, etc.) to consolidate all connection-related
@@ -47,14 +37,14 @@
   // Populates |out_type| with the type of the network connection
   // that we are currently connected and |out_tethering| with the estimate of
   // whether that network is being tethered.
-  virtual bool GetConnectionProperties(NetworkConnectionType* out_type,
-                                       NetworkTethering* out_tethering) = 0;
+  virtual bool GetConnectionProperties(ConnectionType* out_type,
+                                       ConnectionTethering* out_tethering) = 0;
 
   // Returns true if we're allowed to update the system when we're
   // connected to the internet through the given network connection type and the
   // given tethering state.
-  virtual bool IsUpdateAllowedOver(NetworkConnectionType type,
-                                   NetworkTethering tethering) const = 0;
+  virtual bool IsUpdateAllowedOver(ConnectionType type,
+                                   ConnectionTethering tethering) const = 0;
 
   // Returns true if the allowed connection types for update is set in the
   // device policy. Otherwise, returns false.
@@ -67,6 +57,12 @@
   DISALLOW_COPY_AND_ASSIGN(ConnectionManagerInterface);
 };
 
+namespace connection_manager {
+// Factory function which creates a ConnectionManager.
+std::unique_ptr<ConnectionManagerInterface> CreateConnectionManager(
+    SystemState* system_state);
+}
+
 }  // namespace chromeos_update_engine
 
 #endif  // UPDATE_ENGINE_CONNECTION_MANAGER_INTERFACE_H_
diff --git a/connection_manager_unittest.cc b/connection_manager_unittest.cc
index 3e810a7..f814667 100644
--- a/connection_manager_unittest.cc
+++ b/connection_manager_unittest.cc
@@ -34,6 +34,7 @@
 #include "update_engine/fake_shill_proxy.h"
 #include "update_engine/fake_system_state.h"
 
+using chromeos_update_engine::connection_utils::StringForConnectionType;
 using org::chromium::flimflam::ManagerProxyMock;
 using org::chromium::flimflam::ServiceProxyMock;
 using std::set;
@@ -46,6 +47,8 @@
 
 class ConnectionManagerTest : public ::testing::Test {
  public:
+  ConnectionManagerTest() : fake_shill_proxy_(new FakeShillProxy()) {}
+
   void SetUp() override {
     loop_.SetAsCurrent();
     fake_system_state_.set_connection_manager(&cmut_);
@@ -70,22 +73,22 @@
   void TestWithServiceType(
       const char* service_type,
       const char* physical_technology,
-      NetworkConnectionType expected_type);
+      ConnectionType expected_type);
   void TestWithServiceTethering(
       const char* service_tethering,
-      NetworkTethering expected_tethering);
+      ConnectionTethering expected_tethering);
 
   brillo::FakeMessageLoop loop_{nullptr};
   FakeSystemState fake_system_state_;
-  FakeShillProxy fake_shill_proxy_;
+  FakeShillProxy* fake_shill_proxy_;
 
   // ConnectionManager under test.
-  ConnectionManager cmut_{&fake_shill_proxy_, &fake_system_state_};
+  ConnectionManager cmut_{fake_shill_proxy_, &fake_system_state_};
 };
 
 void ConnectionManagerTest::SetManagerReply(const char* default_service,
                                             bool reply_succeeds) {
-  ManagerProxyMock* manager_proxy_mock = fake_shill_proxy_.GetManagerProxy();
+  ManagerProxyMock* manager_proxy_mock = fake_shill_proxy_->GetManagerProxy();
   if (!reply_succeeds) {
     EXPECT_CALL(*manager_proxy_mock, GetProperties(_, _, _))
         .WillOnce(Return(false));
@@ -129,101 +132,95 @@
   EXPECT_CALL(*service_proxy_mock.get(), GetProperties(_, _, _))
       .WillOnce(DoAll(SetArgPointee<0>(reply_dict), Return(true)));
 
-  fake_shill_proxy_.SetServiceForPath(dbus::ObjectPath(service_path),
-                                      std::move(service_proxy_mock));
+  fake_shill_proxy_->SetServiceForPath(dbus::ObjectPath(service_path),
+                                       std::move(service_proxy_mock));
 }
 
 void ConnectionManagerTest::TestWithServiceType(
     const char* service_type,
     const char* physical_technology,
-    NetworkConnectionType expected_type) {
+    ConnectionType expected_type) {
   SetManagerReply("/service/guest/network", true);
   SetServiceReply("/service/guest/network",
                   service_type,
                   physical_technology,
                   shill::kTetheringNotDetectedState);
 
-  NetworkConnectionType type;
-  NetworkTethering tethering;
+  ConnectionType type;
+  ConnectionTethering tethering;
   EXPECT_TRUE(cmut_.GetConnectionProperties(&type, &tethering));
   EXPECT_EQ(expected_type, type);
   testing::Mock::VerifyAndClearExpectations(
-      fake_shill_proxy_.GetManagerProxy());
+      fake_shill_proxy_->GetManagerProxy());
 }
 
 void ConnectionManagerTest::TestWithServiceTethering(
     const char* service_tethering,
-    NetworkTethering expected_tethering) {
+    ConnectionTethering expected_tethering) {
   SetManagerReply("/service/guest/network", true);
   SetServiceReply(
       "/service/guest/network", shill::kTypeWifi, nullptr, service_tethering);
 
-  NetworkConnectionType type;
-  NetworkTethering tethering;
+  ConnectionType type;
+  ConnectionTethering tethering;
   EXPECT_TRUE(cmut_.GetConnectionProperties(&type, &tethering));
   EXPECT_EQ(expected_tethering, tethering);
   testing::Mock::VerifyAndClearExpectations(
-      fake_shill_proxy_.GetManagerProxy());
+      fake_shill_proxy_->GetManagerProxy());
 }
 
 TEST_F(ConnectionManagerTest, SimpleTest) {
-  TestWithServiceType(shill::kTypeEthernet, nullptr,
-                      NetworkConnectionType::kEthernet);
-  TestWithServiceType(shill::kTypeWifi, nullptr,
-                      NetworkConnectionType::kWifi);
-  TestWithServiceType(shill::kTypeWimax, nullptr,
-                      NetworkConnectionType::kWimax);
-  TestWithServiceType(shill::kTypeBluetooth, nullptr,
-                      NetworkConnectionType::kBluetooth);
-  TestWithServiceType(shill::kTypeCellular, nullptr,
-                      NetworkConnectionType::kCellular);
+  TestWithServiceType(shill::kTypeEthernet, nullptr, ConnectionType::kEthernet);
+  TestWithServiceType(shill::kTypeWifi, nullptr, ConnectionType::kWifi);
+  TestWithServiceType(shill::kTypeWimax, nullptr, ConnectionType::kWimax);
+  TestWithServiceType(
+      shill::kTypeBluetooth, nullptr, ConnectionType::kBluetooth);
+  TestWithServiceType(shill::kTypeCellular, nullptr, ConnectionType::kCellular);
 }
 
 TEST_F(ConnectionManagerTest, PhysicalTechnologyTest) {
-  TestWithServiceType(shill::kTypeVPN, nullptr,
-                      NetworkConnectionType::kUnknown);
-  TestWithServiceType(shill::kTypeVPN, shill::kTypeVPN,
-                      NetworkConnectionType::kUnknown);
-  TestWithServiceType(shill::kTypeVPN, shill::kTypeWifi,
-                      NetworkConnectionType::kWifi);
-  TestWithServiceType(shill::kTypeVPN, shill::kTypeWimax,
-                      NetworkConnectionType::kWimax);
+  TestWithServiceType(shill::kTypeVPN, nullptr, ConnectionType::kUnknown);
+  TestWithServiceType(
+      shill::kTypeVPN, shill::kTypeVPN, ConnectionType::kUnknown);
+  TestWithServiceType(shill::kTypeVPN, shill::kTypeWifi, ConnectionType::kWifi);
+  TestWithServiceType(
+      shill::kTypeVPN, shill::kTypeWimax, ConnectionType::kWimax);
 }
 
 TEST_F(ConnectionManagerTest, TetheringTest) {
   TestWithServiceTethering(shill::kTetheringConfirmedState,
-                           NetworkTethering::kConfirmed);
+                           ConnectionTethering::kConfirmed);
   TestWithServiceTethering(shill::kTetheringNotDetectedState,
-                           NetworkTethering::kNotDetected);
+                           ConnectionTethering::kNotDetected);
   TestWithServiceTethering(shill::kTetheringSuspectedState,
-                           NetworkTethering::kSuspected);
+                           ConnectionTethering::kSuspected);
   TestWithServiceTethering("I'm not a valid property value =)",
-                           NetworkTethering::kUnknown);
+                           ConnectionTethering::kUnknown);
 }
 
 TEST_F(ConnectionManagerTest, UnknownTest) {
-  TestWithServiceType("foo", nullptr, NetworkConnectionType::kUnknown);
+  TestWithServiceType("foo", nullptr, ConnectionType::kUnknown);
 }
 
 TEST_F(ConnectionManagerTest, AllowUpdatesOverEthernetTest) {
   // Updates over Ethernet are allowed even if there's no policy.
-  EXPECT_TRUE(cmut_.IsUpdateAllowedOver(NetworkConnectionType::kEthernet,
-                                        NetworkTethering::kUnknown));
+  EXPECT_TRUE(cmut_.IsUpdateAllowedOver(ConnectionType::kEthernet,
+                                        ConnectionTethering::kUnknown));
 }
 
 TEST_F(ConnectionManagerTest, AllowUpdatesOverWifiTest) {
-  EXPECT_TRUE(cmut_.IsUpdateAllowedOver(NetworkConnectionType::kWifi,
-                                        NetworkTethering::kUnknown));
+  EXPECT_TRUE(cmut_.IsUpdateAllowedOver(ConnectionType::kWifi,
+                                        ConnectionTethering::kUnknown));
 }
 
 TEST_F(ConnectionManagerTest, AllowUpdatesOverWimaxTest) {
-  EXPECT_TRUE(cmut_.IsUpdateAllowedOver(NetworkConnectionType::kWimax,
-                                        NetworkTethering::kUnknown));
+  EXPECT_TRUE(cmut_.IsUpdateAllowedOver(ConnectionType::kWimax,
+                                        ConnectionTethering::kUnknown));
 }
 
 TEST_F(ConnectionManagerTest, BlockUpdatesOverBluetoothTest) {
-  EXPECT_FALSE(cmut_.IsUpdateAllowedOver(NetworkConnectionType::kBluetooth,
-                                         NetworkTethering::kUnknown));
+  EXPECT_FALSE(cmut_.IsUpdateAllowedOver(ConnectionType::kBluetooth,
+                                         ConnectionTethering::kUnknown));
 }
 
 TEST_F(ConnectionManagerTest, AllowUpdatesOnlyOver3GPerPolicyTest) {
@@ -233,15 +230,14 @@
 
   // This test tests cellular (3G) being the only connection type being allowed.
   set<string> allowed_set;
-  allowed_set.insert(
-      cmut_.StringForConnectionType(NetworkConnectionType::kCellular));
+  allowed_set.insert(StringForConnectionType(ConnectionType::kCellular));
 
   EXPECT_CALL(allow_3g_policy, GetAllowedConnectionTypesForUpdate(_))
       .Times(1)
       .WillOnce(DoAll(SetArgPointee<0>(allowed_set), Return(true)));
 
-  EXPECT_TRUE(cmut_.IsUpdateAllowedOver(NetworkConnectionType::kCellular,
-                                        NetworkTethering::kUnknown));
+  EXPECT_TRUE(cmut_.IsUpdateAllowedOver(ConnectionType::kCellular,
+                                        ConnectionTethering::kUnknown));
 }
 
 TEST_F(ConnectionManagerTest, AllowUpdatesOver3GAndOtherTypesPerPolicyTest) {
@@ -253,34 +249,32 @@
   // 3G one among them. Only Cellular is currently enforced by the policy
   // setting, the others are ignored (see Bluetooth for example).
   set<string> allowed_set;
-  allowed_set.insert(
-      cmut_.StringForConnectionType(NetworkConnectionType::kCellular));
-  allowed_set.insert(
-      cmut_.StringForConnectionType(NetworkConnectionType::kBluetooth));
+  allowed_set.insert(StringForConnectionType(ConnectionType::kCellular));
+  allowed_set.insert(StringForConnectionType(ConnectionType::kBluetooth));
 
   EXPECT_CALL(allow_3g_policy, GetAllowedConnectionTypesForUpdate(_))
       .Times(3)
       .WillRepeatedly(DoAll(SetArgPointee<0>(allowed_set), Return(true)));
 
-  EXPECT_TRUE(cmut_.IsUpdateAllowedOver(NetworkConnectionType::kEthernet,
-                                        NetworkTethering::kUnknown));
-  EXPECT_TRUE(cmut_.IsUpdateAllowedOver(NetworkConnectionType::kEthernet,
-                                        NetworkTethering::kNotDetected));
-  EXPECT_TRUE(cmut_.IsUpdateAllowedOver(NetworkConnectionType::kCellular,
-                                        NetworkTethering::kUnknown));
-  EXPECT_TRUE(cmut_.IsUpdateAllowedOver(NetworkConnectionType::kWifi,
-                                        NetworkTethering::kUnknown));
-  EXPECT_TRUE(cmut_.IsUpdateAllowedOver(NetworkConnectionType::kWimax,
-                                        NetworkTethering::kUnknown));
-  EXPECT_FALSE(cmut_.IsUpdateAllowedOver(NetworkConnectionType::kBluetooth,
-                                         NetworkTethering::kUnknown));
+  EXPECT_TRUE(cmut_.IsUpdateAllowedOver(ConnectionType::kEthernet,
+                                        ConnectionTethering::kUnknown));
+  EXPECT_TRUE(cmut_.IsUpdateAllowedOver(ConnectionType::kEthernet,
+                                        ConnectionTethering::kNotDetected));
+  EXPECT_TRUE(cmut_.IsUpdateAllowedOver(ConnectionType::kCellular,
+                                        ConnectionTethering::kUnknown));
+  EXPECT_TRUE(cmut_.IsUpdateAllowedOver(ConnectionType::kWifi,
+                                        ConnectionTethering::kUnknown));
+  EXPECT_TRUE(cmut_.IsUpdateAllowedOver(ConnectionType::kWimax,
+                                        ConnectionTethering::kUnknown));
+  EXPECT_FALSE(cmut_.IsUpdateAllowedOver(ConnectionType::kBluetooth,
+                                         ConnectionTethering::kUnknown));
 
   // Tethered networks are treated in the same way as Cellular networks and
   // thus allowed.
-  EXPECT_TRUE(cmut_.IsUpdateAllowedOver(NetworkConnectionType::kEthernet,
-                                        NetworkTethering::kConfirmed));
-  EXPECT_TRUE(cmut_.IsUpdateAllowedOver(NetworkConnectionType::kWifi,
-                                        NetworkTethering::kConfirmed));
+  EXPECT_TRUE(cmut_.IsUpdateAllowedOver(ConnectionType::kEthernet,
+                                        ConnectionTethering::kConfirmed));
+  EXPECT_TRUE(cmut_.IsUpdateAllowedOver(ConnectionType::kWifi,
+                                        ConnectionTethering::kConfirmed));
 }
 
 TEST_F(ConnectionManagerTest, AllowUpdatesOverCellularByDefaultTest) {
@@ -288,8 +282,8 @@
   // Set an empty device policy.
   fake_system_state_.set_device_policy(&device_policy);
 
-  EXPECT_TRUE(cmut_.IsUpdateAllowedOver(NetworkConnectionType::kCellular,
-                                         NetworkTethering::kUnknown));
+  EXPECT_TRUE(cmut_.IsUpdateAllowedOver(ConnectionType::kCellular,
+                                        ConnectionTethering::kUnknown));
 }
 
 TEST_F(ConnectionManagerTest, AllowUpdatesOverTetheredNetworkByDefaultTest) {
@@ -297,12 +291,12 @@
   // Set an empty device policy.
   fake_system_state_.set_device_policy(&device_policy);
 
-  EXPECT_TRUE(cmut_.IsUpdateAllowedOver(NetworkConnectionType::kWifi,
-                                         NetworkTethering::kConfirmed));
-  EXPECT_TRUE(cmut_.IsUpdateAllowedOver(NetworkConnectionType::kEthernet,
-                                         NetworkTethering::kConfirmed));
-  EXPECT_TRUE(cmut_.IsUpdateAllowedOver(NetworkConnectionType::kWifi,
-                                        NetworkTethering::kSuspected));
+  EXPECT_TRUE(cmut_.IsUpdateAllowedOver(ConnectionType::kWifi,
+                                        ConnectionTethering::kConfirmed));
+  EXPECT_TRUE(cmut_.IsUpdateAllowedOver(ConnectionType::kEthernet,
+                                        ConnectionTethering::kConfirmed));
+  EXPECT_TRUE(cmut_.IsUpdateAllowedOver(ConnectionType::kWifi,
+                                        ConnectionTethering::kSuspected));
 }
 
 TEST_F(ConnectionManagerTest, BlockUpdatesOver3GPerPolicyTest) {
@@ -313,19 +307,16 @@
   // Test that updates for 3G are blocked while updates are allowed
   // over several other types.
   set<string> allowed_set;
-  allowed_set.insert(
-      cmut_.StringForConnectionType(NetworkConnectionType::kEthernet));
-  allowed_set.insert(
-      cmut_.StringForConnectionType(NetworkConnectionType::kWifi));
-  allowed_set.insert(
-      cmut_.StringForConnectionType(NetworkConnectionType::kWimax));
+  allowed_set.insert(StringForConnectionType(ConnectionType::kEthernet));
+  allowed_set.insert(StringForConnectionType(ConnectionType::kWifi));
+  allowed_set.insert(StringForConnectionType(ConnectionType::kWimax));
 
   EXPECT_CALL(block_3g_policy, GetAllowedConnectionTypesForUpdate(_))
       .Times(1)
       .WillOnce(DoAll(SetArgPointee<0>(allowed_set), Return(true)));
 
-  EXPECT_FALSE(cmut_.IsUpdateAllowedOver(NetworkConnectionType::kCellular,
-                                         NetworkTethering::kUnknown));
+  EXPECT_FALSE(cmut_.IsUpdateAllowedOver(ConnectionType::kCellular,
+                                         ConnectionTethering::kUnknown));
 }
 
 TEST_F(ConnectionManagerTest, AllowUpdatesOver3GIfPolicyIsNotSet) {
@@ -340,34 +331,31 @@
       .Times(1)
       .WillOnce(Return(false));
 
-  EXPECT_TRUE(cmut_.IsUpdateAllowedOver(NetworkConnectionType::kCellular,
-                                         NetworkTethering::kUnknown));
+  EXPECT_TRUE(cmut_.IsUpdateAllowedOver(ConnectionType::kCellular,
+                                        ConnectionTethering::kUnknown));
 }
 
 TEST_F(ConnectionManagerTest, StringForConnectionTypeTest) {
   EXPECT_STREQ(shill::kTypeEthernet,
-               cmut_.StringForConnectionType(NetworkConnectionType::kEthernet));
+               StringForConnectionType(ConnectionType::kEthernet));
   EXPECT_STREQ(shill::kTypeWifi,
-               cmut_.StringForConnectionType(NetworkConnectionType::kWifi));
+               StringForConnectionType(ConnectionType::kWifi));
   EXPECT_STREQ(shill::kTypeWimax,
-               cmut_.StringForConnectionType(NetworkConnectionType::kWimax));
+               StringForConnectionType(ConnectionType::kWimax));
   EXPECT_STREQ(shill::kTypeBluetooth,
-               cmut_.StringForConnectionType(
-                   NetworkConnectionType::kBluetooth));
+               StringForConnectionType(ConnectionType::kBluetooth));
   EXPECT_STREQ(shill::kTypeCellular,
-               cmut_.StringForConnectionType(NetworkConnectionType::kCellular));
+               StringForConnectionType(ConnectionType::kCellular));
+  EXPECT_STREQ("Unknown", StringForConnectionType(ConnectionType::kUnknown));
   EXPECT_STREQ("Unknown",
-               cmut_.StringForConnectionType(NetworkConnectionType::kUnknown));
-  EXPECT_STREQ("Unknown",
-               cmut_.StringForConnectionType(
-                   static_cast<NetworkConnectionType>(999999)));
+               StringForConnectionType(static_cast<ConnectionType>(999999)));
 }
 
 TEST_F(ConnectionManagerTest, MalformedServiceList) {
   SetManagerReply("/service/guest/network", false);
 
-  NetworkConnectionType type;
-  NetworkTethering tethering;
+  ConnectionType type;
+  ConnectionTethering tethering;
   EXPECT_FALSE(cmut_.GetConnectionProperties(&type, &tethering));
 }
 
diff --git a/connection_utils.cc b/connection_utils.cc
new file mode 100644
index 0000000..9b6b526
--- /dev/null
+++ b/connection_utils.cc
@@ -0,0 +1,70 @@
+//
+// 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/connection_utils.h"
+
+#include <shill/dbus-constants.h>
+
+namespace chromeos_update_engine {
+namespace connection_utils {
+
+ConnectionType ParseConnectionType(const std::string& type_str) {
+  if (type_str == shill::kTypeEthernet) {
+    return ConnectionType::kEthernet;
+  } else if (type_str == shill::kTypeWifi) {
+    return ConnectionType::kWifi;
+  } else if (type_str == shill::kTypeWimax) {
+    return ConnectionType::kWimax;
+  } else if (type_str == shill::kTypeBluetooth) {
+    return ConnectionType::kBluetooth;
+  } else if (type_str == shill::kTypeCellular) {
+    return ConnectionType::kCellular;
+  }
+  return ConnectionType::kUnknown;
+}
+
+ConnectionTethering ParseConnectionTethering(const std::string& tethering_str) {
+  if (tethering_str == shill::kTetheringNotDetectedState) {
+    return ConnectionTethering::kNotDetected;
+  } else if (tethering_str == shill::kTetheringSuspectedState) {
+    return ConnectionTethering::kSuspected;
+  } else if (tethering_str == shill::kTetheringConfirmedState) {
+    return ConnectionTethering::kConfirmed;
+  }
+  return ConnectionTethering::kUnknown;
+}
+
+const char* StringForConnectionType(ConnectionType type) {
+  switch (type) {
+    case ConnectionType::kEthernet:
+      return shill::kTypeEthernet;
+    case ConnectionType::kWifi:
+      return shill::kTypeWifi;
+    case ConnectionType::kWimax:
+      return shill::kTypeWimax;
+    case ConnectionType::kBluetooth:
+      return shill::kTypeBluetooth;
+    case ConnectionType::kCellular:
+      return shill::kTypeCellular;
+    case ConnectionType::kUnknown:
+      return "Unknown";
+  }
+  return "Unknown";
+}
+
+}  // namespace connection_utils
+
+}  // namespace chromeos_update_engine
diff --git a/connection_utils.h b/connection_utils.h
new file mode 100644
index 0000000..e385517
--- /dev/null
+++ b/connection_utils.h
@@ -0,0 +1,51 @@
+//
+// 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_CONNECTION_UTILS_H_
+#define UPDATE_ENGINE_CONNECTION_UTILS_H_
+
+#include <string>
+
+namespace chromeos_update_engine {
+
+enum class ConnectionType {
+  kEthernet,
+  kWifi,
+  kWimax,
+  kBluetooth,
+  kCellular,
+  kUnknown
+};
+
+enum class ConnectionTethering {
+  kNotDetected,
+  kSuspected,
+  kConfirmed,
+  kUnknown,
+};
+
+namespace connection_utils {
+// Helper methods for converting shill strings into symbolic values.
+ConnectionType ParseConnectionType(const std::string& type_str);
+ConnectionTethering ParseConnectionTethering(const std::string& tethering_str);
+
+// Returns the string representation corresponding to the given connection type.
+const char* StringForConnectionType(ConnectionType type);
+}  // namespace connection_utils
+
+}  // namespace chromeos_update_engine
+
+#endif  // UPDATE_ENGINE_CONNECTION_UTILS_H_
diff --git a/daemon.cc b/daemon.cc
index 4c0c52f..f016fec 100644
--- a/daemon.cc
+++ b/daemon.cc
@@ -20,22 +20,15 @@
 
 #include <base/bind.h>
 #include <base/location.h>
-#include <base/time/time.h>
-#if USE_WEAVE || USE_BINDER
+#if USE_BINDER
 #include <binderwrapper/binder_wrapper.h>
-#endif  // USE_WEAVE || USE_BINDER
+#endif  // USE_BINDER
 
-#if defined(__BRILLO__) || defined(__CHROMEOS__)
+#if USE_OMAHA
 #include "update_engine/real_system_state.h"
-#else  // !(defined(__BRILLO__) || defined(__CHROMEOS__))
+#else  // !USE_OMAHA
 #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_OMAHA
 
 namespace chromeos_update_engine {
 
@@ -48,51 +41,35 @@
   if (exit_code != EX_OK)
     return exit_code;
 
-#if USE_WEAVE || USE_BINDER
+#if USE_BINDER
   android::BinderWrapper::Create();
   binder_watcher_.Init();
-#endif  // USE_WEAVE || USE_BINDER
+#endif  // USE_BINDER
 
-#if USE_DBUS
-  // We wait for the D-Bus connection for up two minutes to avoid re-spawning
-  // the daemon too fast causing thrashing if dbus-daemon is not running.
-  scoped_refptr<dbus::Bus> bus = dbus_connection_.ConnectWithTimeout(
-      base::TimeDelta::FromSeconds(kDBusSystemMaxWaitSeconds));
-
-  if (!bus) {
-    // TODO(deymo): Make it possible to run update_engine even if dbus-daemon
-    // is not running or constantly crashing.
-    LOG(ERROR) << "Failed to initialize DBus, aborting.";
-    return 1;
-  }
-
-  CHECK(bus->SetUpAsyncOperations());
-#endif  // USE_DBUS
-
-#if defined(__BRILLO__) || defined(__CHROMEOS__)
+#if USE_OMAHA
   // Initialize update engine global state but continue if something fails.
   // 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);
+  RealSystemState* real_system_state = new RealSystemState();
   daemon_state_.reset(real_system_state);
   LOG_IF(ERROR, !real_system_state->Initialize())
       << "Failed to initialize system state.";
-#else  // !(defined(__BRILLO__) || defined(__CHROMEOS__))
+#else  // !USE_OMAHA
   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__)
+#endif  // USE_OMAHA
 
 #if USE_BINDER
   // Create the Binder Service.
-#if defined(__BRILLO__) || defined(__CHROMEOS__)
+#if USE_OMAHA
   binder_service_ = new BinderUpdateEngineBrilloService{real_system_state};
-#else  // !(defined(__BRILLO__) || defined(__CHROMEOS__))
+#else  // !USE_OMAHA
   binder_service_ = new BinderUpdateEngineAndroidService{
       daemon_state_android->service_delegate()};
-#endif  // defined(__BRILLO__) || defined(__CHROMEOS__)
+#endif  // USE_OMAHA
   auto binder_wrapper = android::BinderWrapper::Get();
   if (!binder_wrapper->RegisterService(binder_service_->ServiceName(),
                                        binder_service_)) {
@@ -104,7 +81,7 @@
 
 #if USE_DBUS
   // Create the DBus service.
-  dbus_adaptor_.reset(new UpdateEngineAdaptor(real_system_state, bus));
+  dbus_adaptor_.reset(new UpdateEngineAdaptor(real_system_state));
   daemon_state_->AddObserver(dbus_adaptor_.get());
 
   dbus_adaptor_->RegisterAsync(base::Bind(&UpdateEngineDaemon::OnDBusRegistered,
diff --git a/daemon.h b/daemon.h
index 8323e56..c10bb28 100644
--- a/daemon.h
+++ b/daemon.h
@@ -20,20 +20,17 @@
 #include <memory>
 #include <string>
 
-#if USE_WEAVE || USE_BINDER
+#if USE_BINDER
 #include <brillo/binder_watcher.h>
-#endif  // USE_WEAVE || USE_BINDER
+#endif  // USE_BINDER
 #include <brillo/daemons/daemon.h>
-#if USE_DBUS
-#include <brillo/dbus/dbus_connection.h>
-#endif  // USE_DBUS
 
 #if USE_BINDER
-#if defined(__BRILLO__) || defined(__CHROMEOS__)
+#if USE_OMAHA
 #include "update_engine/binder_service_brillo.h"
-#else  // !(defined(__BRILLO__) || defined(__CHROMEOS__))
+#else  // !USE_OMAHA
 #include "update_engine/binder_service_android.h"
-#endif  // defined(__BRILLO__) || defined(__CHROMEOS__)
+#endif  // USE_OMAHA
 #endif  // USE_BINDER
 #include "update_engine/common/subprocess.h"
 #include "update_engine/daemon_state_interface.h"
@@ -57,8 +54,7 @@
   // initialization.
   void OnDBusRegistered(bool succeeded);
 
-  // Main D-Bus connection and service adaptor.
-  brillo::DBusConnection dbus_connection_;
+  // Main D-Bus service adaptor.
   std::unique_ptr<UpdateEngineAdaptor> dbus_adaptor_;
 #endif  // USE_DBUS
 
@@ -67,16 +63,16 @@
   // the main() function.
   Subprocess subprocess_;
 
-#if USE_WEAVE || USE_BINDER
+#if USE_BINDER
   brillo::BinderWatcher binder_watcher_;
-#endif  // USE_WEAVE || USE_BINDER
+#endif  // USE_BINDER
 
 #if USE_BINDER
-#if defined(__BRILLO__) || defined(__CHROMEOS__)
+#if USE_OMAHA
   android::sp<BinderUpdateEngineBrilloService> binder_service_;
-#else  // !(defined(__BRILLO__) || defined(__CHROMEOS__))
+#else  // !USE_OMAHA
   android::sp<BinderUpdateEngineAndroidService> binder_service_;
-#endif  // defined(__BRILLO__) || defined(__CHROMEOS__)
+#endif  // USE_OMAHA
 #endif  // USE_BINDER
 
   // The daemon state with all the required daemon classes for the configured
diff --git a/daemon_state_android.cc b/daemon_state_android.cc
index cf1e892..0960b1a 100644
--- a/daemon_state_android.cc
+++ b/daemon_state_android.cc
@@ -58,6 +58,11 @@
     return false;
   }
 
+  // The CertificateChecker singleton is used by the update attempter.
+  certificate_checker_.reset(
+      new CertificateChecker(prefs_.get(), &openssl_wrapper_));
+  certificate_checker_->Init();
+
   // Initialize the UpdateAttempter before the UpdateManager.
   update_attempter_.reset(new UpdateAttempterAndroid(
       this, prefs_.get(), boot_control_.get(), hardware_.get()));
diff --git a/daemon_state_android.h b/daemon_state_android.h
index 5db3ef0..928a14e 100644
--- a/daemon_state_android.h
+++ b/daemon_state_android.h
@@ -20,8 +20,8 @@
 #include <memory>
 #include <set>
 
+#include "update_engine/certificate_checker.h"
 #include "update_engine/common/boot_control_interface.h"
-#include "update_engine/common/certificate_checker.h"
 #include "update_engine/common/hardware_interface.h"
 #include "update_engine/common/prefs_interface.h"
 #include "update_engine/daemon_state_interface.h"
@@ -43,7 +43,7 @@
   void AddObserver(ServiceObserverInterface* observer) override;
   void RemoveObserver(ServiceObserverInterface* observer) override;
 
-  const std::set<ServiceObserverInterface*>& service_observers() {
+  const std::set<ServiceObserverInterface*>& service_observers() override {
     return service_observers_;
   }
 
@@ -64,6 +64,11 @@
 
   // The main class handling the updates.
   std::unique_ptr<UpdateAttempterAndroid> update_attempter_;
+
+  // OpenSSLWrapper and CertificateChecker used for checking changes in SSL
+  // certificates.
+  OpenSSLWrapper openssl_wrapper_;
+  std::unique_ptr<CertificateChecker> certificate_checker_;
 };
 
 }  // namespace chromeos_update_engine
diff --git a/daemon_state_interface.h b/daemon_state_interface.h
index a0944aa..2356816 100644
--- a/daemon_state_interface.h
+++ b/daemon_state_interface.h
@@ -20,6 +20,7 @@
 #include "update_engine/service_observer_interface.h"
 
 #include <memory>
+#include <set>
 
 namespace chromeos_update_engine {
 
@@ -36,6 +37,9 @@
   virtual void AddObserver(ServiceObserverInterface* observer) = 0;
   virtual void RemoveObserver(ServiceObserverInterface* observer) = 0;
 
+  // Return the set of current observers.
+  virtual const std::set<ServiceObserverInterface*>& service_observers() = 0;
+
  protected:
   DaemonStateInterface() = default;
 };
diff --git a/dbus_connection.cc b/dbus_connection.cc
new file mode 100644
index 0000000..cf17ec9
--- /dev/null
+++ b/dbus_connection.cc
@@ -0,0 +1,55 @@
+//
+// 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/dbus_connection.h"
+
+#include <base/time/time.h>
+
+namespace chromeos_update_engine {
+
+namespace {
+const int kDBusSystemMaxWaitSeconds = 2 * 60;
+
+DBusConnection* dbus_connection_singleton = nullptr;
+}  // namespace
+
+DBusConnection::DBusConnection() {
+  // We wait for the D-Bus connection for up two minutes to avoid re-spawning
+  // the daemon too fast causing thrashing if dbus-daemon is not running.
+  bus_ = dbus_connection_.ConnectWithTimeout(
+      base::TimeDelta::FromSeconds(kDBusSystemMaxWaitSeconds));
+
+  if (!bus_) {
+    // TODO(deymo): Make it possible to run update_engine even if dbus-daemon
+    // is not running or constantly crashing.
+    LOG(FATAL) << "Failed to initialize DBus, aborting.";
+  }
+
+  CHECK(bus_->SetUpAsyncOperations());
+}
+
+const scoped_refptr<dbus::Bus>& DBusConnection::GetDBus() {
+  CHECK(bus_);
+  return bus_;
+}
+
+DBusConnection* DBusConnection::Get() {
+  if (!dbus_connection_singleton)
+    dbus_connection_singleton = new DBusConnection();
+  return dbus_connection_singleton;
+}
+
+}  // namespace chromeos_update_engine
diff --git a/dbus_connection.h b/dbus_connection.h
new file mode 100644
index 0000000..c3205ba
--- /dev/null
+++ b/dbus_connection.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_DBUS_CONNECTION_H_
+#define UPDATE_ENGINE_DBUS_CONNECTION_H_
+
+#include <base/memory/ref_counted.h>
+#include <brillo/dbus/dbus_connection.h>
+#include <dbus/bus.h>
+
+namespace chromeos_update_engine {
+
+class DBusConnection {
+ public:
+  DBusConnection();
+
+  const scoped_refptr<dbus::Bus>& GetDBus();
+
+  static DBusConnection* Get();
+
+ private:
+  scoped_refptr<dbus::Bus> bus_;
+
+  brillo::DBusConnection dbus_connection_;
+
+  DISALLOW_COPY_AND_ASSIGN(DBusConnection);
+};
+
+}  // namespace chromeos_update_engine
+
+#endif  // UPDATE_ENGINE_DBUS_CONNECTION_H_
diff --git a/dbus_service.cc b/dbus_service.cc
index e64481b..731d489 100644
--- a/dbus_service.cc
+++ b/dbus_service.cc
@@ -17,6 +17,7 @@
 #include "update_engine/dbus_service.h"
 
 #include "update_engine/dbus-constants.h"
+#include "update_engine/dbus_connection.h"
 #include "update_engine/update_status_utils.h"
 
 namespace chromeos_update_engine {
@@ -160,14 +161,13 @@
   return common_->GetEolStatus(error, out_eol_status);
 }
 
-UpdateEngineAdaptor::UpdateEngineAdaptor(SystemState* system_state,
-                                         const scoped_refptr<dbus::Bus>& bus)
+UpdateEngineAdaptor::UpdateEngineAdaptor(SystemState* system_state)
     : org::chromium::UpdateEngineInterfaceAdaptor(&dbus_service_),
-    bus_(bus),
-    dbus_service_(system_state),
-    dbus_object_(nullptr,
-                 bus,
-                 dbus::ObjectPath(update_engine::kUpdateEngineServicePath)) {}
+      bus_(DBusConnection::Get()->GetDBus()),
+      dbus_service_(system_state),
+      dbus_object_(nullptr,
+                   bus_,
+                   dbus::ObjectPath(update_engine::kUpdateEngineServicePath)) {}
 
 void UpdateEngineAdaptor::RegisterAsync(
     const base::Callback<void(bool)>& completion_callback) {
diff --git a/dbus_service.h b/dbus_service.h
index efad821..644dcee 100644
--- a/dbus_service.h
+++ b/dbus_service.h
@@ -160,8 +160,7 @@
 class UpdateEngineAdaptor : public org::chromium::UpdateEngineInterfaceAdaptor,
                             public ServiceObserverInterface {
  public:
-  UpdateEngineAdaptor(SystemState* system_state,
-                      const scoped_refptr<dbus::Bus>& bus);
+  UpdateEngineAdaptor(SystemState* system_state);
   ~UpdateEngineAdaptor() = default;
 
   // Register the DBus object with the update engine service asynchronously.
@@ -182,9 +181,6 @@
 
   void SendPayloadApplicationComplete(ErrorCode error_code) 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/fake_system_state.cc b/fake_system_state.cc
index 49ba058..d51f775 100644
--- a/fake_system_state.cc
+++ b/fake_system_state.cc
@@ -21,7 +21,7 @@
 // Mock the SystemStateInterface so that we could lie that
 // OOBE is completed even when there's no such marker file, etc.
 FakeSystemState::FakeSystemState()
-    : mock_update_attempter_(this, nullptr, nullptr, nullptr),
+    : mock_update_attempter_(this, nullptr, nullptr),
       mock_request_params_(this),
       fake_update_manager_(&fake_clock_),
       clock_(&fake_clock_),
diff --git a/fake_system_state.h b/fake_system_state.h
index 12d9239..2225933 100644
--- a/fake_system_state.h
+++ b/fake_system_state.h
@@ -20,8 +20,6 @@
 #include <base/logging.h>
 #include <gmock/gmock.h>
 #include <policy/mock_device_policy.h>
-#include <power_manager/dbus-proxies.h>
-#include <power_manager/dbus-proxy-mocks.h>
 
 #include "metrics/metrics_library_mock.h"
 #include "update_engine/common/fake_boot_control.h"
@@ -32,6 +30,7 @@
 #include "update_engine/mock_omaha_request_params.h"
 #include "update_engine/mock_p2p_manager.h"
 #include "update_engine/mock_payload_state.h"
+#include "update_engine/mock_power_manager.h"
 #include "update_engine/mock_update_attempter.h"
 #include "update_engine/system_state.h"
 #include "update_engine/update_manager/fake_update_manager.h"
@@ -85,8 +84,6 @@
     return update_attempter_;
   }
 
-  inline WeaveServiceInterface* weave_service() override { return nullptr; }
-
   inline OmahaRequestParams* request_params() override {
     return request_params_;
   }
@@ -97,9 +94,8 @@
     return update_manager_;
   }
 
-  inline org::chromium::PowerManagerProxyInterface* power_manager_proxy()
-      override {
-    return power_manager_proxy_;
+  inline PowerManagerInterface* power_manager() override {
+    return power_manager_;
   }
 
   inline bool system_rebooted() override { return fake_system_rebooted_; }
@@ -245,7 +241,7 @@
   testing::NiceMock<MockOmahaRequestParams> mock_request_params_;
   testing::NiceMock<MockP2PManager> mock_p2p_manager_;
   chromeos_update_manager::FakeUpdateManager fake_update_manager_;
-  org::chromium::PowerManagerProxyMock mock_power_manager_;
+  testing::NiceMock<MockPowerManager> mock_power_manager_;
 
   // Pointers to objects that client code can override. They are initialized to
   // the default implementations above.
@@ -261,8 +257,7 @@
   OmahaRequestParams* request_params_;
   P2PManager* p2p_manager_;
   chromeos_update_manager::UpdateManager* update_manager_;
-  org::chromium::PowerManagerProxyInterface* power_manager_proxy_{
-      &mock_power_manager_};
+  PowerManagerInterface* power_manager_{&mock_power_manager_};
 
   // Other object pointers (not preinitialized).
   const policy::DevicePolicy* device_policy_;
diff --git a/hardware_android.cc b/hardware_android.cc
index 60e26f2..91c3fbe 100644
--- a/hardware_android.cc
+++ b/hardware_android.cc
@@ -16,17 +16,81 @@
 
 #include "update_engine/hardware_android.h"
 
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <algorithm>
+
+#include <bootloader.h>
+
 #include <base/files/file_util.h>
+#include <base/strings/stringprintf.h>
 #include <brillo/make_unique_ptr.h>
 #include <cutils/properties.h>
 
 #include "update_engine/common/hardware.h"
 #include "update_engine/common/platform_constants.h"
+#include "update_engine/common/utils.h"
+#include "update_engine/utils_android.h"
 
 using std::string;
 
 namespace chromeos_update_engine {
 
+namespace {
+
+// The powerwash arguments passed to recovery. Arguments are separated by \n.
+const char kAndroidRecoveryPowerwashCommand[] =
+    "recovery\n"
+    "--wipe_data\n"
+    "--reason=wipe_data_from_ota\n";
+
+// Android properties that identify the hardware and potentially non-updatable
+// parts of the bootloader (such as the bootloader version and the baseband
+// version).
+const char kPropBootBootloader[] = "ro.boot.bootloader";
+const char kPropBootBaseband[] = "ro.boot.baseband";
+const char kPropProductManufacturer[] = "ro.product.manufacturer";
+const char kPropBootHardwareSKU[] = "ro.boot.hardware.sku";
+const char kPropBootRevision[] = "ro.boot.revision";
+
+// Write a recovery command line |message| to the BCB. The arguments to recovery
+// must be separated by '\n'. An empty string will erase the BCB.
+bool WriteBootloaderRecoveryMessage(const string& message) {
+  base::FilePath misc_device;
+  if (!utils::DeviceForMountPoint("/misc", &misc_device))
+    return false;
+
+  // Setup a bootloader_message with just the command and recovery fields set.
+  bootloader_message boot = {};
+  if (!message.empty()) {
+    strncpy(boot.command, "boot-recovery", sizeof(boot.command) - 1);
+    memcpy(boot.recovery,
+           message.data(),
+           std::min(message.size(), sizeof(boot.recovery) - 1));
+  }
+
+  int fd =
+      HANDLE_EINTR(open(misc_device.value().c_str(), O_WRONLY | O_SYNC, 0600));
+  if (fd < 0) {
+    PLOG(ERROR) << "Opening misc";
+    return false;
+  }
+  ScopedFdCloser fd_closer(&fd);
+  // We only re-write the first part of the bootloader_message, up to and
+  // including the recovery message.
+  size_t boot_size =
+      offsetof(bootloader_message, recovery) + sizeof(boot.recovery);
+  if (!utils::WriteAll(fd, &boot, boot_size)) {
+    PLOG(ERROR) << "Writing recovery command to misc";
+    return false;
+  }
+  return true;
+}
+
+}  // namespace
+
 namespace hardware {
 
 // Factory defined in hardware.h.
@@ -68,6 +132,10 @@
   return property_get_bool("ro.debuggable", 0) != 1;
 }
 
+bool HardwareAndroid::AreDevFeaturesEnabled() const {
+  return !IsNormalBootMode();
+}
+
 bool HardwareAndroid::IsOOBEEnabled() const {
   // No OOBE flow blocking updates for Android-based boards.
   return false;
@@ -81,18 +149,26 @@
 }
 
 string HardwareAndroid::GetHardwareClass() const {
-  LOG(WARNING) << "STUB: GetHardwareClass().";
-  return "ANDROID";
+  char manufacturer[PROPERTY_VALUE_MAX];
+  char sku[PROPERTY_VALUE_MAX];
+  char revision[PROPERTY_VALUE_MAX];
+  property_get(kPropBootHardwareSKU, sku, "");
+  property_get(kPropProductManufacturer, manufacturer, "");
+  property_get(kPropBootRevision, revision, "");
+
+  return base::StringPrintf("%s:%s:%s", manufacturer, sku, revision);
 }
 
 string HardwareAndroid::GetFirmwareVersion() const {
-  LOG(WARNING) << "STUB: GetFirmwareVersion().";
-  return "0";
+  char bootloader[PROPERTY_VALUE_MAX];
+  property_get(kPropBootBootloader, bootloader, "");
+  return bootloader;
 }
 
 string HardwareAndroid::GetECVersion() const {
-  LOG(WARNING) << "STUB: GetECVersion().";
-  return "0";
+  char baseband[PROPERTY_VALUE_MAX];
+  property_get(kPropBootBaseband, baseband, "");
+  return baseband;
 }
 
 int HardwareAndroid::GetPowerwashCount() const {
@@ -100,6 +176,15 @@
   return 0;
 }
 
+bool HardwareAndroid::SchedulePowerwash() {
+  LOG(INFO) << "Scheduling a powerwash to BCB.";
+  return WriteBootloaderRecoveryMessage(kAndroidRecoveryPowerwashCommand);
+}
+
+bool HardwareAndroid::CancelPowerwash() {
+  return WriteBootloaderRecoveryMessage("");
+}
+
 bool HardwareAndroid::GetNonVolatileDirectory(base::FilePath* path) const {
   base::FilePath local_path(constants::kNonVolatileDirectory);
   if (!base::PathExists(local_path)) {
diff --git a/hardware_android.h b/hardware_android.h
index 9aa729c..78af871 100644
--- a/hardware_android.h
+++ b/hardware_android.h
@@ -36,12 +36,15 @@
   // HardwareInterface methods.
   bool IsOfficialBuild() const override;
   bool IsNormalBootMode() const override;
+  bool AreDevFeaturesEnabled() const override;
   bool IsOOBEEnabled() const override;
   bool IsOOBEComplete(base::Time* out_time_of_oobe) const override;
   std::string GetHardwareClass() const override;
   std::string GetFirmwareVersion() const override;
   std::string GetECVersion() const override;
   int GetPowerwashCount() const override;
+  bool SchedulePowerwash() override;
+  bool CancelPowerwash() override;
   bool GetNonVolatileDirectory(base::FilePath* path) const override;
   bool GetPowerwashSafeDirectory(base::FilePath* path) const override;
 
diff --git a/hardware_chromeos.cc b/hardware_chromeos.cc
index 57583a1..4b0b82f 100644
--- a/hardware_chromeos.cc
+++ b/hardware_chromeos.cc
@@ -23,6 +23,7 @@
 #include <base/strings/string_util.h>
 #include <brillo/key_value_store.h>
 #include <brillo/make_unique_ptr.h>
+#include <debugd/dbus-constants.h>
 #include <vboot/crossystem.h>
 
 extern "C" {
@@ -35,6 +36,7 @@
 #include "update_engine/common/platform_constants.h"
 #include "update_engine/common/subprocess.h"
 #include "update_engine/common/utils.h"
+#include "update_engine/dbus_connection.h"
 
 using std::string;
 using std::vector;
@@ -53,6 +55,14 @@
 // a powerwash is performed.
 const char kPowerwashCountMarker[] = "powerwash_count";
 
+// The name of the marker file used to trigger powerwash when post-install
+// completes successfully so that the device is powerwashed on next reboot.
+const char kPowerwashMarkerFile[] =
+    "/mnt/stateful_partition/factory_install_reset";
+
+// The contents of the powerwash marker file.
+const char kPowerwashCommand[] = "safe fast keepimg reason=update_engine\n";
+
 // UpdateManager config path.
 const char* kConfigFilePath = "/etc/update_manager.conf";
 
@@ -76,6 +86,8 @@
 
 void HardwareChromeOS::Init() {
   LoadConfig("" /* root_prefix */, IsNormalBootMode());
+  debugd_proxy_.reset(
+      new org::chromium::debugdProxy(DBusConnection::Get()->GetDBus()));
 }
 
 bool HardwareChromeOS::IsOfficialBuild() const {
@@ -87,6 +99,24 @@
   return !dev_mode;
 }
 
+bool HardwareChromeOS::AreDevFeaturesEnabled() const {
+  // Even though the debugd tools are also gated on devmode, checking here can
+  // save us a D-Bus call so it's worth doing explicitly.
+  if (IsNormalBootMode())
+    return false;
+
+  int32_t dev_features = debugd::DEV_FEATURES_DISABLED;
+  brillo::ErrorPtr error;
+  // Some boards may not include debugd so it's expected that this may fail,
+  // in which case we treat it as disabled.
+  if (debugd_proxy_ && debugd_proxy_->QueryDevFeatures(&dev_features, &error) &&
+      !(dev_features & debugd::DEV_FEATURES_DISABLED)) {
+    LOG(INFO) << "Debugd dev tools enabled.";
+    return true;
+  }
+  return false;
+}
+
 bool HardwareChromeOS::IsOOBEEnabled() const {
   return is_oobe_enabled_;
 }
@@ -162,6 +192,34 @@
   return powerwash_count;
 }
 
+bool HardwareChromeOS::SchedulePowerwash() {
+  bool result = utils::WriteFile(
+      kPowerwashMarkerFile, kPowerwashCommand, strlen(kPowerwashCommand));
+  if (result) {
+    LOG(INFO) << "Created " << kPowerwashMarkerFile
+              << " to powerwash on next reboot";
+  } else {
+    PLOG(ERROR) << "Error in creating powerwash marker file: "
+                << kPowerwashMarkerFile;
+  }
+
+  return result;
+}
+
+bool HardwareChromeOS::CancelPowerwash() {
+  bool result = base::DeleteFile(base::FilePath(kPowerwashMarkerFile), false);
+
+  if (result) {
+    LOG(INFO) << "Successfully deleted the powerwash marker file : "
+              << kPowerwashMarkerFile;
+  } else {
+    PLOG(ERROR) << "Could not delete the powerwash marker file : "
+                << kPowerwashMarkerFile;
+  }
+
+  return result;
+}
+
 bool HardwareChromeOS::GetNonVolatileDirectory(base::FilePath* path) const {
   *path = base::FilePath(constants::kNonVolatileDirectory);
   return true;
diff --git a/hardware_chromeos.h b/hardware_chromeos.h
index d9a73f8..03ad750 100644
--- a/hardware_chromeos.h
+++ b/hardware_chromeos.h
@@ -22,6 +22,7 @@
 
 #include <base/macros.h>
 #include <base/time/time.h>
+#include <debugd/dbus-proxies.h>
 
 #include "update_engine/common/hardware_interface.h"
 
@@ -39,12 +40,15 @@
   // HardwareInterface methods.
   bool IsOfficialBuild() const override;
   bool IsNormalBootMode() const override;
+  bool AreDevFeaturesEnabled() const override;
   bool IsOOBEEnabled() const override;
   bool IsOOBEComplete(base::Time* out_time_of_oobe) const override;
   std::string GetHardwareClass() const override;
   std::string GetFirmwareVersion() const override;
   std::string GetECVersion() const override;
   int GetPowerwashCount() const override;
+  bool SchedulePowerwash() override;
+  bool CancelPowerwash() override;
   bool GetNonVolatileDirectory(base::FilePath* path) const override;
   bool GetPowerwashSafeDirectory(base::FilePath* path) const override;
 
@@ -58,6 +62,8 @@
 
   bool is_oobe_enabled_;
 
+  std::unique_ptr<org::chromium::debugdProxyInterface> debugd_proxy_;
+
   DISALLOW_COPY_AND_ASSIGN(HardwareChromeOS);
 };
 
diff --git a/image_properties.h b/image_properties.h
index 6026c2e..ba6ce44 100644
--- a/image_properties.h
+++ b/image_properties.h
@@ -37,6 +37,10 @@
   // The product version of this image.
   std::string version;
 
+  // A unique string that identifies this build. Normally a combination of the
+  // the version, signing keys and build target.
+  std::string build_fingerprint;
+
   // The board name this image was built for.
   std::string board;
 
diff --git a/image_properties_android.cc b/image_properties_android.cc
index 00822da..e3b7616 100644
--- a/image_properties_android.cc
+++ b/image_properties_android.cc
@@ -20,6 +20,7 @@
 
 #include <base/logging.h>
 #include <brillo/osrelease_reader.h>
+#include <cutils/properties.h>
 
 #include "update_engine/common/boot_control_interface.h"
 #include "update_engine/common/constants.h"
@@ -34,11 +35,16 @@
 // Build time properties name used in Brillo.
 const char kProductId[] = "product_id";
 const char kProductVersion[] = "product_version";
+const char kSystemVersion[] = "system_version";
 
 // Prefs used to store the target channel and powerwash settings.
 const char kPrefsImgPropChannelName[] = "img-prop-channel-name";
 const char kPrefsImgPropPowerwashAllowed[] = "img-prop-powerwash-allowed";
 
+// System properties that identifies the "board".
+const char kPropProductName[] = "ro.product.name";
+const char kPropBuildFingerprint[] = "ro.build.fingerprint";
+
 std::string GetStringWithDefault(const brillo::OsReleaseReader& osrelease,
                                  const std::string& key,
                                  const std::string& default_value) {
@@ -64,9 +70,18 @@
   result.product_id = GetStringWithDefault(
       osrelease, kProductId, "developer-boards:brillo-starter-board");
   result.canary_product_id = result.product_id;
-  result.version = GetStringWithDefault(osrelease, kProductVersion, "0.0.0.0");
+  std::string system_version =
+      GetStringWithDefault(osrelease, kSystemVersion, "0.0.0");
+  std::string product_version =
+      GetStringWithDefault(osrelease, kProductVersion, "0");
+  result.version = system_version + "." + product_version;
 
-  result.board = "brillo";
+  char prop[PROPERTY_VALUE_MAX];
+  property_get(kPropProductName, prop, "brillo");
+  result.board = prop;
+
+  property_get(kPropBuildFingerprint, prop, "none");
+  result.build_fingerprint = prop;
 
   // Brillo images don't have a channel assigned. We stored the name of the
   // channel where we got the image from in prefs at the time of the update, so
diff --git a/image_properties_chromeos.cc b/image_properties_chromeos.cc
index 501e662..6bab63f 100644
--- a/image_properties_chromeos.cc
+++ b/image_properties_chromeos.cc
@@ -115,6 +115,8 @@
   result.omaha_url =
       GetStringWithDefault(lsb_release, kLsbReleaseAutoUpdateServerKey,
                            constants::kOmahaDefaultProductionURL);
+  // Build fingerprint not used in Chrome OS.
+  result.build_fingerprint = "";
 
   return result;
 }
diff --git a/include/debugd/dbus-proxies.h b/include/debugd/dbus-proxies.h
deleted file mode 100644
index a528480..0000000
--- a/include/debugd/dbus-proxies.h
+++ /dev/null
@@ -1,2334 +0,0 @@
-// Automatic generation of D-Bus interfaces:
-//  - org.chromium.debugd
-#ifndef ____CHROMEOS_DBUS_BINDING____________________BUILD_LINK_VAR_CACHE_PORTAGE_CHROMEOS_BASE_DEBUGD_CLIENT_OUT_DEFAULT_GEN_INCLUDE_DEBUGD_DBUS_PROXIES_H
-#define ____CHROMEOS_DBUS_BINDING____________________BUILD_LINK_VAR_CACHE_PORTAGE_CHROMEOS_BASE_DEBUGD_CLIENT_OUT_DEFAULT_GEN_INCLUDE_DEBUGD_DBUS_PROXIES_H
-#include <memory>
-#include <string>
-#include <vector>
-
-#include <base/bind.h>
-#include <base/callback.h>
-#include <base/logging.h>
-#include <base/macros.h>
-#include <base/memory/ref_counted.h>
-#include <brillo/any.h>
-#include <brillo/dbus/dbus_method_invoker.h>
-#include <brillo/dbus/dbus_property.h>
-#include <brillo/dbus/dbus_signal_handler.h>
-#include <brillo/errors/error.h>
-#include <brillo/variant_dictionary.h>
-#include <dbus/bus.h>
-#include <dbus/message.h>
-#include <dbus/object_manager.h>
-#include <dbus/object_path.h>
-#include <dbus/object_proxy.h>
-
-namespace org {
-namespace chromium {
-
-// Abstract interface proxy for org::chromium::debugd.
-class debugdProxyInterface {
- public:
-  virtual ~debugdProxyInterface() = default;
-
-  // Starts pinging the specified hostname with the specified options, with
-  // output directed to the given output file descriptor. The returned opaque
-  // string functions as a handle for this particular ping. Multiple pings
-  // can be running at once.
-  virtual bool PingStart(
-      const dbus::FileDescriptor& in_outfd,
-      const std::string& in_destination,
-      const brillo::VariantDictionary& in_options,
-      std::string* out_handle,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Starts pinging the specified hostname with the specified options, with
-  // output directed to the given output file descriptor. The returned opaque
-  // string functions as a handle for this particular ping. Multiple pings
-  // can be running at once.
-  virtual void PingStartAsync(
-      const dbus::FileDescriptor& in_outfd,
-      const std::string& in_destination,
-      const brillo::VariantDictionary& in_options,
-      const base::Callback<void(const std::string& /*handle*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Stops a running ping.
-  virtual bool PingStop(
-      const std::string& in_handle,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Stops a running ping.
-  virtual void PingStopAsync(
-      const std::string& in_handle,
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Start system/kernel tracing.  If tracing is already enabled it is
-  // stopped first and any collected events are discarded.  The kernel
-  // must have been configured to support tracing.
-  virtual bool SystraceStart(
-      const std::string& in_categories,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Start system/kernel tracing.  If tracing is already enabled it is
-  // stopped first and any collected events are discarded.  The kernel
-  // must have been configured to support tracing.
-  virtual void SystraceStartAsync(
-      const std::string& in_categories,
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Stop system/kernel tracing and write the collected event data.
-  virtual bool SystraceStop(
-      const dbus::FileDescriptor& in_outfd,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Stop system/kernel tracing and write the collected event data.
-  virtual void SystraceStopAsync(
-      const dbus::FileDescriptor& in_outfd,
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Return current status for system/kernel tracing including whether it
-  // is enabled, the tracing clock, and the set of events enabled.
-  virtual bool SystraceStatus(
-      std::string* out_status,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Return current status for system/kernel tracing including whether it
-  // is enabled, the tracing clock, and the set of events enabled.
-  virtual void SystraceStatusAsync(
-      const base::Callback<void(const std::string& /*status*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  virtual bool TracePathStart(
-      const dbus::FileDescriptor& in_outfd,
-      const std::string& in_destination,
-      const brillo::VariantDictionary& in_options,
-      std::string* out_handle,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  virtual void TracePathStartAsync(
-      const dbus::FileDescriptor& in_outfd,
-      const std::string& in_destination,
-      const brillo::VariantDictionary& in_options,
-      const base::Callback<void(const std::string& /*handle*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Stops a running tracepath.
-  virtual bool TracePathStop(
-      const std::string& in_handle,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Stops a running tracepath.
-  virtual void TracePathStopAsync(
-      const std::string& in_handle,
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Returns the routing table.
-  virtual bool GetRoutes(
-      const brillo::VariantDictionary& in_options,
-      std::vector<std::string>* out_result,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Returns the routing table.
-  virtual void GetRoutesAsync(
-      const brillo::VariantDictionary& in_options,
-      const base::Callback<void(const std::vector<std::string>& /*result*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Returns modem information as a JSON string. See the design document for
-  // a rationale.
-  virtual bool GetModemStatus(
-      std::string* out_status,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Returns modem information as a JSON string. See the design document for
-  // a rationale.
-  virtual void GetModemStatusAsync(
-      const base::Callback<void(const std::string& /*status*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Runs the specified command through the modem serial interface and
-  // returns the output.
-  virtual bool RunModemCommand(
-      const std::string& in_command,
-      std::string* out_status,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Runs the specified command through the modem serial interface and
-  // returns the output.
-  virtual void RunModemCommandAsync(
-      const std::string& in_command,
-      const base::Callback<void(const std::string& /*status*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Returns network information as a JSON string. See the design document
-  // for a rationale.
-  virtual bool GetNetworkStatus(
-      std::string* out_status,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Returns network information as a JSON string. See the design document
-  // for a rationale.
-  virtual void GetNetworkStatusAsync(
-      const base::Callback<void(const std::string& /*status*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Returns WiMAX information as a JSON string. See the design document for
-  // a rationale.
-  virtual bool GetWiMaxStatus(
-      std::string* out_status,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Returns WiMAX information as a JSON string. See the design document for
-  // a rationale.
-  virtual void GetWiMaxStatusAsync(
-      const base::Callback<void(const std::string& /*status*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Runs system-wide perf profiling. The profile parameters are selected by
-  // perf_args.
-  virtual bool GetPerfOutput(
-      uint32_t in_duration_sec,
-      const std::vector<std::string>& in_perf_args,
-      int32_t* out_status,
-      std::vector<uint8_t>* out_perf_data,
-      std::vector<uint8_t>* out_perf_stat,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Runs system-wide perf profiling. The profile parameters are selected by
-  // perf_args.
-  virtual void GetPerfOutputAsync(
-      uint32_t in_duration_sec,
-      const std::vector<std::string>& in_perf_args,
-      const base::Callback<void(int32_t /*status*/, const std::vector<uint8_t>& /*perf_data*/, const std::vector<uint8_t>& /*perf_stat*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Runs system-wide perf profiling. It can can profile events other than
-  // cycles (example: iTLB-misses), and can collect branch profiles. It can
-  // also return raw counter values. The exact profile or counters to be
-  // collected is chosen at random and depends on what CPU is used by the
-  // system (certain CPUs do not support certain profiling modes).
-  virtual bool GetRandomPerfOutput(
-      uint32_t in_duration_sec,
-      int32_t* out_status,
-      std::vector<uint8_t>* out_perf_data,
-      std::vector<uint8_t>* out_perf_stat,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Runs system-wide perf profiling. It can can profile events other than
-  // cycles (example: iTLB-misses), and can collect branch profiles. It can
-  // also return raw counter values. The exact profile or counters to be
-  // collected is chosen at random and depends on what CPU is used by the
-  // system (certain CPUs do not support certain profiling modes).
-  virtual void GetRandomPerfOutputAsync(
-      uint32_t in_duration_sec,
-      const base::Callback<void(int32_t /*status*/, const std::vector<uint8_t>& /*perf_data*/, const std::vector<uint8_t>& /*perf_stat*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Returns perf event data. Does systemwide profiling. It can profile
-  // events other than cycles (example: iTLB-misses), and can collect branch
-  // profiles. The exact profile to be collected is chosen at random
-  // and depends on what CPU is used by the system (certain CPUs do not
-  // support certain profiling modes).
-  virtual bool GetRichPerfData(
-      uint32_t in_duration_sec,
-      std::vector<uint8_t>* out_status,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Returns perf event data. Does systemwide profiling. It can profile
-  // events other than cycles (example: iTLB-misses), and can collect branch
-  // profiles. The exact profile to be collected is chosen at random
-  // and depends on what CPU is used by the system (certain CPUs do not
-  // support certain profiling modes).
-  virtual void GetRichPerfDataAsync(
-      uint32_t in_duration_sec,
-      const base::Callback<void(const std::vector<uint8_t>& /*status*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // DEPRECATED: Use DumpDebugLogs instead.
-  // Packages up system logs into a .tar.gz and returns it over the supplied
-  // file descriptor.
-  virtual bool GetDebugLogs(
-      const dbus::FileDescriptor& in_outfd,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // DEPRECATED: Use DumpDebugLogs instead.
-  // Packages up system logs into a .tar.gz and returns it over the supplied
-  // file descriptor.
-  virtual void GetDebugLogsAsync(
-      const dbus::FileDescriptor& in_outfd,
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Packages up system logs into a .tar(.gz) and returns it over the
-  // supplied file descriptor.
-  virtual bool DumpDebugLogs(
-      bool in_is_compressed,
-      const dbus::FileDescriptor& in_outfd,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Packages up system logs into a .tar(.gz) and returns it over the
-  // supplied file descriptor.
-  virtual void DumpDebugLogsAsync(
-      bool in_is_compressed,
-      const dbus::FileDescriptor& in_outfd,
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Enables or disables debug mode for a specified subsystem.
-  virtual bool SetDebugMode(
-      const std::string& in_subsystem,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Enables or disables debug mode for a specified subsystem.
-  virtual void SetDebugModeAsync(
-      const std::string& in_subsystem,
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Fetches the contents of a single system log, identified by name. See
-  // /src/log_tool.cc for a list of valid names.
-  virtual bool GetLog(
-      const std::string& in_log,
-      std::string* out_contents,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Fetches the contents of a single system log, identified by name. See
-  // /src/log_tool.cc for a list of valid names.
-  virtual void GetLogAsync(
-      const std::string& in_log,
-      const base::Callback<void(const std::string& /*contents*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Returns all the system logs.
-  virtual bool GetAllLogs(
-      std::map<std::string, std::string>* out_logs,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Returns all the system logs.
-  virtual void GetAllLogsAsync(
-      const base::Callback<void(const std::map<std::string, std::string>& /*logs*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Returns system logs for feedback reports.
-  virtual bool GetFeedbackLogs(
-      std::map<std::string, std::string>* out_logs,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Returns system logs for feedback reports.
-  virtual void GetFeedbackLogsAsync(
-      const base::Callback<void(const std::map<std::string, std::string>& /*logs*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Returns list of User log file names that Chrome itself must collect.
-  // These logfiles are relative to the user's profile path and must be
-  // collected separately for each user.
-  virtual bool GetUserLogFiles(
-      std::map<std::string, std::string>* out_user_log_files,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Returns list of User log file names that Chrome itself must collect.
-  // These logfiles are relative to the user's profile path and must be
-  // collected separately for each user.
-  virtual void GetUserLogFilesAsync(
-      const base::Callback<void(const std::map<std::string, std::string>& /*user_log_files*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Example method. See /doc/hacking.md.
-  virtual bool GetExample(
-      std::string* out_result,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Example method. See /doc/hacking.md.
-  virtual void GetExampleAsync(
-      const base::Callback<void(const std::string& /*result*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Returns information about network interfaces as a JSON string.
-  virtual bool GetInterfaces(
-      std::string* out_result,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Returns information about network interfaces as a JSON string.
-  virtual void GetInterfacesAsync(
-      const base::Callback<void(const std::string& /*result*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Tests ICMP connectivity to a specified host.
-  virtual bool TestICMP(
-      const std::string& in_host,
-      std::string* out_result,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Tests ICMP connectivity to a specified host.
-  virtual void TestICMPAsync(
-      const std::string& in_host,
-      const base::Callback<void(const std::string& /*result*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Tests ICMP connectivity to a specified host (with options).
-  virtual bool TestICMPWithOptions(
-      const std::string& in_host,
-      const std::map<std::string, std::string>& in_options,
-      std::string* out_result,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Tests ICMP connectivity to a specified host (with options).
-  virtual void TestICMPWithOptionsAsync(
-      const std::string& in_host,
-      const std::map<std::string, std::string>& in_options,
-      const base::Callback<void(const std::string& /*result*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Runs BatteryFirmware utility.
-  virtual bool BatteryFirmware(
-      const std::string& in_option,
-      std::string* out_result,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Runs BatteryFirmware utility.
-  virtual void BatteryFirmwareAsync(
-      const std::string& in_option,
-      const base::Callback<void(const std::string& /*result*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Runs Smartctl utility.
-  virtual bool Smartctl(
-      const std::string& in_option,
-      std::string* out_result,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Runs Smartctl utility.
-  virtual void SmartctlAsync(
-      const std::string& in_option,
-      const base::Callback<void(const std::string& /*result*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Starts running memtester.
-  virtual bool MemtesterStart(
-      const dbus::FileDescriptor& in_outfd,
-      uint32_t in_memory,
-      std::string* out_status,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Starts running memtester.
-  virtual void MemtesterStartAsync(
-      const dbus::FileDescriptor& in_outfd,
-      uint32_t in_memory,
-      const base::Callback<void(const std::string& /*status*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Stops running memtester.
-  virtual bool MemtesterStop(
-      const std::string& in_handle,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Stops running memtester.
-  virtual void MemtesterStopAsync(
-      const std::string& in_handle,
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Starts running badblocks test.
-  virtual bool BadblocksStart(
-      const dbus::FileDescriptor& in_outfd,
-      std::string* out_status,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Starts running badblocks test.
-  virtual void BadblocksStartAsync(
-      const dbus::FileDescriptor& in_outfd,
-      const base::Callback<void(const std::string& /*status*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Stops running badblocks.
-  virtual bool BadblocksStop(
-      const std::string& in_handle,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Stops running badblocks.
-  virtual void BadblocksStopAsync(
-      const std::string& in_handle,
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Starts a packet capture with the specified options, with diagnostic
-  // status directed to the "statfd" file descriptor and packet capture
-  // data sent to the "outfd" file descriptor.  The returned opaque string
-  // functions as a handle for this particular packet capture.  Multiple
-  // captures can be running at once.  Captures can be initiated on
-  // Ethernet-like devices or WiFi devices in "client mode" (showing only
-  // Ethernet frames) by specifying the "device" parameter (see below).
-  // By specifying a channel, the script will find or create a "monitor
-  // mode" interface if one is available and produce an "over the air"
-  // packet capture.  The name of the output packet capture file is sent
-  // to the output file descriptor.
-  virtual bool PacketCaptureStart(
-      const dbus::FileDescriptor& in_statfd,
-      const dbus::FileDescriptor& in_outfd,
-      const brillo::VariantDictionary& in_options,
-      std::string* out_handle,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Starts a packet capture with the specified options, with diagnostic
-  // status directed to the "statfd" file descriptor and packet capture
-  // data sent to the "outfd" file descriptor.  The returned opaque string
-  // functions as a handle for this particular packet capture.  Multiple
-  // captures can be running at once.  Captures can be initiated on
-  // Ethernet-like devices or WiFi devices in "client mode" (showing only
-  // Ethernet frames) by specifying the "device" parameter (see below).
-  // By specifying a channel, the script will find or create a "monitor
-  // mode" interface if one is available and produce an "over the air"
-  // packet capture.  The name of the output packet capture file is sent
-  // to the output file descriptor.
-  virtual void PacketCaptureStartAsync(
-      const dbus::FileDescriptor& in_statfd,
-      const dbus::FileDescriptor& in_outfd,
-      const brillo::VariantDictionary& in_options,
-      const base::Callback<void(const std::string& /*handle*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Stops a running packet capture.
-  virtual bool PacketCaptureStop(
-      const std::string& in_handle,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Stops a running packet capture.
-  virtual void PacketCaptureStopAsync(
-      const std::string& in_handle,
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Triggers show-task-states(T) SysRq.
-  // See https://www.kernel.org/doc/Documentation/sysrq.txt.
-  virtual bool LogKernelTaskStates(
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Triggers show-task-states(T) SysRq.
-  // See https://www.kernel.org/doc/Documentation/sysrq.txt.
-  virtual void LogKernelTaskStatesAsync(
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Triggers uploading of system crashes (the crash_sender program).
-  virtual bool UploadCrashes(
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Triggers uploading of system crashes (the crash_sender program).
-  virtual void UploadCrashesAsync(
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Removes rootfs verification. Requires a system reboot before it will
-  // take effect. Restricted to pre-owner dev mode.
-  virtual bool RemoveRootfsVerification(
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Removes rootfs verification. Requires a system reboot before it will
-  // take effect. Restricted to pre-owner dev mode.
-  virtual void RemoveRootfsVerificationAsync(
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Enables OS booting from a USB image. Restricted to pre-owner dev mode.
-  virtual bool EnableBootFromUsb(
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Enables OS booting from a USB image. Restricted to pre-owner dev mode.
-  virtual void EnableBootFromUsbAsync(
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Sets up sshd to provide an SSH server immediately and on future reboots.
-  // Also installs the test SSH keys to allow access by cros tools. Requires
-  // that rootfs verification has been removed. Restricted to pre-owner dev
-  // mode.
-  virtual bool ConfigureSshServer(
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Sets up sshd to provide an SSH server immediately and on future reboots.
-  // Also installs the test SSH keys to allow access by cros tools. Requires
-  // that rootfs verification has been removed. Restricted to pre-owner dev
-  // mode.
-  virtual void ConfigureSshServerAsync(
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Sets both the system and dev mode password for the indicated account.
-  // Restricted to pre-owner dev mode.
-  virtual bool SetUserPassword(
-      const std::string& in_username,
-      const std::string& in_password,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Sets both the system and dev mode password for the indicated account.
-  // Restricted to pre-owner dev mode.
-  virtual void SetUserPasswordAsync(
-      const std::string& in_username,
-      const std::string& in_password,
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Sets up Chrome for remote debugging. It will take effect after a reboot
-  // and using port 9222.
-  // Requires that rootfs verification has been removed. Restricted to
-  // pre-owner dev mode.
-  virtual bool EnableChromeRemoteDebugging(
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Sets up Chrome for remote debugging. It will take effect after a reboot
-  // and using port 9222.
-  // Requires that rootfs verification has been removed. Restricted to
-  // pre-owner dev mode.
-  virtual void EnableChromeRemoteDebuggingAsync(
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Convenience function to enable a predefined set of tools from the Chrome
-  // UI. Equivalent to calling these functions in order:
-  //   1. EnableBootFromUsb()
-  //   2. ConfigureSshServer()
-  //   3. SetUserPassword("root", root_password)
-  // Requires that rootfs verification has been removed. If any sub-function
-  // fails, this function will exit with an error without attempting any
-  // further configuration or rollback. Restricted to pre-owner dev mode.
-  virtual bool EnableChromeDevFeatures(
-      const std::string& in_root_password,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Convenience function to enable a predefined set of tools from the Chrome
-  // UI. Equivalent to calling these functions in order:
-  //   1. EnableBootFromUsb()
-  //   2. ConfigureSshServer()
-  //   3. SetUserPassword("root", root_password)
-  // Requires that rootfs verification has been removed. If any sub-function
-  // fails, this function will exit with an error without attempting any
-  // further configuration or rollback. Restricted to pre-owner dev mode.
-  virtual void EnableChromeDevFeaturesAsync(
-      const std::string& in_root_password,
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Queries which dev features have been enabled. Each dev feature will be
-  // indicated by a bit flag in the return value. Flags are defined in the
-  // DevFeatureFlag enumeration. If the dev tools are unavailable (system is
-  // not in dev mode/pre-login state), the DEV_FEATURES_DISABLED flag will be
-  // set and the rest of the bits will always be set to 0.
-  virtual bool QueryDevFeatures(
-      int32_t* out_features,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Queries which dev features have been enabled. Each dev feature will be
-  // indicated by a bit flag in the return value. Flags are defined in the
-  // DevFeatureFlag enumeration. If the dev tools are unavailable (system is
-  // not in dev mode/pre-login state), the DEV_FEATURES_DISABLED flag will be
-  // set and the rest of the bits will always be set to 0.
-  virtual void QueryDevFeaturesAsync(
-      const base::Callback<void(int32_t /*features*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Allow uploading of device coredump files.
-  virtual bool EnableDevCoredumpUpload(
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Allow uploading of device coredump files.
-  virtual void EnableDevCoredumpUploadAsync(
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Disallow uploading of device coredump files.
-  virtual bool DisableDevCoredumpUpload(
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // Disallow uploading of device coredump files.
-  virtual void DisableDevCoredumpUploadAsync(
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-};
-
-}  // namespace chromium
-}  // namespace org
-
-namespace org {
-namespace chromium {
-
-// Interface proxy for org::chromium::debugd.
-class debugdProxy final : public debugdProxyInterface {
- public:
-  debugdProxy(const scoped_refptr<dbus::Bus>& bus) :
-      bus_{bus},
-      dbus_object_proxy_{
-          bus_->GetObjectProxy(service_name_, object_path_)} {
-  }
-
-  ~debugdProxy() override {
-    bus_->RemoveObjectProxy(
-        service_name_, object_path_, base::Bind(&base::DoNothing));
-  }
-
-  void ReleaseObjectProxy(const base::Closure& callback) {
-    bus_->RemoveObjectProxy(service_name_, object_path_, callback);
-  }
-
-  const dbus::ObjectPath& GetObjectPath() const {
-    return object_path_;
-  }
-
-  dbus::ObjectProxy* GetObjectProxy() const { return dbus_object_proxy_; }
-
-  // Starts pinging the specified hostname with the specified options, with
-  // output directed to the given output file descriptor. The returned opaque
-  // string functions as a handle for this particular ping. Multiple pings
-  // can be running at once.
-  bool PingStart(
-      const dbus::FileDescriptor& in_outfd,
-      const std::string& in_destination,
-      const brillo::VariantDictionary& in_options,
-      std::string* out_handle,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "PingStart",
-        error,
-        in_outfd,
-        in_destination,
-        in_options);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error, out_handle);
-  }
-
-  // Starts pinging the specified hostname with the specified options, with
-  // output directed to the given output file descriptor. The returned opaque
-  // string functions as a handle for this particular ping. Multiple pings
-  // can be running at once.
-  void PingStartAsync(
-      const dbus::FileDescriptor& in_outfd,
-      const std::string& in_destination,
-      const brillo::VariantDictionary& in_options,
-      const base::Callback<void(const std::string& /*handle*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "PingStart",
-        success_callback,
-        error_callback,
-        in_outfd,
-        in_destination,
-        in_options);
-  }
-
-  // Stops a running ping.
-  bool PingStop(
-      const std::string& in_handle,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "PingStop",
-        error,
-        in_handle);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error);
-  }
-
-  // Stops a running ping.
-  void PingStopAsync(
-      const std::string& in_handle,
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "PingStop",
-        success_callback,
-        error_callback,
-        in_handle);
-  }
-
-  // Start system/kernel tracing.  If tracing is already enabled it is
-  // stopped first and any collected events are discarded.  The kernel
-  // must have been configured to support tracing.
-  bool SystraceStart(
-      const std::string& in_categories,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "SystraceStart",
-        error,
-        in_categories);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error);
-  }
-
-  // Start system/kernel tracing.  If tracing is already enabled it is
-  // stopped first and any collected events are discarded.  The kernel
-  // must have been configured to support tracing.
-  void SystraceStartAsync(
-      const std::string& in_categories,
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "SystraceStart",
-        success_callback,
-        error_callback,
-        in_categories);
-  }
-
-  // Stop system/kernel tracing and write the collected event data.
-  bool SystraceStop(
-      const dbus::FileDescriptor& in_outfd,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "SystraceStop",
-        error,
-        in_outfd);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error);
-  }
-
-  // Stop system/kernel tracing and write the collected event data.
-  void SystraceStopAsync(
-      const dbus::FileDescriptor& in_outfd,
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "SystraceStop",
-        success_callback,
-        error_callback,
-        in_outfd);
-  }
-
-  // Return current status for system/kernel tracing including whether it
-  // is enabled, the tracing clock, and the set of events enabled.
-  bool SystraceStatus(
-      std::string* out_status,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "SystraceStatus",
-        error);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error, out_status);
-  }
-
-  // Return current status for system/kernel tracing including whether it
-  // is enabled, the tracing clock, and the set of events enabled.
-  void SystraceStatusAsync(
-      const base::Callback<void(const std::string& /*status*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "SystraceStatus",
-        success_callback,
-        error_callback);
-  }
-
-  bool TracePathStart(
-      const dbus::FileDescriptor& in_outfd,
-      const std::string& in_destination,
-      const brillo::VariantDictionary& in_options,
-      std::string* out_handle,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "TracePathStart",
-        error,
-        in_outfd,
-        in_destination,
-        in_options);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error, out_handle);
-  }
-
-  void TracePathStartAsync(
-      const dbus::FileDescriptor& in_outfd,
-      const std::string& in_destination,
-      const brillo::VariantDictionary& in_options,
-      const base::Callback<void(const std::string& /*handle*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "TracePathStart",
-        success_callback,
-        error_callback,
-        in_outfd,
-        in_destination,
-        in_options);
-  }
-
-  // Stops a running tracepath.
-  bool TracePathStop(
-      const std::string& in_handle,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "TracePathStop",
-        error,
-        in_handle);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error);
-  }
-
-  // Stops a running tracepath.
-  void TracePathStopAsync(
-      const std::string& in_handle,
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "TracePathStop",
-        success_callback,
-        error_callback,
-        in_handle);
-  }
-
-  // Returns the routing table.
-  bool GetRoutes(
-      const brillo::VariantDictionary& in_options,
-      std::vector<std::string>* out_result,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "GetRoutes",
-        error,
-        in_options);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error, out_result);
-  }
-
-  // Returns the routing table.
-  void GetRoutesAsync(
-      const brillo::VariantDictionary& in_options,
-      const base::Callback<void(const std::vector<std::string>& /*result*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "GetRoutes",
-        success_callback,
-        error_callback,
-        in_options);
-  }
-
-  // Returns modem information as a JSON string. See the design document for
-  // a rationale.
-  bool GetModemStatus(
-      std::string* out_status,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "GetModemStatus",
-        error);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error, out_status);
-  }
-
-  // Returns modem information as a JSON string. See the design document for
-  // a rationale.
-  void GetModemStatusAsync(
-      const base::Callback<void(const std::string& /*status*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "GetModemStatus",
-        success_callback,
-        error_callback);
-  }
-
-  // Runs the specified command through the modem serial interface and
-  // returns the output.
-  bool RunModemCommand(
-      const std::string& in_command,
-      std::string* out_status,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "RunModemCommand",
-        error,
-        in_command);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error, out_status);
-  }
-
-  // Runs the specified command through the modem serial interface and
-  // returns the output.
-  void RunModemCommandAsync(
-      const std::string& in_command,
-      const base::Callback<void(const std::string& /*status*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "RunModemCommand",
-        success_callback,
-        error_callback,
-        in_command);
-  }
-
-  // Returns network information as a JSON string. See the design document
-  // for a rationale.
-  bool GetNetworkStatus(
-      std::string* out_status,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "GetNetworkStatus",
-        error);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error, out_status);
-  }
-
-  // Returns network information as a JSON string. See the design document
-  // for a rationale.
-  void GetNetworkStatusAsync(
-      const base::Callback<void(const std::string& /*status*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "GetNetworkStatus",
-        success_callback,
-        error_callback);
-  }
-
-  // Returns WiMAX information as a JSON string. See the design document for
-  // a rationale.
-  bool GetWiMaxStatus(
-      std::string* out_status,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "GetWiMaxStatus",
-        error);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error, out_status);
-  }
-
-  // Returns WiMAX information as a JSON string. See the design document for
-  // a rationale.
-  void GetWiMaxStatusAsync(
-      const base::Callback<void(const std::string& /*status*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "GetWiMaxStatus",
-        success_callback,
-        error_callback);
-  }
-
-  // Runs system-wide perf profiling. The profile parameters are selected by
-  // perf_args.
-  bool GetPerfOutput(
-      uint32_t in_duration_sec,
-      const std::vector<std::string>& in_perf_args,
-      int32_t* out_status,
-      std::vector<uint8_t>* out_perf_data,
-      std::vector<uint8_t>* out_perf_stat,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "GetPerfOutput",
-        error,
-        in_duration_sec,
-        in_perf_args);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error, out_status, out_perf_data, out_perf_stat);
-  }
-
-  // Runs system-wide perf profiling. The profile parameters are selected by
-  // perf_args.
-  void GetPerfOutputAsync(
-      uint32_t in_duration_sec,
-      const std::vector<std::string>& in_perf_args,
-      const base::Callback<void(int32_t /*status*/, const std::vector<uint8_t>& /*perf_data*/, const std::vector<uint8_t>& /*perf_stat*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "GetPerfOutput",
-        success_callback,
-        error_callback,
-        in_duration_sec,
-        in_perf_args);
-  }
-
-  // Runs system-wide perf profiling. It can can profile events other than
-  // cycles (example: iTLB-misses), and can collect branch profiles. It can
-  // also return raw counter values. The exact profile or counters to be
-  // collected is chosen at random and depends on what CPU is used by the
-  // system (certain CPUs do not support certain profiling modes).
-  bool GetRandomPerfOutput(
-      uint32_t in_duration_sec,
-      int32_t* out_status,
-      std::vector<uint8_t>* out_perf_data,
-      std::vector<uint8_t>* out_perf_stat,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "GetRandomPerfOutput",
-        error,
-        in_duration_sec);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error, out_status, out_perf_data, out_perf_stat);
-  }
-
-  // Runs system-wide perf profiling. It can can profile events other than
-  // cycles (example: iTLB-misses), and can collect branch profiles. It can
-  // also return raw counter values. The exact profile or counters to be
-  // collected is chosen at random and depends on what CPU is used by the
-  // system (certain CPUs do not support certain profiling modes).
-  void GetRandomPerfOutputAsync(
-      uint32_t in_duration_sec,
-      const base::Callback<void(int32_t /*status*/, const std::vector<uint8_t>& /*perf_data*/, const std::vector<uint8_t>& /*perf_stat*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "GetRandomPerfOutput",
-        success_callback,
-        error_callback,
-        in_duration_sec);
-  }
-
-  // Returns perf event data. Does systemwide profiling. It can profile
-  // events other than cycles (example: iTLB-misses), and can collect branch
-  // profiles. The exact profile to be collected is chosen at random
-  // and depends on what CPU is used by the system (certain CPUs do not
-  // support certain profiling modes).
-  bool GetRichPerfData(
-      uint32_t in_duration_sec,
-      std::vector<uint8_t>* out_status,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "GetRichPerfData",
-        error,
-        in_duration_sec);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error, out_status);
-  }
-
-  // Returns perf event data. Does systemwide profiling. It can profile
-  // events other than cycles (example: iTLB-misses), and can collect branch
-  // profiles. The exact profile to be collected is chosen at random
-  // and depends on what CPU is used by the system (certain CPUs do not
-  // support certain profiling modes).
-  void GetRichPerfDataAsync(
-      uint32_t in_duration_sec,
-      const base::Callback<void(const std::vector<uint8_t>& /*status*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "GetRichPerfData",
-        success_callback,
-        error_callback,
-        in_duration_sec);
-  }
-
-  // DEPRECATED: Use DumpDebugLogs instead.
-  // Packages up system logs into a .tar.gz and returns it over the supplied
-  // file descriptor.
-  bool GetDebugLogs(
-      const dbus::FileDescriptor& in_outfd,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "GetDebugLogs",
-        error,
-        in_outfd);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error);
-  }
-
-  // DEPRECATED: Use DumpDebugLogs instead.
-  // Packages up system logs into a .tar.gz and returns it over the supplied
-  // file descriptor.
-  void GetDebugLogsAsync(
-      const dbus::FileDescriptor& in_outfd,
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "GetDebugLogs",
-        success_callback,
-        error_callback,
-        in_outfd);
-  }
-
-  // Packages up system logs into a .tar(.gz) and returns it over the
-  // supplied file descriptor.
-  bool DumpDebugLogs(
-      bool in_is_compressed,
-      const dbus::FileDescriptor& in_outfd,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "DumpDebugLogs",
-        error,
-        in_is_compressed,
-        in_outfd);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error);
-  }
-
-  // Packages up system logs into a .tar(.gz) and returns it over the
-  // supplied file descriptor.
-  void DumpDebugLogsAsync(
-      bool in_is_compressed,
-      const dbus::FileDescriptor& in_outfd,
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "DumpDebugLogs",
-        success_callback,
-        error_callback,
-        in_is_compressed,
-        in_outfd);
-  }
-
-  // Enables or disables debug mode for a specified subsystem.
-  bool SetDebugMode(
-      const std::string& in_subsystem,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "SetDebugMode",
-        error,
-        in_subsystem);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error);
-  }
-
-  // Enables or disables debug mode for a specified subsystem.
-  void SetDebugModeAsync(
-      const std::string& in_subsystem,
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "SetDebugMode",
-        success_callback,
-        error_callback,
-        in_subsystem);
-  }
-
-  // Fetches the contents of a single system log, identified by name. See
-  // /src/log_tool.cc for a list of valid names.
-  bool GetLog(
-      const std::string& in_log,
-      std::string* out_contents,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "GetLog",
-        error,
-        in_log);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error, out_contents);
-  }
-
-  // Fetches the contents of a single system log, identified by name. See
-  // /src/log_tool.cc for a list of valid names.
-  void GetLogAsync(
-      const std::string& in_log,
-      const base::Callback<void(const std::string& /*contents*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "GetLog",
-        success_callback,
-        error_callback,
-        in_log);
-  }
-
-  // Returns all the system logs.
-  bool GetAllLogs(
-      std::map<std::string, std::string>* out_logs,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "GetAllLogs",
-        error);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error, out_logs);
-  }
-
-  // Returns all the system logs.
-  void GetAllLogsAsync(
-      const base::Callback<void(const std::map<std::string, std::string>& /*logs*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "GetAllLogs",
-        success_callback,
-        error_callback);
-  }
-
-  // Returns system logs for feedback reports.
-  bool GetFeedbackLogs(
-      std::map<std::string, std::string>* out_logs,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "GetFeedbackLogs",
-        error);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error, out_logs);
-  }
-
-  // Returns system logs for feedback reports.
-  void GetFeedbackLogsAsync(
-      const base::Callback<void(const std::map<std::string, std::string>& /*logs*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "GetFeedbackLogs",
-        success_callback,
-        error_callback);
-  }
-
-  // Returns list of User log file names that Chrome itself must collect.
-  // These logfiles are relative to the user's profile path and must be
-  // collected separately for each user.
-  bool GetUserLogFiles(
-      std::map<std::string, std::string>* out_user_log_files,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "GetUserLogFiles",
-        error);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error, out_user_log_files);
-  }
-
-  // Returns list of User log file names that Chrome itself must collect.
-  // These logfiles are relative to the user's profile path and must be
-  // collected separately for each user.
-  void GetUserLogFilesAsync(
-      const base::Callback<void(const std::map<std::string, std::string>& /*user_log_files*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "GetUserLogFiles",
-        success_callback,
-        error_callback);
-  }
-
-  // Example method. See /doc/hacking.md.
-  bool GetExample(
-      std::string* out_result,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "GetExample",
-        error);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error, out_result);
-  }
-
-  // Example method. See /doc/hacking.md.
-  void GetExampleAsync(
-      const base::Callback<void(const std::string& /*result*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "GetExample",
-        success_callback,
-        error_callback);
-  }
-
-  // Returns information about network interfaces as a JSON string.
-  bool GetInterfaces(
-      std::string* out_result,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "GetInterfaces",
-        error);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error, out_result);
-  }
-
-  // Returns information about network interfaces as a JSON string.
-  void GetInterfacesAsync(
-      const base::Callback<void(const std::string& /*result*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "GetInterfaces",
-        success_callback,
-        error_callback);
-  }
-
-  // Tests ICMP connectivity to a specified host.
-  bool TestICMP(
-      const std::string& in_host,
-      std::string* out_result,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "TestICMP",
-        error,
-        in_host);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error, out_result);
-  }
-
-  // Tests ICMP connectivity to a specified host.
-  void TestICMPAsync(
-      const std::string& in_host,
-      const base::Callback<void(const std::string& /*result*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "TestICMP",
-        success_callback,
-        error_callback,
-        in_host);
-  }
-
-  // Tests ICMP connectivity to a specified host (with options).
-  bool TestICMPWithOptions(
-      const std::string& in_host,
-      const std::map<std::string, std::string>& in_options,
-      std::string* out_result,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "TestICMPWithOptions",
-        error,
-        in_host,
-        in_options);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error, out_result);
-  }
-
-  // Tests ICMP connectivity to a specified host (with options).
-  void TestICMPWithOptionsAsync(
-      const std::string& in_host,
-      const std::map<std::string, std::string>& in_options,
-      const base::Callback<void(const std::string& /*result*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "TestICMPWithOptions",
-        success_callback,
-        error_callback,
-        in_host,
-        in_options);
-  }
-
-  // Runs BatteryFirmware utility.
-  bool BatteryFirmware(
-      const std::string& in_option,
-      std::string* out_result,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "BatteryFirmware",
-        error,
-        in_option);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error, out_result);
-  }
-
-  // Runs BatteryFirmware utility.
-  void BatteryFirmwareAsync(
-      const std::string& in_option,
-      const base::Callback<void(const std::string& /*result*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "BatteryFirmware",
-        success_callback,
-        error_callback,
-        in_option);
-  }
-
-  // Runs Smartctl utility.
-  bool Smartctl(
-      const std::string& in_option,
-      std::string* out_result,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "Smartctl",
-        error,
-        in_option);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error, out_result);
-  }
-
-  // Runs Smartctl utility.
-  void SmartctlAsync(
-      const std::string& in_option,
-      const base::Callback<void(const std::string& /*result*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "Smartctl",
-        success_callback,
-        error_callback,
-        in_option);
-  }
-
-  // Starts running memtester.
-  bool MemtesterStart(
-      const dbus::FileDescriptor& in_outfd,
-      uint32_t in_memory,
-      std::string* out_status,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "MemtesterStart",
-        error,
-        in_outfd,
-        in_memory);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error, out_status);
-  }
-
-  // Starts running memtester.
-  void MemtesterStartAsync(
-      const dbus::FileDescriptor& in_outfd,
-      uint32_t in_memory,
-      const base::Callback<void(const std::string& /*status*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "MemtesterStart",
-        success_callback,
-        error_callback,
-        in_outfd,
-        in_memory);
-  }
-
-  // Stops running memtester.
-  bool MemtesterStop(
-      const std::string& in_handle,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "MemtesterStop",
-        error,
-        in_handle);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error);
-  }
-
-  // Stops running memtester.
-  void MemtesterStopAsync(
-      const std::string& in_handle,
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "MemtesterStop",
-        success_callback,
-        error_callback,
-        in_handle);
-  }
-
-  // Starts running badblocks test.
-  bool BadblocksStart(
-      const dbus::FileDescriptor& in_outfd,
-      std::string* out_status,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "BadblocksStart",
-        error,
-        in_outfd);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error, out_status);
-  }
-
-  // Starts running badblocks test.
-  void BadblocksStartAsync(
-      const dbus::FileDescriptor& in_outfd,
-      const base::Callback<void(const std::string& /*status*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "BadblocksStart",
-        success_callback,
-        error_callback,
-        in_outfd);
-  }
-
-  // Stops running badblocks.
-  bool BadblocksStop(
-      const std::string& in_handle,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "BadblocksStop",
-        error,
-        in_handle);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error);
-  }
-
-  // Stops running badblocks.
-  void BadblocksStopAsync(
-      const std::string& in_handle,
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "BadblocksStop",
-        success_callback,
-        error_callback,
-        in_handle);
-  }
-
-  // Starts a packet capture with the specified options, with diagnostic
-  // status directed to the "statfd" file descriptor and packet capture
-  // data sent to the "outfd" file descriptor.  The returned opaque string
-  // functions as a handle for this particular packet capture.  Multiple
-  // captures can be running at once.  Captures can be initiated on
-  // Ethernet-like devices or WiFi devices in "client mode" (showing only
-  // Ethernet frames) by specifying the "device" parameter (see below).
-  // By specifying a channel, the script will find or create a "monitor
-  // mode" interface if one is available and produce an "over the air"
-  // packet capture.  The name of the output packet capture file is sent
-  // to the output file descriptor.
-  bool PacketCaptureStart(
-      const dbus::FileDescriptor& in_statfd,
-      const dbus::FileDescriptor& in_outfd,
-      const brillo::VariantDictionary& in_options,
-      std::string* out_handle,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "PacketCaptureStart",
-        error,
-        in_statfd,
-        in_outfd,
-        in_options);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error, out_handle);
-  }
-
-  // Starts a packet capture with the specified options, with diagnostic
-  // status directed to the "statfd" file descriptor and packet capture
-  // data sent to the "outfd" file descriptor.  The returned opaque string
-  // functions as a handle for this particular packet capture.  Multiple
-  // captures can be running at once.  Captures can be initiated on
-  // Ethernet-like devices or WiFi devices in "client mode" (showing only
-  // Ethernet frames) by specifying the "device" parameter (see below).
-  // By specifying a channel, the script will find or create a "monitor
-  // mode" interface if one is available and produce an "over the air"
-  // packet capture.  The name of the output packet capture file is sent
-  // to the output file descriptor.
-  void PacketCaptureStartAsync(
-      const dbus::FileDescriptor& in_statfd,
-      const dbus::FileDescriptor& in_outfd,
-      const brillo::VariantDictionary& in_options,
-      const base::Callback<void(const std::string& /*handle*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "PacketCaptureStart",
-        success_callback,
-        error_callback,
-        in_statfd,
-        in_outfd,
-        in_options);
-  }
-
-  // Stops a running packet capture.
-  bool PacketCaptureStop(
-      const std::string& in_handle,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "PacketCaptureStop",
-        error,
-        in_handle);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error);
-  }
-
-  // Stops a running packet capture.
-  void PacketCaptureStopAsync(
-      const std::string& in_handle,
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "PacketCaptureStop",
-        success_callback,
-        error_callback,
-        in_handle);
-  }
-
-  // Triggers show-task-states(T) SysRq.
-  // See https://www.kernel.org/doc/Documentation/sysrq.txt.
-  bool LogKernelTaskStates(
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "LogKernelTaskStates",
-        error);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error);
-  }
-
-  // Triggers show-task-states(T) SysRq.
-  // See https://www.kernel.org/doc/Documentation/sysrq.txt.
-  void LogKernelTaskStatesAsync(
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "LogKernelTaskStates",
-        success_callback,
-        error_callback);
-  }
-
-  // Triggers uploading of system crashes (the crash_sender program).
-  bool UploadCrashes(
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "UploadCrashes",
-        error);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error);
-  }
-
-  // Triggers uploading of system crashes (the crash_sender program).
-  void UploadCrashesAsync(
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "UploadCrashes",
-        success_callback,
-        error_callback);
-  }
-
-  // Removes rootfs verification. Requires a system reboot before it will
-  // take effect. Restricted to pre-owner dev mode.
-  bool RemoveRootfsVerification(
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "RemoveRootfsVerification",
-        error);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error);
-  }
-
-  // Removes rootfs verification. Requires a system reboot before it will
-  // take effect. Restricted to pre-owner dev mode.
-  void RemoveRootfsVerificationAsync(
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "RemoveRootfsVerification",
-        success_callback,
-        error_callback);
-  }
-
-  // Enables OS booting from a USB image. Restricted to pre-owner dev mode.
-  bool EnableBootFromUsb(
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "EnableBootFromUsb",
-        error);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error);
-  }
-
-  // Enables OS booting from a USB image. Restricted to pre-owner dev mode.
-  void EnableBootFromUsbAsync(
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "EnableBootFromUsb",
-        success_callback,
-        error_callback);
-  }
-
-  // Sets up sshd to provide an SSH server immediately and on future reboots.
-  // Also installs the test SSH keys to allow access by cros tools. Requires
-  // that rootfs verification has been removed. Restricted to pre-owner dev
-  // mode.
-  bool ConfigureSshServer(
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "ConfigureSshServer",
-        error);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error);
-  }
-
-  // Sets up sshd to provide an SSH server immediately and on future reboots.
-  // Also installs the test SSH keys to allow access by cros tools. Requires
-  // that rootfs verification has been removed. Restricted to pre-owner dev
-  // mode.
-  void ConfigureSshServerAsync(
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "ConfigureSshServer",
-        success_callback,
-        error_callback);
-  }
-
-  // Sets both the system and dev mode password for the indicated account.
-  // Restricted to pre-owner dev mode.
-  bool SetUserPassword(
-      const std::string& in_username,
-      const std::string& in_password,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "SetUserPassword",
-        error,
-        in_username,
-        in_password);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error);
-  }
-
-  // Sets both the system and dev mode password for the indicated account.
-  // Restricted to pre-owner dev mode.
-  void SetUserPasswordAsync(
-      const std::string& in_username,
-      const std::string& in_password,
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "SetUserPassword",
-        success_callback,
-        error_callback,
-        in_username,
-        in_password);
-  }
-
-  // Sets up Chrome for remote debugging. It will take effect after a reboot
-  // and using port 9222.
-  // Requires that rootfs verification has been removed. Restricted to
-  // pre-owner dev mode.
-  bool EnableChromeRemoteDebugging(
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "EnableChromeRemoteDebugging",
-        error);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error);
-  }
-
-  // Sets up Chrome for remote debugging. It will take effect after a reboot
-  // and using port 9222.
-  // Requires that rootfs verification has been removed. Restricted to
-  // pre-owner dev mode.
-  void EnableChromeRemoteDebuggingAsync(
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "EnableChromeRemoteDebugging",
-        success_callback,
-        error_callback);
-  }
-
-  // Convenience function to enable a predefined set of tools from the Chrome
-  // UI. Equivalent to calling these functions in order:
-  //   1. EnableBootFromUsb()
-  //   2. ConfigureSshServer()
-  //   3. SetUserPassword("root", root_password)
-  // Requires that rootfs verification has been removed. If any sub-function
-  // fails, this function will exit with an error without attempting any
-  // further configuration or rollback. Restricted to pre-owner dev mode.
-  bool EnableChromeDevFeatures(
-      const std::string& in_root_password,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "EnableChromeDevFeatures",
-        error,
-        in_root_password);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error);
-  }
-
-  // Convenience function to enable a predefined set of tools from the Chrome
-  // UI. Equivalent to calling these functions in order:
-  //   1. EnableBootFromUsb()
-  //   2. ConfigureSshServer()
-  //   3. SetUserPassword("root", root_password)
-  // Requires that rootfs verification has been removed. If any sub-function
-  // fails, this function will exit with an error without attempting any
-  // further configuration or rollback. Restricted to pre-owner dev mode.
-  void EnableChromeDevFeaturesAsync(
-      const std::string& in_root_password,
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "EnableChromeDevFeatures",
-        success_callback,
-        error_callback,
-        in_root_password);
-  }
-
-  // Queries which dev features have been enabled. Each dev feature will be
-  // indicated by a bit flag in the return value. Flags are defined in the
-  // DevFeatureFlag enumeration. If the dev tools are unavailable (system is
-  // not in dev mode/pre-login state), the DEV_FEATURES_DISABLED flag will be
-  // set and the rest of the bits will always be set to 0.
-  bool QueryDevFeatures(
-      int32_t* out_features,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "QueryDevFeatures",
-        error);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error, out_features);
-  }
-
-  // Queries which dev features have been enabled. Each dev feature will be
-  // indicated by a bit flag in the return value. Flags are defined in the
-  // DevFeatureFlag enumeration. If the dev tools are unavailable (system is
-  // not in dev mode/pre-login state), the DEV_FEATURES_DISABLED flag will be
-  // set and the rest of the bits will always be set to 0.
-  void QueryDevFeaturesAsync(
-      const base::Callback<void(int32_t /*features*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "QueryDevFeatures",
-        success_callback,
-        error_callback);
-  }
-
-  // Allow uploading of device coredump files.
-  bool EnableDevCoredumpUpload(
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "EnableDevCoredumpUpload",
-        error);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error);
-  }
-
-  // Allow uploading of device coredump files.
-  void EnableDevCoredumpUploadAsync(
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "EnableDevCoredumpUpload",
-        success_callback,
-        error_callback);
-  }
-
-  // Disallow uploading of device coredump files.
-  bool DisableDevCoredumpUpload(
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "DisableDevCoredumpUpload",
-        error);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error);
-  }
-
-  // Disallow uploading of device coredump files.
-  void DisableDevCoredumpUploadAsync(
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.debugd",
-        "DisableDevCoredumpUpload",
-        success_callback,
-        error_callback);
-  }
-
- private:
-  scoped_refptr<dbus::Bus> bus_;
-  const std::string service_name_{"org.chromium.debugd"};
-  const dbus::ObjectPath object_path_{"/org/chromium/debugd"};
-  dbus::ObjectProxy* dbus_object_proxy_;
-
-  DISALLOW_COPY_AND_ASSIGN(debugdProxy);
-};
-
-}  // namespace chromium
-}  // namespace org
-
-#endif  // ____CHROMEOS_DBUS_BINDING____________________BUILD_LINK_VAR_CACHE_PORTAGE_CHROMEOS_BASE_DEBUGD_CLIENT_OUT_DEFAULT_GEN_INCLUDE_DEBUGD_DBUS_PROXIES_H
diff --git a/include/debugd/dbus-proxy-mocks.h b/include/debugd/dbus-proxy-mocks.h
deleted file mode 100644
index 042a9fd..0000000
--- a/include/debugd/dbus-proxy-mocks.h
+++ /dev/null
@@ -1,453 +0,0 @@
-// Automatic generation of D-Bus interface mock proxies for:
-//  - org.chromium.debugd
-#ifndef ____CHROMEOS_DBUS_BINDING____________________BUILD_LINK_VAR_CACHE_PORTAGE_CHROMEOS_BASE_DEBUGD_CLIENT_OUT_DEFAULT_GEN_INCLUDE_DEBUGD_DBUS_PROXY_MOCKS_H
-#define ____CHROMEOS_DBUS_BINDING____________________BUILD_LINK_VAR_CACHE_PORTAGE_CHROMEOS_BASE_DEBUGD_CLIENT_OUT_DEFAULT_GEN_INCLUDE_DEBUGD_DBUS_PROXY_MOCKS_H
-#include <string>
-#include <vector>
-
-#include <base/callback_forward.h>
-#include <base/logging.h>
-#include <base/macros.h>
-#include <brillo/any.h>
-#include <brillo/errors/error.h>
-#include <brillo/variant_dictionary.h>
-#include <gmock/gmock.h>
-
-#include "debugd/dbus-proxies.h"
-
-namespace org {
-namespace chromium {
-
-// Mock object for debugdProxyInterface.
-class debugdProxyMock : public debugdProxyInterface {
- public:
-  debugdProxyMock() = default;
-
-  MOCK_METHOD6(PingStart,
-               bool(const dbus::FileDescriptor& /*in_outfd*/,
-                    const std::string& /*in_destination*/,
-                    const brillo::VariantDictionary& /*in_options*/,
-                    std::string* /*out_handle*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD6(PingStartAsync,
-               void(const dbus::FileDescriptor& /*in_outfd*/,
-                    const std::string& /*in_destination*/,
-                    const brillo::VariantDictionary& /*in_options*/,
-                    const base::Callback<void(const std::string& /*handle*/)>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(PingStop,
-               bool(const std::string& /*in_handle*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(PingStopAsync,
-               void(const std::string& /*in_handle*/,
-                    const base::Callback<void()>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(SystraceStart,
-               bool(const std::string& /*in_categories*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(SystraceStartAsync,
-               void(const std::string& /*in_categories*/,
-                    const base::Callback<void()>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(SystraceStop,
-               bool(const dbus::FileDescriptor& /*in_outfd*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(SystraceStopAsync,
-               void(const dbus::FileDescriptor& /*in_outfd*/,
-                    const base::Callback<void()>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(SystraceStatus,
-               bool(std::string* /*out_status*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(SystraceStatusAsync,
-               void(const base::Callback<void(const std::string& /*status*/)>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD6(TracePathStart,
-               bool(const dbus::FileDescriptor& /*in_outfd*/,
-                    const std::string& /*in_destination*/,
-                    const brillo::VariantDictionary& /*in_options*/,
-                    std::string* /*out_handle*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD6(TracePathStartAsync,
-               void(const dbus::FileDescriptor& /*in_outfd*/,
-                    const std::string& /*in_destination*/,
-                    const brillo::VariantDictionary& /*in_options*/,
-                    const base::Callback<void(const std::string& /*handle*/)>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(TracePathStop,
-               bool(const std::string& /*in_handle*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(TracePathStopAsync,
-               void(const std::string& /*in_handle*/,
-                    const base::Callback<void()>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(GetRoutes,
-               bool(const brillo::VariantDictionary& /*in_options*/,
-                    std::vector<std::string>* /*out_result*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(GetRoutesAsync,
-               void(const brillo::VariantDictionary& /*in_options*/,
-                    const base::Callback<void(const std::vector<std::string>& /*result*/)>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(GetModemStatus,
-               bool(std::string* /*out_status*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(GetModemStatusAsync,
-               void(const base::Callback<void(const std::string& /*status*/)>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(RunModemCommand,
-               bool(const std::string& /*in_command*/,
-                    std::string* /*out_status*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(RunModemCommandAsync,
-               void(const std::string& /*in_command*/,
-                    const base::Callback<void(const std::string& /*status*/)>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(GetNetworkStatus,
-               bool(std::string* /*out_status*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(GetNetworkStatusAsync,
-               void(const base::Callback<void(const std::string& /*status*/)>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(GetWiMaxStatus,
-               bool(std::string* /*out_status*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(GetWiMaxStatusAsync,
-               void(const base::Callback<void(const std::string& /*status*/)>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD7(GetPerfOutput,
-               bool(uint32_t /*in_duration_sec*/,
-                    const std::vector<std::string>& /*in_perf_args*/,
-                    int32_t* /*out_status*/,
-                    std::vector<uint8_t>* /*out_perf_data*/,
-                    std::vector<uint8_t>* /*out_perf_stat*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD5(GetPerfOutputAsync,
-               void(uint32_t /*in_duration_sec*/,
-                    const std::vector<std::string>& /*in_perf_args*/,
-                    const base::Callback<void(int32_t /*status*/, const std::vector<uint8_t>& /*perf_data*/, const std::vector<uint8_t>& /*perf_stat*/)>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD6(GetRandomPerfOutput,
-               bool(uint32_t /*in_duration_sec*/,
-                    int32_t* /*out_status*/,
-                    std::vector<uint8_t>* /*out_perf_data*/,
-                    std::vector<uint8_t>* /*out_perf_stat*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(GetRandomPerfOutputAsync,
-               void(uint32_t /*in_duration_sec*/,
-                    const base::Callback<void(int32_t /*status*/, const std::vector<uint8_t>& /*perf_data*/, const std::vector<uint8_t>& /*perf_stat*/)>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(GetRichPerfData,
-               bool(uint32_t /*in_duration_sec*/,
-                    std::vector<uint8_t>* /*out_status*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(GetRichPerfDataAsync,
-               void(uint32_t /*in_duration_sec*/,
-                    const base::Callback<void(const std::vector<uint8_t>& /*status*/)>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(GetDebugLogs,
-               bool(const dbus::FileDescriptor& /*in_outfd*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(GetDebugLogsAsync,
-               void(const dbus::FileDescriptor& /*in_outfd*/,
-                    const base::Callback<void()>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(DumpDebugLogs,
-               bool(bool /*in_is_compressed*/,
-                    const dbus::FileDescriptor& /*in_outfd*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD5(DumpDebugLogsAsync,
-               void(bool /*in_is_compressed*/,
-                    const dbus::FileDescriptor& /*in_outfd*/,
-                    const base::Callback<void()>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(SetDebugMode,
-               bool(const std::string& /*in_subsystem*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(SetDebugModeAsync,
-               void(const std::string& /*in_subsystem*/,
-                    const base::Callback<void()>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(GetLog,
-               bool(const std::string& /*in_log*/,
-                    std::string* /*out_contents*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(GetLogAsync,
-               void(const std::string& /*in_log*/,
-                    const base::Callback<void(const std::string& /*contents*/)>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(GetAllLogs,
-               bool(std::map<std::string, std::string>* /*out_logs*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(GetAllLogsAsync,
-               void(const base::Callback<void(const std::map<std::string, std::string>& /*logs*/)>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(GetFeedbackLogs,
-               bool(std::map<std::string, std::string>* /*out_logs*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(GetFeedbackLogsAsync,
-               void(const base::Callback<void(const std::map<std::string, std::string>& /*logs*/)>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(GetUserLogFiles,
-               bool(std::map<std::string, std::string>* /*out_user_log_files*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(GetUserLogFilesAsync,
-               void(const base::Callback<void(const std::map<std::string, std::string>& /*user_log_files*/)>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(GetExample,
-               bool(std::string* /*out_result*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(GetExampleAsync,
-               void(const base::Callback<void(const std::string& /*result*/)>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(GetInterfaces,
-               bool(std::string* /*out_result*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(GetInterfacesAsync,
-               void(const base::Callback<void(const std::string& /*result*/)>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(TestICMP,
-               bool(const std::string& /*in_host*/,
-                    std::string* /*out_result*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(TestICMPAsync,
-               void(const std::string& /*in_host*/,
-                    const base::Callback<void(const std::string& /*result*/)>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD5(TestICMPWithOptions,
-               bool(const std::string& /*in_host*/,
-                    const std::map<std::string, std::string>& /*in_options*/,
-                    std::string* /*out_result*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD5(TestICMPWithOptionsAsync,
-               void(const std::string& /*in_host*/,
-                    const std::map<std::string, std::string>& /*in_options*/,
-                    const base::Callback<void(const std::string& /*result*/)>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(BatteryFirmware,
-               bool(const std::string& /*in_option*/,
-                    std::string* /*out_result*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(BatteryFirmwareAsync,
-               void(const std::string& /*in_option*/,
-                    const base::Callback<void(const std::string& /*result*/)>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(Smartctl,
-               bool(const std::string& /*in_option*/,
-                    std::string* /*out_result*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(SmartctlAsync,
-               void(const std::string& /*in_option*/,
-                    const base::Callback<void(const std::string& /*result*/)>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD5(MemtesterStart,
-               bool(const dbus::FileDescriptor& /*in_outfd*/,
-                    uint32_t /*in_memory*/,
-                    std::string* /*out_status*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD5(MemtesterStartAsync,
-               void(const dbus::FileDescriptor& /*in_outfd*/,
-                    uint32_t /*in_memory*/,
-                    const base::Callback<void(const std::string& /*status*/)>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(MemtesterStop,
-               bool(const std::string& /*in_handle*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(MemtesterStopAsync,
-               void(const std::string& /*in_handle*/,
-                    const base::Callback<void()>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(BadblocksStart,
-               bool(const dbus::FileDescriptor& /*in_outfd*/,
-                    std::string* /*out_status*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(BadblocksStartAsync,
-               void(const dbus::FileDescriptor& /*in_outfd*/,
-                    const base::Callback<void(const std::string& /*status*/)>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(BadblocksStop,
-               bool(const std::string& /*in_handle*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(BadblocksStopAsync,
-               void(const std::string& /*in_handle*/,
-                    const base::Callback<void()>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD6(PacketCaptureStart,
-               bool(const dbus::FileDescriptor& /*in_statfd*/,
-                    const dbus::FileDescriptor& /*in_outfd*/,
-                    const brillo::VariantDictionary& /*in_options*/,
-                    std::string* /*out_handle*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD6(PacketCaptureStartAsync,
-               void(const dbus::FileDescriptor& /*in_statfd*/,
-                    const dbus::FileDescriptor& /*in_outfd*/,
-                    const brillo::VariantDictionary& /*in_options*/,
-                    const base::Callback<void(const std::string& /*handle*/)>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(PacketCaptureStop,
-               bool(const std::string& /*in_handle*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(PacketCaptureStopAsync,
-               void(const std::string& /*in_handle*/,
-                    const base::Callback<void()>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD2(LogKernelTaskStates,
-               bool(brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(LogKernelTaskStatesAsync,
-               void(const base::Callback<void()>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD2(UploadCrashes,
-               bool(brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(UploadCrashesAsync,
-               void(const base::Callback<void()>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD2(RemoveRootfsVerification,
-               bool(brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(RemoveRootfsVerificationAsync,
-               void(const base::Callback<void()>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD2(EnableBootFromUsb,
-               bool(brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(EnableBootFromUsbAsync,
-               void(const base::Callback<void()>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD2(ConfigureSshServer,
-               bool(brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(ConfigureSshServerAsync,
-               void(const base::Callback<void()>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(SetUserPassword,
-               bool(const std::string& /*in_username*/,
-                    const std::string& /*in_password*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD5(SetUserPasswordAsync,
-               void(const std::string& /*in_username*/,
-                    const std::string& /*in_password*/,
-                    const base::Callback<void()>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD2(EnableChromeRemoteDebugging,
-               bool(brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(EnableChromeRemoteDebuggingAsync,
-               void(const base::Callback<void()>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(EnableChromeDevFeatures,
-               bool(const std::string& /*in_root_password*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(EnableChromeDevFeaturesAsync,
-               void(const std::string& /*in_root_password*/,
-                    const base::Callback<void()>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(QueryDevFeatures,
-               bool(int32_t* /*out_features*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(QueryDevFeaturesAsync,
-               void(const base::Callback<void(int32_t /*features*/)>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD2(EnableDevCoredumpUpload,
-               bool(brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(EnableDevCoredumpUploadAsync,
-               void(const base::Callback<void()>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD2(DisableDevCoredumpUpload,
-               bool(brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(DisableDevCoredumpUploadAsync,
-               void(const base::Callback<void()>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(debugdProxyMock);
-};
-}  // namespace chromium
-}  // namespace org
-
-#endif  // ____CHROMEOS_DBUS_BINDING____________________BUILD_LINK_VAR_CACHE_PORTAGE_CHROMEOS_BASE_DEBUGD_CLIENT_OUT_DEFAULT_GEN_INCLUDE_DEBUGD_DBUS_PROXY_MOCKS_H
diff --git a/include/libcros/dbus-proxy-mocks.h b/include/libcros/dbus-proxy-mocks.h
deleted file mode 100644
index 16790bd..0000000
--- a/include/libcros/dbus-proxy-mocks.h
+++ /dev/null
@@ -1,77 +0,0 @@
-// Automatic generation of D-Bus interface mock proxies for:
-//  - org.chromium.LibCrosServiceInterface
-//  - org.chromium.UpdateEngineLibcrosProxyResolvedInterface
-#ifndef ____CHROMEOS_DBUS_BINDING___UPDATE_ENGINE_INCLUDE_LIBCROS_DBUS_PROXY_MOCKS_H
-#define ____CHROMEOS_DBUS_BINDING___UPDATE_ENGINE_INCLUDE_LIBCROS_DBUS_PROXY_MOCKS_H
-#include <string>
-#include <vector>
-
-#include <base/callback_forward.h>
-#include <base/logging.h>
-#include <base/macros.h>
-#include <brillo/any.h>
-#include <brillo/errors/error.h>
-#include <brillo/variant_dictionary.h>
-#include <gmock/gmock.h>
-
-#include "libcros/dbus-proxies.h"
-
-namespace org {
-namespace chromium {
-
-// Mock object for LibCrosServiceInterfaceProxyInterface.
-class LibCrosServiceInterfaceProxyMock : public LibCrosServiceInterfaceProxyInterface {
- public:
-  LibCrosServiceInterfaceProxyMock() = default;
-
-  MOCK_METHOD5(ResolveNetworkProxy,
-               bool(const std::string& /*in_source_url*/,
-                    const std::string& /*in_signal_interface*/,
-                    const std::string& /*in_signal_name*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD6(ResolveNetworkProxyAsync,
-               void(const std::string& /*in_source_url*/,
-                    const std::string& /*in_signal_interface*/,
-                    const std::string& /*in_signal_name*/,
-                    const base::Callback<void()>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(GetKioskAppRequiredPlatformVersion,
-               bool(std::string* /*out_required_platform_version*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(GetKioskAppRequiredPlatformVersionAsync,
-               void(const base::Callback<void(const std::string& /*required_platform_version*/)>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_CONST_METHOD0(GetObjectPath, const dbus::ObjectPath&());
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(LibCrosServiceInterfaceProxyMock);
-};
-}  // namespace chromium
-}  // namespace org
-
-namespace org {
-namespace chromium {
-
-// Mock object for UpdateEngineLibcrosProxyResolvedInterfaceProxyInterface.
-class UpdateEngineLibcrosProxyResolvedInterfaceProxyMock : public UpdateEngineLibcrosProxyResolvedInterfaceProxyInterface {
- public:
-  UpdateEngineLibcrosProxyResolvedInterfaceProxyMock() = default;
-
-  MOCK_METHOD2(RegisterProxyResolvedSignalHandler,
-               void(const base::Callback<void(const std::string&,
-                                              const std::string&,
-                                              const std::string&)>& /*signal_callback*/,
-                    dbus::ObjectProxy::OnConnectedCallback /*on_connected_callback*/));
-  MOCK_CONST_METHOD0(GetObjectPath, const dbus::ObjectPath&());
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(UpdateEngineLibcrosProxyResolvedInterfaceProxyMock);
-};
-}  // namespace chromium
-}  // namespace org
-
-#endif  // ____CHROMEOS_DBUS_BINDING___UPDATE_ENGINE_INCLUDE_LIBCROS_DBUS_PROXY_MOCKS_H
diff --git a/include/power_manager/dbus-proxies.h b/include/power_manager/dbus-proxies.h
deleted file mode 100644
index e66848d..0000000
--- a/include/power_manager/dbus-proxies.h
+++ /dev/null
@@ -1,1280 +0,0 @@
-// Automatic generation of D-Bus interfaces:
-//  - org.chromium.PowerManager
-#ifndef ____CHROMEOS_DBUS_BINDING____________________BUILD_LINK_TMP_PORTAGE_CHROMEOS_BASE_POWER_MANAGER_9999_WORK_BUILD_OUT_DEFAULT_GEN_INCLUDE_POWER_MANAGER_DBUS_PROXIES_H
-#define ____CHROMEOS_DBUS_BINDING____________________BUILD_LINK_TMP_PORTAGE_CHROMEOS_BASE_POWER_MANAGER_9999_WORK_BUILD_OUT_DEFAULT_GEN_INCLUDE_POWER_MANAGER_DBUS_PROXIES_H
-#include <memory>
-#include <string>
-#include <vector>
-
-#include <base/bind.h>
-#include <base/callback.h>
-#include <base/logging.h>
-#include <base/macros.h>
-#include <base/memory/ref_counted.h>
-#include <brillo/any.h>
-#include <brillo/dbus/dbus_method_invoker.h>
-#include <brillo/dbus/dbus_property.h>
-#include <brillo/dbus/dbus_signal_handler.h>
-#include <brillo/errors/error.h>
-#include <brillo/variant_dictionary.h>
-#include <dbus/bus.h>
-#include <dbus/message.h>
-#include <dbus/object_manager.h>
-#include <dbus/object_path.h>
-#include <dbus/object_proxy.h>
-
-namespace org {
-namespace chromium {
-
-// Abstract interface proxy for org::chromium::PowerManager.
-class PowerManagerProxyInterface {
- public:
-  virtual ~PowerManagerProxyInterface() = default;
-
-  virtual bool RequestShutdown(
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  virtual void RequestShutdownAsync(
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // The |reason| arg is a power_manager::RequestRestartReason value.
-  virtual bool RequestRestart(
-      int32_t in_reason,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // The |reason| arg is a power_manager::RequestRestartReason value.
-  virtual void RequestRestartAsync(
-      int32_t in_reason,
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // The |external_wakeup_count| arg is optional, and it will call two
-  // different methods in the backend. This can't be expressed in the DBus
-  // Introspection XML file.
-  virtual bool RequestSuspend(
-      uint64_t in_external_wakeup_count,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // The |external_wakeup_count| arg is optional, and it will call two
-  // different methods in the backend. This can't be expressed in the DBus
-  // Introspection XML file.
-  virtual void RequestSuspendAsync(
-      uint64_t in_external_wakeup_count,
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  virtual bool DecreaseScreenBrightness(
-      bool in_allow_off,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  virtual void DecreaseScreenBrightnessAsync(
-      bool in_allow_off,
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  virtual bool IncreaseScreenBrightness(
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  virtual void IncreaseScreenBrightnessAsync(
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  virtual bool GetScreenBrightnessPercent(
-      double* out_percent,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  virtual void GetScreenBrightnessPercentAsync(
-      const base::Callback<void(double /*percent*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // The |style| arg must be one of the values:
-  //   power_manager::kBrightnessTransitionGradual or
-  //   power_manager::kBrightnessTransitionInstant.
-  virtual bool SetScreenBrightnessPercent(
-      double in_percent,
-      int32_t in_style,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // The |style| arg must be one of the values:
-  //   power_manager::kBrightnessTransitionGradual or
-  //   power_manager::kBrightnessTransitionInstant.
-  virtual void SetScreenBrightnessPercentAsync(
-      double in_percent,
-      int32_t in_style,
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  virtual bool DecreaseKeyboardBrightness(
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  virtual void DecreaseKeyboardBrightnessAsync(
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  virtual bool IncreaseKeyboardBrightness(
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  virtual void IncreaseKeyboardBrightnessAsync(
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // The |serialized_proto| arg is a serialized
-  // power_manager::PowerSupplyProperties protobuf.
-  virtual bool GetPowerSupplyProperties(
-      std::vector<uint8_t>* out_serialized_proto,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // The |serialized_proto| arg is a serialized
-  // power_manager::PowerSupplyProperties protobuf.
-  virtual void GetPowerSupplyPropertiesAsync(
-      const base::Callback<void(const std::vector<uint8_t>& /*serialized_proto*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  virtual bool HandleVideoActivity(
-      bool in_fullscreen,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  virtual void HandleVideoActivityAsync(
-      bool in_fullscreen,
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // The |type| arg is a power_manager::UserActivityType.
-  virtual bool HandleUserActivity(
-      int32_t in_type,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // The |type| arg is a power_manager::UserActivityType.
-  virtual void HandleUserActivityAsync(
-      int32_t in_type,
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  virtual bool SetIsProjecting(
-      bool in_is_projecting,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  virtual void SetIsProjectingAsync(
-      bool in_is_projecting,
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // The |serialized_proto| arg is a serialized
-  // power_manager::PowerManagementPolicy protobuf.
-  virtual bool SetPolicy(
-      const std::vector<uint8_t>& in_serialized_proto,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // The |serialized_proto| arg is a serialized
-  // power_manager::PowerManagementPolicy protobuf.
-  virtual void SetPolicyAsync(
-      const std::vector<uint8_t>& in_serialized_proto,
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  virtual bool SetPowerSource(
-      const std::string& in_id,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  virtual void SetPowerSourceAsync(
-      const std::string& in_id,
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // The |timestamp_internal| arg is represented as the return value of
-  // base::TimeTicks::ToInternalValue().
-  virtual bool HandlePowerButtonAcknowledgment(
-      int64_t in_timestamp_internal,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // The |timestamp_internal| arg is represented as the return value of
-  // base::TimeTicks::ToInternalValue().
-  virtual void HandlePowerButtonAcknowledgmentAsync(
-      int64_t in_timestamp_internal,
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // The |serialized_request_proto| arg is a serialized
-  // power_manager::RegisterSuspendDelayRequest protobuf.
-  // The |serialized_reply_proto| arg is a serialized
-  // RegisterSuspendDelayReply protobuf.
-  virtual bool RegisterSuspendDelay(
-      const std::vector<uint8_t>& in_serialized_request_proto,
-      std::vector<uint8_t>* out_serialized_reply_proto,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // The |serialized_request_proto| arg is a serialized
-  // power_manager::RegisterSuspendDelayRequest protobuf.
-  // The |serialized_reply_proto| arg is a serialized
-  // RegisterSuspendDelayReply protobuf.
-  virtual void RegisterSuspendDelayAsync(
-      const std::vector<uint8_t>& in_serialized_request_proto,
-      const base::Callback<void(const std::vector<uint8_t>& /*serialized_reply_proto*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // The |serialized_proto| arg is a serialized
-  // power_manager::UnregisterSuspendDelayRequest protobuf.
-  virtual bool UnregisterSuspendDelay(
-      const std::vector<uint8_t>& in_serialized_proto,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // The |serialized_proto| arg is a serialized
-  // power_manager::UnregisterSuspendDelayRequest protobuf.
-  virtual void UnregisterSuspendDelayAsync(
-      const std::vector<uint8_t>& in_serialized_proto,
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // The |serialized_proto| arg is a serialized
-  // power_manager::SuspendReadinessInfo protobuf.
-  virtual bool HandleSuspendReadiness(
-      const std::vector<uint8_t>& in_serialized_proto,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // The |serialized_proto| arg is a serialized
-  // power_manager::SuspendReadinessInfo protobuf.
-  virtual void HandleSuspendReadinessAsync(
-      const std::vector<uint8_t>& in_serialized_proto,
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // The |serialized_request_proto| arg is a serialized
-  // power_manager::RegisterSuspendDelayRequest protobuf.
-  // The |serialized_reply_proto| arg is a serialized
-  // RegisterSuspendDelayReply protobuf.
-  virtual bool RegisterDarkSuspendDelay(
-      const std::vector<uint8_t>& in_serialized_request_proto,
-      std::vector<uint8_t>* out_serialized_reply_proto,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // The |serialized_request_proto| arg is a serialized
-  // power_manager::RegisterSuspendDelayRequest protobuf.
-  // The |serialized_reply_proto| arg is a serialized
-  // RegisterSuspendDelayReply protobuf.
-  virtual void RegisterDarkSuspendDelayAsync(
-      const std::vector<uint8_t>& in_serialized_request_proto,
-      const base::Callback<void(const std::vector<uint8_t>& /*serialized_reply_proto*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // The |serialized_proto| arg is a serialized
-  // power_manager::UnregisterSuspendDelayRequest protobuf.
-  virtual bool UnregisterDarkSuspendDelay(
-      const std::vector<uint8_t>& in_serialized_proto,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // The |serialized_proto| arg is a serialized
-  // power_manager::UnregisterSuspendDelayRequest protobuf.
-  virtual void UnregisterDarkSuspendDelayAsync(
-      const std::vector<uint8_t>& in_serialized_proto,
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // The |serialized_proto| arg is a serialized
-  // power_manager::SuspendReadinessInfo protobuf.
-  virtual bool HandleDarkSuspendReadiness(
-      const std::vector<uint8_t>& in_serialized_proto,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // The |serialized_proto| arg is a serialized
-  // power_manager::SuspendReadinessInfo protobuf.
-  virtual void HandleDarkSuspendReadinessAsync(
-      const std::vector<uint8_t>& in_serialized_proto,
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // The |serialized_proto| arg is a serialized
-  // power_manager::DarkResumeWakeReason protobuf.
-  virtual bool RecordDarkResumeWakeReason(
-      const std::vector<uint8_t>& in_serialized_proto,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  // The |serialized_proto| arg is a serialized
-  // power_manager::DarkResumeWakeReason protobuf.
-  virtual void RecordDarkResumeWakeReasonAsync(
-      const std::vector<uint8_t>& in_serialized_proto,
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  virtual void RegisterBrightnessChangedSignalHandler(
-      const base::Callback<void(int32_t,
-                                bool)>& signal_callback,
-      dbus::ObjectProxy::OnConnectedCallback on_connected_callback) = 0;
-
-  virtual void RegisterKeyboardBrightnessChangedSignalHandler(
-      const base::Callback<void(int32_t,
-                                bool)>& signal_callback,
-      dbus::ObjectProxy::OnConnectedCallback on_connected_callback) = 0;
-
-  virtual void RegisterPeripheralBatteryStatusSignalHandler(
-      const base::Callback<void(const std::vector<uint8_t>&)>& signal_callback,
-      dbus::ObjectProxy::OnConnectedCallback on_connected_callback) = 0;
-
-  virtual void RegisterPowerSupplyPollSignalHandler(
-      const base::Callback<void(const std::vector<uint8_t>&)>& signal_callback,
-      dbus::ObjectProxy::OnConnectedCallback on_connected_callback) = 0;
-
-  virtual void RegisterSuspendImminentSignalHandler(
-      const base::Callback<void(const std::vector<uint8_t>&)>& signal_callback,
-      dbus::ObjectProxy::OnConnectedCallback on_connected_callback) = 0;
-
-  virtual void RegisterSuspendDoneSignalHandler(
-      const base::Callback<void(const std::vector<uint8_t>&)>& signal_callback,
-      dbus::ObjectProxy::OnConnectedCallback on_connected_callback) = 0;
-
-  virtual void RegisterDarkSuspendImminentSignalHandler(
-      const base::Callback<void(const std::vector<uint8_t>&)>& signal_callback,
-      dbus::ObjectProxy::OnConnectedCallback on_connected_callback) = 0;
-
-  virtual void RegisterInputEventSignalHandler(
-      const base::Callback<void(const std::vector<uint8_t>&)>& signal_callback,
-      dbus::ObjectProxy::OnConnectedCallback on_connected_callback) = 0;
-
-  virtual void RegisterIdleActionImminentSignalHandler(
-      const base::Callback<void(const std::vector<uint8_t>&)>& signal_callback,
-      dbus::ObjectProxy::OnConnectedCallback on_connected_callback) = 0;
-
-  virtual void RegisterIdleActionDeferredSignalHandler(
-      const base::Closure& signal_callback,
-      dbus::ObjectProxy::OnConnectedCallback on_connected_callback) = 0;
-};
-
-}  // namespace chromium
-}  // namespace org
-
-namespace org {
-namespace chromium {
-
-// Interface proxy for org::chromium::PowerManager.
-class PowerManagerProxy final : public PowerManagerProxyInterface {
- public:
-  PowerManagerProxy(const scoped_refptr<dbus::Bus>& bus) :
-      bus_{bus},
-      dbus_object_proxy_{
-          bus_->GetObjectProxy(service_name_, object_path_)} {
-  }
-
-  ~PowerManagerProxy() override {
-    bus_->RemoveObjectProxy(
-        service_name_, object_path_, base::Bind(&base::DoNothing));
-  }
-
-  void RegisterBrightnessChangedSignalHandler(
-      const base::Callback<void(int32_t,
-                                bool)>& signal_callback,
-      dbus::ObjectProxy::OnConnectedCallback on_connected_callback) override {
-    brillo::dbus_utils::ConnectToSignal(
-        dbus_object_proxy_,
-        "org.chromium.PowerManager",
-        "BrightnessChanged",
-        signal_callback,
-        on_connected_callback);
-  }
-
-  void RegisterKeyboardBrightnessChangedSignalHandler(
-      const base::Callback<void(int32_t,
-                                bool)>& signal_callback,
-      dbus::ObjectProxy::OnConnectedCallback on_connected_callback) override {
-    brillo::dbus_utils::ConnectToSignal(
-        dbus_object_proxy_,
-        "org.chromium.PowerManager",
-        "KeyboardBrightnessChanged",
-        signal_callback,
-        on_connected_callback);
-  }
-
-  void RegisterPeripheralBatteryStatusSignalHandler(
-      const base::Callback<void(const std::vector<uint8_t>&)>& signal_callback,
-      dbus::ObjectProxy::OnConnectedCallback on_connected_callback) override {
-    brillo::dbus_utils::ConnectToSignal(
-        dbus_object_proxy_,
-        "org.chromium.PowerManager",
-        "PeripheralBatteryStatus",
-        signal_callback,
-        on_connected_callback);
-  }
-
-  void RegisterPowerSupplyPollSignalHandler(
-      const base::Callback<void(const std::vector<uint8_t>&)>& signal_callback,
-      dbus::ObjectProxy::OnConnectedCallback on_connected_callback) override {
-    brillo::dbus_utils::ConnectToSignal(
-        dbus_object_proxy_,
-        "org.chromium.PowerManager",
-        "PowerSupplyPoll",
-        signal_callback,
-        on_connected_callback);
-  }
-
-  void RegisterSuspendImminentSignalHandler(
-      const base::Callback<void(const std::vector<uint8_t>&)>& signal_callback,
-      dbus::ObjectProxy::OnConnectedCallback on_connected_callback) override {
-    brillo::dbus_utils::ConnectToSignal(
-        dbus_object_proxy_,
-        "org.chromium.PowerManager",
-        "SuspendImminent",
-        signal_callback,
-        on_connected_callback);
-  }
-
-  void RegisterSuspendDoneSignalHandler(
-      const base::Callback<void(const std::vector<uint8_t>&)>& signal_callback,
-      dbus::ObjectProxy::OnConnectedCallback on_connected_callback) override {
-    brillo::dbus_utils::ConnectToSignal(
-        dbus_object_proxy_,
-        "org.chromium.PowerManager",
-        "SuspendDone",
-        signal_callback,
-        on_connected_callback);
-  }
-
-  void RegisterDarkSuspendImminentSignalHandler(
-      const base::Callback<void(const std::vector<uint8_t>&)>& signal_callback,
-      dbus::ObjectProxy::OnConnectedCallback on_connected_callback) override {
-    brillo::dbus_utils::ConnectToSignal(
-        dbus_object_proxy_,
-        "org.chromium.PowerManager",
-        "DarkSuspendImminent",
-        signal_callback,
-        on_connected_callback);
-  }
-
-  void RegisterInputEventSignalHandler(
-      const base::Callback<void(const std::vector<uint8_t>&)>& signal_callback,
-      dbus::ObjectProxy::OnConnectedCallback on_connected_callback) override {
-    brillo::dbus_utils::ConnectToSignal(
-        dbus_object_proxy_,
-        "org.chromium.PowerManager",
-        "InputEvent",
-        signal_callback,
-        on_connected_callback);
-  }
-
-  void RegisterIdleActionImminentSignalHandler(
-      const base::Callback<void(const std::vector<uint8_t>&)>& signal_callback,
-      dbus::ObjectProxy::OnConnectedCallback on_connected_callback) override {
-    brillo::dbus_utils::ConnectToSignal(
-        dbus_object_proxy_,
-        "org.chromium.PowerManager",
-        "IdleActionImminent",
-        signal_callback,
-        on_connected_callback);
-  }
-
-  void RegisterIdleActionDeferredSignalHandler(
-      const base::Closure& signal_callback,
-      dbus::ObjectProxy::OnConnectedCallback on_connected_callback) override {
-    brillo::dbus_utils::ConnectToSignal(
-        dbus_object_proxy_,
-        "org.chromium.PowerManager",
-        "IdleActionDeferred",
-        signal_callback,
-        on_connected_callback);
-  }
-
-  void ReleaseObjectProxy(const base::Closure& callback) {
-    bus_->RemoveObjectProxy(service_name_, object_path_, callback);
-  }
-
-  const dbus::ObjectPath& GetObjectPath() const {
-    return object_path_;
-  }
-
-  dbus::ObjectProxy* GetObjectProxy() const { return dbus_object_proxy_; }
-
-  bool RequestShutdown(
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.PowerManager",
-        "RequestShutdown",
-        error);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error);
-  }
-
-  void RequestShutdownAsync(
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.PowerManager",
-        "RequestShutdown",
-        success_callback,
-        error_callback);
-  }
-
-  // The |reason| arg is a power_manager::RequestRestartReason value.
-  bool RequestRestart(
-      int32_t in_reason,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.PowerManager",
-        "RequestRestart",
-        error,
-        in_reason);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error);
-  }
-
-  // The |reason| arg is a power_manager::RequestRestartReason value.
-  void RequestRestartAsync(
-      int32_t in_reason,
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.PowerManager",
-        "RequestRestart",
-        success_callback,
-        error_callback,
-        in_reason);
-  }
-
-  // The |external_wakeup_count| arg is optional, and it will call two
-  // different methods in the backend. This can't be expressed in the DBus
-  // Introspection XML file.
-  bool RequestSuspend(
-      uint64_t in_external_wakeup_count,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.PowerManager",
-        "RequestSuspend",
-        error,
-        in_external_wakeup_count);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error);
-  }
-
-  // The |external_wakeup_count| arg is optional, and it will call two
-  // different methods in the backend. This can't be expressed in the DBus
-  // Introspection XML file.
-  void RequestSuspendAsync(
-      uint64_t in_external_wakeup_count,
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.PowerManager",
-        "RequestSuspend",
-        success_callback,
-        error_callback,
-        in_external_wakeup_count);
-  }
-
-  bool DecreaseScreenBrightness(
-      bool in_allow_off,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.PowerManager",
-        "DecreaseScreenBrightness",
-        error,
-        in_allow_off);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error);
-  }
-
-  void DecreaseScreenBrightnessAsync(
-      bool in_allow_off,
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.PowerManager",
-        "DecreaseScreenBrightness",
-        success_callback,
-        error_callback,
-        in_allow_off);
-  }
-
-  bool IncreaseScreenBrightness(
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.PowerManager",
-        "IncreaseScreenBrightness",
-        error);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error);
-  }
-
-  void IncreaseScreenBrightnessAsync(
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.PowerManager",
-        "IncreaseScreenBrightness",
-        success_callback,
-        error_callback);
-  }
-
-  bool GetScreenBrightnessPercent(
-      double* out_percent,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.PowerManager",
-        "GetScreenBrightnessPercent",
-        error);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error, out_percent);
-  }
-
-  void GetScreenBrightnessPercentAsync(
-      const base::Callback<void(double /*percent*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.PowerManager",
-        "GetScreenBrightnessPercent",
-        success_callback,
-        error_callback);
-  }
-
-  // The |style| arg must be one of the values:
-  //   power_manager::kBrightnessTransitionGradual or
-  //   power_manager::kBrightnessTransitionInstant.
-  bool SetScreenBrightnessPercent(
-      double in_percent,
-      int32_t in_style,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.PowerManager",
-        "SetScreenBrightnessPercent",
-        error,
-        in_percent,
-        in_style);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error);
-  }
-
-  // The |style| arg must be one of the values:
-  //   power_manager::kBrightnessTransitionGradual or
-  //   power_manager::kBrightnessTransitionInstant.
-  void SetScreenBrightnessPercentAsync(
-      double in_percent,
-      int32_t in_style,
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.PowerManager",
-        "SetScreenBrightnessPercent",
-        success_callback,
-        error_callback,
-        in_percent,
-        in_style);
-  }
-
-  bool DecreaseKeyboardBrightness(
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.PowerManager",
-        "DecreaseKeyboardBrightness",
-        error);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error);
-  }
-
-  void DecreaseKeyboardBrightnessAsync(
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.PowerManager",
-        "DecreaseKeyboardBrightness",
-        success_callback,
-        error_callback);
-  }
-
-  bool IncreaseKeyboardBrightness(
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.PowerManager",
-        "IncreaseKeyboardBrightness",
-        error);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error);
-  }
-
-  void IncreaseKeyboardBrightnessAsync(
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.PowerManager",
-        "IncreaseKeyboardBrightness",
-        success_callback,
-        error_callback);
-  }
-
-  // The |serialized_proto| arg is a serialized
-  // power_manager::PowerSupplyProperties protobuf.
-  bool GetPowerSupplyProperties(
-      std::vector<uint8_t>* out_serialized_proto,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.PowerManager",
-        "GetPowerSupplyProperties",
-        error);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error, out_serialized_proto);
-  }
-
-  // The |serialized_proto| arg is a serialized
-  // power_manager::PowerSupplyProperties protobuf.
-  void GetPowerSupplyPropertiesAsync(
-      const base::Callback<void(const std::vector<uint8_t>& /*serialized_proto*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.PowerManager",
-        "GetPowerSupplyProperties",
-        success_callback,
-        error_callback);
-  }
-
-  bool HandleVideoActivity(
-      bool in_fullscreen,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.PowerManager",
-        "HandleVideoActivity",
-        error,
-        in_fullscreen);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error);
-  }
-
-  void HandleVideoActivityAsync(
-      bool in_fullscreen,
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.PowerManager",
-        "HandleVideoActivity",
-        success_callback,
-        error_callback,
-        in_fullscreen);
-  }
-
-  // The |type| arg is a power_manager::UserActivityType.
-  bool HandleUserActivity(
-      int32_t in_type,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.PowerManager",
-        "HandleUserActivity",
-        error,
-        in_type);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error);
-  }
-
-  // The |type| arg is a power_manager::UserActivityType.
-  void HandleUserActivityAsync(
-      int32_t in_type,
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.PowerManager",
-        "HandleUserActivity",
-        success_callback,
-        error_callback,
-        in_type);
-  }
-
-  bool SetIsProjecting(
-      bool in_is_projecting,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.PowerManager",
-        "SetIsProjecting",
-        error,
-        in_is_projecting);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error);
-  }
-
-  void SetIsProjectingAsync(
-      bool in_is_projecting,
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.PowerManager",
-        "SetIsProjecting",
-        success_callback,
-        error_callback,
-        in_is_projecting);
-  }
-
-  // The |serialized_proto| arg is a serialized
-  // power_manager::PowerManagementPolicy protobuf.
-  bool SetPolicy(
-      const std::vector<uint8_t>& in_serialized_proto,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.PowerManager",
-        "SetPolicy",
-        error,
-        in_serialized_proto);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error);
-  }
-
-  // The |serialized_proto| arg is a serialized
-  // power_manager::PowerManagementPolicy protobuf.
-  void SetPolicyAsync(
-      const std::vector<uint8_t>& in_serialized_proto,
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.PowerManager",
-        "SetPolicy",
-        success_callback,
-        error_callback,
-        in_serialized_proto);
-  }
-
-  bool SetPowerSource(
-      const std::string& in_id,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.PowerManager",
-        "SetPowerSource",
-        error,
-        in_id);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error);
-  }
-
-  void SetPowerSourceAsync(
-      const std::string& in_id,
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.PowerManager",
-        "SetPowerSource",
-        success_callback,
-        error_callback,
-        in_id);
-  }
-
-  // The |timestamp_internal| arg is represented as the return value of
-  // base::TimeTicks::ToInternalValue().
-  bool HandlePowerButtonAcknowledgment(
-      int64_t in_timestamp_internal,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.PowerManager",
-        "HandlePowerButtonAcknowledgment",
-        error,
-        in_timestamp_internal);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error);
-  }
-
-  // The |timestamp_internal| arg is represented as the return value of
-  // base::TimeTicks::ToInternalValue().
-  void HandlePowerButtonAcknowledgmentAsync(
-      int64_t in_timestamp_internal,
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.PowerManager",
-        "HandlePowerButtonAcknowledgment",
-        success_callback,
-        error_callback,
-        in_timestamp_internal);
-  }
-
-  // The |serialized_request_proto| arg is a serialized
-  // power_manager::RegisterSuspendDelayRequest protobuf.
-  // The |serialized_reply_proto| arg is a serialized
-  // RegisterSuspendDelayReply protobuf.
-  bool RegisterSuspendDelay(
-      const std::vector<uint8_t>& in_serialized_request_proto,
-      std::vector<uint8_t>* out_serialized_reply_proto,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.PowerManager",
-        "RegisterSuspendDelay",
-        error,
-        in_serialized_request_proto);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error, out_serialized_reply_proto);
-  }
-
-  // The |serialized_request_proto| arg is a serialized
-  // power_manager::RegisterSuspendDelayRequest protobuf.
-  // The |serialized_reply_proto| arg is a serialized
-  // RegisterSuspendDelayReply protobuf.
-  void RegisterSuspendDelayAsync(
-      const std::vector<uint8_t>& in_serialized_request_proto,
-      const base::Callback<void(const std::vector<uint8_t>& /*serialized_reply_proto*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.PowerManager",
-        "RegisterSuspendDelay",
-        success_callback,
-        error_callback,
-        in_serialized_request_proto);
-  }
-
-  // The |serialized_proto| arg is a serialized
-  // power_manager::UnregisterSuspendDelayRequest protobuf.
-  bool UnregisterSuspendDelay(
-      const std::vector<uint8_t>& in_serialized_proto,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.PowerManager",
-        "UnregisterSuspendDelay",
-        error,
-        in_serialized_proto);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error);
-  }
-
-  // The |serialized_proto| arg is a serialized
-  // power_manager::UnregisterSuspendDelayRequest protobuf.
-  void UnregisterSuspendDelayAsync(
-      const std::vector<uint8_t>& in_serialized_proto,
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.PowerManager",
-        "UnregisterSuspendDelay",
-        success_callback,
-        error_callback,
-        in_serialized_proto);
-  }
-
-  // The |serialized_proto| arg is a serialized
-  // power_manager::SuspendReadinessInfo protobuf.
-  bool HandleSuspendReadiness(
-      const std::vector<uint8_t>& in_serialized_proto,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.PowerManager",
-        "HandleSuspendReadiness",
-        error,
-        in_serialized_proto);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error);
-  }
-
-  // The |serialized_proto| arg is a serialized
-  // power_manager::SuspendReadinessInfo protobuf.
-  void HandleSuspendReadinessAsync(
-      const std::vector<uint8_t>& in_serialized_proto,
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.PowerManager",
-        "HandleSuspendReadiness",
-        success_callback,
-        error_callback,
-        in_serialized_proto);
-  }
-
-  // The |serialized_request_proto| arg is a serialized
-  // power_manager::RegisterSuspendDelayRequest protobuf.
-  // The |serialized_reply_proto| arg is a serialized
-  // RegisterSuspendDelayReply protobuf.
-  bool RegisterDarkSuspendDelay(
-      const std::vector<uint8_t>& in_serialized_request_proto,
-      std::vector<uint8_t>* out_serialized_reply_proto,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.PowerManager",
-        "RegisterDarkSuspendDelay",
-        error,
-        in_serialized_request_proto);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error, out_serialized_reply_proto);
-  }
-
-  // The |serialized_request_proto| arg is a serialized
-  // power_manager::RegisterSuspendDelayRequest protobuf.
-  // The |serialized_reply_proto| arg is a serialized
-  // RegisterSuspendDelayReply protobuf.
-  void RegisterDarkSuspendDelayAsync(
-      const std::vector<uint8_t>& in_serialized_request_proto,
-      const base::Callback<void(const std::vector<uint8_t>& /*serialized_reply_proto*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.PowerManager",
-        "RegisterDarkSuspendDelay",
-        success_callback,
-        error_callback,
-        in_serialized_request_proto);
-  }
-
-  // The |serialized_proto| arg is a serialized
-  // power_manager::UnregisterSuspendDelayRequest protobuf.
-  bool UnregisterDarkSuspendDelay(
-      const std::vector<uint8_t>& in_serialized_proto,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.PowerManager",
-        "UnregisterDarkSuspendDelay",
-        error,
-        in_serialized_proto);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error);
-  }
-
-  // The |serialized_proto| arg is a serialized
-  // power_manager::UnregisterSuspendDelayRequest protobuf.
-  void UnregisterDarkSuspendDelayAsync(
-      const std::vector<uint8_t>& in_serialized_proto,
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.PowerManager",
-        "UnregisterDarkSuspendDelay",
-        success_callback,
-        error_callback,
-        in_serialized_proto);
-  }
-
-  // The |serialized_proto| arg is a serialized
-  // power_manager::SuspendReadinessInfo protobuf.
-  bool HandleDarkSuspendReadiness(
-      const std::vector<uint8_t>& in_serialized_proto,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.PowerManager",
-        "HandleDarkSuspendReadiness",
-        error,
-        in_serialized_proto);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error);
-  }
-
-  // The |serialized_proto| arg is a serialized
-  // power_manager::SuspendReadinessInfo protobuf.
-  void HandleDarkSuspendReadinessAsync(
-      const std::vector<uint8_t>& in_serialized_proto,
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.PowerManager",
-        "HandleDarkSuspendReadiness",
-        success_callback,
-        error_callback,
-        in_serialized_proto);
-  }
-
-  // The |serialized_proto| arg is a serialized
-  // power_manager::DarkResumeWakeReason protobuf.
-  bool RecordDarkResumeWakeReason(
-      const std::vector<uint8_t>& in_serialized_proto,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.PowerManager",
-        "RecordDarkResumeWakeReason",
-        error,
-        in_serialized_proto);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error);
-  }
-
-  // The |serialized_proto| arg is a serialized
-  // power_manager::DarkResumeWakeReason protobuf.
-  void RecordDarkResumeWakeReasonAsync(
-      const std::vector<uint8_t>& in_serialized_proto,
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.PowerManager",
-        "RecordDarkResumeWakeReason",
-        success_callback,
-        error_callback,
-        in_serialized_proto);
-  }
-
- private:
-  scoped_refptr<dbus::Bus> bus_;
-  const std::string service_name_{"org.chromium.PowerManager"};
-  const dbus::ObjectPath object_path_{"/org/chromium/PowerManager"};
-  dbus::ObjectProxy* dbus_object_proxy_;
-
-  DISALLOW_COPY_AND_ASSIGN(PowerManagerProxy);
-};
-
-}  // namespace chromium
-}  // namespace org
-
-#endif  // ____CHROMEOS_DBUS_BINDING____________________BUILD_LINK_TMP_PORTAGE_CHROMEOS_BASE_POWER_MANAGER_9999_WORK_BUILD_OUT_DEFAULT_GEN_INCLUDE_POWER_MANAGER_DBUS_PROXIES_H
diff --git a/include/power_manager/dbus-proxy-mocks.h b/include/power_manager/dbus-proxy-mocks.h
deleted file mode 100644
index d4e3dd0..0000000
--- a/include/power_manager/dbus-proxy-mocks.h
+++ /dev/null
@@ -1,266 +0,0 @@
-// Automatic generation of D-Bus interface mock proxies for:
-//  - org.chromium.PowerManager
-#ifndef ____CHROMEOS_DBUS_BINDING____________________BUILD_LINK_TMP_PORTAGE_CHROMEOS_BASE_POWER_MANAGER_9999_WORK_BUILD_OUT_DEFAULT_GEN_INCLUDE_POWER_MANAGER_DBUS_PROXY_MOCKS_H
-#define ____CHROMEOS_DBUS_BINDING____________________BUILD_LINK_TMP_PORTAGE_CHROMEOS_BASE_POWER_MANAGER_9999_WORK_BUILD_OUT_DEFAULT_GEN_INCLUDE_POWER_MANAGER_DBUS_PROXY_MOCKS_H
-#include <string>
-#include <vector>
-
-#include <base/callback_forward.h>
-#include <base/logging.h>
-#include <base/macros.h>
-#include <brillo/any.h>
-#include <brillo/errors/error.h>
-#include <brillo/variant_dictionary.h>
-#include <gmock/gmock.h>
-
-#include "power_manager/dbus-proxies.h"
-
-namespace org {
-namespace chromium {
-
-// Mock object for PowerManagerProxyInterface.
-class PowerManagerProxyMock : public PowerManagerProxyInterface {
- public:
-  PowerManagerProxyMock() = default;
-
-  MOCK_METHOD2(RequestShutdown,
-               bool(brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(RequestShutdownAsync,
-               void(const base::Callback<void()>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(RequestRestart,
-               bool(int32_t /*in_reason*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(RequestRestartAsync,
-               void(int32_t /*in_reason*/,
-                    const base::Callback<void()>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(RequestSuspend,
-               bool(uint64_t /*in_external_wakeup_count*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(RequestSuspendAsync,
-               void(uint64_t /*in_external_wakeup_count*/,
-                    const base::Callback<void()>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(DecreaseScreenBrightness,
-               bool(bool /*in_allow_off*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(DecreaseScreenBrightnessAsync,
-               void(bool /*in_allow_off*/,
-                    const base::Callback<void()>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD2(IncreaseScreenBrightness,
-               bool(brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(IncreaseScreenBrightnessAsync,
-               void(const base::Callback<void()>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(GetScreenBrightnessPercent,
-               bool(double* /*out_percent*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(GetScreenBrightnessPercentAsync,
-               void(const base::Callback<void(double /*percent*/)>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(SetScreenBrightnessPercent,
-               bool(double /*in_percent*/,
-                    int32_t /*in_style*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD5(SetScreenBrightnessPercentAsync,
-               void(double /*in_percent*/,
-                    int32_t /*in_style*/,
-                    const base::Callback<void()>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD2(DecreaseKeyboardBrightness,
-               bool(brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(DecreaseKeyboardBrightnessAsync,
-               void(const base::Callback<void()>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD2(IncreaseKeyboardBrightness,
-               bool(brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(IncreaseKeyboardBrightnessAsync,
-               void(const base::Callback<void()>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(GetPowerSupplyProperties,
-               bool(std::vector<uint8_t>* /*out_serialized_proto*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(GetPowerSupplyPropertiesAsync,
-               void(const base::Callback<void(const std::vector<uint8_t>& /*serialized_proto*/)>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(HandleVideoActivity,
-               bool(bool /*in_fullscreen*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(HandleVideoActivityAsync,
-               void(bool /*in_fullscreen*/,
-                    const base::Callback<void()>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(HandleUserActivity,
-               bool(int32_t /*in_type*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(HandleUserActivityAsync,
-               void(int32_t /*in_type*/,
-                    const base::Callback<void()>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(SetIsProjecting,
-               bool(bool /*in_is_projecting*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(SetIsProjectingAsync,
-               void(bool /*in_is_projecting*/,
-                    const base::Callback<void()>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(SetPolicy,
-               bool(const std::vector<uint8_t>& /*in_serialized_proto*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(SetPolicyAsync,
-               void(const std::vector<uint8_t>& /*in_serialized_proto*/,
-                    const base::Callback<void()>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(SetPowerSource,
-               bool(const std::string& /*in_id*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(SetPowerSourceAsync,
-               void(const std::string& /*in_id*/,
-                    const base::Callback<void()>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(HandlePowerButtonAcknowledgment,
-               bool(int64_t /*in_timestamp_internal*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(HandlePowerButtonAcknowledgmentAsync,
-               void(int64_t /*in_timestamp_internal*/,
-                    const base::Callback<void()>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(RegisterSuspendDelay,
-               bool(const std::vector<uint8_t>& /*in_serialized_request_proto*/,
-                    std::vector<uint8_t>* /*out_serialized_reply_proto*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(RegisterSuspendDelayAsync,
-               void(const std::vector<uint8_t>& /*in_serialized_request_proto*/,
-                    const base::Callback<void(const std::vector<uint8_t>& /*serialized_reply_proto*/)>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(UnregisterSuspendDelay,
-               bool(const std::vector<uint8_t>& /*in_serialized_proto*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(UnregisterSuspendDelayAsync,
-               void(const std::vector<uint8_t>& /*in_serialized_proto*/,
-                    const base::Callback<void()>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(HandleSuspendReadiness,
-               bool(const std::vector<uint8_t>& /*in_serialized_proto*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(HandleSuspendReadinessAsync,
-               void(const std::vector<uint8_t>& /*in_serialized_proto*/,
-                    const base::Callback<void()>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(RegisterDarkSuspendDelay,
-               bool(const std::vector<uint8_t>& /*in_serialized_request_proto*/,
-                    std::vector<uint8_t>* /*out_serialized_reply_proto*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(RegisterDarkSuspendDelayAsync,
-               void(const std::vector<uint8_t>& /*in_serialized_request_proto*/,
-                    const base::Callback<void(const std::vector<uint8_t>& /*serialized_reply_proto*/)>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(UnregisterDarkSuspendDelay,
-               bool(const std::vector<uint8_t>& /*in_serialized_proto*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(UnregisterDarkSuspendDelayAsync,
-               void(const std::vector<uint8_t>& /*in_serialized_proto*/,
-                    const base::Callback<void()>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(HandleDarkSuspendReadiness,
-               bool(const std::vector<uint8_t>& /*in_serialized_proto*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(HandleDarkSuspendReadinessAsync,
-               void(const std::vector<uint8_t>& /*in_serialized_proto*/,
-                    const base::Callback<void()>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(RecordDarkResumeWakeReason,
-               bool(const std::vector<uint8_t>& /*in_serialized_proto*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(RecordDarkResumeWakeReasonAsync,
-               void(const std::vector<uint8_t>& /*in_serialized_proto*/,
-                    const base::Callback<void()>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD2(RegisterBrightnessChangedSignalHandler,
-               void(const base::Callback<void(int32_t,
-                                              bool)>& /*signal_callback*/,
-                    dbus::ObjectProxy::OnConnectedCallback /*on_connected_callback*/));
-  MOCK_METHOD2(RegisterKeyboardBrightnessChangedSignalHandler,
-               void(const base::Callback<void(int32_t,
-                                              bool)>& /*signal_callback*/,
-                    dbus::ObjectProxy::OnConnectedCallback /*on_connected_callback*/));
-  MOCK_METHOD2(RegisterPeripheralBatteryStatusSignalHandler,
-               void(const base::Callback<void(const std::vector<uint8_t>&)>& /*signal_callback*/,
-                    dbus::ObjectProxy::OnConnectedCallback /*on_connected_callback*/));
-  MOCK_METHOD2(RegisterPowerSupplyPollSignalHandler,
-               void(const base::Callback<void(const std::vector<uint8_t>&)>& /*signal_callback*/,
-                    dbus::ObjectProxy::OnConnectedCallback /*on_connected_callback*/));
-  MOCK_METHOD2(RegisterSuspendImminentSignalHandler,
-               void(const base::Callback<void(const std::vector<uint8_t>&)>& /*signal_callback*/,
-                    dbus::ObjectProxy::OnConnectedCallback /*on_connected_callback*/));
-  MOCK_METHOD2(RegisterSuspendDoneSignalHandler,
-               void(const base::Callback<void(const std::vector<uint8_t>&)>& /*signal_callback*/,
-                    dbus::ObjectProxy::OnConnectedCallback /*on_connected_callback*/));
-  MOCK_METHOD2(RegisterDarkSuspendImminentSignalHandler,
-               void(const base::Callback<void(const std::vector<uint8_t>&)>& /*signal_callback*/,
-                    dbus::ObjectProxy::OnConnectedCallback /*on_connected_callback*/));
-  MOCK_METHOD2(RegisterInputEventSignalHandler,
-               void(const base::Callback<void(const std::vector<uint8_t>&)>& /*signal_callback*/,
-                    dbus::ObjectProxy::OnConnectedCallback /*on_connected_callback*/));
-  MOCK_METHOD2(RegisterIdleActionImminentSignalHandler,
-               void(const base::Callback<void(const std::vector<uint8_t>&)>& /*signal_callback*/,
-                    dbus::ObjectProxy::OnConnectedCallback /*on_connected_callback*/));
-  MOCK_METHOD2(RegisterIdleActionDeferredSignalHandler,
-               void(const base::Closure& /*signal_callback*/,
-                    dbus::ObjectProxy::OnConnectedCallback /*on_connected_callback*/));
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(PowerManagerProxyMock);
-};
-}  // namespace chromium
-}  // namespace org
-
-#endif  // ____CHROMEOS_DBUS_BINDING____________________BUILD_LINK_TMP_PORTAGE_CHROMEOS_BASE_POWER_MANAGER_9999_WORK_BUILD_OUT_DEFAULT_GEN_INCLUDE_POWER_MANAGER_DBUS_PROXY_MOCKS_H
diff --git a/include/session_manager/dbus-proxies.h b/include/session_manager/dbus-proxies.h
deleted file mode 100644
index 2ca0128..0000000
--- a/include/session_manager/dbus-proxies.h
+++ /dev/null
@@ -1,1065 +0,0 @@
-// Automatic generation of D-Bus interfaces:
-//  - org.chromium.SessionManagerInterface
-#ifndef ____CHROMEOS_DBUS_BINDING____________________BUILD_LINK_VAR_CACHE_PORTAGE_CHROMEOS_BASE_CHROMEOS_LOGIN_OUT_DEFAULT_GEN_INCLUDE_SESSION_MANAGER_DBUS_PROXIES_H
-#define ____CHROMEOS_DBUS_BINDING____________________BUILD_LINK_VAR_CACHE_PORTAGE_CHROMEOS_BASE_CHROMEOS_LOGIN_OUT_DEFAULT_GEN_INCLUDE_SESSION_MANAGER_DBUS_PROXIES_H
-#include <memory>
-#include <string>
-#include <vector>
-
-#include <base/bind.h>
-#include <base/callback.h>
-#include <base/logging.h>
-#include <base/macros.h>
-#include <base/memory/ref_counted.h>
-#include <brillo/any.h>
-#include <brillo/dbus/dbus_method_invoker.h>
-#include <brillo/dbus/dbus_property.h>
-#include <brillo/dbus/dbus_signal_handler.h>
-#include <brillo/errors/error.h>
-#include <brillo/variant_dictionary.h>
-#include <dbus/bus.h>
-#include <dbus/message.h>
-#include <dbus/object_manager.h>
-#include <dbus/object_path.h>
-#include <dbus/object_proxy.h>
-
-namespace org {
-namespace chromium {
-
-// Abstract interface proxy for org::chromium::SessionManagerInterface.
-class SessionManagerInterfaceProxyInterface {
- public:
-  virtual ~SessionManagerInterfaceProxyInterface() = default;
-
-  virtual bool EmitLoginPromptVisible(
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  virtual void EmitLoginPromptVisibleAsync(
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  virtual bool EnableChromeTesting(
-      bool in_force_relaunch,
-      const std::vector<std::string>& in_extra_arguments,
-      std::string* out_filepath,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  virtual void EnableChromeTestingAsync(
-      bool in_force_relaunch,
-      const std::vector<std::string>& in_extra_arguments,
-      const base::Callback<void(const std::string& /*filepath*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  virtual bool StartSession(
-      const std::string& in_email_address,
-      const std::string& in_unique_identifier,
-      bool* out_done,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  virtual void StartSessionAsync(
-      const std::string& in_email_address,
-      const std::string& in_unique_identifier,
-      const base::Callback<void(bool /*done*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  virtual bool StopSession(
-      const std::string& in_unique_identifier,
-      bool* out_done,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  virtual void StopSessionAsync(
-      const std::string& in_unique_identifier,
-      const base::Callback<void(bool /*done*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  virtual bool StorePolicy(
-      const std::vector<uint8_t>& in_policy_blob,
-      bool* out_done,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  virtual void StorePolicyAsync(
-      const std::vector<uint8_t>& in_policy_blob,
-      const base::Callback<void(bool /*done*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  virtual bool RetrievePolicy(
-      std::vector<uint8_t>* out_policy_blob,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  virtual void RetrievePolicyAsync(
-      const base::Callback<void(const std::vector<uint8_t>& /*policy_blob*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  virtual bool StorePolicyForUser(
-      const std::string& in_user_email,
-      const std::vector<uint8_t>& in_policy_blob,
-      bool* out_done,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  virtual void StorePolicyForUserAsync(
-      const std::string& in_user_email,
-      const std::vector<uint8_t>& in_policy_blob,
-      const base::Callback<void(bool /*done*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  virtual bool RetrievePolicyForUser(
-      const std::string& in_user_email,
-      std::vector<uint8_t>* out_policy_blob,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  virtual void RetrievePolicyForUserAsync(
-      const std::string& in_user_email,
-      const base::Callback<void(const std::vector<uint8_t>& /*policy_blob*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  virtual bool StoreDeviceLocalAccountPolicy(
-      const std::string& in_account_id,
-      const std::vector<uint8_t>& in_policy_blob,
-      bool* out_done,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  virtual void StoreDeviceLocalAccountPolicyAsync(
-      const std::string& in_account_id,
-      const std::vector<uint8_t>& in_policy_blob,
-      const base::Callback<void(bool /*done*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  virtual bool RetrieveDeviceLocalAccountPolicy(
-      const std::string& in_account_id,
-      std::vector<uint8_t>* out_policy_blob,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  virtual void RetrieveDeviceLocalAccountPolicyAsync(
-      const std::string& in_account_id,
-      const base::Callback<void(const std::vector<uint8_t>& /*policy_blob*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  virtual bool RetrieveSessionState(
-      std::string* out_state,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  virtual void RetrieveSessionStateAsync(
-      const base::Callback<void(const std::string& /*state*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  virtual bool RetrieveActiveSessions(
-      std::map<std::string, std::string>* out_sessions,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  virtual void RetrieveActiveSessionsAsync(
-      const base::Callback<void(const std::map<std::string, std::string>& /*sessions*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  virtual bool HandleSupervisedUserCreationStarting(
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  virtual void HandleSupervisedUserCreationStartingAsync(
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  virtual bool HandleSupervisedUserCreationFinished(
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  virtual void HandleSupervisedUserCreationFinishedAsync(
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  virtual bool LockScreen(
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  virtual void LockScreenAsync(
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  virtual bool HandleLockScreenShown(
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  virtual void HandleLockScreenShownAsync(
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  virtual bool HandleLockScreenDismissed(
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  virtual void HandleLockScreenDismissedAsync(
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  virtual bool RestartJob(
-      const dbus::FileDescriptor& in_cred_fd,
-      const std::vector<std::string>& in_argv,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  virtual void RestartJobAsync(
-      const dbus::FileDescriptor& in_cred_fd,
-      const std::vector<std::string>& in_argv,
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  virtual bool StartDeviceWipe(
-      bool* out_done,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  virtual void StartDeviceWipeAsync(
-      const base::Callback<void(bool /*done*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  virtual bool SetFlagsForUser(
-      const std::string& in_user_email,
-      const std::vector<std::string>& in_flags,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  virtual void SetFlagsForUserAsync(
-      const std::string& in_user_email,
-      const std::vector<std::string>& in_flags,
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  virtual bool GetServerBackedStateKeys(
-      std::vector<std::vector<uint8_t>>* out_state_keys,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  virtual void GetServerBackedStateKeysAsync(
-      const base::Callback<void(const std::vector<std::vector<uint8_t>>& /*state_keys*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  virtual bool InitMachineInfo(
-      const std::string& in_data,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  virtual void InitMachineInfoAsync(
-      const std::string& in_data,
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) = 0;
-
-  virtual void RegisterLoginPromptVisibleSignalHandler(
-      const base::Closure& signal_callback,
-      dbus::ObjectProxy::OnConnectedCallback on_connected_callback) = 0;
-
-  virtual void RegisterSessionStateChangedSignalHandler(
-      const base::Callback<void(const std::string&)>& signal_callback,
-      dbus::ObjectProxy::OnConnectedCallback on_connected_callback) = 0;
-
-  virtual void RegisterSetOwnerKeyCompleteSignalHandler(
-      const base::Callback<void(const std::string&)>& signal_callback,
-      dbus::ObjectProxy::OnConnectedCallback on_connected_callback) = 0;
-
-  virtual void RegisterPropertyChangeCompleteSignalHandler(
-      const base::Callback<void(const std::string&)>& signal_callback,
-      dbus::ObjectProxy::OnConnectedCallback on_connected_callback) = 0;
-
-  virtual void RegisterScreenIsLockedSignalHandler(
-      const base::Closure& signal_callback,
-      dbus::ObjectProxy::OnConnectedCallback on_connected_callback) = 0;
-
-  virtual void RegisterScreenIsUnlockedSignalHandler(
-      const base::Closure& signal_callback,
-      dbus::ObjectProxy::OnConnectedCallback on_connected_callback) = 0;
-};
-
-}  // namespace chromium
-}  // namespace org
-
-namespace org {
-namespace chromium {
-
-// Interface proxy for org::chromium::SessionManagerInterface.
-class SessionManagerInterfaceProxy final : public SessionManagerInterfaceProxyInterface {
- public:
-  SessionManagerInterfaceProxy(const scoped_refptr<dbus::Bus>& bus) :
-      bus_{bus},
-      dbus_object_proxy_{
-          bus_->GetObjectProxy(service_name_, object_path_)} {
-  }
-
-  ~SessionManagerInterfaceProxy() override {
-    bus_->RemoveObjectProxy(
-        service_name_, object_path_, base::Bind(&base::DoNothing));
-  }
-
-  void RegisterLoginPromptVisibleSignalHandler(
-      const base::Closure& signal_callback,
-      dbus::ObjectProxy::OnConnectedCallback on_connected_callback) override {
-    brillo::dbus_utils::ConnectToSignal(
-        dbus_object_proxy_,
-        "org.chromium.SessionManagerInterface",
-        "LoginPromptVisible",
-        signal_callback,
-        on_connected_callback);
-  }
-
-  void RegisterSessionStateChangedSignalHandler(
-      const base::Callback<void(const std::string&)>& signal_callback,
-      dbus::ObjectProxy::OnConnectedCallback on_connected_callback) override {
-    brillo::dbus_utils::ConnectToSignal(
-        dbus_object_proxy_,
-        "org.chromium.SessionManagerInterface",
-        "SessionStateChanged",
-        signal_callback,
-        on_connected_callback);
-  }
-
-  void RegisterSetOwnerKeyCompleteSignalHandler(
-      const base::Callback<void(const std::string&)>& signal_callback,
-      dbus::ObjectProxy::OnConnectedCallback on_connected_callback) override {
-    brillo::dbus_utils::ConnectToSignal(
-        dbus_object_proxy_,
-        "org.chromium.SessionManagerInterface",
-        "SetOwnerKeyComplete",
-        signal_callback,
-        on_connected_callback);
-  }
-
-  void RegisterPropertyChangeCompleteSignalHandler(
-      const base::Callback<void(const std::string&)>& signal_callback,
-      dbus::ObjectProxy::OnConnectedCallback on_connected_callback) override {
-    brillo::dbus_utils::ConnectToSignal(
-        dbus_object_proxy_,
-        "org.chromium.SessionManagerInterface",
-        "PropertyChangeComplete",
-        signal_callback,
-        on_connected_callback);
-  }
-
-  void RegisterScreenIsLockedSignalHandler(
-      const base::Closure& signal_callback,
-      dbus::ObjectProxy::OnConnectedCallback on_connected_callback) override {
-    brillo::dbus_utils::ConnectToSignal(
-        dbus_object_proxy_,
-        "org.chromium.SessionManagerInterface",
-        "ScreenIsLocked",
-        signal_callback,
-        on_connected_callback);
-  }
-
-  void RegisterScreenIsUnlockedSignalHandler(
-      const base::Closure& signal_callback,
-      dbus::ObjectProxy::OnConnectedCallback on_connected_callback) override {
-    brillo::dbus_utils::ConnectToSignal(
-        dbus_object_proxy_,
-        "org.chromium.SessionManagerInterface",
-        "ScreenIsUnlocked",
-        signal_callback,
-        on_connected_callback);
-  }
-
-  void ReleaseObjectProxy(const base::Closure& callback) {
-    bus_->RemoveObjectProxy(service_name_, object_path_, callback);
-  }
-
-  const dbus::ObjectPath& GetObjectPath() const {
-    return object_path_;
-  }
-
-  dbus::ObjectProxy* GetObjectProxy() const { return dbus_object_proxy_; }
-
-  bool EmitLoginPromptVisible(
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.SessionManagerInterface",
-        "EmitLoginPromptVisible",
-        error);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error);
-  }
-
-  void EmitLoginPromptVisibleAsync(
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.SessionManagerInterface",
-        "EmitLoginPromptVisible",
-        success_callback,
-        error_callback);
-  }
-
-  bool EnableChromeTesting(
-      bool in_force_relaunch,
-      const std::vector<std::string>& in_extra_arguments,
-      std::string* out_filepath,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.SessionManagerInterface",
-        "EnableChromeTesting",
-        error,
-        in_force_relaunch,
-        in_extra_arguments);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error, out_filepath);
-  }
-
-  void EnableChromeTestingAsync(
-      bool in_force_relaunch,
-      const std::vector<std::string>& in_extra_arguments,
-      const base::Callback<void(const std::string& /*filepath*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.SessionManagerInterface",
-        "EnableChromeTesting",
-        success_callback,
-        error_callback,
-        in_force_relaunch,
-        in_extra_arguments);
-  }
-
-  bool StartSession(
-      const std::string& in_email_address,
-      const std::string& in_unique_identifier,
-      bool* out_done,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.SessionManagerInterface",
-        "StartSession",
-        error,
-        in_email_address,
-        in_unique_identifier);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error, out_done);
-  }
-
-  void StartSessionAsync(
-      const std::string& in_email_address,
-      const std::string& in_unique_identifier,
-      const base::Callback<void(bool /*done*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.SessionManagerInterface",
-        "StartSession",
-        success_callback,
-        error_callback,
-        in_email_address,
-        in_unique_identifier);
-  }
-
-  bool StopSession(
-      const std::string& in_unique_identifier,
-      bool* out_done,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.SessionManagerInterface",
-        "StopSession",
-        error,
-        in_unique_identifier);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error, out_done);
-  }
-
-  void StopSessionAsync(
-      const std::string& in_unique_identifier,
-      const base::Callback<void(bool /*done*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.SessionManagerInterface",
-        "StopSession",
-        success_callback,
-        error_callback,
-        in_unique_identifier);
-  }
-
-  bool StorePolicy(
-      const std::vector<uint8_t>& in_policy_blob,
-      bool* out_done,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.SessionManagerInterface",
-        "StorePolicy",
-        error,
-        in_policy_blob);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error, out_done);
-  }
-
-  void StorePolicyAsync(
-      const std::vector<uint8_t>& in_policy_blob,
-      const base::Callback<void(bool /*done*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.SessionManagerInterface",
-        "StorePolicy",
-        success_callback,
-        error_callback,
-        in_policy_blob);
-  }
-
-  bool RetrievePolicy(
-      std::vector<uint8_t>* out_policy_blob,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.SessionManagerInterface",
-        "RetrievePolicy",
-        error);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error, out_policy_blob);
-  }
-
-  void RetrievePolicyAsync(
-      const base::Callback<void(const std::vector<uint8_t>& /*policy_blob*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.SessionManagerInterface",
-        "RetrievePolicy",
-        success_callback,
-        error_callback);
-  }
-
-  bool StorePolicyForUser(
-      const std::string& in_user_email,
-      const std::vector<uint8_t>& in_policy_blob,
-      bool* out_done,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.SessionManagerInterface",
-        "StorePolicyForUser",
-        error,
-        in_user_email,
-        in_policy_blob);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error, out_done);
-  }
-
-  void StorePolicyForUserAsync(
-      const std::string& in_user_email,
-      const std::vector<uint8_t>& in_policy_blob,
-      const base::Callback<void(bool /*done*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.SessionManagerInterface",
-        "StorePolicyForUser",
-        success_callback,
-        error_callback,
-        in_user_email,
-        in_policy_blob);
-  }
-
-  bool RetrievePolicyForUser(
-      const std::string& in_user_email,
-      std::vector<uint8_t>* out_policy_blob,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.SessionManagerInterface",
-        "RetrievePolicyForUser",
-        error,
-        in_user_email);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error, out_policy_blob);
-  }
-
-  void RetrievePolicyForUserAsync(
-      const std::string& in_user_email,
-      const base::Callback<void(const std::vector<uint8_t>& /*policy_blob*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.SessionManagerInterface",
-        "RetrievePolicyForUser",
-        success_callback,
-        error_callback,
-        in_user_email);
-  }
-
-  bool StoreDeviceLocalAccountPolicy(
-      const std::string& in_account_id,
-      const std::vector<uint8_t>& in_policy_blob,
-      bool* out_done,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.SessionManagerInterface",
-        "StoreDeviceLocalAccountPolicy",
-        error,
-        in_account_id,
-        in_policy_blob);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error, out_done);
-  }
-
-  void StoreDeviceLocalAccountPolicyAsync(
-      const std::string& in_account_id,
-      const std::vector<uint8_t>& in_policy_blob,
-      const base::Callback<void(bool /*done*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.SessionManagerInterface",
-        "StoreDeviceLocalAccountPolicy",
-        success_callback,
-        error_callback,
-        in_account_id,
-        in_policy_blob);
-  }
-
-  bool RetrieveDeviceLocalAccountPolicy(
-      const std::string& in_account_id,
-      std::vector<uint8_t>* out_policy_blob,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.SessionManagerInterface",
-        "RetrieveDeviceLocalAccountPolicy",
-        error,
-        in_account_id);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error, out_policy_blob);
-  }
-
-  void RetrieveDeviceLocalAccountPolicyAsync(
-      const std::string& in_account_id,
-      const base::Callback<void(const std::vector<uint8_t>& /*policy_blob*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.SessionManagerInterface",
-        "RetrieveDeviceLocalAccountPolicy",
-        success_callback,
-        error_callback,
-        in_account_id);
-  }
-
-  bool RetrieveSessionState(
-      std::string* out_state,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.SessionManagerInterface",
-        "RetrieveSessionState",
-        error);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error, out_state);
-  }
-
-  void RetrieveSessionStateAsync(
-      const base::Callback<void(const std::string& /*state*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.SessionManagerInterface",
-        "RetrieveSessionState",
-        success_callback,
-        error_callback);
-  }
-
-  bool RetrieveActiveSessions(
-      std::map<std::string, std::string>* out_sessions,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.SessionManagerInterface",
-        "RetrieveActiveSessions",
-        error);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error, out_sessions);
-  }
-
-  void RetrieveActiveSessionsAsync(
-      const base::Callback<void(const std::map<std::string, std::string>& /*sessions*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.SessionManagerInterface",
-        "RetrieveActiveSessions",
-        success_callback,
-        error_callback);
-  }
-
-  bool HandleSupervisedUserCreationStarting(
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.SessionManagerInterface",
-        "HandleSupervisedUserCreationStarting",
-        error);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error);
-  }
-
-  void HandleSupervisedUserCreationStartingAsync(
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.SessionManagerInterface",
-        "HandleSupervisedUserCreationStarting",
-        success_callback,
-        error_callback);
-  }
-
-  bool HandleSupervisedUserCreationFinished(
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.SessionManagerInterface",
-        "HandleSupervisedUserCreationFinished",
-        error);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error);
-  }
-
-  void HandleSupervisedUserCreationFinishedAsync(
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.SessionManagerInterface",
-        "HandleSupervisedUserCreationFinished",
-        success_callback,
-        error_callback);
-  }
-
-  bool LockScreen(
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.SessionManagerInterface",
-        "LockScreen",
-        error);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error);
-  }
-
-  void LockScreenAsync(
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.SessionManagerInterface",
-        "LockScreen",
-        success_callback,
-        error_callback);
-  }
-
-  bool HandleLockScreenShown(
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.SessionManagerInterface",
-        "HandleLockScreenShown",
-        error);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error);
-  }
-
-  void HandleLockScreenShownAsync(
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.SessionManagerInterface",
-        "HandleLockScreenShown",
-        success_callback,
-        error_callback);
-  }
-
-  bool HandleLockScreenDismissed(
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.SessionManagerInterface",
-        "HandleLockScreenDismissed",
-        error);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error);
-  }
-
-  void HandleLockScreenDismissedAsync(
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.SessionManagerInterface",
-        "HandleLockScreenDismissed",
-        success_callback,
-        error_callback);
-  }
-
-  bool RestartJob(
-      const dbus::FileDescriptor& in_cred_fd,
-      const std::vector<std::string>& in_argv,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.SessionManagerInterface",
-        "RestartJob",
-        error,
-        in_cred_fd,
-        in_argv);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error);
-  }
-
-  void RestartJobAsync(
-      const dbus::FileDescriptor& in_cred_fd,
-      const std::vector<std::string>& in_argv,
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.SessionManagerInterface",
-        "RestartJob",
-        success_callback,
-        error_callback,
-        in_cred_fd,
-        in_argv);
-  }
-
-  bool StartDeviceWipe(
-      bool* out_done,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.SessionManagerInterface",
-        "StartDeviceWipe",
-        error);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error, out_done);
-  }
-
-  void StartDeviceWipeAsync(
-      const base::Callback<void(bool /*done*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.SessionManagerInterface",
-        "StartDeviceWipe",
-        success_callback,
-        error_callback);
-  }
-
-  bool SetFlagsForUser(
-      const std::string& in_user_email,
-      const std::vector<std::string>& in_flags,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.SessionManagerInterface",
-        "SetFlagsForUser",
-        error,
-        in_user_email,
-        in_flags);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error);
-  }
-
-  void SetFlagsForUserAsync(
-      const std::string& in_user_email,
-      const std::vector<std::string>& in_flags,
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.SessionManagerInterface",
-        "SetFlagsForUser",
-        success_callback,
-        error_callback,
-        in_user_email,
-        in_flags);
-  }
-
-  bool GetServerBackedStateKeys(
-      std::vector<std::vector<uint8_t>>* out_state_keys,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.SessionManagerInterface",
-        "GetServerBackedStateKeys",
-        error);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error, out_state_keys);
-  }
-
-  void GetServerBackedStateKeysAsync(
-      const base::Callback<void(const std::vector<std::vector<uint8_t>>& /*state_keys*/)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.SessionManagerInterface",
-        "GetServerBackedStateKeys",
-        success_callback,
-        error_callback);
-  }
-
-  bool InitMachineInfo(
-      const std::string& in_data,
-      brillo::ErrorPtr* error,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    auto response = brillo::dbus_utils::CallMethodAndBlockWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.SessionManagerInterface",
-        "InitMachineInfo",
-        error,
-        in_data);
-    return response && brillo::dbus_utils::ExtractMethodCallResults(
-        response.get(), error);
-  }
-
-  void InitMachineInfoAsync(
-      const std::string& in_data,
-      const base::Callback<void()>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback,
-      int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) override {
-    brillo::dbus_utils::CallMethodWithTimeout(
-        timeout_ms,
-        dbus_object_proxy_,
-        "org.chromium.SessionManagerInterface",
-        "InitMachineInfo",
-        success_callback,
-        error_callback,
-        in_data);
-  }
-
- private:
-  scoped_refptr<dbus::Bus> bus_;
-  const std::string service_name_{"org.chromium.SessionManager"};
-  const dbus::ObjectPath object_path_{"/org/chromium/SessionManager"};
-  dbus::ObjectProxy* dbus_object_proxy_;
-
-  DISALLOW_COPY_AND_ASSIGN(SessionManagerInterfaceProxy);
-};
-
-}  // namespace chromium
-}  // namespace org
-
-#endif  // ____CHROMEOS_DBUS_BINDING____________________BUILD_LINK_VAR_CACHE_PORTAGE_CHROMEOS_BASE_CHROMEOS_LOGIN_OUT_DEFAULT_GEN_INCLUDE_SESSION_MANAGER_DBUS_PROXIES_H
diff --git a/include/session_manager/dbus-proxy-mocks.h b/include/session_manager/dbus-proxy-mocks.h
deleted file mode 100644
index 2b6ce4d..0000000
--- a/include/session_manager/dbus-proxy-mocks.h
+++ /dev/null
@@ -1,252 +0,0 @@
-// Automatic generation of D-Bus interface mock proxies for:
-//  - org.chromium.SessionManagerInterface
-#ifndef ____CHROMEOS_DBUS_BINDING____________________BUILD_LINK_VAR_CACHE_PORTAGE_CHROMEOS_BASE_CHROMEOS_LOGIN_OUT_DEFAULT_GEN_INCLUDE_SESSION_MANAGER_DBUS_PROXY_MOCKS_H
-#define ____CHROMEOS_DBUS_BINDING____________________BUILD_LINK_VAR_CACHE_PORTAGE_CHROMEOS_BASE_CHROMEOS_LOGIN_OUT_DEFAULT_GEN_INCLUDE_SESSION_MANAGER_DBUS_PROXY_MOCKS_H
-#include <string>
-#include <vector>
-
-#include <base/callback_forward.h>
-#include <base/logging.h>
-#include <base/macros.h>
-#include <brillo/any.h>
-#include <brillo/errors/error.h>
-#include <brillo/variant_dictionary.h>
-#include <gmock/gmock.h>
-
-#include "session_manager/dbus-proxies.h"
-
-namespace org {
-namespace chromium {
-
-// Mock object for SessionManagerInterfaceProxyInterface.
-class SessionManagerInterfaceProxyMock : public SessionManagerInterfaceProxyInterface {
- public:
-  SessionManagerInterfaceProxyMock() = default;
-
-  MOCK_METHOD2(EmitLoginPromptVisible,
-               bool(brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(EmitLoginPromptVisibleAsync,
-               void(const base::Callback<void()>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD5(EnableChromeTesting,
-               bool(bool /*in_force_relaunch*/,
-                    const std::vector<std::string>& /*in_extra_arguments*/,
-                    std::string* /*out_filepath*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD5(EnableChromeTestingAsync,
-               void(bool /*in_force_relaunch*/,
-                    const std::vector<std::string>& /*in_extra_arguments*/,
-                    const base::Callback<void(const std::string& /*filepath*/)>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD5(StartSession,
-               bool(const std::string& /*in_email_address*/,
-                    const std::string& /*in_unique_identifier*/,
-                    bool* /*out_done*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD5(StartSessionAsync,
-               void(const std::string& /*in_email_address*/,
-                    const std::string& /*in_unique_identifier*/,
-                    const base::Callback<void(bool /*done*/)>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(StopSession,
-               bool(const std::string& /*in_unique_identifier*/,
-                    bool* /*out_done*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(StopSessionAsync,
-               void(const std::string& /*in_unique_identifier*/,
-                    const base::Callback<void(bool /*done*/)>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(StorePolicy,
-               bool(const std::vector<uint8_t>& /*in_policy_blob*/,
-                    bool* /*out_done*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(StorePolicyAsync,
-               void(const std::vector<uint8_t>& /*in_policy_blob*/,
-                    const base::Callback<void(bool /*done*/)>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(RetrievePolicy,
-               bool(std::vector<uint8_t>* /*out_policy_blob*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(RetrievePolicyAsync,
-               void(const base::Callback<void(const std::vector<uint8_t>& /*policy_blob*/)>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD5(StorePolicyForUser,
-               bool(const std::string& /*in_user_email*/,
-                    const std::vector<uint8_t>& /*in_policy_blob*/,
-                    bool* /*out_done*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD5(StorePolicyForUserAsync,
-               void(const std::string& /*in_user_email*/,
-                    const std::vector<uint8_t>& /*in_policy_blob*/,
-                    const base::Callback<void(bool /*done*/)>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(RetrievePolicyForUser,
-               bool(const std::string& /*in_user_email*/,
-                    std::vector<uint8_t>* /*out_policy_blob*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(RetrievePolicyForUserAsync,
-               void(const std::string& /*in_user_email*/,
-                    const base::Callback<void(const std::vector<uint8_t>& /*policy_blob*/)>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD5(StoreDeviceLocalAccountPolicy,
-               bool(const std::string& /*in_account_id*/,
-                    const std::vector<uint8_t>& /*in_policy_blob*/,
-                    bool* /*out_done*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD5(StoreDeviceLocalAccountPolicyAsync,
-               void(const std::string& /*in_account_id*/,
-                    const std::vector<uint8_t>& /*in_policy_blob*/,
-                    const base::Callback<void(bool /*done*/)>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(RetrieveDeviceLocalAccountPolicy,
-               bool(const std::string& /*in_account_id*/,
-                    std::vector<uint8_t>* /*out_policy_blob*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(RetrieveDeviceLocalAccountPolicyAsync,
-               void(const std::string& /*in_account_id*/,
-                    const base::Callback<void(const std::vector<uint8_t>& /*policy_blob*/)>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(RetrieveSessionState,
-               bool(std::string* /*out_state*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(RetrieveSessionStateAsync,
-               void(const base::Callback<void(const std::string& /*state*/)>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(RetrieveActiveSessions,
-               bool(std::map<std::string, std::string>* /*out_sessions*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(RetrieveActiveSessionsAsync,
-               void(const base::Callback<void(const std::map<std::string, std::string>& /*sessions*/)>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD2(HandleSupervisedUserCreationStarting,
-               bool(brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(HandleSupervisedUserCreationStartingAsync,
-               void(const base::Callback<void()>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD2(HandleSupervisedUserCreationFinished,
-               bool(brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(HandleSupervisedUserCreationFinishedAsync,
-               void(const base::Callback<void()>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD2(LockScreen,
-               bool(brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(LockScreenAsync,
-               void(const base::Callback<void()>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD2(HandleLockScreenShown,
-               bool(brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(HandleLockScreenShownAsync,
-               void(const base::Callback<void()>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD2(HandleLockScreenDismissed,
-               bool(brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(HandleLockScreenDismissedAsync,
-               void(const base::Callback<void()>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(RestartJob,
-               bool(const dbus::FileDescriptor& /*in_cred_fd*/,
-                    const std::vector<std::string>& /*in_argv*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD5(RestartJobAsync,
-               void(const dbus::FileDescriptor& /*in_cred_fd*/,
-                    const std::vector<std::string>& /*in_argv*/,
-                    const base::Callback<void()>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(StartDeviceWipe,
-               bool(bool* /*out_done*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(StartDeviceWipeAsync,
-               void(const base::Callback<void(bool /*done*/)>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(SetFlagsForUser,
-               bool(const std::string& /*in_user_email*/,
-                    const std::vector<std::string>& /*in_flags*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD5(SetFlagsForUserAsync,
-               void(const std::string& /*in_user_email*/,
-                    const std::vector<std::string>& /*in_flags*/,
-                    const base::Callback<void()>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(GetServerBackedStateKeys,
-               bool(std::vector<std::vector<uint8_t>>* /*out_state_keys*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(GetServerBackedStateKeysAsync,
-               void(const base::Callback<void(const std::vector<std::vector<uint8_t>>& /*state_keys*/)>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(InitMachineInfo,
-               bool(const std::string& /*in_data*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(InitMachineInfoAsync,
-               void(const std::string& /*in_data*/,
-                    const base::Callback<void()>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD2(RegisterLoginPromptVisibleSignalHandler,
-               void(const base::Closure& /*signal_callback*/,
-                    dbus::ObjectProxy::OnConnectedCallback /*on_connected_callback*/));
-  MOCK_METHOD2(RegisterSessionStateChangedSignalHandler,
-               void(const base::Callback<void(const std::string&)>& /*signal_callback*/,
-                    dbus::ObjectProxy::OnConnectedCallback /*on_connected_callback*/));
-  MOCK_METHOD2(RegisterSetOwnerKeyCompleteSignalHandler,
-               void(const base::Callback<void(const std::string&)>& /*signal_callback*/,
-                    dbus::ObjectProxy::OnConnectedCallback /*on_connected_callback*/));
-  MOCK_METHOD2(RegisterPropertyChangeCompleteSignalHandler,
-               void(const base::Callback<void(const std::string&)>& /*signal_callback*/,
-                    dbus::ObjectProxy::OnConnectedCallback /*on_connected_callback*/));
-  MOCK_METHOD2(RegisterScreenIsLockedSignalHandler,
-               void(const base::Closure& /*signal_callback*/,
-                    dbus::ObjectProxy::OnConnectedCallback /*on_connected_callback*/));
-  MOCK_METHOD2(RegisterScreenIsUnlockedSignalHandler,
-               void(const base::Closure& /*signal_callback*/,
-                    dbus::ObjectProxy::OnConnectedCallback /*on_connected_callback*/));
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(SessionManagerInterfaceProxyMock);
-};
-}  // namespace chromium
-}  // namespace org
-
-#endif  // ____CHROMEOS_DBUS_BINDING____________________BUILD_LINK_VAR_CACHE_PORTAGE_CHROMEOS_BASE_CHROMEOS_LOGIN_OUT_DEFAULT_GEN_INCLUDE_SESSION_MANAGER_DBUS_PROXY_MOCKS_H
diff --git a/include/shill/dbus-proxy-mocks.h b/include/shill/dbus-proxy-mocks.h
deleted file mode 100644
index e5d52f7..0000000
--- a/include/shill/dbus-proxy-mocks.h
+++ /dev/null
@@ -1,549 +0,0 @@
-// Automatic generation of D-Bus interface mock proxies for:
-//  - org.chromium.flimflam.Manager
-//  - org.chromium.flimflam.Service
-#ifndef ____CHROMEOS_DBUS_BINDING___UPDATE_ENGINE_INCLUDE_SHILL_DBUS_PROXY_MOCKS_H
-#define ____CHROMEOS_DBUS_BINDING___UPDATE_ENGINE_INCLUDE_SHILL_DBUS_PROXY_MOCKS_H
-#include <string>
-#include <vector>
-
-#include <base/callback_forward.h>
-#include <base/logging.h>
-#include <base/macros.h>
-#include <brillo/any.h>
-#include <brillo/errors/error.h>
-#include <brillo/variant_dictionary.h>
-#include <gmock/gmock.h>
-
-#include "shill/dbus-proxies.h"
-
-namespace org {
-namespace chromium {
-namespace flimflam {
-
-// Mock object for ManagerProxyInterface.
-class ManagerProxyMock : public ManagerProxyInterface {
- public:
-  ManagerProxyMock() = default;
-
-  MOCK_METHOD3(GetProperties,
-               bool(brillo::VariantDictionary*,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(GetPropertiesAsync,
-               void(const base::Callback<void(const brillo::VariantDictionary&)>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(SetProperty,
-               bool(const std::string&,
-                    const brillo::Any&,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD5(SetPropertyAsync,
-               void(const std::string&,
-                    const brillo::Any&,
-                    const base::Callback<void()>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(GetState,
-               bool(std::string*,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(GetStateAsync,
-               void(const base::Callback<void(const std::string&)>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(CreateProfile,
-               bool(const std::string&,
-                    dbus::ObjectPath*,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(CreateProfileAsync,
-               void(const std::string&,
-                    const base::Callback<void(const dbus::ObjectPath&)>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(RemoveProfile,
-               bool(const std::string&,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(RemoveProfileAsync,
-               void(const std::string&,
-                    const base::Callback<void()>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(PushProfile,
-               bool(const std::string&,
-                    dbus::ObjectPath*,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(PushProfileAsync,
-               void(const std::string&,
-                    const base::Callback<void(const dbus::ObjectPath&)>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD5(InsertUserProfile,
-               bool(const std::string&,
-                    const std::string&,
-                    dbus::ObjectPath*,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD5(InsertUserProfileAsync,
-               void(const std::string&,
-                    const std::string&,
-                    const base::Callback<void(const dbus::ObjectPath&)>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(PopProfile,
-               bool(const std::string&,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(PopProfileAsync,
-               void(const std::string&,
-                    const base::Callback<void()>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD2(PopAnyProfile,
-               bool(brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(PopAnyProfileAsync,
-               void(const base::Callback<void()>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD2(PopAllUserProfiles,
-               bool(brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(PopAllUserProfilesAsync,
-               void(const base::Callback<void()>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD2(RecheckPortal,
-               bool(brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(RecheckPortalAsync,
-               void(const base::Callback<void()>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(RequestScan,
-               bool(const std::string&,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(RequestScanAsync,
-               void(const std::string&,
-                    const base::Callback<void()>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(EnableTechnology,
-               bool(const std::string&,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(EnableTechnologyAsync,
-               void(const std::string&,
-                    const base::Callback<void()>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(DisableTechnology,
-               bool(const std::string&,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(DisableTechnologyAsync,
-               void(const std::string&,
-                    const base::Callback<void()>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(GetService,
-               bool(const brillo::VariantDictionary&,
-                    dbus::ObjectPath*,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(GetServiceAsync,
-               void(const brillo::VariantDictionary&,
-                    const base::Callback<void(const dbus::ObjectPath&)>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(GetWifiService,
-               bool(const brillo::VariantDictionary&,
-                    dbus::ObjectPath*,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(GetWifiServiceAsync,
-               void(const brillo::VariantDictionary&,
-                    const base::Callback<void(const dbus::ObjectPath&)>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(ConfigureService,
-               bool(const brillo::VariantDictionary&,
-                    dbus::ObjectPath*,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(ConfigureServiceAsync,
-               void(const brillo::VariantDictionary&,
-                    const base::Callback<void(const dbus::ObjectPath&)>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD5(ConfigureServiceForProfile,
-               bool(const dbus::ObjectPath&,
-                    const brillo::VariantDictionary&,
-                    dbus::ObjectPath*,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD5(ConfigureServiceForProfileAsync,
-               void(const dbus::ObjectPath&,
-                    const brillo::VariantDictionary&,
-                    const base::Callback<void(const dbus::ObjectPath&)>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(FindMatchingService,
-               bool(const brillo::VariantDictionary&,
-                    dbus::ObjectPath*,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(FindMatchingServiceAsync,
-               void(const brillo::VariantDictionary&,
-                    const base::Callback<void(const dbus::ObjectPath&)>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(GetVPNService,
-               bool(const brillo::VariantDictionary&,
-                    dbus::ObjectPath*,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(GetVPNServiceAsync,
-               void(const brillo::VariantDictionary&,
-                    const base::Callback<void(const dbus::ObjectPath&)>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(GetDebugLevel,
-               bool(int32_t*,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(GetDebugLevelAsync,
-               void(const base::Callback<void(int32_t)>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(SetDebugLevel,
-               bool(int32_t,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(SetDebugLevelAsync,
-               void(int32_t,
-                    const base::Callback<void()>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(GetServiceOrder,
-               bool(std::string*,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(GetServiceOrderAsync,
-               void(const base::Callback<void(const std::string&)>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(SetServiceOrder,
-               bool(const std::string&,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(SetServiceOrderAsync,
-               void(const std::string&,
-                    const base::Callback<void()>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(GetDebugTags,
-               bool(std::string*,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(GetDebugTagsAsync,
-               void(const base::Callback<void(const std::string&)>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(SetDebugTags,
-               bool(const std::string&,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(SetDebugTagsAsync,
-               void(const std::string&,
-                    const base::Callback<void()>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(ListDebugTags,
-               bool(std::string*,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(ListDebugTagsAsync,
-               void(const base::Callback<void(const std::string&)>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(GetNetworksForGeolocation,
-               bool(brillo::VariantDictionary*,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(GetNetworksForGeolocationAsync,
-               void(const base::Callback<void(const brillo::VariantDictionary&)>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD10(VerifyDestination,
-                bool(const std::string& /*in_certificate*/,
-                     const std::string& /*in_public_key*/,
-                     const std::string& /*in_nonce*/,
-                     const std::string& /*in_signed_data*/,
-                     const std::string& /*in_destination_udn*/,
-                     const std::string& /*in_hotspot_ssid*/,
-                     const std::string& /*in_hotspot_bssid*/,
-                     bool*,
-                     brillo::ErrorPtr* /*error*/,
-                     int /*timeout_ms*/));
-  MOCK_METHOD10(VerifyDestinationAsync,
-                void(const std::string& /*in_certificate*/,
-                     const std::string& /*in_public_key*/,
-                     const std::string& /*in_nonce*/,
-                     const std::string& /*in_signed_data*/,
-                     const std::string& /*in_destination_udn*/,
-                     const std::string& /*in_hotspot_ssid*/,
-                     const std::string& /*in_hotspot_bssid*/,
-                     const base::Callback<void(bool)>& /*success_callback*/,
-                     const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                     int /*timeout_ms*/));
-  bool VerifyAndEncryptCredentials(const std::string& /*in_certificate*/,
-                                   const std::string& /*in_public_key*/,
-                                   const std::string& /*in_nonce*/,
-                                   const std::string& /*in_signed_data*/,
-                                   const std::string& /*in_destination_udn*/,
-                                   const std::string& /*in_hotspot_ssid*/,
-                                   const std::string& /*in_hotspot_bssid*/,
-                                   const dbus::ObjectPath& /*in_network*/,
-                                   std::string*,
-                                   brillo::ErrorPtr* /*error*/,
-                                   int /*timeout_ms*/) override {
-    LOG(WARNING) << "VerifyAndEncryptCredentials(): gmock can't handle methods with 11 arguments. You can override this method in a subclass if you need to.";
-    return false;
-  }
-  void VerifyAndEncryptCredentialsAsync(const std::string& /*in_certificate*/,
-                                        const std::string& /*in_public_key*/,
-                                        const std::string& /*in_nonce*/,
-                                        const std::string& /*in_signed_data*/,
-                                        const std::string& /*in_destination_udn*/,
-                                        const std::string& /*in_hotspot_ssid*/,
-                                        const std::string& /*in_hotspot_bssid*/,
-                                        const dbus::ObjectPath& /*in_network*/,
-                                        const base::Callback<void(const std::string&)>& /*success_callback*/,
-                                        const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                                        int /*timeout_ms*/) override {
-    LOG(WARNING) << "VerifyAndEncryptCredentialsAsync(): gmock can't handle methods with 11 arguments. You can override this method in a subclass if you need to.";
-  }
-  bool VerifyAndEncryptData(const std::string& /*in_certificate*/,
-                            const std::string& /*in_public_key*/,
-                            const std::string& /*in_nonce*/,
-                            const std::string& /*in_signed_data*/,
-                            const std::string& /*in_destination_udn*/,
-                            const std::string& /*in_hotspot_ssid*/,
-                            const std::string& /*in_hotspot_bssid*/,
-                            const std::string& /*in_data*/,
-                            std::string*,
-                            brillo::ErrorPtr* /*error*/,
-                            int /*timeout_ms*/) override {
-    LOG(WARNING) << "VerifyAndEncryptData(): gmock can't handle methods with 11 arguments. You can override this method in a subclass if you need to.";
-    return false;
-  }
-  void VerifyAndEncryptDataAsync(const std::string& /*in_certificate*/,
-                                 const std::string& /*in_public_key*/,
-                                 const std::string& /*in_nonce*/,
-                                 const std::string& /*in_signed_data*/,
-                                 const std::string& /*in_destination_udn*/,
-                                 const std::string& /*in_hotspot_ssid*/,
-                                 const std::string& /*in_hotspot_bssid*/,
-                                 const std::string& /*in_data*/,
-                                 const base::Callback<void(const std::string&)>& /*success_callback*/,
-                                 const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                                 int /*timeout_ms*/) override {
-    LOG(WARNING) << "VerifyAndEncryptDataAsync(): gmock can't handle methods with 11 arguments. You can override this method in a subclass if you need to.";
-  }
-  MOCK_METHOD2(ConnectToBestServices,
-               bool(brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(ConnectToBestServicesAsync,
-               void(const base::Callback<void()>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD2(CreateConnectivityReport,
-               bool(brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(CreateConnectivityReportAsync,
-               void(const base::Callback<void()>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(ClaimInterface,
-               bool(const std::string& /*in_claimer_name*/,
-                    const std::string& /*in_interface_name*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD5(ClaimInterfaceAsync,
-               void(const std::string& /*in_claimer_name*/,
-                    const std::string& /*in_interface_name*/,
-                    const base::Callback<void()>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(ReleaseInterface,
-               bool(const std::string& /*in_claimer_name*/,
-                    const std::string& /*in_interface_name*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD5(ReleaseInterfaceAsync,
-               void(const std::string& /*in_claimer_name*/,
-                    const std::string& /*in_interface_name*/,
-                    const base::Callback<void()>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(SetSchedScan,
-               bool(bool,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(SetSchedScanAsync,
-               void(bool,
-                    const base::Callback<void()>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(SetupApModeInterface,
-               bool(std::string* /*out_interface_name*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(SetupApModeInterfaceAsync,
-               void(const base::Callback<void(const std::string& /*interface_name*/)>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(SetupStationModeInterface,
-               bool(std::string* /*out_interface_name*/,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(SetupStationModeInterfaceAsync,
-               void(const base::Callback<void(const std::string& /*interface_name*/)>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD2(RegisterPropertyChangedSignalHandler,
-               void(const base::Callback<void(const std::string&,
-                                              const brillo::Any&)>& /*signal_callback*/,
-                    dbus::ObjectProxy::OnConnectedCallback /*on_connected_callback*/));
-  MOCK_METHOD2(RegisterStateChangedSignalHandler,
-               void(const base::Callback<void(const std::string&)>& /*signal_callback*/,
-                    dbus::ObjectProxy::OnConnectedCallback /*on_connected_callback*/));
-  MOCK_CONST_METHOD0(GetObjectPath, const dbus::ObjectPath&());
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(ManagerProxyMock);
-};
-}  // namespace flimflam
-}  // namespace chromium
-}  // namespace org
-
-namespace org {
-namespace chromium {
-namespace flimflam {
-
-// Mock object for ServiceProxyInterface.
-class ServiceProxyMock : public ServiceProxyInterface {
- public:
-  ServiceProxyMock() = default;
-
-  MOCK_METHOD3(GetProperties,
-               bool(brillo::VariantDictionary*,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(GetPropertiesAsync,
-               void(const base::Callback<void(const brillo::VariantDictionary&)>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(SetProperty,
-               bool(const std::string&,
-                    const brillo::Any&,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD5(SetPropertyAsync,
-               void(const std::string&,
-                    const brillo::Any&,
-                    const base::Callback<void()>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(SetProperties,
-               bool(const brillo::VariantDictionary&,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(SetPropertiesAsync,
-               void(const brillo::VariantDictionary&,
-                    const base::Callback<void()>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(ClearProperty,
-               bool(const std::string&,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(ClearPropertyAsync,
-               void(const std::string&,
-                    const base::Callback<void()>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(ClearProperties,
-               bool(const std::vector<std::string>&,
-                    std::vector<bool>*,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(ClearPropertiesAsync,
-               void(const std::vector<std::string>&,
-                    const base::Callback<void(const std::vector<bool>&)>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD2(Connect,
-               bool(brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(ConnectAsync,
-               void(const base::Callback<void()>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD2(Disconnect,
-               bool(brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(DisconnectAsync,
-               void(const base::Callback<void()>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD2(Remove,
-               bool(brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(RemoveAsync,
-               void(const base::Callback<void()>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(ActivateCellularModem,
-               bool(const std::string&,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD4(ActivateCellularModemAsync,
-               void(const std::string&,
-                    const base::Callback<void()>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD2(CompleteCellularActivation,
-               bool(brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(CompleteCellularActivationAsync,
-               void(const base::Callback<void()>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(GetLoadableProfileEntries,
-               bool(std::map<dbus::ObjectPath, std::string>*,
-                    brillo::ErrorPtr* /*error*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD3(GetLoadableProfileEntriesAsync,
-               void(const base::Callback<void(const std::map<dbus::ObjectPath, std::string>&)>& /*success_callback*/,
-                    const base::Callback<void(brillo::Error*)>& /*error_callback*/,
-                    int /*timeout_ms*/));
-  MOCK_METHOD2(RegisterPropertyChangedSignalHandler,
-               void(const base::Callback<void(const std::string&,
-                                              const brillo::Any&)>& /*signal_callback*/,
-                    dbus::ObjectProxy::OnConnectedCallback /*on_connected_callback*/));
-  MOCK_CONST_METHOD0(GetObjectPath, const dbus::ObjectPath&());
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(ServiceProxyMock);
-};
-}  // namespace flimflam
-}  // namespace chromium
-}  // namespace org
-
-#endif  // ____CHROMEOS_DBUS_BINDING___UPDATE_ENGINE_INCLUDE_SHILL_DBUS_PROXY_MOCKS_H
diff --git a/include/update_includes.sh b/include/update_includes.sh
deleted file mode 100755
index 6008d59..0000000
--- a/include/update_includes.sh
+++ /dev/null
@@ -1,79 +0,0 @@
-#!/bin/bash
-
-#
-# 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.
-#
-
-DBUS_GENERATOR=$(which dbus-binding-generator)
-MY_DIR=$(dirname "$0")
-
-if [[ -z "${ANDROID_HOST_OUT}" ]]; then
-  echo "You must run envsetup.sh and lunch first." >&2
-  exit 1
-fi
-
-if [[ -z "${DBUS_GENERATOR}" ]]; then
-  echo "DBus bindings generator not found." >&2
-  exit 1
-fi
-
-set -e
-
-# generate <kind> <dir> <xml> [xml ...]
-# Generate a DBus proxy and/or proxy mock in the passed |dir| for the provided
-# |xml| service files.
-# The parameter |kind| determines whether it should generate the mock only
-# (mock), the proxy only (proxy) or both (both).
-generate() {
-  local kind="$1"
-  local dir="$2"
-  local xmls=("${@:3}")
-
-  mkdir -p "${MY_DIR}/${dir}"
-  local outdir=$(realpath "${MY_DIR}/${dir}")
-  local proxyh="${outdir}/dbus-proxies.h"
-  local mockh="${outdir}/dbus-proxy-mocks.h"
-
-  ${DBUS_GENERATOR} "${xmls[@]}" --mock="${mockh}" --proxy="${proxyh}"
-
-  # Fix the include path to the dbus-proxies.h to include ${dir}.
-  sed "s,include \"dbus-proxies.h\",include \"${dir}/dbus-proxies.h\"," \
-    -i "${mockh}"
-
-  # Fix the header guards to be independent from the checkout location.
-  local guard=$(realpath "${MY_DIR}/../.." | tr '[:lower:]/ ' '[:upper:]__')
-  for header in "${mockh}" "${proxyh}"; do
-    sed "s,___CHROMEOS_DBUS_BINDING__${guard},___CHROMEOS_DBUS_BINDING__," \
-      -i "${header}"
-  done
-
-  # Remove the files not requested.
-  if [[ "${kind}" ==  "mock" ]]; then
-    rm -f "${proxyh}"
-  elif [[ "${kind}" == "proxy" ]]; then
-    rm -f "${mockh}"
-  fi
-}
-
-UE_DIR=$(realpath "${MY_DIR}/..")
-SHILL_DIR=$(realpath "${UE_DIR}/../connectivity/shill")
-
-generate mock "libcros" \
-  "${UE_DIR}/dbus_bindings/org.chromium.LibCrosService.dbus-xml"
-
-generate mock "shill" \
-  "${SHILL_DIR}"/dbus_bindings/org.chromium.flimflam.{Manager,Service}.dbus-xml
-
-echo "Done."
diff --git a/common/libcurl_http_fetcher.cc b/libcurl_http_fetcher.cc
similarity index 89%
rename from common/libcurl_http_fetcher.cc
rename to libcurl_http_fetcher.cc
index a128fd8..eac6ea0 100644
--- a/common/libcurl_http_fetcher.cc
+++ b/libcurl_http_fetcher.cc
@@ -14,7 +14,10 @@
 // limitations under the License.
 //
 
-#include "update_engine/common/libcurl_http_fetcher.h"
+#include "update_engine/libcurl_http_fetcher.h"
+
+#include <sys/types.h>
+#include <unistd.h>
 
 #include <algorithm>
 #include <string>
@@ -26,7 +29,12 @@
 #include <base/strings/string_util.h>
 #include <base/strings/stringprintf.h>
 
-#include "update_engine/common/certificate_checker.h"
+#ifdef __ANDROID__
+#include <cutils/qtaguid.h>
+#include <private/android_filesystem_config.h>
+#endif  // __ANDROID__
+
+#include "update_engine/certificate_checker.h"
 #include "update_engine/common/hardware_interface.h"
 #include "update_engine/common/platform_constants.h"
 
@@ -41,9 +49,52 @@
 namespace chromeos_update_engine {
 
 namespace {
+
 const int kNoNetworkRetrySeconds = 10;
+
+// libcurl's CURLOPT_SOCKOPTFUNCTION callback function. Called after the socket
+// is created but before it is connected. This callback tags the created socket
+// so the network usage can be tracked in Android.
+int LibcurlSockoptCallback(void* /* clientp */,
+                           curl_socket_t curlfd,
+                           curlsocktype /* purpose */) {
+#ifdef __ANDROID__
+  // Socket tag used by all network sockets. See qtaguid kernel module for
+  // stats.
+  const int kUpdateEngineSocketTag = 0x55417243;  // "CrAU" in little-endian.
+  qtaguid_tagSocket(curlfd, kUpdateEngineSocketTag, AID_OTA_UPDATE);
+#endif  // __ANDROID__
+  return CURL_SOCKOPT_OK;
+}
+
 }  // namespace
 
+// static
+int LibcurlHttpFetcher::LibcurlCloseSocketCallback(void* clientp,
+                                                   curl_socket_t item) {
+#ifdef __ANDROID__
+  qtaguid_untagSocket(item);
+#endif  // __ANDROID__
+  LibcurlHttpFetcher* fetcher = static_cast<LibcurlHttpFetcher*>(clientp);
+  // Stop watching the socket before closing it.
+  for (size_t t = 0; t < arraysize(fetcher->fd_task_maps_); ++t) {
+    const auto fd_task_pair = fetcher->fd_task_maps_[t].find(item);
+    if (fd_task_pair != fetcher->fd_task_maps_[t].end()) {
+      if (!MessageLoop::current()->CancelTask(fd_task_pair->second)) {
+        LOG(WARNING) << "Error canceling the watch task "
+                     << fd_task_pair->second << " for "
+                     << (t ? "writing" : "reading") << " the fd " << item;
+      }
+      fetcher->fd_task_maps_[t].erase(item);
+    }
+  }
+
+  // Documentation for this callback says to return 0 on success or 1 on error.
+  if (!IGNORE_EINTR(close(item)))
+    return 0;
+  return 1;
+}
+
 LibcurlHttpFetcher::LibcurlHttpFetcher(ProxyResolver* proxy_resolver,
                                        HardwareInterface* hardware)
     : HttpFetcher(proxy_resolver), hardware_(hardware) {
@@ -58,6 +109,7 @@
 LibcurlHttpFetcher::~LibcurlHttpFetcher() {
   LOG_IF(ERROR, transfer_in_progress_)
       << "Destroying the fetcher while a transfer is in progress.";
+  CancelProxyResolution();
   CleanUp();
 }
 
@@ -101,6 +153,13 @@
   CHECK(curl_handle_);
   ignore_failure_ = false;
 
+  // Tag and untag the socket for network usage stats.
+  curl_easy_setopt(
+      curl_handle_, CURLOPT_SOCKOPTFUNCTION, LibcurlSockoptCallback);
+  curl_easy_setopt(
+      curl_handle_, CURLOPT_CLOSESOCKETFUNCTION, LibcurlCloseSocketCallback);
+  curl_easy_setopt(curl_handle_, CURLOPT_CLOSESOCKETDATA, this);
+
   CHECK(HasProxy());
   bool is_direct = (GetCurrentProxy() == kNoProxy);
   LOG(INFO) << "Using proxy: " << (is_direct ? "no" : "yes");
@@ -249,6 +308,8 @@
   LOG(INFO) << "Setting up curl options for HTTPS";
   CHECK_EQ(curl_easy_setopt(curl_handle_, CURLOPT_SSL_VERIFYPEER, 1),
            CURLE_OK);
+  CHECK_EQ(curl_easy_setopt(curl_handle_, CURLOPT_SSL_VERIFYHOST, 2),
+           CURLE_OK);
   CHECK_EQ(curl_easy_setopt(curl_handle_, CURLOPT_CAPATH,
                             constants::kCACertificatesPath),
            CURLE_OK);
@@ -307,6 +368,7 @@
 }
 
 void LibcurlHttpFetcher::ForceTransferTermination() {
+  CancelProxyResolution();
   CleanUp();
   if (delegate_) {
     // Note that after the callback returns this object may be destroyed.
@@ -385,7 +447,7 @@
       http_response_code_ == 0 &&
       no_network_retry_count_ < no_network_max_retries_) {
     no_network_retry_count_++;
-    MessageLoop::current()->PostDelayedTask(
+    retry_task_id_ = MessageLoop::current()->PostDelayedTask(
         FROM_HERE,
         base::Bind(&LibcurlHttpFetcher::RetryTimeoutCallback,
                    base::Unretained(this)),
@@ -411,7 +473,7 @@
     if (HasProxy()) {
       // We have another proxy. Retry immediately.
       LOG(INFO) << "Retrying with next proxy setting";
-      MessageLoop::current()->PostTask(
+      retry_task_id_ = MessageLoop::current()->PostTask(
           FROM_HERE,
           base::Bind(&LibcurlHttpFetcher::RetryTimeoutCallback,
                      base::Unretained(this)));
@@ -438,7 +500,7 @@
     }
     // Need to restart transfer
     LOG(INFO) << "Restarting transfer to download the remaining bytes";
-    MessageLoop::current()->PostDelayedTask(
+    retry_task_id_ = MessageLoop::current()->PostDelayedTask(
         FROM_HERE,
         base::Bind(&LibcurlHttpFetcher::RetryTimeoutCallback,
                    base::Unretained(this)),
@@ -616,6 +678,7 @@
 }
 
 void LibcurlHttpFetcher::RetryTimeoutCallback() {
+  retry_task_id_ = MessageLoop::kTaskIdNull;
   if (transfer_paused_) {
     restart_transfer_on_unpause_ = true;
     return;
@@ -640,6 +703,9 @@
 }
 
 void LibcurlHttpFetcher::CleanUp() {
+  MessageLoop::current()->CancelTask(retry_task_id_);
+  retry_task_id_ = MessageLoop::kTaskIdNull;
+
   MessageLoop::current()->CancelTask(timeout_id_);
   timeout_id_ = MessageLoop::kTaskIdNull;
 
diff --git a/common/libcurl_http_fetcher.h b/libcurl_http_fetcher.h
similarity index 93%
rename from common/libcurl_http_fetcher.h
rename to libcurl_http_fetcher.h
index 7101aaa..61871c9 100644
--- a/common/libcurl_http_fetcher.h
+++ b/libcurl_http_fetcher.h
@@ -14,8 +14,8 @@
 // limitations under the License.
 //
 
-#ifndef UPDATE_ENGINE_COMMON_LIBCURL_HTTP_FETCHER_H_
-#define UPDATE_ENGINE_COMMON_LIBCURL_HTTP_FETCHER_H_
+#ifndef UPDATE_ENGINE_LIBCURL_HTTP_FETCHER_H_
+#define UPDATE_ENGINE_LIBCURL_HTTP_FETCHER_H_
 
 #include <map>
 #include <memory>
@@ -28,7 +28,7 @@
 #include <base/macros.h>
 #include <brillo/message_loops/message_loop.h>
 
-#include "update_engine/common/certificate_checker.h"
+#include "update_engine/certificate_checker.h"
 #include "update_engine/common/hardware_interface.h"
 #include "update_engine/common/http_fetcher.h"
 
@@ -107,6 +107,10 @@
   }
 
  private:
+  // libcurl's CURLOPT_CLOSESOCKETFUNCTION callback function. Called when
+  // closing a socket created with the CURLOPT_OPENSOCKETFUNCTION callback.
+  static int LibcurlCloseSocketCallback(void* clientp, curl_socket_t item);
+
   // Callback for when proxy resolution has completed. This begins the
   // transfer.
   void ProxiesResolved();
@@ -233,6 +237,9 @@
   // Seconds to wait before retrying a resume.
   int retry_seconds_{20};
 
+  // When waiting for a retry, the task id of the retry callback.
+  brillo::MessageLoop::TaskId retry_task_id_{brillo::MessageLoop::kTaskIdNull};
+
   // Number of resumes due to no network (e.g., HTTP response code 0).
   int no_network_retry_count_{0};
   int no_network_max_retries_{0};
@@ -265,4 +272,4 @@
 
 }  // namespace chromeos_update_engine
 
-#endif  // UPDATE_ENGINE_COMMON_LIBCURL_HTTP_FETCHER_H_
+#endif  // UPDATE_ENGINE_LIBCURL_HTTP_FETCHER_H_
diff --git a/metrics.h b/metrics.h
index bb9fa5e..7c369ee 100644
--- a/metrics.h
+++ b/metrics.h
@@ -19,7 +19,7 @@
 
 #include <base/time/time.h>
 
-#include "update_engine/common/certificate_checker.h"
+#include "update_engine/certificate_checker.h"
 #include "update_engine/common/constants.h"
 #include "update_engine/common/error_code.h"
 
diff --git a/metrics_utils.cc b/metrics_utils.cc
index 4f26758..15e3a8a 100644
--- a/metrics_utils.cc
+++ b/metrics_utils.cc
@@ -230,31 +230,31 @@
   return metrics::DownloadErrorCode::kInputMalformed;
 }
 
-metrics::ConnectionType GetConnectionType(NetworkConnectionType type,
-                                          NetworkTethering tethering) {
+metrics::ConnectionType GetConnectionType(ConnectionType type,
+                                          ConnectionTethering tethering) {
   switch (type) {
-    case NetworkConnectionType::kUnknown:
+    case ConnectionType::kUnknown:
       return metrics::ConnectionType::kUnknown;
 
-    case NetworkConnectionType::kEthernet:
-      if (tethering == NetworkTethering::kConfirmed)
+    case ConnectionType::kEthernet:
+      if (tethering == ConnectionTethering::kConfirmed)
         return metrics::ConnectionType::kTetheredEthernet;
       else
         return metrics::ConnectionType::kEthernet;
 
-    case NetworkConnectionType::kWifi:
-      if (tethering == NetworkTethering::kConfirmed)
+    case ConnectionType::kWifi:
+      if (tethering == ConnectionTethering::kConfirmed)
         return metrics::ConnectionType::kTetheredWifi;
       else
         return metrics::ConnectionType::kWifi;
 
-    case NetworkConnectionType::kWimax:
+    case ConnectionType::kWimax:
       return metrics::ConnectionType::kWimax;
 
-    case NetworkConnectionType::kBluetooth:
+    case ConnectionType::kBluetooth:
       return metrics::ConnectionType::kBluetooth;
 
-    case NetworkConnectionType::kCellular:
+    case ConnectionType::kCellular:
       return metrics::ConnectionType::kCellular;
   }
 
diff --git a/metrics_utils.h b/metrics_utils.h
index 7c3b02d..d9826c1 100644
--- a/metrics_utils.h
+++ b/metrics_utils.h
@@ -17,7 +17,7 @@
 #ifndef UPDATE_ENGINE_METRICS_UTILS_H_
 #define UPDATE_ENGINE_METRICS_UTILS_H_
 
-#include "update_engine/connection_manager.h"
+#include "update_engine/connection_utils.h"
 #include "update_engine/metrics.h"
 
 namespace chromeos_update_engine {
@@ -39,8 +39,8 @@
 metrics::AttemptResult GetAttemptResult(ErrorCode code);
 
 // Calculates the internet connection type given |type| and |tethering|.
-metrics::ConnectionType GetConnectionType(NetworkConnectionType type,
-                                          NetworkTethering tethering);
+metrics::ConnectionType GetConnectionType(ConnectionType type,
+                                          ConnectionTethering tethering);
 
 // This function returns the duration on the wallclock since the last
 // time it was called for the same |state_variable_key| value.
diff --git a/metrics_utils_unittest.cc b/metrics_utils_unittest.cc
index e702c17..edf6bc3 100644
--- a/metrics_utils_unittest.cc
+++ b/metrics_utils_unittest.cc
@@ -30,51 +30,51 @@
 TEST(MetricsUtilsTest, GetConnectionType) {
   // Check that expected combinations map to the right value.
   EXPECT_EQ(metrics::ConnectionType::kUnknown,
-            GetConnectionType(NetworkConnectionType::kUnknown,
-                              NetworkTethering::kUnknown));
+            GetConnectionType(ConnectionType::kUnknown,
+                              ConnectionTethering::kUnknown));
   EXPECT_EQ(metrics::ConnectionType::kEthernet,
-            GetConnectionType(NetworkConnectionType::kEthernet,
-                              NetworkTethering::kUnknown));
+            GetConnectionType(ConnectionType::kEthernet,
+                              ConnectionTethering::kUnknown));
   EXPECT_EQ(metrics::ConnectionType::kWifi,
-            GetConnectionType(NetworkConnectionType::kWifi,
-                              NetworkTethering::kUnknown));
+            GetConnectionType(ConnectionType::kWifi,
+                              ConnectionTethering::kUnknown));
   EXPECT_EQ(metrics::ConnectionType::kWimax,
-            GetConnectionType(NetworkConnectionType::kWimax,
-                              NetworkTethering::kUnknown));
+            GetConnectionType(ConnectionType::kWimax,
+                              ConnectionTethering::kUnknown));
   EXPECT_EQ(metrics::ConnectionType::kBluetooth,
-            GetConnectionType(NetworkConnectionType::kBluetooth,
-                              NetworkTethering::kUnknown));
+            GetConnectionType(ConnectionType::kBluetooth,
+                              ConnectionTethering::kUnknown));
   EXPECT_EQ(metrics::ConnectionType::kCellular,
-            GetConnectionType(NetworkConnectionType::kCellular,
-                              NetworkTethering::kUnknown));
+            GetConnectionType(ConnectionType::kCellular,
+                              ConnectionTethering::kUnknown));
   EXPECT_EQ(metrics::ConnectionType::kTetheredEthernet,
-            GetConnectionType(NetworkConnectionType::kEthernet,
-                              NetworkTethering::kConfirmed));
+            GetConnectionType(ConnectionType::kEthernet,
+                              ConnectionTethering::kConfirmed));
   EXPECT_EQ(metrics::ConnectionType::kTetheredWifi,
-            GetConnectionType(NetworkConnectionType::kWifi,
-                              NetworkTethering::kConfirmed));
+            GetConnectionType(ConnectionType::kWifi,
+                              ConnectionTethering::kConfirmed));
 
   // Ensure that we don't report tethered ethernet unless it's confirmed.
   EXPECT_EQ(metrics::ConnectionType::kEthernet,
-            GetConnectionType(NetworkConnectionType::kEthernet,
-                              NetworkTethering::kNotDetected));
+            GetConnectionType(ConnectionType::kEthernet,
+                              ConnectionTethering::kNotDetected));
   EXPECT_EQ(metrics::ConnectionType::kEthernet,
-            GetConnectionType(NetworkConnectionType::kEthernet,
-                              NetworkTethering::kSuspected));
+            GetConnectionType(ConnectionType::kEthernet,
+                              ConnectionTethering::kSuspected));
   EXPECT_EQ(metrics::ConnectionType::kEthernet,
-            GetConnectionType(NetworkConnectionType::kEthernet,
-                              NetworkTethering::kUnknown));
+            GetConnectionType(ConnectionType::kEthernet,
+                              ConnectionTethering::kUnknown));
 
   // Ditto for tethered wifi.
   EXPECT_EQ(metrics::ConnectionType::kWifi,
-            GetConnectionType(NetworkConnectionType::kWifi,
-                              NetworkTethering::kNotDetected));
+            GetConnectionType(ConnectionType::kWifi,
+                              ConnectionTethering::kNotDetected));
   EXPECT_EQ(metrics::ConnectionType::kWifi,
-            GetConnectionType(NetworkConnectionType::kWifi,
-                              NetworkTethering::kSuspected));
+            GetConnectionType(ConnectionType::kWifi,
+                              ConnectionTethering::kSuspected));
   EXPECT_EQ(metrics::ConnectionType::kWifi,
-            GetConnectionType(NetworkConnectionType::kWifi,
-                              NetworkTethering::kUnknown));
+            GetConnectionType(ConnectionType::kWifi,
+                              ConnectionTethering::kUnknown));
 }
 
 TEST(MetricsUtilsTest, WallclockDurationHelper) {
diff --git a/common/mock_certificate_checker.h b/mock_certificate_checker.h
similarity index 81%
rename from common/mock_certificate_checker.h
rename to mock_certificate_checker.h
index 1f55ca1..c86f502 100644
--- a/common/mock_certificate_checker.h
+++ b/mock_certificate_checker.h
@@ -14,13 +14,13 @@
 // limitations under the License.
 //
 
-#ifndef UPDATE_ENGINE_COMMON_MOCK_CERTIFICATE_CHECKER_H_
-#define UPDATE_ENGINE_COMMON_MOCK_CERTIFICATE_CHECKER_H_
+#ifndef UPDATE_ENGINE_MOCK_CERTIFICATE_CHECKER_H_
+#define UPDATE_ENGINE_MOCK_CERTIFICATE_CHECKER_H_
 
 #include <gmock/gmock.h>
 #include <openssl/ssl.h>
 
-#include "update_engine/common/certificate_checker.h"
+#include "update_engine/certificate_checker.h"
 
 namespace chromeos_update_engine {
 
@@ -35,4 +35,4 @@
 
 }  // namespace chromeos_update_engine
 
-#endif  // UPDATE_ENGINE_COMMON_MOCK_CERTIFICATE_CHECKER_H_
+#endif  // UPDATE_ENGINE_MOCK_CERTIFICATE_CHECKER_H_
diff --git a/mock_connection_manager.h b/mock_connection_manager.h
index c0745b7..2fff68c 100644
--- a/mock_connection_manager.h
+++ b/mock_connection_manager.h
@@ -31,11 +31,11 @@
   MockConnectionManager() = default;
 
   MOCK_METHOD2(GetConnectionProperties,
-               bool(NetworkConnectionType* out_type,
-                    NetworkTethering* out_tethering));
+               bool(ConnectionType* out_type,
+                    ConnectionTethering* out_tethering));
 
-  MOCK_CONST_METHOD2(IsUpdateAllowedOver, bool(NetworkConnectionType type,
-                                               NetworkTethering tethering));
+  MOCK_CONST_METHOD2(IsUpdateAllowedOver,
+                     bool(ConnectionType type, ConnectionTethering tethering));
   MOCK_CONST_METHOD0(IsAllowedConnectionTypesForUpdateSet, bool());
 };
 
diff --git a/mock_power_manager.h b/mock_power_manager.h
new file mode 100644
index 0000000..8363171
--- /dev/null
+++ b/mock_power_manager.h
@@ -0,0 +1,35 @@
+//
+// 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_MOCK_POWER_MANAGER_H_
+#define UPDATE_ENGINE_MOCK_POWER_MANAGER_H_
+
+#include <gmock/gmock.h>
+
+#include "update_engine/power_manager_interface.h"
+
+namespace chromeos_update_engine {
+
+class MockPowerManager : public PowerManagerInterface {
+ public:
+  MockPowerManager() = default;
+
+  MOCK_METHOD0(RequestReboot, bool(void));
+};
+
+}  // namespace chromeos_update_engine
+
+#endif  // UPDATE_ENGINE_MOCK_POWER_MANAGER_H_
diff --git a/network_selector.h b/network_selector.h
new file mode 100644
index 0000000..22aed8e
--- /dev/null
+++ b/network_selector.h
@@ -0,0 +1,33 @@
+//
+// 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_NETWORK_SELECTOR_H_
+#define UPDATE_ENGINE_NETWORK_SELECTOR_H_
+
+#include <memory>
+
+#include "update_engine/network_selector_interface.h"
+
+namespace chromeos_update_engine {
+namespace network {
+
+// Creates the NetworkSelectorInterface instance for the given platform.
+std::unique_ptr<NetworkSelectorInterface> CreateNetworkSelector();
+
+}  // namespace network
+}  // namespace chromeos_update_engine
+
+#endif  // UPDATE_ENGINE_NETWORK_SELECTOR_H_
diff --git a/network_selector_android.cc b/network_selector_android.cc
new file mode 100644
index 0000000..6879b69
--- /dev/null
+++ b/network_selector_android.cc
@@ -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.
+//
+
+#include "update_engine/network_selector_android.h"
+
+#include <android/multinetwork.h>
+#include <base/logging.h>
+#include <brillo/make_unique_ptr.h>
+
+namespace chromeos_update_engine {
+
+namespace network {
+
+// Factory defined in network_selector.h.
+std::unique_ptr<NetworkSelectorInterface> CreateNetworkSelector() {
+  return brillo::make_unique_ptr(new NetworkSelectorAndroid());
+}
+
+}  // namespace network
+
+// Defined in network_selector_interface.h.
+const NetworkId kDefaultNetworkId = NETWORK_UNSPECIFIED;
+
+bool NetworkSelectorAndroid::SetProcessNetwork(NetworkId network_id) {
+  if (android_setprocnetwork(network_id) < 0) {
+    PLOG(ERROR) << "Binding the network to " << network_id;
+    return false;
+  }
+  return true;
+}
+
+}  // namespace chromeos_update_engine
diff --git a/network_selector_android.h b/network_selector_android.h
new file mode 100644
index 0000000..135536c
--- /dev/null
+++ b/network_selector_android.h
@@ -0,0 +1,40 @@
+//
+// 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_NETWORK_SELECTOR_ANDROID_H_
+#define UPDATE_ENGINE_NETWORK_SELECTOR_ANDROID_H_
+
+#include <base/macros.h>
+
+#include "update_engine/network_selector_interface.h"
+
+namespace chromeos_update_engine {
+
+class NetworkSelectorAndroid final : public NetworkSelectorInterface {
+ public:
+  NetworkSelectorAndroid() = default;
+  ~NetworkSelectorAndroid() override = default;
+
+  // NetworkSelectorInterface overrides.
+  bool SetProcessNetwork(NetworkId network_id) override;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(NetworkSelectorAndroid);
+};
+
+}  // namespace chromeos_update_engine
+
+#endif  // UPDATE_ENGINE_NETWORK_SELECTOR_ANDROID_H_
diff --git a/network_selector_interface.h b/network_selector_interface.h
new file mode 100644
index 0000000..6c17b2c
--- /dev/null
+++ b/network_selector_interface.h
@@ -0,0 +1,49 @@
+//
+// 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_NETWORK_SELECTOR_INTERFACE_H_
+#define UPDATE_ENGINE_NETWORK_SELECTOR_INTERFACE_H_
+
+#include <cstdint>
+
+namespace chromeos_update_engine {
+
+typedef uint64_t NetworkId;
+
+// A constant value used to indicate the default network id. Defined in the
+// network_selector_*.cc file.
+extern const NetworkId kDefaultNetworkId;
+
+// A class that handles the network used for the connections performed from this
+// process in a platform-specific way.
+
+class NetworkSelectorInterface {
+ public:
+
+  virtual ~NetworkSelectorInterface() = default;
+
+  // Set the current process network. All sockets created in the future will be
+  // bound to this particular network. Call this with the special value
+  // kNetworkId to use the default network.
+  virtual bool SetProcessNetwork(NetworkId network_id) = 0;
+
+ protected:
+  NetworkSelectorInterface() = default;
+};
+
+}  // namespace chromeos_update_engine
+
+#endif  // UPDATE_ENGINE_NETWORK_SELECTOR_INTERFACE_H_
diff --git a/network_selector_stub.cc b/network_selector_stub.cc
new file mode 100644
index 0000000..218d454
--- /dev/null
+++ b/network_selector_stub.cc
@@ -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.
+//
+
+#include "update_engine/network_selector_stub.h"
+
+#include <base/logging.h>
+#include <brillo/make_unique_ptr.h>
+
+namespace chromeos_update_engine {
+
+namespace network {
+
+// Factory defined in network_selector.h.
+std::unique_ptr<NetworkSelectorInterface> CreateNetworkSelector() {
+  return brillo::make_unique_ptr(new NetworkSelectorStub());
+}
+
+}  // namespace network
+
+// Defined in network_selector_interface.h.
+const NetworkId kDefaultNetworkId = 0;
+
+bool NetworkSelectorStub::SetProcessNetwork(NetworkId network_id) {
+  if (network_id != kDefaultNetworkId) {
+    LOG(ERROR) << "SetProcessNetwork not implemented.";
+    return false;
+  }
+  return true;
+}
+
+}  // namespace chromeos_update_engine
diff --git a/network_selector_stub.h b/network_selector_stub.h
new file mode 100644
index 0000000..b3f7b48
--- /dev/null
+++ b/network_selector_stub.h
@@ -0,0 +1,40 @@
+//
+// 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_NETWORK_SELECTOR_STUB_H_
+#define UPDATE_ENGINE_NETWORK_SELECTOR_STUB_H_
+
+#include <base/macros.h>
+
+#include "update_engine/network_selector_interface.h"
+
+namespace chromeos_update_engine {
+
+class NetworkSelectorStub final : public NetworkSelectorInterface {
+ public:
+  NetworkSelectorStub() = default;
+  ~NetworkSelectorStub() override = default;
+
+  // NetworkSelectorInterface overrides.
+  bool SetProcessNetwork(NetworkId network_id) override;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(NetworkSelectorStub);
+};
+
+}  // namespace chromeos_update_engine
+
+#endif  // UPDATE_ENGINE_NETWORK_SELECTOR_STUB_H_
diff --git a/omaha_request_action.cc b/omaha_request_action.cc
index fb258c2..ed3c716 100644
--- a/omaha_request_action.cc
+++ b/omaha_request_action.cc
@@ -40,7 +40,7 @@
 #include "update_engine/common/platform_constants.h"
 #include "update_engine/common/prefs_interface.h"
 #include "update_engine/common/utils.h"
-#include "update_engine/connection_manager.h"
+#include "update_engine/connection_manager_interface.h"
 #include "update_engine/metrics.h"
 #include "update_engine/metrics_utils.h"
 #include "update_engine/omaha_request_params.h"
@@ -77,6 +77,11 @@
 
 static const char* kOmahaUpdaterVersion = "0.1.0.0";
 
+// X-GoogleUpdate headers.
+static const char* kXGoogleUpdateInteractivity = "X-GoogleUpdate-Interactivity";
+static const char* kXGoogleUpdateAppId = "X-GoogleUpdate-AppId";
+static const char* kXGoogleUpdateUpdater = "X-GoogleUpdate-Updater";
+
 // updatecheck attributes (without the underscore prefix).
 static const char* kEolAttr = "eol";
 
@@ -253,11 +258,18 @@
   app_cohort_args += GetCohortArgXml(system_state->prefs(),
                                      "cohortname", kPrefsOmahaCohortName);
 
+  string fingerprint_arg;
+  if (!params->os_build_fingerprint().empty()) {
+    fingerprint_arg =
+        "fingerprint=\"" + XmlEncodeWithDefault(params->os_build_fingerprint(), "") + "\" ";
+  }
+
   string app_xml = "    <app "
       "appid=\"" + XmlEncodeWithDefault(params->GetAppId(), "") + "\" " +
       app_cohort_args +
       app_versions +
       app_channels +
+      fingerprint_arg +
       "lang=\"" + XmlEncodeWithDefault(params->app_lang(), "en-US") + "\" " +
       "board=\"" + XmlEncodeWithDefault(params->os_board(), "") + "\" " +
       "hardware_class=\"" + XmlEncodeWithDefault(params->hwid(), "") + "\" " +
@@ -649,6 +661,15 @@
                                     GetInstallDate(system_state_),
                                     system_state_));
 
+  // Set X-GoogleUpdate headers.
+  http_fetcher_->SetHeader(kXGoogleUpdateInteractivity,
+                           params_->interactive() ? "fg" : "bg");
+  http_fetcher_->SetHeader(kXGoogleUpdateAppId, params_->GetAppId());
+  http_fetcher_->SetHeader(
+      kXGoogleUpdateUpdater,
+      base::StringPrintf(
+          "%s-%s", constants::kOmahaUpdaterID, kOmahaUpdaterVersion));
+
   http_fetcher_->SetPostData(request_post.data(), request_post.size(),
                              kHttpContentTypeTextXml);
   LOG(INFO) << "Posting an Omaha request to " << params_->update_url();
@@ -1212,7 +1233,7 @@
      return kWallClockWaitDoneAndUpdateCheckWaitNotRequired;
     }
   } else {
-    update_first_seen_at = Time::Now();
+    update_first_seen_at = system_state_->clock()->GetWallclockTime();
     update_first_seen_at_int = update_first_seen_at.ToInternalValue();
     if (system_state_->prefs()->SetInt64(kPrefsUpdateFirstSeenAt,
                                          update_first_seen_at_int)) {
@@ -1229,9 +1250,10 @@
     }
   }
 
-  TimeDelta elapsed_time = Time::Now() - update_first_seen_at;
-  TimeDelta max_scatter_period = TimeDelta::FromDays(
-      output_object->max_days_to_scatter);
+  TimeDelta elapsed_time =
+      system_state_->clock()->GetWallclockTime() - update_first_seen_at;
+  TimeDelta max_scatter_period =
+      TimeDelta::FromDays(output_object->max_days_to_scatter);
 
   LOG(INFO) << "Waiting Period = "
             << utils::FormatSecs(params_->waiting_period().InSeconds())
@@ -1557,8 +1579,8 @@
 bool OmahaRequestAction::IsUpdateAllowedOverCurrentConnection(
     ErrorCode* error,
     const OmahaResponse& response) const {
-  NetworkConnectionType type;
-  NetworkTethering tethering;
+  ConnectionType type;
+  ConnectionTethering tethering;
   ConnectionManagerInterface* connection_manager =
       system_state_->connection_manager();
   if (!connection_manager->GetConnectionProperties(&type, &tethering)) {
@@ -1571,8 +1593,8 @@
   bool is_device_policy_set = connection_manager->
                                   IsAllowedConnectionTypesForUpdateSet();
   // Treats tethered connection as if it is cellular connection.
-  bool is_over_cellular = type == NetworkConnectionType::kCellular ||
-                          tethering == NetworkTethering::kConfirmed;
+  bool is_over_cellular = type == ConnectionType::kCellular ||
+                          tethering == ConnectionTethering::kConfirmed;
 
   if (!is_over_cellular) {
     // There's no need to further check user preferences as we are not over
@@ -1591,7 +1613,7 @@
   }
 
   LOG(INFO) << "We are connected via "
-            << ConnectionManager::StringForConnectionType(type)
+            << connection_utils::StringForConnectionType(type)
             << ", Updates allowed: " << (is_allowed ? "Yes" : "No");
   return is_allowed;
 }
diff --git a/omaha_request_action_unittest.cc b/omaha_request_action_unittest.cc
index 6c24f86..cb3ef71 100644
--- a/omaha_request_action_unittest.cc
+++ b/omaha_request_action_unittest.cc
@@ -352,7 +352,9 @@
       .Times(expected_download_error_code == metrics::DownloadErrorCode::kUnset
              ? 0 : 1);
 
-  loop.PostTask(base::Bind([&processor] { processor.StartProcessing(); }));
+  loop.PostTask(base::Bind(
+      [](ActionProcessor* processor) { processor->StartProcessing(); },
+      base::Unretained(&processor)));
   loop.Run();
   EXPECT_FALSE(loop.PendingTasks());
   if (collector_action.has_input_object_ && out_response)
@@ -385,7 +387,9 @@
   processor.set_delegate(&delegate);
   processor.EnqueueAction(&action);
 
-  loop.PostTask(base::Bind([&processor] { processor.StartProcessing(); }));
+  loop.PostTask(base::Bind(
+      [](ActionProcessor* processor) { processor->StartProcessing(); },
+      base::Unretained(&processor)));
   loop.Run();
   EXPECT_FALSE(loop.PendingTasks());
 
@@ -458,6 +462,33 @@
   EXPECT_FALSE(fake_prefs_.Exists(kPrefsOmahaCohortName));
 }
 
+TEST_F(OmahaRequestActionTest, ExtraHeadersSentTest) {
+  const string http_response = "<?xml invalid response";
+  request_params_.set_interactive(true);
+
+  brillo::FakeMessageLoop loop(nullptr);
+  loop.SetAsCurrent();
+
+  MockHttpFetcher* fetcher =
+      new MockHttpFetcher(http_response.data(), http_response.size(), nullptr);
+  OmahaRequestAction action(
+      &fake_system_state_, nullptr, brillo::make_unique_ptr(fetcher), false);
+  ActionProcessor processor;
+  processor.EnqueueAction(&action);
+
+  loop.PostTask(base::Bind(
+      [](ActionProcessor* processor) { processor->StartProcessing(); },
+      base::Unretained(&processor)));
+  loop.Run();
+  EXPECT_FALSE(loop.PendingTasks());
+
+  // Check that the headers were set in the fetcher during the action. Note that
+  // we set this request as "interactive".
+  EXPECT_EQ("fg", fetcher->GetHeader("X-GoogleUpdate-Interactivity"));
+  EXPECT_EQ(kTestAppId, fetcher->GetHeader("X-GoogleUpdate-AppId"));
+  EXPECT_NE("", fetcher->GetHeader("X-GoogleUpdate-Updater"));
+}
+
 TEST_F(OmahaRequestActionTest, ValidUpdateBlockedByConnection) {
   OmahaResponse response;
   // Set up a connection manager that doesn't allow a valid update over
@@ -467,11 +498,11 @@
 
   EXPECT_CALL(mock_cm, GetConnectionProperties(_, _))
       .WillRepeatedly(
-          DoAll(SetArgumentPointee<0>(NetworkConnectionType::kEthernet),
-                SetArgumentPointee<1>(NetworkTethering::kUnknown),
+          DoAll(SetArgumentPointee<0>(ConnectionType::kEthernet),
+                SetArgumentPointee<1>(ConnectionTethering::kUnknown),
                 Return(true)));
-  EXPECT_CALL(mock_cm, IsUpdateAllowedOver(NetworkConnectionType::kEthernet, _))
-    .WillRepeatedly(Return(false));
+  EXPECT_CALL(mock_cm, IsUpdateAllowedOver(ConnectionType::kEthernet, _))
+      .WillRepeatedly(Return(false));
 
   ASSERT_FALSE(
       TestUpdateCheck(nullptr,  // request_params
@@ -497,12 +528,12 @@
 
   EXPECT_CALL(mock_cm, GetConnectionProperties(_, _))
       .WillRepeatedly(
-          DoAll(SetArgumentPointee<0>(NetworkConnectionType::kCellular),
-                SetArgumentPointee<1>(NetworkTethering::kUnknown),
+          DoAll(SetArgumentPointee<0>(ConnectionType::kCellular),
+                SetArgumentPointee<1>(ConnectionTethering::kUnknown),
                 Return(true)));
   EXPECT_CALL(mock_cm, IsAllowedConnectionTypesForUpdateSet())
       .WillRepeatedly(Return(true));
-  EXPECT_CALL(mock_cm, IsUpdateAllowedOver(NetworkConnectionType::kCellular, _))
+  EXPECT_CALL(mock_cm, IsUpdateAllowedOver(ConnectionType::kCellular, _))
       .WillRepeatedly(Return(true));
 
   ASSERT_TRUE(
@@ -529,12 +560,12 @@
 
   EXPECT_CALL(mock_cm, GetConnectionProperties(_, _))
       .WillRepeatedly(
-          DoAll(SetArgumentPointee<0>(NetworkConnectionType::kCellular),
-                SetArgumentPointee<1>(NetworkTethering::kUnknown),
+          DoAll(SetArgumentPointee<0>(ConnectionType::kCellular),
+                SetArgumentPointee<1>(ConnectionTethering::kUnknown),
                 Return(true)));
   EXPECT_CALL(mock_cm, IsAllowedConnectionTypesForUpdateSet())
       .WillRepeatedly(Return(true));
-  EXPECT_CALL(mock_cm, IsUpdateAllowedOver(NetworkConnectionType::kCellular, _))
+  EXPECT_CALL(mock_cm, IsUpdateAllowedOver(ConnectionType::kCellular, _))
       .WillRepeatedly(Return(false));
 
   ASSERT_FALSE(
@@ -563,12 +594,12 @@
 
   EXPECT_CALL(mock_cm, GetConnectionProperties(_, _))
       .WillRepeatedly(
-          DoAll(SetArgumentPointee<0>(NetworkConnectionType::kCellular),
-                SetArgumentPointee<1>(NetworkTethering::kUnknown),
+          DoAll(SetArgumentPointee<0>(ConnectionType::kCellular),
+                SetArgumentPointee<1>(ConnectionTethering::kUnknown),
                 Return(true)));
   EXPECT_CALL(mock_cm, IsAllowedConnectionTypesForUpdateSet())
       .WillRepeatedly(Return(false));
-  EXPECT_CALL(mock_cm, IsUpdateAllowedOver(NetworkConnectionType::kCellular, _))
+  EXPECT_CALL(mock_cm, IsUpdateAllowedOver(ConnectionType::kCellular, _))
       .WillRepeatedly(Return(true));
 
   ASSERT_TRUE(
@@ -604,12 +635,12 @@
 
   EXPECT_CALL(mock_cm, GetConnectionProperties(_, _))
       .WillRepeatedly(
-          DoAll(SetArgumentPointee<0>(NetworkConnectionType::kCellular),
-                SetArgumentPointee<1>(NetworkTethering::kUnknown),
+          DoAll(SetArgumentPointee<0>(ConnectionType::kCellular),
+                SetArgumentPointee<1>(ConnectionTethering::kUnknown),
                 Return(true)));
   EXPECT_CALL(mock_cm, IsAllowedConnectionTypesForUpdateSet())
       .WillRepeatedly(Return(false));
-  EXPECT_CALL(mock_cm, IsUpdateAllowedOver(NetworkConnectionType::kCellular, _))
+  EXPECT_CALL(mock_cm, IsUpdateAllowedOver(ConnectionType::kCellular, _))
       .WillRepeatedly(Return(true));
 
   ASSERT_FALSE(
@@ -644,12 +675,12 @@
 
   EXPECT_CALL(mock_cm, GetConnectionProperties(_, _))
       .WillRepeatedly(
-          DoAll(SetArgumentPointee<0>(NetworkConnectionType::kCellular),
-                SetArgumentPointee<1>(NetworkTethering::kUnknown),
+          DoAll(SetArgumentPointee<0>(ConnectionType::kCellular),
+                SetArgumentPointee<1>(ConnectionTethering::kUnknown),
                 Return(true)));
   EXPECT_CALL(mock_cm, IsAllowedConnectionTypesForUpdateSet())
       .WillRepeatedly(Return(false));
-  EXPECT_CALL(mock_cm, IsUpdateAllowedOver(NetworkConnectionType::kCellular, _))
+  EXPECT_CALL(mock_cm, IsUpdateAllowedOver(ConnectionType::kCellular, _))
       .WillRepeatedly(Return(true));
 
   ASSERT_TRUE(
@@ -1080,7 +1111,9 @@
   processor.set_delegate(&delegate);
   processor.EnqueueAction(&action);
 
-  loop.PostTask(base::Bind([&processor] { processor.StartProcessing(); }));
+  loop.PostTask(base::Bind(
+      [](ActionProcessor* processor) { processor->StartProcessing(); },
+      base::Unretained(&processor)));
   loop.Run();
   EXPECT_FALSE(loop.PendingTasks());
   EXPECT_FALSE(processor.IsRunning());
@@ -1954,36 +1987,37 @@
   params.set_waiting_period(TimeDelta().FromDays(1));
   params.set_update_check_count_wait_enabled(false);
 
-  ASSERT_FALSE(TestUpdateCheck(
-                      &params,
-                      fake_update_response_.GetUpdateResponse(),
-                      -1,
-                      false,  // ping_only
-                      ErrorCode::kOmahaUpdateDeferredPerPolicy,
-                      metrics::CheckResult::kUpdateAvailable,
-                      metrics::CheckReaction::kDeferring,
-                      metrics::DownloadErrorCode::kUnset,
-                      &response,
-                      nullptr));
+  Time arbitrary_date;
+  Time::FromString("6/4/1989", &arbitrary_date);
+  fake_system_state_.fake_clock()->SetWallclockTime(arbitrary_date);
+  ASSERT_FALSE(TestUpdateCheck(&params,
+                               fake_update_response_.GetUpdateResponse(),
+                               -1,
+                               false,  // ping_only
+                               ErrorCode::kOmahaUpdateDeferredPerPolicy,
+                               metrics::CheckResult::kUpdateAvailable,
+                               metrics::CheckReaction::kDeferring,
+                               metrics::DownloadErrorCode::kUnset,
+                               &response,
+                               nullptr));
 
   int64_t timestamp = 0;
   ASSERT_TRUE(fake_prefs_.GetInt64(kPrefsUpdateFirstSeenAt, &timestamp));
-  ASSERT_GT(timestamp, 0);
+  EXPECT_EQ(arbitrary_date.ToInternalValue(), timestamp);
   EXPECT_FALSE(response.update_exists);
 
   // Verify if we are interactive check we don't defer.
   params.set_interactive(true);
-  ASSERT_TRUE(
-      TestUpdateCheck(&params,
-                      fake_update_response_.GetUpdateResponse(),
-                      -1,
-                      false,  // ping_only
-                      ErrorCode::kSuccess,
-                      metrics::CheckResult::kUpdateAvailable,
-                      metrics::CheckReaction::kUpdating,
-                      metrics::DownloadErrorCode::kUnset,
-                      &response,
-                      nullptr));
+  ASSERT_TRUE(TestUpdateCheck(&params,
+                              fake_update_response_.GetUpdateResponse(),
+                              -1,
+                              false,  // ping_only
+                              ErrorCode::kSuccess,
+                              metrics::CheckResult::kUpdateAvailable,
+                              metrics::CheckReaction::kUpdating,
+                              metrics::DownloadErrorCode::kUnset,
+                              &response,
+                              nullptr));
   EXPECT_TRUE(response.update_exists);
 }
 
@@ -1994,23 +2028,22 @@
   params.set_waiting_period(TimeDelta().FromDays(1));
   params.set_update_check_count_wait_enabled(false);
 
-  // Set the timestamp to a very old value such that it exceeds the
-  // waiting period set above.
-  Time t1;
+  Time t1, t2;
   Time::FromString("1/1/2012", &t1);
-  ASSERT_TRUE(fake_prefs_.SetInt64(
-      kPrefsUpdateFirstSeenAt, t1.ToInternalValue()));
-  ASSERT_TRUE(TestUpdateCheck(
-                      &params,
-                      fake_update_response_.GetUpdateResponse(),
-                      -1,
-                      false,  // ping_only
-                      ErrorCode::kSuccess,
-                      metrics::CheckResult::kUpdateAvailable,
-                      metrics::CheckReaction::kUpdating,
-                      metrics::DownloadErrorCode::kUnset,
-                      &response,
-                      nullptr));
+  Time::FromString("1/3/2012", &t2);
+  ASSERT_TRUE(
+      fake_prefs_.SetInt64(kPrefsUpdateFirstSeenAt, t1.ToInternalValue()));
+  fake_system_state_.fake_clock()->SetWallclockTime(t2);
+  ASSERT_TRUE(TestUpdateCheck(&params,
+                              fake_update_response_.GetUpdateResponse(),
+                              -1,
+                              false,  // ping_only
+                              ErrorCode::kSuccess,
+                              metrics::CheckResult::kUpdateAvailable,
+                              metrics::CheckReaction::kUpdating,
+                              metrics::DownloadErrorCode::kUnset,
+                              &response,
+                              nullptr));
 
   EXPECT_TRUE(response.update_exists);
 
diff --git a/omaha_request_params.h b/omaha_request_params.h
index 379563a..3a28ed1 100644
--- a/omaha_request_params.h
+++ b/omaha_request_params.h
@@ -102,6 +102,9 @@
   inline std::string os_version() const { return os_version_; }
   inline std::string os_sp() const { return os_sp_; }
   inline std::string os_board() const { return image_props_.board; }
+  inline std::string os_build_fingerprint() const {
+    return image_props_.build_fingerprint;
+  }
   inline std::string board_app_id() const { return image_props_.product_id; }
   inline std::string canary_app_id() const {
     return image_props_.canary_product_id;
diff --git a/payload_consumer/delta_performer.cc b/payload_consumer/delta_performer.cc
index 7679571..4a8178c 100644
--- a/payload_consumer/delta_performer.cc
+++ b/payload_consumer/delta_performer.cc
@@ -26,13 +26,14 @@
 #include <string>
 #include <vector>
 
-#include <applypatch/imgpatch.h>
 #include <base/files/file_util.h>
 #include <base/format_macros.h>
+#include <base/strings/string_number_conversions.h>
 #include <base/strings/string_util.h>
 #include <base/strings/stringprintf.h>
 #include <brillo/data_encoding.h>
 #include <brillo/make_unique_ptr.h>
+#include <bsdiff/bspatch.h>
 #include <google/protobuf/repeated_field.h>
 
 #include "update_engine/common/constants.h"
@@ -130,6 +131,39 @@
   *err = 0;
   return fd;
 }
+
+// Discard the tail of the block device referenced by |fd|, from the offset
+// |data_size| until the end of the block device. Returns whether the data was
+// discarded.
+bool DiscardPartitionTail(const FileDescriptorPtr& fd, uint64_t data_size) {
+  uint64_t part_size = fd->BlockDevSize();
+  if (!part_size || part_size <= data_size)
+    return false;
+
+  struct blkioctl_request {
+    int number;
+    const char* name;
+  };
+  const vector<blkioctl_request> blkioctl_requests = {
+      {BLKSECDISCARD, "BLKSECDISCARD"},
+      {BLKDISCARD, "BLKDISCARD"},
+#ifdef BLKZEROOUT
+      {BLKZEROOUT, "BLKZEROOUT"},
+#endif
+  };
+  for (const auto& req : blkioctl_requests) {
+    int error = 0;
+    if (fd->BlkIoctl(req.number, data_size, part_size - data_size, &error) &&
+        error == 0) {
+      return true;
+    }
+    LOG(WARNING) << "Error discarding the last "
+                 << (part_size - data_size) / 1024 << " KiB using ioctl("
+                 << req.name << ")";
+  }
+  return false;
+}
+
 }  // namespace
 
 
@@ -249,9 +283,15 @@
   if (op_result)
     return true;
 
+  size_t partition_first_op_num =
+      current_partition_ ? acc_num_operations_[current_partition_ - 1] : 0;
   LOG(ERROR) << "Failed to perform " << op_type_name << " operation "
-             << next_operation_num_;
-  *error = ErrorCode::kDownloadOperationExecutionError;
+             << next_operation_num_ << ", which is the operation "
+             << next_operation_num_ - partition_first_op_num
+             << " in partition \""
+             << partitions_[current_partition_].partition_name() << "\"";
+  if (*error == ErrorCode::kSuccess)
+    *error = ErrorCode::kDownloadOperationExecutionError;
   return false;
 }
 
@@ -321,6 +361,15 @@
                << ", file " << target_path_;
     return false;
   }
+
+  LOG(INFO) << "Applying " << partition.operations().size()
+            << " operations to partition \"" << partition.partition_name()
+            << "\"";
+
+  // Discard the end of the partition, but ignore failures.
+  DiscardPartitionTail(
+      target_fd_, install_plan_->partitions[current_partition_].target_size);
+
   return true;
 }
 
@@ -678,16 +727,17 @@
         op_result = PerformBsdiffOperation(op);
         break;
       case InstallOperation::SOURCE_COPY:
-        op_result = PerformSourceCopyOperation(op);
+        op_result = PerformSourceCopyOperation(op, error);
         break;
       case InstallOperation::SOURCE_BSDIFF:
-        op_result = PerformSourceBsdiffOperation(op);
+        op_result = PerformSourceBsdiffOperation(op, error);
         break;
       case InstallOperation::IMGDIFF:
-        op_result = PerformImgdiffOperation(op);
+        // TODO(deymo): Replace with PUFFIN operation.
+        op_result = false;
         break;
       default:
-       op_result = false;
+        op_result = false;
     }
     if (!HandleOpResult(op_result, InstallOperationTypeName(op.type()), error))
       return false;
@@ -793,6 +843,7 @@
           (partition.has_postinstall_path() ? partition.postinstall_path()
                                             : kPostinstallDefaultScript);
       install_part.filesystem_type = partition.filesystem_type();
+      install_part.postinstall_optional = partition.postinstall_optional();
     }
 
     if (partition.has_old_partition_info()) {
@@ -903,8 +954,7 @@
 #endif  // !defined(BLKZEROOUT)
 
   brillo::Blob zeros;
-  for (int i = 0; i < operation.dst_extents_size(); i++) {
-    Extent extent = operation.dst_extents(i);
+  for (const Extent& extent : operation.dst_extents()) {
     const uint64_t start = extent.start_block() * block_size_;
     const uint64_t length = extent.num_blocks() * block_size_;
     if (attempt_ioctl) {
@@ -982,7 +1032,7 @@
 // each block in |extents|. For example, [(3, 2), (8, 1)] would give [3, 4, 8].
 void ExtentsToBlocks(const RepeatedPtrField<Extent>& extents,
                      vector<uint64_t>* blocks) {
-  for (Extent ext : extents) {
+  for (const Extent& ext : extents) {
     for (uint64_t j = 0; j < ext.num_blocks(); j++)
       blocks->push_back(ext.start_block() + j);
   }
@@ -991,23 +1041,43 @@
 // Takes |extents| and returns the number of blocks in those extents.
 uint64_t GetBlockCount(const RepeatedPtrField<Extent>& extents) {
   uint64_t sum = 0;
-  for (Extent ext : extents) {
+  for (const Extent& ext : extents) {
     sum += ext.num_blocks();
   }
   return sum;
 }
 
 // Compare |calculated_hash| with source hash in |operation|, return false and
-// dump hash if don't match.
+// dump hash and set |error| if don't match.
 bool ValidateSourceHash(const brillo::Blob& calculated_hash,
-                        const InstallOperation& operation) {
+                        const InstallOperation& operation,
+                        ErrorCode* error) {
   brillo::Blob expected_source_hash(operation.src_sha256_hash().begin(),
                                     operation.src_sha256_hash().end());
   if (calculated_hash != expected_source_hash) {
-    LOG(ERROR) << "Hash verification failed. Expected hash = ";
-    utils::HexDumpVector(expected_source_hash);
-    LOG(ERROR) << "Calculated hash = ";
-    utils::HexDumpVector(calculated_hash);
+    LOG(ERROR) << "The hash of the source data on disk for this operation "
+               << "doesn't match the expected value. This could mean that the "
+               << "delta update payload was targeted for another version, or "
+               << "that the source partition was modified after it was "
+               << "installed, for example, by mounting a filesystem.";
+    LOG(ERROR) << "Expected:   sha256|hex = "
+               << base::HexEncode(expected_source_hash.data(),
+                                  expected_source_hash.size());
+    LOG(ERROR) << "Calculated: sha256|hex = "
+               << base::HexEncode(calculated_hash.data(),
+                                  calculated_hash.size());
+
+    vector<string> source_extents;
+    for (const Extent& ext : operation.src_extents()) {
+      source_extents.push_back(
+          base::StringPrintf("%" PRIu64 ":%" PRIu64,
+                             static_cast<uint64_t>(ext.start_block()),
+                             static_cast<uint64_t>(ext.num_blocks())));
+    }
+    LOG(ERROR) << "Operation source (offset:size) in blocks: "
+               << base::JoinString(source_extents, ",");
+
+    *error = ErrorCode::kDownloadStateInitializationError;
     return false;
   }
   return true;
@@ -1016,7 +1086,7 @@
 }  // namespace
 
 bool DeltaPerformer::PerformSourceCopyOperation(
-    const InstallOperation& operation) {
+    const InstallOperation& operation, ErrorCode* error) {
   if (operation.has_src_length())
     TEST_AND_RETURN_FALSE(operation.src_length() % block_size_ == 0);
   if (operation.has_dst_length())
@@ -1069,7 +1139,7 @@
   if (operation.has_src_sha256_hash()) {
     TEST_AND_RETURN_FALSE(source_hasher.Finalize());
     TEST_AND_RETURN_FALSE(
-        ValidateSourceHash(source_hasher.raw_hash(), operation));
+        ValidateSourceHash(source_hasher.raw_hash(), operation, error));
   }
 
   DCHECK_EQ(bytes_read, static_cast<ssize_t>(blocks_to_read * block_size_));
@@ -1083,11 +1153,11 @@
     string* positions_string) {
   string ret;
   uint64_t length = 0;
-  for (int i = 0; i < extents.size(); i++) {
-    Extent extent = extents.Get(i);
+  for (const Extent& extent : extents) {
     int64_t start = extent.start_block() * block_size;
-    uint64_t this_length = min(full_length - length,
-                               extent.num_blocks() * block_size);
+    uint64_t this_length =
+        min(full_length - length,
+            static_cast<uint64_t>(extent.num_blocks()) * block_size);
     ret += base::StringPrintf("%" PRIi64 ":%" PRIu64 ",", start, this_length);
     length += this_length;
   }
@@ -1115,31 +1185,14 @@
                                                        operation.dst_length(),
                                                        &output_positions));
 
-  string temp_filename;
-  TEST_AND_RETURN_FALSE(utils::MakeTempFile("au_patch.XXXXXX",
-                                            &temp_filename,
-                                            nullptr));
-  ScopedPathUnlinker path_unlinker(temp_filename);
-  {
-    int fd = open(temp_filename.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0644);
-    ScopedFdCloser fd_closer(&fd);
-    TEST_AND_RETURN_FALSE(
-        utils::WriteAll(fd, buffer_.data(), operation.data_length()));
-  }
-
-  // Update the buffer to release the patch data memory as soon as the patch
-  // file is written out.
+  TEST_AND_RETURN_FALSE(bsdiff::bspatch(target_path_.c_str(),
+                                        target_path_.c_str(),
+                                        buffer_.data(),
+                                        buffer_.size(),
+                                        input_positions.c_str(),
+                                        output_positions.c_str()) == 0);
   DiscardBuffer(true, buffer_.size());
 
-  vector<string> cmd{kBspatchPath, target_path_, target_path_, temp_filename,
-                     input_positions, output_positions};
-
-  int return_code = 0;
-  TEST_AND_RETURN_FALSE(
-      Subprocess::SynchronousExecFlags(cmd, Subprocess::kSearchPath,
-                                       &return_code, nullptr));
-  TEST_AND_RETURN_FALSE(return_code == 0);
-
   if (operation.dst_length() % block_size_) {
     // Zero out rest of final block.
     // TODO(adlr): build this into bspatch; it's more efficient that way.
@@ -1157,7 +1210,7 @@
 }
 
 bool DeltaPerformer::PerformSourceBsdiffOperation(
-    const InstallOperation& operation) {
+    const InstallOperation& operation, ErrorCode* error) {
   // Since we delete data off the beginning of the buffer as we use it,
   // the data we need should be exactly at the beginning of the buffer.
   TEST_AND_RETURN_FALSE(buffer_offset_ == operation.data_offset());
@@ -1173,8 +1226,8 @@
     brillo::Blob buf(kMaxBlocksToRead * block_size_);
     for (const Extent& extent : operation.src_extents()) {
       for (uint64_t i = 0; i < extent.num_blocks(); i += kMaxBlocksToRead) {
-        uint64_t blocks_to_read =
-            min(kMaxBlocksToRead, extent.num_blocks() - i);
+        uint64_t blocks_to_read = min(
+            kMaxBlocksToRead, static_cast<uint64_t>(extent.num_blocks()) - i);
         ssize_t bytes_to_read = blocks_to_read * block_size_;
         ssize_t bytes_read_this_iteration = 0;
         TEST_AND_RETURN_FALSE(
@@ -1187,7 +1240,7 @@
     }
     TEST_AND_RETURN_FALSE(source_hasher.Finalize());
     TEST_AND_RETURN_FALSE(
-        ValidateSourceHash(source_hasher.raw_hash(), operation));
+        ValidateSourceHash(source_hasher.raw_hash(), operation, error));
   }
 
   string input_positions;
@@ -1201,80 +1254,12 @@
                                                        operation.dst_length(),
                                                        &output_positions));
 
-  string temp_filename;
-  TEST_AND_RETURN_FALSE(utils::MakeTempFile("au_patch.XXXXXX",
-                                            &temp_filename,
-                                            nullptr));
-  ScopedPathUnlinker path_unlinker(temp_filename);
-  {
-    int fd = open(temp_filename.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0644);
-    ScopedFdCloser fd_closer(&fd);
-    TEST_AND_RETURN_FALSE(
-        utils::WriteAll(fd, buffer_.data(), operation.data_length()));
-  }
-
-  // Update the buffer to release the patch data memory as soon as the patch
-  // file is written out.
-  DiscardBuffer(true, buffer_.size());
-
-  vector<string> cmd{kBspatchPath, source_path_, target_path_, temp_filename,
-                     input_positions, output_positions};
-
-  int return_code = 0;
-  TEST_AND_RETURN_FALSE(
-      Subprocess::SynchronousExecFlags(cmd, Subprocess::kSearchPath,
-                                       &return_code, nullptr));
-  TEST_AND_RETURN_FALSE(return_code == 0);
-  return true;
-}
-
-bool DeltaPerformer::PerformImgdiffOperation(
-    const InstallOperation& operation) {
-  // Since we delete data off the beginning of the buffer as we use it,
-  // the data we need should be exactly at the beginning of the buffer.
-  TEST_AND_RETURN_FALSE(buffer_offset_ == operation.data_offset());
-  TEST_AND_RETURN_FALSE(buffer_.size() >= operation.data_length());
-
-  uint64_t src_blocks = GetBlockCount(operation.src_extents());
-  brillo::Blob src_data(src_blocks * block_size_);
-
-  ssize_t bytes_read = 0;
-  for (const Extent& extent : operation.src_extents()) {
-    ssize_t bytes_read_this_iteration = 0;
-    ssize_t bytes_to_read = extent.num_blocks() * block_size_;
-    TEST_AND_RETURN_FALSE(utils::PReadAll(source_fd_,
-                                          &src_data[bytes_read],
-                                          bytes_to_read,
-                                          extent.start_block() * block_size_,
-                                          &bytes_read_this_iteration));
-    TEST_AND_RETURN_FALSE(bytes_read_this_iteration == bytes_to_read);
-    bytes_read += bytes_read_this_iteration;
-  }
-
-  if (operation.has_src_sha256_hash()) {
-    brillo::Blob src_hash;
-    TEST_AND_RETURN_FALSE(HashCalculator::RawHashOfData(src_data, &src_hash));
-    TEST_AND_RETURN_FALSE(ValidateSourceHash(src_hash, operation));
-  }
-
-  vector<Extent> target_extents(operation.dst_extents().begin(),
-                                operation.dst_extents().end());
-  DirectExtentWriter writer;
-  TEST_AND_RETURN_FALSE(writer.Init(target_fd_, target_extents, block_size_));
-  TEST_AND_RETURN_FALSE(
-      ApplyImagePatch(src_data.data(),
-                      src_data.size(),
-                      buffer_.data(),
-                      operation.data_length(),
-                      [](const unsigned char* data, ssize_t len, void* token) {
-                        return reinterpret_cast<ExtentWriter*>(token)
-                                       ->Write(data, len)
-                                   ? len
-                                   : 0;
-                      },
-                      &writer) == 0);
-  TEST_AND_RETURN_FALSE(writer.End());
-
+  TEST_AND_RETURN_FALSE(bsdiff::bspatch(source_path_.c_str(),
+                                        target_path_.c_str(),
+                                        buffer_.data(),
+                                        buffer_.size(),
+                                        input_positions.c_str(),
+                                        output_positions.c_str()) == 0);
   DiscardBuffer(true, buffer_.size());
   return true;
 }
@@ -1640,7 +1625,7 @@
 }
 
 bool DeltaPerformer::CanResumeUpdate(PrefsInterface* prefs,
-                                     string update_check_response_hash) {
+                                     const string& update_check_response_hash) {
   int64_t next_operation = kUpdateStateOperationInvalid;
   if (!(prefs->GetInt64(kPrefsUpdateStateNextOperation, &next_operation) &&
         next_operation != kUpdateStateOperationInvalid &&
diff --git a/payload_consumer/delta_performer.h b/payload_consumer/delta_performer.h
index 4da631f..71d7178 100644
--- a/payload_consumer/delta_performer.h
+++ b/payload_consumer/delta_performer.h
@@ -140,7 +140,7 @@
   // Returns true if a previous update attempt can be continued based on the
   // persistent preferences and the new update check response hash.
   static bool CanResumeUpdate(PrefsInterface* prefs,
-                              std::string update_check_response_hash);
+                              const std::string& update_check_response_hash);
 
   // Resets the persistent update progress state to indicate that an update
   // can't be resumed. Performs a quick update-in-progress reset if |quick| is
@@ -244,13 +244,16 @@
   bool PerformInstallOperation(const InstallOperation& operation);
 
   // These perform a specific type of operation and return true on success.
+  // |error| will be set if source hash mismatch, otherwise |error| might not be
+  // set even if it fails.
   bool PerformReplaceOperation(const InstallOperation& operation);
   bool PerformZeroOrDiscardOperation(const InstallOperation& operation);
   bool PerformMoveOperation(const InstallOperation& operation);
   bool PerformBsdiffOperation(const InstallOperation& operation);
-  bool PerformSourceCopyOperation(const InstallOperation& operation);
-  bool PerformSourceBsdiffOperation(const InstallOperation& operation);
-  bool PerformImgdiffOperation(const InstallOperation& operation);
+  bool PerformSourceCopyOperation(const InstallOperation& operation,
+                                  ErrorCode* error);
+  bool PerformSourceBsdiffOperation(const InstallOperation& operation,
+                                    ErrorCode* error);
 
   // Extracts the payload signature message from the blob on the |operation| if
   // the offset matches the one specified by the manifest. Returns whether the
diff --git a/payload_consumer/delta_performer_unittest.cc b/payload_consumer/delta_performer_unittest.cc
index 52d19e0..12d0708 100644
--- a/payload_consumer/delta_performer_unittest.cc
+++ b/payload_consumer/delta_performer_unittest.cc
@@ -87,60 +87,6 @@
     0x00, 0x00, 0x59, 0x5a,
 };
 
-// Gzipped 'abc', generated with:
-// echo -n abc | minigzip | hexdump -v -e '"    " 12/1 "0x%02x, " "\n"'
-const uint8_t kSourceGzippedData[] = {
-    0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x4b, 0x4c,
-    0x4a, 0x06, 0x00, 0xc2, 0x41, 0x24, 0x35, 0x03, 0x00, 0x00, 0x00,
-};
-
-// Gzipped 'def', generated with:
-// echo -n def | minigzip | hexdump -v -e '"    " 12/1 "0x%02x, " "\n"'
-const uint8_t kTargetGzippedData[] = {
-    0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x4b, 0x49,
-    0x4d, 0x03, 0x00, 0x61, 0xe1, 0xc4, 0x0c, 0x03, 0x00, 0x00, 0x00,
-};
-
-// Imgdiff data, generated with:
-// echo -n abc | minigzip > abc && truncate -s 4096 abc
-// echo -n def | minigzip > def && truncate -s 4096 def
-// imgdiff abc def patch && hexdump -v -e '"    " 12/1 "0x%02x, " "\n"' patch
-const uint8_t kImgdiffData[] = {
-    0x49, 0x4d, 0x47, 0x44, 0x49, 0x46, 0x46, 0x32, 0x03, 0x00, 0x00, 0x00,
-    0x03, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x1f, 0x8b, 0x08, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x02, 0x00, 0x00, 0x00, 0x0a, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x7a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0xf1, 0xff,
-    0xff, 0xff, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf1, 0x0f,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x42, 0x53, 0x44, 0x49, 0x46, 0x46, 0x34, 0x30, 0x2a, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x5a,
-    0x68, 0x39, 0x31, 0x41, 0x59, 0x26, 0x53, 0x59, 0xc3, 0xc8, 0xfb, 0x1f,
-    0x00, 0x00, 0x01, 0x40, 0x00, 0x5c, 0x00, 0x20, 0x00, 0x30, 0xcd, 0x34,
-    0x12, 0x34, 0x54, 0x60, 0x5c, 0xce, 0x2e, 0xe4, 0x8a, 0x70, 0xa1, 0x21,
-    0x87, 0x91, 0xf6, 0x3e, 0x42, 0x5a, 0x68, 0x39, 0x17, 0x72, 0x45, 0x38,
-    0x50, 0x90, 0x00, 0x00, 0x00, 0x00, 0x42, 0x5a, 0x68, 0x39, 0x31, 0x41,
-    0x59, 0x26, 0x53, 0x59, 0x42, 0x3c, 0xb0, 0xf9, 0x00, 0x00, 0x00, 0x01,
-    0x00, 0x07, 0x00, 0x20, 0x00, 0x21, 0x98, 0x19, 0x84, 0x61, 0x77, 0x24,
-    0x53, 0x85, 0x09, 0x04, 0x23, 0xcb, 0x0f, 0x90, 0x42, 0x53, 0x44, 0x49,
-    0x46, 0x46, 0x34, 0x30, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x35, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf1, 0x0f, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x42, 0x5a, 0x68, 0x39, 0x31, 0x41, 0x59, 0x26,
-    0x53, 0x59, 0x6f, 0x02, 0x77, 0xf3, 0x00, 0x00, 0x07, 0x40, 0x41, 0xe0,
-    0x10, 0xc0, 0x00, 0x00, 0x02, 0x20, 0x00, 0x20, 0x00, 0x21, 0x29, 0xa3,
-    0x10, 0x86, 0x03, 0x84, 0x04, 0xae, 0x5f, 0x17, 0x72, 0x45, 0x38, 0x50,
-    0x90, 0x6f, 0x02, 0x77, 0xf3, 0x42, 0x5a, 0x68, 0x39, 0x31, 0x41, 0x59,
-    0x26, 0x53, 0x59, 0x71, 0x62, 0xbd, 0xa7, 0x00, 0x00, 0x20, 0x40, 0x32,
-    0xc0, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x80, 0x00, 0x48, 0x20, 0x00,
-    0x30, 0xc0, 0x02, 0xa5, 0x19, 0xa5, 0x92, 0x6f, 0xc2, 0x5d, 0xac, 0x0e,
-    0x17, 0x72, 0x45, 0x38, 0x50, 0x90, 0x71, 0x62, 0xbd, 0xa7, 0x42, 0x5a,
-    0x68, 0x39, 0x17, 0x72, 0x45, 0x38, 0x50, 0x90, 0x00, 0x00, 0x00, 0x00,
-};
-
 }  // namespace
 
 class DeltaPerformerTest : public ::testing::Test {
@@ -534,33 +480,6 @@
   EXPECT_EQ(expected_data, ApplyPayload(payload_data, source_path, true));
 }
 
-TEST_F(DeltaPerformerTest, ImgdiffOperationTest) {
-  brillo::Blob imgdiff_data(std::begin(kImgdiffData), std::end(kImgdiffData));
-
-  AnnotatedOperation aop;
-  *(aop.op.add_src_extents()) = ExtentForRange(0, 1);
-  *(aop.op.add_dst_extents()) = ExtentForRange(0, 1);
-  aop.op.set_data_offset(0);
-  aop.op.set_data_length(imgdiff_data.size());
-  aop.op.set_type(InstallOperation::IMGDIFF);
-
-  brillo::Blob payload_data = GeneratePayload(imgdiff_data, {aop}, false);
-
-  string source_path;
-  EXPECT_TRUE(utils::MakeTempFile("Source-XXXXXX", &source_path, nullptr));
-  ScopedPathUnlinker path_unlinker(source_path);
-  brillo::Blob source_data(std::begin(kSourceGzippedData),
-                           std::end(kSourceGzippedData));
-  source_data.resize(4096);  // block size
-  EXPECT_TRUE(utils::WriteFile(
-      source_path.c_str(), source_data.data(), source_data.size()));
-
-  brillo::Blob target_data(std::begin(kTargetGzippedData),
-                           std::end(kTargetGzippedData));
-  target_data.resize(4096);  // block size
-  EXPECT_EQ(target_data, ApplyPayload(payload_data, source_path, true));
-}
-
 TEST_F(DeltaPerformerTest, SourceHashMismatchTest) {
   brillo::Blob expected_data = {'f', 'o', 'o'};
   brillo::Blob actual_data = {'b', 'a', 'r'};
diff --git a/payload_consumer/download_action.cc b/payload_consumer/download_action.cc
index fdbbd72..084848e 100644
--- a/payload_consumer/download_action.cc
+++ b/payload_consumer/download_action.cc
@@ -27,6 +27,7 @@
 
 #include "update_engine/common/action_pipe.h"
 #include "update_engine/common/boot_control_interface.h"
+#include "update_engine/common/error_code_utils.h"
 #include "update_engine/common/utils.h"
 #include "update_engine/omaha_request_params.h"
 #include "update_engine/p2p_manager.h"
@@ -270,7 +271,8 @@
         length, bytes_received_, install_plan_.payload_size);
   }
   if (writer_ && !writer_->Write(bytes, length, &code_)) {
-    LOG(ERROR) << "Error " << code_ << " in DeltaPerformer's Write method when "
+    LOG(ERROR) << "Error " << utils::ErrorCodeToString(code_) << " (" << code_
+               << ") in DeltaPerformer's Write method when "
                << "processing the received payload -- Terminating processing";
     // Delete p2p file, if applicable.
     if (!p2p_file_id_.empty())
diff --git a/payload_consumer/download_action.h b/payload_consumer/download_action.h
index fc32068..285930a 100644
--- a/payload_consumer/download_action.h
+++ b/payload_consumer/download_action.h
@@ -24,8 +24,6 @@
 #include <memory>
 #include <string>
 
-#include <curl/curl.h>
-
 #include "update_engine/common/action.h"
 #include "update_engine/common/boot_control_interface.h"
 #include "update_engine/common/http_fetcher.h"
diff --git a/payload_consumer/download_action_unittest.cc b/payload_consumer/download_action_unittest.cc
index 4ffd35c..5e9ef5c 100644
--- a/payload_consumer/download_action_unittest.cc
+++ b/payload_consumer/download_action_unittest.cc
@@ -395,8 +395,11 @@
   processor.EnqueueAction(&download_action);
   processor.EnqueueAction(&test_action);
 
-  loop.PostTask(FROM_HERE,
-                base::Bind([&processor] { processor.StartProcessing(); }));
+  loop.PostTask(
+      FROM_HERE,
+      base::Bind(
+          [](ActionProcessor* processor) { processor->StartProcessing(); },
+          base::Unretained(&processor)));
   loop.Run();
   EXPECT_FALSE(loop.PendingTasks());
 
diff --git a/payload_consumer/file_descriptor.cc b/payload_consumer/file_descriptor.cc
index 309c60d..8a23dea 100644
--- a/payload_consumer/file_descriptor.cc
+++ b/payload_consumer/file_descriptor.cc
@@ -24,6 +24,8 @@
 
 #include <base/posix/eintr_wrapper.h>
 
+#include "update_engine/common/utils.h"
+
 namespace chromeos_update_engine {
 
 bool EintrSafeFileDescriptor::Open(const char* path, int flags, mode_t mode) {
@@ -65,6 +67,20 @@
   return lseek64(fd_, offset, whence);
 }
 
+uint64_t EintrSafeFileDescriptor::BlockDevSize() {
+  if (fd_ < 0)
+    return 0;
+  struct stat stbuf;
+  if (fstat(fd_, &stbuf) < 0) {
+    PLOG(ERROR) << "Error stat-ing fd " << fd_;
+    return 0;
+  }
+  if (!S_ISBLK(stbuf.st_mode))
+    return 0;
+  off_t block_size = utils::BlockDevSize(fd_);
+  return block_size < 0 ? 0 : block_size;
+}
+
 bool EintrSafeFileDescriptor::BlkIoctl(int request,
                                        uint64_t start,
                                        uint64_t length,
diff --git a/payload_consumer/file_descriptor.h b/payload_consumer/file_descriptor.h
index 3c15415..7bb2974 100644
--- a/payload_consumer/file_descriptor.h
+++ b/payload_consumer/file_descriptor.h
@@ -78,6 +78,10 @@
   // may set errno accordingly.
   virtual off64_t Seek(off64_t offset, int whence) = 0;
 
+  // Return the size of the block device in bytes, or 0 if the device is not a
+  // block device or an error occurred.
+  virtual uint64_t BlockDevSize() = 0;
+
   // Runs a ioctl() on the file descriptor if supported. Returns whether
   // the operation is supported. The |request| can be one of BLKDISCARD,
   // BLKZEROOUT and BLKSECDISCARD to discard, write zeros or securely discard
@@ -119,6 +123,7 @@
   ssize_t Read(void* buf, size_t count) override;
   ssize_t Write(const void* buf, size_t count) override;
   off64_t Seek(off64_t offset, int whence) override;
+  uint64_t BlockDevSize() override;
   bool BlkIoctl(int request,
                 uint64_t start,
                 uint64_t length,
diff --git a/payload_consumer/filesystem_verifier_action.cc b/payload_consumer/filesystem_verifier_action.cc
index 4b476db..5156f96 100644
--- a/payload_consumer/filesystem_verifier_action.cc
+++ b/payload_consumer/filesystem_verifier_action.cc
@@ -91,18 +91,7 @@
 
 void FilesystemVerifierAction::StartPartitionHashing() {
   if (partition_index_ == install_plan_.partitions.size()) {
-    switch (verifier_step_) {
-      case VerifierStep::kVerifySourceHash:
-        // The action will skip kVerifySourceHash step if target partition hash
-        // matches, if we are in this step, it means target hash does not match,
-        // and now that the source hash matches, we should set the error code to
-        // reflect the error in target partition.
-        Cleanup(ErrorCode::kNewRootfsVerificationError);
-        break;
-      case VerifierStep::kVerifyTargetHash:
-        Cleanup(ErrorCode::kSuccess);
-        break;
-    }
+    Cleanup(ErrorCode::kSuccess);
     return;
   }
   InstallPlan::Partition& partition =
@@ -224,7 +213,6 @@
         // switch to kVerifySourceHash step to check if it's because the source
         // partition does not match either.
         verifier_step_ = VerifierStep::kVerifySourceHash;
-        partition_index_ = 0;
       } else {
         partition_index_++;
       }
@@ -256,8 +244,13 @@
                   << "run: .../src/scripts/sha256_partitions.sh .../file.bin";
         return Cleanup(ErrorCode::kDownloadStateInitializationError);
       }
-      partition_index_++;
-      break;
+      // The action will skip kVerifySourceHash step if target partition hash
+      // matches, if we are in this step, it means target hash does not match,
+      // and now that the source partition hash matches, we should set the error
+      // code to reflect the error in target partition.
+      // We only need to verify the source partition which the target hash does
+      // not match, the rest of the partitions don't matter.
+      return Cleanup(ErrorCode::kNewRootfsVerificationError);
   }
   // Start hashing the next partition, if any.
   hasher_.reset();
diff --git a/payload_consumer/install_plan.cc b/payload_consumer/install_plan.cc
index 51e85b3..b04da74 100644
--- a/payload_consumer/install_plan.cc
+++ b/payload_consumer/install_plan.cc
@@ -115,7 +115,8 @@
           target_hash == that.target_hash &&
           run_postinstall == that.run_postinstall &&
           postinstall_path == that.postinstall_path &&
-          filesystem_type == that.filesystem_type);
+          filesystem_type == that.filesystem_type &&
+          postinstall_optional == that.postinstall_optional);
 }
 
 }  // namespace chromeos_update_engine
diff --git a/payload_consumer/install_plan.h b/payload_consumer/install_plan.h
index f9240c7..3f0005c 100644
--- a/payload_consumer/install_plan.h
+++ b/payload_consumer/install_plan.h
@@ -91,6 +91,7 @@
     bool run_postinstall{false};
     std::string postinstall_path;
     std::string filesystem_type;
+    bool postinstall_optional{false};
   };
   std::vector<Partition> partitions;
 
diff --git a/payload_consumer/mtd_file_descriptor.h b/payload_consumer/mtd_file_descriptor.h
index 9ac1ec1..6c945b2 100644
--- a/payload_consumer/mtd_file_descriptor.h
+++ b/payload_consumer/mtd_file_descriptor.h
@@ -40,6 +40,7 @@
   ssize_t Read(void* buf, size_t count) override;
   ssize_t Write(const void* buf, size_t count) override;
   off64_t Seek(off64_t offset, int whence) override;
+  uint64_t BlockDevSize() override { return 0; }
   bool BlkIoctl(int request,
                 uint64_t start,
                 uint64_t length,
@@ -75,6 +76,7 @@
   ssize_t Read(void* buf, size_t count) override;
   ssize_t Write(const void* buf, size_t count) override;
   off64_t Seek(off64_t offset, int whence) override;
+  uint64_t BlockDevSize() override { return 0; }
   bool BlkIoctl(int request,
                 uint64_t start,
                 uint64_t length,
diff --git a/payload_consumer/payload_constants.cc b/payload_consumer/payload_constants.cc
index 3d78e0a..4c11d7a 100644
--- a/payload_consumer/payload_constants.cc
+++ b/payload_consumer/payload_constants.cc
@@ -31,7 +31,6 @@
 const char kLegacyPartitionNameRoot[] = "system";
 
 const char kDeltaMagic[4] = {'C', 'r', 'A', 'U'};
-const char kBspatchPath[] = "bspatch";
 
 const char* InstallOperationTypeName(InstallOperation_Type op_type) {
   switch (op_type) {
diff --git a/payload_consumer/postinstall_runner_action.cc b/payload_consumer/postinstall_runner_action.cc
index dd40485..27a9ed6 100644
--- a/payload_consumer/postinstall_runner_action.cc
+++ b/payload_consumer/postinstall_runner_action.cc
@@ -58,8 +58,8 @@
   install_plan_ = GetInputObject();
 
   if (install_plan_.powerwash_required) {
-    if (utils::CreatePowerwashMarkerFile(powerwash_marker_file_)) {
-      powerwash_marker_created_ = true;
+    if (hardware_->SchedulePowerwash()) {
+      powerwash_scheduled_ = true;
     } else {
       return CompletePostinstall(ErrorCode::kPostinstallPowerwashError);
     }
@@ -118,6 +118,13 @@
   fs_mount_dir_ = temp_dir.value();
 #endif  // __ANDROID__
 
+  // Double check that the fs_mount_dir is not busy with a previous mounted
+  // filesystem from a previous crashed postinstall step.
+  if (utils::IsMountpoint(fs_mount_dir_)) {
+    LOG(INFO) << "Found previously mounted filesystem at " << fs_mount_dir_;
+    utils::UnmountFilesystem(fs_mount_dir_);
+  }
+
   base::FilePath postinstall_path(partition.postinstall_path);
   if (postinstall_path.IsAbsolute()) {
     LOG(ERROR) << "Invalid absolute path passed to postinstall, use a relative"
@@ -240,7 +247,8 @@
 
 bool PostinstallRunnerAction::ProcessProgressLine(const string& line) {
   double frac = 0;
-  if (sscanf(line.c_str(), "global_progress %lf", &frac) == 1) {
+  if (sscanf(line.c_str(), "global_progress %lf", &frac) == 1 &&
+      !std::isnan(frac)) {
     ReportProgress(frac);
     return true;
   }
@@ -304,7 +312,14 @@
       // to get back to FW A.
       error_code = ErrorCode::kPostinstallFirmwareRONotUpdatable;
     }
-    return CompletePostinstall(error_code);
+
+    // If postinstall script for this partition is optional we can ignore the
+    // result.
+    if (install_plan_.partitions[current_partition_].postinstall_optional) {
+      LOG(INFO) << "Ignoring postinstall failure since it is optional";
+    } else {
+      return CompletePostinstall(error_code);
+    }
   }
   accumulated_weight_ += partition_weight_[current_partition_];
   current_partition_++;
@@ -327,9 +342,9 @@
   if (error_code != ErrorCode::kSuccess) {
     LOG(ERROR) << "Postinstall action failed.";
 
-    // Undo any changes done to trigger Powerwash using clobber-state.
-    if (powerwash_marker_created_)
-      utils::DeletePowerwashMarkerFile(powerwash_marker_file_);
+    // Undo any changes done to trigger Powerwash.
+    if (powerwash_scheduled_)
+      hardware_->CancelPowerwash();
 
     return;
   }
diff --git a/payload_consumer/postinstall_runner_action.h b/payload_consumer/postinstall_runner_action.h
index 26e18a1..2e48e11 100644
--- a/payload_consumer/postinstall_runner_action.h
+++ b/payload_consumer/postinstall_runner_action.h
@@ -24,6 +24,8 @@
 #include <gtest/gtest_prod.h>
 
 #include "update_engine/common/action.h"
+#include "update_engine/common/boot_control_interface.h"
+#include "update_engine/common/hardware_interface.h"
 #include "update_engine/payload_consumer/install_plan.h"
 
 // The Postinstall Runner Action is responsible for running the postinstall
@@ -35,8 +37,9 @@
 
 class PostinstallRunnerAction : public InstallPlanAction {
  public:
-  explicit PostinstallRunnerAction(BootControlInterface* boot_control)
-      : PostinstallRunnerAction(boot_control, nullptr) {}
+  PostinstallRunnerAction(BootControlInterface* boot_control,
+                          HardwareInterface* hardware)
+      : boot_control_(boot_control), hardware_(hardware) {}
 
   // InstallPlanAction overrides.
   void PerformAction() override;
@@ -63,12 +66,6 @@
   friend class PostinstallRunnerActionTest;
   FRIEND_TEST(PostinstallRunnerActionTest, ProcessProgressLineTest);
 
-  // Special constructor used for testing purposes.
-  PostinstallRunnerAction(BootControlInterface* boot_control,
-                          const char* powerwash_marker_file)
-      : boot_control_(boot_control),
-        powerwash_marker_file_(powerwash_marker_file) {}
-
   void PerformPartitionPostinstall();
 
   // Called whenever the |progress_fd_| has data available to read.
@@ -127,13 +124,12 @@
   // The BootControlInerface used to mark the new slot as ready.
   BootControlInterface* boot_control_;
 
-  // True if Powerwash Marker was created before invoking post-install script.
-  // False otherwise. Used for cleaning up if post-install fails.
-  bool powerwash_marker_created_{false};
+  // HardwareInterface used to signal powerwash.
+  HardwareInterface* hardware_;
 
-  // Non-null value will cause post-install to override the default marker
-  // file name; used for testing.
-  const char* powerwash_marker_file_;
+  // Whether the Powerwash was scheduled before invoking post-install script.
+  // Used for cleaning up if post-install fails.
+  bool powerwash_scheduled_{false};
 
   // Postinstall command currently running, or 0 if no program running.
   pid_t current_command_{0};
diff --git a/payload_consumer/postinstall_runner_action_unittest.cc b/payload_consumer/postinstall_runner_action_unittest.cc
index 3b6b49a..e82a866 100644
--- a/payload_consumer/postinstall_runner_action_unittest.cc
+++ b/payload_consumer/postinstall_runner_action_unittest.cc
@@ -26,7 +26,6 @@
 
 #include <base/bind.h>
 #include <base/files/file_util.h>
-#include <base/files/scoped_temp_dir.h>
 #include <base/message_loop/message_loop.h>
 #include <base/strings/string_util.h>
 #include <base/strings/stringprintf.h>
@@ -38,6 +37,7 @@
 
 #include "update_engine/common/constants.h"
 #include "update_engine/common/fake_boot_control.h"
+#include "update_engine/common/fake_hardware.h"
 #include "update_engine/common/test_utils.h"
 #include "update_engine/common/utils.h"
 
@@ -88,10 +88,6 @@
     loop_.SetAsCurrent();
     async_signal_handler_.Init();
     subprocess_.Init(&async_signal_handler_);
-    ASSERT_TRUE(working_dir_.CreateUniqueTempDir());
-    // We use a test-specific powerwash marker file, to avoid race conditions.
-    powerwash_marker_file_ =
-        working_dir_.path().Append("factory_install_reset").value();
     // These tests use the postinstall files generated by "generate_images.sh"
     // stored in the "disk_ext2_unittest.img" image.
     postinstall_image_ =
@@ -154,14 +150,11 @@
   brillo::AsynchronousSignalHandler async_signal_handler_;
   Subprocess subprocess_;
 
-  // A temporary working directory used for the test.
-  base::ScopedTempDir working_dir_;
-  string powerwash_marker_file_;
-
   // The path to the postinstall sample image.
   string postinstall_image_;
 
   FakeBootControl fake_boot_control_;
+  FakeHardware fake_hardware_;
   PostinstActionProcessorDelegate processor_delegate_;
 
   // The PostinstallRunnerAction delegate receiving the progress updates.
@@ -189,8 +182,7 @@
   install_plan.download_url = "http://127.0.0.1:8080/update";
   install_plan.powerwash_required = powerwash_required;
   feeder_action.set_obj(install_plan);
-  PostinstallRunnerAction runner_action(&fake_boot_control_,
-                                        powerwash_marker_file_.c_str());
+  PostinstallRunnerAction runner_action(&fake_boot_control_, &fake_hardware_);
   postinstall_action_ = &runner_action;
   runner_action.set_delegate(setup_action_delegate_);
   BondActions(&feeder_action, &runner_action);
@@ -201,8 +193,11 @@
   processor.EnqueueAction(&collector_action);
   processor.set_delegate(&processor_delegate_);
 
-  loop_.PostTask(FROM_HERE,
-                 base::Bind([&processor] { processor.StartProcessing(); }));
+  loop_.PostTask(
+      FROM_HERE,
+      base::Bind(
+          [](ActionProcessor* processor) { processor->StartProcessing(); },
+          base::Unretained(&processor)));
   loop_.Run();
   ASSERT_FALSE(processor.IsRunning());
   postinstall_action_ = nullptr;
@@ -216,8 +211,7 @@
 }
 
 TEST_F(PostinstallRunnerActionTest, ProcessProgressLineTest) {
-  PostinstallRunnerAction action(&fake_boot_control_,
-                                 powerwash_marker_file_.c_str());
+  PostinstallRunnerAction action(&fake_boot_control_, &fake_hardware_);
   testing::StrictMock<MockPostinstallRunnerActionDelegate> mock_delegate_;
   action.set_delegate(&mock_delegate_);
 
@@ -226,15 +220,23 @@
   action.accumulated_weight_ = 1;
   action.total_weight_ = 8;
 
-  // 50% of the second actions is 2/8 = 0.25 of the total.
+  // 50% of the second action is 2/8 = 0.25 of the total.
   EXPECT_CALL(mock_delegate_, ProgressUpdate(0.25));
   action.ProcessProgressLine("global_progress 0.5");
   testing::Mock::VerifyAndClearExpectations(&mock_delegate_);
 
+  // 1.5 should be read as 100%, to catch rounding error cases like 1.000001.
+  // 100% of the second is 3/8 of the total.
+  EXPECT_CALL(mock_delegate_, ProgressUpdate(0.375));
+  action.ProcessProgressLine("global_progress 1.5");
+  testing::Mock::VerifyAndClearExpectations(&mock_delegate_);
+
   // None of these should trigger a progress update.
   action.ProcessProgressLine("foo_bar");
   action.ProcessProgressLine("global_progress");
   action.ProcessProgressLine("global_progress ");
+  action.ProcessProgressLine("global_progress NaN");
+  action.ProcessProgressLine("global_progress Exception in ... :)");
 }
 
 // Test that postinstall succeeds in the simple case of running the default
@@ -246,7 +248,7 @@
   EXPECT_TRUE(processor_delegate_.processing_done_called_);
 
   // Since powerwash_required was false, this should not trigger a powerwash.
-  EXPECT_FALSE(utils::FileExists(powerwash_marker_file_.c_str()));
+  EXPECT_FALSE(fake_hardware_.IsPowerwashScheduled());
 }
 
 TEST_F(PostinstallRunnerActionTest, RunAsRootRunSymlinkFileTest) {
@@ -261,11 +263,8 @@
   RunPosinstallAction(loop.dev(), "bin/postinst_example", true);
   EXPECT_EQ(ErrorCode::kSuccess, processor_delegate_.code_);
 
-  // Check that the powerwash marker file was set.
-  string actual_cmd;
-  EXPECT_TRUE(base::ReadFileToString(base::FilePath(powerwash_marker_file_),
-                                     &actual_cmd));
-  EXPECT_EQ(kPowerwashCommand, actual_cmd);
+  // Check that powerwash was scheduled.
+  EXPECT_TRUE(fake_hardware_.IsPowerwashScheduled());
 }
 
 // Runs postinstall from a partition file that doesn't mount, so it should
@@ -276,7 +275,7 @@
 
   // In case of failure, Postinstall should not signal a powerwash even if it
   // was requested.
-  EXPECT_FALSE(utils::FileExists(powerwash_marker_file_.c_str()));
+  EXPECT_FALSE(fake_hardware_.IsPowerwashScheduled());
 }
 
 // Check that the failures from the postinstall script cause the action to
diff --git a/payload_generator/ab_generator.cc b/payload_generator/ab_generator.cc
index 8c736a5..efb8ccf 100644
--- a/payload_generator/ab_generator.cc
+++ b/payload_generator/ab_generator.cc
@@ -110,7 +110,7 @@
   int curr_src_ext_index = 0;
   Extent curr_src_ext = original_op.src_extents(curr_src_ext_index);
   for (int i = 0; i < original_op.dst_extents_size(); i++) {
-    Extent dst_ext = original_op.dst_extents(i);
+    const Extent& dst_ext = original_op.dst_extents(i);
     // The new operation which will have only one dst extent.
     InstallOperation new_op;
     uint64_t blocks_left = dst_ext.num_blocks();
@@ -165,7 +165,7 @@
 
   uint32_t data_offset = original_op.data_offset();
   for (int i = 0; i < original_op.dst_extents_size(); i++) {
-    Extent dst_ext = original_op.dst_extents(i);
+    const Extent& dst_ext = original_op.dst_extents(i);
     // Make a new operation with only one dst extent.
     InstallOperation new_op;
     *(new_op.add_dst_extents()) = dst_ext;
diff --git a/payload_generator/ab_generator_unittest.cc b/payload_generator/ab_generator_unittest.cc
index 224880d..3fd2323 100644
--- a/payload_generator/ab_generator_unittest.cc
+++ b/payload_generator/ab_generator_unittest.cc
@@ -42,7 +42,7 @@
 
 namespace {
 
-bool ExtentEquals(Extent ext, uint64_t start_block, uint64_t num_blocks) {
+bool ExtentEquals(const Extent& ext, uint64_t start_block, uint64_t num_blocks) {
   return ext.start_block() == start_block && ext.num_blocks() == num_blocks;
 }
 
diff --git a/payload_generator/delta_diff_generator.cc b/payload_generator/delta_diff_generator.cc
index 91d212e..1db2144 100644
--- a/payload_generator/delta_diff_generator.cc
+++ b/payload_generator/delta_diff_generator.cc
@@ -92,20 +92,8 @@
 
       // Select payload generation strategy based on the config.
       unique_ptr<OperationsGenerator> strategy;
-      // We don't efficiently support deltas on squashfs. For now, we will
-      // produce full operations in that case.
-      if (!old_part.path.empty() &&
-          !diff_utils::IsSquashfs4Filesystem(new_part.path)) {
+      if (!old_part.path.empty()) {
         // Delta update.
-        if (diff_utils::IsExtFilesystem(new_part.path)) {
-          LOG_IF(WARNING, old_part.size != new_part.size)
-              << "Old and new filesystems have different size.";
-          // TODO(deymo): Our tools only support growing the filesystem size
-          // during an update. Remove this check when that's fixed.
-          // crbug.com/192136
-          LOG_IF(FATAL, old_part.size > new_part.size)
-              << "Shirking the filesystem size is not supported at the moment.";
-        }
         if (config.version.minor == kInPlaceMinorPayloadVersion) {
           LOG(INFO) << "Using generator InplaceGenerator().";
           strategy.reset(new InplaceGenerator());
diff --git a/payload_generator/delta_diff_utils.cc b/payload_generator/delta_diff_utils.cc
index 6f895f6..44aff7a 100644
--- a/payload_generator/delta_diff_utils.cc
+++ b/payload_generator/delta_diff_utils.cc
@@ -17,7 +17,12 @@
 #include "update_engine/payload_generator/delta_diff_utils.h"
 
 #include <endian.h>
+// TODO: Remove these pragmas when b/35721782 is fixed.
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wmacro-redefined"
 #include <ext2fs/ext2fs.h>
+#pragma clang diagnostic pop
+
 
 #include <algorithm>
 #include <map>
@@ -115,19 +120,9 @@
   size_t src_idx = 0;
   size_t dst_idx = 0;
   uint64_t src_offset = 0, dst_offset = 0;
-  bool new_src = true, new_dst = true;
   size_t removed_bytes = 0, nonfull_block_bytes;
   bool do_remove = false;
   while (src_idx < src_extents->size() && dst_idx < dst_extents->size()) {
-    if (new_src) {
-      src_offset = 0;
-      new_src = false;
-    }
-    if (new_dst) {
-      dst_offset = 0;
-      new_dst = false;
-    }
-
     do_remove = ((*src_extents)[src_idx].start_block() + src_offset ==
                  (*dst_extents)[dst_idx].start_block() + dst_offset);
 
@@ -140,10 +135,17 @@
     src_offset += min_num_blocks;
     dst_offset += min_num_blocks;
 
-    new_src = ProcessExtentBlockRange(src_extents, &src_idx, do_remove,
-                                      prev_src_offset, src_offset);
-    new_dst = ProcessExtentBlockRange(dst_extents, &dst_idx, do_remove,
-                                      prev_dst_offset, dst_offset);
+    bool new_src = ProcessExtentBlockRange(src_extents, &src_idx, do_remove,
+                                           prev_src_offset, src_offset);
+    bool new_dst = ProcessExtentBlockRange(dst_extents, &dst_idx, do_remove,
+                                           prev_dst_offset, dst_offset);
+    if (new_src) {
+      src_offset = 0;
+    }
+    if (new_dst) {
+      dst_offset = 0;
+    }
+
     if (do_remove)
       removed_bytes += min_num_blocks * kBlockSize;
   }
@@ -183,8 +185,8 @@
       aops,
       old_part.path,
       new_part.path,
-      old_part.fs_interface ? old_part.fs_interface->GetBlockCount() : 0,
-      new_part.fs_interface->GetBlockCount(),
+      old_part.size / kBlockSize,
+      new_part.size / kBlockSize,
       soft_chunk_blocks,
       version,
       blob_file,
@@ -323,6 +325,13 @@
   for (uint64_t block = old_num_blocks; block-- > 0; ) {
     if (old_block_ids[block] != 0 && !old_visited_blocks->ContainsBlock(block))
       old_blocks_map[old_block_ids[block]].push_back(block);
+
+    // Mark all zeroed blocks in the old image as "used" since it doesn't make
+    // any sense to spend I/O to read zeros from the source partition and more
+    // importantly, these could sometimes be blocks discarded in the SSD which
+    // would read non-zero values.
+    if (old_block_ids[block] == 0)
+      old_visited_blocks->AddBlock(block);
   }
 
   // The collection of blocks in the new partition with just zeros. This is a
@@ -363,7 +372,7 @@
   // TODO(deymo): Produce ZERO operations instead of calling DeltaReadFile().
   size_t num_ops = aops->size();
   new_visited_blocks->AddExtents(new_zeros);
-  for (Extent extent : new_zeros) {
+  for (const Extent& extent : new_zeros) {
     TEST_AND_RETURN_FALSE(DeltaReadFile(aops,
                                         "",
                                         new_part,
@@ -384,7 +393,7 @@
   uint64_t used_blocks = 0;
   old_visited_blocks->AddExtents(old_identical_blocks);
   new_visited_blocks->AddExtents(new_identical_blocks);
-  for (Extent extent : new_identical_blocks) {
+  for (const Extent& extent : new_identical_blocks) {
     // We split the operation at the extent boundary or when bigger than
     // chunk_blocks.
     for (uint64_t op_block_offset = 0; op_block_offset < extent.num_blocks();
@@ -397,8 +406,8 @@
                            : InstallOperation::MOVE);
 
       uint64_t chunk_num_blocks =
-        std::min(extent.num_blocks() - op_block_offset,
-                 static_cast<uint64_t>(chunk_blocks));
+          std::min(static_cast<uint64_t>(extent.num_blocks()) - op_block_offset,
+                   static_cast<uint64_t>(chunk_blocks));
 
       // The current operation represents the move/copy operation for the
       // sublist starting at |used_blocks| of length |chunk_num_blocks| where
@@ -798,32 +807,6 @@
   return true;
 }
 
-bool IsSquashfs4Filesystem(const string& device) {
-  brillo::Blob header;
-  // See fs/squashfs/squashfs_fs.h for format details. We only support
-  // Squashfs 4.x little endian.
-
-  // The first 96 is enough to read the squashfs superblock.
-  const ssize_t kSquashfsSuperBlockSize = 96;
-  if (!utils::ReadFileChunk(device, 0, kSquashfsSuperBlockSize, &header) ||
-      header.size() < kSquashfsSuperBlockSize)
-    return false;
-
-  // Check magic, squashfs_fs.h: SQUASHFS_MAGIC
-  if (memcmp(header.data(), "hsqs", 4) != 0)
-    return false;  // Only little endian is supported.
-
-  // squashfs_fs.h: struct squashfs_super_block.s_major
-  uint16_t s_major = *reinterpret_cast<const uint16_t*>(
-      header.data() + 5 * sizeof(uint32_t) + 4 * sizeof(uint16_t));
-
-  if (s_major != 4) {
-    LOG(ERROR) << "Found unsupported squashfs major version " << s_major;
-    return false;
-  }
-  return true;
-}
-
 }  // namespace diff_utils
 
 }  // namespace chromeos_update_engine
diff --git a/payload_generator/delta_diff_utils.h b/payload_generator/delta_diff_utils.h
index 4cc85fc..7254bca 100644
--- a/payload_generator/delta_diff_utils.h
+++ b/payload_generator/delta_diff_utils.h
@@ -143,11 +143,6 @@
 // false.
 bool IsExtFilesystem(const std::string& device);
 
-// Returns whether the filesystem is a squashfs4 filesystem. In case of failure,
-// such as if the file |device| doesn't exists or can't be read, it returns
-// false.
-bool IsSquashfs4Filesystem(const std::string& device);
-
 }  // namespace diff_utils
 
 }  // namespace chromeos_update_engine
diff --git a/payload_generator/delta_diff_utils_unittest.cc b/payload_generator/delta_diff_utils_unittest.cc
index ce02a54..232eab7 100644
--- a/payload_generator/delta_diff_utils_unittest.cc
+++ b/payload_generator/delta_diff_utils_unittest.cc
@@ -40,43 +40,6 @@
 
 namespace {
 
-// Squashfs example filesystem, generated with:
-//   echo hola>hola
-//   mksquashfs hola hola.sqfs -noappend -nopad
-//   hexdump hola.sqfs -e '16/1 "%02x, " "\n"'
-const uint8_t kSquashfsFile[] = {
-  0x68, 0x73, 0x71, 0x73, 0x02, 0x00, 0x00, 0x00,  // magic, inodes
-  0x3e, 0x49, 0x61, 0x54, 0x00, 0x00, 0x02, 0x00,
-  0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x11, 0x00,
-  0xc0, 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00,  // flags, noids, major, minor
-  0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // root_inode
-  0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // bytes_used
-  0xe7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x93, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0xbd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0xd5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x68, 0x6f, 0x6c, 0x61, 0x0a, 0x2c, 0x00, 0x78,
-  0xda, 0x63, 0x62, 0x58, 0xc2, 0xc8, 0xc0, 0xc0,
-  0xc8, 0xd0, 0x6b, 0x91, 0x18, 0x02, 0x64, 0xa0,
-  0x00, 0x56, 0x06, 0x90, 0xcc, 0x7f, 0xb0, 0xbc,
-  0x9d, 0x67, 0x62, 0x08, 0x13, 0x54, 0x1c, 0x44,
-  0x4b, 0x03, 0x31, 0x33, 0x10, 0x03, 0x00, 0xb5,
-  0x87, 0x04, 0x89, 0x16, 0x00, 0x78, 0xda, 0x63,
-  0x60, 0x80, 0x00, 0x46, 0x28, 0xcd, 0xc4, 0xc0,
-  0xcc, 0x90, 0x91, 0x9f, 0x93, 0x08, 0x00, 0x04,
-  0x70, 0x01, 0xab, 0x10, 0x80, 0x60, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
-  0x01, 0x00, 0x00, 0x00, 0x00, 0xab, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x78,
-  0xda, 0x63, 0x60, 0x80, 0x00, 0x05, 0x28, 0x0d,
-  0x00, 0x01, 0x10, 0x00, 0x21, 0xc5, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x80, 0x99,
-  0xcd, 0x02, 0x00, 0x88, 0x13, 0x00, 0x00, 0xdd,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-
 // Writes the |data| in the blocks specified by |extents| on the partition
 // |part_path|. The |data| size could be smaller than the size of the blocks
 // passed.
@@ -93,8 +56,9 @@
       break;
     TEST_AND_RETURN_FALSE(
         fseek(fp.get(), extent.start_block() * block_size, SEEK_SET) == 0);
-    uint64_t to_write = std::min(extent.num_blocks() * block_size,
-                                 data.size() - offset);
+    uint64_t to_write =
+        std::min(static_cast<uint64_t>(extent.num_blocks()) * block_size,
+                 static_cast<uint64_t>(data.size()) - offset);
     TEST_AND_RETURN_FALSE(
         fwrite(data.data() + offset, 1, to_write, fp.get()) == to_write);
     offset += extent.num_blocks() * block_size;
@@ -747,26 +711,4 @@
       test_utils::GetBuildArtifactsPath("gen/disk_ext2_4k.img")));
 }
 
-TEST_F(DeltaDiffUtilsTest, IsSquashfs4FilesystemTest) {
-  uint8_t buffer[sizeof(kSquashfsFile)];
-  memcpy(buffer, kSquashfsFile, sizeof(kSquashfsFile));
-  string img;
-  EXPECT_TRUE(utils::MakeTempFile("img.XXXXXX", &img, nullptr));
-  ScopedPathUnlinker img_unlinker(img);
-
-  // Not enough bytes passed.
-  EXPECT_TRUE(utils::WriteFile(img.c_str(), buffer, 10));
-  EXPECT_FALSE(diff_utils::IsSquashfs4Filesystem(img));
-
-  // The whole file system is passed, which is enough for parsing.
-  EXPECT_TRUE(utils::WriteFile(img.c_str(), buffer, sizeof(kSquashfsFile)));
-  EXPECT_TRUE(diff_utils::IsSquashfs4Filesystem(img));
-
-  // Modify the major version to 5.
-  uint16_t* s_major = reinterpret_cast<uint16_t*>(buffer + 0x1c);
-  *s_major = 5;
-  EXPECT_TRUE(utils::WriteFile(img.c_str(), buffer, sizeof(kSquashfsFile)));
-  EXPECT_FALSE(diff_utils::IsSquashfs4Filesystem(img));
-}
-
 }  // namespace chromeos_update_engine
diff --git a/payload_generator/ext2_filesystem.cc b/payload_generator/ext2_filesystem.cc
index b452b41..ee2f8c2 100644
--- a/payload_generator/ext2_filesystem.cc
+++ b/payload_generator/ext2_filesystem.cc
@@ -17,8 +17,12 @@
 #include "update_engine/payload_generator/ext2_filesystem.h"
 
 #include <et/com_err.h>
+// TODO: Remove these pragmas when b/35721782 is fixed.
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wmacro-redefined"
 #include <ext2fs/ext2_io.h>
 #include <ext2fs/ext2fs.h>
+#pragma clang diagnostic pop
 
 #include <map>
 #include <set>
diff --git a/payload_generator/ext2_filesystem.h b/payload_generator/ext2_filesystem.h
index 248e208..1a4e1a1 100644
--- a/payload_generator/ext2_filesystem.h
+++ b/payload_generator/ext2_filesystem.h
@@ -23,7 +23,11 @@
 #include <string>
 #include <vector>
 
+// TODO: Remove these pragmas when b/35721782 is fixed.
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wmacro-redefined"
 #include <ext2fs/ext2fs.h>
+#pragma clang diagnostic pop
 
 namespace chromeos_update_engine {
 
diff --git a/payload_generator/extent_ranges.cc b/payload_generator/extent_ranges.cc
index 848fdc7..0e0cdf7 100644
--- a/payload_generator/extent_ranges.cc
+++ b/payload_generator/extent_ranges.cc
@@ -24,6 +24,7 @@
 #include <base/logging.h>
 
 #include "update_engine/payload_consumer/payload_constants.h"
+#include "update_engine/payload_generator/extent_utils.h"
 
 using std::set;
 using std::vector;
@@ -249,6 +250,7 @@
     out.back().set_num_blocks(blocks_needed);
     break;
   }
+  CHECK(out_blocks == BlocksInExtents(out));
   return out;
 }
 
diff --git a/payload_generator/extent_utils.cc b/payload_generator/extent_utils.cc
index 72e4b7c..89ccca2 100644
--- a/payload_generator/extent_utils.cc
+++ b/payload_generator/extent_utils.cc
@@ -99,8 +99,9 @@
 string ExtentsToString(const vector<Extent>& extents) {
   string ext_str;
   for (const Extent& e : extents)
-    ext_str += base::StringPrintf(
-        "[%" PRIu64 ", %" PRIu64 "] ", e.start_block(), e.num_blocks());
+    ext_str += base::StringPrintf("[%" PRIu64 ", %" PRIu64 "] ",
+                                  static_cast<uint64_t>(e.start_block()),
+                                  static_cast<uint64_t>(e.num_blocks()));
   return ext_str;
 }
 
diff --git a/payload_generator/fake_filesystem.cc b/payload_generator/fake_filesystem.cc
index c765286..234e2f6 100644
--- a/payload_generator/fake_filesystem.cc
+++ b/payload_generator/fake_filesystem.cc
@@ -39,7 +39,7 @@
 }
 
 void FakeFilesystem::AddFile(const std::string& filename,
-                             const std::vector<Extent> extents) {
+                             const std::vector<Extent>& extents) {
   File file;
   file.name = filename;
   file.extents = extents;
diff --git a/payload_generator/fake_filesystem.h b/payload_generator/fake_filesystem.h
index a14b8d3..1b13920 100644
--- a/payload_generator/fake_filesystem.h
+++ b/payload_generator/fake_filesystem.h
@@ -43,7 +43,7 @@
   // Fake methods.
 
   // Add a file to the list of fake files.
-  void AddFile(const std::string& filename, const std::vector<Extent> extents);
+  void AddFile(const std::string& filename, const std::vector<Extent>& extents);
 
   // Sets the PAYLOAD_MINOR_VERSION key stored by LoadSettings(). Use a negative
   // value to produce an error in LoadSettings().
diff --git a/payload_generator/generate_delta_main.cc b/payload_generator/generate_delta_main.cc
index 9014369..776650f 100644
--- a/payload_generator/generate_delta_main.cc
+++ b/payload_generator/generate_delta_main.cc
@@ -20,7 +20,6 @@
 #include <sys/types.h>
 #include <unistd.h>
 
-#include <set>
 #include <string>
 #include <vector>
 
@@ -46,7 +45,6 @@
 // and an output file as arguments and the path to an output file and
 // generates a delta that can be sent to Chrome OS clients.
 
-using std::set;
 using std::string;
 using std::vector;
 
@@ -259,6 +257,17 @@
                 "a single argument with a colon between paths, e.g. "
                 "/path/to/part:/path/to/part2:/path/to/last_part . Path has "
                 "to match the order of partition_names.");
+  DEFINE_string(old_mapfiles,
+                "",
+                "Path to the .map files associated with the partition files "
+                "in the old partition. The .map file is normally generated "
+                "when creating the image in Android builds. Only recommended "
+                "for unsupported filesystem. Pass multiple files separated by "
+                "a colon as with -old_partitions.");
+  DEFINE_string(new_mapfiles,
+                "",
+                "Path to the .map files associated with the partition files "
+                "in the new partition, similar to the -old_mapfiles flag.");
   DEFINE_string(partition_names,
                 string(kLegacyPartitionNameRoot) + ":" +
                 kLegacyPartitionNameKernel,
@@ -401,6 +410,16 @@
   // PayloadGenerationConfig.
   PayloadGenerationConfig payload_config;
   vector<string> partition_names, old_partitions, new_partitions;
+  vector<string> old_mapfiles, new_mapfiles;
+
+  if (!FLAGS_old_mapfiles.empty()) {
+    old_mapfiles = base::SplitString(
+        FLAGS_old_mapfiles, ":", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
+  }
+  if (!FLAGS_new_mapfiles.empty()) {
+    new_mapfiles = base::SplitString(
+        FLAGS_new_mapfiles, ":", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
+  }
 
   partition_names =
       base::SplitString(FLAGS_partition_names, ":", base::TRIM_WHITESPACE,
@@ -445,6 +464,8 @@
         << "Partition name can't be empty, see --partition_names.";
     payload_config.target.partitions.emplace_back(partition_names[i]);
     payload_config.target.partitions.back().path = new_partitions[i];
+    if (i < new_mapfiles.size())
+      payload_config.target.partitions.back().mapfile_path = new_mapfiles[i];
   }
 
   if (payload_config.is_delta) {
@@ -461,6 +482,8 @@
     for (size_t i = 0; i < partition_names.size(); i++) {
       payload_config.source.partitions.emplace_back(partition_names[i]);
       payload_config.source.partitions.back().path = old_partitions[i];
+      if (i < old_mapfiles.size())
+        payload_config.source.partitions.back().mapfile_path = old_mapfiles[i];
     }
   }
 
diff --git a/payload_generator/inplace_generator.cc b/payload_generator/inplace_generator.cc
index 30dbafc..bc140e8 100644
--- a/payload_generator/inplace_generator.cc
+++ b/payload_generator/inplace_generator.cc
@@ -677,17 +677,13 @@
 
   enum BlockField { READER = 0, WRITER, BLOCK_FIELD_COUNT };
   for (int field = READER; field < BLOCK_FIELD_COUNT; field++) {
-    const int extents_size =
-        (field == READER) ? operation.src_extents_size() :
-        operation.dst_extents_size();
     const char* past_participle = (field == READER) ? "read" : "written";
     const google::protobuf::RepeatedPtrField<Extent>& extents =
         (field == READER) ? operation.src_extents() : operation.dst_extents();
     Vertex::Index Block::*access_type = (field == READER) ?
         &Block::reader : &Block::writer;
 
-    for (int i = 0; i < extents_size; i++) {
-      const Extent& extent = extents.Get(i);
+    for (const Extent& extent : extents) {
       for (uint64_t block = extent.start_block();
            block < (extent.start_block() + extent.num_blocks()); block++) {
         if ((*blocks)[block].*access_type != Vertex::kInvalidIndex) {
@@ -708,7 +704,7 @@
 bool InplaceGenerator::AddInstallOpToGraph(Graph* graph,
                                            Vertex::Index existing_vertex,
                                            vector<Block>* blocks,
-                                           const InstallOperation operation,
+                                           const InstallOperation& operation,
                                            const string& op_name) {
   Vertex::Index vertex = existing_vertex;
   if (vertex == Vertex::kInvalidIndex) {
@@ -738,6 +734,7 @@
 }
 
 bool InplaceGenerator::ResolveReadAfterWriteDependencies(
+    const PartitionConfig& old_part,
     const PartitionConfig& new_part,
     uint64_t partition_size,
     size_t block_size,
@@ -746,7 +743,7 @@
   // Convert the operations to the graph.
   Graph graph;
   CheckGraph(graph);
-  vector<Block> blocks(new_part.size / block_size);
+  vector<Block> blocks(std::max(old_part.size, new_part.size) / block_size);
   for (const auto& aop : *aops) {
     AddInstallOpToGraph(
         &graph, Vertex::kInvalidIndex, &blocks, aop.op, aop.name);
@@ -815,12 +812,8 @@
                                                        blob_file));
   LOG(INFO) << "Done reading " << new_part.name;
 
-  TEST_AND_RETURN_FALSE(
-    ResolveReadAfterWriteDependencies(new_part,
-                                      partition_size,
-                                      config.block_size,
-                                      blob_file,
-                                      aops));
+  TEST_AND_RETURN_FALSE(ResolveReadAfterWriteDependencies(
+      old_part, new_part, partition_size, config.block_size, blob_file, aops));
   LOG(INFO) << "Done reordering " << new_part.name;
   return true;
 }
diff --git a/payload_generator/inplace_generator.h b/payload_generator/inplace_generator.h
index 4839824..f108639 100644
--- a/payload_generator/inplace_generator.h
+++ b/payload_generator/inplace_generator.h
@@ -193,7 +193,7 @@
   static bool AddInstallOpToGraph(Graph* graph,
                                   Vertex::Index existing_vertex,
                                   std::vector<Block>* blocks,
-                                  const InstallOperation operation,
+                                  const InstallOperation& operation,
                                   const std::string& op_name);
 
   // Apply the transformation stored in |the_map| to the |collection| vector
@@ -212,6 +212,7 @@
   // On success, stores the new operations in |aops| in the right order and
   // returns true.
   static bool ResolveReadAfterWriteDependencies(
+      const PartitionConfig& old_part,
       const PartitionConfig& new_part,
       uint64_t partition_size,
       size_t block_size,
diff --git a/payload_generator/inplace_generator_unittest.cc b/payload_generator/inplace_generator_unittest.cc
index cde4bfc..20ac50b 100644
--- a/payload_generator/inplace_generator_unittest.cc
+++ b/payload_generator/inplace_generator_unittest.cc
@@ -33,6 +33,7 @@
 #include "update_engine/common/utils.h"
 #include "update_engine/payload_generator/cycle_breaker.h"
 #include "update_engine/payload_generator/delta_diff_generator.h"
+#include "update_engine/payload_generator/delta_diff_utils.h"
 #include "update_engine/payload_generator/extent_ranges.h"
 #include "update_engine/payload_generator/graph_types.h"
 #include "update_engine/payload_generator/graph_utils.h"
@@ -118,6 +119,16 @@
     blob_file_.reset(new BlobFileWriter(blob_fd_, &blob_file_size_));
   }
 
+  // Dump the list of operations |aops| in case of test failure.
+  void DumpAopsOnFailure(const vector<AnnotatedOperation>& aops) {
+    if (HasNonfatalFailure()) {
+      LOG(INFO) << "Result operation list:";
+      for (const auto& aop : aops) {
+        LOG(INFO) << aop;
+      }
+    }
+  }
+
   // Blob file name, file descriptor and file size used to store operation
   // blobs.
   string blob_path_;
@@ -618,19 +629,21 @@
   // space, forcing it to create a new full operation and the second case with
   // one extra block in the partition that can be used for the move operation.
   for (const auto part_blocks : vector<uint64_t>{num_blocks, num_blocks + 1}) {
-    SCOPED_TRACE(base::StringPrintf("Using partition_blocs=%" PRIu64,
-                                    part_blocks));
+    SCOPED_TRACE(
+        base::StringPrintf("Using partition_blocks=%" PRIu64, part_blocks));
     vector<AnnotatedOperation> result_aops = aops;
     EXPECT_TRUE(InplaceGenerator::ResolveReadAfterWriteDependencies(
-      part, part_blocks * block_size, block_size, blob_file_.get(),
-      &result_aops));
+        part,
+        part,
+        part_blocks * block_size,
+        block_size,
+        blob_file_.get(),
+        &result_aops));
 
     size_t full_ops = 0;
     for (const auto& aop : result_aops) {
-      if (aop.op.type() == InstallOperation::REPLACE ||
-          aop.op.type() == InstallOperation::REPLACE_BZ) {
+      if (diff_utils::IsAReplaceOperation(aop.op.type()))
         full_ops++;
-      }
 
       if (aop.op.type() != InstallOperation::MOVE)
         continue;
@@ -648,13 +661,90 @@
     // operation for it.
     EXPECT_EQ(part_blocks == num_blocks ? 2U : 1U, full_ops);
 
-    if (HasNonfatalFailure()) {
-      LOG(INFO) << "Result operation list:";
-      for (const auto& aop : result_aops) {
-        LOG(INFO) << aop;
+    DumpAopsOnFailure(result_aops);
+  }
+}
+
+// Test that we can shrink a filesystem and break cycles.
+TEST_F(InplaceGeneratorTest, ResolveReadAfterWriteDependenciesShrinkData) {
+  size_t block_size = 4096;
+  size_t old_blocks = 10;
+  size_t new_blocks = 8;
+  vector<AnnotatedOperation> aops;
+
+  // Create a loop using the blocks 1-6 and one other operation writing to the
+  // block 7 from outside the new partition. The loop in the blocks 1-6 uses
+  // two-block operations, so it needs two blocks of scratch space. It can't use
+  // the block 0 as scratch space (see previous test) and it can't use the
+  // blocks 7 or 8 due the last move operation.
+
+  aops.emplace_back();
+  aops.back().name = base::StringPrintf("<bz-block-0>");
+  aops.back().op.set_type(InstallOperation::REPLACE_BZ);
+  StoreExtents({ExtentForRange(0, 1)}, aops.back().op.mutable_dst_extents());
+
+  const size_t num_ops = 3;
+  for (size_t i = 0; i < num_ops; i++) {
+    AnnotatedOperation aop;
+    aop.name = base::StringPrintf("<op-%" PRIuS ">", i);
+    aop.op.set_type(InstallOperation::BSDIFF);
+    StoreExtents({ExtentForRange(1 + 2 * i, 2)}, aop.op.mutable_src_extents());
+    StoreExtents({ExtentForRange(1 + 2 * ((i + 1) % num_ops), 2)},
+                 aop.op.mutable_dst_extents());
+    aops.push_back(aop);
+  }
+
+  {
+    AnnotatedOperation aop;
+    aop.name = "<op-shrink>";
+    aop.op.set_type(InstallOperation::BSDIFF);
+    StoreExtents({ExtentForRange(8, 1)}, aop.op.mutable_src_extents());
+    StoreExtents({ExtentForRange(7, 1)}, aop.op.mutable_dst_extents());
+    aops.push_back(aop);
+  }
+
+  PartitionConfig old_part("part");
+  old_part.path = "/dev/zero";
+  old_part.size = old_blocks * block_size;
+
+  PartitionConfig new_part("part");
+  new_part.path = "/dev/zero";
+  new_part.size = new_blocks * block_size;
+
+  CreateBlobFile();
+
+  EXPECT_TRUE(InplaceGenerator::ResolveReadAfterWriteDependencies(
+      old_part,
+      new_part,
+      (old_blocks + 2) * block_size,  // enough scratch space.
+      block_size,
+      blob_file_.get(),
+      &aops));
+
+  size_t full_ops = 0;
+  for (const auto& aop : aops) {
+    if (diff_utils::IsAReplaceOperation(aop.op.type()))
+      full_ops++;
+  }
+  // There should be only one REPLACE* operation, the one we added for block 0.
+  EXPECT_EQ(1U, full_ops);
+
+  // There should be only one MOVE operation, the one used to break the loop
+  // which should write to scratch space past the block 7 (the last block of the
+  // new partition) which is being written later.
+  size_t move_ops = 0;
+  for (const auto& aop : aops) {
+    if (aop.op.type() == InstallOperation::MOVE) {
+      move_ops++;
+      for (const Extent& extent : aop.op.dst_extents()) {
+        EXPECT_LE(7U, extent.start_block()) << "On dst extents for aop: "
+                                            << aop;
       }
     }
   }
+  EXPECT_EQ(1U, move_ops);
+
+  DumpAopsOnFailure(aops);
 }
 
 }  // namespace chromeos_update_engine
diff --git a/payload_generator/mapfile_filesystem.cc b/payload_generator/mapfile_filesystem.cc
new file mode 100644
index 0000000..f4f0804
--- /dev/null
+++ b/payload_generator/mapfile_filesystem.cc
@@ -0,0 +1,151 @@
+//
+// 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/payload_generator/mapfile_filesystem.h"
+
+#include <algorithm>
+#include <map>
+
+#include <base/files/file_util.h>
+#include <base/logging.h>
+#include <base/strings/string_number_conversions.h>
+#include <base/strings/string_split.h>
+#include <brillo/make_unique_ptr.h>
+
+#include "update_engine/common/utils.h"
+#include "update_engine/payload_generator/extent_ranges.h"
+#include "update_engine/payload_generator/extent_utils.h"
+#include "update_engine/update_metadata.pb.h"
+
+using std::string;
+using std::vector;
+
+namespace {
+// The .map file is defined in terms of 4K blocks.
+size_t kMapfileBlockSize = 4096;
+}  // namespace
+
+namespace chromeos_update_engine {
+
+std::unique_ptr<MapfileFilesystem> MapfileFilesystem::CreateFromFile(
+    const string& filename, const string& mapfile_filename) {
+  if (filename.empty() || mapfile_filename.empty())
+    return nullptr;
+
+  off_t file_size = utils::FileSize(filename);
+  if (file_size < 0)
+    return nullptr;
+
+  if (file_size % kMapfileBlockSize) {
+    LOG(ERROR) << "Image file " << filename << " has a size of " << file_size
+               << " which is not multiple of " << kMapfileBlockSize;
+    return nullptr;
+  }
+  off_t num_blocks = file_size / kMapfileBlockSize;
+
+  if (!utils::FileExists(mapfile_filename.c_str())) {
+    LOG(ERROR) << "File " << mapfile_filename << " doesn't exist";
+    return nullptr;
+  }
+
+  return brillo::make_unique_ptr(
+      new MapfileFilesystem(mapfile_filename, num_blocks));
+}
+
+MapfileFilesystem::MapfileFilesystem(const string& mapfile_filename,
+                                     off_t num_blocks)
+    : mapfile_filename_(mapfile_filename), num_blocks_(num_blocks) {}
+
+size_t MapfileFilesystem::GetBlockSize() const {
+  return kMapfileBlockSize;
+}
+
+size_t MapfileFilesystem::GetBlockCount() const {
+  return num_blocks_;
+}
+
+bool MapfileFilesystem::GetFiles(vector<File>* files) const {
+  files->clear();
+
+  string file_data;
+  if (!base::ReadFileToString(base::FilePath(mapfile_filename_), &file_data)) {
+    LOG(ERROR) << "Unable to read .map file: " << mapfile_filename_;
+    return false;
+  }
+
+  // Iterate over all the lines in the file and generate one File entry per
+  // line.
+  vector<base::StringPiece> lines = base::SplitStringPiece(
+      file_data, "\n", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
+  for (const base::StringPiece& line : lines) {
+    File mapped_file;
+
+    mapped_file.extents = {};
+    size_t delim, last_delim = line.size();
+    while ((delim = line.rfind(' ', last_delim - 1)) != string::npos) {
+      string blocks =
+          line.substr(delim + 1, last_delim - (delim + 1)).as_string();
+      size_t dash = blocks.find('-', 0);
+      uint64_t block_start, block_end;
+      if (dash == string::npos && base::StringToUint64(blocks, &block_start)) {
+        mapped_file.extents.push_back(ExtentForRange(block_start, 1));
+      } else if (dash != string::npos &&
+                 base::StringToUint64(blocks.substr(0, dash), &block_start) &&
+                 base::StringToUint64(blocks.substr(dash + 1), &block_end)) {
+        if (block_end < block_start) {
+          LOG(ERROR) << "End block " << block_end
+                     << " is smaller than start block " << block_start
+                     << std::endl
+                     << line;
+          return false;
+        }
+        if (block_end > static_cast<uint64_t>(num_blocks_)) {
+          LOG(ERROR) << "The end block " << block_end
+                     << " is past the end of the file of " << num_blocks_
+                     << " blocks" << std::endl
+                     << line;
+          return false;
+        }
+        mapped_file.extents.push_back(
+            ExtentForRange(block_start, block_end - block_start + 1));
+      } else {
+        // If we can't parse N or N-M, we assume the block is actually part of
+        // the name of the file.
+        break;
+      }
+      last_delim = delim;
+    }
+    // We parsed the blocks from the end of the line, so we need to reverse
+    // the Extents in the file.
+    std::reverse(mapped_file.extents.begin(), mapped_file.extents.end());
+
+    if (last_delim == string::npos)
+      continue;
+    mapped_file.name = line.substr(0, last_delim).as_string();
+
+    files->push_back(mapped_file);
+  }
+
+  return true;
+}
+
+bool MapfileFilesystem::LoadSettings(brillo::KeyValueStore* store) const {
+  // Settings not supported in mapfile since the storage format is unknown.
+  LOG(ERROR) << "mapfile doesn't support LoadSettings().";
+  return false;
+}
+
+}  // namespace chromeos_update_engine
diff --git a/payload_generator/mapfile_filesystem.h b/payload_generator/mapfile_filesystem.h
new file mode 100644
index 0000000..fc03c4c
--- /dev/null
+++ b/payload_generator/mapfile_filesystem.h
@@ -0,0 +1,65 @@
+//
+// 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.
+//
+
+// A filesystem parser based on the Android .map files. When generating a
+// filesystem with the Android tools, either squashfs or ext4, a .map file can
+// be generated at the same time with the list of files and the 4K-blocks where
+// the data for those files is located in the filesystem. This class parses this
+// .map text file instead of parsing the structure of the actual filesystem
+// contents.
+
+#ifndef UPDATE_ENGINE_PAYLOAD_GENERATOR_MAPFILE_FILESYSTEM_H_
+#define UPDATE_ENGINE_PAYLOAD_GENERATOR_MAPFILE_FILESYSTEM_H_
+
+#include "update_engine/payload_generator/filesystem_interface.h"
+
+#include <memory>
+#include <string>
+#include <vector>
+
+namespace chromeos_update_engine {
+
+class MapfileFilesystem : public FilesystemInterface {
+ public:
+  static std::unique_ptr<MapfileFilesystem> CreateFromFile(
+      const std::string& filename, const std::string& mapfile_filename);
+  virtual ~MapfileFilesystem() = default;
+
+  // FilesystemInterface overrides.
+  size_t GetBlockSize() const override;
+  size_t GetBlockCount() const override;
+
+  // All the generated FilesystemInterface::File are reported as regular files.
+  // Files may overlap with other files in the same block.
+  bool GetFiles(std::vector<File>* files) const override;
+
+  bool LoadSettings(brillo::KeyValueStore* store) const override;
+
+ private:
+  MapfileFilesystem(const std::string& mapfile_filename, off_t num_blocks);
+
+  // The file where the map filesystem is stored.
+  std::string mapfile_filename_;
+
+  // The number of blocks in the filesystem.
+  off_t num_blocks_;
+
+  DISALLOW_COPY_AND_ASSIGN(MapfileFilesystem);
+};
+
+}  // namespace chromeos_update_engine
+
+#endif  // UPDATE_ENGINE_PAYLOAD_GENERATOR_MAPFILE_FILESYSTEM_H_
diff --git a/payload_generator/mapfile_filesystem_unittest.cc b/payload_generator/mapfile_filesystem_unittest.cc
new file mode 100644
index 0000000..36ae3bf
--- /dev/null
+++ b/payload_generator/mapfile_filesystem_unittest.cc
@@ -0,0 +1,134 @@
+//
+// 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/payload_generator/mapfile_filesystem.h"
+
+#include <unistd.h>
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include <base/format_macros.h>
+#include <base/logging.h>
+#include <base/strings/string_number_conversions.h>
+#include <base/strings/string_util.h>
+#include <base/strings/stringprintf.h>
+#include <gtest/gtest.h>
+
+#include "update_engine/common/test_utils.h"
+#include "update_engine/common/utils.h"
+#include "update_engine/payload_generator/extent_ranges.h"
+#include "update_engine/payload_generator/extent_utils.h"
+
+using std::map;
+using std::string;
+using std::unique_ptr;
+using std::vector;
+
+namespace chromeos_update_engine {
+
+namespace {
+
+// Checks that all the blocks in |extents| are in the range [0, total_blocks).
+void ExpectBlocksInRange(const vector<Extent>& extents, uint64_t total_blocks) {
+  for (const Extent& extent : extents) {
+    EXPECT_LE(0U, extent.start_block());
+    EXPECT_LE(extent.start_block() + extent.num_blocks(), total_blocks);
+  }
+}
+
+}  // namespace
+
+class MapfileFilesystemTest : public ::testing::Test {
+ protected:
+  test_utils::ScopedTempFile temp_file_{"mapfile_file.XXXXXX"};
+  test_utils::ScopedTempFile temp_mapfile_{"mapfile_mapfile.XXXXXX"};
+};
+
+TEST_F(MapfileFilesystemTest, EmptyFilesystem) {
+  unique_ptr<MapfileFilesystem> fs = MapfileFilesystem::CreateFromFile(
+      temp_file_.path(), temp_mapfile_.path());
+  ASSERT_NE(nullptr, fs.get());
+
+  EXPECT_EQ(0U, fs->GetBlockCount());
+  // .map files are always 4KiB blocks.
+  EXPECT_EQ(4096U, fs->GetBlockSize());
+}
+
+TEST_F(MapfileFilesystemTest, SeveralFileFormatTest) {
+  string text =
+      "/fileA 1\n"
+      "/fileB 2-4\n"
+      "/fileC 5-6 9 11-12\n"
+      "/file with spaces 14 19\n"
+      "/1234 7\n";
+  test_utils::WriteFileString(temp_mapfile_.path(), text);
+  EXPECT_EQ(0, HANDLE_EINTR(truncate(temp_file_.path().c_str(), 4096 * 20)));
+
+  unique_ptr<MapfileFilesystem> fs = MapfileFilesystem::CreateFromFile(
+      temp_file_.path(), temp_mapfile_.path());
+  ASSERT_NE(nullptr, fs.get());
+
+  vector<FilesystemInterface::File> files;
+  EXPECT_TRUE(fs->GetFiles(&files));
+
+  map<string, FilesystemInterface::File> map_files;
+  for (const auto& file : files) {
+    EXPECT_EQ(map_files.end(), map_files.find(file.name))
+        << "File " << file.name << " repeated in the list.";
+    map_files[file.name] = file;
+    ExpectBlocksInRange(file.extents, fs->GetBlockCount());
+  }
+
+  EXPECT_EQ(map_files["/fileA"].extents,
+            (vector<Extent>{ExtentForRange(1, 1)}));
+  EXPECT_EQ(map_files["/fileB"].extents,
+            (vector<Extent>{ExtentForRange(2, 3)}));
+  EXPECT_EQ(
+      map_files["/fileC"].extents,
+      (vector<Extent>{
+          ExtentForRange(5, 2), ExtentForRange(9, 1), ExtentForRange(11, 2)}));
+  EXPECT_EQ(map_files["/file with spaces"].extents,
+            (vector<Extent>{ExtentForRange(14, 1), ExtentForRange(19, 1)}));
+  EXPECT_EQ(map_files["/1234"].extents, (vector<Extent>{ExtentForRange(7, 1)}));
+}
+
+TEST_F(MapfileFilesystemTest, BlockNumberTooBigTest) {
+  test_utils::WriteFileString(temp_mapfile_.path(), "/some/file 1-4\n");
+  EXPECT_EQ(0, HANDLE_EINTR(truncate(temp_file_.path().c_str(), 4096 * 3)));
+
+  unique_ptr<MapfileFilesystem> fs = MapfileFilesystem::CreateFromFile(
+      temp_file_.path(), temp_mapfile_.path());
+  ASSERT_NE(nullptr, fs.get());
+
+  vector<FilesystemInterface::File> files;
+  EXPECT_FALSE(fs->GetFiles(&files));
+}
+
+TEST_F(MapfileFilesystemTest, EndBeforeStartTest) {
+  test_utils::WriteFileString(temp_mapfile_.path(), "/some/file 2-1\n");
+  EXPECT_EQ(0, HANDLE_EINTR(truncate(temp_file_.path().c_str(), 4096 * 3)));
+
+  unique_ptr<MapfileFilesystem> fs = MapfileFilesystem::CreateFromFile(
+      temp_file_.path(), temp_mapfile_.path());
+  ASSERT_NE(nullptr, fs.get());
+
+  vector<FilesystemInterface::File> files;
+  EXPECT_FALSE(fs->GetFiles(&files));
+}
+
+}  // namespace chromeos_update_engine
diff --git a/payload_generator/payload_file.cc b/payload_generator/payload_file.cc
index de81a39..ddf6f0a 100644
--- a/payload_generator/payload_file.cc
+++ b/payload_generator/payload_file.cc
@@ -138,6 +138,7 @@
           partition->set_postinstall_path(part.postinstall.path);
         if (!part.postinstall.filesystem_type.empty())
           partition->set_filesystem_type(part.postinstall.filesystem_type);
+        partition->set_postinstall_optional(part.postinstall.optional);
       }
       for (const AnnotatedOperation& aop : part.aops) {
         *partition->add_operations() = aop.op;
@@ -193,7 +194,7 @@
   ScopedFileWriterCloser writer_closer(&writer);
 
   // Write header
-  TEST_AND_RETURN_FALSE(writer.Write(kDeltaMagic, sizeof(kDeltaMagic)));
+  TEST_AND_RETURN_FALSE_ERRNO(writer.Write(kDeltaMagic, sizeof(kDeltaMagic)));
 
   // Write major version number
   TEST_AND_RETURN_FALSE(WriteUint64AsBigEndian(&writer, major_version_));
@@ -208,8 +209,8 @@
     // Metadata signature has the same size as payload signature, because they
     // are both the same kind of signature for the same kind of hash.
     uint32_t metadata_signature_size = htobe32(signature_blob_length);
-    TEST_AND_RETURN_FALSE(writer.Write(&metadata_signature_size,
-                                       sizeof(metadata_signature_size)));
+    TEST_AND_RETURN_FALSE_ERRNO(writer.Write(&metadata_signature_size,
+                                             sizeof(metadata_signature_size)));
     metadata_size += sizeof(metadata_signature_size);
     // Set correct size instead of big endian size.
     metadata_signature_size = signature_blob_length;
@@ -218,8 +219,8 @@
   // Write protobuf
   LOG(INFO) << "Writing final delta file protobuf... "
             << serialized_manifest.size();
-  TEST_AND_RETURN_FALSE(writer.Write(serialized_manifest.data(),
-                                     serialized_manifest.size()));
+  TEST_AND_RETURN_FALSE_ERRNO(
+      writer.Write(serialized_manifest.data(), serialized_manifest.size()));
 
   // Write metadata signature blob.
   if (major_version_ == kBrilloMajorPayloadVersion &&
@@ -232,8 +233,8 @@
         PayloadSigner::SignHashWithKeys(metadata_hash,
                                         vector<string>(1, private_key_path),
                                         &metadata_signature));
-    TEST_AND_RETURN_FALSE(writer.Write(metadata_signature.data(),
-                                       metadata_signature.size()));
+    TEST_AND_RETURN_FALSE_ERRNO(
+        writer.Write(metadata_signature.data(), metadata_signature.size()));
   }
 
   // Append the data blobs
@@ -249,7 +250,7 @@
       break;
     }
     TEST_AND_RETURN_FALSE_ERRNO(rc > 0);
-    TEST_AND_RETURN_FALSE(writer.Write(buf.data(), rc));
+    TEST_AND_RETURN_FALSE_ERRNO(writer.Write(buf.data(), rc));
   }
 
   // Write payload signature blob.
@@ -263,8 +264,8 @@
         metadata_signature_size,
         metadata_size + metadata_signature_size + manifest_.signatures_offset(),
         &signature_blob));
-    TEST_AND_RETURN_FALSE(writer.Write(signature_blob.data(),
-                                       signature_blob.size()));
+    TEST_AND_RETURN_FALSE_ERRNO(
+        writer.Write(signature_blob.data(), signature_blob.size()));
   }
 
   ReportPayloadUsage(metadata_size);
@@ -280,10 +281,12 @@
   ScopedFdCloser in_fd_closer(&in_fd);
 
   DirectFileWriter writer;
-  TEST_AND_RETURN_FALSE(
-      writer.Open(new_data_blobs_path.c_str(),
-                  O_WRONLY | O_TRUNC | O_CREAT,
-                  0644) == 0);
+  int rc = writer.Open(
+      new_data_blobs_path.c_str(), O_WRONLY | O_TRUNC | O_CREAT, 0644);
+  if (rc != 0) {
+    PLOG(ERROR) << "Error creating " << new_data_blobs_path;
+    return false;
+  }
   ScopedFileWriterCloser writer_closer(&writer);
   uint64_t out_file_size = 0;
 
@@ -300,7 +303,7 @@
       TEST_AND_RETURN_FALSE(AddOperationHash(&aop.op, buf));
 
       aop.op.set_data_offset(out_file_size);
-      TEST_AND_RETURN_FALSE(writer.Write(buf.data(), buf.size()));
+      TEST_AND_RETURN_FALSE_ERRNO(writer.Write(buf.data(), buf.size()));
       out_file_size += buf.size();
     }
   }
diff --git a/payload_generator/payload_generation_config.cc b/payload_generator/payload_generation_config.cc
index c705f60..e85d693 100644
--- a/payload_generator/payload_generation_config.cc
+++ b/payload_generator/payload_generation_config.cc
@@ -23,12 +23,13 @@
 #include "update_engine/payload_generator/delta_diff_generator.h"
 #include "update_engine/payload_generator/delta_diff_utils.h"
 #include "update_engine/payload_generator/ext2_filesystem.h"
+#include "update_engine/payload_generator/mapfile_filesystem.h"
 #include "update_engine/payload_generator/raw_filesystem.h"
 
 namespace chromeos_update_engine {
 
 bool PostInstallConfig::IsEmpty() const {
-  return run == false && path.empty() && filesystem_type.empty();
+  return !run && path.empty() && filesystem_type.empty() && !optional;
 }
 
 bool PartitionConfig::ValidateExists() const {
@@ -49,18 +50,24 @@
     fs_interface = Ext2Filesystem::CreateFromFile(path);
     // TODO(deymo): The delta generator algorithm doesn't support a block size
     // different than 4 KiB. Remove this check once that's fixed. b/26972455
-    if (fs_interface)
+    if (fs_interface) {
       TEST_AND_RETURN_FALSE(fs_interface->GetBlockSize() == kBlockSize);
+      return true;
+    }
   }
 
-  if (!fs_interface) {
-    // Fall back to a RAW filesystem.
-    TEST_AND_RETURN_FALSE(size % kBlockSize == 0);
-    fs_interface = RawFilesystem::Create(
-      "<" + name + "-partition>",
-      kBlockSize,
-      size / kBlockSize);
+  if (!mapfile_path.empty()) {
+    fs_interface = MapfileFilesystem::CreateFromFile(path, mapfile_path);
+    if (fs_interface) {
+      TEST_AND_RETURN_FALSE(fs_interface->GetBlockSize() == kBlockSize);
+      return true;
+    }
   }
+
+  // Fall back to a RAW filesystem.
+  TEST_AND_RETURN_FALSE(size % kBlockSize == 0);
+  fs_interface = RawFilesystem::Create(
+      "<" + name + "-partition>", kBlockSize, size / kBlockSize);
   return true;
 }
 
@@ -90,6 +97,8 @@
     store.GetString("POSTINSTALL_PATH_" + part.name, &part.postinstall.path);
     store.GetString("FILESYSTEM_TYPE_" + part.name,
                     &part.postinstall.filesystem_type);
+    store.GetBoolean("POSTINSTALL_OPTIONAL_" + part.name,
+                     &part.postinstall.optional);
   }
   if (!found_postinstall) {
     LOG(ERROR) << "No valid postinstall config found.";
diff --git a/payload_generator/payload_generation_config.h b/payload_generator/payload_generation_config.h
index 2601821..8617d14 100644
--- a/payload_generator/payload_generation_config.h
+++ b/payload_generator/payload_generation_config.h
@@ -46,6 +46,9 @@
   // The filesystem type used to mount the partition in order to run the
   // post-install program.
   std::string filesystem_type;
+
+  // Whether this postinstall script should be ignored if it fails.
+  bool optional = false;
 };
 
 struct PartitionConfig {
@@ -63,6 +66,11 @@
   // device such as a loop device.
   std::string path;
 
+  // The path to the .map file associated with |path| if any. The .map file is
+  // generated by the Android filesystem generation tools when creating a
+  // filesystem and describes the blocks used by each file.
+  std::string mapfile_path;
+
   // The size of the data in |path|. If rootfs verification is used (verity)
   // this value should match the size of the verity device for the rootfs, and
   // the size of the whole kernel. This value could be smaller than the
diff --git a/payload_generator/payload_generation_config_unittest.cc b/payload_generator/payload_generation_config_unittest.cc
index 122d94a..3545056 100644
--- a/payload_generator/payload_generation_config_unittest.cc
+++ b/payload_generator/payload_generation_config_unittest.cc
@@ -29,12 +29,14 @@
   EXPECT_TRUE(
       store.LoadFromString("RUN_POSTINSTALL_root=true\n"
                            "POSTINSTALL_PATH_root=postinstall\n"
-                           "FILESYSTEM_TYPE_root=ext4"));
+                           "FILESYSTEM_TYPE_root=ext4\n"
+                           "POSTINSTALL_OPTIONAL_root=true"));
   EXPECT_TRUE(image_config.LoadPostInstallConfig(store));
   EXPECT_FALSE(image_config.partitions[0].postinstall.IsEmpty());
   EXPECT_EQ(true, image_config.partitions[0].postinstall.run);
   EXPECT_EQ("postinstall", image_config.partitions[0].postinstall.path);
   EXPECT_EQ("ext4", image_config.partitions[0].postinstall.filesystem_type);
+  EXPECT_TRUE(image_config.partitions[0].postinstall.optional);
 }
 
 TEST_F(PayloadGenerationConfigTest, LoadPostInstallConfigNameMismatchTest) {
diff --git a/payload_generator/payload_signer_unittest.cc b/payload_generator/payload_signer_unittest.cc
index e159f08..62b6e7a 100644
--- a/payload_generator/payload_signer_unittest.cc
+++ b/payload_generator/payload_signer_unittest.cc
@@ -174,7 +174,7 @@
   EXPECT_EQ(1, signatures.signatures_size());
   const Signatures_Signature& signature = signatures.signatures(0);
   EXPECT_EQ(1U, signature.version());
-  const string sig_data = signature.data();
+  const string& sig_data = signature.data();
   ASSERT_EQ(arraysize(kDataSignature), sig_data.size());
   for (size_t i = 0; i < arraysize(kDataSignature); i++) {
     EXPECT_EQ(kDataSignature[i], static_cast<uint8_t>(sig_data[i]));
diff --git a/payload_state.cc b/payload_state.cc
index 72f7646..846f901 100644
--- a/payload_state.cc
+++ b/payload_state.cc
@@ -31,6 +31,7 @@
 #include "update_engine/common/hardware_interface.h"
 #include "update_engine/common/prefs.h"
 #include "update_engine/common/utils.h"
+#include "update_engine/connection_manager_interface.h"
 #include "update_engine/metrics_utils.h"
 #include "update_engine/omaha_request_params.h"
 #include "update_engine/payload_consumer/install_plan.h"
@@ -186,8 +187,8 @@
   attempt_num_bytes_downloaded_ = 0;
 
   metrics::ConnectionType type;
-  NetworkConnectionType network_connection_type;
-  NetworkTethering tethering;
+  ConnectionType network_connection_type;
+  ConnectionTethering tethering;
   ConnectionManagerInterface* connection_manager =
       system_state_->connection_manager();
   if (!connection_manager->GetConnectionProperties(&network_connection_type,
diff --git a/power_manager_android.cc b/power_manager_android.cc
new file mode 100644
index 0000000..6b7e880
--- /dev/null
+++ b/power_manager_android.cc
@@ -0,0 +1,34 @@
+//
+// 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/power_manager_android.h"
+
+#include <base/logging.h>
+
+namespace chromeos_update_engine {
+
+namespace power_manager {
+std::unique_ptr<PowerManagerInterface> CreatePowerManager() {
+  return std::unique_ptr<PowerManagerInterface>(new PowerManagerAndroid());
+}
+}
+
+bool PowerManagerAndroid::RequestReboot() {
+  LOG(WARNING) << "PowerManager not implemented.";
+  return false;
+}
+
+}  // namespace chromeos_update_engine
diff --git a/power_manager_android.h b/power_manager_android.h
new file mode 100644
index 0000000..86399ab
--- /dev/null
+++ b/power_manager_android.h
@@ -0,0 +1,40 @@
+//
+// 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_POWER_MANAGER_ANDROID_H_
+#define UPDATE_ENGINE_POWER_MANAGER_ANDROID_H_
+
+#include <base/macros.h>
+
+#include "update_engine/power_manager_interface.h"
+
+namespace chromeos_update_engine {
+
+class PowerManagerAndroid : public PowerManagerInterface {
+ public:
+  PowerManagerAndroid() = default;
+  ~PowerManagerAndroid() override = default;
+
+  // PowerManagerInterface overrides.
+  bool RequestReboot() override;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(PowerManagerAndroid);
+};
+
+}  // namespace chromeos_update_engine
+
+#endif  // UPDATE_ENGINE_POWER_MANAGER_ANDROID_H_
diff --git a/power_manager_chromeos.cc b/power_manager_chromeos.cc
new file mode 100644
index 0000000..e175f95
--- /dev/null
+++ b/power_manager_chromeos.cc
@@ -0,0 +1,43 @@
+//
+// 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/power_manager_chromeos.h"
+
+#include <power_manager/dbus-constants.h>
+#include <power_manager/dbus-proxies.h>
+
+#include "update_engine/dbus_connection.h"
+
+namespace chromeos_update_engine {
+
+namespace power_manager {
+std::unique_ptr<PowerManagerInterface> CreatePowerManager() {
+  return std::unique_ptr<PowerManagerInterface>(new PowerManagerChromeOS());
+}
+}
+
+PowerManagerChromeOS::PowerManagerChromeOS()
+    : power_manager_proxy_(DBusConnection::Get()->GetDBus()) {}
+
+bool PowerManagerChromeOS::RequestReboot() {
+  LOG(INFO) << "Calling " << ::power_manager::kPowerManagerInterface << "."
+            << ::power_manager::kRequestRestartMethod;
+  brillo::ErrorPtr error;
+  return power_manager_proxy_.RequestRestart(
+      ::power_manager::REQUEST_RESTART_FOR_UPDATE, &error);
+}
+
+}  // namespace chromeos_update_engine
diff --git a/power_manager_chromeos.h b/power_manager_chromeos.h
new file mode 100644
index 0000000..ad49889
--- /dev/null
+++ b/power_manager_chromeos.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_POWER_MANAGER_H_
+#define UPDATE_ENGINE_POWER_MANAGER_H_
+
+#include <base/macros.h>
+#include <power_manager/dbus-proxies.h>
+
+#include "update_engine/power_manager_interface.h"
+
+namespace chromeos_update_engine {
+
+class PowerManagerChromeOS : public PowerManagerInterface {
+ public:
+  PowerManagerChromeOS();
+  ~PowerManagerChromeOS() override = default;
+
+  // PowerManagerInterface overrides.
+  bool RequestReboot() override;
+
+ private:
+  // Real DBus proxy using the DBus connection.
+  org::chromium::PowerManagerProxy power_manager_proxy_;
+
+  DISALLOW_COPY_AND_ASSIGN(PowerManagerChromeOS);
+};
+
+}  // namespace chromeos_update_engine
+
+#endif  // UPDATE_ENGINE_POWER_MANAGER_H_
diff --git a/power_manager_interface.h b/power_manager_interface.h
new file mode 100644
index 0000000..be059ec
--- /dev/null
+++ b/power_manager_interface.h
@@ -0,0 +1,47 @@
+//
+// 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_POWER_MANAGER_INTERFACE_H_
+#define UPDATE_ENGINE_POWER_MANAGER_INTERFACE_H_
+
+#include <memory>
+
+#include <base/macros.h>
+
+namespace chromeos_update_engine {
+
+class PowerManagerInterface {
+ public:
+  virtual ~PowerManagerInterface() = default;
+
+  // Request the power manager to restart the device. Returns true on success.
+  virtual bool RequestReboot() = 0;
+
+ protected:
+  PowerManagerInterface() = default;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(PowerManagerInterface);
+};
+
+namespace power_manager {
+// Factory function which create a PowerManager.
+std::unique_ptr<PowerManagerInterface> CreatePowerManager();
+}
+
+}  // namespace chromeos_update_engine
+
+#endif  // UPDATE_ENGINE_POWER_MANAGER_INTERFACE_H_
diff --git a/pylintrc b/pylintrc
new file mode 100644
index 0000000..f83f8c6
--- /dev/null
+++ b/pylintrc
@@ -0,0 +1,439 @@
+# Copyright 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.
+
+[MASTER]
+
+# Specify a configuration file.
+#rcfile=
+
+# Python code to execute, usually for sys.path manipulation such as
+# pygtk.require().
+#init-hook=
+
+# Profiled execution.
+profile=no
+
+# Add files or directories to the blacklist. They should be base names, not
+# paths.
+ignore=CVS,.svn,.git
+
+# Pickle collected data for later comparisons.
+persistent=yes
+
+# List of plugins (as comma separated values of python modules names) to load,
+# usually to register additional checkers.
+load-plugins=
+
+# Use multiple processes to speed up Pylint.
+jobs=1
+
+# Allow loading of arbitrary C extensions. Extensions are imported into the
+# active Python interpreter and may run arbitrary code.
+unsafe-load-any-extension=no
+
+# A comma-separated list of package or module names from where C extensions may
+# be loaded. Extensions are loading into the active Python interpreter and may
+# run arbitrary code
+extension-pkg-whitelist=
+
+# Allow optimization of some AST trees. This will activate a peephole AST
+# optimizer, which will apply various small optimizations. For instance, it can
+# be used to obtain the result of joining multiple strings with the addition
+# operator. Joining a lot of strings can lead to a maximum recursion error in
+# Pylint and this flag can prevent that. It has one side effect, the resulting
+# AST will be different than the one from reality.
+optimize-ast=no
+
+
+[MESSAGES CONTROL]
+
+# List of checkers and warnings to enable.
+enable=old-raise-syntax
+
+# Only show warnings with the listed confidence levels. Leave empty to show
+# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED
+confidence=
+
+# Enable the message, report, category or checker with the given id(s). You can
+# either give multiple identifier separated by comma (,) or put this option
+# multiple time. See also the "--disable" option for examples.
+#enable=
+
+# Disable the message, report, category or checker with the given id(s). You
+# can either give multiple identifiers separated by comma (,) or put this
+# option multiple times (only on the command line, not in the configuration
+# file where it should appear only once).You can also use "--disable=all" to
+# disable everything first and then reenable specific checks. For example, if
+# you want to run only the similarities checker, you can use "--disable=all
+# --enable=similarities". If you want to run only the classes checker, but have
+# no Warning level messages displayed, use"--disable=all --enable=classes
+# --disable=W"
+# We leave many of the style warnings to judgement/peer review.
+disable=
+    fixme,
+    locally-disabled,
+    locally-enabled,
+    no-self-use,
+    star-args,
+    too-few-public-methods,
+    too-many-arguments,
+    too-many-branches,
+    too-many-instance-attributes,
+    too-many-lines,
+    too-many-locals,
+    too-many-public-methods,
+    too-many-return-statements,
+    too-many-statements,
+
+
+[REPORTS]
+
+# Set the output format. Available formats are text, parseable, colorized, msvs
+# (visual studio) and html. You can also give a reporter class, eg
+# mypackage.mymodule.MyReporterClass.
+output-format=text
+
+# Put messages in a separate file for each module / package specified on the
+# command line instead of printing them on stdout. Reports (if any) will be
+# written in a file name "pylint_global.[txt|html]".
+files-output=no
+
+# Tells whether to display a full report or only the messages
+reports=no
+
+# Python expression which should return a note less than 10 (10 is the highest
+# note). You have access to the variables errors warning, statement which
+# respectively contain the number of errors / warnings messages and the total
+# number of statements analyzed. This is used by the global evaluation report
+# (RP0004).
+#evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
+
+# Template used to display messages. This is a python new-style format string
+# used to format the message information. See doc for all details
+#msg-template=
+
+
+[SIMILARITIES]
+
+# Minimum lines number of a similarity.
+min-similarity-lines=20
+
+# Ignore comments when computing similarities.
+ignore-comments=yes
+
+# Ignore docstrings when computing similarities.
+ignore-docstrings=yes
+
+# Ignore imports when computing similarities.
+ignore-imports=no
+
+
+[TYPECHECK]
+
+# Tells whether missing members accessed in mixin class should be ignored. A
+# mixin class is detected if its name ends with "mixin" (case insensitive).
+ignore-mixin-members=yes
+
+# List of module names for which member attributes should not be checked
+# (useful for modules/projects where namespaces are manipulated during runtime
+# and thus existing member attributes cannot be deduced by static analysis. It
+# supports qualified module names, as well as Unix pattern matching.
+ignored-modules=
+
+# List of classes names for which member attributes should not be checked
+# (useful for classes with attributes dynamically set). This supports can work
+# with qualified names.
+ignored-classes=hashlib,numpy
+
+# List of members which are set dynamically and missed by pylint inference
+# system, and so shouldn't trigger E1101 when accessed. Python regular
+# expressions are accepted.
+generated-members=
+
+# List of decorators that create context managers from functions, such as
+# contextlib.contextmanager.
+contextmanager-decorators=contextlib.contextmanager,contextlib2.contextmanager
+
+
+[SPELLING]
+
+# Spelling dictionary name. Available dictionaries: none. To make it working
+# install python-enchant package.
+spelling-dict=
+
+# List of comma separated words that should not be checked.
+spelling-ignore-words=
+
+# A path to a file that contains private dictionary; one word per line.
+spelling-private-dict-file=
+
+# Tells whether to store unknown words to indicated private dictionary in
+# --spelling-private-dict-file option instead of raising a message.
+spelling-store-unknown-words=no
+
+
+[LOGGING]
+
+# Logging modules to check that the string format arguments are in logging
+# function parameter format
+logging-modules=logging
+
+
+[VARIABLES]
+
+# Tells whether we should check for unused import in __init__ files.
+init-import=no
+
+# A regular expression matching names used for dummy variables (i.e. not used).
+dummy-variables-rgx=^\*{0,2}(_$|unused_|dummy_)
+
+# List of additional names supposed to be defined in builtins. Remember that
+# you should avoid to define new builtins when possible.
+additional-builtins=
+
+# List of strings which can identify a callback function by name. A callback
+# name must start or end with one of those strings.
+callbacks=cb_,_cb
+
+
+[FORMAT]
+
+# Maximum number of characters on a single line.
+max-line-length=80
+
+# Allow the body of an if to be on the same line as the test if there is no
+# else.
+single-line-if-stmt=no
+
+# Regexp for a line that is allowed to be longer than the limit.
+# This "ignore" regex is today composed of 4 independent parts:
+# (1) Long import lines
+# (2) URLs in comments or pydocs. Detecting URLs by regex is a hard problem and
+#     no amount of tweaking will make a perfect regex AFAICT. This one is a good
+#     compromise.
+# (3) Constant string literals at the start of files don't need to be broken
+#     across lines. Allowing long paths, streamz and urls to be on a single
+#     line. Also requires that the string not be a triplequoted string.
+ignore-long-lines=(?x)
+  (^\s*(import|from)\s
+   |^\s*(\#\ )?<?(https?|ftp):\/\/[^\s\/$.?#].[^\s]*>?$
+   |^[a-zA-Z_][a-zA-Z0-9_]*\s*=\s*("[^"]\S+"|'[^']\S+')
+   )
+
+# Maximum number of lines in a module
+max-module-lines=99999
+
+# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
+# tab).
+indent-string='  '
+
+# Number of spaces of indent required inside a hanging  or continued line.
+indent-after-paren=4
+
+# Expected format of line ending, e.g. empty (any line ending), LF or CRLF.
+expected-line-ending-format=LF
+
+# Make sure : in dicts and trailing commas are checked for whitespace.
+no-space-check=
+
+
+[MISCELLANEOUS]
+
+# List of note tags to take in consideration, separated by a comma.
+notes=FIXME,XXX,TODO
+
+
+[BASIC]
+
+# Required attributes for module, separated by a comma
+required-attributes=
+
+# List of builtins function names that should not be used, separated by a comma
+bad-functions=map,filter,input,apply,reduce
+
+# Good variable names which should always be accepted, separated by a comma
+good-names=i,j,k,ex,x,_
+
+# Bad variable names which should always be refused, separated by a comma
+bad-names=foo,bar,baz,toto,tutu,tata
+
+# Colon-delimited sets of names that determine each other's naming style when
+# the name regexes allow several styles.
+name-group=
+
+# Include a hint for the correct naming format with invalid-name
+include-naming-hint=no
+
+# Regular expression which should only match correct function names.
+# 'camel_case' and 'snake_case' group names are used for consistency of naming
+# styles across functions and methods.
+function-rgx=^(?:(?P<camel_case>_?[A-Z][a-zA-Z0-9]*)|(?P<snake_case>_?[a-z][a-z0-9_]*))$
+
+# Naming hint for function names
+function-name-hint=[a-z_][a-z0-9_]{2,30}$
+
+# Regular expression which should only match correct variable names
+variable-rgx=^[a-z][a-z0-9_]*$
+
+# Naming hint for variable names
+variable-name-hint=[a-z_][a-z0-9_]{2,30}$
+
+# Regular expression which should only match correct module level names
+const-rgx=^(_?[A-Z][A-Z0-9_]*|__[a-z0-9_]+__|_?[a-z][a-z0-9_]*)$
+
+# Naming hint for constant names
+const-name-hint=(([A-Z_][A-Z0-9_]*)|(__.*__))$
+
+# Regular expression which should only match correct instance attribute names
+attr-rgx=^_{0,2}[a-z][a-z0-9_]*$
+
+# Naming hint for attribute names
+attr-name-hint=[a-z_][a-z0-9_]{2,30}$
+
+# Regular expression which should only match correct argument names
+argument-rgx=^[a-z][a-z0-9_]*$
+
+# Naming hint for argument names
+argument-name-hint=[a-z_][a-z0-9_]{2,30}$
+
+# Regular expression which should only match correct class attribute
+class-attribute-rgx=^(_?[A-Z][A-Z0-9_]*|__[a-z0-9_]+__|_?[a-z][a-z0-9_]*)$
+
+# Naming hint for class attribute names
+class-attribute-name-hint=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$
+
+# Regular expression which should only match correct list comprehension /
+# generator expression variable names
+inlinevar-rgx=^[a-z][a-z0-9_]*$
+
+# Naming hint for inline iteration names
+inlinevar-name-hint=[A-Za-z_][A-Za-z0-9_]*$
+
+# Regular expression which should only match correct class names
+class-rgx=^_?[A-Z][a-zA-Z0-9]*$
+
+# Naming hint for class names
+class-name-hint=[A-Z_][a-zA-Z0-9]+$
+
+# Regular expression which should only match correct module names. The
+# leading underscore is sanctioned for private modules by Google's style
+# guide.
+module-rgx=^(_?[a-z][a-z0-9_]*)|__init__$
+
+# Naming hint for module names
+module-name-hint=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
+
+# Regular expression which should only match correct method names.
+# 'camel_case' and 'snake_case' group names are used for consistency of naming
+# styles across functions and methods. 'exempt' indicates a name which is
+# consistent with all naming styles.
+method-rgx=^(?:(?P<exempt>__[a-z0-9_]+__|next)|(?P<camel_case>_{0,2}[A-Z][a-zA-Z0-9]*)|(?P<snake_case>_{0,2}[a-z][a-z0-9_]*))$
+
+# Naming hint for method names
+method-name-hint=[a-z_][a-z0-9_]{2,30}$
+
+# Regular expression which should only match function or class names that do
+# not require a docstring.
+no-docstring-rgx=(__.*__|main)
+
+# Minimum line length for functions/classes that require docstrings, shorter
+# ones are exempt.
+docstring-min-length=10
+
+# List of decorators that define properties, such as abc.abstractproperty.
+property-classes=abc.abstractproperty
+
+
+[ELIF]
+
+# Maximum number of nested blocks for function / method body
+max-nested-blocks=5
+
+
+[DESIGN]
+
+# Maximum number of arguments for function / method
+max-args=5
+
+# Argument names that match this expression will be ignored. Default to name
+# with leading underscore
+ignored-argument-names=_.*
+
+# Maximum number of locals for function / method body
+max-locals=15
+
+# Maximum number of return / yield for function / method body
+max-returns=6
+
+# Maximum number of branch for function / method body
+max-branches=12
+
+# Maximum number of statements in function / method body
+max-statements=50
+
+# Maximum number of parents for a class (see R0901).
+max-parents=10
+
+# Maximum number of attributes for a class (see R0902).
+max-attributes=7
+
+# Minimum number of public methods for a class (see R0903).
+min-public-methods=2
+
+# Maximum number of public methods for a class (see R0904).
+max-public-methods=20
+
+# Maximum number of boolean expressions in a if statement
+max-bool-expr=5
+
+
+[CLASSES]
+
+# List of method names used to declare (i.e. assign) instance attributes.
+defining-attr-methods=__init__,__new__,setUp
+
+# List of valid names for the first argument in a class method.
+valid-classmethod-first-arg=cls
+
+# List of valid names for the first argument in a metaclass class method.
+valid-metaclass-classmethod-first-arg=mcs
+
+# List of member names, which should be excluded from the protected access
+# warning.
+exclude-protected=_asdict,_fields,_replace,_source,_make
+
+
+[IMPORTS]
+
+# Deprecated modules which should not be used, separated by a comma
+deprecated-modules=regsub,TERMIOS,Bastion,rexec,optparse
+
+# Create a graph of every (i.e. internal and external) dependencies in the
+# given file (report RP0402 must not be disabled)
+import-graph=
+
+# Create a graph of external dependencies in the given file (report RP0402 must
+# not be disabled)
+ext-import-graph=
+
+# Create a graph of internal dependencies in the given file (report RP0402 must
+# not be disabled)
+int-import-graph=
+
+
+[EXCEPTIONS]
+
+# Exceptions that will emit a warning when being caught. Defaults to
+# "Exception"
+overgeneral-exceptions=StandardError,Exception,BaseException
diff --git a/real_system_state.cc b/real_system_state.cc
index 74921e2..5cbf723 100644
--- a/real_system_state.cc
+++ b/real_system_state.cc
@@ -24,29 +24,24 @@
 #include <base/time/time.h>
 #include <brillo/make_unique_ptr.h>
 #include <brillo/message_loops/message_loop.h>
+#if USE_LIBCROS
 #include <chromeos/dbus/service_constants.h>
+#endif  // USE_LIBCROS
 
 #include "update_engine/common/boot_control.h"
 #include "update_engine/common/boot_control_stub.h"
 #include "update_engine/common/constants.h"
 #include "update_engine/common/hardware.h"
 #include "update_engine/common/utils.h"
+#if USE_DBUS
+#include "update_engine/dbus_connection.h"
+#endif  // USE_DBUS
 #include "update_engine/update_manager/state_factory.h"
-#include "update_engine/weave_service_factory.h"
 
 using brillo::MessageLoop;
 
 namespace chromeos_update_engine {
 
-RealSystemState::RealSystemState(const scoped_refptr<dbus::Bus>& bus)
-    : debugd_proxy_(bus),
-      libcros_proxy_(bus, chromeos::kLibCrosServiceName),
-      network_proxy_service_proxy_(bus, chromeos::kNetworkProxyServiceName),
-      power_manager_proxy_(bus),
-      session_manager_proxy_(bus),
-      shill_proxy_(bus) {
-}
-
 RealSystemState::~RealSystemState() {
   // Prevent any DBus communication from UpdateAttempter when shutting down the
   // daemon.
@@ -70,11 +65,27 @@
     return false;
   }
 
+#if USE_LIBCROS
+  libcros_proxy_.reset(new org::chromium::LibCrosServiceInterfaceProxy(
+      DBusConnection::Get()->GetDBus(), chromeos::kLibCrosServiceName));
+  network_proxy_service_proxy_.reset(
+      new org::chromium::NetworkProxyServiceInterfaceProxy(
+          DBusConnection::Get()->GetDBus(),
+          chromeos::kNetworkProxyServiceName));
+#endif  // USE_LIBCROS
+
   LOG_IF(INFO, !hardware_->IsNormalBootMode()) << "Booted in dev mode.";
   LOG_IF(INFO, !hardware_->IsOfficialBuild()) << "Booted non-official build.";
 
-  if (!shill_proxy_.Init()) {
-    LOG(ERROR) << "Failed to initialize shill proxy.";
+  connection_manager_ = connection_manager::CreateConnectionManager(this);
+  if (!connection_manager_) {
+    LOG(ERROR) << "Error intializing the ConnectionManagerInterface.";
+    return false;
+  }
+
+  power_manager_ = power_manager::CreatePowerManager();
+  if (!power_manager_) {
+    LOG(ERROR) << "Error intializing the PowerManagerInterface.";
     return false;
   }
 
@@ -132,21 +143,27 @@
       new CertificateChecker(prefs_.get(), &openssl_wrapper_));
   certificate_checker_->Init();
 
+#if USE_LIBCROS
+  org::chromium::NetworkProxyServiceInterfaceProxyInterface* net_proxy =
+      network_proxy_service_proxy_.get();
+  org::chromium::LibCrosServiceInterfaceProxyInterface* libcros_proxy =
+      libcros_proxy_.get();
+#else
+  org::chromium::NetworkProxyServiceInterfaceProxyInterface* net_proxy =
+      nullptr;
+  org::chromium::LibCrosServiceInterfaceProxyInterface* libcros_proxy =
+      nullptr;
+#endif  // USE_LIBCROS
+
   // Initialize the UpdateAttempter before the UpdateManager.
   update_attempter_.reset(new UpdateAttempter(this, certificate_checker_.get(),
-                                              &network_proxy_service_proxy_,
-                                              &debugd_proxy_));
+                                              net_proxy));
   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 =
       chromeos_update_manager::DefaultStateFactory(
-          &policy_provider_, &shill_proxy_, &session_manager_proxy_,
-          &libcros_proxy_, this);
+          &policy_provider_, libcros_proxy, this);
   if (!um_state) {
     LOG(ERROR) << "Failed to initialize the Update Manager.";
     return false;
diff --git a/real_system_state.h b/real_system_state.h
index 18eddab..64964cd 100644
--- a/real_system_state.h
+++ b/real_system_state.h
@@ -20,28 +20,28 @@
 #include "update_engine/system_state.h"
 
 #include <memory>
+#include <set>
 
-#include <debugd/dbus-proxies.h>
-#include <libcros/dbus-proxies.h>
 #include <metrics/metrics_library.h>
-#include <network_proxy/dbus-proxies.h>
 #include <policy/device_policy.h>
-#include <power_manager/dbus-proxies.h>
-#include <session_manager/dbus-proxies.h>
 
+#if USE_LIBCROS
+#include <libcros/dbus-proxies.h>
+#include <network_proxy/dbus-proxies.h>
+#endif  // USE_LIBCROS
+
+#include "update_engine/certificate_checker.h"
 #include "update_engine/common/boot_control_interface.h"
-#include "update_engine/common/certificate_checker.h"
 #include "update_engine/common/clock.h"
 #include "update_engine/common/hardware_interface.h"
 #include "update_engine/common/prefs.h"
-#include "update_engine/connection_manager.h"
+#include "update_engine/connection_manager_interface.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"
+#include "update_engine/power_manager_interface.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 {
 
@@ -51,7 +51,7 @@
  public:
   // Constructs all system objects that do not require separate initialization;
   // see Initialize() below for the remaining ones.
-  explicit RealSystemState(const scoped_refptr<dbus::Bus>& bus);
+  RealSystemState() = default;
   ~RealSystemState() override;
 
   // Initializes and sets systems objects that require an initialization
@@ -65,6 +65,10 @@
 
   void AddObserver(ServiceObserverInterface* observer) override;
   void RemoveObserver(ServiceObserverInterface* observer) override;
+  const std::set<ServiceObserverInterface*>& service_observers() override {
+    CHECK(update_attempter_.get());
+    return update_attempter_->service_observers();
+  }
 
   // SystemState overrides.
   inline void set_device_policy(
@@ -83,7 +87,7 @@
   inline ClockInterface* clock() override { return &clock_; }
 
   inline ConnectionManagerInterface* connection_manager() override {
-    return &connection_manager_;
+    return connection_manager_.get();
   }
 
   inline HardwareInterface* hardware() override { return hardware_.get(); }
@@ -106,10 +110,6 @@
     return update_attempter_.get();
   }
 
-  inline WeaveServiceInterface* weave_service() override {
-    return weave_service_.get();
-  }
-
   inline OmahaRequestParams* request_params() override {
     return &request_params_;
   }
@@ -120,21 +120,22 @@
     return update_manager_.get();
   }
 
-  inline org::chromium::PowerManagerProxyInterface* power_manager_proxy()
-      override {
-    return &power_manager_proxy_;
+  inline PowerManagerInterface* power_manager() override {
+    return power_manager_.get();
   }
 
   inline bool system_rebooted() override { return system_rebooted_; }
 
  private:
+#if USE_LIBCROS
   // Real DBus proxies using the DBus connection.
-  org::chromium::debugdProxy debugd_proxy_;
-  org::chromium::LibCrosServiceInterfaceProxy libcros_proxy_;
-  org::chromium::NetworkProxyServiceInterfaceProxy network_proxy_service_proxy_;
-  org::chromium::PowerManagerProxy power_manager_proxy_;
-  org::chromium::SessionManagerInterfaceProxy session_manager_proxy_;
-  ShillProxy shill_proxy_;
+  std::unique_ptr<org::chromium::LibCrosServiceInterfaceProxy> libcros_proxy_;
+  std::unique_ptr<org::chromium::NetworkProxyServiceInterfaceProxy>
+      network_proxy_service_proxy_;
+#endif  // USE_LIBCROS
+
+  // Interface for the power manager.
+  std::unique_ptr<PowerManagerInterface> power_manager_;
 
   // Interface for the clock.
   std::unique_ptr<BootControlInterface> boot_control_;
@@ -147,7 +148,7 @@
 
   // The connection manager object that makes download decisions depending on
   // the current type of connection.
-  ConnectionManager connection_manager_{&shill_proxy_, this};
+  std::unique_ptr<ConnectionManagerInterface> connection_manager_;
 
   // Interface for the hardware functions.
   std::unique_ptr<HardwareInterface> hardware_;
@@ -177,8 +178,6 @@
 
   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/scripts/brillo_update_payload b/scripts/brillo_update_payload
index 75b089d..b139491 100755
--- a/scripts/brillo_update_payload
+++ b/scripts/brillo_update_payload
@@ -175,18 +175,28 @@
 be used."
 fi
 
-DEFINE_string work_dir "/tmp" "Where to dump temporary files."
+DEFINE_string work_dir "${TMPDIR:-/tmp}" "Where to dump temporary files."
 
 # Parse command line flag arguments
 FLAGS "$@" || exit 1
 eval set -- "${FLAGS_ARGV}"
 set -e
 
+# Override the TMPDIR with the passed work_dir flags, which anyway defaults to
+# ${TMPDIR}.
+TMPDIR="${FLAGS_work_dir}"
+export TMPDIR
+
 # Associative arrays from partition name to file in the source and target
 # images. The size of the updated area must be the size of the file.
 declare -A SRC_PARTITIONS
 declare -A DST_PARTITIONS
 
+# Associative arrays for the .map files associated with each src/dst partition
+# file in SRC_PARTITIONS and DST_PARTITIONS.
+declare -A SRC_PARTITIONS_MAP
+declare -A DST_PARTITIONS_MAP
+
 # List of partition names in order.
 declare -a PARTITIONS_ORDER
 
@@ -219,6 +229,18 @@
   echo "${default_value}"
 }
 
+# truncate_file <file_path> <file_size>
+#
+# Truncate the given |file_path| to |file_size| using perl.
+# The truncate binary might not be available.
+truncate_file() {
+  local file_path="$1"
+  local file_size="$2"
+  perl -e "open(FILE, \"+<\", \$ARGV[0]); \
+           truncate(FILE, ${file_size}); \
+           close(FILE);" "${file_path}"
+}
+
 # Create a temporary file in the work_dir with an optional pattern name.
 # Prints the name of the newly created file.
 create_tempfile() {
@@ -410,26 +432,45 @@
       part_file="${temp_raw}"
     fi
 
-    # delta_generator only supports images multiple of 4 KiB, so we pad with
-    # zeros if needed.
+    # Extract the .map file (if one is available).
+    part_map_file=$(create_tempfile "${part}.map.XXXXXX")
+    CLEANUP_FILES+=("${part_map_file}")
+    unzip -p "${image}" "IMAGES/${part}.map" >"${part_map_file}" || \
+      part_map_file=""
+
+    # delta_generator only supports images multiple of 4 KiB. For target images
+    # we pad the data with zeros if needed, but for source images we truncate
+    # down the data since the last block of the old image could be padded on
+    # disk with unknown data.
     filesize=$(stat -c%s "${part_file}")
     if [[ $(( filesize % 4096 )) -ne 0 ]]; then
-      echo "Rounding up partition ${part}.img to multiple of 4 KiB."
-      : $(( filesize = (filesize + 4095) & -4096 ))
-      truncate --size="${filesize}" "${part_file}"
+      if [[ "${partitions_array}" == "SRC_PARTITIONS" ]]; then
+        echo "Rounding DOWN partition ${part}.img to a multiple of 4 KiB."
+        : $(( filesize = filesize & -4096 ))
+        if [[ ${filesize} == 0 ]]; then
+          echo "Source partition ${part}.img is empty after rounding down," \
+            "skipping."
+          continue
+        fi
+      else
+        echo "Rounding UP partition ${part}.img to a multiple of 4 KiB."
+        : $(( filesize = (filesize + 4095) & -4096 ))
+      fi
+      truncate_file "${part_file}" "${filesize}"
     fi
 
     eval "${partitions_array}[\"${part}\"]=\"${part_file}\""
+    eval "${partitions_array}_MAP[\"${part}\"]=\"${part_map_file}\""
     echo "Extracted ${partitions_array}[${part}]: ${filesize} bytes"
   done
 }
 
 validate_generate() {
   [[ -n "${FLAGS_payload}" ]] ||
-    die "Error: you must specify an output filename with --payload FILENAME"
+    die "You must specify an output filename with --payload FILENAME"
 
   [[ -n "${FLAGS_target_image}" ]] ||
-    die "Error: you must specify a target image with --target_image FILENAME"
+    die "You must specify a target image with --target_image FILENAME"
 }
 
 cmd_generate() {
@@ -450,27 +491,34 @@
   GENERATOR_ARGS=( -out_file="${FLAGS_payload}" )
 
   local part old_partitions="" new_partitions="" partition_names=""
+  local old_mapfiles="" new_mapfiles=""
   for part in "${PARTITIONS_ORDER[@]}"; do
     if [[ -n "${partition_names}" ]]; then
       partition_names+=":"
       new_partitions+=":"
       old_partitions+=":"
+      new_mapfiles+=":"
+      old_mapfiles+=":"
     fi
     partition_names+="${part}"
     new_partitions+="${DST_PARTITIONS[${part}]}"
     old_partitions+="${SRC_PARTITIONS[${part}]:-}"
+    new_mapfiles+="${DST_PARTITIONS_MAP[${part}]:-}"
+    old_mapfiles+="${SRC_PARTITIONS_MAP[${part}]:-}"
   done
 
   # Target image args:
   GENERATOR_ARGS+=(
     -partition_names="${partition_names}"
     -new_partitions="${new_partitions}"
+    -new_mapfiles="${new_mapfiles}"
   )
 
   if [[ "${payload_type}" == "delta" ]]; then
     # Source image args:
     GENERATOR_ARGS+=(
       -old_partitions="${old_partitions}"
+      -old_mapfiles="${old_mapfiles}"
     )
     if [[ -n "${FORCE_MINOR_VERSION}" ]]; then
       GENERATOR_ARGS+=( --minor_version="${FORCE_MINOR_VERSION}" )
@@ -499,17 +547,17 @@
 
 validate_hash() {
   [[ -n "${FLAGS_signature_size}" ]] ||
-    die "Error: you must specify signature size with --signature_size SIZES"
+    die "You must specify signature size with --signature_size SIZES"
 
   [[ -n "${FLAGS_unsigned_payload}" ]] ||
-    die "Error: you must specify the input unsigned payload with \
+    die "You must specify the input unsigned payload with \
 --unsigned_payload FILENAME"
 
   [[ -n "${FLAGS_payload_hash_file}" ]] ||
-    die "Error: you must specify --payload_hash_file FILENAME"
+    die "You must specify --payload_hash_file FILENAME"
 
   [[ -n "${FLAGS_metadata_hash_file}" ]] ||
-    die "Error: you must specify --metadata_hash_file FILENAME"
+    die "You must specify --metadata_hash_file FILENAME"
 }
 
 cmd_hash() {
@@ -524,22 +572,21 @@
 
 validate_sign() {
   [[ -n "${FLAGS_signature_size}" ]] ||
-    die "Error: you must specify signature size with --signature_size SIZES"
+    die "You must specify signature size with --signature_size SIZES"
 
   [[ -n "${FLAGS_unsigned_payload}" ]] ||
-    die "Error: you must specify the input unsigned payload with \
+    die "You must specify the input unsigned payload with \
 --unsigned_payload FILENAME"
 
   [[ -n "${FLAGS_payload}" ]] ||
-    die "Error: you must specify the output signed payload with \
---payload FILENAME"
+    die "You must specify the output signed payload with --payload FILENAME"
 
   [[ -n "${FLAGS_payload_signature_file}" ]] ||
-    die "Error: you must specify the payload signature file with \
+    die "You must specify the payload signature file with \
 --payload_signature_file SIGNATURES"
 
   [[ -n "${FLAGS_metadata_signature_file}" ]] ||
-    die "Error: you must specify the metadata signature file with \
+    die "You must specify the metadata signature file with \
 --metadata_signature_file SIGNATURES"
 }
 
@@ -562,10 +609,10 @@
 
 validate_properties() {
   [[ -n "${FLAGS_payload}" ]] ||
-    die "Error: you must specify the payload file with --payload FILENAME"
+    die "You must specify the payload file with --payload FILENAME"
 
   [[ -n "${FLAGS_properties_file}" ]] ||
-    die "Error: you must specify a non empty --properties_file FILENAME"
+    die "You must specify a non empty --properties_file FILENAME"
 }
 
 cmd_properties() {
@@ -575,7 +622,7 @@
 }
 
 # Sanity check that the real generator exists:
-GENERATOR="$(which delta_generator)"
+GENERATOR="$(which delta_generator || true)"
 [[ -x "${GENERATOR}" ]] || die "can't find delta_generator"
 
 case "$COMMAND" in
diff --git a/scripts/paycheck.py b/scripts/paycheck.py
new file mode 100755
index 0000000..0195f53
--- /dev/null
+++ b/scripts/paycheck.py
@@ -0,0 +1,232 @@
+#!/usr/bin/python2
+#
+# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Command-line tool for checking and applying Chrome OS update payloads."""
+
+from __future__ import print_function
+
+import optparse
+import os
+import sys
+
+# pylint: disable=F0401
+lib_dir = os.path.join(os.path.dirname(__file__), 'lib')
+if os.path.exists(lib_dir) and os.path.isdir(lib_dir):
+  sys.path.insert(1, lib_dir)
+import update_payload
+
+
+_TYPE_FULL = 'full'
+_TYPE_DELTA = 'delta'
+
+
+def ParseArguments(argv):
+  """Parse and validate command-line arguments.
+
+  Args:
+    argv: command-line arguments to parse (excluding the program name)
+
+  Returns:
+    A tuple (opts, payload, extra_args), where `opts' are the options
+    returned by the parser, `payload' is the name of the payload file
+    (mandatory argument) and `extra_args' are any additional command-line
+    arguments.
+  """
+  parser = optparse.OptionParser(
+      usage=('Usage: %prog [OPTION...] PAYLOAD [DST_KERN DST_ROOT '
+             '[SRC_KERN SRC_ROOT]]'),
+      description=('Applies a Chrome OS update PAYLOAD to SRC_KERN and '
+                   'SRC_ROOT emitting DST_KERN and DST_ROOT, respectively. '
+                   'SRC_KERN and SRC_ROOT are only needed for delta payloads. '
+                   'When no partitions are provided, verifies the payload '
+                   'integrity.'),
+      epilog=('Note: a payload may verify correctly but fail to apply, and '
+              'vice versa; this is by design and can be thought of as static '
+              'vs dynamic correctness. A payload that both verifies and '
+              'applies correctly should be safe for use by the Chrome OS '
+              'Update Engine. Use --check to verify a payload prior to '
+              'applying it.'))
+
+  check_opts = optparse.OptionGroup(parser, 'Checking payload integrity')
+  check_opts.add_option('-c', '--check', action='store_true', default=False,
+                        help=('force payload integrity check (e.g. before '
+                              'applying)'))
+  check_opts.add_option('-D', '--describe', action='store_true', default=False,
+                        help='Print a friendly description of the payload.')
+  check_opts.add_option('-r', '--report', metavar='FILE',
+                        help="dump payload report (`-' for stdout)")
+  check_opts.add_option('-t', '--type', metavar='TYPE', dest='assert_type',
+                        help=("assert that payload is either `%s' or `%s'" %
+                              (_TYPE_FULL, _TYPE_DELTA)))
+  check_opts.add_option('-z', '--block-size', metavar='NUM', default=0,
+                        type='int',
+                        help='assert a non-default (4096) payload block size')
+  check_opts.add_option('-u', '--allow-unhashed', action='store_true',
+                        default=False, help='allow unhashed operations')
+  check_opts.add_option('-d', '--disabled_tests', metavar='TESTLIST',
+                        default=(),
+                        help=('comma-separated list of tests to disable; '
+                              'available values: ' +
+                              ', '.join(update_payload.CHECKS_TO_DISABLE)))
+  check_opts.add_option('-k', '--key', metavar='FILE',
+                        help=('Override standard key used for signature '
+                              'validation'))
+  check_opts.add_option('-m', '--meta-sig', metavar='FILE',
+                        help='verify metadata against its signature')
+  check_opts.add_option('-p', '--root-part-size', metavar='NUM',
+                        default=0, type='int',
+                        help=('override rootfs partition size auto-inference'))
+  check_opts.add_option('-P', '--kern-part-size', metavar='NUM',
+                        default=0, type='int',
+                        help=('override kernel partition size auto-inference'))
+  parser.add_option_group(check_opts)
+
+  trace_opts = optparse.OptionGroup(parser, 'Applying payload')
+  trace_opts.add_option('-x', '--extract-bsdiff', action='store_true',
+                        default=False,
+                        help=('use temp input/output files with BSDIFF '
+                              'operations (not in-place)'))
+  trace_opts.add_option('--bspatch-path', metavar='FILE',
+                        help=('use the specified bspatch binary'))
+  parser.add_option_group(trace_opts)
+
+  trace_opts = optparse.OptionGroup(parser, 'Block tracing')
+  trace_opts.add_option('-b', '--root-block', metavar='BLOCK', type='int',
+                        help='trace the origin for a rootfs block')
+  trace_opts.add_option('-B', '--kern-block', metavar='BLOCK', type='int',
+                        help='trace the origin for a kernel block')
+  trace_opts.add_option('-s', '--skip', metavar='NUM', default='0', type='int',
+                        help='skip first NUM occurrences of traced block')
+  parser.add_option_group(trace_opts)
+
+  # Parse command-line arguments.
+  opts, args = parser.parse_args(argv)
+
+  # Validate a value given to --type, if any.
+  if opts.assert_type not in (None, _TYPE_FULL, _TYPE_DELTA):
+    parser.error('invalid argument to --type: %s' % opts.assert_type)
+
+  # Convert and validate --disabled_tests value list, if provided.
+  if opts.disabled_tests:
+    opts.disabled_tests = opts.disabled_tests.split(',')
+    for test in opts.disabled_tests:
+      if test not in update_payload.CHECKS_TO_DISABLE:
+        parser.error('invalid argument to --disabled_tests: %s' % test)
+
+  # Ensure consistent use of block tracing options.
+  do_block_trace = not (opts.root_block is None and opts.kern_block is None)
+  if opts.skip and not do_block_trace:
+    parser.error('--skip must be used with either --root-block or --kern-block')
+
+  # There are several options that imply --check.
+  opts.check = (opts.check or opts.report or opts.assert_type or
+                opts.block_size or opts.allow_unhashed or
+                opts.disabled_tests or opts.meta_sig or opts.key or
+                opts.root_part_size or opts.kern_part_size)
+
+  # Check number of arguments, enforce payload type accordingly.
+  if len(args) == 3:
+    if opts.assert_type == _TYPE_DELTA:
+      parser.error('%s payload requires source partition arguments' %
+                   _TYPE_DELTA)
+    opts.assert_type = _TYPE_FULL
+  elif len(args) == 5:
+    if opts.assert_type == _TYPE_FULL:
+      parser.error('%s payload does not accept source partition arguments' %
+                   _TYPE_FULL)
+    opts.assert_type = _TYPE_DELTA
+  elif len(args) == 1:
+    # Not applying payload; if block tracing not requested either, do an
+    # integrity check.
+    if not do_block_trace:
+      opts.check = True
+    if opts.extract_bsdiff:
+      parser.error('--extract-bsdiff can only be used when applying payloads')
+    if opts.bspatch_path:
+      parser.error('--bspatch-path can only be used when applying payloads')
+  else:
+    parser.error('unexpected number of arguments')
+
+  # By default, look for a metadata-signature file with a name based on the name
+  # of the payload we are checking. We only do it if check was triggered.
+  if opts.check and not opts.meta_sig:
+    default_meta_sig = args[0] + '.metadata-signature'
+    if os.path.isfile(default_meta_sig):
+      opts.meta_sig = default_meta_sig
+      print('Using default metadata signature', opts.meta_sig, file=sys.stderr)
+
+  return opts, args[0], args[1:]
+
+
+def main(argv):
+  # Parse and validate arguments.
+  options, payload_file_name, extra_args = ParseArguments(argv[1:])
+
+  with open(payload_file_name) as payload_file:
+    payload = update_payload.Payload(payload_file)
+    try:
+      # Initialize payload.
+      payload.Init()
+
+      if options.describe:
+        payload.Describe()
+
+      # Perform payload integrity checks.
+      if options.check:
+        report_file = None
+        do_close_report_file = False
+        metadata_sig_file = None
+        try:
+          if options.report:
+            if options.report == '-':
+              report_file = sys.stdout
+            else:
+              report_file = open(options.report, 'w')
+              do_close_report_file = True
+
+          metadata_sig_file = options.meta_sig and open(options.meta_sig)
+          payload.Check(
+              pubkey_file_name=options.key,
+              metadata_sig_file=metadata_sig_file,
+              report_out_file=report_file,
+              assert_type=options.assert_type,
+              block_size=int(options.block_size),
+              rootfs_part_size=options.root_part_size,
+              kernel_part_size=options.kern_part_size,
+              allow_unhashed=options.allow_unhashed,
+              disabled_tests=options.disabled_tests)
+        finally:
+          if metadata_sig_file:
+            metadata_sig_file.close()
+          if do_close_report_file:
+            report_file.close()
+
+      # Trace blocks.
+      if options.root_block is not None:
+        payload.TraceBlock(options.root_block, options.skip, sys.stdout, False)
+      if options.kern_block is not None:
+        payload.TraceBlock(options.kern_block, options.skip, sys.stdout, True)
+
+      # Apply payload.
+      if extra_args:
+        dargs = {'bsdiff_in_place': not options.extract_bsdiff}
+        if options.bspatch_path:
+          dargs['bspatch_path'] = options.bspatch_path
+        if options.assert_type == _TYPE_DELTA:
+          dargs['old_kernel_part'] = extra_args[2]
+          dargs['old_rootfs_part'] = extra_args[3]
+
+        payload.Apply(extra_args[0], extra_args[1], **dargs)
+
+    except update_payload.PayloadError, e:
+      sys.stderr.write('Error: %s\n' % e)
+      return 1
+
+  return 0
+
+
+if __name__ == '__main__':
+  sys.exit(main(sys.argv))
diff --git a/scripts/test_paycheck.sh b/scripts/test_paycheck.sh
new file mode 100755
index 0000000..c395db4
--- /dev/null
+++ b/scripts/test_paycheck.sh
@@ -0,0 +1,175 @@
+#!/bin/bash
+#
+# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# A test script for paycheck.py and the update_payload.py library.
+#
+# This script requires three payload files, along with a metadata signature for
+# each, and a public key for verifying signatures. Payload include:
+#
+# - A full payload for release X (old_full_payload)
+#
+# - A full payload for release Y (new_full_payload), where Y > X
+#
+# - A delta payload from X to Y (delta_payload)
+#
+# The test performs the following:
+#
+# - It verifies each payload against its metadata signature, also asserting the
+#   payload type. Another artifact is a human-readable payload report, which
+#   is output to stdout to be inspected by the user.
+#
+# - It performs a random block trace on the delta payload (both kernel and
+#   rootfs blocks), dumping the traces to stdout for the user to inspect.
+#
+# - It applies old_full_payload to yield old kernel (old_kern.part) and rootfs
+#   (old_root.part) partitions.
+#
+# - It applies delta_payload to old_{kern,root}.part to yield new kernel
+#   (new_delta_kern.part) and rootfs (new_delta_root.part) partitions.
+#
+# - It applies new_full_payload to yield reference new kernel
+#   (new_full_kern.part) and rootfs (new_full_root.part) partitions.
+#
+# - It compares new_{delta,full}_kern.part and new_{delta,full}_root.part to
+#   ensure that they are binary identical.
+#
+# If all steps have completed successfully we know with high certainty that
+# paycheck.py (and hence update_payload.py) correctly parses both full and
+# delta payloads, and applies them to yield the expected result. We also know
+# that tracing works, to the extent it does not crash. Manual inspection of
+# payload reports and block traces will improve this our confidence and are
+# strongly encouraged. Finally, each paycheck.py execution is timed.
+
+
+# Stop on errors, unset variables.
+set -e
+set -u
+
+# Temporary image files.
+OLD_KERN_PART=old_kern.part
+OLD_ROOT_PART=old_root.part
+NEW_DELTA_KERN_PART=new_delta_kern.part
+NEW_DELTA_ROOT_PART=new_delta_root.part
+NEW_FULL_KERN_PART=new_full_kern.part
+NEW_FULL_ROOT_PART=new_full_root.part
+
+
+log() {
+  echo "$@" >&2
+}
+
+die() {
+  log "$@"
+  exit 1
+}
+
+usage_and_exit() {
+  cat >&2 <<EOF
+Usage: ${0##*/} old_full_payload delta_payload new_full_payload
+EOF
+  exit
+}
+
+check_payload() {
+  payload_file=$1
+  payload_type=$2
+
+  time ${paycheck} -t ${payload_type} ${payload_file}
+}
+
+trace_kern_block() {
+  payload_file=$1
+  block=$2
+  time ${paycheck} -B ${block} ${payload_file}
+}
+
+trace_root_block() {
+  payload_file=$1
+  block=$2
+  time ${paycheck} -b ${block} ${payload_file}
+}
+
+apply_full_payload() {
+  payload_file=$1
+  dst_kern_part="$2/$3"
+  dst_root_part="$2/$4"
+
+  time ${paycheck} ${payload_file} ${dst_kern_part} ${dst_root_part}
+}
+
+apply_delta_payload() {
+  payload_file=$1
+  dst_kern_part="$2/$3"
+  dst_root_part="$2/$4"
+  src_kern_part="$2/$5"
+  src_root_part="$2/$6"
+
+  time ${paycheck} ${payload_file} ${dst_kern_part} ${dst_root_part} \
+    ${src_kern_part} ${src_root_part}
+}
+
+main() {
+  # Read command-line arguments.
+  if [ $# == 1 ] && [ "$1" == "-h" ]; then
+    usage_and_exit
+  elif [ $# != 3 ]; then
+    die "Error: unexpected number of arguments"
+  fi
+  old_full_payload="$1"
+  delta_payload="$2"
+  new_full_payload="$3"
+
+  # Find paycheck.py
+  paycheck=${0%/*}/paycheck.py
+  if [ -z "${paycheck}" ] || [ ! -x ${paycheck} ]; then
+    die "cannot find ${paycheck} or file is not executable"
+  fi
+
+  # Check the payloads statically.
+  log "Checking payloads..."
+  check_payload "${old_full_payload}" full
+  check_payload "${new_full_payload}" full
+  check_payload "${delta_payload}" delta
+  log "Done"
+
+  # Trace a random block between 0-1024 on all payloads.
+  block=$((RANDOM * 1024 / 32767))
+  log "Tracing a random block (${block}) in full/delta payloads..."
+  trace_kern_block "${new_full_payload}" ${block}
+  trace_root_block "${new_full_payload}" ${block}
+  trace_kern_block "${delta_payload}" ${block}
+  trace_root_block "${delta_payload}" ${block}
+  log "Done"
+
+  # Apply full/delta payloads and verify results are identical.
+  tmpdir="$(mktemp -d --tmpdir test_paycheck.XXXXXXXX)"
+  log "Initiating application of payloads at $tmpdir"
+
+  log "Applying old full payload..."
+  apply_full_payload "${old_full_payload}" "${tmpdir}" "${OLD_KERN_PART}" \
+    "${OLD_ROOT_PART}"
+  log "Done"
+
+  log "Applying delta payload to old partitions..."
+  apply_delta_payload "${delta_payload}" "${tmpdir}" "${NEW_DELTA_KERN_PART}" \
+    "${NEW_DELTA_ROOT_PART}" "${OLD_KERN_PART}" "${OLD_ROOT_PART}"
+  log "Done"
+
+  log "Applying new full payload..."
+  apply_full_payload "${new_full_payload}" "${tmpdir}" "${NEW_FULL_KERN_PART}" \
+    "${NEW_FULL_ROOT_PART}"
+  log "Done"
+
+  log "Comparing results of delta and new full updates..."
+  diff "${tmpdir}/${NEW_FULL_KERN_PART}" "${tmpdir}/${NEW_DELTA_KERN_PART}"
+  diff "${tmpdir}/${NEW_FULL_ROOT_PART}" "${tmpdir}/${NEW_DELTA_ROOT_PART}"
+  log "Done"
+
+  log "Cleaning up"
+  rm -fr "${tmpdir}"
+}
+
+main "$@"
diff --git a/scripts/update_device.py b/scripts/update_device.py
new file mode 100755
index 0000000..75c58a7
--- /dev/null
+++ b/scripts/update_device.py
@@ -0,0 +1,301 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2017 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.
+#
+
+"""Send an A/B update to an Android device over adb."""
+
+import argparse
+import BaseHTTPServer
+import logging
+import os
+import socket
+import subprocess
+import sys
+import threading
+import zipfile
+
+
+# The path used to store the OTA package when applying the package from a file.
+OTA_PACKAGE_PATH = '/data/ota_package'
+
+
+def CopyFileObjLength(fsrc, fdst, buffer_size=128 * 1024, copy_length=None):
+  """Copy from a file object to another.
+
+  This function is similar to shutil.copyfileobj except that it allows to copy
+  less than the full source file.
+
+  Args:
+    fsrc: source file object where to read from.
+    fdst: destination file object where to write to.
+    buffer_size: size of the copy buffer in memory.
+    copy_length: maximum number of bytes to copy, or None to copy everything.
+
+  Returns:
+    the number of bytes copied.
+  """
+  copied = 0
+  while True:
+    chunk_size = buffer_size
+    if copy_length is not None:
+      chunk_size = min(chunk_size, copy_length - copied)
+      if not chunk_size:
+        break
+    buf = fsrc.read(chunk_size)
+    if not buf:
+      break
+    fdst.write(buf)
+    copied += len(buf)
+  return copied
+
+
+class AndroidOTAPackage(object):
+  """Android update payload using the .zip format.
+
+  Android OTA packages traditionally used a .zip file to store the payload. When
+  applying A/B updates over the network, a payload binary is stored RAW inside
+  this .zip file which is used by update_engine to apply the payload. To do
+  this, an offset and size inside the .zip file are provided.
+  """
+
+  # Android OTA package file paths.
+  OTA_PAYLOAD_BIN = 'payload.bin'
+  OTA_PAYLOAD_PROPERTIES_TXT = 'payload_properties.txt'
+
+  def __init__(self, otafilename):
+    self.otafilename = otafilename
+
+    otazip = zipfile.ZipFile(otafilename, 'r')
+    payload_info = otazip.getinfo(self.OTA_PAYLOAD_BIN)
+    self.offset = payload_info.header_offset + len(payload_info.FileHeader())
+    self.size = payload_info.file_size
+    self.properties = otazip.read(self.OTA_PAYLOAD_PROPERTIES_TXT)
+
+
+class UpdateHandler(BaseHTTPServer.BaseHTTPRequestHandler):
+  """A HTTPServer that supports single-range requests.
+
+  Attributes:
+    serving_payload: path to the only payload file we are serving.
+  """
+
+  @staticmethod
+  def _ParseRange(range_str, file_size):
+    """Parse an HTTP range string.
+
+    Args:
+      range_str: HTTP Range header in the request, not including "Header:".
+      file_size: total size of the serving file.
+
+    Returns:
+      A tuple (start_range, end_range) with the range of bytes requested.
+    """
+    start_range = 0
+    end_range = file_size
+
+    if range_str:
+      range_str = range_str.split('=', 1)[1]
+      s, e = range_str.split('-', 1)
+      if s:
+        start_range = int(s)
+        if e:
+          end_range = int(e) + 1
+      elif e:
+        if int(e) < file_size:
+          start_range = file_size - int(e)
+    return start_range, end_range
+
+
+  def do_GET(self):  # pylint: disable=invalid-name
+    """Reply with the requested payload file."""
+    if self.path != '/payload':
+      self.send_error(404, 'Unknown request')
+      return
+
+    if not self.serving_payload:
+      self.send_error(500, 'No serving payload set')
+      return
+
+    try:
+      f = open(self.serving_payload, 'rb')
+    except IOError:
+      self.send_error(404, 'File not found')
+      return
+    # Handle the range request.
+    if 'Range' in self.headers:
+      self.send_response(206)
+    else:
+      self.send_response(200)
+
+    stat = os.fstat(f.fileno())
+    start_range, end_range = self._ParseRange(self.headers.get('range'),
+                                              stat.st_size)
+    logging.info('Serving request for %s from %s [%d, %d) length: %d',
+             self.path, self.serving_payload, start_range, end_range,
+             end_range - start_range)
+
+    self.send_header('Accept-Ranges', 'bytes')
+    self.send_header('Content-Range',
+                     'bytes ' + str(start_range) + '-' + str(end_range - 1) +
+                     '/' + str(end_range - start_range))
+    self.send_header('Content-Length', end_range - start_range)
+
+    self.send_header('Last-Modified', self.date_time_string(stat.st_mtime))
+    self.send_header('Content-type', 'application/octet-stream')
+    self.end_headers()
+
+    f.seek(start_range)
+    CopyFileObjLength(f, self.wfile, copy_length=end_range - start_range)
+
+
+class ServerThread(threading.Thread):
+  """A thread for serving HTTP requests."""
+
+  def __init__(self, ota_filename):
+    threading.Thread.__init__(self)
+    # serving_payload is a class attribute and the UpdateHandler class is
+    # instantiated with every request.
+    UpdateHandler.serving_payload = ota_filename
+    self._httpd = BaseHTTPServer.HTTPServer(('127.0.0.1', 0), UpdateHandler)
+    self.port = self._httpd.server_port
+
+  def run(self):
+    try:
+      self._httpd.serve_forever()
+    except (KeyboardInterrupt, socket.error):
+      pass
+    logging.info('Server Terminated')
+
+  def StopServer(self):
+    self._httpd.socket.close()
+
+
+def StartServer(ota_filename):
+  t = ServerThread(ota_filename)
+  t.start()
+  return t
+
+
+def AndroidUpdateCommand(ota_filename, payload_url):
+  """Return the command to run to start the update in the Android device."""
+  ota = AndroidOTAPackage(ota_filename)
+  headers = ota.properties
+  headers += 'USER_AGENT=Dalvik (something, something)\n'
+
+  # headers += 'POWERWASH=1\n'
+  headers += 'NETWORK_ID=0\n'
+
+  return ['update_engine_client', '--update', '--follow',
+          '--payload=%s' % payload_url, '--offset=%d' % ota.offset,
+          '--size=%d' % ota.size, '--headers="%s"' % headers]
+
+
+class AdbHost(object):
+  """Represents a device connected via ADB."""
+
+  def __init__(self, device_serial=None):
+    """Construct an instance.
+
+    Args:
+        device_serial: options string serial number of attached device.
+    """
+    self._device_serial = device_serial
+    self._command_prefix = ['adb']
+    if self._device_serial:
+      self._command_prefix += ['-s', self._device_serial]
+
+  def adb(self, command):
+    """Run an ADB command like "adb push".
+
+    Args:
+      command: list of strings containing command and arguments to run
+
+    Returns:
+      the program's return code.
+
+    Raises:
+      subprocess.CalledProcessError on command exit != 0.
+    """
+    command = self._command_prefix + command
+    logging.info('Running: %s', ' '.join(str(x) for x in command))
+    p = subprocess.Popen(command, universal_newlines=True)
+    p.wait()
+    return p.returncode
+
+
+def main():
+  parser = argparse.ArgumentParser(description='Android A/B OTA helper.')
+  parser.add_argument('otafile', metavar='ZIP', type=str,
+                      help='the OTA package file (a .zip file).')
+  parser.add_argument('--file', action='store_true',
+                      help='Push the file to the device before updating.')
+  parser.add_argument('--no-push', action='store_true',
+                      help='Skip the "push" command when using --file')
+  parser.add_argument('-s', type=str, default='', metavar='DEVICE',
+                      help='The specific device to use.')
+  parser.add_argument('--no-verbose', action='store_true',
+                      help='Less verbose output')
+  args = parser.parse_args()
+  logging.basicConfig(
+      level=logging.WARNING if args.no_verbose else logging.INFO)
+
+  dut = AdbHost(args.s)
+
+  server_thread = None
+  # List of commands to execute on exit.
+  finalize_cmds = []
+  # Commands to execute when canceling an update.
+  cancel_cmd = ['shell', 'su', '0', 'update_engine_client', '--cancel']
+  # List of commands to perform the update.
+  cmds = []
+
+  if args.file:
+    # Update via pushing a file to /data.
+    device_ota_file = os.path.join(OTA_PACKAGE_PATH, 'debug.zip')
+    payload_url = 'file://' + device_ota_file
+    if not args.no_push:
+      cmds.append(['push', args.otafile, device_ota_file])
+    cmds.append(['shell', 'su', '0', 'chown', 'system:cache', device_ota_file])
+    cmds.append(['shell', 'su', '0', 'chmod', '0660', device_ota_file])
+  else:
+    # Update via sending the payload over the network with an "adb reverse"
+    # command.
+    device_port = 1234
+    payload_url = 'http://127.0.0.1:%d/payload' % device_port
+    server_thread = StartServer(args.otafile)
+    cmds.append(
+        ['reverse', 'tcp:%d' % device_port, 'tcp:%d' % server_thread.port])
+    finalize_cmds.append(['reverse', '--remove', 'tcp:%d' % device_port])
+
+  try:
+    # The main update command using the configured payload_url.
+    update_cmd = AndroidUpdateCommand(args.otafile, payload_url)
+    cmds.append(['shell', 'su', '0'] + update_cmd)
+
+    for cmd in cmds:
+      dut.adb(cmd)
+  except KeyboardInterrupt:
+    dut.adb(cancel_cmd)
+  finally:
+    if server_thread:
+      server_thread.StopServer()
+    for cmd in finalize_cmds:
+      dut.adb(cmd)
+
+  return 0
+
+if __name__ == '__main__':
+  sys.exit(main())
diff --git a/scripts/update_payload/__init__.py b/scripts/update_payload/__init__.py
new file mode 100644
index 0000000..1906a16
--- /dev/null
+++ b/scripts/update_payload/__init__.py
@@ -0,0 +1,11 @@
+# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Library for processing, verifying and applying Chrome OS update payloads."""
+
+# Just raise the interface classes to the root namespace.
+# pylint: disable=W0401
+from checker import CHECKS_TO_DISABLE
+from error import PayloadError
+from payload import Payload
diff --git a/scripts/update_payload/applier.py b/scripts/update_payload/applier.py
new file mode 100644
index 0000000..e3708c7
--- /dev/null
+++ b/scripts/update_payload/applier.py
@@ -0,0 +1,582 @@
+# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Applying a Chrome OS update payload.
+
+This module is used internally by the main Payload class for applying an update
+payload. The interface for invoking the applier is as follows:
+
+  applier = PayloadApplier(payload)
+  applier.Run(...)
+
+"""
+
+from __future__ import print_function
+
+import array
+import bz2
+import hashlib
+import itertools
+import os
+import shutil
+import subprocess
+import sys
+import tempfile
+
+import common
+from error import PayloadError
+
+
+#
+# Helper functions.
+#
+def _VerifySha256(file_obj, expected_hash, name, length=-1):
+  """Verifies the SHA256 hash of a file.
+
+  Args:
+    file_obj: file object to read
+    expected_hash: the hash digest we expect to be getting
+    name: name string of this hash, for error reporting
+    length: precise length of data to verify (optional)
+
+  Raises:
+    PayloadError if computed hash doesn't match expected one, or if fails to
+    read the specified length of data.
+  """
+  # pylint: disable=E1101
+  hasher = hashlib.sha256()
+  block_length = 1024 * 1024
+  max_length = length if length >= 0 else sys.maxint
+
+  while max_length > 0:
+    read_length = min(max_length, block_length)
+    data = file_obj.read(read_length)
+    if not data:
+      break
+    max_length -= len(data)
+    hasher.update(data)
+
+  if length >= 0 and max_length > 0:
+    raise PayloadError(
+        'insufficient data (%d instead of %d) when verifying %s' %
+        (length - max_length, length, name))
+
+  actual_hash = hasher.digest()
+  if actual_hash != expected_hash:
+    raise PayloadError('%s hash (%s) not as expected (%s)' %
+                       (name, common.FormatSha256(actual_hash),
+                        common.FormatSha256(expected_hash)))
+
+
+def _ReadExtents(file_obj, extents, block_size, max_length=-1):
+  """Reads data from file as defined by extent sequence.
+
+  This tries to be efficient by not copying data as it is read in chunks.
+
+  Args:
+    file_obj: file object
+    extents: sequence of block extents (offset and length)
+    block_size: size of each block
+    max_length: maximum length to read (optional)
+
+  Returns:
+    A character array containing the concatenated read data.
+  """
+  data = array.array('c')
+  if max_length < 0:
+    max_length = sys.maxint
+  for ex in extents:
+    if max_length == 0:
+      break
+    read_length = min(max_length, ex.num_blocks * block_size)
+
+    # Fill with zeros or read from file, depending on the type of extent.
+    if ex.start_block == common.PSEUDO_EXTENT_MARKER:
+      data.extend(itertools.repeat('\0', read_length))
+    else:
+      file_obj.seek(ex.start_block * block_size)
+      data.fromfile(file_obj, read_length)
+
+    max_length -= read_length
+
+  return data
+
+
+def _WriteExtents(file_obj, data, extents, block_size, base_name):
+  """Writes data to file as defined by extent sequence.
+
+  This tries to be efficient by not copy data as it is written in chunks.
+
+  Args:
+    file_obj: file object
+    data: data to write
+    extents: sequence of block extents (offset and length)
+    block_size: size of each block
+    base_name: name string of extent sequence for error reporting
+
+  Raises:
+    PayloadError when things don't add up.
+  """
+  data_offset = 0
+  data_length = len(data)
+  for ex, ex_name in common.ExtentIter(extents, base_name):
+    if not data_length:
+      raise PayloadError('%s: more write extents than data' % ex_name)
+    write_length = min(data_length, ex.num_blocks * block_size)
+
+    # Only do actual writing if this is not a pseudo-extent.
+    if ex.start_block != common.PSEUDO_EXTENT_MARKER:
+      file_obj.seek(ex.start_block * block_size)
+      data_view = buffer(data, data_offset, write_length)
+      file_obj.write(data_view)
+
+    data_offset += write_length
+    data_length -= write_length
+
+  if data_length:
+    raise PayloadError('%s: more data than write extents' % base_name)
+
+
+def _ExtentsToBspatchArg(extents, block_size, base_name, data_length=-1):
+  """Translates an extent sequence into a bspatch-compatible string argument.
+
+  Args:
+    extents: sequence of block extents (offset and length)
+    block_size: size of each block
+    base_name: name string of extent sequence for error reporting
+    data_length: the actual total length of the data in bytes (optional)
+
+  Returns:
+    A tuple consisting of (i) a string of the form
+    "off_1:len_1,...,off_n:len_n", (ii) an offset where zero padding is needed
+    for filling the last extent, (iii) the length of the padding (zero means no
+    padding is needed and the extents cover the full length of data).
+
+  Raises:
+    PayloadError if data_length is too short or too long.
+  """
+  arg = ''
+  pad_off = pad_len = 0
+  if data_length < 0:
+    data_length = sys.maxint
+  for ex, ex_name in common.ExtentIter(extents, base_name):
+    if not data_length:
+      raise PayloadError('%s: more extents than total data length' % ex_name)
+
+    is_pseudo = ex.start_block == common.PSEUDO_EXTENT_MARKER
+    start_byte = -1 if is_pseudo else ex.start_block * block_size
+    num_bytes = ex.num_blocks * block_size
+    if data_length < num_bytes:
+      # We're only padding a real extent.
+      if not is_pseudo:
+        pad_off = start_byte + data_length
+        pad_len = num_bytes - data_length
+
+      num_bytes = data_length
+
+    arg += '%s%d:%d' % (arg and ',', start_byte, num_bytes)
+    data_length -= num_bytes
+
+  if data_length:
+    raise PayloadError('%s: extents not covering full data length' % base_name)
+
+  return arg, pad_off, pad_len
+
+
+#
+# Payload application.
+#
+class PayloadApplier(object):
+  """Applying an update payload.
+
+  This is a short-lived object whose purpose is to isolate the logic used for
+  applying an update payload.
+  """
+
+  def __init__(self, payload, bsdiff_in_place=True, bspatch_path=None,
+               imgpatch_path=None, truncate_to_expected_size=True):
+    """Initialize the applier.
+
+    Args:
+      payload: the payload object to check
+      bsdiff_in_place: whether to perform BSDIFF operation in-place (optional)
+      bspatch_path: path to the bspatch binary (optional)
+      imgpatch_path: path to the imgpatch binary (optional)
+      truncate_to_expected_size: whether to truncate the resulting partitions
+                                 to their expected sizes, as specified in the
+                                 payload (optional)
+    """
+    assert payload.is_init, 'uninitialized update payload'
+    self.payload = payload
+    self.block_size = payload.manifest.block_size
+    self.minor_version = payload.manifest.minor_version
+    self.bsdiff_in_place = bsdiff_in_place
+    self.bspatch_path = bspatch_path or 'bspatch'
+    self.imgpatch_path = imgpatch_path or 'imgpatch'
+    self.truncate_to_expected_size = truncate_to_expected_size
+
+  def _ApplyReplaceOperation(self, op, op_name, out_data, part_file, part_size):
+    """Applies a REPLACE{,_BZ} operation.
+
+    Args:
+      op: the operation object
+      op_name: name string for error reporting
+      out_data: the data to be written
+      part_file: the partition file object
+      part_size: the size of the partition
+
+    Raises:
+      PayloadError if something goes wrong.
+    """
+    block_size = self.block_size
+    data_length = len(out_data)
+
+    # Decompress data if needed.
+    if op.type == common.OpType.REPLACE_BZ:
+      out_data = bz2.decompress(out_data)
+      data_length = len(out_data)
+
+    # Write data to blocks specified in dst extents.
+    data_start = 0
+    for ex, ex_name in common.ExtentIter(op.dst_extents,
+                                         '%s.dst_extents' % op_name):
+      start_block = ex.start_block
+      num_blocks = ex.num_blocks
+      count = num_blocks * block_size
+
+      # Make sure it's not a fake (signature) operation.
+      if start_block != common.PSEUDO_EXTENT_MARKER:
+        data_end = data_start + count
+
+        # Make sure we're not running past partition boundary.
+        if (start_block + num_blocks) * block_size > part_size:
+          raise PayloadError(
+              '%s: extent (%s) exceeds partition size (%d)' %
+              (ex_name, common.FormatExtent(ex, block_size),
+               part_size))
+
+        # Make sure that we have enough data to write.
+        if data_end >= data_length + block_size:
+          raise PayloadError(
+              '%s: more dst blocks than data (even with padding)')
+
+        # Pad with zeros if necessary.
+        if data_end > data_length:
+          padding = data_end - data_length
+          out_data += '\0' * padding
+
+        self.payload.payload_file.seek(start_block * block_size)
+        part_file.seek(start_block * block_size)
+        part_file.write(out_data[data_start:data_end])
+
+      data_start += count
+
+    # Make sure we wrote all data.
+    if data_start < data_length:
+      raise PayloadError('%s: wrote fewer bytes (%d) than expected (%d)' %
+                         (op_name, data_start, data_length))
+
+  def _ApplyMoveOperation(self, op, op_name, part_file):
+    """Applies a MOVE operation.
+
+    Note that this operation must read the whole block data from the input and
+    only then dump it, due to our in-place update semantics; otherwise, it
+    might clobber data midway through.
+
+    Args:
+      op: the operation object
+      op_name: name string for error reporting
+      part_file: the partition file object
+
+    Raises:
+      PayloadError if something goes wrong.
+    """
+    block_size = self.block_size
+
+    # Gather input raw data from src extents.
+    in_data = _ReadExtents(part_file, op.src_extents, block_size)
+
+    # Dump extracted data to dst extents.
+    _WriteExtents(part_file, in_data, op.dst_extents, block_size,
+                  '%s.dst_extents' % op_name)
+
+  def _ApplyBsdiffOperation(self, op, op_name, patch_data, new_part_file):
+    """Applies a BSDIFF operation.
+
+    Args:
+      op: the operation object
+      op_name: name string for error reporting
+      patch_data: the binary patch content
+      new_part_file: the target partition file object
+
+    Raises:
+      PayloadError if something goes wrong.
+    """
+    # Implemented using a SOURCE_BSDIFF operation with the source and target
+    # partition set to the new partition.
+    self._ApplyDiffOperation(op, op_name, patch_data, new_part_file,
+                             new_part_file)
+
+  def _ApplySourceCopyOperation(self, op, op_name, old_part_file,
+                                new_part_file):
+    """Applies a SOURCE_COPY operation.
+
+    Args:
+      op: the operation object
+      op_name: name string for error reporting
+      old_part_file: the old partition file object
+      new_part_file: the new partition file object
+
+    Raises:
+      PayloadError if something goes wrong.
+    """
+    if not old_part_file:
+      raise PayloadError(
+          '%s: no source partition file provided for operation type (%d)' %
+          (op_name, op.type))
+
+    block_size = self.block_size
+
+    # Gather input raw data from src extents.
+    in_data = _ReadExtents(old_part_file, op.src_extents, block_size)
+
+    # Dump extracted data to dst extents.
+    _WriteExtents(new_part_file, in_data, op.dst_extents, block_size,
+                  '%s.dst_extents' % op_name)
+
+  def _ApplyDiffOperation(self, op, op_name, patch_data, old_part_file,
+                          new_part_file):
+    """Applies a SOURCE_BSDIFF or IMGDIFF operation.
+
+    Args:
+      op: the operation object
+      op_name: name string for error reporting
+      patch_data: the binary patch content
+      old_part_file: the source partition file object
+      new_part_file: the target partition file object
+
+    Raises:
+      PayloadError if something goes wrong.
+    """
+    if not old_part_file:
+      raise PayloadError(
+          '%s: no source partition file provided for operation type (%d)' %
+          (op_name, op.type))
+
+    block_size = self.block_size
+
+    # Dump patch data to file.
+    with tempfile.NamedTemporaryFile(delete=False) as patch_file:
+      patch_file_name = patch_file.name
+      patch_file.write(patch_data)
+
+    if (hasattr(new_part_file, 'fileno') and
+        ((not old_part_file) or hasattr(old_part_file, 'fileno')) and
+        op.type != common.OpType.IMGDIFF):
+      # Construct input and output extents argument for bspatch.
+      in_extents_arg, _, _ = _ExtentsToBspatchArg(
+          op.src_extents, block_size, '%s.src_extents' % op_name,
+          data_length=op.src_length)
+      out_extents_arg, pad_off, pad_len = _ExtentsToBspatchArg(
+          op.dst_extents, block_size, '%s.dst_extents' % op_name,
+          data_length=op.dst_length)
+
+      new_file_name = '/dev/fd/%d' % new_part_file.fileno()
+      # Diff from source partition.
+      old_file_name = '/dev/fd/%d' % old_part_file.fileno()
+
+      # Invoke bspatch on partition file with extents args.
+      bspatch_cmd = [self.bspatch_path, old_file_name, new_file_name,
+                     patch_file_name, in_extents_arg, out_extents_arg]
+      subprocess.check_call(bspatch_cmd)
+
+      # Pad with zeros past the total output length.
+      if pad_len:
+        new_part_file.seek(pad_off)
+        new_part_file.write('\0' * pad_len)
+    else:
+      # Gather input raw data and write to a temp file.
+      input_part_file = old_part_file if old_part_file else new_part_file
+      in_data = _ReadExtents(input_part_file, op.src_extents, block_size,
+                             max_length=op.src_length)
+      with tempfile.NamedTemporaryFile(delete=False) as in_file:
+        in_file_name = in_file.name
+        in_file.write(in_data)
+
+      # Allocate temporary output file.
+      with tempfile.NamedTemporaryFile(delete=False) as out_file:
+        out_file_name = out_file.name
+
+      # Invoke bspatch.
+      patch_cmd = [self.bspatch_path, in_file_name, out_file_name,
+                   patch_file_name]
+      if op.type == common.OpType.IMGDIFF:
+        patch_cmd[0] = self.imgpatch_path
+      subprocess.check_call(patch_cmd)
+
+      # Read output.
+      with open(out_file_name, 'rb') as out_file:
+        out_data = out_file.read()
+        if len(out_data) != op.dst_length:
+          raise PayloadError(
+              '%s: actual patched data length (%d) not as expected (%d)' %
+              (op_name, len(out_data), op.dst_length))
+
+      # Write output back to partition, with padding.
+      unaligned_out_len = len(out_data) % block_size
+      if unaligned_out_len:
+        out_data += '\0' * (block_size - unaligned_out_len)
+      _WriteExtents(new_part_file, out_data, op.dst_extents, block_size,
+                    '%s.dst_extents' % op_name)
+
+      # Delete input/output files.
+      os.remove(in_file_name)
+      os.remove(out_file_name)
+
+    # Delete patch file.
+    os.remove(patch_file_name)
+
+  def _ApplyOperations(self, operations, base_name, old_part_file,
+                       new_part_file, part_size):
+    """Applies a sequence of update operations to a partition.
+
+    This assumes an in-place update semantics for MOVE and BSDIFF, namely all
+    reads are performed first, then the data is processed and written back to
+    the same file.
+
+    Args:
+      operations: the sequence of operations
+      base_name: the name of the operation sequence
+      old_part_file: the old partition file object, open for reading/writing
+      new_part_file: the new partition file object, open for reading/writing
+      part_size: the partition size
+
+    Raises:
+      PayloadError if anything goes wrong while processing the payload.
+    """
+    for op, op_name in common.OperationIter(operations, base_name):
+      # Read data blob.
+      data = self.payload.ReadDataBlob(op.data_offset, op.data_length)
+
+      if op.type in (common.OpType.REPLACE, common.OpType.REPLACE_BZ):
+        self._ApplyReplaceOperation(op, op_name, data, new_part_file, part_size)
+      elif op.type == common.OpType.MOVE:
+        self._ApplyMoveOperation(op, op_name, new_part_file)
+      elif op.type == common.OpType.BSDIFF:
+        self._ApplyBsdiffOperation(op, op_name, data, new_part_file)
+      elif op.type == common.OpType.SOURCE_COPY:
+        self._ApplySourceCopyOperation(op, op_name, old_part_file,
+                                       new_part_file)
+      elif op.type in (common.OpType.SOURCE_BSDIFF, common.OpType.IMGDIFF):
+        self._ApplyDiffOperation(op, op_name, data, old_part_file,
+                                 new_part_file)
+      else:
+        raise PayloadError('%s: unknown operation type (%d)' %
+                           (op_name, op.type))
+
+  def _ApplyToPartition(self, operations, part_name, base_name,
+                        new_part_file_name, new_part_info,
+                        old_part_file_name=None, old_part_info=None):
+    """Applies an update to a partition.
+
+    Args:
+      operations: the sequence of update operations to apply
+      part_name: the name of the partition, for error reporting
+      base_name: the name of the operation sequence
+      new_part_file_name: file name to write partition data to
+      new_part_info: size and expected hash of dest partition
+      old_part_file_name: file name of source partition (optional)
+      old_part_info: size and expected hash of source partition (optional)
+
+    Raises:
+      PayloadError if anything goes wrong with the update.
+    """
+    # Do we have a source partition?
+    if old_part_file_name:
+      # Verify the source partition.
+      with open(old_part_file_name, 'rb') as old_part_file:
+        _VerifySha256(old_part_file, old_part_info.hash,
+                      'old ' + part_name, length=old_part_info.size)
+      new_part_file_mode = 'r+b'
+      if self.minor_version == common.INPLACE_MINOR_PAYLOAD_VERSION:
+        # Copy the src partition to the dst one; make sure we don't truncate it.
+        shutil.copyfile(old_part_file_name, new_part_file_name)
+      elif (self.minor_version == common.SOURCE_MINOR_PAYLOAD_VERSION or
+            self.minor_version == common.OPSRCHASH_MINOR_PAYLOAD_VERSION or
+            self.minor_version == common.IMGDIFF_MINOR_PAYLOAD_VERSION):
+        # In minor version >= 2, we don't want to copy the partitions, so
+        # instead just make the new partition file.
+        open(new_part_file_name, 'w').close()
+      else:
+        raise PayloadError("Unknown minor version: %d" % self.minor_version)
+    else:
+      # We need to create/truncate the dst partition file.
+      new_part_file_mode = 'w+b'
+
+    # Apply operations.
+    with open(new_part_file_name, new_part_file_mode) as new_part_file:
+      old_part_file = (open(old_part_file_name, 'r+b')
+                       if old_part_file_name else None)
+      try:
+        self._ApplyOperations(operations, base_name, old_part_file,
+                              new_part_file, new_part_info.size)
+      finally:
+        if old_part_file:
+          old_part_file.close()
+
+      # Truncate the result, if so instructed.
+      if self.truncate_to_expected_size:
+        new_part_file.seek(0, 2)
+        if new_part_file.tell() > new_part_info.size:
+          new_part_file.seek(new_part_info.size)
+          new_part_file.truncate()
+
+    # Verify the resulting partition.
+    with open(new_part_file_name, 'rb') as new_part_file:
+      _VerifySha256(new_part_file, new_part_info.hash,
+                    'new ' + part_name, length=new_part_info.size)
+
+  def Run(self, new_kernel_part, new_rootfs_part, old_kernel_part=None,
+          old_rootfs_part=None):
+    """Applier entry point, invoking all update operations.
+
+    Args:
+      new_kernel_part: name of dest kernel partition file
+      new_rootfs_part: name of dest rootfs partition file
+      old_kernel_part: name of source kernel partition file (optional)
+      old_rootfs_part: name of source rootfs partition file (optional)
+
+    Raises:
+      PayloadError if payload application failed.
+    """
+    self.payload.ResetFile()
+
+    # Make sure the arguments are sane and match the payload.
+    if not (new_kernel_part and new_rootfs_part):
+      raise PayloadError('missing dst {kernel,rootfs} partitions')
+
+    if not (old_kernel_part or old_rootfs_part):
+      if not self.payload.IsFull():
+        raise PayloadError('trying to apply a non-full update without src '
+                           '{kernel,rootfs} partitions')
+    elif old_kernel_part and old_rootfs_part:
+      if not self.payload.IsDelta():
+        raise PayloadError('trying to apply a non-delta update onto src '
+                           '{kernel,rootfs} partitions')
+    else:
+      raise PayloadError('not all src partitions provided')
+
+    # Apply update to rootfs.
+    self._ApplyToPartition(
+        self.payload.manifest.install_operations, 'rootfs',
+        'install_operations', new_rootfs_part,
+        self.payload.manifest.new_rootfs_info, old_rootfs_part,
+        self.payload.manifest.old_rootfs_info)
+
+    # Apply update to kernel update.
+    self._ApplyToPartition(
+        self.payload.manifest.kernel_install_operations, 'kernel',
+        'kernel_install_operations', new_kernel_part,
+        self.payload.manifest.new_kernel_info, old_kernel_part,
+        self.payload.manifest.old_kernel_info)
diff --git a/scripts/update_payload/block_tracer.py b/scripts/update_payload/block_tracer.py
new file mode 100644
index 0000000..f222b21
--- /dev/null
+++ b/scripts/update_payload/block_tracer.py
@@ -0,0 +1,113 @@
+# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Tracing block data source through a Chrome OS update payload.
+
+This module is used internally by the main Payload class for tracing block
+content through an update payload. This is a useful feature in debugging
+payload applying functionality in this package. The interface for invoking the
+tracer is as follows:
+
+  tracer = PayloadBlockTracer(payload)
+  tracer.Run(...)
+
+"""
+
+from __future__ import print_function
+
+import common
+
+
+#
+# Payload block tracing.
+#
+class PayloadBlockTracer(object):
+  """Tracing the origin of block data through update instructions.
+
+  This is a short-lived object whose purpose is to isolate the logic used for
+  tracing the origin of destination partition blocks.
+
+  """
+
+  def __init__(self, payload):
+    assert payload.is_init, 'uninitialized update payload'
+    self.payload = payload
+
+  @staticmethod
+  def _TraceBlock(block, skip, trace_out_file, operations, base_name):
+    """Trace the origin of a given block through a sequence of operations.
+
+    This method tries to map the given dest block to the corresponding source
+    block from which its content originates in the course of an update. It
+    further tries to trace transitive origins through MOVE operations. It is
+    rather efficient, doing the actual tracing by means of a single reverse
+    sweep through the operation sequence. It dumps a log of operations and
+    source blocks responsible for the data in the given dest block to the
+    provided output file.
+
+    Args:
+      block: the block number to trace
+      skip: number of initial transitive origins to ignore
+      trace_out_file: a file object to dump the trace to
+      operations: the sequence of operations
+      base_name: name of the operation sequence
+    """
+    # Traverse operations backwards.
+    for op, op_name in common.OperationIter(operations, base_name,
+                                            reverse=True):
+      total_block_offset = 0
+      found = False
+
+      # Is the traced block mentioned in the dest extents?
+      for dst_ex, dst_ex_name in common.ExtentIter(op.dst_extents,
+                                                   op_name + '.dst_extents'):
+        if (block >= dst_ex.start_block
+            and block < dst_ex.start_block + dst_ex.num_blocks):
+          if skip:
+            skip -= 1
+          else:
+            total_block_offset += block - dst_ex.start_block
+            trace_out_file.write(
+                '%d: %s: found %s (total block offset: %d)\n' %
+                (block, dst_ex_name, common.FormatExtent(dst_ex),
+                 total_block_offset))
+            found = True
+            break
+
+        total_block_offset += dst_ex.num_blocks
+
+      if found:
+        # Don't trace further, unless it's a MOVE.
+        if op.type != common.OpType.MOVE:
+          break
+
+        # For MOVE, find corresponding source block and keep tracing.
+        for src_ex, src_ex_name in common.ExtentIter(op.src_extents,
+                                                     op_name + '.src_extents'):
+          if total_block_offset < src_ex.num_blocks:
+            block = src_ex.start_block + total_block_offset
+            trace_out_file.write(
+                '%s:  mapped to %s (%d)\n' %
+                (src_ex_name, common.FormatExtent(src_ex), block))
+            break
+
+          total_block_offset -= src_ex.num_blocks
+
+  def Run(self, block, skip, trace_out_file, is_kernel):
+    """Block tracer entry point, invoking the actual search.
+
+    Args:
+      block: the block number whose origin to trace
+      skip: the number of first origin mappings to skip
+      trace_out_file: file object to dump the trace to
+      is_kernel: trace through kernel (True) or rootfs (False) operations
+    """
+    if is_kernel:
+      operations = self.payload.manifest.kernel_install_operations
+      base_name = 'kernel_install_operations'
+    else:
+      operations = self.payload.manifest.install_operations
+      base_name = 'install_operations'
+
+    self._TraceBlock(block, skip, trace_out_file, operations, base_name)
diff --git a/scripts/update_payload/checker.py b/scripts/update_payload/checker.py
new file mode 100644
index 0000000..e13ea13
--- /dev/null
+++ b/scripts/update_payload/checker.py
@@ -0,0 +1,1275 @@
+# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Verifying the integrity of a Chrome OS update payload.
+
+This module is used internally by the main Payload class for verifying the
+integrity of an update payload. The interface for invoking the checks is as
+follows:
+
+  checker = PayloadChecker(payload)
+  checker.Run(...)
+"""
+
+from __future__ import print_function
+
+import array
+import base64
+import hashlib
+import itertools
+import os
+import subprocess
+
+import common
+import error
+import format_utils
+import histogram
+import update_metadata_pb2
+
+
+#
+# Constants.
+#
+
+_CHECK_DST_PSEUDO_EXTENTS = 'dst-pseudo-extents'
+_CHECK_MOVE_SAME_SRC_DST_BLOCK = 'move-same-src-dst-block'
+_CHECK_PAYLOAD_SIG = 'payload-sig'
+CHECKS_TO_DISABLE = (
+    _CHECK_DST_PSEUDO_EXTENTS,
+    _CHECK_MOVE_SAME_SRC_DST_BLOCK,
+    _CHECK_PAYLOAD_SIG,
+)
+
+_TYPE_FULL = 'full'
+_TYPE_DELTA = 'delta'
+
+_DEFAULT_BLOCK_SIZE = 4096
+
+_DEFAULT_PUBKEY_BASE_NAME = 'update-payload-key.pub.pem'
+_DEFAULT_PUBKEY_FILE_NAME = os.path.join(os.path.dirname(__file__),
+                                         _DEFAULT_PUBKEY_BASE_NAME)
+
+# Supported minor version map to payload types allowed to be using them.
+_SUPPORTED_MINOR_VERSIONS = {
+    0: (_TYPE_FULL,),
+    1: (_TYPE_DELTA,),
+    2: (_TYPE_DELTA,),
+    3: (_TYPE_DELTA,),
+    4: (_TYPE_DELTA,),
+}
+
+_OLD_DELTA_USABLE_PART_SIZE = 2 * 1024 * 1024 * 1024
+
+#
+# Helper functions.
+#
+
+def _IsPowerOfTwo(val):
+  """Returns True iff val is a power of two."""
+  return val > 0 and (val & (val - 1)) == 0
+
+
+def _AddFormat(format_func, value):
+  """Adds a custom formatted representation to ordinary string representation.
+
+  Args:
+    format_func: A value formatter.
+    value: Value to be formatted and returned.
+
+  Returns:
+    A string 'x (y)' where x = str(value) and y = format_func(value).
+  """
+  ret = str(value)
+  formatted_str = format_func(value)
+  if formatted_str:
+    ret += ' (%s)' % formatted_str
+  return ret
+
+
+def _AddHumanReadableSize(size):
+  """Adds a human readable representation to a byte size value."""
+  return _AddFormat(format_utils.BytesToHumanReadable, size)
+
+
+#
+# Payload report generator.
+#
+
+class _PayloadReport(object):
+  """A payload report generator.
+
+  A report is essentially a sequence of nodes, which represent data points. It
+  is initialized to have a "global", untitled section. A node may be a
+  sub-report itself.
+  """
+
+  # Report nodes: Field, sub-report, section.
+  class Node(object):
+    """A report node interface."""
+
+    @staticmethod
+    def _Indent(indent, line):
+      """Indents a line by a given indentation amount.
+
+      Args:
+        indent: The indentation amount.
+        line: The line content (string).
+
+      Returns:
+        The properly indented line (string).
+      """
+      return '%*s%s' % (indent, '', line)
+
+    def GenerateLines(self, base_indent, sub_indent, curr_section):
+      """Generates the report lines for this node.
+
+      Args:
+        base_indent: Base indentation for each line.
+        sub_indent: Additional indentation for sub-nodes.
+        curr_section: The current report section object.
+
+      Returns:
+        A pair consisting of a list of properly indented report lines and a new
+        current section object.
+      """
+      raise NotImplementedError
+
+  class FieldNode(Node):
+    """A field report node, representing a (name, value) pair."""
+
+    def __init__(self, name, value, linebreak, indent):
+      super(_PayloadReport.FieldNode, self).__init__()
+      self.name = name
+      self.value = value
+      self.linebreak = linebreak
+      self.indent = indent
+
+    def GenerateLines(self, base_indent, sub_indent, curr_section):
+      """Generates a properly formatted 'name : value' entry."""
+      report_output = ''
+      if self.name:
+        report_output += self.name.ljust(curr_section.max_field_name_len) + ' :'
+      value_lines = str(self.value).splitlines()
+      if self.linebreak and self.name:
+        report_output += '\n' + '\n'.join(
+            ['%*s%s' % (self.indent, '', line) for line in value_lines])
+      else:
+        if self.name:
+          report_output += ' '
+        report_output += '%*s' % (self.indent, '')
+        cont_line_indent = len(report_output)
+        indented_value_lines = [value_lines[0]]
+        indented_value_lines.extend(['%*s%s' % (cont_line_indent, '', line)
+                                     for line in value_lines[1:]])
+        report_output += '\n'.join(indented_value_lines)
+
+      report_lines = [self._Indent(base_indent, line + '\n')
+                      for line in report_output.split('\n')]
+      return report_lines, curr_section
+
+  class SubReportNode(Node):
+    """A sub-report node, representing a nested report."""
+
+    def __init__(self, title, report):
+      super(_PayloadReport.SubReportNode, self).__init__()
+      self.title = title
+      self.report = report
+
+    def GenerateLines(self, base_indent, sub_indent, curr_section):
+      """Recurse with indentation."""
+      report_lines = [self._Indent(base_indent, self.title + ' =>\n')]
+      report_lines.extend(self.report.GenerateLines(base_indent + sub_indent,
+                                                    sub_indent))
+      return report_lines, curr_section
+
+  class SectionNode(Node):
+    """A section header node."""
+
+    def __init__(self, title=None):
+      super(_PayloadReport.SectionNode, self).__init__()
+      self.title = title
+      self.max_field_name_len = 0
+
+    def GenerateLines(self, base_indent, sub_indent, curr_section):
+      """Dump a title line, return self as the (new) current section."""
+      report_lines = []
+      if self.title:
+        report_lines.append(self._Indent(base_indent,
+                                         '=== %s ===\n' % self.title))
+      return report_lines, self
+
+  def __init__(self):
+    self.report = []
+    self.last_section = self.global_section = self.SectionNode()
+    self.is_finalized = False
+
+  def GenerateLines(self, base_indent, sub_indent):
+    """Generates the lines in the report, properly indented.
+
+    Args:
+      base_indent: The indentation used for root-level report lines.
+      sub_indent: The indentation offset used for sub-reports.
+
+    Returns:
+      A list of indented report lines.
+    """
+    report_lines = []
+    curr_section = self.global_section
+    for node in self.report:
+      node_report_lines, curr_section = node.GenerateLines(
+          base_indent, sub_indent, curr_section)
+      report_lines.extend(node_report_lines)
+
+    return report_lines
+
+  def Dump(self, out_file, base_indent=0, sub_indent=2):
+    """Dumps the report to a file.
+
+    Args:
+      out_file: File object to output the content to.
+      base_indent: Base indentation for report lines.
+      sub_indent: Added indentation for sub-reports.
+    """
+    report_lines = self.GenerateLines(base_indent, sub_indent)
+    if report_lines and not self.is_finalized:
+      report_lines.append('(incomplete report)\n')
+
+    for line in report_lines:
+      out_file.write(line)
+
+  def AddField(self, name, value, linebreak=False, indent=0):
+    """Adds a field/value pair to the payload report.
+
+    Args:
+      name: The field's name.
+      value: The field's value.
+      linebreak: Whether the value should be printed on a new line.
+      indent: Amount of extra indent for each line of the value.
+    """
+    assert not self.is_finalized
+    if name and self.last_section.max_field_name_len < len(name):
+      self.last_section.max_field_name_len = len(name)
+    self.report.append(self.FieldNode(name, value, linebreak, indent))
+
+  def AddSubReport(self, title):
+    """Adds and returns a sub-report with a title."""
+    assert not self.is_finalized
+    sub_report = self.SubReportNode(title, type(self)())
+    self.report.append(sub_report)
+    return sub_report.report
+
+  def AddSection(self, title):
+    """Adds a new section title."""
+    assert not self.is_finalized
+    self.last_section = self.SectionNode(title)
+    self.report.append(self.last_section)
+
+  def Finalize(self):
+    """Seals the report, marking it as complete."""
+    self.is_finalized = True
+
+
+#
+# Payload verification.
+#
+
+class PayloadChecker(object):
+  """Checking the integrity of an update payload.
+
+  This is a short-lived object whose purpose is to isolate the logic used for
+  verifying the integrity of an update payload.
+  """
+
+  def __init__(self, payload, assert_type=None, block_size=0,
+               allow_unhashed=False, disabled_tests=()):
+    """Initialize the checker.
+
+    Args:
+      payload: The payload object to check.
+      assert_type: Assert that payload is either 'full' or 'delta' (optional).
+      block_size: Expected filesystem / payload block size (optional).
+      allow_unhashed: Allow operations with unhashed data blobs.
+      disabled_tests: Sequence of tests to disable.
+    """
+    if not payload.is_init:
+      raise ValueError('Uninitialized update payload.')
+
+    # Set checker configuration.
+    self.payload = payload
+    self.block_size = block_size if block_size else _DEFAULT_BLOCK_SIZE
+    if not _IsPowerOfTwo(self.block_size):
+      raise error.PayloadError(
+          'Expected block (%d) size is not a power of two.' % self.block_size)
+    if assert_type not in (None, _TYPE_FULL, _TYPE_DELTA):
+      raise error.PayloadError('Invalid assert_type value (%r).' %
+                               assert_type)
+    self.payload_type = assert_type
+    self.allow_unhashed = allow_unhashed
+
+    # Disable specific tests.
+    self.check_dst_pseudo_extents = (
+        _CHECK_DST_PSEUDO_EXTENTS not in disabled_tests)
+    self.check_move_same_src_dst_block = (
+        _CHECK_MOVE_SAME_SRC_DST_BLOCK not in disabled_tests)
+    self.check_payload_sig = _CHECK_PAYLOAD_SIG not in disabled_tests
+
+    # Reset state; these will be assigned when the manifest is checked.
+    self.sigs_offset = 0
+    self.sigs_size = 0
+    self.old_rootfs_fs_size = 0
+    self.old_kernel_fs_size = 0
+    self.new_rootfs_fs_size = 0
+    self.new_kernel_fs_size = 0
+    self.minor_version = None
+
+  @staticmethod
+  def _CheckElem(msg, name, report, is_mandatory, is_submsg, convert=str,
+                 msg_name=None, linebreak=False, indent=0):
+    """Adds an element from a protobuf message to the payload report.
+
+    Checks to see whether a message contains a given element, and if so adds
+    the element value to the provided report. A missing mandatory element
+    causes an exception to be raised.
+
+    Args:
+      msg: The message containing the element.
+      name: The name of the element.
+      report: A report object to add the element name/value to.
+      is_mandatory: Whether or not this element must be present.
+      is_submsg: Whether this element is itself a message.
+      convert: A function for converting the element value for reporting.
+      msg_name: The name of the message object (for error reporting).
+      linebreak: Whether the value report should induce a line break.
+      indent: Amount of indent used for reporting the value.
+
+    Returns:
+      A pair consisting of the element value and the generated sub-report for
+      it (if the element is a sub-message, None otherwise). If the element is
+      missing, returns (None, None).
+
+    Raises:
+      error.PayloadError if a mandatory element is missing.
+    """
+    if not msg.HasField(name):
+      if is_mandatory:
+        raise error.PayloadError('%smissing mandatory %s %r.' %
+                                 (msg_name + ' ' if msg_name else '',
+                                  'sub-message' if is_submsg else 'field',
+                                  name))
+      return None, None
+
+    value = getattr(msg, name)
+    if is_submsg:
+      return value, report and report.AddSubReport(name)
+    else:
+      if report:
+        report.AddField(name, convert(value), linebreak=linebreak,
+                        indent=indent)
+      return value, None
+
+  @staticmethod
+  def _CheckMandatoryField(msg, field_name, report, msg_name, convert=str,
+                           linebreak=False, indent=0):
+    """Adds a mandatory field; returning first component from _CheckElem."""
+    return PayloadChecker._CheckElem(msg, field_name, report, True, False,
+                                     convert=convert, msg_name=msg_name,
+                                     linebreak=linebreak, indent=indent)[0]
+
+  @staticmethod
+  def _CheckOptionalField(msg, field_name, report, convert=str,
+                          linebreak=False, indent=0):
+    """Adds an optional field; returning first component from _CheckElem."""
+    return PayloadChecker._CheckElem(msg, field_name, report, False, False,
+                                     convert=convert, linebreak=linebreak,
+                                     indent=indent)[0]
+
+  @staticmethod
+  def _CheckMandatorySubMsg(msg, submsg_name, report, msg_name):
+    """Adds a mandatory sub-message; wrapper for _CheckElem."""
+    return PayloadChecker._CheckElem(msg, submsg_name, report, True, True,
+                                     msg_name)
+
+  @staticmethod
+  def _CheckOptionalSubMsg(msg, submsg_name, report):
+    """Adds an optional sub-message; wrapper for _CheckElem."""
+    return PayloadChecker._CheckElem(msg, submsg_name, report, False, True)
+
+  @staticmethod
+  def _CheckPresentIff(val1, val2, name1, name2, obj_name):
+    """Checks that val1 is None iff val2 is None.
+
+    Args:
+      val1: first value to be compared.
+      val2: second value to be compared.
+      name1: name of object holding the first value.
+      name2: name of object holding the second value.
+      obj_name: Name of the object containing these values.
+
+    Raises:
+      error.PayloadError if assertion does not hold.
+    """
+    if None in (val1, val2) and val1 is not val2:
+      present, missing = (name1, name2) if val2 is None else (name2, name1)
+      raise error.PayloadError('%r present without %r%s.' %
+                               (present, missing,
+                                ' in ' + obj_name if obj_name else ''))
+
+  @staticmethod
+  def _Run(cmd, send_data=None):
+    """Runs a subprocess, returns its output.
+
+    Args:
+      cmd: Sequence of command-line argument for invoking the subprocess.
+      send_data: Data to feed to the process via its stdin.
+
+    Returns:
+      A tuple containing the stdout and stderr output of the process.
+    """
+    run_process = subprocess.Popen(cmd, stdin=subprocess.PIPE,
+                                   stdout=subprocess.PIPE)
+    try:
+      result = run_process.communicate(input=send_data)
+    finally:
+      exit_code = run_process.wait()
+
+    if exit_code:
+      raise RuntimeError('Subprocess %r failed with code %r.' %
+                         (cmd, exit_code))
+
+    return result
+
+  @staticmethod
+  def _CheckSha256Signature(sig_data, pubkey_file_name, actual_hash, sig_name):
+    """Verifies an actual hash against a signed one.
+
+    Args:
+      sig_data: The raw signature data.
+      pubkey_file_name: Public key used for verifying signature.
+      actual_hash: The actual hash digest.
+      sig_name: Signature name for error reporting.
+
+    Raises:
+      error.PayloadError if signature could not be verified.
+    """
+    if len(sig_data) != 256:
+      raise error.PayloadError(
+          '%s: signature size (%d) not as expected (256).' %
+          (sig_name, len(sig_data)))
+    signed_data, _ = PayloadChecker._Run(
+        ['openssl', 'rsautl', '-verify', '-pubin', '-inkey', pubkey_file_name],
+        send_data=sig_data)
+
+    if len(signed_data) != len(common.SIG_ASN1_HEADER) + 32:
+      raise error.PayloadError('%s: unexpected signed data length (%d).' %
+                               (sig_name, len(signed_data)))
+
+    if not signed_data.startswith(common.SIG_ASN1_HEADER):
+      raise error.PayloadError('%s: not containing standard ASN.1 prefix.' %
+                               sig_name)
+
+    signed_hash = signed_data[len(common.SIG_ASN1_HEADER):]
+    if signed_hash != actual_hash:
+      raise error.PayloadError(
+          '%s: signed hash (%s) different from actual (%s).' %
+          (sig_name, common.FormatSha256(signed_hash),
+           common.FormatSha256(actual_hash)))
+
+  @staticmethod
+  def _CheckBlocksFitLength(length, num_blocks, block_size, length_name,
+                            block_name=None):
+    """Checks that a given length fits given block space.
+
+    This ensures that the number of blocks allocated is appropriate for the
+    length of the data residing in these blocks.
+
+    Args:
+      length: The actual length of the data.
+      num_blocks: The number of blocks allocated for it.
+      block_size: The size of each block in bytes.
+      length_name: Name of length (used for error reporting).
+      block_name: Name of block (used for error reporting).
+
+    Raises:
+      error.PayloadError if the aforementioned invariant is not satisfied.
+    """
+    # Check: length <= num_blocks * block_size.
+    if length > num_blocks * block_size:
+      raise error.PayloadError(
+          '%s (%d) > num %sblocks (%d) * block_size (%d).' %
+          (length_name, length, block_name or '', num_blocks, block_size))
+
+    # Check: length > (num_blocks - 1) * block_size.
+    if length <= (num_blocks - 1) * block_size:
+      raise error.PayloadError(
+          '%s (%d) <= (num %sblocks - 1 (%d)) * block_size (%d).' %
+          (length_name, length, block_name or '', num_blocks - 1, block_size))
+
+  def _CheckManifestMinorVersion(self, report):
+    """Checks the payload manifest minor_version field.
+
+    Args:
+      report: The report object to add to.
+
+    Raises:
+      error.PayloadError if any of the checks fail.
+    """
+    self.minor_version = self._CheckOptionalField(self.payload.manifest,
+                                                  'minor_version', report)
+    if self.minor_version in _SUPPORTED_MINOR_VERSIONS:
+      if self.payload_type not in _SUPPORTED_MINOR_VERSIONS[self.minor_version]:
+        raise error.PayloadError(
+            'Minor version %d not compatible with payload type %s.' %
+            (self.minor_version, self.payload_type))
+    elif self.minor_version is None:
+      raise error.PayloadError('Minor version is not set.')
+    else:
+      raise error.PayloadError('Unsupported minor version: %d' %
+                               self.minor_version)
+
+  def _CheckManifest(self, report, rootfs_part_size=0, kernel_part_size=0):
+    """Checks the payload manifest.
+
+    Args:
+      report: A report object to add to.
+      rootfs_part_size: Size of the rootfs partition in bytes.
+      kernel_part_size: Size of the kernel partition in bytes.
+
+    Returns:
+      A tuple consisting of the partition block size used during the update
+      (integer), the signatures block offset and size.
+
+    Raises:
+      error.PayloadError if any of the checks fail.
+    """
+    manifest = self.payload.manifest
+    report.AddSection('manifest')
+
+    # Check: block_size must exist and match the expected value.
+    actual_block_size = self._CheckMandatoryField(manifest, 'block_size',
+                                                  report, 'manifest')
+    if actual_block_size != self.block_size:
+      raise error.PayloadError('Block_size (%d) not as expected (%d).' %
+                               (actual_block_size, self.block_size))
+
+    # Check: signatures_offset <==> signatures_size.
+    self.sigs_offset = self._CheckOptionalField(manifest, 'signatures_offset',
+                                                report)
+    self.sigs_size = self._CheckOptionalField(manifest, 'signatures_size',
+                                              report)
+    self._CheckPresentIff(self.sigs_offset, self.sigs_size,
+                          'signatures_offset', 'signatures_size', 'manifest')
+
+    # Check: old_kernel_info <==> old_rootfs_info.
+    oki_msg, oki_report = self._CheckOptionalSubMsg(manifest,
+                                                    'old_kernel_info', report)
+    ori_msg, ori_report = self._CheckOptionalSubMsg(manifest,
+                                                    'old_rootfs_info', report)
+    self._CheckPresentIff(oki_msg, ori_msg, 'old_kernel_info',
+                          'old_rootfs_info', 'manifest')
+    if oki_msg:  # equivalently, ori_msg
+      # Assert/mark delta payload.
+      if self.payload_type == _TYPE_FULL:
+        raise error.PayloadError(
+            'Apparent full payload contains old_{kernel,rootfs}_info.')
+      self.payload_type = _TYPE_DELTA
+
+      # Check: {size, hash} present in old_{kernel,rootfs}_info.
+      self.old_kernel_fs_size = self._CheckMandatoryField(
+          oki_msg, 'size', oki_report, 'old_kernel_info')
+      self._CheckMandatoryField(oki_msg, 'hash', oki_report, 'old_kernel_info',
+                                convert=common.FormatSha256)
+      self.old_rootfs_fs_size = self._CheckMandatoryField(
+          ori_msg, 'size', ori_report, 'old_rootfs_info')
+      self._CheckMandatoryField(ori_msg, 'hash', ori_report, 'old_rootfs_info',
+                                convert=common.FormatSha256)
+
+      # Check: old_{kernel,rootfs} size must fit in respective partition.
+      if kernel_part_size and self.old_kernel_fs_size > kernel_part_size:
+        raise error.PayloadError(
+            'Old kernel content (%d) exceed partition size (%d).' %
+            (self.old_kernel_fs_size, kernel_part_size))
+      if rootfs_part_size and self.old_rootfs_fs_size > rootfs_part_size:
+        raise error.PayloadError(
+            'Old rootfs content (%d) exceed partition size (%d).' %
+            (self.old_rootfs_fs_size, rootfs_part_size))
+    else:
+      # Assert/mark full payload.
+      if self.payload_type == _TYPE_DELTA:
+        raise error.PayloadError(
+            'Apparent delta payload missing old_{kernel,rootfs}_info.')
+      self.payload_type = _TYPE_FULL
+
+    # Check: new_kernel_info present; contains {size, hash}.
+    nki_msg, nki_report = self._CheckMandatorySubMsg(
+        manifest, 'new_kernel_info', report, 'manifest')
+    self.new_kernel_fs_size = self._CheckMandatoryField(
+        nki_msg, 'size', nki_report, 'new_kernel_info')
+    self._CheckMandatoryField(nki_msg, 'hash', nki_report, 'new_kernel_info',
+                              convert=common.FormatSha256)
+
+    # Check: new_rootfs_info present; contains {size, hash}.
+    nri_msg, nri_report = self._CheckMandatorySubMsg(
+        manifest, 'new_rootfs_info', report, 'manifest')
+    self.new_rootfs_fs_size = self._CheckMandatoryField(
+        nri_msg, 'size', nri_report, 'new_rootfs_info')
+    self._CheckMandatoryField(nri_msg, 'hash', nri_report, 'new_rootfs_info',
+                              convert=common.FormatSha256)
+
+    # Check: new_{kernel,rootfs} size must fit in respective partition.
+    if kernel_part_size and self.new_kernel_fs_size > kernel_part_size:
+      raise error.PayloadError(
+          'New kernel content (%d) exceed partition size (%d).' %
+          (self.new_kernel_fs_size, kernel_part_size))
+    if rootfs_part_size and self.new_rootfs_fs_size > rootfs_part_size:
+      raise error.PayloadError(
+          'New rootfs content (%d) exceed partition size (%d).' %
+          (self.new_rootfs_fs_size, rootfs_part_size))
+
+    # Check: minor_version makes sense for the payload type. This check should
+    # run after the payload type has been set.
+    self._CheckManifestMinorVersion(report)
+
+  def _CheckLength(self, length, total_blocks, op_name, length_name):
+    """Checks whether a length matches the space designated in extents.
+
+    Args:
+      length: The total length of the data.
+      total_blocks: The total number of blocks in extents.
+      op_name: Operation name (for error reporting).
+      length_name: Length name (for error reporting).
+
+    Raises:
+      error.PayloadError is there a problem with the length.
+    """
+    # Check: length is non-zero.
+    if length == 0:
+      raise error.PayloadError('%s: %s is zero.' % (op_name, length_name))
+
+    # Check that length matches number of blocks.
+    self._CheckBlocksFitLength(length, total_blocks, self.block_size,
+                               '%s: %s' % (op_name, length_name))
+
+  def _CheckExtents(self, extents, usable_size, block_counters, name,
+                    allow_pseudo=False, allow_signature=False):
+    """Checks a sequence of extents.
+
+    Args:
+      extents: The sequence of extents to check.
+      usable_size: The usable size of the partition to which the extents apply.
+      block_counters: Array of counters corresponding to the number of blocks.
+      name: The name of the extent block.
+      allow_pseudo: Whether or not pseudo block numbers are allowed.
+      allow_signature: Whether or not the extents are used for a signature.
+
+    Returns:
+      The total number of blocks in the extents.
+
+    Raises:
+      error.PayloadError if any of the entailed checks fails.
+    """
+    total_num_blocks = 0
+    for ex, ex_name in common.ExtentIter(extents, name):
+      # Check: Mandatory fields.
+      start_block = PayloadChecker._CheckMandatoryField(ex, 'start_block',
+                                                        None, ex_name)
+      num_blocks = PayloadChecker._CheckMandatoryField(ex, 'num_blocks', None,
+                                                       ex_name)
+      end_block = start_block + num_blocks
+
+      # Check: num_blocks > 0.
+      if num_blocks == 0:
+        raise error.PayloadError('%s: extent length is zero.' % ex_name)
+
+      if start_block != common.PSEUDO_EXTENT_MARKER:
+        # Check: Make sure we're within the partition limit.
+        if usable_size and end_block * self.block_size > usable_size:
+          raise error.PayloadError(
+              '%s: extent (%s) exceeds usable partition size (%d).' %
+              (ex_name, common.FormatExtent(ex, self.block_size), usable_size))
+
+        # Record block usage.
+        for i in xrange(start_block, end_block):
+          block_counters[i] += 1
+      elif not (allow_pseudo or (allow_signature and len(extents) == 1)):
+        # Pseudo-extents must be allowed explicitly, or otherwise be part of a
+        # signature operation (in which case there has to be exactly one).
+        raise error.PayloadError('%s: unexpected pseudo-extent.' % ex_name)
+
+      total_num_blocks += num_blocks
+
+    return total_num_blocks
+
+  def _CheckReplaceOperation(self, op, data_length, total_dst_blocks, op_name):
+    """Specific checks for REPLACE/REPLACE_BZ operations.
+
+    Args:
+      op: The operation object from the manifest.
+      data_length: The length of the data blob associated with the operation.
+      total_dst_blocks: Total number of blocks in dst_extents.
+      op_name: Operation name for error reporting.
+
+    Raises:
+      error.PayloadError if any check fails.
+    """
+    # Check: Does not contain src extents.
+    if op.src_extents:
+      raise error.PayloadError('%s: contains src_extents.' % op_name)
+
+    # Check: Contains data.
+    if data_length is None:
+      raise error.PayloadError('%s: missing data_{offset,length}.' % op_name)
+
+    if op.type == common.OpType.REPLACE:
+      PayloadChecker._CheckBlocksFitLength(data_length, total_dst_blocks,
+                                           self.block_size,
+                                           op_name + '.data_length', 'dst')
+    else:
+      # Check: data_length must be smaller than the alotted dst blocks.
+      if data_length >= total_dst_blocks * self.block_size:
+        raise error.PayloadError(
+            '%s: data_length (%d) must be less than allotted dst block '
+            'space (%d * %d).' %
+            (op_name, data_length, total_dst_blocks, self.block_size))
+
+  def _CheckMoveOperation(self, op, data_offset, total_src_blocks,
+                          total_dst_blocks, op_name):
+    """Specific checks for MOVE operations.
+
+    Args:
+      op: The operation object from the manifest.
+      data_offset: The offset of a data blob for the operation.
+      total_src_blocks: Total number of blocks in src_extents.
+      total_dst_blocks: Total number of blocks in dst_extents.
+      op_name: Operation name for error reporting.
+
+    Raises:
+      error.PayloadError if any check fails.
+    """
+    # Check: No data_{offset,length}.
+    if data_offset is not None:
+      raise error.PayloadError('%s: contains data_{offset,length}.' % op_name)
+
+    # Check: total_src_blocks == total_dst_blocks.
+    if total_src_blocks != total_dst_blocks:
+      raise error.PayloadError(
+          '%s: total src blocks (%d) != total dst blocks (%d).' %
+          (op_name, total_src_blocks, total_dst_blocks))
+
+    # Check: For all i, i-th src block index != i-th dst block index.
+    i = 0
+    src_extent_iter = iter(op.src_extents)
+    dst_extent_iter = iter(op.dst_extents)
+    src_extent = dst_extent = None
+    src_idx = src_num = dst_idx = dst_num = 0
+    while i < total_src_blocks:
+      # Get the next source extent, if needed.
+      if not src_extent:
+        try:
+          src_extent = src_extent_iter.next()
+        except StopIteration:
+          raise error.PayloadError('%s: ran out of src extents (%d/%d).' %
+                                   (op_name, i, total_src_blocks))
+        src_idx = src_extent.start_block
+        src_num = src_extent.num_blocks
+
+      # Get the next dest extent, if needed.
+      if not dst_extent:
+        try:
+          dst_extent = dst_extent_iter.next()
+        except StopIteration:
+          raise error.PayloadError('%s: ran out of dst extents (%d/%d).' %
+                                   (op_name, i, total_dst_blocks))
+        dst_idx = dst_extent.start_block
+        dst_num = dst_extent.num_blocks
+
+      # Check: start block is not 0. See crbug/480751; there are still versions
+      # of update_engine which fail when seeking to 0 in PReadAll and PWriteAll,
+      # so we need to fail payloads that try to MOVE to/from block 0.
+      if src_idx == 0 or dst_idx == 0:
+        raise error.PayloadError(
+            '%s: MOVE operation cannot have extent with start block 0' %
+            op_name)
+
+      if self.check_move_same_src_dst_block and src_idx == dst_idx:
+        raise error.PayloadError(
+            '%s: src/dst block number %d is the same (%d).' %
+            (op_name, i, src_idx))
+
+      advance = min(src_num, dst_num)
+      i += advance
+
+      src_idx += advance
+      src_num -= advance
+      if src_num == 0:
+        src_extent = None
+
+      dst_idx += advance
+      dst_num -= advance
+      if dst_num == 0:
+        dst_extent = None
+
+    # Make sure we've exhausted all src/dst extents.
+    if src_extent:
+      raise error.PayloadError('%s: excess src blocks.' % op_name)
+    if dst_extent:
+      raise error.PayloadError('%s: excess dst blocks.' % op_name)
+
+  def _CheckAnyDiffOperation(self, data_length, total_dst_blocks, op_name):
+    """Specific checks for BSDIFF, SOURCE_BSDIFF and IMGDIFF operations.
+
+    Args:
+      data_length: The length of the data blob associated with the operation.
+      total_dst_blocks: Total number of blocks in dst_extents.
+      op_name: Operation name for error reporting.
+
+    Raises:
+      error.PayloadError if any check fails.
+    """
+    # Check: data_{offset,length} present.
+    if data_length is None:
+      raise error.PayloadError('%s: missing data_{offset,length}.' % op_name)
+
+    # Check: data_length is strictly smaller than the alotted dst blocks.
+    if data_length >= total_dst_blocks * self.block_size:
+      raise error.PayloadError(
+          '%s: data_length (%d) must be smaller than allotted dst space '
+          '(%d * %d = %d).' %
+          (op_name, data_length, total_dst_blocks, self.block_size,
+           total_dst_blocks * self.block_size))
+
+  def _CheckSourceCopyOperation(self, data_offset, total_src_blocks,
+                                total_dst_blocks, op_name):
+    """Specific checks for SOURCE_COPY.
+
+    Args:
+      data_offset: The offset of a data blob for the operation.
+      total_src_blocks: Total number of blocks in src_extents.
+      total_dst_blocks: Total number of blocks in dst_extents.
+      op_name: Operation name for error reporting.
+
+    Raises:
+      error.PayloadError if any check fails.
+    """
+    # Check: No data_{offset,length}.
+    if data_offset is not None:
+      raise error.PayloadError('%s: contains data_{offset,length}.' % op_name)
+
+    # Check: total_src_blocks == total_dst_blocks.
+    if total_src_blocks != total_dst_blocks:
+      raise error.PayloadError(
+          '%s: total src blocks (%d) != total dst blocks (%d).' %
+          (op_name, total_src_blocks, total_dst_blocks))
+
+  def _CheckAnySourceOperation(self, op, total_src_blocks, op_name):
+    """Specific checks for SOURCE_* operations.
+
+    Args:
+      op: The operation object from the manifest.
+      total_src_blocks: Total number of blocks in src_extents.
+      op_name: Operation name for error reporting.
+
+    Raises:
+      error.PayloadError if any check fails.
+    """
+    # Check: total_src_blocks != 0.
+    if total_src_blocks == 0:
+      raise error.PayloadError('%s: no src blocks in a source op.' % op_name)
+
+    # Check: src_sha256_hash present in minor version >= 3.
+    if self.minor_version >= 3 and op.src_sha256_hash is None:
+      raise error.PayloadError('%s: source hash missing.' % op_name)
+
+  def _CheckOperation(self, op, op_name, is_last, old_block_counters,
+                      new_block_counters, old_usable_size, new_usable_size,
+                      prev_data_offset, allow_signature, blob_hash_counts):
+    """Checks a single update operation.
+
+    Args:
+      op: The operation object.
+      op_name: Operation name string for error reporting.
+      is_last: Whether this is the last operation in the sequence.
+      old_block_counters: Arrays of block read counters.
+      new_block_counters: Arrays of block write counters.
+      old_usable_size: The overall usable size for src data in bytes.
+      new_usable_size: The overall usable size for dst data in bytes.
+      prev_data_offset: Offset of last used data bytes.
+      allow_signature: Whether this may be a signature operation.
+      blob_hash_counts: Counters for hashed/unhashed blobs.
+
+    Returns:
+      The amount of data blob associated with the operation.
+
+    Raises:
+      error.PayloadError if any check has failed.
+    """
+    # Check extents.
+    total_src_blocks = self._CheckExtents(
+        op.src_extents, old_usable_size, old_block_counters,
+        op_name + '.src_extents', allow_pseudo=True)
+    allow_signature_in_extents = (allow_signature and is_last and
+                                  op.type == common.OpType.REPLACE)
+    total_dst_blocks = self._CheckExtents(
+        op.dst_extents, new_usable_size, new_block_counters,
+        op_name + '.dst_extents',
+        allow_pseudo=(not self.check_dst_pseudo_extents),
+        allow_signature=allow_signature_in_extents)
+
+    # Check: data_offset present <==> data_length present.
+    data_offset = self._CheckOptionalField(op, 'data_offset', None)
+    data_length = self._CheckOptionalField(op, 'data_length', None)
+    self._CheckPresentIff(data_offset, data_length, 'data_offset',
+                          'data_length', op_name)
+
+    # Check: At least one dst_extent.
+    if not op.dst_extents:
+      raise error.PayloadError('%s: dst_extents is empty.' % op_name)
+
+    # Check {src,dst}_length, if present.
+    if op.HasField('src_length'):
+      self._CheckLength(op.src_length, total_src_blocks, op_name, 'src_length')
+    if op.HasField('dst_length'):
+      self._CheckLength(op.dst_length, total_dst_blocks, op_name, 'dst_length')
+
+    if op.HasField('data_sha256_hash'):
+      blob_hash_counts['hashed'] += 1
+
+      # Check: Operation carries data.
+      if data_offset is None:
+        raise error.PayloadError(
+            '%s: data_sha256_hash present but no data_{offset,length}.' %
+            op_name)
+
+      # Check: Hash verifies correctly.
+      # pylint cannot find the method in hashlib, for some reason.
+      # pylint: disable=E1101
+      actual_hash = hashlib.sha256(self.payload.ReadDataBlob(data_offset,
+                                                             data_length))
+      if op.data_sha256_hash != actual_hash.digest():
+        raise error.PayloadError(
+            '%s: data_sha256_hash (%s) does not match actual hash (%s).' %
+            (op_name, common.FormatSha256(op.data_sha256_hash),
+             common.FormatSha256(actual_hash.digest())))
+    elif data_offset is not None:
+      if allow_signature_in_extents:
+        blob_hash_counts['signature'] += 1
+      elif self.allow_unhashed:
+        blob_hash_counts['unhashed'] += 1
+      else:
+        raise error.PayloadError('%s: unhashed operation not allowed.' %
+                                 op_name)
+
+    if data_offset is not None:
+      # Check: Contiguous use of data section.
+      if data_offset != prev_data_offset:
+        raise error.PayloadError(
+            '%s: data offset (%d) not matching amount used so far (%d).' %
+            (op_name, data_offset, prev_data_offset))
+
+    # Type-specific checks.
+    if op.type in (common.OpType.REPLACE, common.OpType.REPLACE_BZ):
+      self._CheckReplaceOperation(op, data_length, total_dst_blocks, op_name)
+    elif op.type == common.OpType.MOVE and self.minor_version == 1:
+      self._CheckMoveOperation(op, data_offset, total_src_blocks,
+                               total_dst_blocks, op_name)
+    elif op.type == common.OpType.BSDIFF and self.minor_version == 1:
+      self._CheckAnyDiffOperation(data_length, total_dst_blocks, op_name)
+    elif op.type == common.OpType.SOURCE_COPY and self.minor_version >= 2:
+      self._CheckSourceCopyOperation(data_offset, total_src_blocks,
+                                     total_dst_blocks, op_name)
+      self._CheckAnySourceOperation(op, total_src_blocks, op_name)
+    elif op.type == common.OpType.SOURCE_BSDIFF and self.minor_version >= 2:
+      self._CheckAnyDiffOperation(data_length, total_dst_blocks, op_name)
+      self._CheckAnySourceOperation(op, total_src_blocks, op_name)
+    elif op.type == common.OpType.IMGDIFF and self.minor_version >= 4:
+      self._CheckAnyDiffOperation(data_length, total_dst_blocks, op_name)
+      self._CheckAnySourceOperation(op, total_src_blocks, op_name)
+    else:
+      raise error.PayloadError(
+          'Operation %s (type %d) not allowed in minor version %d' %
+          (op_name, op.type, self.minor_version))
+    return data_length if data_length is not None else 0
+
+  def _SizeToNumBlocks(self, size):
+    """Returns the number of blocks needed to contain a given byte size."""
+    return (size + self.block_size - 1) / self.block_size
+
+  def _AllocBlockCounters(self, total_size):
+    """Returns a freshly initialized array of block counters.
+
+    Note that the generated array is not portable as is due to byte-ordering
+    issues, hence it should not be serialized.
+
+    Args:
+      total_size: The total block size in bytes.
+
+    Returns:
+      An array of unsigned short elements initialized to zero, one for each of
+      the blocks necessary for containing the partition.
+    """
+    return array.array('H',
+                       itertools.repeat(0, self._SizeToNumBlocks(total_size)))
+
+  def _CheckOperations(self, operations, report, base_name, old_fs_size,
+                       new_fs_size, new_usable_size, prev_data_offset,
+                       allow_signature):
+    """Checks a sequence of update operations.
+
+    Args:
+      operations: The sequence of operations to check.
+      report: The report object to add to.
+      base_name: The name of the operation block.
+      old_fs_size: The old filesystem size in bytes.
+      new_fs_size: The new filesystem size in bytes.
+      new_usable_size: The overall usable size of the new partition in bytes.
+      prev_data_offset: Offset of last used data bytes.
+      allow_signature: Whether this sequence may contain signature operations.
+
+    Returns:
+      The total data blob size used.
+
+    Raises:
+      error.PayloadError if any of the checks fails.
+    """
+    # The total size of data blobs used by operations scanned thus far.
+    total_data_used = 0
+    # Counts of specific operation types.
+    op_counts = {
+        common.OpType.REPLACE: 0,
+        common.OpType.REPLACE_BZ: 0,
+        common.OpType.MOVE: 0,
+        common.OpType.BSDIFF: 0,
+        common.OpType.SOURCE_COPY: 0,
+        common.OpType.SOURCE_BSDIFF: 0,
+        common.OpType.IMGDIFF: 0,
+    }
+    # Total blob sizes for each operation type.
+    op_blob_totals = {
+        common.OpType.REPLACE: 0,
+        common.OpType.REPLACE_BZ: 0,
+        # MOVE operations don't have blobs.
+        common.OpType.BSDIFF: 0,
+        # SOURCE_COPY operations don't have blobs.
+        common.OpType.SOURCE_BSDIFF: 0,
+        common.OpType.IMGDIFF: 0,
+    }
+    # Counts of hashed vs unhashed operations.
+    blob_hash_counts = {
+        'hashed': 0,
+        'unhashed': 0,
+    }
+    if allow_signature:
+      blob_hash_counts['signature'] = 0
+
+    # Allocate old and new block counters.
+    old_block_counters = (self._AllocBlockCounters(new_usable_size)
+                          if old_fs_size else None)
+    new_block_counters = self._AllocBlockCounters(new_usable_size)
+
+    # Process and verify each operation.
+    op_num = 0
+    for op, op_name in common.OperationIter(operations, base_name):
+      op_num += 1
+
+      # Check: Type is valid.
+      if op.type not in op_counts.keys():
+        raise error.PayloadError('%s: invalid type (%d).' % (op_name, op.type))
+      op_counts[op.type] += 1
+
+      is_last = op_num == len(operations)
+      curr_data_used = self._CheckOperation(
+          op, op_name, is_last, old_block_counters, new_block_counters,
+          new_usable_size if old_fs_size else 0, new_usable_size,
+          prev_data_offset + total_data_used, allow_signature,
+          blob_hash_counts)
+      if curr_data_used:
+        op_blob_totals[op.type] += curr_data_used
+        total_data_used += curr_data_used
+
+    # Report totals and breakdown statistics.
+    report.AddField('total operations', op_num)
+    report.AddField(
+        None,
+        histogram.Histogram.FromCountDict(op_counts,
+                                          key_names=common.OpType.NAMES),
+        indent=1)
+    report.AddField('total blobs', sum(blob_hash_counts.values()))
+    report.AddField(None,
+                    histogram.Histogram.FromCountDict(blob_hash_counts),
+                    indent=1)
+    report.AddField('total blob size', _AddHumanReadableSize(total_data_used))
+    report.AddField(
+        None,
+        histogram.Histogram.FromCountDict(op_blob_totals,
+                                          formatter=_AddHumanReadableSize,
+                                          key_names=common.OpType.NAMES),
+        indent=1)
+
+    # Report read/write histograms.
+    if old_block_counters:
+      report.AddField('block read hist',
+                      histogram.Histogram.FromKeyList(old_block_counters),
+                      linebreak=True, indent=1)
+
+    new_write_hist = histogram.Histogram.FromKeyList(
+        new_block_counters[:self._SizeToNumBlocks(new_fs_size)])
+    report.AddField('block write hist', new_write_hist, linebreak=True,
+                    indent=1)
+
+    # Check: Full update must write each dst block once.
+    if self.payload_type == _TYPE_FULL and new_write_hist.GetKeys() != [1]:
+      raise error.PayloadError(
+          '%s: not all blocks written exactly once during full update.' %
+          base_name)
+
+    return total_data_used
+
+  def _CheckSignatures(self, report, pubkey_file_name):
+    """Checks a payload's signature block."""
+    sigs_raw = self.payload.ReadDataBlob(self.sigs_offset, self.sigs_size)
+    sigs = update_metadata_pb2.Signatures()
+    sigs.ParseFromString(sigs_raw)
+    report.AddSection('signatures')
+
+    # Check: At least one signature present.
+    # pylint cannot see through the protobuf object, it seems.
+    # pylint: disable=E1101
+    if not sigs.signatures:
+      raise error.PayloadError('Signature block is empty.')
+
+    last_ops_section = (self.payload.manifest.kernel_install_operations or
+                        self.payload.manifest.install_operations)
+    fake_sig_op = last_ops_section[-1]
+    # Check: signatures_{offset,size} must match the last (fake) operation.
+    if not (fake_sig_op.type == common.OpType.REPLACE and
+            self.sigs_offset == fake_sig_op.data_offset and
+            self.sigs_size == fake_sig_op.data_length):
+      raise error.PayloadError(
+          'Signatures_{offset,size} (%d+%d) does not match last operation '
+          '(%d+%d).' %
+          (self.sigs_offset, self.sigs_size, fake_sig_op.data_offset,
+           fake_sig_op.data_length))
+
+    # Compute the checksum of all data up to signature blob.
+    # TODO(garnold) we're re-reading the whole data section into a string
+    # just to compute the checksum; instead, we could do it incrementally as
+    # we read the blobs one-by-one, under the assumption that we're reading
+    # them in order (which currently holds). This should be reconsidered.
+    payload_hasher = self.payload.manifest_hasher.copy()
+    common.Read(self.payload.payload_file, self.sigs_offset,
+                offset=self.payload.data_offset, hasher=payload_hasher)
+
+    for sig, sig_name in common.SignatureIter(sigs.signatures, 'signatures'):
+      sig_report = report.AddSubReport(sig_name)
+
+      # Check: Signature contains mandatory fields.
+      self._CheckMandatoryField(sig, 'version', sig_report, sig_name)
+      self._CheckMandatoryField(sig, 'data', None, sig_name)
+      sig_report.AddField('data len', len(sig.data))
+
+      # Check: Signatures pertains to actual payload hash.
+      if sig.version == 1:
+        self._CheckSha256Signature(sig.data, pubkey_file_name,
+                                   payload_hasher.digest(), sig_name)
+      else:
+        raise error.PayloadError('Unknown signature version (%d).' %
+                                 sig.version)
+
+  def Run(self, pubkey_file_name=None, metadata_sig_file=None,
+          rootfs_part_size=0, kernel_part_size=0, report_out_file=None):
+    """Checker entry point, invoking all checks.
+
+    Args:
+      pubkey_file_name: Public key used for signature verification.
+      metadata_sig_file: Metadata signature, if verification is desired.
+      rootfs_part_size: The size of rootfs partitions in bytes (default: infer
+                        based on payload type and version).
+      kernel_part_size: The size of kernel partitions in bytes (default: use
+                        reported filesystem size).
+      report_out_file: File object to dump the report to.
+
+    Raises:
+      error.PayloadError if payload verification failed.
+    """
+    if not pubkey_file_name:
+      pubkey_file_name = _DEFAULT_PUBKEY_FILE_NAME
+
+    report = _PayloadReport()
+
+    # Get payload file size.
+    self.payload.payload_file.seek(0, 2)
+    payload_file_size = self.payload.payload_file.tell()
+    self.payload.ResetFile()
+
+    try:
+      # Check metadata signature (if provided).
+      if metadata_sig_file:
+        metadata_sig = base64.b64decode(metadata_sig_file.read())
+        self._CheckSha256Signature(metadata_sig, pubkey_file_name,
+                                   self.payload.manifest_hasher.digest(),
+                                   'metadata signature')
+
+      # Part 1: Check the file header.
+      report.AddSection('header')
+      # Check: Payload version is valid.
+      if self.payload.header.version != 1:
+        raise error.PayloadError('Unknown payload version (%d).' %
+                                 self.payload.header.version)
+      report.AddField('version', self.payload.header.version)
+      report.AddField('manifest len', self.payload.header.manifest_len)
+
+      # Part 2: Check the manifest.
+      self._CheckManifest(report, rootfs_part_size, kernel_part_size)
+      assert self.payload_type, 'payload type should be known by now'
+
+      # Infer the usable partition size when validating rootfs operations:
+      # - If rootfs partition size was provided, use that.
+      # - Otherwise, if this is an older delta (minor version < 2), stick with
+      #   a known constant size. This is necessary because older deltas may
+      #   exceed the filesystem size when moving data blocks around.
+      # - Otherwise, use the encoded filesystem size.
+      new_rootfs_usable_size = self.new_rootfs_fs_size
+      if rootfs_part_size:
+        new_rootfs_usable_size = rootfs_part_size
+      elif self.payload_type == _TYPE_DELTA and self.minor_version in (None, 1):
+        new_rootfs_usable_size = _OLD_DELTA_USABLE_PART_SIZE
+
+      # Part 3: Examine rootfs operations.
+      # TODO(garnold)(chromium:243559) only default to the filesystem size if
+      # no explicit size provided *and* the partition size is not embedded in
+      # the payload; see issue for more details.
+      report.AddSection('rootfs operations')
+      total_blob_size = self._CheckOperations(
+          self.payload.manifest.install_operations, report,
+          'install_operations', self.old_rootfs_fs_size,
+          self.new_rootfs_fs_size, new_rootfs_usable_size, 0, False)
+
+      # Part 4: Examine kernel operations.
+      # TODO(garnold)(chromium:243559) as above.
+      report.AddSection('kernel operations')
+      total_blob_size += self._CheckOperations(
+          self.payload.manifest.kernel_install_operations, report,
+          'kernel_install_operations', self.old_kernel_fs_size,
+          self.new_kernel_fs_size,
+          kernel_part_size if kernel_part_size else self.new_kernel_fs_size,
+          total_blob_size, True)
+
+      # Check: Operations data reach the end of the payload file.
+      used_payload_size = self.payload.data_offset + total_blob_size
+      if used_payload_size != payload_file_size:
+        raise error.PayloadError(
+            'Used payload size (%d) different from actual file size (%d).' %
+            (used_payload_size, payload_file_size))
+
+      # Part 5: Handle payload signatures message.
+      if self.check_payload_sig and self.sigs_size:
+        self._CheckSignatures(report, pubkey_file_name)
+
+      # Part 6: Summary.
+      report.AddSection('summary')
+      report.AddField('update type', self.payload_type)
+
+      report.Finalize()
+    finally:
+      if report_out_file:
+        report.Dump(report_out_file)
diff --git a/scripts/update_payload/checker_unittest.py b/scripts/update_payload/checker_unittest.py
new file mode 100755
index 0000000..56b1a30
--- /dev/null
+++ b/scripts/update_payload/checker_unittest.py
@@ -0,0 +1,1326 @@
+#!/usr/bin/python2
+#
+# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Unit testing checker.py."""
+
+from __future__ import print_function
+
+import array
+import collections
+import cStringIO
+import hashlib
+import itertools
+import os
+import unittest
+
+# pylint cannot find mox.
+# pylint: disable=F0401
+import mox
+
+import checker
+import common
+import payload as update_payload  # Avoid name conflicts later.
+import test_utils
+import update_metadata_pb2
+
+
+def _OpTypeByName(op_name):
+  op_name_to_type = {
+      'REPLACE': common.OpType.REPLACE,
+      'REPLACE_BZ': common.OpType.REPLACE_BZ,
+      'MOVE': common.OpType.MOVE,
+      'BSDIFF': common.OpType.BSDIFF,
+      'SOURCE_COPY': common.OpType.SOURCE_COPY,
+      'SOURCE_BSDIFF': common.OpType.SOURCE_BSDIFF,
+      'ZERO': common.OpType.ZERO,
+      'DISCARD': common.OpType.DISCARD,
+      'REPLACE_XZ': common.OpType.REPLACE_XZ,
+      'IMGDIFF': common.OpType.IMGDIFF,
+  }
+  return op_name_to_type[op_name]
+
+
+def _GetPayloadChecker(payload_gen_write_to_file_func, payload_gen_dargs=None,
+                       checker_init_dargs=None):
+  """Returns a payload checker from a given payload generator."""
+  if payload_gen_dargs is None:
+    payload_gen_dargs = {}
+  if checker_init_dargs is None:
+    checker_init_dargs = {}
+
+  payload_file = cStringIO.StringIO()
+  payload_gen_write_to_file_func(payload_file, **payload_gen_dargs)
+  payload_file.seek(0)
+  payload = update_payload.Payload(payload_file)
+  payload.Init()
+  return checker.PayloadChecker(payload, **checker_init_dargs)
+
+
+def _GetPayloadCheckerWithData(payload_gen):
+  """Returns a payload checker from a given payload generator."""
+  payload_file = cStringIO.StringIO()
+  payload_gen.WriteToFile(payload_file)
+  payload_file.seek(0)
+  payload = update_payload.Payload(payload_file)
+  payload.Init()
+  return checker.PayloadChecker(payload)
+
+
+# This class doesn't need an __init__().
+# pylint: disable=W0232
+# Unit testing is all about running protected methods.
+# pylint: disable=W0212
+# Don't bark about missing members of classes you cannot import.
+# pylint: disable=E1101
+class PayloadCheckerTest(mox.MoxTestBase):
+  """Tests the PayloadChecker class.
+
+  In addition to ordinary testFoo() methods, which are automatically invoked by
+  the unittest framework, in this class we make use of DoBarTest() calls that
+  implement parametric tests of certain features. In order to invoke each test,
+  which embodies a unique combination of parameter values, as a complete unit
+  test, we perform explicit enumeration of the parameter space and create
+  individual invocation contexts for each, which are then bound as
+  testBar__param1=val1__param2=val2(). The enumeration of parameter spaces for
+  all such tests is done in AddAllParametricTests().
+  """
+
+  def MockPayload(self):
+    """Create a mock payload object, complete with a mock manifest."""
+    payload = self.mox.CreateMock(update_payload.Payload)
+    payload.is_init = True
+    payload.manifest = self.mox.CreateMock(
+        update_metadata_pb2.DeltaArchiveManifest)
+    return payload
+
+  @staticmethod
+  def NewExtent(start_block, num_blocks):
+    """Returns an Extent message.
+
+    Each of the provided fields is set iff it is >= 0; otherwise, it's left at
+    its default state.
+
+    Args:
+      start_block: The starting block of the extent.
+      num_blocks: The number of blocks in the extent.
+
+    Returns:
+      An Extent message.
+    """
+    ex = update_metadata_pb2.Extent()
+    if start_block >= 0:
+      ex.start_block = start_block
+    if num_blocks >= 0:
+      ex.num_blocks = num_blocks
+    return ex
+
+  @staticmethod
+  def NewExtentList(*args):
+    """Returns an list of extents.
+
+    Args:
+      *args: (start_block, num_blocks) pairs defining the extents.
+
+    Returns:
+      A list of Extent objects.
+    """
+    ex_list = []
+    for start_block, num_blocks in args:
+      ex_list.append(PayloadCheckerTest.NewExtent(start_block, num_blocks))
+    return ex_list
+
+  @staticmethod
+  def AddToMessage(repeated_field, field_vals):
+    for field_val in field_vals:
+      new_field = repeated_field.add()
+      new_field.CopyFrom(field_val)
+
+  def SetupAddElemTest(self, is_present, is_submsg, convert=str,
+                       linebreak=False, indent=0):
+    """Setup for testing of _CheckElem() and its derivatives.
+
+    Args:
+      is_present: Whether or not the element is found in the message.
+      is_submsg: Whether the element is a sub-message itself.
+      convert: A representation conversion function.
+      linebreak: Whether or not a linebreak is to be used in the report.
+      indent: Indentation used for the report.
+
+    Returns:
+      msg: A mock message object.
+      report: A mock report object.
+      subreport: A mock sub-report object.
+      name: An element name to check.
+      val: Expected element value.
+    """
+    name = 'foo'
+    val = 'fake submsg' if is_submsg else 'fake field'
+    subreport = 'fake subreport'
+
+    # Create a mock message.
+    msg = self.mox.CreateMock(update_metadata_pb2._message.Message)
+    msg.HasField(name).AndReturn(is_present)
+    setattr(msg, name, val)
+
+    # Create a mock report.
+    report = self.mox.CreateMock(checker._PayloadReport)
+    if is_present:
+      if is_submsg:
+        report.AddSubReport(name).AndReturn(subreport)
+      else:
+        report.AddField(name, convert(val), linebreak=linebreak, indent=indent)
+
+    self.mox.ReplayAll()
+    return (msg, report, subreport, name, val)
+
+  def DoAddElemTest(self, is_present, is_mandatory, is_submsg, convert,
+                    linebreak, indent):
+    """Parametric testing of _CheckElem().
+
+    Args:
+      is_present: Whether or not the element is found in the message.
+      is_mandatory: Whether or not it's a mandatory element.
+      is_submsg: Whether the element is a sub-message itself.
+      convert: A representation conversion function.
+      linebreak: Whether or not a linebreak is to be used in the report.
+      indent: Indentation used for the report.
+    """
+    msg, report, subreport, name, val = self.SetupAddElemTest(
+        is_present, is_submsg, convert, linebreak, indent)
+
+    args = (msg, name, report, is_mandatory, is_submsg)
+    kwargs = {'convert': convert, 'linebreak': linebreak, 'indent': indent}
+    if is_mandatory and not is_present:
+      self.assertRaises(update_payload.PayloadError,
+                        checker.PayloadChecker._CheckElem, *args, **kwargs)
+    else:
+      ret_val, ret_subreport = checker.PayloadChecker._CheckElem(*args,
+                                                                 **kwargs)
+      self.assertEquals(val if is_present else None, ret_val)
+      self.assertEquals(subreport if is_present and is_submsg else None,
+                        ret_subreport)
+
+  def DoAddFieldTest(self, is_mandatory, is_present, convert, linebreak,
+                     indent):
+    """Parametric testing of _Check{Mandatory,Optional}Field().
+
+    Args:
+      is_mandatory: Whether we're testing a mandatory call.
+      is_present: Whether or not the element is found in the message.
+      convert: A representation conversion function.
+      linebreak: Whether or not a linebreak is to be used in the report.
+      indent: Indentation used for the report.
+    """
+    msg, report, _, name, val = self.SetupAddElemTest(
+        is_present, False, convert, linebreak, indent)
+
+    # Prepare for invocation of the tested method.
+    args = [msg, name, report]
+    kwargs = {'convert': convert, 'linebreak': linebreak, 'indent': indent}
+    if is_mandatory:
+      args.append('bar')
+      tested_func = checker.PayloadChecker._CheckMandatoryField
+    else:
+      tested_func = checker.PayloadChecker._CheckOptionalField
+
+    # Test the method call.
+    if is_mandatory and not is_present:
+      self.assertRaises(update_payload.PayloadError, tested_func, *args,
+                        **kwargs)
+    else:
+      ret_val = tested_func(*args, **kwargs)
+      self.assertEquals(val if is_present else None, ret_val)
+
+  def DoAddSubMsgTest(self, is_mandatory, is_present):
+    """Parametrized testing of _Check{Mandatory,Optional}SubMsg().
+
+    Args:
+      is_mandatory: Whether we're testing a mandatory call.
+      is_present: Whether or not the element is found in the message.
+    """
+    msg, report, subreport, name, val = self.SetupAddElemTest(is_present, True)
+
+    # Prepare for invocation of the tested method.
+    args = [msg, name, report]
+    if is_mandatory:
+      args.append('bar')
+      tested_func = checker.PayloadChecker._CheckMandatorySubMsg
+    else:
+      tested_func = checker.PayloadChecker._CheckOptionalSubMsg
+
+    # Test the method call.
+    if is_mandatory and not is_present:
+      self.assertRaises(update_payload.PayloadError, tested_func, *args)
+    else:
+      ret_val, ret_subreport = tested_func(*args)
+      self.assertEquals(val if is_present else None, ret_val)
+      self.assertEquals(subreport if is_present else None, ret_subreport)
+
+  def testCheckPresentIff(self):
+    """Tests _CheckPresentIff()."""
+    self.assertIsNone(checker.PayloadChecker._CheckPresentIff(
+        None, None, 'foo', 'bar', 'baz'))
+    self.assertIsNone(checker.PayloadChecker._CheckPresentIff(
+        'a', 'b', 'foo', 'bar', 'baz'))
+    self.assertRaises(update_payload.PayloadError,
+                      checker.PayloadChecker._CheckPresentIff,
+                      'a', None, 'foo', 'bar', 'baz')
+    self.assertRaises(update_payload.PayloadError,
+                      checker.PayloadChecker._CheckPresentIff,
+                      None, 'b', 'foo', 'bar', 'baz')
+
+  def DoCheckSha256SignatureTest(self, expect_pass, expect_subprocess_call,
+                                 sig_data, sig_asn1_header,
+                                 returned_signed_hash, expected_signed_hash):
+    """Parametric testing of _CheckSha256SignatureTest().
+
+    Args:
+      expect_pass: Whether or not it should pass.
+      expect_subprocess_call: Whether to expect the openssl call to happen.
+      sig_data: The signature raw data.
+      sig_asn1_header: The ASN1 header.
+      returned_signed_hash: The signed hash data retuned by openssl.
+      expected_signed_hash: The signed hash data to compare against.
+    """
+    try:
+      # Stub out the subprocess invocation.
+      self.mox.StubOutWithMock(checker.PayloadChecker, '_Run')
+      if expect_subprocess_call:
+        checker.PayloadChecker._Run(
+            mox.IsA(list), send_data=sig_data).AndReturn(
+                (sig_asn1_header + returned_signed_hash, None))
+
+      self.mox.ReplayAll()
+      if expect_pass:
+        self.assertIsNone(checker.PayloadChecker._CheckSha256Signature(
+            sig_data, 'foo', expected_signed_hash, 'bar'))
+      else:
+        self.assertRaises(update_payload.PayloadError,
+                          checker.PayloadChecker._CheckSha256Signature,
+                          sig_data, 'foo', expected_signed_hash, 'bar')
+    finally:
+      self.mox.UnsetStubs()
+
+  def testCheckSha256Signature_Pass(self):
+    """Tests _CheckSha256Signature(); pass case."""
+    sig_data = 'fake-signature'.ljust(256)
+    signed_hash = hashlib.sha256('fake-data').digest()
+    self.DoCheckSha256SignatureTest(True, True, sig_data,
+                                    common.SIG_ASN1_HEADER, signed_hash,
+                                    signed_hash)
+
+  def testCheckSha256Signature_FailBadSignature(self):
+    """Tests _CheckSha256Signature(); fails due to malformed signature."""
+    sig_data = 'fake-signature'  # Malformed (not 256 bytes in length).
+    signed_hash = hashlib.sha256('fake-data').digest()
+    self.DoCheckSha256SignatureTest(False, False, sig_data,
+                                    common.SIG_ASN1_HEADER, signed_hash,
+                                    signed_hash)
+
+  def testCheckSha256Signature_FailBadOutputLength(self):
+    """Tests _CheckSha256Signature(); fails due to unexpected output length."""
+    sig_data = 'fake-signature'.ljust(256)
+    signed_hash = 'fake-hash'  # Malformed (not 32 bytes in length).
+    self.DoCheckSha256SignatureTest(False, True, sig_data,
+                                    common.SIG_ASN1_HEADER, signed_hash,
+                                    signed_hash)
+
+  def testCheckSha256Signature_FailBadAsnHeader(self):
+    """Tests _CheckSha256Signature(); fails due to bad ASN1 header."""
+    sig_data = 'fake-signature'.ljust(256)
+    signed_hash = hashlib.sha256('fake-data').digest()
+    bad_asn1_header = 'bad-asn-header'.ljust(len(common.SIG_ASN1_HEADER))
+    self.DoCheckSha256SignatureTest(False, True, sig_data, bad_asn1_header,
+                                    signed_hash, signed_hash)
+
+  def testCheckSha256Signature_FailBadHash(self):
+    """Tests _CheckSha256Signature(); fails due to bad hash returned."""
+    sig_data = 'fake-signature'.ljust(256)
+    expected_signed_hash = hashlib.sha256('fake-data').digest()
+    returned_signed_hash = hashlib.sha256('bad-fake-data').digest()
+    self.DoCheckSha256SignatureTest(False, True, sig_data,
+                                    common.SIG_ASN1_HEADER,
+                                    expected_signed_hash, returned_signed_hash)
+
+  def testCheckBlocksFitLength_Pass(self):
+    """Tests _CheckBlocksFitLength(); pass case."""
+    self.assertIsNone(checker.PayloadChecker._CheckBlocksFitLength(
+        64, 4, 16, 'foo'))
+    self.assertIsNone(checker.PayloadChecker._CheckBlocksFitLength(
+        60, 4, 16, 'foo'))
+    self.assertIsNone(checker.PayloadChecker._CheckBlocksFitLength(
+        49, 4, 16, 'foo'))
+    self.assertIsNone(checker.PayloadChecker._CheckBlocksFitLength(
+        48, 3, 16, 'foo'))
+
+  def testCheckBlocksFitLength_TooManyBlocks(self):
+    """Tests _CheckBlocksFitLength(); fails due to excess blocks."""
+    self.assertRaises(update_payload.PayloadError,
+                      checker.PayloadChecker._CheckBlocksFitLength,
+                      64, 5, 16, 'foo')
+    self.assertRaises(update_payload.PayloadError,
+                      checker.PayloadChecker._CheckBlocksFitLength,
+                      60, 5, 16, 'foo')
+    self.assertRaises(update_payload.PayloadError,
+                      checker.PayloadChecker._CheckBlocksFitLength,
+                      49, 5, 16, 'foo')
+    self.assertRaises(update_payload.PayloadError,
+                      checker.PayloadChecker._CheckBlocksFitLength,
+                      48, 4, 16, 'foo')
+
+  def testCheckBlocksFitLength_TooFewBlocks(self):
+    """Tests _CheckBlocksFitLength(); fails due to insufficient blocks."""
+    self.assertRaises(update_payload.PayloadError,
+                      checker.PayloadChecker._CheckBlocksFitLength,
+                      64, 3, 16, 'foo')
+    self.assertRaises(update_payload.PayloadError,
+                      checker.PayloadChecker._CheckBlocksFitLength,
+                      60, 3, 16, 'foo')
+    self.assertRaises(update_payload.PayloadError,
+                      checker.PayloadChecker._CheckBlocksFitLength,
+                      49, 3, 16, 'foo')
+    self.assertRaises(update_payload.PayloadError,
+                      checker.PayloadChecker._CheckBlocksFitLength,
+                      48, 2, 16, 'foo')
+
+  def DoCheckManifestTest(self, fail_mismatched_block_size, fail_bad_sigs,
+                          fail_mismatched_oki_ori, fail_bad_oki, fail_bad_ori,
+                          fail_bad_nki, fail_bad_nri, fail_old_kernel_fs_size,
+                          fail_old_rootfs_fs_size, fail_new_kernel_fs_size,
+                          fail_new_rootfs_fs_size):
+    """Parametric testing of _CheckManifest().
+
+    Args:
+      fail_mismatched_block_size: Simulate a missing block_size field.
+      fail_bad_sigs: Make signatures descriptor inconsistent.
+      fail_mismatched_oki_ori: Make old rootfs/kernel info partially present.
+      fail_bad_oki: Tamper with old kernel info.
+      fail_bad_ori: Tamper with old rootfs info.
+      fail_bad_nki: Tamper with new kernel info.
+      fail_bad_nri: Tamper with new rootfs info.
+      fail_old_kernel_fs_size: Make old kernel fs size too big.
+      fail_old_rootfs_fs_size: Make old rootfs fs size too big.
+      fail_new_kernel_fs_size: Make new kernel fs size too big.
+      fail_new_rootfs_fs_size: Make new rootfs fs size too big.
+    """
+    # Generate a test payload. For this test, we only care about the manifest
+    # and don't need any data blobs, hence we can use a plain paylaod generator
+    # (which also gives us more control on things that can be screwed up).
+    payload_gen = test_utils.PayloadGenerator()
+
+    # Tamper with block size, if required.
+    if fail_mismatched_block_size:
+      payload_gen.SetBlockSize(test_utils.KiB(1))
+    else:
+      payload_gen.SetBlockSize(test_utils.KiB(4))
+
+    # Add some operations.
+    payload_gen.AddOperation(False, common.OpType.MOVE,
+                             src_extents=[(0, 16), (16, 497)],
+                             dst_extents=[(16, 496), (0, 16)])
+    payload_gen.AddOperation(True, common.OpType.MOVE,
+                             src_extents=[(0, 8), (8, 8)],
+                             dst_extents=[(8, 8), (0, 8)])
+
+    # Set an invalid signatures block (offset but no size), if required.
+    if fail_bad_sigs:
+      payload_gen.SetSignatures(32, None)
+
+    # Set partition / filesystem sizes.
+    rootfs_part_size = test_utils.MiB(8)
+    kernel_part_size = test_utils.KiB(512)
+    old_rootfs_fs_size = new_rootfs_fs_size = rootfs_part_size
+    old_kernel_fs_size = new_kernel_fs_size = kernel_part_size
+    if fail_old_kernel_fs_size:
+      old_kernel_fs_size += 100
+    if fail_old_rootfs_fs_size:
+      old_rootfs_fs_size += 100
+    if fail_new_kernel_fs_size:
+      new_kernel_fs_size += 100
+    if fail_new_rootfs_fs_size:
+      new_rootfs_fs_size += 100
+
+    # Add old kernel/rootfs partition info, as required.
+    if fail_mismatched_oki_ori or fail_old_kernel_fs_size or fail_bad_oki:
+      oki_hash = (None if fail_bad_oki
+                  else hashlib.sha256('fake-oki-content').digest())
+      payload_gen.SetPartInfo(True, False, old_kernel_fs_size, oki_hash)
+    if not fail_mismatched_oki_ori and (fail_old_rootfs_fs_size or
+                                        fail_bad_ori):
+      ori_hash = (None if fail_bad_ori
+                  else hashlib.sha256('fake-ori-content').digest())
+      payload_gen.SetPartInfo(False, False, old_rootfs_fs_size, ori_hash)
+
+    # Add new kernel/rootfs partition info.
+    payload_gen.SetPartInfo(
+        True, True, new_kernel_fs_size,
+        None if fail_bad_nki else hashlib.sha256('fake-nki-content').digest())
+    payload_gen.SetPartInfo(
+        False, True, new_rootfs_fs_size,
+        None if fail_bad_nri else hashlib.sha256('fake-nri-content').digest())
+
+    # Set the minor version.
+    payload_gen.SetMinorVersion(0)
+
+    # Create the test object.
+    payload_checker = _GetPayloadChecker(payload_gen.WriteToFile)
+    report = checker._PayloadReport()
+
+    should_fail = (fail_mismatched_block_size or fail_bad_sigs or
+                   fail_mismatched_oki_ori or fail_bad_oki or fail_bad_ori or
+                   fail_bad_nki or fail_bad_nri or fail_old_kernel_fs_size or
+                   fail_old_rootfs_fs_size or fail_new_kernel_fs_size or
+                   fail_new_rootfs_fs_size)
+    if should_fail:
+      self.assertRaises(update_payload.PayloadError,
+                        payload_checker._CheckManifest, report,
+                        rootfs_part_size, kernel_part_size)
+    else:
+      self.assertIsNone(payload_checker._CheckManifest(report,
+                                                       rootfs_part_size,
+                                                       kernel_part_size))
+
+  def testCheckLength(self):
+    """Tests _CheckLength()."""
+    payload_checker = checker.PayloadChecker(self.MockPayload())
+    block_size = payload_checker.block_size
+
+    # Passes.
+    self.assertIsNone(payload_checker._CheckLength(
+        int(3.5 * block_size), 4, 'foo', 'bar'))
+    # Fails, too few blocks.
+    self.assertRaises(update_payload.PayloadError,
+                      payload_checker._CheckLength,
+                      int(3.5 * block_size), 3, 'foo', 'bar')
+    # Fails, too many blocks.
+    self.assertRaises(update_payload.PayloadError,
+                      payload_checker._CheckLength,
+                      int(3.5 * block_size), 5, 'foo', 'bar')
+
+  def testCheckExtents(self):
+    """Tests _CheckExtents()."""
+    payload_checker = checker.PayloadChecker(self.MockPayload())
+    block_size = payload_checker.block_size
+
+    # Passes w/ all real extents.
+    extents = self.NewExtentList((0, 4), (8, 3), (1024, 16))
+    self.assertEquals(
+        23,
+        payload_checker._CheckExtents(extents, (1024 + 16) * block_size,
+                                      collections.defaultdict(int), 'foo'))
+
+    # Passes w/ pseudo-extents (aka sparse holes).
+    extents = self.NewExtentList((0, 4), (common.PSEUDO_EXTENT_MARKER, 5),
+                                 (8, 3))
+    self.assertEquals(
+        12,
+        payload_checker._CheckExtents(extents, (1024 + 16) * block_size,
+                                      collections.defaultdict(int), 'foo',
+                                      allow_pseudo=True))
+
+    # Passes w/ pseudo-extent due to a signature.
+    extents = self.NewExtentList((common.PSEUDO_EXTENT_MARKER, 2))
+    self.assertEquals(
+        2,
+        payload_checker._CheckExtents(extents, (1024 + 16) * block_size,
+                                      collections.defaultdict(int), 'foo',
+                                      allow_signature=True))
+
+    # Fails, extent missing a start block.
+    extents = self.NewExtentList((-1, 4), (8, 3), (1024, 16))
+    self.assertRaises(
+        update_payload.PayloadError, payload_checker._CheckExtents,
+        extents, (1024 + 16) * block_size, collections.defaultdict(int),
+        'foo')
+
+    # Fails, extent missing block count.
+    extents = self.NewExtentList((0, -1), (8, 3), (1024, 16))
+    self.assertRaises(
+        update_payload.PayloadError, payload_checker._CheckExtents,
+        extents, (1024 + 16) * block_size, collections.defaultdict(int),
+        'foo')
+
+    # Fails, extent has zero blocks.
+    extents = self.NewExtentList((0, 4), (8, 3), (1024, 0))
+    self.assertRaises(
+        update_payload.PayloadError, payload_checker._CheckExtents,
+        extents, (1024 + 16) * block_size, collections.defaultdict(int),
+        'foo')
+
+    # Fails, extent exceeds partition boundaries.
+    extents = self.NewExtentList((0, 4), (8, 3), (1024, 16))
+    self.assertRaises(
+        update_payload.PayloadError, payload_checker._CheckExtents,
+        extents, (1024 + 15) * block_size, collections.defaultdict(int),
+        'foo')
+
+  def testCheckReplaceOperation(self):
+    """Tests _CheckReplaceOperation() where op.type == REPLACE."""
+    payload_checker = checker.PayloadChecker(self.MockPayload())
+    block_size = payload_checker.block_size
+    data_length = 10000
+
+    op = self.mox.CreateMock(
+        update_metadata_pb2.InstallOperation)
+    op.type = common.OpType.REPLACE
+
+    # Pass.
+    op.src_extents = []
+    self.assertIsNone(
+        payload_checker._CheckReplaceOperation(
+            op, data_length, (data_length + block_size - 1) / block_size,
+            'foo'))
+
+    # Fail, src extents founds.
+    op.src_extents = ['bar']
+    self.assertRaises(
+        update_payload.PayloadError,
+        payload_checker._CheckReplaceOperation,
+        op, data_length, (data_length + block_size - 1) / block_size, 'foo')
+
+    # Fail, missing data.
+    op.src_extents = []
+    self.assertRaises(
+        update_payload.PayloadError,
+        payload_checker._CheckReplaceOperation,
+        op, None, (data_length + block_size - 1) / block_size, 'foo')
+
+    # Fail, length / block number mismatch.
+    op.src_extents = ['bar']
+    self.assertRaises(
+        update_payload.PayloadError,
+        payload_checker._CheckReplaceOperation,
+        op, data_length, (data_length + block_size - 1) / block_size + 1, 'foo')
+
+  def testCheckReplaceBzOperation(self):
+    """Tests _CheckReplaceOperation() where op.type == REPLACE_BZ."""
+    payload_checker = checker.PayloadChecker(self.MockPayload())
+    block_size = payload_checker.block_size
+    data_length = block_size * 3
+
+    op = self.mox.CreateMock(
+        update_metadata_pb2.InstallOperation)
+    op.type = common.OpType.REPLACE_BZ
+
+    # Pass.
+    op.src_extents = []
+    self.assertIsNone(
+        payload_checker._CheckReplaceOperation(
+            op, data_length, (data_length + block_size - 1) / block_size + 5,
+            'foo'))
+
+    # Fail, src extents founds.
+    op.src_extents = ['bar']
+    self.assertRaises(
+        update_payload.PayloadError,
+        payload_checker._CheckReplaceOperation,
+        op, data_length, (data_length + block_size - 1) / block_size + 5, 'foo')
+
+    # Fail, missing data.
+    op.src_extents = []
+    self.assertRaises(
+        update_payload.PayloadError,
+        payload_checker._CheckReplaceOperation,
+        op, None, (data_length + block_size - 1) / block_size, 'foo')
+
+    # Fail, too few blocks to justify BZ.
+    op.src_extents = []
+    self.assertRaises(
+        update_payload.PayloadError,
+        payload_checker._CheckReplaceOperation,
+        op, data_length, (data_length + block_size - 1) / block_size, 'foo')
+
+  def testCheckMoveOperation_Pass(self):
+    """Tests _CheckMoveOperation(); pass case."""
+    payload_checker = checker.PayloadChecker(self.MockPayload())
+    op = update_metadata_pb2.InstallOperation()
+    op.type = common.OpType.MOVE
+
+    self.AddToMessage(op.src_extents,
+                      self.NewExtentList((1, 4), (12, 2), (1024, 128)))
+    self.AddToMessage(op.dst_extents,
+                      self.NewExtentList((16, 128), (512, 6)))
+    self.assertIsNone(
+        payload_checker._CheckMoveOperation(op, None, 134, 134, 'foo'))
+
+  def testCheckMoveOperation_FailContainsData(self):
+    """Tests _CheckMoveOperation(); fails, message contains data."""
+    payload_checker = checker.PayloadChecker(self.MockPayload())
+    op = update_metadata_pb2.InstallOperation()
+    op.type = common.OpType.MOVE
+
+    self.AddToMessage(op.src_extents,
+                      self.NewExtentList((1, 4), (12, 2), (1024, 128)))
+    self.AddToMessage(op.dst_extents,
+                      self.NewExtentList((16, 128), (512, 6)))
+    self.assertRaises(
+        update_payload.PayloadError,
+        payload_checker._CheckMoveOperation,
+        op, 1024, 134, 134, 'foo')
+
+  def testCheckMoveOperation_FailInsufficientSrcBlocks(self):
+    """Tests _CheckMoveOperation(); fails, not enough actual src blocks."""
+    payload_checker = checker.PayloadChecker(self.MockPayload())
+    op = update_metadata_pb2.InstallOperation()
+    op.type = common.OpType.MOVE
+
+    self.AddToMessage(op.src_extents,
+                      self.NewExtentList((1, 4), (12, 2), (1024, 127)))
+    self.AddToMessage(op.dst_extents,
+                      self.NewExtentList((16, 128), (512, 6)))
+    self.assertRaises(
+        update_payload.PayloadError,
+        payload_checker._CheckMoveOperation,
+        op, None, 134, 134, 'foo')
+
+  def testCheckMoveOperation_FailInsufficientDstBlocks(self):
+    """Tests _CheckMoveOperation(); fails, not enough actual dst blocks."""
+    payload_checker = checker.PayloadChecker(self.MockPayload())
+    op = update_metadata_pb2.InstallOperation()
+    op.type = common.OpType.MOVE
+
+    self.AddToMessage(op.src_extents,
+                      self.NewExtentList((1, 4), (12, 2), (1024, 128)))
+    self.AddToMessage(op.dst_extents,
+                      self.NewExtentList((16, 128), (512, 5)))
+    self.assertRaises(
+        update_payload.PayloadError,
+        payload_checker._CheckMoveOperation,
+        op, None, 134, 134, 'foo')
+
+  def testCheckMoveOperation_FailExcessSrcBlocks(self):
+    """Tests _CheckMoveOperation(); fails, too many actual src blocks."""
+    payload_checker = checker.PayloadChecker(self.MockPayload())
+    op = update_metadata_pb2.InstallOperation()
+    op.type = common.OpType.MOVE
+
+    self.AddToMessage(op.src_extents,
+                      self.NewExtentList((1, 4), (12, 2), (1024, 128)))
+    self.AddToMessage(op.dst_extents,
+                      self.NewExtentList((16, 128), (512, 5)))
+    self.assertRaises(
+        update_payload.PayloadError,
+        payload_checker._CheckMoveOperation,
+        op, None, 134, 134, 'foo')
+    self.AddToMessage(op.src_extents,
+                      self.NewExtentList((1, 4), (12, 2), (1024, 129)))
+    self.AddToMessage(op.dst_extents,
+                      self.NewExtentList((16, 128), (512, 6)))
+    self.assertRaises(
+        update_payload.PayloadError,
+        payload_checker._CheckMoveOperation,
+        op, None, 134, 134, 'foo')
+
+  def testCheckMoveOperation_FailExcessDstBlocks(self):
+    """Tests _CheckMoveOperation(); fails, too many actual dst blocks."""
+    payload_checker = checker.PayloadChecker(self.MockPayload())
+    op = update_metadata_pb2.InstallOperation()
+    op.type = common.OpType.MOVE
+
+    self.AddToMessage(op.src_extents,
+                      self.NewExtentList((1, 4), (12, 2), (1024, 128)))
+    self.AddToMessage(op.dst_extents,
+                      self.NewExtentList((16, 128), (512, 7)))
+    self.assertRaises(
+        update_payload.PayloadError,
+        payload_checker._CheckMoveOperation,
+        op, None, 134, 134, 'foo')
+
+  def testCheckMoveOperation_FailStagnantBlocks(self):
+    """Tests _CheckMoveOperation(); fails, there are blocks that do not move."""
+    payload_checker = checker.PayloadChecker(self.MockPayload())
+    op = update_metadata_pb2.InstallOperation()
+    op.type = common.OpType.MOVE
+
+    self.AddToMessage(op.src_extents,
+                      self.NewExtentList((1, 4), (12, 2), (1024, 128)))
+    self.AddToMessage(op.dst_extents,
+                      self.NewExtentList((8, 128), (512, 6)))
+    self.assertRaises(
+        update_payload.PayloadError,
+        payload_checker._CheckMoveOperation,
+        op, None, 134, 134, 'foo')
+
+  def testCheckMoveOperation_FailZeroStartBlock(self):
+    """Tests _CheckMoveOperation(); fails, has extent with start block 0."""
+    payload_checker = checker.PayloadChecker(self.MockPayload())
+    op = update_metadata_pb2.InstallOperation()
+    op.type = common.OpType.MOVE
+
+    self.AddToMessage(op.src_extents,
+                      self.NewExtentList((0, 4), (12, 2), (1024, 128)))
+    self.AddToMessage(op.dst_extents,
+                      self.NewExtentList((8, 128), (512, 6)))
+    self.assertRaises(
+        update_payload.PayloadError,
+        payload_checker._CheckMoveOperation,
+        op, None, 134, 134, 'foo')
+
+    self.AddToMessage(op.src_extents,
+                      self.NewExtentList((1, 4), (12, 2), (1024, 128)))
+    self.AddToMessage(op.dst_extents,
+                      self.NewExtentList((0, 128), (512, 6)))
+    self.assertRaises(
+        update_payload.PayloadError,
+        payload_checker._CheckMoveOperation,
+        op, None, 134, 134, 'foo')
+
+  def testCheckAnyDiff(self):
+    """Tests _CheckAnyDiffOperation()."""
+    payload_checker = checker.PayloadChecker(self.MockPayload())
+
+    # Pass.
+    self.assertIsNone(
+        payload_checker._CheckAnyDiffOperation(10000, 3, 'foo'))
+
+    # Fail, missing data blob.
+    self.assertRaises(
+        update_payload.PayloadError,
+        payload_checker._CheckAnyDiffOperation,
+        None, 3, 'foo')
+
+    # Fail, too big of a diff blob (unjustified).
+    self.assertRaises(
+        update_payload.PayloadError,
+        payload_checker._CheckAnyDiffOperation,
+        10000, 2, 'foo')
+
+  def testCheckSourceCopyOperation_Pass(self):
+    """Tests _CheckSourceCopyOperation(); pass case."""
+    payload_checker = checker.PayloadChecker(self.MockPayload())
+    self.assertIsNone(
+        payload_checker._CheckSourceCopyOperation(None, 134, 134, 'foo'))
+
+  def testCheckSourceCopyOperation_FailContainsData(self):
+    """Tests _CheckSourceCopyOperation(); message contains data."""
+    payload_checker = checker.PayloadChecker(self.MockPayload())
+    self.assertRaises(update_payload.PayloadError,
+                      payload_checker._CheckSourceCopyOperation,
+                      134, 0, 0, 'foo')
+
+  def testCheckSourceCopyOperation_FailBlockCountsMismatch(self):
+    """Tests _CheckSourceCopyOperation(); src and dst block totals not equal."""
+    payload_checker = checker.PayloadChecker(self.MockPayload())
+    self.assertRaises(update_payload.PayloadError,
+                      payload_checker._CheckSourceCopyOperation,
+                      None, 0, 1, 'foo')
+
+  def DoCheckOperationTest(self, op_type_name, is_last, allow_signature,
+                           allow_unhashed, fail_src_extents, fail_dst_extents,
+                           fail_mismatched_data_offset_length,
+                           fail_missing_dst_extents, fail_src_length,
+                           fail_dst_length, fail_data_hash,
+                           fail_prev_data_offset, fail_bad_minor_version):
+    """Parametric testing of _CheckOperation().
+
+    Args:
+      op_type_name: 'REPLACE', 'REPLACE_BZ', 'MOVE', 'BSDIFF', 'SOURCE_COPY',
+        or 'SOURCE_BSDIFF'.
+      is_last: Whether we're testing the last operation in a sequence.
+      allow_signature: Whether we're testing a signature-capable operation.
+      allow_unhashed: Whether we're allowing to not hash the data.
+      fail_src_extents: Tamper with src extents.
+      fail_dst_extents: Tamper with dst extents.
+      fail_mismatched_data_offset_length: Make data_{offset,length}
+        inconsistent.
+      fail_missing_dst_extents: Do not include dst extents.
+      fail_src_length: Make src length inconsistent.
+      fail_dst_length: Make dst length inconsistent.
+      fail_data_hash: Tamper with the data blob hash.
+      fail_prev_data_offset: Make data space uses incontiguous.
+      fail_bad_minor_version: Make minor version incompatible with op.
+    """
+    op_type = _OpTypeByName(op_type_name)
+
+    # Create the test object.
+    payload = self.MockPayload()
+    payload_checker = checker.PayloadChecker(payload,
+                                             allow_unhashed=allow_unhashed)
+    block_size = payload_checker.block_size
+
+    # Create auxiliary arguments.
+    old_part_size = test_utils.MiB(4)
+    new_part_size = test_utils.MiB(8)
+    old_block_counters = array.array(
+        'B', [0] * ((old_part_size + block_size - 1) / block_size))
+    new_block_counters = array.array(
+        'B', [0] * ((new_part_size + block_size - 1) / block_size))
+    prev_data_offset = 1876
+    blob_hash_counts = collections.defaultdict(int)
+
+    # Create the operation object for the test.
+    op = update_metadata_pb2.InstallOperation()
+    op.type = op_type
+
+    total_src_blocks = 0
+    if op_type in (common.OpType.MOVE, common.OpType.BSDIFF,
+                   common.OpType.SOURCE_COPY, common.OpType.SOURCE_BSDIFF):
+      if fail_src_extents:
+        self.AddToMessage(op.src_extents,
+                          self.NewExtentList((1, 0)))
+      else:
+        self.AddToMessage(op.src_extents,
+                          self.NewExtentList((1, 16)))
+        total_src_blocks = 16
+
+    if op_type in (common.OpType.REPLACE, common.OpType.REPLACE_BZ):
+      payload_checker.minor_version = 0
+    elif op_type in (common.OpType.MOVE, common.OpType.BSDIFF):
+      payload_checker.minor_version = 2 if fail_bad_minor_version else 1
+    elif op_type in (common.OpType.SOURCE_COPY, common.OpType.SOURCE_BSDIFF):
+      payload_checker.minor_version = 1 if fail_bad_minor_version else 2
+
+    if op_type not in (common.OpType.MOVE, common.OpType.SOURCE_COPY):
+      if not fail_mismatched_data_offset_length:
+        op.data_length = 16 * block_size - 8
+      if fail_prev_data_offset:
+        op.data_offset = prev_data_offset + 16
+      else:
+        op.data_offset = prev_data_offset
+
+      fake_data = 'fake-data'.ljust(op.data_length)
+      if not (allow_unhashed or (is_last and allow_signature and
+                                 op_type == common.OpType.REPLACE)):
+        if not fail_data_hash:
+          # Create a valid data blob hash.
+          op.data_sha256_hash = hashlib.sha256(fake_data).digest()
+          payload.ReadDataBlob(op.data_offset, op.data_length).AndReturn(
+              fake_data)
+      elif fail_data_hash:
+        # Create an invalid data blob hash.
+        op.data_sha256_hash = hashlib.sha256(
+            fake_data.replace(' ', '-')).digest()
+        payload.ReadDataBlob(op.data_offset, op.data_length).AndReturn(
+            fake_data)
+
+    total_dst_blocks = 0
+    if not fail_missing_dst_extents:
+      total_dst_blocks = 16
+      if fail_dst_extents:
+        self.AddToMessage(op.dst_extents,
+                          self.NewExtentList((4, 16), (32, 0)))
+      else:
+        self.AddToMessage(op.dst_extents,
+                          self.NewExtentList((4, 8), (64, 8)))
+
+    if total_src_blocks:
+      if fail_src_length:
+        op.src_length = total_src_blocks * block_size + 8
+      else:
+        op.src_length = total_src_blocks * block_size
+    elif fail_src_length:
+      # Add an orphaned src_length.
+      op.src_length = 16
+
+    if total_dst_blocks:
+      if fail_dst_length:
+        op.dst_length = total_dst_blocks * block_size + 8
+      else:
+        op.dst_length = total_dst_blocks * block_size
+
+    self.mox.ReplayAll()
+    should_fail = (fail_src_extents or fail_dst_extents or
+                   fail_mismatched_data_offset_length or
+                   fail_missing_dst_extents or fail_src_length or
+                   fail_dst_length or fail_data_hash or fail_prev_data_offset or
+                   fail_bad_minor_version)
+    args = (op, 'foo', is_last, old_block_counters, new_block_counters,
+            old_part_size, new_part_size, prev_data_offset, allow_signature,
+            blob_hash_counts)
+    if should_fail:
+      self.assertRaises(update_payload.PayloadError,
+                        payload_checker._CheckOperation, *args)
+    else:
+      self.assertEqual(op.data_length if op.HasField('data_length') else 0,
+                       payload_checker._CheckOperation(*args))
+
+  def testAllocBlockCounters(self):
+    """Tests _CheckMoveOperation()."""
+    payload_checker = checker.PayloadChecker(self.MockPayload())
+    block_size = payload_checker.block_size
+
+    # Check allocation for block-aligned partition size, ensure it's integers.
+    result = payload_checker._AllocBlockCounters(16 * block_size)
+    self.assertEqual(16, len(result))
+    self.assertEqual(int, type(result[0]))
+
+    # Check allocation of unaligned partition sizes.
+    result = payload_checker._AllocBlockCounters(16 * block_size - 1)
+    self.assertEqual(16, len(result))
+    result = payload_checker._AllocBlockCounters(16 * block_size + 1)
+    self.assertEqual(17, len(result))
+
+  def DoCheckOperationsTest(self, fail_nonexhaustive_full_update):
+    # Generate a test payload. For this test, we only care about one
+    # (arbitrary) set of operations, so we'll only be generating kernel and
+    # test with them.
+    payload_gen = test_utils.PayloadGenerator()
+
+    block_size = test_utils.KiB(4)
+    payload_gen.SetBlockSize(block_size)
+
+    rootfs_part_size = test_utils.MiB(8)
+
+    # Fake rootfs operations in a full update, tampered with as required.
+    rootfs_op_type = common.OpType.REPLACE
+    rootfs_data_length = rootfs_part_size
+    if fail_nonexhaustive_full_update:
+      rootfs_data_length -= block_size
+
+    payload_gen.AddOperation(False, rootfs_op_type,
+                             dst_extents=[(0, rootfs_data_length / block_size)],
+                             data_offset=0,
+                             data_length=rootfs_data_length)
+
+    # Create the test object.
+    payload_checker = _GetPayloadChecker(payload_gen.WriteToFile,
+                                         checker_init_dargs={
+                                             'allow_unhashed': True})
+    payload_checker.payload_type = checker._TYPE_FULL
+    report = checker._PayloadReport()
+
+    args = (payload_checker.payload.manifest.install_operations, report,
+            'foo', 0, rootfs_part_size, rootfs_part_size, 0, False)
+    if fail_nonexhaustive_full_update:
+      self.assertRaises(update_payload.PayloadError,
+                        payload_checker._CheckOperations, *args)
+    else:
+      self.assertEqual(rootfs_data_length,
+                       payload_checker._CheckOperations(*args))
+
+  def DoCheckSignaturesTest(self, fail_empty_sigs_blob, fail_missing_pseudo_op,
+                            fail_mismatched_pseudo_op, fail_sig_missing_fields,
+                            fail_unknown_sig_version, fail_incorrect_sig):
+    # Generate a test payload. For this test, we only care about the signature
+    # block and how it relates to the payload hash. Therefore, we're generating
+    # a random (otherwise useless) payload for this purpose.
+    payload_gen = test_utils.EnhancedPayloadGenerator()
+    block_size = test_utils.KiB(4)
+    payload_gen.SetBlockSize(block_size)
+    rootfs_part_size = test_utils.MiB(2)
+    kernel_part_size = test_utils.KiB(16)
+    payload_gen.SetPartInfo(False, True, rootfs_part_size,
+                            hashlib.sha256('fake-new-rootfs-content').digest())
+    payload_gen.SetPartInfo(True, True, kernel_part_size,
+                            hashlib.sha256('fake-new-kernel-content').digest())
+    payload_gen.SetMinorVersion(0)
+    payload_gen.AddOperationWithData(
+        False, common.OpType.REPLACE,
+        dst_extents=[(0, rootfs_part_size / block_size)],
+        data_blob=os.urandom(rootfs_part_size))
+
+    do_forge_pseudo_op = (fail_missing_pseudo_op or fail_mismatched_pseudo_op)
+    do_forge_sigs_data = (do_forge_pseudo_op or fail_empty_sigs_blob or
+                          fail_sig_missing_fields or fail_unknown_sig_version
+                          or fail_incorrect_sig)
+
+    sigs_data = None
+    if do_forge_sigs_data:
+      sigs_gen = test_utils.SignaturesGenerator()
+      if not fail_empty_sigs_blob:
+        if fail_sig_missing_fields:
+          sig_data = None
+        else:
+          sig_data = test_utils.SignSha256('fake-payload-content',
+                                           test_utils._PRIVKEY_FILE_NAME)
+        sigs_gen.AddSig(5 if fail_unknown_sig_version else 1, sig_data)
+
+      sigs_data = sigs_gen.ToBinary()
+      payload_gen.SetSignatures(payload_gen.curr_offset, len(sigs_data))
+
+    if do_forge_pseudo_op:
+      assert sigs_data is not None, 'should have forged signatures blob by now'
+      sigs_len = len(sigs_data)
+      payload_gen.AddOperation(
+          False, common.OpType.REPLACE,
+          data_offset=payload_gen.curr_offset / 2,
+          data_length=sigs_len / 2,
+          dst_extents=[(0, (sigs_len / 2 + block_size - 1) / block_size)])
+
+    # Generate payload (complete w/ signature) and create the test object.
+    payload_checker = _GetPayloadChecker(
+        payload_gen.WriteToFileWithData,
+        payload_gen_dargs={
+            'sigs_data': sigs_data,
+            'privkey_file_name': test_utils._PRIVKEY_FILE_NAME,
+            'do_add_pseudo_operation': not do_forge_pseudo_op})
+    payload_checker.payload_type = checker._TYPE_FULL
+    report = checker._PayloadReport()
+
+    # We have to check the manifest first in order to set signature attributes.
+    payload_checker._CheckManifest(report, rootfs_part_size, kernel_part_size)
+
+    should_fail = (fail_empty_sigs_blob or fail_missing_pseudo_op or
+                   fail_mismatched_pseudo_op or fail_sig_missing_fields or
+                   fail_unknown_sig_version or fail_incorrect_sig)
+    args = (report, test_utils._PUBKEY_FILE_NAME)
+    if should_fail:
+      self.assertRaises(update_payload.PayloadError,
+                        payload_checker._CheckSignatures, *args)
+    else:
+      self.assertIsNone(payload_checker._CheckSignatures(*args))
+
+  def DoCheckManifestMinorVersionTest(self, minor_version, payload_type):
+    """Parametric testing for CheckManifestMinorVersion().
+
+    Args:
+      minor_version: The payload minor version to test with.
+      payload_type: The type of the payload we're testing, delta or full.
+    """
+    # Create the test object.
+    payload = self.MockPayload()
+    payload.manifest.minor_version = minor_version
+    payload_checker = checker.PayloadChecker(payload)
+    payload_checker.payload_type = payload_type
+    report = checker._PayloadReport()
+
+    should_succeed = (
+        (minor_version == 0 and payload_type == checker._TYPE_FULL) or
+        (minor_version == 1 and payload_type == checker._TYPE_DELTA) or
+        (minor_version == 2 and payload_type == checker._TYPE_DELTA) or
+        (minor_version == 3 and payload_type == checker._TYPE_DELTA) or
+        (minor_version == 4 and payload_type == checker._TYPE_DELTA))
+    args = (report,)
+
+    if should_succeed:
+      self.assertIsNone(payload_checker._CheckManifestMinorVersion(*args))
+    else:
+      self.assertRaises(update_payload.PayloadError,
+                        payload_checker._CheckManifestMinorVersion, *args)
+
+  def DoRunTest(self, rootfs_part_size_provided, kernel_part_size_provided,
+                fail_wrong_payload_type, fail_invalid_block_size,
+                fail_mismatched_block_size, fail_excess_data,
+                fail_rootfs_part_size_exceeded,
+                fail_kernel_part_size_exceeded):
+    # Generate a test payload. For this test, we generate a full update that
+    # has sample kernel and rootfs operations. Since most testing is done with
+    # internal PayloadChecker methods that are tested elsewhere, here we only
+    # tamper with what's actually being manipulated and/or tested in the Run()
+    # method itself. Note that the checker doesn't verify partition hashes, so
+    # they're safe to fake.
+    payload_gen = test_utils.EnhancedPayloadGenerator()
+    block_size = test_utils.KiB(4)
+    payload_gen.SetBlockSize(block_size)
+    kernel_filesystem_size = test_utils.KiB(16)
+    rootfs_filesystem_size = test_utils.MiB(2)
+    payload_gen.SetPartInfo(False, True, rootfs_filesystem_size,
+                            hashlib.sha256('fake-new-rootfs-content').digest())
+    payload_gen.SetPartInfo(True, True, kernel_filesystem_size,
+                            hashlib.sha256('fake-new-kernel-content').digest())
+    payload_gen.SetMinorVersion(0)
+
+    rootfs_part_size = 0
+    if rootfs_part_size_provided:
+      rootfs_part_size = rootfs_filesystem_size + block_size
+    rootfs_op_size = rootfs_part_size or rootfs_filesystem_size
+    if fail_rootfs_part_size_exceeded:
+      rootfs_op_size += block_size
+    payload_gen.AddOperationWithData(
+        False, common.OpType.REPLACE,
+        dst_extents=[(0, rootfs_op_size / block_size)],
+        data_blob=os.urandom(rootfs_op_size))
+
+    kernel_part_size = 0
+    if kernel_part_size_provided:
+      kernel_part_size = kernel_filesystem_size + block_size
+    kernel_op_size = kernel_part_size or kernel_filesystem_size
+    if fail_kernel_part_size_exceeded:
+      kernel_op_size += block_size
+    payload_gen.AddOperationWithData(
+        True, common.OpType.REPLACE,
+        dst_extents=[(0, kernel_op_size / block_size)],
+        data_blob=os.urandom(kernel_op_size))
+
+    # Generate payload (complete w/ signature) and create the test object.
+    if fail_invalid_block_size:
+      use_block_size = block_size + 5  # Not a power of two.
+    elif fail_mismatched_block_size:
+      use_block_size = block_size * 2  # Different that payload stated.
+    else:
+      use_block_size = block_size
+
+    kwargs = {
+        'payload_gen_dargs': {
+            'privkey_file_name': test_utils._PRIVKEY_FILE_NAME,
+            'do_add_pseudo_operation': True,
+            'is_pseudo_in_kernel': True,
+            'padding': os.urandom(1024) if fail_excess_data else None},
+        'checker_init_dargs': {
+            'assert_type': 'delta' if fail_wrong_payload_type else 'full',
+            'block_size': use_block_size}}
+    if fail_invalid_block_size:
+      self.assertRaises(update_payload.PayloadError, _GetPayloadChecker,
+                        payload_gen.WriteToFileWithData, **kwargs)
+    else:
+      payload_checker = _GetPayloadChecker(payload_gen.WriteToFileWithData,
+                                           **kwargs)
+
+      kwargs = {'pubkey_file_name': test_utils._PUBKEY_FILE_NAME,
+                'rootfs_part_size': rootfs_part_size,
+                'kernel_part_size': kernel_part_size}
+      should_fail = (fail_wrong_payload_type or fail_mismatched_block_size or
+                     fail_excess_data or
+                     fail_rootfs_part_size_exceeded or
+                     fail_kernel_part_size_exceeded)
+      if should_fail:
+        self.assertRaises(update_payload.PayloadError, payload_checker.Run,
+                          **kwargs)
+      else:
+        self.assertIsNone(payload_checker.Run(**kwargs))
+
+# This implements a generic API, hence the occasional unused args.
+# pylint: disable=W0613
+def ValidateCheckOperationTest(op_type_name, is_last, allow_signature,
+                               allow_unhashed, fail_src_extents,
+                               fail_dst_extents,
+                               fail_mismatched_data_offset_length,
+                               fail_missing_dst_extents, fail_src_length,
+                               fail_dst_length, fail_data_hash,
+                               fail_prev_data_offset, fail_bad_minor_version):
+  """Returns True iff the combination of arguments represents a valid test."""
+  op_type = _OpTypeByName(op_type_name)
+
+  # REPLACE/REPLACE_BZ operations don't read data from src partition. They are
+  # compatible with all valid minor versions, so we don't need to check that.
+  if (op_type in (common.OpType.REPLACE, common.OpType.REPLACE_BZ) and (
+      fail_src_extents or fail_src_length or fail_bad_minor_version)):
+    return False
+
+  # MOVE and SOURCE_COPY operations don't carry data.
+  if (op_type in (common.OpType.MOVE, common.OpType.SOURCE_COPY) and (
+      fail_mismatched_data_offset_length or fail_data_hash or
+      fail_prev_data_offset)):
+    return False
+
+  return True
+
+
+def TestMethodBody(run_method_name, run_dargs):
+  """Returns a function that invokes a named method with named arguments."""
+  return lambda self: getattr(self, run_method_name)(**run_dargs)
+
+
+def AddParametricTests(tested_method_name, arg_space, validate_func=None):
+  """Enumerates and adds specific parametric tests to PayloadCheckerTest.
+
+  This function enumerates a space of test parameters (defined by arg_space),
+  then binds a new, unique method name in PayloadCheckerTest to a test function
+  that gets handed the said parameters. This is a preferable approach to doing
+  the enumeration and invocation during the tests because this way each test is
+  treated as a complete run by the unittest framework, and so benefits from the
+  usual setUp/tearDown mechanics.
+
+  Args:
+    tested_method_name: Name of the tested PayloadChecker method.
+    arg_space: A dictionary containing variables (keys) and lists of values
+               (values) associated with them.
+    validate_func: A function used for validating test argument combinations.
+  """
+  for value_tuple in itertools.product(*arg_space.itervalues()):
+    run_dargs = dict(zip(arg_space.iterkeys(), value_tuple))
+    if validate_func and not validate_func(**run_dargs):
+      continue
+    run_method_name = 'Do%sTest' % tested_method_name
+    test_method_name = 'test%s' % tested_method_name
+    for arg_key, arg_val in run_dargs.iteritems():
+      if arg_val or type(arg_val) is int:
+        test_method_name += '__%s=%s' % (arg_key, arg_val)
+    setattr(PayloadCheckerTest, test_method_name,
+            TestMethodBody(run_method_name, run_dargs))
+
+
+def AddAllParametricTests():
+  """Enumerates and adds all parametric tests to PayloadCheckerTest."""
+  # Add all _CheckElem() test cases.
+  AddParametricTests('AddElem',
+                     {'linebreak': (True, False),
+                      'indent': (0, 1, 2),
+                      'convert': (str, lambda s: s[::-1]),
+                      'is_present': (True, False),
+                      'is_mandatory': (True, False),
+                      'is_submsg': (True, False)})
+
+  # Add all _Add{Mandatory,Optional}Field tests.
+  AddParametricTests('AddField',
+                     {'is_mandatory': (True, False),
+                      'linebreak': (True, False),
+                      'indent': (0, 1, 2),
+                      'convert': (str, lambda s: s[::-1]),
+                      'is_present': (True, False)})
+
+  # Add all _Add{Mandatory,Optional}SubMsg tests.
+  AddParametricTests('AddSubMsg',
+                     {'is_mandatory': (True, False),
+                      'is_present': (True, False)})
+
+  # Add all _CheckManifest() test cases.
+  AddParametricTests('CheckManifest',
+                     {'fail_mismatched_block_size': (True, False),
+                      'fail_bad_sigs': (True, False),
+                      'fail_mismatched_oki_ori': (True, False),
+                      'fail_bad_oki': (True, False),
+                      'fail_bad_ori': (True, False),
+                      'fail_bad_nki': (True, False),
+                      'fail_bad_nri': (True, False),
+                      'fail_old_kernel_fs_size': (True, False),
+                      'fail_old_rootfs_fs_size': (True, False),
+                      'fail_new_kernel_fs_size': (True, False),
+                      'fail_new_rootfs_fs_size': (True, False)})
+
+  # Add all _CheckOperation() test cases.
+  AddParametricTests('CheckOperation',
+                     {'op_type_name': ('REPLACE', 'REPLACE_BZ', 'MOVE',
+                                       'BSDIFF', 'SOURCE_COPY',
+                                       'SOURCE_BSDIFF'),
+                      'is_last': (True, False),
+                      'allow_signature': (True, False),
+                      'allow_unhashed': (True, False),
+                      'fail_src_extents': (True, False),
+                      'fail_dst_extents': (True, False),
+                      'fail_mismatched_data_offset_length': (True, False),
+                      'fail_missing_dst_extents': (True, False),
+                      'fail_src_length': (True, False),
+                      'fail_dst_length': (True, False),
+                      'fail_data_hash': (True, False),
+                      'fail_prev_data_offset': (True, False),
+                      'fail_bad_minor_version': (True, False)},
+                     validate_func=ValidateCheckOperationTest)
+
+  # Add all _CheckOperations() test cases.
+  AddParametricTests('CheckOperations',
+                     {'fail_nonexhaustive_full_update': (True, False)})
+
+  # Add all _CheckOperations() test cases.
+  AddParametricTests('CheckSignatures',
+                     {'fail_empty_sigs_blob': (True, False),
+                      'fail_missing_pseudo_op': (True, False),
+                      'fail_mismatched_pseudo_op': (True, False),
+                      'fail_sig_missing_fields': (True, False),
+                      'fail_unknown_sig_version': (True, False),
+                      'fail_incorrect_sig': (True, False)})
+
+  # Add all _CheckManifestMinorVersion() test cases.
+  AddParametricTests('CheckManifestMinorVersion',
+                     {'minor_version': (None, 0, 1, 2, 3, 4, 555),
+                      'payload_type': (checker._TYPE_FULL,
+                                       checker._TYPE_DELTA)})
+
+  # Add all Run() test cases.
+  AddParametricTests('Run',
+                     {'rootfs_part_size_provided': (True, False),
+                      'kernel_part_size_provided': (True, False),
+                      'fail_wrong_payload_type': (True, False),
+                      'fail_invalid_block_size': (True, False),
+                      'fail_mismatched_block_size': (True, False),
+                      'fail_excess_data': (True, False),
+                      'fail_rootfs_part_size_exceeded': (True, False),
+                      'fail_kernel_part_size_exceeded': (True, False)})
+
+
+if __name__ == '__main__':
+  AddAllParametricTests()
+  unittest.main()
diff --git a/scripts/update_payload/common.py b/scripts/update_payload/common.py
new file mode 100644
index 0000000..678fc5d
--- /dev/null
+++ b/scripts/update_payload/common.py
@@ -0,0 +1,204 @@
+# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Utilities for update payload processing."""
+
+from __future__ import print_function
+
+from error import PayloadError
+import update_metadata_pb2
+
+
+#
+# Constants.
+#
+PSEUDO_EXTENT_MARKER = (1L << 64) - 1  # UINT64_MAX
+
+SIG_ASN1_HEADER = (
+    '\x30\x31\x30\x0d\x06\x09\x60\x86'
+    '\x48\x01\x65\x03\x04\x02\x01\x05'
+    '\x00\x04\x20'
+)
+
+CHROMEOS_MAJOR_PAYLOAD_VERSION = 1
+BRILLO_MAJOR_PAYLOAD_VERSION = 2
+
+INPLACE_MINOR_PAYLOAD_VERSION = 1
+SOURCE_MINOR_PAYLOAD_VERSION = 2
+OPSRCHASH_MINOR_PAYLOAD_VERSION = 3
+IMGDIFF_MINOR_PAYLOAD_VERSION = 4
+
+#
+# Payload operation types.
+#
+class OpType(object):
+  """Container for operation type constants."""
+  _CLASS = update_metadata_pb2.InstallOperation
+  # pylint: disable=E1101
+  REPLACE = _CLASS.REPLACE
+  REPLACE_BZ = _CLASS.REPLACE_BZ
+  MOVE = _CLASS.MOVE
+  BSDIFF = _CLASS.BSDIFF
+  SOURCE_COPY = _CLASS.SOURCE_COPY
+  SOURCE_BSDIFF = _CLASS.SOURCE_BSDIFF
+  ZERO = _CLASS.ZERO
+  DISCARD = _CLASS.DISCARD
+  REPLACE_XZ = _CLASS.REPLACE_XZ
+  IMGDIFF = _CLASS.IMGDIFF
+  ALL = (REPLACE, REPLACE_BZ, MOVE, BSDIFF, SOURCE_COPY, SOURCE_BSDIFF, ZERO,
+         DISCARD, REPLACE_XZ, IMGDIFF)
+  NAMES = {
+      REPLACE: 'REPLACE',
+      REPLACE_BZ: 'REPLACE_BZ',
+      MOVE: 'MOVE',
+      BSDIFF: 'BSDIFF',
+      SOURCE_COPY: 'SOURCE_COPY',
+      SOURCE_BSDIFF: 'SOURCE_BSDIFF',
+      ZERO: 'ZERO',
+      DISCARD: 'DISCARD',
+      REPLACE_XZ: 'REPLACE_XZ',
+      IMGDIFF: 'IMGDIFF',
+  }
+
+  def __init__(self):
+    pass
+
+
+#
+# Checked and hashed reading of data.
+#
+def IntPackingFmtStr(size, is_unsigned):
+  """Returns an integer format string for use by the struct module.
+
+  Args:
+    size: the integer size in bytes (2, 4 or 8)
+    is_unsigned: whether it is signed or not
+
+  Returns:
+    A format string for packing/unpacking integer values; assumes network byte
+    order (big-endian).
+
+  Raises:
+    PayloadError if something is wrong with the arguments.
+  """
+  # Determine the base conversion format.
+  if size == 2:
+    fmt = 'h'
+  elif size == 4:
+    fmt = 'i'
+  elif size == 8:
+    fmt = 'q'
+  else:
+    raise PayloadError('unsupport numeric field size (%s)' % size)
+
+  # Signed or unsigned?
+  if is_unsigned:
+    fmt = fmt.upper()
+
+  # Make it network byte order (big-endian).
+  fmt = '!' + fmt
+
+  return fmt
+
+
+def Read(file_obj, length, offset=None, hasher=None):
+  """Reads binary data from a file.
+
+  Args:
+    file_obj: an open file object
+    length: the length of the data to read
+    offset: an offset to seek to prior to reading; this is an absolute offset
+            from either the beginning (non-negative) or end (negative) of the
+            file.  (optional)
+    hasher: a hashing object to pass the read data through (optional)
+
+  Returns:
+    A string containing the read data.
+
+  Raises:
+    PayloadError if a read error occurred or not enough data was read.
+  """
+  if offset is not None:
+    if offset >= 0:
+      file_obj.seek(offset)
+    else:
+      file_obj.seek(offset, 2)
+
+  try:
+    data = file_obj.read(length)
+  except IOError, e:
+    raise PayloadError('error reading from file (%s): %s' % (file_obj.name, e))
+
+  if len(data) != length:
+    raise PayloadError(
+        'reading from file (%s) too short (%d instead of %d bytes)' %
+        (file_obj.name, len(data), length))
+
+  if hasher:
+    hasher.update(data)
+
+  return data
+
+
+#
+# Formatting functions.
+#
+def FormatExtent(ex, block_size=0):
+  end_block = ex.start_block + ex.num_blocks
+  if block_size:
+    return '%d->%d * %d' % (ex.start_block, end_block, block_size)
+  else:
+    return '%d->%d' % (ex.start_block, end_block)
+
+
+def FormatSha256(digest):
+  """Returns a canonical string representation of a SHA256 digest."""
+  return digest.encode('base64').strip()
+
+
+#
+# Useful iterators.
+#
+def _ObjNameIter(items, base_name, reverse=False, name_format_func=None):
+  """A generic (item, name) tuple iterators.
+
+  Args:
+    items: the sequence of objects to iterate on
+    base_name: the base name for all objects
+    reverse: whether iteration should be in reverse order
+    name_format_func: a function to apply to the name string
+
+  Yields:
+    An iterator whose i-th invocation returns (items[i], name), where name ==
+    base_name + '[i]' (with a formatting function optionally applied to it).
+  """
+  idx, inc = (len(items), -1) if reverse else (1, 1)
+  if reverse:
+    items = reversed(items)
+  for item in items:
+    item_name = '%s[%d]' % (base_name, idx)
+    if name_format_func:
+      item_name = name_format_func(item, item_name)
+    yield (item, item_name)
+    idx += inc
+
+
+def _OperationNameFormatter(op, op_name):
+  return '%s(%s)' % (op_name, OpType.NAMES.get(op.type, '?'))
+
+
+def OperationIter(operations, base_name, reverse=False):
+  """An (item, name) iterator for update operations."""
+  return _ObjNameIter(operations, base_name, reverse=reverse,
+                      name_format_func=_OperationNameFormatter)
+
+
+def ExtentIter(extents, base_name, reverse=False):
+  """An (item, name) iterator for operation extents."""
+  return _ObjNameIter(extents, base_name, reverse=reverse)
+
+
+def SignatureIter(sigs, base_name, reverse=False):
+  """An (item, name) iterator for signatures."""
+  return _ObjNameIter(sigs, base_name, reverse=reverse)
diff --git a/scripts/update_payload/error.py b/scripts/update_payload/error.py
new file mode 100644
index 0000000..8b9cadd
--- /dev/null
+++ b/scripts/update_payload/error.py
@@ -0,0 +1,9 @@
+# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Payload handling errors."""
+
+
+class PayloadError(Exception):
+  """An update payload general processing error."""
diff --git a/scripts/update_payload/format_utils.py b/scripts/update_payload/format_utils.py
new file mode 100644
index 0000000..2c3775c
--- /dev/null
+++ b/scripts/update_payload/format_utils.py
@@ -0,0 +1,97 @@
+# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Various formatting functions."""
+
+
+def NumToPercent(num, total, min_precision=1, max_precision=5):
+  """Returns the percentage (string) of |num| out of |total|.
+
+  If the percentage includes a fraction, it will be computed down to the least
+  precision that yields a non-zero and ranging between |min_precision| and
+  |max_precision|. Values are always rounded down. All arithmetic operations
+  are integer built-ins. Examples (using default precision):
+
+    (1, 1) => 100%
+    (3, 10) => 30%
+    (3, 9) => 33.3%
+    (3, 900) => 0.3%
+    (3, 9000000) => 0.00003%
+    (3, 900000000) => 0%
+    (5, 2) => 250%
+
+  Args:
+    num: the value of the part
+    total: the value of the whole
+    min_precision: minimum precision for fractional percentage
+    max_precision: maximum precision for fractional percentage
+  Returns:
+    Percentage string, or None if percent cannot be computed (i.e. total is
+    zero).
+
+  """
+  if total == 0:
+    return None
+
+  percent = 0
+  precision = min(min_precision, max_precision)
+  factor = 10 ** precision
+  while precision <= max_precision:
+    percent = num * 100 * factor / total
+    if percent:
+      break
+    factor *= 10
+    precision += 1
+
+  whole, frac = divmod(percent, factor)
+  while frac and not frac % 10:
+    frac /= 10
+    precision -= 1
+
+  return '%d%s%%' % (whole, '.%0*d' % (precision, frac) if frac else '')
+
+
+def BytesToHumanReadable(size, precision=1, decimal=False):
+  """Returns a human readable representation of a given |size|.
+
+  The returned string includes unit notations in either binary (KiB, MiB, etc)
+  or decimal (kB, MB, etc), based on the value of |decimal|. The chosen unit is
+  the largest that yields a whole (or mixed) number. It may contain up to
+  |precision| fractional digits. Values are always rounded down. Largest unit
+  is an exabyte. All arithmetic operations are integer built-ins. Examples
+  (using default precision and binary units):
+
+    4096 => 4 KiB
+    5000 => 4.8 KiB
+    500000 => 488.2 KiB
+    5000000 => 4.7 MiB
+
+  Args:
+    size: the size in bytes
+    precision: the number of digits past the decimal point
+    decimal: whether to compute/present decimal or binary units
+  Returns:
+    Readable size string, or None if no conversion is applicable (i.e. size is
+    less than the smallest unit).
+
+  """
+  constants = (
+      (('KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB'), 1024),
+      (('kB', 'MB', 'GB', 'TB', 'PB', 'EB'), 1000)
+  )
+  suffixes, base = constants[decimal]
+  exp, magnitude = 0, 1
+  while exp < len(suffixes):
+    next_magnitude = magnitude * base
+    if size < next_magnitude:
+      break
+    exp += 1
+    magnitude = next_magnitude
+
+  if exp != 0:
+    whole = size / magnitude
+    frac = (size % magnitude) * (10 ** precision) / magnitude
+    while frac and not frac % 10:
+      frac /= 10
+    return '%d%s %s' % (whole, '.%d' % frac if frac else '', suffixes[exp - 1])
diff --git a/scripts/update_payload/format_utils_unittest.py b/scripts/update_payload/format_utils_unittest.py
new file mode 100755
index 0000000..8c5ba8e
--- /dev/null
+++ b/scripts/update_payload/format_utils_unittest.py
@@ -0,0 +1,76 @@
+#!/usr/bin/python
+#
+# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Unit tests for format_utils.py."""
+
+import unittest
+
+import format_utils
+
+
+class NumToPercentTest(unittest.TestCase):
+  def testHundredPercent(self):
+    self.assertEqual(format_utils.NumToPercent(1, 1), '100%')
+
+  def testOverHundredPercent(self):
+    self.assertEqual(format_utils.NumToPercent(5, 2), '250%')
+
+  def testWholePercent(self):
+    self.assertEqual(format_utils.NumToPercent(3, 10), '30%')
+
+  def testDefaultMinPrecision(self):
+    self.assertEqual(format_utils.NumToPercent(3, 9), '33.3%')
+    self.assertEqual(format_utils.NumToPercent(3, 900), '0.3%')
+
+  def testDefaultMaxPrecision(self):
+    self.assertEqual(format_utils.NumToPercent(3, 9000000), '0.00003%')
+    self.assertEqual(format_utils.NumToPercent(3, 90000000), '0%')
+
+  def testCustomMinPrecision(self):
+    self.assertEqual(format_utils.NumToPercent(3, 9, min_precision=3),
+                     '33.333%')
+    self.assertEqual(format_utils.NumToPercent(3, 9, min_precision=0),
+                     '33%')
+
+  def testCustomMaxPrecision(self):
+    self.assertEqual(format_utils.NumToPercent(3, 900, max_precision=1),
+                     '0.3%')
+    self.assertEqual(format_utils.NumToPercent(3, 9000, max_precision=1),
+                     '0%')
+
+
+class BytesToHumanReadableTest(unittest.TestCase):
+  def testBaseTwo(self):
+    self.assertEqual(format_utils.BytesToHumanReadable(0x1000), '4 KiB')
+    self.assertEqual(format_utils.BytesToHumanReadable(0x400000), '4 MiB')
+    self.assertEqual(format_utils.BytesToHumanReadable(0x100000000), '4 GiB')
+    self.assertEqual(format_utils.BytesToHumanReadable(0x40000000000), '4 TiB')
+
+  def testDecimal(self):
+    self.assertEqual(format_utils.BytesToHumanReadable(5000, decimal=True),
+                     '5 kB')
+    self.assertEqual(format_utils.BytesToHumanReadable(5000000, decimal=True),
+                     '5 MB')
+    self.assertEqual(format_utils.BytesToHumanReadable(5000000000,
+                                                       decimal=True),
+                     '5 GB')
+
+  def testDefaultPrecision(self):
+    self.assertEqual(format_utils.BytesToHumanReadable(5000), '4.8 KiB')
+    self.assertEqual(format_utils.BytesToHumanReadable(500000), '488.2 KiB')
+    self.assertEqual(format_utils.BytesToHumanReadable(5000000), '4.7 MiB')
+
+  def testCustomPrecision(self):
+    self.assertEqual(format_utils.BytesToHumanReadable(5000, precision=3),
+                     '4.882 KiB')
+    self.assertEqual(format_utils.BytesToHumanReadable(500000, precision=0),
+                     '488 KiB')
+    self.assertEqual(format_utils.BytesToHumanReadable(5000000, precision=5),
+                     '4.76837 MiB')
+
+
+if __name__ == '__main__':
+  unittest.main()
diff --git a/scripts/update_payload/histogram.py b/scripts/update_payload/histogram.py
new file mode 100644
index 0000000..9916329
--- /dev/null
+++ b/scripts/update_payload/histogram.py
@@ -0,0 +1,117 @@
+# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Histogram generation tools."""
+
+from collections import defaultdict
+
+import format_utils
+
+
+class Histogram(object):
+  """A histogram generating object.
+
+  This object serves the sole purpose of formatting (key, val) pairs as an
+  ASCII histogram, including bars and percentage markers, and taking care of
+  label alignment, scaling, etc. In addition to the standard __init__
+  interface, two static methods are provided for conveniently converting data
+  in different formats into a histogram. Histogram generation is exported via
+  its __str__ method, and looks as follows:
+
+    Yes |################    | 5 (83.3%)
+    No  |###                 | 1 (16.6%)
+
+  TODO(garnold) we may want to add actual methods for adding data or tweaking
+  the output layout and formatting. For now, though, this is fine.
+
+  """
+
+  def __init__(self, data, scale=20, formatter=None):
+    """Initialize a histogram object.
+
+    Args:
+      data: list of (key, count) pairs constituting the histogram
+      scale: number of characters used to indicate 100%
+      formatter: function used for formatting raw histogram values
+
+    """
+    self.data = data
+    self.scale = scale
+    self.formatter = formatter or str
+    self.max_key_len = max([len(str(key)) for key, count in self.data])
+    self.total = sum([count for key, count in self.data])
+
+  @staticmethod
+  def FromCountDict(count_dict, scale=20, formatter=None, key_names=None):
+    """Takes a dictionary of counts and returns a histogram object.
+
+    This simply converts a mapping from names to counts into a list of (key,
+    count) pairs, optionally translating keys into name strings, then
+    generating and returning a histogram for them. This is a useful convenience
+    call for clients that update a dictionary of counters as they (say) scan a
+    data stream.
+
+    Args:
+      count_dict: dictionary mapping keys to occurrence counts
+      scale: number of characters used to indicate 100%
+      formatter: function used for formatting raw histogram values
+      key_names: dictionary mapping keys to name strings
+    Returns:
+      A histogram object based on the given data.
+
+    """
+    namer = None
+    if key_names:
+      namer = lambda key: key_names[key]
+    else:
+      namer = lambda key: key
+
+    hist = [(namer(key), count) for key, count in count_dict.items()]
+    return Histogram(hist, scale, formatter)
+
+  @staticmethod
+  def FromKeyList(key_list, scale=20, formatter=None, key_names=None):
+    """Takes a list of (possibly recurring) keys and returns a histogram object.
+
+    This converts the list into a dictionary of counters, then uses
+    FromCountDict() to generate the actual histogram. For example:
+
+      ['a', 'a', 'b', 'a', 'b'] --> {'a': 3, 'b': 2} --> ...
+
+    Args:
+      key_list: list of (possibly recurring) keys
+      scale: number of characters used to indicate 100%
+      formatter: function used for formatting raw histogram values
+      key_names: dictionary mapping keys to name strings
+    Returns:
+      A histogram object based on the given data.
+
+    """
+    count_dict = defaultdict(int)  # Unset items default to zero
+    for key in key_list:
+      count_dict[key] += 1
+    return Histogram.FromCountDict(count_dict, scale, formatter, key_names)
+
+  def __str__(self):
+    hist_lines = []
+    hist_bar = '|'
+    for key, count in self.data:
+      if self.total:
+        bar_len = count * self.scale / self.total
+        hist_bar = '|%s|' % ('#' * bar_len).ljust(self.scale)
+
+      line = '%s %s %s' % (
+          str(key).ljust(self.max_key_len),
+          hist_bar,
+          self.formatter(count))
+      percent_str = format_utils.NumToPercent(count, self.total)
+      if percent_str:
+        line += ' (%s)' % percent_str
+      hist_lines.append(line)
+
+    return '\n'.join(hist_lines)
+
+  def GetKeys(self):
+    """Returns the keys of the histogram."""
+    return [key for key, _ in self.data]
diff --git a/scripts/update_payload/histogram_unittest.py b/scripts/update_payload/histogram_unittest.py
new file mode 100755
index 0000000..421ff20
--- /dev/null
+++ b/scripts/update_payload/histogram_unittest.py
@@ -0,0 +1,60 @@
+#!/usr/bin/python
+#
+# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Unit tests for histogram.py."""
+
+import unittest
+
+import format_utils
+import histogram
+
+
+class HistogramTest(unittest.TestCase):
+
+  @staticmethod
+  def AddHumanReadableSize(size):
+    fmt = format_utils.BytesToHumanReadable(size)
+    return '%s (%s)' % (size, fmt) if fmt else str(size)
+
+  def CompareToExpectedDefault(self, actual_str):
+    expected_str = (
+        'Yes |################    | 5 (83.3%)\n'
+        'No  |###                 | 1 (16.6%)'
+    )
+    self.assertEqual(actual_str, expected_str)
+
+  def testExampleHistogram(self):
+    self.CompareToExpectedDefault(str(histogram.Histogram(
+        [('Yes', 5), ('No', 1)])))
+
+  def testFromCountDict(self):
+    self.CompareToExpectedDefault(str(histogram.Histogram.FromCountDict(
+        {'Yes': 5, 'No': 1})))
+
+  def testFromKeyList(self):
+    self.CompareToExpectedDefault(str(histogram.Histogram.FromKeyList(
+        ['Yes', 'Yes', 'No', 'Yes', 'Yes', 'Yes'])))
+
+  def testCustomScale(self):
+    expected_str = (
+        'Yes |#### | 5 (83.3%)\n'
+        'No  |     | 1 (16.6%)'
+    )
+    actual_str = str(histogram.Histogram([('Yes', 5), ('No', 1)], scale=5))
+    self.assertEqual(actual_str, expected_str)
+
+  def testCustomFormatter(self):
+    expected_str = (
+        'Yes |################    | 5000 (4.8 KiB) (83.3%)\n'
+        'No  |###                 | 1000 (16.6%)'
+    )
+    actual_str = str(histogram.Histogram(
+        [('Yes', 5000), ('No', 1000)], formatter=self.AddHumanReadableSize))
+    self.assertEqual(actual_str, expected_str)
+
+
+if __name__ == '__main__':
+  unittest.main()
diff --git a/scripts/update_payload/payload-test-key.pem b/scripts/update_payload/payload-test-key.pem
new file mode 100644
index 0000000..342e923
--- /dev/null
+++ b/scripts/update_payload/payload-test-key.pem
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpQIBAAKCAQEAvtGHtqO21Uhy2wGz9fluIpIUR8G7dZoCZhZukGkm4mlfgL71
+xPSArjx02/w/FhYxOusV6/XQeKgL3i8cni3HCkCOurZLpi2L5Ver6qrxKFh6WBVZ
+0Dj7N6P/Mf5jZdhfvVyweLlsNK8Ypeb+RazfrsXhd4cy3dBMxouGwH7R7QQXTFCo
+Cc8kgJBTxILl3jfvY8OrNKgYiCETa7tQdFkP0bfPwH9cAXuMjHXiZatim0tF+ivp
+kM2v/6LTxtD6Rq1wks/N6CHi8efrRaviFp7c0mNmBNFaV54cHEUW2SlNIiRun7L0
+1nAz/D8kuoHfx4E3Mtj0DbvngZJMX/X+rJQ5cQIDAQABAoIBADmE2X7hbJxwAUcp
+BUExFdTP6dMTf9lcOjrhqiRXvgPjtYkOhvD+rsdWq/cf2zhiKibTdEEzUMr+BM3N
+r7eyntvlR+DaUIVgF1pjigvryVPbD837aZ5NftRv194PC5FInttq1Dsf0ZEz8p8X
+uS/xg1+ggG1SUK/yOSJkLpNZ5xelbclQJ9bnJST8PR8XbEieA83xt5M2DcooPzq0
+/99m/daA5hmSWs6n8sFrIZDQxDhLyyW4J72jjoNTE87eCpwK855yXMelpEPDZNQi
+nB3x5Y/bGbl81PInqL2q14lekrVYdYZ7bOBVlsmyvz6f1e4OOE1aaAM+w6ArA4az
+6elZQE0CgYEA4GOU6BBu9jLqFdqV9jIkWsgz5ZWINz8PLJPtZzk5I9KO1m+GAUy2
+h/1IGGR6qRQR49hMtq4C0lUifxquq0xivzJ87U9oxKC9yEeTxkmDe5csVHsnAtqT
+xRgVM7Ysrut5NLU1zm0q3jBmkDu7d99LvscM/3n7eJ6RiYpnA54O6I8CgYEA2bNA
+34PTvxBS2deRoxKQNlVU14FtirE+q0+k0wcE85wr7wIMpR13al8T1TpE8J1yvvZM
+92HMGFGfYNDB46b8VfJ5AxEUFwdruec6sTVVfkMZMOqM/A08yiaLzQ1exDxNwaja
+fLuG5FAVRD/2g7fLBcsmosyNgcgNr1XA8Q/nvf8CgYEAwaSOg7py19rWcqehlMZu
+4z00tCNYWzz7LmA2l0clzYlPJTU3MvXt6+ujhRFpXXJpgfRPN7Nx0ewQihoPtNqF
+uTSr5OwLoOyK+0Tx/UPByS2L3xgscWUJ8yQ2X9sOMqIZhmf/mDZTsU2ZpU03GlrE
+dk43JF4zq0NEm6qp/dAwU3cCgYEAvECl+KKmmLIk8vvWlI2Y52Mi2rixYR2kc7+L
+aHDJd1+1HhlHlgDFItbU765Trz5322phZArN0rnCeJYNFC9yRWBIBL7gAIoKPdgW
+iOb15xlez04EXHGV/7kVa1wEdu0u0CiTxwjivMwDl+E36u8kQP5LirwYIgI800H0
+doCqhUECgYEAjvA38OS7hy56Q4LQtmHFBuRIn4E5SrIGMwNIH6TGbEKQix3ajTCQ
+0fSoLDGTkU6dH+T4v0WheveN2a2Kofqm0UQx5V2rfnY/Ut1fAAWgL/lsHLDnzPUZ
+bvTOANl8TbT49xAfNXTaGWe7F7nYz+bK0UDif1tJNDLQw7USD5I8lbQ=
+-----END RSA PRIVATE KEY-----
diff --git a/scripts/update_payload/payload-test-key.pub b/scripts/update_payload/payload-test-key.pub
new file mode 100644
index 0000000..fdae963
--- /dev/null
+++ b/scripts/update_payload/payload-test-key.pub
@@ -0,0 +1,9 @@
+-----BEGIN PUBLIC KEY-----
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvtGHtqO21Uhy2wGz9flu
+IpIUR8G7dZoCZhZukGkm4mlfgL71xPSArjx02/w/FhYxOusV6/XQeKgL3i8cni3H
+CkCOurZLpi2L5Ver6qrxKFh6WBVZ0Dj7N6P/Mf5jZdhfvVyweLlsNK8Ypeb+Razf
+rsXhd4cy3dBMxouGwH7R7QQXTFCoCc8kgJBTxILl3jfvY8OrNKgYiCETa7tQdFkP
+0bfPwH9cAXuMjHXiZatim0tF+ivpkM2v/6LTxtD6Rq1wks/N6CHi8efrRaviFp7c
+0mNmBNFaV54cHEUW2SlNIiRun7L01nAz/D8kuoHfx4E3Mtj0DbvngZJMX/X+rJQ5
+cQIDAQAB
+-----END PUBLIC KEY-----
diff --git a/scripts/update_payload/payload.py b/scripts/update_payload/payload.py
new file mode 100644
index 0000000..f76c0de
--- /dev/null
+++ b/scripts/update_payload/payload.py
@@ -0,0 +1,341 @@
+# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Tools for reading, verifying and applying Chrome OS update payloads."""
+
+from __future__ import print_function
+
+import hashlib
+import struct
+
+import applier
+import block_tracer
+import checker
+import common
+from error import PayloadError
+import update_metadata_pb2
+
+
+#
+# Helper functions.
+#
+def _ReadInt(file_obj, size, is_unsigned, hasher=None):
+  """Reads a binary-encoded integer from a file.
+
+  It will do the correct conversion based on the reported size and whether or
+  not a signed number is expected. Assumes a network (big-endian) byte
+  ordering.
+
+  Args:
+    file_obj: a file object
+    size: the integer size in bytes (2, 4 or 8)
+    is_unsigned: whether it is signed or not
+    hasher: an optional hasher to pass the value through
+
+  Returns:
+    An "unpacked" (Python) integer value.
+
+  Raises:
+    PayloadError if an read error occurred.
+  """
+  return struct.unpack(common.IntPackingFmtStr(size, is_unsigned),
+                       common.Read(file_obj, size, hasher=hasher))[0]
+
+
+#
+# Update payload.
+#
+class Payload(object):
+  """Chrome OS update payload processor."""
+
+  class _PayloadHeader(object):
+    """Update payload header struct."""
+
+    # Header constants; sizes are in bytes.
+    _MAGIC = 'CrAU'
+    _VERSION_SIZE = 8
+    _MANIFEST_LEN_SIZE = 8
+    _METADATA_SIGNATURE_LEN_SIZE = 4
+
+    def __init__(self):
+      self.version = None
+      self.manifest_len = None
+      self.metadata_signature_len = None
+      self.size = None
+
+    def ReadFromPayload(self, payload_file, hasher=None):
+      """Reads the payload header from a file.
+
+      Reads the payload header from the |payload_file| and updates the |hasher|
+      if one is passed. The parsed header is stored in the _PayloadHeader
+      instance attributes.
+
+      Args:
+        payload_file: a file object
+        hasher: an optional hasher to pass the value through
+
+      Returns:
+        None.
+
+      Raises:
+        PayloadError if a read error occurred or the header is invalid.
+      """
+      # Verify magic
+      magic = common.Read(payload_file, len(self._MAGIC), hasher=hasher)
+      if magic != self._MAGIC:
+        raise PayloadError('invalid payload magic: %s' % magic)
+
+      self.version = _ReadInt(payload_file, self._VERSION_SIZE, True,
+                              hasher=hasher)
+      self.manifest_len = _ReadInt(payload_file, self._MANIFEST_LEN_SIZE, True,
+                                   hasher=hasher)
+      self.size = (len(self._MAGIC) + self._VERSION_SIZE +
+                   self._MANIFEST_LEN_SIZE)
+      self.metadata_signature_len = 0
+
+      if self.version == common.BRILLO_MAJOR_PAYLOAD_VERSION:
+        self.size += self._METADATA_SIGNATURE_LEN_SIZE
+        self.metadata_signature_len = _ReadInt(
+            payload_file, self._METADATA_SIGNATURE_LEN_SIZE, True,
+            hasher=hasher)
+
+
+  def __init__(self, payload_file):
+    """Initialize the payload object.
+
+    Args:
+      payload_file: update payload file object open for reading
+    """
+    self.payload_file = payload_file
+    self.manifest_hasher = None
+    self.is_init = False
+    self.header = None
+    self.manifest = None
+    self.data_offset = None
+    self.metadata_signature = None
+    self.metadata_size = None
+
+  def _ReadHeader(self):
+    """Reads and returns the payload header.
+
+    Returns:
+      A payload header object.
+
+    Raises:
+      PayloadError if a read error occurred.
+    """
+    header = self._PayloadHeader()
+    header.ReadFromPayload(self.payload_file, self.manifest_hasher)
+    return header
+
+  def _ReadManifest(self):
+    """Reads and returns the payload manifest.
+
+    Returns:
+      A string containing the payload manifest in binary form.
+
+    Raises:
+      PayloadError if a read error occurred.
+    """
+    if not self.header:
+      raise PayloadError('payload header not present')
+
+    return common.Read(self.payload_file, self.header.manifest_len,
+                       hasher=self.manifest_hasher)
+
+  def _ReadMetadataSignature(self):
+    """Reads and returns the metadata signatures.
+
+    Returns:
+      A string containing the metadata signatures protobuf in binary form or
+      an empty string if no metadata signature found in the payload.
+
+    Raises:
+      PayloadError if a read error occurred.
+    """
+    if not self.header:
+      raise PayloadError('payload header not present')
+
+    return common.Read(
+        self.payload_file, self.header.metadata_signature_len,
+        offset=self.header.size + self.header.manifest_len)
+
+  def ReadDataBlob(self, offset, length):
+    """Reads and returns a single data blob from the update payload.
+
+    Args:
+      offset: offset to the beginning of the blob from the end of the manifest
+      length: the blob's length
+
+    Returns:
+      A string containing the raw blob data.
+
+    Raises:
+      PayloadError if a read error occurred.
+    """
+    return common.Read(self.payload_file, length,
+                       offset=self.data_offset + offset)
+
+  def Init(self):
+    """Initializes the payload object.
+
+    This is a prerequisite for any other public API call.
+
+    Raises:
+      PayloadError if object already initialized or fails to initialize
+      correctly.
+    """
+    if self.is_init:
+      raise PayloadError('payload object already initialized')
+
+    # Initialize hash context.
+    # pylint: disable=E1101
+    self.manifest_hasher = hashlib.sha256()
+
+    # Read the file header.
+    self.header = self._ReadHeader()
+
+    # Read the manifest.
+    manifest_raw = self._ReadManifest()
+    self.manifest = update_metadata_pb2.DeltaArchiveManifest()
+    self.manifest.ParseFromString(manifest_raw)
+
+    # Read the metadata signature (if any).
+    metadata_signature_raw = self._ReadMetadataSignature()
+    if metadata_signature_raw:
+      self.metadata_signature = update_metadata_pb2.Signatures()
+      self.metadata_signature.ParseFromString(metadata_signature_raw)
+
+    self.metadata_size = self.header.size + self.header.manifest_len
+    self.data_offset = self.metadata_size + self.header.metadata_signature_len
+
+    self.is_init = True
+
+  def Describe(self):
+    """Emits the payload embedded description data to standard output."""
+    def _DescribeImageInfo(description, image_info):
+      def _DisplayIndentedValue(name, value):
+        print('  {:<14} {}'.format(name+':', value))
+
+      print('%s:' % description)
+      _DisplayIndentedValue('Channel', image_info.channel)
+      _DisplayIndentedValue('Board', image_info.board)
+      _DisplayIndentedValue('Version', image_info.version)
+      _DisplayIndentedValue('Key', image_info.key)
+
+      if image_info.build_channel != image_info.channel:
+        _DisplayIndentedValue('Build channel', image_info.build_channel)
+
+      if image_info.build_version != image_info.version:
+        _DisplayIndentedValue('Build version', image_info.build_version)
+
+    if self.manifest.HasField('old_image_info'):
+      # pylint: disable=E1101
+      _DescribeImageInfo('Old Image', self.manifest.old_image_info)
+
+    if self.manifest.HasField('new_image_info'):
+      # pylint: disable=E1101
+      _DescribeImageInfo('New Image', self.manifest.new_image_info)
+
+  def _AssertInit(self):
+    """Raises an exception if the object was not initialized."""
+    if not self.is_init:
+      raise PayloadError('payload object not initialized')
+
+  def ResetFile(self):
+    """Resets the offset of the payload file to right past the manifest."""
+    self.payload_file.seek(self.data_offset)
+
+  def IsDelta(self):
+    """Returns True iff the payload appears to be a delta."""
+    self._AssertInit()
+    return (self.manifest.HasField('old_kernel_info') or
+            self.manifest.HasField('old_rootfs_info') or
+            any(partition.HasField('old_partition_info')
+                for partition in self.manifest.partitions))
+
+  def IsFull(self):
+    """Returns True iff the payload appears to be a full."""
+    return not self.IsDelta()
+
+  def Check(self, pubkey_file_name=None, metadata_sig_file=None,
+            report_out_file=None, assert_type=None, block_size=0,
+            rootfs_part_size=0, kernel_part_size=0, allow_unhashed=False,
+            disabled_tests=()):
+    """Checks the payload integrity.
+
+    Args:
+      pubkey_file_name: public key used for signature verification
+      metadata_sig_file: metadata signature, if verification is desired
+      report_out_file: file object to dump the report to
+      assert_type: assert that payload is either 'full' or 'delta'
+      block_size: expected filesystem / payload block size
+      rootfs_part_size: the size of (physical) rootfs partitions in bytes
+      kernel_part_size: the size of (physical) kernel partitions in bytes
+      allow_unhashed: allow unhashed operation blobs
+      disabled_tests: list of tests to disable
+
+    Raises:
+      PayloadError if payload verification failed.
+    """
+    self._AssertInit()
+
+    # Create a short-lived payload checker object and run it.
+    helper = checker.PayloadChecker(
+        self, assert_type=assert_type, block_size=block_size,
+        allow_unhashed=allow_unhashed, disabled_tests=disabled_tests)
+    helper.Run(pubkey_file_name=pubkey_file_name,
+               metadata_sig_file=metadata_sig_file,
+               rootfs_part_size=rootfs_part_size,
+               kernel_part_size=kernel_part_size,
+               report_out_file=report_out_file)
+
+  def Apply(self, new_kernel_part, new_rootfs_part, old_kernel_part=None,
+            old_rootfs_part=None, bsdiff_in_place=True, bspatch_path=None,
+            truncate_to_expected_size=True):
+    """Applies the update payload.
+
+    Args:
+      new_kernel_part: name of dest kernel partition file
+      new_rootfs_part: name of dest rootfs partition file
+      old_kernel_part: name of source kernel partition file (optional)
+      old_rootfs_part: name of source rootfs partition file (optional)
+      bsdiff_in_place: whether to perform BSDIFF operations in-place (optional)
+      bspatch_path: path to the bspatch binary (optional)
+      truncate_to_expected_size: whether to truncate the resulting partitions
+                                 to their expected sizes, as specified in the
+                                 payload (optional)
+
+    Raises:
+      PayloadError if payload application failed.
+    """
+    self._AssertInit()
+
+    # Create a short-lived payload applier object and run it.
+    helper = applier.PayloadApplier(
+        self, bsdiff_in_place=bsdiff_in_place, bspatch_path=bspatch_path,
+        truncate_to_expected_size=truncate_to_expected_size)
+    helper.Run(new_kernel_part, new_rootfs_part,
+               old_kernel_part=old_kernel_part,
+               old_rootfs_part=old_rootfs_part)
+
+  def TraceBlock(self, block, skip, trace_out_file, is_kernel):
+    """Traces the origin(s) of a given dest partition block.
+
+    The tracing tries to find origins transitively, when possible (it currently
+    only works for move operations, where the mapping of src/dst is
+    one-to-one). It will dump a list of operations and source blocks
+    responsible for the data in the given dest block.
+
+    Args:
+      block: the block number whose origin to trace
+      skip: the number of first origin mappings to skip
+      trace_out_file: file object to dump the trace to
+      is_kernel: trace through kernel (True) or rootfs (False) operations
+    """
+    self._AssertInit()
+
+    # Create a short-lived payload block tracer object and run it.
+    helper = block_tracer.PayloadBlockTracer(self)
+    helper.Run(block, skip, trace_out_file, is_kernel)
diff --git a/scripts/update_payload/test_utils.py b/scripts/update_payload/test_utils.py
new file mode 100644
index 0000000..61a91f5
--- /dev/null
+++ b/scripts/update_payload/test_utils.py
@@ -0,0 +1,364 @@
+# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Utilities for unit testing."""
+
+from __future__ import print_function
+
+import cStringIO
+import hashlib
+import os
+import struct
+import subprocess
+
+import common
+import payload
+import update_metadata_pb2
+
+
+class TestError(Exception):
+  """An error during testing of update payload code."""
+
+
+# Private/public RSA keys used for testing.
+_PRIVKEY_FILE_NAME = os.path.join(os.path.dirname(__file__),
+                                  'payload-test-key.pem')
+_PUBKEY_FILE_NAME = os.path.join(os.path.dirname(__file__),
+                                 'payload-test-key.pub')
+
+
+def KiB(count):
+  return count << 10
+
+
+def MiB(count):
+  return count << 20
+
+
+def GiB(count):
+  return count << 30
+
+
+def _WriteInt(file_obj, size, is_unsigned, val):
+  """Writes a binary-encoded integer to a file.
+
+  It will do the correct conversion based on the reported size and whether or
+  not a signed number is expected. Assumes a network (big-endian) byte
+  ordering.
+
+  Args:
+    file_obj: a file object
+    size: the integer size in bytes (2, 4 or 8)
+    is_unsigned: whether it is signed or not
+    val: integer value to encode
+
+  Raises:
+    PayloadError if a write error occurred.
+  """
+  try:
+    file_obj.write(struct.pack(common.IntPackingFmtStr(size, is_unsigned), val))
+  except IOError, e:
+    raise payload.PayloadError('error writing to file (%s): %s' %
+                               (file_obj.name, e))
+
+
+def _SetMsgField(msg, field_name, val):
+  """Sets or clears a field in a protobuf message."""
+  if val is None:
+    msg.ClearField(field_name)
+  else:
+    setattr(msg, field_name, val)
+
+
+def SignSha256(data, privkey_file_name):
+  """Signs the data's SHA256 hash with an RSA private key.
+
+  Args:
+    data: the data whose SHA256 hash we want to sign
+    privkey_file_name: private key used for signing data
+
+  Returns:
+    The signature string, prepended with an ASN1 header.
+
+  Raises:
+    TestError if something goes wrong.
+  """
+  # pylint: disable=E1101
+  data_sha256_hash = common.SIG_ASN1_HEADER + hashlib.sha256(data).digest()
+  sign_cmd = ['openssl', 'rsautl', '-sign', '-inkey', privkey_file_name]
+  try:
+    sign_process = subprocess.Popen(sign_cmd, stdin=subprocess.PIPE,
+                                    stdout=subprocess.PIPE)
+    sig, _ = sign_process.communicate(input=data_sha256_hash)
+  except Exception as e:
+    raise TestError('signing subprocess failed: %s' % e)
+
+  return sig
+
+
+class SignaturesGenerator(object):
+  """Generates a payload signatures data block."""
+
+  def __init__(self):
+    self.sigs = update_metadata_pb2.Signatures()
+
+  def AddSig(self, version, data):
+    """Adds a signature to the signature sequence.
+
+    Args:
+      version: signature version (None means do not assign)
+      data: signature binary data (None means do not assign)
+    """
+    # Pylint fails to identify a member of the Signatures message.
+    # pylint: disable=E1101
+    sig = self.sigs.signatures.add()
+    if version is not None:
+      sig.version = version
+    if data is not None:
+      sig.data = data
+
+  def ToBinary(self):
+    """Returns the binary representation of the signature block."""
+    return self.sigs.SerializeToString()
+
+
+class PayloadGenerator(object):
+  """Generates an update payload allowing low-level control.
+
+  Attributes:
+    manifest: the protobuf containing the payload manifest
+    version: the payload version identifier
+    block_size: the block size pertaining to update operations
+
+  """
+
+  def __init__(self, version=1):
+    self.manifest = update_metadata_pb2.DeltaArchiveManifest()
+    self.version = version
+    self.block_size = 0
+
+  @staticmethod
+  def _WriteExtent(ex, val):
+    """Returns an Extent message."""
+    start_block, num_blocks = val
+    _SetMsgField(ex, 'start_block', start_block)
+    _SetMsgField(ex, 'num_blocks', num_blocks)
+
+  @staticmethod
+  def _AddValuesToRepeatedField(repeated_field, values, write_func):
+    """Adds values to a repeated message field."""
+    if values:
+      for val in values:
+        new_item = repeated_field.add()
+        write_func(new_item, val)
+
+  @staticmethod
+  def _AddExtents(extents_field, values):
+    """Adds extents to an extents field."""
+    PayloadGenerator._AddValuesToRepeatedField(
+        extents_field, values, PayloadGenerator._WriteExtent)
+
+  def SetBlockSize(self, block_size):
+    """Sets the payload's block size."""
+    self.block_size = block_size
+    _SetMsgField(self.manifest, 'block_size', block_size)
+
+  def SetPartInfo(self, is_kernel, is_new, part_size, part_hash):
+    """Set the partition info entry.
+
+    Args:
+      is_kernel: whether this is kernel partition info
+      is_new: whether to set old (False) or new (True) info
+      part_size: the partition size (in fact, filesystem size)
+      part_hash: the partition hash
+    """
+    if is_kernel:
+      # pylint: disable=E1101
+      part_info = (self.manifest.new_kernel_info if is_new
+                   else self.manifest.old_kernel_info)
+    else:
+      # pylint: disable=E1101
+      part_info = (self.manifest.new_rootfs_info if is_new
+                   else self.manifest.old_rootfs_info)
+    _SetMsgField(part_info, 'size', part_size)
+    _SetMsgField(part_info, 'hash', part_hash)
+
+  def AddOperation(self, is_kernel, op_type, data_offset=None,
+                   data_length=None, src_extents=None, src_length=None,
+                   dst_extents=None, dst_length=None, data_sha256_hash=None):
+    """Adds an InstallOperation entry."""
+    # pylint: disable=E1101
+    operations = (self.manifest.kernel_install_operations if is_kernel
+                  else self.manifest.install_operations)
+
+    op = operations.add()
+    op.type = op_type
+
+    _SetMsgField(op, 'data_offset', data_offset)
+    _SetMsgField(op, 'data_length', data_length)
+
+    self._AddExtents(op.src_extents, src_extents)
+    _SetMsgField(op, 'src_length', src_length)
+
+    self._AddExtents(op.dst_extents, dst_extents)
+    _SetMsgField(op, 'dst_length', dst_length)
+
+    _SetMsgField(op, 'data_sha256_hash', data_sha256_hash)
+
+  def SetSignatures(self, sigs_offset, sigs_size):
+    """Set the payload's signature block descriptors."""
+    _SetMsgField(self.manifest, 'signatures_offset', sigs_offset)
+    _SetMsgField(self.manifest, 'signatures_size', sigs_size)
+
+  def SetMinorVersion(self, minor_version):
+    """Set the payload's minor version field."""
+    _SetMsgField(self.manifest, 'minor_version', minor_version)
+
+  def _WriteHeaderToFile(self, file_obj, manifest_len):
+    """Writes a payload heaer to a file."""
+    # We need to access protected members in Payload for writing the header.
+    # pylint: disable=W0212
+    file_obj.write(payload.Payload._PayloadHeader._MAGIC)
+    _WriteInt(file_obj, payload.Payload._PayloadHeader._VERSION_SIZE, True,
+              self.version)
+    _WriteInt(file_obj, payload.Payload._PayloadHeader._MANIFEST_LEN_SIZE, True,
+              manifest_len)
+
+  def WriteToFile(self, file_obj, manifest_len=-1, data_blobs=None,
+                  sigs_data=None, padding=None):
+    """Writes the payload content to a file.
+
+    Args:
+      file_obj: a file object open for writing
+      manifest_len: manifest len to dump (otherwise computed automatically)
+      data_blobs: a list of data blobs to be concatenated to the payload
+      sigs_data: a binary Signatures message to be concatenated to the payload
+      padding: stuff to dump past the normal data blobs provided (optional)
+    """
+    manifest = self.manifest.SerializeToString()
+    if manifest_len < 0:
+      manifest_len = len(manifest)
+    self._WriteHeaderToFile(file_obj, manifest_len)
+    file_obj.write(manifest)
+    if data_blobs:
+      for data_blob in data_blobs:
+        file_obj.write(data_blob)
+    if sigs_data:
+      file_obj.write(sigs_data)
+    if padding:
+      file_obj.write(padding)
+
+
+class EnhancedPayloadGenerator(PayloadGenerator):
+  """Payload generator with automatic handling of data blobs.
+
+  Attributes:
+    data_blobs: a list of blobs, in the order they were added
+    curr_offset: the currently consumed offset of blobs added to the payload
+  """
+
+  def __init__(self):
+    super(EnhancedPayloadGenerator, self).__init__()
+    self.data_blobs = []
+    self.curr_offset = 0
+
+  def AddData(self, data_blob):
+    """Adds a (possibly orphan) data blob."""
+    data_length = len(data_blob)
+    data_offset = self.curr_offset
+    self.curr_offset += data_length
+    self.data_blobs.append(data_blob)
+    return data_length, data_offset
+
+  def AddOperationWithData(self, is_kernel, op_type, src_extents=None,
+                           src_length=None, dst_extents=None, dst_length=None,
+                           data_blob=None, do_hash_data_blob=True):
+    """Adds an install operation and associated data blob.
+
+    This takes care of obtaining a hash of the data blob (if so instructed)
+    and appending it to the internally maintained list of blobs, including the
+    necessary offset/length accounting.
+
+    Args:
+      is_kernel: whether this is a kernel (True) or rootfs (False) operation
+      op_type: one of REPLACE, REPLACE_BZ, MOVE or BSDIFF
+      src_extents: list of (start, length) pairs indicating src block ranges
+      src_length: size of the src data in bytes (needed for BSDIFF)
+      dst_extents: list of (start, length) pairs indicating dst block ranges
+      dst_length: size of the dst data in bytes (needed for BSDIFF)
+      data_blob: a data blob associated with this operation
+      do_hash_data_blob: whether or not to compute and add a data blob hash
+    """
+    data_offset = data_length = data_sha256_hash = None
+    if data_blob is not None:
+      if do_hash_data_blob:
+        # pylint: disable=E1101
+        data_sha256_hash = hashlib.sha256(data_blob).digest()
+      data_length, data_offset = self.AddData(data_blob)
+
+    self.AddOperation(is_kernel, op_type, data_offset=data_offset,
+                      data_length=data_length, src_extents=src_extents,
+                      src_length=src_length, dst_extents=dst_extents,
+                      dst_length=dst_length, data_sha256_hash=data_sha256_hash)
+
+  def WriteToFileWithData(self, file_obj, sigs_data=None,
+                          privkey_file_name=None,
+                          do_add_pseudo_operation=False,
+                          is_pseudo_in_kernel=False, padding=None):
+    """Writes the payload content to a file, optionally signing the content.
+
+    Args:
+      file_obj: a file object open for writing
+      sigs_data: signatures blob to be appended to the payload (optional;
+                 payload signature fields assumed to be preset by the caller)
+      privkey_file_name: key used for signing the payload (optional; used only
+                         if explicit signatures blob not provided)
+      do_add_pseudo_operation: whether a pseudo-operation should be added to
+                               account for the signature blob
+      is_pseudo_in_kernel: whether the pseudo-operation should be added to
+                           kernel (True) or rootfs (False) operations
+      padding: stuff to dump past the normal data blobs provided (optional)
+
+    Raises:
+      TestError: if arguments are inconsistent or something goes wrong.
+    """
+    sigs_len = len(sigs_data) if sigs_data else 0
+
+    # Do we need to generate a genuine signatures blob?
+    do_generate_sigs_data = sigs_data is None and privkey_file_name
+
+    if do_generate_sigs_data:
+      # First, sign some arbitrary data to obtain the size of a signature blob.
+      fake_sig = SignSha256('fake-payload-data', privkey_file_name)
+      fake_sigs_gen = SignaturesGenerator()
+      fake_sigs_gen.AddSig(1, fake_sig)
+      sigs_len = len(fake_sigs_gen.ToBinary())
+
+      # Update the payload with proper signature attributes.
+      self.SetSignatures(self.curr_offset, sigs_len)
+
+    # Add a pseudo-operation to account for the signature blob, if requested.
+    if do_add_pseudo_operation:
+      if not self.block_size:
+        raise TestError('cannot add pseudo-operation without knowing the '
+                        'payload block size')
+      self.AddOperation(
+          is_pseudo_in_kernel, common.OpType.REPLACE,
+          data_offset=self.curr_offset, data_length=sigs_len,
+          dst_extents=[(common.PSEUDO_EXTENT_MARKER,
+                        (sigs_len + self.block_size - 1) / self.block_size)])
+
+    if do_generate_sigs_data:
+      # Once all payload fields are updated, dump and sign it.
+      temp_payload_file = cStringIO.StringIO()
+      self.WriteToFile(temp_payload_file, data_blobs=self.data_blobs)
+      sig = SignSha256(temp_payload_file.getvalue(), privkey_file_name)
+      sigs_gen = SignaturesGenerator()
+      sigs_gen.AddSig(1, sig)
+      sigs_data = sigs_gen.ToBinary()
+      assert len(sigs_data) == sigs_len, 'signature blob lengths mismatch'
+
+    # Dump the whole thing, complete with data and signature blob, to a file.
+    self.WriteToFile(file_obj, data_blobs=self.data_blobs, sigs_data=sigs_data,
+                     padding=padding)
diff --git a/scripts/update_payload/update-payload-key.pub.pem b/scripts/update_payload/update-payload-key.pub.pem
new file mode 100644
index 0000000..7ac369f
--- /dev/null
+++ b/scripts/update_payload/update-payload-key.pub.pem
@@ -0,0 +1,9 @@
+-----BEGIN PUBLIC KEY-----
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1Bg9BnjWhX3jJyECeXqF
+O28nkYTF1NHWLlFHgzAGg+ysva22BL3S5LlsNejnYVg/xzx3izvAQyOF3I1TJVOy
+2fH1DoZOWyKuckMyUrFQbO6OV1VIvPUPKckHadWcXSsHj2lBdDPH9xRDEBsXeztf
+nAGBD8GlAyTU7iH+Bf+xzyK9k4BmITf4Nx4xWhRZ6gm2Fc2SEP3x5N5fohkLv5ZP
+kFr0fj5wUK+0XF95rkGFBLIq2XACS3dmxMFToFl1HMM1HonUg9TAH+3dVH93zue1
+y81mkTuGnNX+zYya5ov2kD8zW1V10iTOSJfOlho5T8FpKbG37o3yYcUiyMHKO1Iv
+PQIDAQAB
+-----END PUBLIC KEY-----
diff --git a/scripts/update_payload/update_metadata_pb2.py b/scripts/update_payload/update_metadata_pb2.py
new file mode 100644
index 0000000..46c475e
--- /dev/null
+++ b/scripts/update_payload/update_metadata_pb2.py
@@ -0,0 +1,620 @@
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: update_metadata.proto
+
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import message as _message
+from google.protobuf import reflection as _reflection
+from google.protobuf import descriptor_pb2
+# @@protoc_insertion_point(imports)
+
+
+
+
+DESCRIPTOR = _descriptor.FileDescriptor(
+  name='update_metadata.proto',
+  package='chromeos_update_engine',
+  serialized_pb='\n\x15update_metadata.proto\x12\x16\x63hromeos_update_engine\"1\n\x06\x45xtent\x12\x13\n\x0bstart_block\x18\x01 \x01(\x04\x12\x12\n\nnum_blocks\x18\x02 \x01(\x04\"z\n\nSignatures\x12@\n\nsignatures\x18\x01 \x03(\x0b\x32,.chromeos_update_engine.Signatures.Signature\x1a*\n\tSignature\x12\x0f\n\x07version\x18\x01 \x01(\r\x12\x0c\n\x04\x64\x61ta\x18\x02 \x01(\x0c\"+\n\rPartitionInfo\x12\x0c\n\x04size\x18\x01 \x01(\x04\x12\x0c\n\x04hash\x18\x02 \x01(\x0c\"w\n\tImageInfo\x12\r\n\x05\x62oard\x18\x01 \x01(\t\x12\x0b\n\x03key\x18\x02 \x01(\t\x12\x0f\n\x07\x63hannel\x18\x03 \x01(\t\x12\x0f\n\x07version\x18\x04 \x01(\t\x12\x15\n\rbuild_channel\x18\x05 \x01(\t\x12\x15\n\rbuild_version\x18\x06 \x01(\t\"\xd2\x03\n\x10InstallOperation\x12;\n\x04type\x18\x01 \x02(\x0e\x32-.chromeos_update_engine.InstallOperation.Type\x12\x13\n\x0b\x64\x61ta_offset\x18\x02 \x01(\r\x12\x13\n\x0b\x64\x61ta_length\x18\x03 \x01(\r\x12\x33\n\x0bsrc_extents\x18\x04 \x03(\x0b\x32\x1e.chromeos_update_engine.Extent\x12\x12\n\nsrc_length\x18\x05 \x01(\x04\x12\x33\n\x0b\x64st_extents\x18\x06 \x03(\x0b\x32\x1e.chromeos_update_engine.Extent\x12\x12\n\ndst_length\x18\x07 \x01(\x04\x12\x18\n\x10\x64\x61ta_sha256_hash\x18\x08 \x01(\x0c\x12\x17\n\x0fsrc_sha256_hash\x18\t \x01(\x0c\"\x91\x01\n\x04Type\x12\x0b\n\x07REPLACE\x10\x00\x12\x0e\n\nREPLACE_BZ\x10\x01\x12\x08\n\x04MOVE\x10\x02\x12\n\n\x06\x42SDIFF\x10\x03\x12\x0f\n\x0bSOURCE_COPY\x10\x04\x12\x11\n\rSOURCE_BSDIFF\x10\x05\x12\x08\n\x04ZERO\x10\x06\x12\x0b\n\x07\x44ISCARD\x10\x07\x12\x0e\n\nREPLACE_XZ\x10\x08\x12\x0b\n\x07IMGDIFF\x10\t\"\x88\x03\n\x0fPartitionUpdate\x12\x16\n\x0epartition_name\x18\x01 \x02(\t\x12\x17\n\x0frun_postinstall\x18\x02 \x01(\x08\x12\x18\n\x10postinstall_path\x18\x03 \x01(\t\x12\x17\n\x0f\x66ilesystem_type\x18\x04 \x01(\t\x12M\n\x17new_partition_signature\x18\x05 \x03(\x0b\x32,.chromeos_update_engine.Signatures.Signature\x12\x41\n\x12old_partition_info\x18\x06 \x01(\x0b\x32%.chromeos_update_engine.PartitionInfo\x12\x41\n\x12new_partition_info\x18\x07 \x01(\x0b\x32%.chromeos_update_engine.PartitionInfo\x12<\n\noperations\x18\x08 \x03(\x0b\x32(.chromeos_update_engine.InstallOperation\"\xc4\x05\n\x14\x44\x65ltaArchiveManifest\x12\x44\n\x12install_operations\x18\x01 \x03(\x0b\x32(.chromeos_update_engine.InstallOperation\x12K\n\x19kernel_install_operations\x18\x02 \x03(\x0b\x32(.chromeos_update_engine.InstallOperation\x12\x18\n\nblock_size\x18\x03 \x01(\r:\x04\x34\x30\x39\x36\x12\x19\n\x11signatures_offset\x18\x04 \x01(\x04\x12\x17\n\x0fsignatures_size\x18\x05 \x01(\x04\x12>\n\x0fold_kernel_info\x18\x06 \x01(\x0b\x32%.chromeos_update_engine.PartitionInfo\x12>\n\x0fnew_kernel_info\x18\x07 \x01(\x0b\x32%.chromeos_update_engine.PartitionInfo\x12>\n\x0fold_rootfs_info\x18\x08 \x01(\x0b\x32%.chromeos_update_engine.PartitionInfo\x12>\n\x0fnew_rootfs_info\x18\t \x01(\x0b\x32%.chromeos_update_engine.PartitionInfo\x12\x39\n\x0eold_image_info\x18\n \x01(\x0b\x32!.chromeos_update_engine.ImageInfo\x12\x39\n\x0enew_image_info\x18\x0b \x01(\x0b\x32!.chromeos_update_engine.ImageInfo\x12\x18\n\rminor_version\x18\x0c \x01(\r:\x01\x30\x12;\n\npartitions\x18\r \x03(\x0b\x32\'.chromeos_update_engine.PartitionUpdateB\x02H\x03')
+
+
+
+_INSTALLOPERATION_TYPE = _descriptor.EnumDescriptor(
+  name='Type',
+  full_name='chromeos_update_engine.InstallOperation.Type',
+  filename=None,
+  file=DESCRIPTOR,
+  values=[
+    _descriptor.EnumValueDescriptor(
+      name='REPLACE', index=0, number=0,
+      options=None,
+      type=None),
+    _descriptor.EnumValueDescriptor(
+      name='REPLACE_BZ', index=1, number=1,
+      options=None,
+      type=None),
+    _descriptor.EnumValueDescriptor(
+      name='MOVE', index=2, number=2,
+      options=None,
+      type=None),
+    _descriptor.EnumValueDescriptor(
+      name='BSDIFF', index=3, number=3,
+      options=None,
+      type=None),
+    _descriptor.EnumValueDescriptor(
+      name='SOURCE_COPY', index=4, number=4,
+      options=None,
+      type=None),
+    _descriptor.EnumValueDescriptor(
+      name='SOURCE_BSDIFF', index=5, number=5,
+      options=None,
+      type=None),
+    _descriptor.EnumValueDescriptor(
+      name='ZERO', index=6, number=6,
+      options=None,
+      type=None),
+    _descriptor.EnumValueDescriptor(
+      name='DISCARD', index=7, number=7,
+      options=None,
+      type=None),
+    _descriptor.EnumValueDescriptor(
+      name='REPLACE_XZ', index=8, number=8,
+      options=None,
+      type=None),
+    _descriptor.EnumValueDescriptor(
+      name='IMGDIFF', index=9, number=9,
+      options=None,
+      type=None),
+  ],
+  containing_type=None,
+  options=None,
+  serialized_start=712,
+  serialized_end=857,
+)
+
+
+_EXTENT = _descriptor.Descriptor(
+  name='Extent',
+  full_name='chromeos_update_engine.Extent',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='start_block', full_name='chromeos_update_engine.Extent.start_block', index=0,
+      number=1, type=4, cpp_type=4, label=1,
+      has_default_value=False, default_value=0,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='num_blocks', full_name='chromeos_update_engine.Extent.num_blocks', index=1,
+      number=2, type=4, cpp_type=4, label=1,
+      has_default_value=False, default_value=0,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  options=None,
+  is_extendable=False,
+  extension_ranges=[],
+  serialized_start=49,
+  serialized_end=98,
+)
+
+
+_SIGNATURES_SIGNATURE = _descriptor.Descriptor(
+  name='Signature',
+  full_name='chromeos_update_engine.Signatures.Signature',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='version', full_name='chromeos_update_engine.Signatures.Signature.version', index=0,
+      number=1, type=13, cpp_type=3, label=1,
+      has_default_value=False, default_value=0,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='data', full_name='chromeos_update_engine.Signatures.Signature.data', index=1,
+      number=2, type=12, cpp_type=9, label=1,
+      has_default_value=False, default_value="",
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  options=None,
+  is_extendable=False,
+  extension_ranges=[],
+  serialized_start=180,
+  serialized_end=222,
+)
+
+_SIGNATURES = _descriptor.Descriptor(
+  name='Signatures',
+  full_name='chromeos_update_engine.Signatures',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='signatures', full_name='chromeos_update_engine.Signatures.signatures', index=0,
+      number=1, type=11, cpp_type=10, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+  ],
+  extensions=[
+  ],
+  nested_types=[_SIGNATURES_SIGNATURE, ],
+  enum_types=[
+  ],
+  options=None,
+  is_extendable=False,
+  extension_ranges=[],
+  serialized_start=100,
+  serialized_end=222,
+)
+
+
+_PARTITIONINFO = _descriptor.Descriptor(
+  name='PartitionInfo',
+  full_name='chromeos_update_engine.PartitionInfo',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='size', full_name='chromeos_update_engine.PartitionInfo.size', index=0,
+      number=1, type=4, cpp_type=4, label=1,
+      has_default_value=False, default_value=0,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='hash', full_name='chromeos_update_engine.PartitionInfo.hash', index=1,
+      number=2, type=12, cpp_type=9, label=1,
+      has_default_value=False, default_value="",
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  options=None,
+  is_extendable=False,
+  extension_ranges=[],
+  serialized_start=224,
+  serialized_end=267,
+)
+
+
+_IMAGEINFO = _descriptor.Descriptor(
+  name='ImageInfo',
+  full_name='chromeos_update_engine.ImageInfo',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='board', full_name='chromeos_update_engine.ImageInfo.board', index=0,
+      number=1, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=unicode("", "utf-8"),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='key', full_name='chromeos_update_engine.ImageInfo.key', index=1,
+      number=2, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=unicode("", "utf-8"),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='channel', full_name='chromeos_update_engine.ImageInfo.channel', index=2,
+      number=3, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=unicode("", "utf-8"),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='version', full_name='chromeos_update_engine.ImageInfo.version', index=3,
+      number=4, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=unicode("", "utf-8"),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='build_channel', full_name='chromeos_update_engine.ImageInfo.build_channel', index=4,
+      number=5, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=unicode("", "utf-8"),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='build_version', full_name='chromeos_update_engine.ImageInfo.build_version', index=5,
+      number=6, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=unicode("", "utf-8"),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  options=None,
+  is_extendable=False,
+  extension_ranges=[],
+  serialized_start=269,
+  serialized_end=388,
+)
+
+
+_INSTALLOPERATION = _descriptor.Descriptor(
+  name='InstallOperation',
+  full_name='chromeos_update_engine.InstallOperation',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='type', full_name='chromeos_update_engine.InstallOperation.type', index=0,
+      number=1, type=14, cpp_type=8, label=2,
+      has_default_value=False, default_value=0,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='data_offset', full_name='chromeos_update_engine.InstallOperation.data_offset', index=1,
+      number=2, type=13, cpp_type=3, label=1,
+      has_default_value=False, default_value=0,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='data_length', full_name='chromeos_update_engine.InstallOperation.data_length', index=2,
+      number=3, type=13, cpp_type=3, label=1,
+      has_default_value=False, default_value=0,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='src_extents', full_name='chromeos_update_engine.InstallOperation.src_extents', index=3,
+      number=4, type=11, cpp_type=10, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='src_length', full_name='chromeos_update_engine.InstallOperation.src_length', index=4,
+      number=5, type=4, cpp_type=4, label=1,
+      has_default_value=False, default_value=0,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='dst_extents', full_name='chromeos_update_engine.InstallOperation.dst_extents', index=5,
+      number=6, type=11, cpp_type=10, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='dst_length', full_name='chromeos_update_engine.InstallOperation.dst_length', index=6,
+      number=7, type=4, cpp_type=4, label=1,
+      has_default_value=False, default_value=0,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='data_sha256_hash', full_name='chromeos_update_engine.InstallOperation.data_sha256_hash', index=7,
+      number=8, type=12, cpp_type=9, label=1,
+      has_default_value=False, default_value="",
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='src_sha256_hash', full_name='chromeos_update_engine.InstallOperation.src_sha256_hash', index=8,
+      number=9, type=12, cpp_type=9, label=1,
+      has_default_value=False, default_value="",
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+    _INSTALLOPERATION_TYPE,
+  ],
+  options=None,
+  is_extendable=False,
+  extension_ranges=[],
+  serialized_start=391,
+  serialized_end=857,
+)
+
+
+_PARTITIONUPDATE = _descriptor.Descriptor(
+  name='PartitionUpdate',
+  full_name='chromeos_update_engine.PartitionUpdate',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='partition_name', full_name='chromeos_update_engine.PartitionUpdate.partition_name', index=0,
+      number=1, type=9, cpp_type=9, label=2,
+      has_default_value=False, default_value=unicode("", "utf-8"),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='run_postinstall', full_name='chromeos_update_engine.PartitionUpdate.run_postinstall', index=1,
+      number=2, type=8, cpp_type=7, label=1,
+      has_default_value=False, default_value=False,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='postinstall_path', full_name='chromeos_update_engine.PartitionUpdate.postinstall_path', index=2,
+      number=3, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=unicode("", "utf-8"),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='filesystem_type', full_name='chromeos_update_engine.PartitionUpdate.filesystem_type', index=3,
+      number=4, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=unicode("", "utf-8"),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='new_partition_signature', full_name='chromeos_update_engine.PartitionUpdate.new_partition_signature', index=4,
+      number=5, type=11, cpp_type=10, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='old_partition_info', full_name='chromeos_update_engine.PartitionUpdate.old_partition_info', index=5,
+      number=6, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='new_partition_info', full_name='chromeos_update_engine.PartitionUpdate.new_partition_info', index=6,
+      number=7, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='operations', full_name='chromeos_update_engine.PartitionUpdate.operations', index=7,
+      number=8, type=11, cpp_type=10, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  options=None,
+  is_extendable=False,
+  extension_ranges=[],
+  serialized_start=860,
+  serialized_end=1252,
+)
+
+
+_DELTAARCHIVEMANIFEST = _descriptor.Descriptor(
+  name='DeltaArchiveManifest',
+  full_name='chromeos_update_engine.DeltaArchiveManifest',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='install_operations', full_name='chromeos_update_engine.DeltaArchiveManifest.install_operations', index=0,
+      number=1, type=11, cpp_type=10, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='kernel_install_operations', full_name='chromeos_update_engine.DeltaArchiveManifest.kernel_install_operations', index=1,
+      number=2, type=11, cpp_type=10, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='block_size', full_name='chromeos_update_engine.DeltaArchiveManifest.block_size', index=2,
+      number=3, type=13, cpp_type=3, label=1,
+      has_default_value=True, default_value=4096,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='signatures_offset', full_name='chromeos_update_engine.DeltaArchiveManifest.signatures_offset', index=3,
+      number=4, type=4, cpp_type=4, label=1,
+      has_default_value=False, default_value=0,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='signatures_size', full_name='chromeos_update_engine.DeltaArchiveManifest.signatures_size', index=4,
+      number=5, type=4, cpp_type=4, label=1,
+      has_default_value=False, default_value=0,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='old_kernel_info', full_name='chromeos_update_engine.DeltaArchiveManifest.old_kernel_info', index=5,
+      number=6, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='new_kernel_info', full_name='chromeos_update_engine.DeltaArchiveManifest.new_kernel_info', index=6,
+      number=7, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='old_rootfs_info', full_name='chromeos_update_engine.DeltaArchiveManifest.old_rootfs_info', index=7,
+      number=8, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='new_rootfs_info', full_name='chromeos_update_engine.DeltaArchiveManifest.new_rootfs_info', index=8,
+      number=9, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='old_image_info', full_name='chromeos_update_engine.DeltaArchiveManifest.old_image_info', index=9,
+      number=10, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='new_image_info', full_name='chromeos_update_engine.DeltaArchiveManifest.new_image_info', index=10,
+      number=11, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='minor_version', full_name='chromeos_update_engine.DeltaArchiveManifest.minor_version', index=11,
+      number=12, type=13, cpp_type=3, label=1,
+      has_default_value=True, default_value=0,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='partitions', full_name='chromeos_update_engine.DeltaArchiveManifest.partitions', index=12,
+      number=13, type=11, cpp_type=10, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  options=None,
+  is_extendable=False,
+  extension_ranges=[],
+  serialized_start=1255,
+  serialized_end=1963,
+)
+
+_SIGNATURES_SIGNATURE.containing_type = _SIGNATURES;
+_SIGNATURES.fields_by_name['signatures'].message_type = _SIGNATURES_SIGNATURE
+_INSTALLOPERATION.fields_by_name['type'].enum_type = _INSTALLOPERATION_TYPE
+_INSTALLOPERATION.fields_by_name['src_extents'].message_type = _EXTENT
+_INSTALLOPERATION.fields_by_name['dst_extents'].message_type = _EXTENT
+_INSTALLOPERATION_TYPE.containing_type = _INSTALLOPERATION;
+_PARTITIONUPDATE.fields_by_name['new_partition_signature'].message_type = _SIGNATURES_SIGNATURE
+_PARTITIONUPDATE.fields_by_name['old_partition_info'].message_type = _PARTITIONINFO
+_PARTITIONUPDATE.fields_by_name['new_partition_info'].message_type = _PARTITIONINFO
+_PARTITIONUPDATE.fields_by_name['operations'].message_type = _INSTALLOPERATION
+_DELTAARCHIVEMANIFEST.fields_by_name['install_operations'].message_type = _INSTALLOPERATION
+_DELTAARCHIVEMANIFEST.fields_by_name['kernel_install_operations'].message_type = _INSTALLOPERATION
+_DELTAARCHIVEMANIFEST.fields_by_name['old_kernel_info'].message_type = _PARTITIONINFO
+_DELTAARCHIVEMANIFEST.fields_by_name['new_kernel_info'].message_type = _PARTITIONINFO
+_DELTAARCHIVEMANIFEST.fields_by_name['old_rootfs_info'].message_type = _PARTITIONINFO
+_DELTAARCHIVEMANIFEST.fields_by_name['new_rootfs_info'].message_type = _PARTITIONINFO
+_DELTAARCHIVEMANIFEST.fields_by_name['old_image_info'].message_type = _IMAGEINFO
+_DELTAARCHIVEMANIFEST.fields_by_name['new_image_info'].message_type = _IMAGEINFO
+_DELTAARCHIVEMANIFEST.fields_by_name['partitions'].message_type = _PARTITIONUPDATE
+DESCRIPTOR.message_types_by_name['Extent'] = _EXTENT
+DESCRIPTOR.message_types_by_name['Signatures'] = _SIGNATURES
+DESCRIPTOR.message_types_by_name['PartitionInfo'] = _PARTITIONINFO
+DESCRIPTOR.message_types_by_name['ImageInfo'] = _IMAGEINFO
+DESCRIPTOR.message_types_by_name['InstallOperation'] = _INSTALLOPERATION
+DESCRIPTOR.message_types_by_name['PartitionUpdate'] = _PARTITIONUPDATE
+DESCRIPTOR.message_types_by_name['DeltaArchiveManifest'] = _DELTAARCHIVEMANIFEST
+
+class Extent(_message.Message):
+  __metaclass__ = _reflection.GeneratedProtocolMessageType
+  DESCRIPTOR = _EXTENT
+
+  # @@protoc_insertion_point(class_scope:chromeos_update_engine.Extent)
+
+class Signatures(_message.Message):
+  __metaclass__ = _reflection.GeneratedProtocolMessageType
+
+  class Signature(_message.Message):
+    __metaclass__ = _reflection.GeneratedProtocolMessageType
+    DESCRIPTOR = _SIGNATURES_SIGNATURE
+
+    # @@protoc_insertion_point(class_scope:chromeos_update_engine.Signatures.Signature)
+  DESCRIPTOR = _SIGNATURES
+
+  # @@protoc_insertion_point(class_scope:chromeos_update_engine.Signatures)
+
+class PartitionInfo(_message.Message):
+  __metaclass__ = _reflection.GeneratedProtocolMessageType
+  DESCRIPTOR = _PARTITIONINFO
+
+  # @@protoc_insertion_point(class_scope:chromeos_update_engine.PartitionInfo)
+
+class ImageInfo(_message.Message):
+  __metaclass__ = _reflection.GeneratedProtocolMessageType
+  DESCRIPTOR = _IMAGEINFO
+
+  # @@protoc_insertion_point(class_scope:chromeos_update_engine.ImageInfo)
+
+class InstallOperation(_message.Message):
+  __metaclass__ = _reflection.GeneratedProtocolMessageType
+  DESCRIPTOR = _INSTALLOPERATION
+
+  # @@protoc_insertion_point(class_scope:chromeos_update_engine.InstallOperation)
+
+class PartitionUpdate(_message.Message):
+  __metaclass__ = _reflection.GeneratedProtocolMessageType
+  DESCRIPTOR = _PARTITIONUPDATE
+
+  # @@protoc_insertion_point(class_scope:chromeos_update_engine.PartitionUpdate)
+
+class DeltaArchiveManifest(_message.Message):
+  __metaclass__ = _reflection.GeneratedProtocolMessageType
+  DESCRIPTOR = _DELTAARCHIVEMANIFEST
+
+  # @@protoc_insertion_point(class_scope:chromeos_update_engine.DeltaArchiveManifest)
+
+
+DESCRIPTOR.has_options = True
+DESCRIPTOR._options = _descriptor._ParseOptions(descriptor_pb2.FileOptions(), 'H\003')
+# @@protoc_insertion_point(module_scope)
diff --git a/service_observer_interface.h b/service_observer_interface.h
index 75a739f..893df04 100644
--- a/service_observer_interface.h
+++ b/service_observer_interface.h
@@ -40,9 +40,6 @@
   // Called whenever an update attempt is completed.
   virtual void SendPayloadApplicationComplete(ErrorCode error_code) = 0;
 
-  // Called whenever the channel we are tracking changes.
-  virtual void SendChannelChangeUpdate(const std::string& tracking_channel) = 0;
-
  protected:
   ServiceObserverInterface() = default;
 };
diff --git a/shill_proxy.cc b/shill_proxy.cc
index 1c050b4..d398bba 100644
--- a/shill_proxy.cc
+++ b/shill_proxy.cc
@@ -16,6 +16,8 @@
 
 #include "update_engine/shill_proxy.h"
 
+#include "update_engine/dbus_connection.h"
+
 using org::chromium::flimflam::ManagerProxy;
 using org::chromium::flimflam::ManagerProxyInterface;
 using org::chromium::flimflam::ServiceProxy;
@@ -23,12 +25,9 @@
 
 namespace chromeos_update_engine {
 
-ShillProxy::ShillProxy(const scoped_refptr<dbus::Bus>& bus) : bus_(bus) {}
-
-bool ShillProxy::Init() {
-  manager_proxy_.reset(new ManagerProxy(bus_));
-  return true;
-}
+ShillProxy::ShillProxy()
+    : bus_(DBusConnection::Get()->GetDBus()),
+      manager_proxy_(new ManagerProxy(bus_)) {}
 
 ManagerProxyInterface* ShillProxy::GetManagerProxy() {
   return manager_proxy_.get();
diff --git a/shill_proxy.h b/shill_proxy.h
index 6d545f6..4b466c9 100644
--- a/shill_proxy.h
+++ b/shill_proxy.h
@@ -32,13 +32,9 @@
 // This class implements the connection to shill using real DBus calls.
 class ShillProxy : public ShillProxyInterface {
  public:
-  explicit ShillProxy(const scoped_refptr<dbus::Bus>& bus);
+  ShillProxy();
   ~ShillProxy() override = default;
 
-  // Initializes the ShillProxy instance creating the manager proxy from the
-  // |bus_|.
-  bool Init();
-
   // ShillProxyInterface overrides.
   org::chromium::flimflam::ManagerProxyInterface* GetManagerProxy() override;
   std::unique_ptr<org::chromium::flimflam::ServiceProxyInterface>
diff --git a/sideload_main.cc b/sideload_main.cc
new file mode 100644
index 0000000..574d062
--- /dev/null
+++ b/sideload_main.cc
@@ -0,0 +1,224 @@
+//
+// 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 <xz.h>
+
+#include <string>
+#include <vector>
+
+#include <base/command_line.h>
+#include <base/logging.h>
+#include <base/strings/string_split.h>
+#include <base/strings/stringprintf.h>
+#include <brillo/asynchronous_signal_handler.h>
+#include <brillo/flag_helper.h>
+#include <brillo/make_unique_ptr.h>
+#include <brillo/message_loops/base_message_loop.h>
+#include <brillo/streams/file_stream.h>
+#include <brillo/streams/stream.h>
+
+#include "update_engine/common/boot_control.h"
+#include "update_engine/common/error_code_utils.h"
+#include "update_engine/common/hardware.h"
+#include "update_engine/common/prefs.h"
+#include "update_engine/common/subprocess.h"
+#include "update_engine/common/terminator.h"
+#include "update_engine/common/utils.h"
+#include "update_engine/update_attempter_android.h"
+
+using std::string;
+using std::vector;
+using update_engine::UpdateStatus;
+
+namespace {
+// The root directory used for temporary files in update_engine_sideload.
+const char kSideloadRootTempDir[] = "/tmp/update_engine_sideload";
+}  // namespace
+
+namespace chromeos_update_engine {
+namespace {
+
+void SetupLogging() {
+  string log_file;
+  logging::LoggingSettings log_settings;
+  log_settings.lock_log = logging::DONT_LOCK_LOG_FILE;
+  log_settings.delete_old = logging::APPEND_TO_OLD_LOG_FILE;
+  log_settings.log_file = nullptr;
+  log_settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG;
+
+  logging::InitLogging(log_settings);
+}
+
+class SideloadDaemonState : public DaemonStateInterface,
+                            public ServiceObserverInterface {
+ public:
+  explicit SideloadDaemonState(brillo::StreamPtr status_stream)
+      : status_stream_(std::move(status_stream)) {
+    // Add this class as the only observer.
+    observers_.insert(this);
+  }
+  ~SideloadDaemonState() override = default;
+
+  // DaemonStateInterface overrides.
+  bool StartUpdater() override { return true; }
+  void AddObserver(ServiceObserverInterface* observer) override {}
+  void RemoveObserver(ServiceObserverInterface* observer) override {}
+  const std::set<ServiceObserverInterface*>& service_observers() override {
+    return observers_;
+  }
+
+  // ServiceObserverInterface overrides.
+  void SendStatusUpdate(int64_t last_checked_time,
+                        double progress,
+                        UpdateStatus status,
+                        const string& new_version,
+                        int64_t new_size) override {
+    if (status_ != status && (status == UpdateStatus::DOWNLOADING ||
+                              status == UpdateStatus::FINALIZING)) {
+      // Split the progress bar in two parts for the two stages DOWNLOADING and
+      // FINALIZING.
+      ReportStatus(base::StringPrintf(
+          "ui_print Step %d/2", status == UpdateStatus::DOWNLOADING ? 1 : 2));
+      ReportStatus(base::StringPrintf("progress 0.5 0"));
+    }
+    if (status_ != status || fabs(progress - progress_) > 0.005) {
+      ReportStatus(base::StringPrintf("set_progress %.lf", progress));
+    }
+    progress_ = progress;
+    status_ = status;
+  }
+
+  void SendPayloadApplicationComplete(ErrorCode error_code) override {
+    if (error_code != ErrorCode::kSuccess) {
+      ReportStatus(
+          base::StringPrintf("ui_print Error applying update: %d (%s)",
+                             error_code,
+                             utils::ErrorCodeToString(error_code).c_str()));
+    }
+    error_code_ = error_code;
+    brillo::MessageLoop::current()->BreakLoop();
+  }
+
+  // Getters.
+  UpdateStatus status() { return status_; }
+  ErrorCode error_code() { return error_code_; }
+
+ private:
+  // Report a status message in the status_stream_, if any. These messages
+  // should conform to the specification defined in the Android recovery.
+  void ReportStatus(const string& message) {
+    if (!status_stream_)
+      return;
+    string status_line = message + "\n";
+    status_stream_->WriteAllBlocking(
+        status_line.data(), status_line.size(), nullptr);
+  }
+
+  std::set<ServiceObserverInterface*> observers_;
+  brillo::StreamPtr status_stream_;
+
+  // The last status and error code reported.
+  UpdateStatus status_{UpdateStatus::IDLE};
+  ErrorCode error_code_{ErrorCode::kSuccess};
+  double progress_{-1.};
+};
+
+// Apply an update payload directly from the given payload URI.
+bool ApplyUpdatePayload(const string& payload,
+                        int64_t payload_offset,
+                        int64_t payload_size,
+                        const vector<string>& headers,
+                        int64_t status_fd) {
+  brillo::BaseMessageLoop loop;
+  loop.SetAsCurrent();
+
+  // Setup the subprocess handler.
+  brillo::AsynchronousSignalHandler handler;
+  handler.Init();
+  Subprocess subprocess;
+  subprocess.Init(&handler);
+
+  SideloadDaemonState sideload_daemon_state(
+      brillo::FileStream::FromFileDescriptor(status_fd, true, nullptr));
+
+  // During the sideload we don't access the prefs persisted on disk but instead
+  // use a temporary memory storage.
+  MemoryPrefs prefs;
+
+  std::unique_ptr<BootControlInterface> boot_control =
+      boot_control::CreateBootControl();
+  if (!boot_control) {
+    LOG(ERROR) << "Error initializing the BootControlInterface.";
+    return false;
+  }
+
+  std::unique_ptr<HardwareInterface> hardware = hardware::CreateHardware();
+  if (!hardware) {
+    LOG(ERROR) << "Error initializing the HardwareInterface.";
+    return false;
+  }
+
+  UpdateAttempterAndroid update_attempter(
+      &sideload_daemon_state, &prefs, boot_control.get(), hardware.get());
+  update_attempter.Init();
+
+  TEST_AND_RETURN_FALSE(update_attempter.ApplyPayload(
+      payload, payload_offset, payload_size, headers, nullptr));
+
+  loop.Run();
+  return sideload_daemon_state.status() == UpdateStatus::UPDATED_NEED_REBOOT;
+}
+
+}  // namespace
+}  // namespace chromeos_update_engine
+
+int main(int argc, char** argv) {
+  DEFINE_string(payload,
+                "file:///data/payload.bin",
+                "The URI to the update payload to use.");
+  DEFINE_int64(
+      offset, 0, "The offset in the payload where the CrAU update starts. ");
+  DEFINE_int64(size,
+               0,
+               "The size of the CrAU part of the payload. If 0 is passed, it "
+               "will be autodetected.");
+  DEFINE_string(headers,
+                "",
+                "A list of key-value pairs, one element of the list per line.");
+  DEFINE_int64(status_fd, -1, "A file descriptor to notify the update status.");
+
+  chromeos_update_engine::Terminator::Init();
+  chromeos_update_engine::SetupLogging();
+  brillo::FlagHelper::Init(argc, argv, "Update Engine Sideload");
+
+  LOG(INFO) << "Update Engine Sideloading starting";
+
+  // xz-embedded requires to initialize its CRC-32 table once on startup.
+  xz_crc32_init();
+
+  // When called from recovery, /data is not accessible, so we need to use
+  // /tmp for temporary files.
+  chromeos_update_engine::utils::SetRootTempDir(kSideloadRootTempDir);
+
+  vector<string> headers = base::SplitString(
+      FLAGS_headers, "\n", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
+
+  if (!chromeos_update_engine::ApplyUpdatePayload(
+          FLAGS_payload, FLAGS_offset, FLAGS_size, headers, FLAGS_status_fd))
+    return 1;
+
+  return 0;
+}
diff --git a/system_state.h b/system_state.h
index 7923217..d538427 100644
--- a/system_state.h
+++ b/system_state.h
@@ -17,12 +17,6 @@
 #ifndef UPDATE_ENGINE_SYSTEM_STATE_H_
 #define UPDATE_ENGINE_SYSTEM_STATE_H_
 
-namespace org {
-namespace chromium {
-class PowerManagerProxyInterface;
-}  // namespace chromium
-}  // namespace org
-
 class MetricsLibraryInterface;
 
 namespace chromeos_update_manager {
@@ -49,9 +43,9 @@
 class OmahaRequestParams;
 class P2PManager;
 class PayloadStateInterface;
+class PowerManagerInterface;
 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
@@ -99,9 +93,6 @@
   // 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;
@@ -112,8 +103,8 @@
   // Returns a pointer to the UpdateManager singleton.
   virtual chromeos_update_manager::UpdateManager* update_manager() = 0;
 
-  // DBus proxies. Mocked during test.
-  virtual org::chromium::PowerManagerProxyInterface* power_manager_proxy() = 0;
+  // Gets the power manager object. Mocked during test.
+  virtual PowerManagerInterface* power_manager() = 0;
 
   // If true, this is the first instance of the update engine since the system
   // restarted. Important for tracking whether you are running instance of the
diff --git a/update_attempter.cc b/update_attempter.cc
index ef07132..6b07ff9 100644
--- a/update_attempter.cc
+++ b/update_attempter.cc
@@ -32,29 +32,25 @@
 #include <base/strings/string_util.h>
 #include <base/strings/stringprintf.h>
 #include <brillo/bind_lambda.h>
+#include <brillo/errors/error_codes.h>
 #include <brillo/make_unique_ptr.h>
 #include <brillo/message_loops/message_loop.h>
-#include <debugd/dbus-constants.h>
-#include <debugd/dbus-proxies.h>
 #include <policy/device_policy.h>
 #include <policy/libpolicy.h>
-#include <power_manager/dbus-constants.h>
-#include <power_manager/dbus-proxies.h>
 #include <update_engine/dbus-constants.h>
 
+#include "update_engine/certificate_checker.h"
 #include "update_engine/common/boot_control_interface.h"
-#include "update_engine/common/certificate_checker.h"
 #include "update_engine/common/clock_interface.h"
 #include "update_engine/common/constants.h"
 #include "update_engine/common/hardware_interface.h"
-#include "update_engine/common/libcurl_http_fetcher.h"
 #include "update_engine/common/multi_range_http_fetcher.h"
 #include "update_engine/common/platform_constants.h"
 #include "update_engine/common/prefs_interface.h"
 #include "update_engine/common/subprocess.h"
 #include "update_engine/common/utils.h"
-#include "update_engine/connection_manager.h"
-#include "update_engine/dbus_service.h"
+#include "update_engine/connection_manager_interface.h"
+#include "update_engine/libcurl_http_fetcher.h"
 #include "update_engine/metrics.h"
 #include "update_engine/omaha_request_action.h"
 #include "update_engine/omaha_request_params.h"
@@ -64,6 +60,7 @@
 #include "update_engine/payload_consumer/filesystem_verifier_action.h"
 #include "update_engine/payload_consumer/postinstall_runner_action.h"
 #include "update_engine/payload_state_interface.h"
+#include "update_engine/power_manager_interface.h"
 #include "update_engine/system_state.h"
 #include "update_engine/update_manager/policy.h"
 #include "update_engine/update_manager/update_manager.h"
@@ -127,15 +124,15 @@
     SystemState* system_state,
     CertificateChecker* cert_checker,
     org::chromium::NetworkProxyServiceInterfaceProxyInterface*
-        network_proxy_service_proxy,
-    org::chromium::debugdProxyInterface* debugd_proxy)
+        network_proxy_service_proxy)
     : processor_(new ActionProcessor()),
       system_state_(system_state),
-      cert_checker_(cert_checker),
 #if USE_LIBCROS
-      chrome_proxy_resolver_(network_proxy_service_proxy),
+      cert_checker_(cert_checker),
+      chrome_proxy_resolver_(network_proxy_service_proxy) {
+#else
+      cert_checker_(cert_checker) {
 #endif  // USE_LIBCROS
-      debugd_proxy_(debugd_proxy) {
 }
 
 UpdateAttempter::~UpdateAttempter() {
@@ -409,8 +406,6 @@
                                                  &error_message)) {
       LOG(ERROR) << "Setting the channel failed: " << error_message;
     }
-    // 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,
@@ -584,7 +579,8 @@
 void UpdateAttempter::BuildPostInstallActions(
     InstallPlanAction* previous_action) {
   shared_ptr<PostinstallRunnerAction> postinstall_runner_action(
-      new PostinstallRunnerAction(system_state_->boot_control()));
+      new PostinstallRunnerAction(system_state_->boot_control(),
+                                  system_state_->hardware()));
   postinstall_runner_action->set_delegate(this);
   actions_.push_back(shared_ptr<AbstractAction>(postinstall_runner_action));
   BondActions(previous_action,
@@ -808,7 +804,7 @@
 }
 
 bool UpdateAttempter::RebootIfNeeded() {
-  if (USE_POWER_MANAGEMENT && RequestPowerManagerReboot())
+  if (system_state_->power_manager()->RequestReboot())
     return true;
 
   return RebootDirectly();
@@ -824,20 +820,6 @@
   prefs_->SetInt64(kPrefsUpdateCompletedBootTime, value);
 }
 
-bool UpdateAttempter::RequestPowerManagerReboot() {
-  org::chromium::PowerManagerProxyInterface* power_manager_proxy =
-      system_state_->power_manager_proxy();
-  if (!power_manager_proxy) {
-    LOG(WARNING) << "No PowerManager proxy defined, skipping reboot.";
-    return false;
-  }
-  LOG(INFO) << "Calling " << power_manager::kPowerManagerInterface << "."
-            << power_manager::kRequestRestartMethod;
-  brillo::ErrorPtr error;
-  return power_manager_proxy->RequestRestart(
-      power_manager::REQUEST_RESTART_FOR_UPDATE, &error);
-}
-
 bool UpdateAttempter::RebootDirectly() {
   vector<string> command;
   command.push_back("/sbin/shutdown");
@@ -1084,44 +1066,6 @@
   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;
-  }
-  // Notify observers the target channel change.
-  BroadcastChannel();
-  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;
-}
-
 void UpdateAttempter::ProgressUpdate(double progress) {
   // Self throttle based on progress. Also send notifications if progress is
   // too slow.
@@ -1158,6 +1102,12 @@
       if (!boot_control->SetActiveBootSlot(boot_control->GetCurrentSlot()))
         ret_value = false;
 
+      // Mark the current slot as successful again, since marking it as active
+      // may reset the successful bit. We ignore the result of whether marking
+      // the current slot as successful worked.
+      if (!boot_control->MarkBootSuccessfulAsync(Bind([](bool successful){})))
+        ret_value = false;
+
       // Notify the PayloadState that the successful payload was canceled.
       system_state_->payload_state()->ResetUpdateStatus();
 
@@ -1233,13 +1183,6 @@
   last_notify_time_ = TimeTicks::Now();
 }
 
-void UpdateAttempter::BroadcastChannel() {
-  for (const auto& observer : service_observers_) {
-    observer->SendChannelChangeUpdate(
-        system_state_->request_params()->target_channel());
-  }
-}
-
 uint32_t UpdateAttempter::GetErrorCodeFlags()  {
   uint32_t flags = 0;
 
@@ -1356,7 +1299,8 @@
   start_action_processor_ = false;
   MessageLoop::current()->PostTask(
       FROM_HERE,
-      Bind([this] { this->processor_->StartProcessing(); }));
+      Bind([](ActionProcessor* processor) { processor->StartProcessing(); },
+           base::Unretained(processor_.get())));
 }
 
 void UpdateAttempter::DisableDeltaUpdateIfNeeded() {
@@ -1596,28 +1540,13 @@
     return true;
   }
 
-  // Even though the debugd tools are also gated on devmode, checking here can
-  // save us a D-Bus call so it's worth doing explicitly.
-  if (system_state_->hardware()->IsNormalBootMode()) {
-    LOG(INFO) << "Not in devmode; disallowing custom update sources.";
-    return false;
-  }
-
-  // Official images in devmode are allowed a custom update source iff the
-  // debugd dev tools are enabled.
-  if (!debugd_proxy_)
-    return false;
-  int32_t dev_features = debugd::DEV_FEATURES_DISABLED;
-  brillo::ErrorPtr error;
-  bool success = debugd_proxy_->QueryDevFeatures(&dev_features, &error);
-
-  // Some boards may not include debugd so it's expected that this may fail,
-  // in which case we default to disallowing custom update sources.
-  if (success && !(dev_features & debugd::DEV_FEATURES_DISABLED)) {
-    LOG(INFO) << "Debugd dev tools enabled; allowing any update source.";
+  if (system_state_->hardware()->AreDevFeaturesEnabled()) {
+    LOG(INFO) << "Developer features enabled; allowing custom update sources.";
     return true;
   }
-  LOG(INFO) << "Debugd dev tools disabled; disallowing custom update sources.";
+
+  LOG(INFO)
+      << "Developer features disabled; disallowing custom update sources.";
   return false;
 }
 
diff --git a/update_attempter.h b/update_attempter.h
index d354f40..193e172 100644
--- a/update_attempter.h
+++ b/update_attempter.h
@@ -29,10 +29,12 @@
 #include <base/time/time.h>
 #include <gtest/gtest_prod.h>  // for FRIEND_TEST
 
+#if USE_LIBCROS
 #include "update_engine/chrome_browser_proxy_resolver.h"
+#endif  // USE_LIBCROS
+#include "update_engine/certificate_checker.h"
 #include "update_engine/client_library/include/update_engine/update_status.h"
 #include "update_engine/common/action_processor.h"
-#include "update_engine/common/certificate_checker.h"
 #include "update_engine/common/cpu_limiter.h"
 #include "update_engine/omaha_request_params.h"
 #include "update_engine/omaha_response_handler_action.h"
@@ -43,13 +45,11 @@
 #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;
 
 namespace org {
 namespace chromium {
-class debugdProxyInterface;
 class NetworkProxyServiceInterfaceProxyInterface;
 }  // namespace chromium
 }  // namespace org
@@ -65,7 +65,6 @@
 class UpdateAttempter : public ActionProcessorDelegate,
                         public DownloadActionDelegate,
                         public CertificateChecker::Observer,
-                        public WeaveServiceInterface::DelegateInterface,
                         public PostinstallRunnerAction::DelegateInterface {
  public:
   using UpdateStatus = update_engine::UpdateStatus;
@@ -74,8 +73,7 @@
   UpdateAttempter(SystemState* system_state,
                   CertificateChecker* cert_checker,
                   org::chromium::NetworkProxyServiceInterfaceProxyInterface*
-                      network_proxy_service_proxy,
-                  org::chromium::debugdProxyInterface* debugd_proxy);
+                      network_proxy_service_proxy);
   ~UpdateAttempter() override;
 
   // Further initialization to be done post construction.
@@ -106,16 +104,6 @@
                        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;
-
   // PostinstallRunnerAction::DelegateInterface
   void ProgressUpdate(double progress) override;
 
@@ -187,9 +175,6 @@
   // 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();
@@ -250,6 +235,10 @@
     service_observers_.erase(observer);
   }
 
+  const std::set<ServiceObserverInterface*>& service_observers() {
+    return service_observers_;
+  }
+
   // Remove all the observers.
   void ClearObservers() { service_observers_.clear(); }
 
@@ -388,10 +377,6 @@
   // |update_completed_marker_| is empty.
   void WriteUpdateCompletedMarker();
 
-  // Sends a D-Bus message to the Chrome OS power manager asking it to reboot
-  // the system. Returns true on success.
-  bool RequestPowerManagerReboot();
-
   // Reboots the system directly by calling /sbin/shutdown. Returns true on
   // success.
   bool RebootDirectly();
@@ -518,8 +503,6 @@
   std::string forced_app_version_;
   std::string forced_omaha_url_;
 
-  org::chromium::debugdProxyInterface* debugd_proxy_;
-
   DISALLOW_COPY_AND_ASSIGN(UpdateAttempter);
 };
 
diff --git a/update_attempter_android.cc b/update_attempter_android.cc
index 87c7e0d..dcdd989 100644
--- a/update_attempter_android.cc
+++ b/update_attempter_android.cc
@@ -28,15 +28,22 @@
 #include <brillo/strings/string_utils.h>
 
 #include "update_engine/common/constants.h"
-#include "update_engine/common/libcurl_http_fetcher.h"
+#include "update_engine/common/file_fetcher.h"
 #include "update_engine/common/multi_range_http_fetcher.h"
 #include "update_engine/common/utils.h"
-#include "update_engine/daemon_state_android.h"
+#include "update_engine/daemon_state_interface.h"
+#include "update_engine/network_selector.h"
 #include "update_engine/payload_consumer/download_action.h"
 #include "update_engine/payload_consumer/filesystem_verifier_action.h"
 #include "update_engine/payload_consumer/postinstall_runner_action.h"
 #include "update_engine/update_status_utils.h"
 
+#ifndef _UE_SIDELOAD
+// Do not include support for external HTTP(s) urls when building
+// update_engine_sideload.
+#include "update_engine/libcurl_http_fetcher.h"
+#endif
+
 using base::Bind;
 using base::TimeDelta;
 using base::TimeTicks;
@@ -70,7 +77,7 @@
 }  // namespace
 
 UpdateAttempterAndroid::UpdateAttempterAndroid(
-    DaemonStateAndroid* daemon_state,
+    DaemonStateInterface* daemon_state,
     PrefsInterface* prefs,
     BootControlInterface* boot_control,
     HardwareInterface* hardware)
@@ -79,6 +86,7 @@
       boot_control_(boot_control),
       hardware_(hardware),
       processor_(new ActionProcessor()) {
+  network_selector_ = network::CreateNetworkSelector();
 }
 
 UpdateAttempterAndroid::~UpdateAttempterAndroid() {
@@ -168,12 +176,30 @@
 
   install_plan_.source_slot = boot_control_->GetCurrentSlot();
   install_plan_.target_slot = install_plan_.source_slot == 0 ? 1 : 0;
-  install_plan_.powerwash_required = false;
+
+  int data_wipe = 0;
+  install_plan_.powerwash_required =
+      base::StringToInt(headers[kPayloadPropertyPowerwash], &data_wipe) &&
+      data_wipe != 0;
+
+  NetworkId network_id = kDefaultNetworkId;
+  if (!headers[kPayloadPropertyNetworkId].empty()) {
+    if (!base::StringToUint64(headers[kPayloadPropertyNetworkId],
+                              &network_id)) {
+      return LogAndSetError(
+          error,
+          FROM_HERE,
+          "Invalid network_id: " + headers[kPayloadPropertyNetworkId]);
+    }
+    if (!network_selector_->SetProcessNetwork(network_id)) {
+      LOG(WARNING) << "Unable to set network_id, continuing with the update.";
+    }
+  }
 
   LOG(INFO) << "Using this install plan:";
   install_plan_.Dump();
 
-  BuildUpdateActions();
+  BuildUpdateActions(payload_url);
   SetupDownload();
   // Setup extra headers.
   HttpFetcher* fetcher = download_action_->http_fetcher();
@@ -182,7 +208,6 @@
   if (!headers[kPayloadPropertyUserAgent].empty())
     fetcher->SetHeader("User-Agent", headers[kPayloadPropertyUserAgent]);
 
-  cpu_limiter_.StartLimiter();
   SetStatusAndNotify(UpdateStatus::UPDATE_AVAILABLE);
   ongoing_update_ = true;
 
@@ -231,6 +256,12 @@
       if (!boot_control_->SetActiveBootSlot(boot_control_->GetCurrentSlot()))
         ret_value = false;
 
+      // Mark the current slot as successful again, since marking it as active
+      // may reset the successful bit. We ignore the result of whether marking
+      // the current slot as successful worked.
+      if (!boot_control_->MarkBootSuccessfulAsync(Bind([](bool successful){})))
+        ret_value = false;
+
       if (!ret_value) {
         return LogAndSetError(
             error,
@@ -255,13 +286,30 @@
                                             ErrorCode code) {
   LOG(INFO) << "Processing Done.";
 
-  if (code == ErrorCode::kSuccess) {
-    // Update succeeded.
-    WriteUpdateCompletedMarker();
-    prefs_->SetInt64(kPrefsDeltaUpdateFailures, 0);
-    DeltaPerformer::ResetUpdateProgress(prefs_, false);
+  switch (code) {
+    case ErrorCode::kSuccess:
+      // Update succeeded.
+      WriteUpdateCompletedMarker();
+      prefs_->SetInt64(kPrefsDeltaUpdateFailures, 0);
+      DeltaPerformer::ResetUpdateProgress(prefs_, false);
 
-    LOG(INFO) << "Update successfully applied, waiting to reboot.";
+      LOG(INFO) << "Update successfully applied, waiting to reboot.";
+      break;
+
+    case ErrorCode::kFilesystemCopierError:
+    case ErrorCode::kNewRootfsVerificationError:
+    case ErrorCode::kNewKernelVerificationError:
+    case ErrorCode::kFilesystemVerifierError:
+    case ErrorCode::kDownloadStateInitializationError:
+      // Reset the ongoing update for these errors so it starts from the
+      // beginning next time.
+      DeltaPerformer::ResetUpdateProgress(prefs_, false);
+      LOG(INFO) << "Resetting update progress.";
+      break;
+
+    default:
+      // Ignore all other error codes.
+      break;
   }
 
   TerminateUpdateAndNotify(code);
@@ -350,7 +398,9 @@
 void UpdateAttempterAndroid::ScheduleProcessingStart() {
   LOG(INFO) << "Scheduling an action processor start.";
   brillo::MessageLoop::current()->PostTask(
-      FROM_HERE, Bind([this] { this->processor_->StartProcessing(); }));
+      FROM_HERE,
+      Bind([](ActionProcessor* processor) { processor->StartProcessing(); },
+           base::Unretained(processor_.get())));
 }
 
 void UpdateAttempterAndroid::TerminateUpdateAndNotify(ErrorCode error_code) {
@@ -359,8 +409,6 @@
     return;
   }
 
-  // Reset cpu shares back to normal.
-  cpu_limiter_.StopLimiter();
   download_progress_ = 0;
   actions_.clear();
   UpdateStatus new_status =
@@ -382,7 +430,7 @@
   last_notify_time_ = TimeTicks::Now();
 }
 
-void UpdateAttempterAndroid::BuildUpdateActions() {
+void UpdateAttempterAndroid::BuildUpdateActions(const string& url) {
   CHECK(!processor_->IsRunning());
   processor_->set_delegate(this);
 
@@ -390,9 +438,20 @@
   shared_ptr<InstallPlanAction> install_plan_action(
       new InstallPlanAction(install_plan_));
 
-  LibcurlHttpFetcher* download_fetcher =
-      new LibcurlHttpFetcher(&proxy_resolver_, hardware_);
-  download_fetcher->set_server_to_check(ServerToCheck::kDownload);
+  HttpFetcher* download_fetcher = nullptr;
+  if (FileFetcher::SupportedUrl(url)) {
+    DLOG(INFO) << "Using FileFetcher for file URL.";
+    download_fetcher = new FileFetcher();
+  } else {
+#ifdef _UE_SIDELOAD
+    LOG(FATAL) << "Unsupported sideload URI: " << url;
+#else
+    LibcurlHttpFetcher* libcurl_fetcher =
+        new LibcurlHttpFetcher(&proxy_resolver_, hardware_);
+    libcurl_fetcher->set_server_to_check(ServerToCheck::kDownload);
+    download_fetcher = libcurl_fetcher;
+#endif  // _UE_SIDELOAD
+  }
   shared_ptr<DownloadAction> download_action(new DownloadAction(
       prefs_,
       boot_control_,
@@ -403,10 +462,11 @@
       new FilesystemVerifierAction());
 
   shared_ptr<PostinstallRunnerAction> postinstall_runner_action(
-      new PostinstallRunnerAction(boot_control_));
+      new PostinstallRunnerAction(boot_control_, hardware_));
 
   download_action->set_delegate(this);
   download_action_ = download_action;
+  postinstall_runner_action->set_delegate(this);
 
   actions_.push_back(shared_ptr<AbstractAction>(install_plan_action));
   actions_.push_back(shared_ptr<AbstractAction>(download_action));
diff --git a/update_attempter_android.h b/update_attempter_android.h
index 4fdac2c..6a5c227 100644
--- a/update_attempter_android.h
+++ b/update_attempter_android.h
@@ -28,9 +28,10 @@
 #include "update_engine/client_library/include/update_engine/update_status.h"
 #include "update_engine/common/action_processor.h"
 #include "update_engine/common/boot_control_interface.h"
-#include "update_engine/common/cpu_limiter.h"
 #include "update_engine/common/hardware_interface.h"
 #include "update_engine/common/prefs_interface.h"
+#include "update_engine/daemon_state_interface.h"
+#include "update_engine/network_selector_interface.h"
 #include "update_engine/payload_consumer/download_action.h"
 #include "update_engine/payload_consumer/postinstall_runner_action.h"
 #include "update_engine/service_delegate_android_interface.h"
@@ -38,8 +39,6 @@
 
 namespace chromeos_update_engine {
 
-class DaemonStateAndroid;
-
 class UpdateAttempterAndroid
     : public ServiceDelegateAndroidInterface,
       public ActionProcessorDelegate,
@@ -48,7 +47,7 @@
  public:
   using UpdateStatus = update_engine::UpdateStatus;
 
-  UpdateAttempterAndroid(DaemonStateAndroid* daemon_state,
+  UpdateAttempterAndroid(DaemonStateInterface* daemon_state,
                          PrefsInterface* prefs,
                          BootControlInterface* boot_control_,
                          HardwareInterface* hardware_);
@@ -108,8 +107,8 @@
   void SetStatusAndNotify(UpdateStatus status);
 
   // Helper method to construct the sequence of actions to be performed for
-  // applying an update.
-  void BuildUpdateActions();
+  // applying an update from the given |url|.
+  void BuildUpdateActions(const std::string& url);
 
   // Sets up the download parameters based on the update requested on the
   // |install_plan_|.
@@ -122,7 +121,7 @@
   // Returns whether an update was completed in the current boot.
   bool UpdateCompletedOnThisBoot();
 
-  DaemonStateAndroid* daemon_state_;
+  DaemonStateInterface* daemon_state_;
 
   // DaemonStateAndroid pointers.
   PrefsInterface* prefs_;
@@ -160,8 +159,8 @@
   // Only direct proxy supported.
   DirectProxyResolver proxy_resolver_;
 
-  // CPU limiter during the update.
-  CPULimiter cpu_limiter_;
+  // Helper class to select the network to use during the update.
+  std::unique_ptr<NetworkSelectorInterface> network_selector_;
 
   // Whether we have marked the current slot as good. This step is required
   // before applying an update to the other slot.
diff --git a/update_attempter_unittest.cc b/update_attempter_unittest.cc
index e3dab7d..93bcc5c 100644
--- a/update_attempter_unittest.cc
+++ b/update_attempter_unittest.cc
@@ -27,15 +27,14 @@
 #include <brillo/message_loops/base_message_loop.h>
 #include <brillo/message_loops/message_loop.h>
 #include <brillo/message_loops/message_loop_utils.h>
-#include <debugd/dbus-constants.h>
-#include <debugd/dbus-proxies.h>
-#include <debugd/dbus-proxy-mocks.h>
 #include <gtest/gtest.h>
 #include <policy/libpolicy.h>
 #include <policy/mock_device_policy.h>
 
+#if USE_LIBCROS
 #include "network_proxy/dbus-proxies.h"
 #include "network_proxy/dbus-proxy-mocks.h"
+#endif // USE_LIBCROS
 #include "update_engine/common/fake_clock.h"
 #include "update_engine/common/fake_prefs.h"
 #include "update_engine/common/mock_action.h"
@@ -54,9 +53,14 @@
 #include "update_engine/payload_consumer/payload_constants.h"
 #include "update_engine/payload_consumer/postinstall_runner_action.h"
 
+namespace org {
+namespace chromium {
+class NetworkProxyServiceInterfaceProxyMock;
+}  // namespace chromium
+}  // namespace org
+
 using base::Time;
 using base::TimeDelta;
-using org::chromium::debugdProxyMock;
 using org::chromium::NetworkProxyServiceInterfaceProxyInterface;
 using org::chromium::NetworkProxyServiceInterfaceProxyMock;
 using std::string;
@@ -82,10 +86,8 @@
  public:
   UpdateAttempterUnderTest(
       SystemState* system_state,
-      NetworkProxyServiceInterfaceProxyInterface* network_proxy_service_proxy,
-      org::chromium::debugdProxyInterface* debugd_proxy)
-      : UpdateAttempter(system_state, nullptr, network_proxy_service_proxy,
-                        debugd_proxy) {}
+      NetworkProxyServiceInterfaceProxyInterface* network_proxy_service_proxy)
+      : UpdateAttempter(system_state, nullptr, network_proxy_service_proxy) {}
 
   // Wrap the update scheduling method, allowing us to opt out of scheduled
   // updates for testing purposes.
@@ -185,13 +187,15 @@
   brillo::BaseMessageLoop loop_{&base_loop_};
 
   FakeSystemState fake_system_state_;
-  org::chromium::debugdProxyMock debugd_proxy_mock_;
+#if USE_LIBCROS
   NetworkProxyServiceInterfaceProxyMock network_proxy_service_proxy_mock_;
+  UpdateAttempterUnderTest attempter_{&fake_system_state_,
+                                      &network_proxy_service_proxy_mock_};
+#else
+  UpdateAttempterUnderTest attempter_{&fake_system_state_, nullptr};
+#endif  // USE_LIBCROS
   OpenSSLWrapper openssl_wrapper_;
   CertificateChecker certificate_checker_;
-  UpdateAttempterUnderTest attempter_{&fake_system_state_,
-                                      &network_proxy_service_proxy_mock_,
-                                      &debugd_proxy_mock_};
 
   NiceMock<MockActionProcessor>* processor_;
   NiceMock<MockPrefs>* prefs_;  // Shortcut to fake_system_state_->mock_prefs().
@@ -202,7 +206,10 @@
 };
 
 void UpdateAttempterTest::ScheduleQuitMainLoop() {
-  loop_.PostTask(FROM_HERE, base::Bind([this] { this->loop_.BreakLoop(); }));
+  loop_.PostTask(
+      FROM_HERE,
+      base::Bind([](brillo::BaseMessageLoop* loop) { loop->BreakLoop(); },
+                 base::Unretained(&loop_)));
 }
 
 TEST_F(UpdateAttempterTest, ActionCompletedDownloadTest) {
@@ -250,11 +257,8 @@
   EXPECT_TRUE(utils::GetBootId(&boot_id));
   fake_prefs.SetString(kPrefsUpdateCompletedOnBootId, boot_id);
   fake_system_state_.set_prefs(&fake_prefs);
-  UpdateAttempterUnderTest attempter(&fake_system_state_,
-                                     &network_proxy_service_proxy_mock_,
-                                     &debugd_proxy_mock_);
-  attempter.Init();
-  EXPECT_EQ(UpdateStatus::UPDATED_NEED_REBOOT, attempter.status());
+  attempter_.Init();
+  EXPECT_EQ(UpdateStatus::UPDATED_NEED_REBOOT, attempter_.status());
 }
 
 TEST_F(UpdateAttempterTest, GetErrorCodeForActionTest) {
@@ -277,7 +281,7 @@
             GetErrorCodeForAction(&filesystem_verifier_action,
                                   ErrorCode::kError));
   PostinstallRunnerAction postinstall_runner_action(
-      fake_system_state.fake_boot_control());
+      fake_system_state.fake_boot_control(), fake_system_state.fake_hardware());
   EXPECT_EQ(ErrorCode::kPostinstallRunnerError,
             GetErrorCodeForAction(&postinstall_runner_action,
                                   ErrorCode::kError));
@@ -920,22 +924,19 @@
 }
 
 TEST_F(UpdateAttempterTest, BootTimeInUpdateMarkerFile) {
-  UpdateAttempterUnderTest attempter{&fake_system_state_,
-                                     &network_proxy_service_proxy_mock_,
-                                     &debugd_proxy_mock_};
   FakeClock fake_clock;
   fake_clock.SetBootTime(Time::FromTimeT(42));
   fake_system_state_.set_clock(&fake_clock);
   FakePrefs fake_prefs;
   fake_system_state_.set_prefs(&fake_prefs);
-  attempter.Init();
+  attempter_.Init();
 
   Time boot_time;
-  EXPECT_FALSE(attempter.GetBootTimeAtUpdate(&boot_time));
+  EXPECT_FALSE(attempter_.GetBootTimeAtUpdate(&boot_time));
 
-  attempter.WriteUpdateCompletedMarker();
+  attempter_.WriteUpdateCompletedMarker();
 
-  EXPECT_TRUE(attempter.GetBootTimeAtUpdate(&boot_time));
+  EXPECT_TRUE(attempter_.GetBootTimeAtUpdate(&boot_time));
   EXPECT_EQ(boot_time.ToTimeT(), 42);
 }
 
@@ -946,48 +947,26 @@
 
 TEST_F(UpdateAttempterTest, AnyUpdateSourceAllowedOfficialDevmode) {
   fake_system_state_.fake_hardware()->SetIsOfficialBuild(true);
-  fake_system_state_.fake_hardware()->SetIsNormalBootMode(false);
-  EXPECT_CALL(debugd_proxy_mock_, QueryDevFeatures(_, _, _))
-      .WillRepeatedly(DoAll(SetArgumentPointee<0>(0), Return(true)));
+  fake_system_state_.fake_hardware()->SetAreDevFeaturesEnabled(true);
   EXPECT_TRUE(attempter_.IsAnyUpdateSourceAllowed());
 }
 
 TEST_F(UpdateAttempterTest, AnyUpdateSourceDisallowedOfficialNormal) {
   fake_system_state_.fake_hardware()->SetIsOfficialBuild(true);
-  fake_system_state_.fake_hardware()->SetIsNormalBootMode(true);
-  // debugd should not be queried in this case.
-  EXPECT_CALL(debugd_proxy_mock_, QueryDevFeatures(_, _, _)).Times(0);
-  EXPECT_FALSE(attempter_.IsAnyUpdateSourceAllowed());
-}
-
-TEST_F(UpdateAttempterTest, AnyUpdateSourceDisallowedDebugdDisabled) {
-  using debugd::DEV_FEATURES_DISABLED;
-  fake_system_state_.fake_hardware()->SetIsOfficialBuild(true);
-  fake_system_state_.fake_hardware()->SetIsNormalBootMode(false);
-  EXPECT_CALL(debugd_proxy_mock_, QueryDevFeatures(_, _, _))
-      .WillRepeatedly(
-          DoAll(SetArgumentPointee<0>(DEV_FEATURES_DISABLED), Return(true)));
-  EXPECT_FALSE(attempter_.IsAnyUpdateSourceAllowed());
-}
-
-TEST_F(UpdateAttempterTest, AnyUpdateSourceDisallowedDebugdFailure) {
-  fake_system_state_.fake_hardware()->SetIsOfficialBuild(true);
-  fake_system_state_.fake_hardware()->SetIsNormalBootMode(false);
-  EXPECT_CALL(debugd_proxy_mock_, QueryDevFeatures(_, _, _))
-      .WillRepeatedly(Return(false));
+  fake_system_state_.fake_hardware()->SetAreDevFeaturesEnabled(false);
   EXPECT_FALSE(attempter_.IsAnyUpdateSourceAllowed());
 }
 
 TEST_F(UpdateAttempterTest, CheckForUpdateAUTest) {
   fake_system_state_.fake_hardware()->SetIsOfficialBuild(true);
-  fake_system_state_.fake_hardware()->SetIsNormalBootMode(true);
+  fake_system_state_.fake_hardware()->SetAreDevFeaturesEnabled(false);
   attempter_.CheckForUpdate("", "autest", true);
   EXPECT_EQ(constants::kOmahaDefaultAUTestURL, attempter_.forced_omaha_url());
 }
 
 TEST_F(UpdateAttempterTest, CheckForUpdateScheduledAUTest) {
   fake_system_state_.fake_hardware()->SetIsOfficialBuild(true);
-  fake_system_state_.fake_hardware()->SetIsNormalBootMode(true);
+  fake_system_state_.fake_hardware()->SetAreDevFeaturesEnabled(false);
   attempter_.CheckForUpdate("", "autest-scheduled", true);
   EXPECT_EQ(constants::kOmahaDefaultAUTestURL, attempter_.forced_omaha_url());
 }
diff --git a/update_engine.gyp b/update_engine.gyp
index 6c2ff16..6b7e5f4 100644
--- a/update_engine.gyp
+++ b/update_engine.gyp
@@ -49,8 +49,8 @@
       'USE_HWID_OVERRIDE=<(USE_hwid_override)',
       'USE_LIBCROS=<(USE_libcros)',
       'USE_MTD=<(USE_mtd)',
-      'USE_POWER_MANAGEMENT=<(USE_power_management)',
-      'USE_WEAVE=<(USE_buffet)',
+      'USE_OMAHA=1',
+      'USE_SHILL=1',
     ],
     'include_dirs': [
       # We need this include dir because we include all the local code as
@@ -137,9 +137,6 @@
       'variables': {
         'exported_deps': [
           'libcrypto',
-          'libcurl',
-          'libimgpatch',
-          'libssl',
           'xz-embedded',
         ],
         'deps': ['<@(exported_deps)'],
@@ -158,6 +155,7 @@
           ],
         },
         'libraries': [
+          '-lbspatch',
           '-lbz2',
           '-lrt',
         ],
@@ -165,7 +163,6 @@
       'sources': [
         'common/action_processor.cc',
         'common/boot_control_stub.cc',
-        'common/certificate_checker.cc',
         'common/clock.cc',
         'common/constants.cc',
         'common/cpu_limiter.cc',
@@ -174,7 +171,6 @@
         'common/http_common.cc',
         'common/http_fetcher.cc',
         'common/hwid_override.cc',
-        'common/libcurl_http_fetcher.cc',
         'common/multi_range_http_fetcher.cc',
         'common/platform_constants_chromeos.cc',
         'common/prefs.cc',
@@ -221,13 +217,15 @@
       'variables': {
         'exported_deps': [
           'dbus-1',
+          'expat',
+          'libcurl',
           'libdebugd-client',
-          'libsession_manager-client',
           'libmetrics-<(libbase_ver)',
           'libpower_manager-client',
-          'libupdate_engine-client',
+          'libsession_manager-client',
           'libshill-client',
-          'expat',
+          'libssl',
+          'libupdate_engine-client',
         ],
         'deps': ['<@(exported_deps)'],
       },
@@ -254,12 +252,16 @@
       },
       'sources': [
         'boot_control_chromeos.cc',
+        'certificate_checker.cc',
         'common_service.cc',
         'connection_manager.cc',
+        'connection_utils.cc',
         'daemon.cc',
+        'dbus_connection.cc',
         'dbus_service.cc',
         'hardware_chromeos.cc',
         'image_properties_chromeos.cc',
+        'libcurl_http_fetcher.cc',
         'metrics.cc',
         'metrics_utils.cc',
         'omaha_request_action.cc',
@@ -268,6 +270,7 @@
         'omaha_utils.cc',
         'p2p_manager.cc',
         'payload_state.cc',
+        'power_manager_chromeos.cc',
         'proxy_resolver.cc',
         'real_system_state.cc',
         'shill_proxy.cc',
@@ -287,19 +290,8 @@
         '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)',
-            ],
-          },
-        }],
         ['USE_libcros == 1', {
           'dependencies': [
             'update_engine-other-dbus-proxies',
@@ -398,6 +390,7 @@
         'payload_generator/graph_types.cc',
         'payload_generator/graph_utils.cc',
         'payload_generator/inplace_generator.cc',
+        'payload_generator/mapfile_filesystem.cc',
         'payload_generator/payload_file.cc',
         'payload_generator/payload_generation_config.cc',
         'payload_generator/payload_signer.cc',
@@ -493,12 +486,13 @@
           'includes': ['../../../platform2/common-mk/common_test.gypi'],
           'sources': [
             'boot_control_chromeos_unittest.cc',
+            'certificate_checker_unittest.cc',
             'common/action_pipe_unittest.cc',
             'common/action_processor_unittest.cc',
             'common/action_unittest.cc',
-            'common/certificate_checker_unittest.cc',
             'common/cpu_limiter_unittest.cc',
             'common/fake_prefs.cc',
+            'common/file_fetcher.cc',  # Only required for tests.
             'common/hash_calculator_unittest.cc',
             'common/http_fetcher_unittest.cc',
             'common/hwid_override_unittest.cc',
@@ -541,6 +535,7 @@
             'payload_generator/full_update_generator_unittest.cc',
             'payload_generator/graph_utils_unittest.cc',
             'payload_generator/inplace_generator_unittest.cc',
+            'payload_generator/mapfile_filesystem_unittest.cc',
             'payload_generator/payload_file_unittest.cc',
             'payload_generator/payload_generation_config_unittest.cc',
             'payload_generator/payload_signer_unittest.cc',
diff --git a/update_engine.rc b/update_engine.rc
index 62bbcc7..b6a706a 100644
--- a/update_engine.rc
+++ b/update_engine.rc
@@ -1,5 +1,5 @@
 service update_engine /system/bin/update_engine --logtostderr --foreground
     class late_start
     user root
-    group root system wakelock dbus inet
+    group root system wakelock inet cache
     writepid /dev/cpuset/system-background/tasks
diff --git a/update_manager/boxed_value.cc b/update_manager/boxed_value.cc
index a4aeede..9758d33 100644
--- a/update_manager/boxed_value.cc
+++ b/update_manager/boxed_value.cc
@@ -25,9 +25,13 @@
 #include <base/time/time.h>
 
 #include "update_engine/common/utils.h"
+#include "update_engine/connection_utils.h"
 #include "update_engine/update_manager/shill_provider.h"
 #include "update_engine/update_manager/updater_provider.h"
 
+using chromeos_update_engine::ConnectionTethering;
+using chromeos_update_engine::ConnectionType;
+using chromeos_update_engine::connection_utils::StringForConnectionType;
 using std::set;
 using std::string;
 
@@ -91,29 +95,10 @@
   return chromeos_update_engine::utils::FormatTimeDelta(*val);
 }
 
-static string ConnectionTypeToString(ConnectionType type) {
-  switch (type) {
-    case ConnectionType::kEthernet:
-      return "Ethernet";
-    case ConnectionType::kWifi:
-      return "Wifi";
-    case ConnectionType::kWimax:
-      return "Wimax";
-    case ConnectionType::kBluetooth:
-      return "Bluetooth";
-    case ConnectionType::kCellular:
-      return "Cellular";
-    case ConnectionType::kUnknown:
-      return "Unknown";
-  }
-  NOTREACHED();
-  return "Unknown";
-}
-
 template<>
 string BoxedValue::ValuePrinter<ConnectionType>(const void* value) {
   const ConnectionType* val = reinterpret_cast<const ConnectionType*>(value);
-  return ConnectionTypeToString(*val);
+  return StringForConnectionType(*val);
 }
 
 template<>
@@ -125,7 +110,7 @@
     ConnectionType type = it;
     if (ret.size() > 0)
       ret += ",";
-    ret += ConnectionTypeToString(type);
+    ret += StringForConnectionType(type);
   }
   return ret;
 }
diff --git a/update_manager/boxed_value_unittest.cc b/update_manager/boxed_value_unittest.cc
index 47bfd8f..2a086a6 100644
--- a/update_manager/boxed_value_unittest.cc
+++ b/update_manager/boxed_value_unittest.cc
@@ -31,6 +31,8 @@
 
 using base::Time;
 using base::TimeDelta;
+using chromeos_update_engine::ConnectionTethering;
+using chromeos_update_engine::ConnectionType;
 using std::list;
 using std::map;
 using std::set;
@@ -156,17 +158,17 @@
 }
 
 TEST(UmBoxedValueTest, ConnectionTypeToString) {
-  EXPECT_EQ("Ethernet",
+  EXPECT_EQ("ethernet",
             BoxedValue(new ConnectionType(ConnectionType::kEthernet))
             .ToString());
-  EXPECT_EQ("Wifi",
+  EXPECT_EQ("wifi",
             BoxedValue(new ConnectionType(ConnectionType::kWifi)).ToString());
-  EXPECT_EQ("Wimax",
+  EXPECT_EQ("wimax",
             BoxedValue(new ConnectionType(ConnectionType::kWimax)).ToString());
-  EXPECT_EQ("Bluetooth",
+  EXPECT_EQ("bluetooth",
             BoxedValue(new ConnectionType(ConnectionType::kBluetooth))
             .ToString());
-  EXPECT_EQ("Cellular",
+  EXPECT_EQ("cellular",
             BoxedValue(new ConnectionType(ConnectionType::kCellular))
             .ToString());
   EXPECT_EQ("Unknown",
@@ -193,11 +195,11 @@
   set<ConnectionType>* set1 = new set<ConnectionType>;
   set1->insert(ConnectionType::kWimax);
   set1->insert(ConnectionType::kEthernet);
-  EXPECT_EQ("Ethernet,Wimax", BoxedValue(set1).ToString());
+  EXPECT_EQ("ethernet,wimax", BoxedValue(set1).ToString());
 
   set<ConnectionType>* set2 = new set<ConnectionType>;
   set2->insert(ConnectionType::kWifi);
-  EXPECT_EQ("Wifi", BoxedValue(set2).ToString());
+  EXPECT_EQ("wifi", BoxedValue(set2).ToString());
 }
 
 TEST(UmBoxedValueTest, StageToString) {
diff --git a/update_manager/chromeos_policy.cc b/update_manager/chromeos_policy.cc
index e1fe398..e3893d3 100644
--- a/update_manager/chromeos_policy.cc
+++ b/update_manager/chromeos_policy.cc
@@ -33,6 +33,8 @@
 
 using base::Time;
 using base::TimeDelta;
+using chromeos_update_engine::ConnectionTethering;
+using chromeos_update_engine::ConnectionType;
 using chromeos_update_engine::ErrorCode;
 using std::get;
 using std::max;
diff --git a/update_manager/chromeos_policy_unittest.cc b/update_manager/chromeos_policy_unittest.cc
index 8a1796f..0c38700 100644
--- a/update_manager/chromeos_policy_unittest.cc
+++ b/update_manager/chromeos_policy_unittest.cc
@@ -32,6 +32,8 @@
 
 using base::Time;
 using base::TimeDelta;
+using chromeos_update_engine::ConnectionTethering;
+using chromeos_update_engine::ConnectionType;
 using chromeos_update_engine::ErrorCode;
 using chromeos_update_engine::FakeClock;
 using std::set;
diff --git a/update_manager/device_policy_provider.h b/update_manager/device_policy_provider.h
index 0eb04c1..3537d13 100644
--- a/update_manager/device_policy_provider.h
+++ b/update_manager/device_policy_provider.h
@@ -52,7 +52,7 @@
   // Variable returning the set of connection types allowed for updates. The
   // identifiers returned are consistent with the ones returned by the
   // ShillProvider.
-  virtual Variable<std::set<ConnectionType>>*
+  virtual Variable<std::set<chromeos_update_engine::ConnectionType>>*
       var_allowed_connection_types_for_update() = 0;
 
   // Variable stating the name of the device owner. For enterprise enrolled
diff --git a/update_manager/fake_device_policy_provider.h b/update_manager/fake_device_policy_provider.h
index 0ab2d3c..9e4f5b7 100644
--- a/update_manager/fake_device_policy_provider.h
+++ b/update_manager/fake_device_policy_provider.h
@@ -54,7 +54,7 @@
     return &var_scatter_factor_;
   }
 
-  FakeVariable<std::set<ConnectionType>>*
+  FakeVariable<std::set<chromeos_update_engine::ConnectionType>>*
       var_allowed_connection_types_for_update() override {
     return &var_allowed_connection_types_for_update_;
   }
@@ -88,7 +88,7 @@
       "target_version_prefix", kVariableModePoll};
   FakeVariable<base::TimeDelta> var_scatter_factor_{
       "scatter_factor", kVariableModePoll};
-  FakeVariable<std::set<ConnectionType>>
+  FakeVariable<std::set<chromeos_update_engine::ConnectionType>>
       var_allowed_connection_types_for_update_{
           "allowed_connection_types_for_update", kVariableModePoll};
   FakeVariable<std::string> var_owner_{"owner", kVariableModePoll};
diff --git a/update_manager/fake_shill_provider.h b/update_manager/fake_shill_provider.h
index b68e858..7f1c8f5 100644
--- a/update_manager/fake_shill_provider.h
+++ b/update_manager/fake_shill_provider.h
@@ -31,11 +31,12 @@
     return &var_is_connected_;
   }
 
-  FakeVariable<ConnectionType>* var_conn_type() override {
+  FakeVariable<chromeos_update_engine::ConnectionType>* var_conn_type()
+      override {
     return &var_conn_type_;
   }
 
-  FakeVariable<ConnectionTethering>*
+  FakeVariable<chromeos_update_engine::ConnectionTethering>*
       var_conn_tethering() override {
     return &var_conn_tethering_;
   }
@@ -46,8 +47,9 @@
 
  private:
   FakeVariable<bool> var_is_connected_{"is_connected", kVariableModePoll};
-  FakeVariable<ConnectionType> var_conn_type_{"conn_type", kVariableModePoll};
-  FakeVariable<ConnectionTethering> var_conn_tethering_{
+  FakeVariable<chromeos_update_engine::ConnectionType> var_conn_type_{
+      "conn_type", kVariableModePoll};
+  FakeVariable<chromeos_update_engine::ConnectionTethering> var_conn_tethering_{
       "conn_tethering", kVariableModePoll};
   FakeVariable<base::Time> var_conn_last_changed_{
       "conn_last_changed", kVariableModePoll};
diff --git a/update_manager/real_device_policy_provider.cc b/update_manager/real_device_policy_provider.cc
index 0e76518..d9880c3 100644
--- a/update_manager/real_device_policy_provider.cc
+++ b/update_manager/real_device_policy_provider.cc
@@ -24,11 +24,12 @@
 #include <policy/device_policy.h>
 
 #include "update_engine/common/utils.h"
+#include "update_engine/connection_utils.h"
 #include "update_engine/update_manager/generic_variables.h"
-#include "update_engine/update_manager/real_shill_provider.h"
 
 using base::TimeDelta;
 using brillo::MessageLoop;
+using chromeos_update_engine::ConnectionType;
 using policy::DevicePolicy;
 using std::set;
 using std::string;
@@ -51,6 +52,7 @@
   // On Init() we try to get the device policy and keep updating it.
   RefreshDevicePolicyAndReschedule();
 
+#if USE_DBUS
   // We also listen for signals from the session manager to force a device
   // policy refresh.
   session_manager_proxy_->RegisterPropertyChangeCompleteSignalHandler(
@@ -58,6 +60,7 @@
                  base::Unretained(this)),
       base::Bind(&RealDevicePolicyProvider::OnSignalConnected,
                  base::Unretained(this)));
+#endif  // USE_DBUS
   return true;
 }
 
@@ -133,7 +136,7 @@
   allowed_types->clear();
   for (auto& type_str : allowed_types_str) {
     ConnectionType type =
-        RealShillProvider::ParseConnectionType(type_str.c_str());
+        chromeos_update_engine::connection_utils::ParseConnectionType(type_str);
     if (type != ConnectionType::kUnknown) {
       allowed_types->insert(type);
     } else {
diff --git a/update_manager/real_device_policy_provider.h b/update_manager/real_device_policy_provider.h
index 6e798ca..5b5ee58 100644
--- a/update_manager/real_device_policy_provider.h
+++ b/update_manager/real_device_policy_provider.h
@@ -17,13 +17,16 @@
 #ifndef UPDATE_ENGINE_UPDATE_MANAGER_REAL_DEVICE_POLICY_PROVIDER_H_
 #define UPDATE_ENGINE_UPDATE_MANAGER_REAL_DEVICE_POLICY_PROVIDER_H_
 
+#include <memory>
 #include <set>
 #include <string>
 
 #include <brillo/message_loops/message_loop.h>
 #include <gtest/gtest_prod.h>  // for FRIEND_TEST
 #include <policy/libpolicy.h>
+#if USE_DBUS
 #include <session_manager/dbus-proxies.h>
+#endif  // USE_DBUS
 
 #include "update_engine/update_manager/device_policy_provider.h"
 #include "update_engine/update_manager/generic_variables.h"
@@ -33,11 +36,16 @@
 // DevicePolicyProvider concrete implementation.
 class RealDevicePolicyProvider : public DevicePolicyProvider {
  public:
-  RealDevicePolicyProvider(org::chromium::SessionManagerInterfaceProxyInterface*
-                               session_manager_proxy,
-                           policy::PolicyProvider* policy_provider)
+#if USE_DBUS
+  RealDevicePolicyProvider(
+      std::unique_ptr<org::chromium::SessionManagerInterfaceProxyInterface>
+          session_manager_proxy,
+      policy::PolicyProvider* policy_provider)
       : policy_provider_(policy_provider),
-        session_manager_proxy_(session_manager_proxy) {}
+        session_manager_proxy_(std::move(session_manager_proxy)) {}
+#endif  // USE_DBUS
+  explicit RealDevicePolicyProvider(policy::PolicyProvider* policy_provider)
+      : policy_provider_(policy_provider) {}
   ~RealDevicePolicyProvider();
 
   // Initializes the provider and returns whether it succeeded.
@@ -67,7 +75,7 @@
     return &var_scatter_factor_;
   }
 
-  Variable<std::set<ConnectionType>>*
+  Variable<std::set<chromeos_update_engine::ConnectionType>>*
       var_allowed_connection_types_for_update() override {
     return &var_allowed_connection_types_for_update_;
   }
@@ -130,7 +138,7 @@
   // Wrapper for DevicePolicy::GetAllowedConnectionTypesForUpdate() that
   // converts the result to a set of ConnectionType elements instead of strings.
   bool ConvertAllowedConnectionTypesForUpdate(
-      std::set<ConnectionType>* allowed_types) const;
+      std::set<chromeos_update_engine::ConnectionType>* allowed_types) const;
 
   // Used for fetching information about the device policy.
   policy::PolicyProvider* policy_provider_;
@@ -139,9 +147,11 @@
   brillo::MessageLoop::TaskId scheduled_refresh_{
       brillo::MessageLoop::kTaskIdNull};
 
-  // The DBus (mockable) session manager proxy, owned by the caller.
-  org::chromium::SessionManagerInterfaceProxyInterface* session_manager_proxy_{
-      nullptr};
+#if USE_DBUS
+  // The DBus (mockable) session manager proxy.
+  std::unique_ptr<org::chromium::SessionManagerInterfaceProxyInterface>
+      session_manager_proxy_;
+#endif  // USE_DBUS
 
   // Variable exposing whether the policy is loaded.
   AsyncCopyVariable<bool> var_device_policy_is_loaded_{
@@ -155,7 +165,7 @@
   AsyncCopyVariable<std::string> var_target_version_prefix_{
       "target_version_prefix"};
   AsyncCopyVariable<base::TimeDelta> var_scatter_factor_{"scatter_factor"};
-  AsyncCopyVariable<std::set<ConnectionType>>
+  AsyncCopyVariable<std::set<chromeos_update_engine::ConnectionType>>
       var_allowed_connection_types_for_update_{
           "allowed_connection_types_for_update"};
   AsyncCopyVariable<std::string> var_owner_{"owner"};
diff --git a/update_manager/real_device_policy_provider_unittest.cc b/update_manager/real_device_policy_provider_unittest.cc
index 09c9095..71c95bb 100644
--- a/update_manager/real_device_policy_provider_unittest.cc
+++ b/update_manager/real_device_policy_provider_unittest.cc
@@ -18,6 +18,7 @@
 
 #include <memory>
 
+#include <brillo/make_unique_ptr.h>
 #include <brillo/message_loops/fake_message_loop.h>
 #include <brillo/message_loops/message_loop.h>
 #include <brillo/message_loops/message_loop_utils.h>
@@ -25,16 +26,23 @@
 #include <gtest/gtest.h>
 #include <policy/mock_device_policy.h>
 #include <policy/mock_libpolicy.h>
+#if USE_DBUS
 #include <session_manager/dbus-proxies.h>
 #include <session_manager/dbus-proxy-mocks.h>
+#endif  // USE_DBUS
 
 #include "update_engine/common/test_utils.h"
+#if USE_DBUS
 #include "update_engine/dbus_test_utils.h"
+#endif  // USE_DBUS
 #include "update_engine/update_manager/umtest_utils.h"
 
 using base::TimeDelta;
 using brillo::MessageLoop;
+using chromeos_update_engine::ConnectionType;
+#if USE_DBUS
 using chromeos_update_engine::dbus_test_utils::MockSignalHandler;
+#endif  // USE_DBUS
 using std::set;
 using std::string;
 using std::unique_ptr;
@@ -51,17 +59,26 @@
  protected:
   void SetUp() override {
     loop_.SetAsCurrent();
-    provider_.reset(new RealDevicePolicyProvider(&session_manager_proxy_mock_,
-                                                 &mock_policy_provider_));
+#if USE_DBUS
+    auto session_manager_proxy_mock =
+        new org::chromium::SessionManagerInterfaceProxyMock();
+    provider_.reset(new RealDevicePolicyProvider(
+        brillo::make_unique_ptr(session_manager_proxy_mock),
+        &mock_policy_provider_));
+#else
+    provider_.reset(new RealDevicePolicyProvider(&mock_policy_provider_));
+#endif  // USE_DBUS
     // By default, we have a device policy loaded. Tests can call
     // SetUpNonExistentDevicePolicy() to override this.
     SetUpExistentDevicePolicy();
 
+#if USE_DBUS
     // Setup the session manager_proxy such that it will accept the signal
     // handler and store it in the |property_change_complete_| once registered.
     MOCK_SIGNAL_HANDLER_EXPECT_SIGNAL_HANDLER(property_change_complete_,
-                                              session_manager_proxy_mock_,
+                                              *session_manager_proxy_mock,
                                               PropertyChangeComplete);
+#endif  // USE_DBUS
   }
 
   void TearDown() override {
@@ -89,13 +106,14 @@
   }
 
   brillo::FakeMessageLoop loop_{nullptr};
-  org::chromium::SessionManagerInterfaceProxyMock session_manager_proxy_mock_;
   testing::NiceMock<policy::MockDevicePolicy> mock_device_policy_;
   testing::NiceMock<policy::MockPolicyProvider> mock_policy_provider_;
   unique_ptr<RealDevicePolicyProvider> provider_;
 
+#if USE_DBUS
   // The registered signal handler for the signal.
   MockSignalHandler<void(const string&)> property_change_complete_;
+#endif  // USE_DBUS
 };
 
 TEST_F(UmRealDevicePolicyProviderTest, RefreshScheduledTest) {
@@ -111,21 +129,29 @@
   EXPECT_CALL(mock_policy_provider_, Reload());
   EXPECT_TRUE(provider_->Init());
   Mock::VerifyAndClearExpectations(&mock_policy_provider_);
-
+  // We won't be notified that signal is connected without DBus.
+#if USE_DBUS
   EXPECT_CALL(mock_policy_provider_, Reload());
+#endif  // USE_DBUS
   loop_.RunOnce(false);
 }
 
 TEST_F(UmRealDevicePolicyProviderTest, NonExistentDevicePolicyReloaded) {
   // Checks that the policy is reloaded by RefreshDevicePolicy().
   SetUpNonExistentDevicePolicy();
+  // We won't be notified that signal is connected without DBus.
+#if USE_DBUS
   EXPECT_CALL(mock_policy_provider_, Reload()).Times(3);
+#else
+  EXPECT_CALL(mock_policy_provider_, Reload()).Times(2);
+#endif  // USE_DBUS
   EXPECT_TRUE(provider_->Init());
   loop_.RunOnce(false);
   // Force the policy refresh.
   provider_->RefreshDevicePolicy();
 }
 
+#if USE_DBUS
 TEST_F(UmRealDevicePolicyProviderTest, SessionManagerSignalForcesReload) {
   // Checks that a signal from the SessionManager forces a reload.
   SetUpNonExistentDevicePolicy();
@@ -138,6 +164,7 @@
   ASSERT_TRUE(property_change_complete_.IsHandlerRegistered());
   property_change_complete_.signal_callback().Run("success");
 }
+#endif  // USE_DBUS
 
 TEST_F(UmRealDevicePolicyProviderTest, NonExistentDevicePolicyEmptyVariables) {
   SetUpNonExistentDevicePolicy();
@@ -195,7 +222,11 @@
 TEST_F(UmRealDevicePolicyProviderTest, ScatterFactorConverted) {
   SetUpExistentDevicePolicy();
   EXPECT_CALL(mock_device_policy_, GetScatterFactorInSeconds(_))
+#if USE_DBUS
       .Times(2)
+#else
+      .Times(1)
+#endif  // USE_DBUS
       .WillRepeatedly(DoAll(SetArgPointee<0>(1234), Return(true)));
   EXPECT_TRUE(provider_->Init());
   loop_.RunOnce(false);
@@ -207,7 +238,11 @@
 TEST_F(UmRealDevicePolicyProviderTest, NegativeScatterFactorIgnored) {
   SetUpExistentDevicePolicy();
   EXPECT_CALL(mock_device_policy_, GetScatterFactorInSeconds(_))
+#if USE_DBUS
       .Times(2)
+#else
+      .Times(1)
+#endif  // USE_DBUS
       .WillRepeatedly(DoAll(SetArgPointee<0>(-1), Return(true)));
   EXPECT_TRUE(provider_->Init());
   loop_.RunOnce(false);
@@ -218,7 +253,11 @@
 TEST_F(UmRealDevicePolicyProviderTest, AllowedTypesConverted) {
   SetUpExistentDevicePolicy();
   EXPECT_CALL(mock_device_policy_, GetAllowedConnectionTypesForUpdate(_))
+#if USE_DBUS
       .Times(2)
+#else
+      .Times(1)
+#endif  // USE_DBUS
       .WillRepeatedly(DoAll(
           SetArgPointee<0>(set<string>{"bluetooth", "wifi", "not-a-type"}),
           Return(true)));
diff --git a/update_manager/real_shill_provider.cc b/update_manager/real_shill_provider.cc
index 7938180..2c58a7e 100644
--- a/update_manager/real_shill_provider.cc
+++ b/update_manager/real_shill_provider.cc
@@ -24,39 +24,13 @@
 #include <shill/dbus-constants.h>
 #include <shill/dbus-proxies.h>
 
+using chromeos_update_engine::connection_utils::ParseConnectionType;
 using org::chromium::flimflam::ManagerProxyInterface;
 using org::chromium::flimflam::ServiceProxyInterface;
 using std::string;
 
 namespace chromeos_update_manager {
 
-ConnectionType RealShillProvider::ParseConnectionType(const string& type_str) {
-  if (type_str == shill::kTypeEthernet) {
-    return ConnectionType::kEthernet;
-  } else if (type_str == shill::kTypeWifi) {
-    return ConnectionType::kWifi;
-  } else if (type_str == shill::kTypeWimax) {
-    return ConnectionType::kWimax;
-  } else if (type_str == shill::kTypeBluetooth) {
-    return ConnectionType::kBluetooth;
-  } else if (type_str == shill::kTypeCellular) {
-    return ConnectionType::kCellular;
-  }
-  return ConnectionType::kUnknown;
-}
-
-ConnectionTethering RealShillProvider::ParseConnectionTethering(
-    const string& tethering_str) {
-  if (tethering_str == shill::kTetheringNotDetectedState) {
-    return ConnectionTethering::kNotDetected;
-  } else if (tethering_str == shill::kTetheringSuspectedState) {
-    return ConnectionTethering::kSuspected;
-  } else if (tethering_str == shill::kTetheringConfirmedState) {
-    return ConnectionTethering::kConfirmed;
-  }
-  return ConnectionTethering::kUnknown;
-}
-
 bool RealShillProvider::Init() {
   ManagerProxyInterface* manager_proxy = shill_proxy_->GetManagerProxy();
   if (!manager_proxy)
@@ -157,7 +131,8 @@
     // If the property doesn't contain a string value, the empty string will
     // become kUnknown.
     var_conn_tethering_.SetValue(
-        ParseConnectionTethering(prop_tethering->second.TryGet<string>()));
+        chromeos_update_engine::connection_utils::ParseConnectionTethering(
+            prop_tethering->second.TryGet<string>()));
   }
 
   // Get the connection type.
@@ -175,7 +150,8 @@
         LOG(ERROR) << "No PhysicalTechnology property found for a VPN"
                    << " connection (service: " << default_service_path_.value()
                    << "). Using default kUnknown value.";
-        var_conn_type_.SetValue(ConnectionType::kUnknown);
+        var_conn_type_.SetValue(
+            chromeos_update_engine::ConnectionType::kUnknown);
       } else {
         var_conn_type_.SetValue(
             ParseConnectionType(prop_physical->second.TryGet<string>()));
diff --git a/update_manager/real_shill_provider.h b/update_manager/real_shill_provider.h
index dbd6fc5..e7708c8 100644
--- a/update_manager/real_shill_provider.h
+++ b/update_manager/real_shill_provider.h
@@ -21,6 +21,7 @@
 // update engine's connection_manager.  We need to make sure to deprecate use of
 // connection manager when the time comes.
 
+#include <memory>
 #include <string>
 
 #include <base/time/time.h>
@@ -49,11 +50,11 @@
     return &var_is_connected_;
   }
 
-  Variable<ConnectionType>* var_conn_type() override {
+  Variable<chromeos_update_engine::ConnectionType>* var_conn_type() override {
     return &var_conn_type_;
   }
 
-  Variable<ConnectionTethering>* var_conn_tethering() override {
+  Variable<chromeos_update_engine::ConnectionTethering>* var_conn_tethering() override {
     return &var_conn_tethering_;
   }
 
@@ -61,11 +62,6 @@
     return &var_conn_last_changed_;
   }
 
-  // Helper methods for converting shill strings into symbolic values.
-  static ConnectionType ParseConnectionType(const std::string& type_str);
-  static ConnectionTethering ParseConnectionTethering(
-      const std::string& tethering_str);
-
  private:
   // A handler for ManagerProxy.PropertyChanged signal.
   void OnManagerPropertyChanged(const std::string& name,
@@ -83,17 +79,18 @@
   // The current default service path, if connected. "/" means not connected.
   dbus::ObjectPath default_service_path_{"uninitialized"};
 
-  // The mockable interface to access the shill DBus proxies, owned by the
-  // caller.
-  chromeos_update_engine::ShillProxyInterface* shill_proxy_;
+  // The mockable interface to access the shill DBus proxies.
+  std::unique_ptr<chromeos_update_engine::ShillProxyInterface> shill_proxy_;
 
   // A clock abstraction (mockable).
   chromeos_update_engine::ClockInterface* const clock_;
 
   // The provider's variables.
   AsyncCopyVariable<bool> var_is_connected_{"is_connected"};
-  AsyncCopyVariable<ConnectionType> var_conn_type_{"conn_type"};
-  AsyncCopyVariable<ConnectionTethering> var_conn_tethering_{"conn_tethering"};
+  AsyncCopyVariable<chromeos_update_engine::ConnectionType> var_conn_type_{
+      "conn_type"};
+  AsyncCopyVariable<chromeos_update_engine::ConnectionTethering>
+      var_conn_tethering_{"conn_tethering"};
   AsyncCopyVariable<base::Time> var_conn_last_changed_{"conn_last_changed"};
 
   DISALLOW_COPY_AND_ASSIGN(RealShillProvider);
diff --git a/update_manager/real_shill_provider_unittest.cc b/update_manager/real_shill_provider_unittest.cc
index 2fa0628..e821dc7 100644
--- a/update_manager/real_shill_provider_unittest.cc
+++ b/update_manager/real_shill_provider_unittest.cc
@@ -35,6 +35,8 @@
 
 using base::Time;
 using base::TimeDelta;
+using chromeos_update_engine::ConnectionTethering;
+using chromeos_update_engine::ConnectionType;
 using chromeos_update_engine::FakeClock;
 using org::chromium::flimflam::ManagerProxyMock;
 using org::chromium::flimflam::ServiceProxyMock;
@@ -65,9 +67,10 @@
   void SetUp() override {
     fake_clock_.SetWallclockTime(InitTime());
     loop_.SetAsCurrent();
-    provider_.reset(new RealShillProvider(&fake_shill_proxy_, &fake_clock_));
+    fake_shill_proxy_ = new chromeos_update_engine::FakeShillProxy();
+    provider_.reset(new RealShillProvider(fake_shill_proxy_, &fake_clock_));
 
-    ManagerProxyMock* manager_proxy_mock = fake_shill_proxy_.GetManagerProxy();
+    ManagerProxyMock* manager_proxy_mock = fake_shill_proxy_->GetManagerProxy();
 
     // The PropertyChanged signal should be subscribed to.
     MOCK_SIGNAL_HANDLER_EXPECT_SIGNAL_HANDLER(
@@ -202,7 +205,7 @@
 
   brillo::FakeMessageLoop loop_{nullptr};
   FakeClock fake_clock_;
-  chromeos_update_engine::FakeShillProxy fake_shill_proxy_;
+  chromeos_update_engine::FakeShillProxy* fake_shill_proxy_;
 
   // The registered signal handler for the signal Manager.PropertyChanged.
   chromeos_update_engine::dbus_test_utils::MockSignalHandler<
@@ -213,7 +216,7 @@
 
 void UmRealShillProviderTest::SetManagerReply(const char* default_service,
                                               bool reply_succeeds) {
-  ManagerProxyMock* manager_proxy_mock = fake_shill_proxy_.GetManagerProxy();
+  ManagerProxyMock* manager_proxy_mock = fake_shill_proxy_->GetManagerProxy();
   if (!reply_succeeds) {
     EXPECT_CALL(*manager_proxy_mock, GetProperties(_, _, _))
         .WillOnce(Return(false));
@@ -258,7 +261,7 @@
   EXPECT_CALL(*service_proxy_mock, GetProperties(_, _, _))
       .WillOnce(DoAll(SetArgPointee<0>(reply_dict), Return(true)));
 
-  fake_shill_proxy_.SetServiceForPath(
+  fake_shill_proxy_->SetServiceForPath(
       dbus::ObjectPath(service_path),
       brillo::make_unique_ptr(service_proxy_mock));
   return service_proxy_mock;
@@ -287,7 +290,7 @@
 
 // Ensure that a service path property including a different type is ignored.
 TEST_F(UmRealShillProviderTest, InvalidServicePathType) {
-  ManagerProxyMock* manager_proxy_mock = fake_shill_proxy_.GetManagerProxy();
+  ManagerProxyMock* manager_proxy_mock = fake_shill_proxy_->GetManagerProxy();
   brillo::VariantDictionary reply_dict;
   reply_dict[shill::kDefaultServiceProperty] = "/not/an/object/path";
   EXPECT_CALL(*manager_proxy_mock, GetProperties(_, _, _))
diff --git a/update_manager/real_system_provider.cc b/update_manager/real_system_provider.cc
index 395bf83..9b968ca 100644
--- a/update_manager/real_system_provider.cc
+++ b/update_manager/real_system_provider.cc
@@ -20,7 +20,9 @@
 #include <base/callback.h>
 #include <base/logging.h>
 #include <base/time/time.h>
+#if USE_LIBCROS
 #include <libcros/dbus-proxies.h>
+#endif
 
 #include "update_engine/common/utils.h"
 #include "update_engine/update_manager/generic_variables.h"
diff --git a/update_manager/real_system_provider_unittest.cc b/update_manager/real_system_provider_unittest.cc
index 2a56f8b..821a6cc 100644
--- a/update_manager/real_system_provider_unittest.cc
+++ b/update_manager/real_system_provider_unittest.cc
@@ -20,37 +20,48 @@
 
 #include <base/time/time.h>
 #include <brillo/make_unique_ptr.h>
+#include <gmock/gmock.h>
 #include <gtest/gtest.h>
 
-#include "libcros/dbus-proxy-mocks.h"
 #include "update_engine/common/fake_boot_control.h"
 #include "update_engine/common/fake_hardware.h"
 #include "update_engine/update_manager/umtest_utils.h"
+#if USE_LIBCROS
+#include "libcros/dbus-proxies.h"
+#include "libcros/dbus-proxy-mocks.h"
 
 using org::chromium::LibCrosServiceInterfaceProxyMock;
+#endif  // USE_LIBCROS
 using std::unique_ptr;
 using testing::_;
 using testing::DoAll;
 using testing::Return;
 using testing::SetArgPointee;
 
+#if USE_LIBCROS
 namespace {
 const char kRequiredPlatformVersion[] ="1234.0.0";
 }  // namespace
+#endif  // USE_LIBCROS
 
 namespace chromeos_update_manager {
 
 class UmRealSystemProviderTest : public ::testing::Test {
  protected:
   void SetUp() override {
+#if USE_LIBCROS
     libcros_proxy_mock_.reset(new LibCrosServiceInterfaceProxyMock());
     ON_CALL(*libcros_proxy_mock_,
             GetKioskAppRequiredPlatformVersion(_, _, _))
         .WillByDefault(
             DoAll(SetArgPointee<0>(kRequiredPlatformVersion), Return(true)));
 
-    provider_.reset(new RealSystemProvider(&fake_hardware_, &fake_boot_control_,
-                                           libcros_proxy_mock_.get()));
+    provider_.reset(new RealSystemProvider(
+        &fake_hardware_, &fake_boot_control_, libcros_proxy_mock_.get()));
+#else
+    provider_.reset(
+        new RealSystemProvider(&fake_hardware_, &fake_boot_control_, nullptr));
+#endif  // USE_LIBCROS
     EXPECT_TRUE(provider_->Init());
   }
 
@@ -58,7 +69,9 @@
   chromeos_update_engine::FakeBootControl fake_boot_control_;
   unique_ptr<RealSystemProvider> provider_;
 
-  std::unique_ptr<LibCrosServiceInterfaceProxyMock> libcros_proxy_mock_;
+#if USE_LIBCROS
+  unique_ptr<LibCrosServiceInterfaceProxyMock> libcros_proxy_mock_;
+#endif  // USE_LIBCROS
 };
 
 TEST_F(UmRealSystemProviderTest, InitTest) {
diff --git a/update_manager/shill_provider.h b/update_manager/shill_provider.h
index b40f255..e6f4628 100644
--- a/update_manager/shill_provider.h
+++ b/update_manager/shill_provider.h
@@ -19,27 +19,12 @@
 
 #include <base/time/time.h>
 
+#include "update_engine/connection_utils.h"
 #include "update_engine/update_manager/provider.h"
 #include "update_engine/update_manager/variable.h"
 
 namespace chromeos_update_manager {
 
-enum class ConnectionType {
-  kEthernet,
-  kWifi,
-  kWimax,
-  kBluetooth,
-  kCellular,
-  kUnknown
-};
-
-enum class ConnectionTethering {
-  kNotDetected,
-  kSuspected,
-  kConfirmed,
-  kUnknown,
-};
-
 // Provider for networking related information.
 class ShillProvider : public Provider {
  public:
@@ -50,11 +35,12 @@
 
   // A variable returning the current network connection type. Unknown if not
   // connected.
-  virtual Variable<ConnectionType>* var_conn_type() = 0;
+  virtual Variable<chromeos_update_engine::ConnectionType>* var_conn_type() = 0;
 
   // A variable returning the tethering mode of a network connection. Unknown if
   // not connected.
-  virtual Variable<ConnectionTethering>* var_conn_tethering() = 0;
+  virtual Variable<chromeos_update_engine::ConnectionTethering>*
+      var_conn_tethering() = 0;
 
   // A variable returning the time when network connection last changed.
   // Initialized to current time.
diff --git a/update_manager/state_factory.cc b/update_manager/state_factory.cc
index 1da3fb9..70fc80b 100644
--- a/update_manager/state_factory.cc
+++ b/update_manager/state_factory.cc
@@ -19,16 +19,27 @@
 #include <memory>
 
 #include <base/logging.h>
+#include <brillo/make_unique_ptr.h>
+#if USE_DBUS
+#include <session_manager/dbus-proxies.h>
+#endif  // USE_DBUS
 
 #include "update_engine/common/clock_interface.h"
+#if USE_DBUS
+#include "update_engine/dbus_connection.h"
+#endif  // USE_DBUS
+#include "update_engine/update_manager/fake_shill_provider.h"
 #include "update_engine/update_manager/real_config_provider.h"
 #include "update_engine/update_manager/real_device_policy_provider.h"
 #include "update_engine/update_manager/real_random_provider.h"
-#include "update_engine/update_manager/real_shill_provider.h"
 #include "update_engine/update_manager/real_state.h"
 #include "update_engine/update_manager/real_system_provider.h"
 #include "update_engine/update_manager/real_time_provider.h"
 #include "update_engine/update_manager/real_updater_provider.h"
+#if USE_SHILL
+#include "update_engine/shill_proxy.h"
+#include "update_engine/update_manager/real_shill_provider.h"
+#endif  // USE_SHILL
 
 using std::unique_ptr;
 
@@ -36,22 +47,32 @@
 
 State* DefaultStateFactory(
     policy::PolicyProvider* policy_provider,
-    chromeos_update_engine::ShillProxy* shill_proxy,
-    org::chromium::SessionManagerInterfaceProxyInterface* session_manager_proxy,
     org::chromium::LibCrosServiceInterfaceProxyInterface* libcros_proxy,
     chromeos_update_engine::SystemState* system_state) {
   chromeos_update_engine::ClockInterface* const clock = system_state->clock();
   unique_ptr<RealConfigProvider> config_provider(
       new RealConfigProvider(system_state->hardware()));
+#if USE_DBUS
+  scoped_refptr<dbus::Bus> bus =
+      chromeos_update_engine::DBusConnection::Get()->GetDBus();
   unique_ptr<RealDevicePolicyProvider> device_policy_provider(
-      new RealDevicePolicyProvider(session_manager_proxy, policy_provider));
-  unique_ptr<RealRandomProvider> random_provider(new RealRandomProvider());
+      new RealDevicePolicyProvider(
+          brillo::make_unique_ptr(
+              new org::chromium::SessionManagerInterfaceProxy(bus)),
+          policy_provider));
+#else
+  unique_ptr<RealDevicePolicyProvider> device_policy_provider(
+      new RealDevicePolicyProvider(policy_provider));
+#endif  // USE_DBUS
+#if USE_SHILL
   unique_ptr<RealShillProvider> shill_provider(
-      new RealShillProvider(shill_proxy, clock));
-  unique_ptr<RealSystemProvider> system_provider(
-      new RealSystemProvider(system_state->hardware(),
-                             system_state->boot_control(),
-                             libcros_proxy));
+      new RealShillProvider(new chromeos_update_engine::ShillProxy(), clock));
+#else
+  unique_ptr<FakeShillProvider> shill_provider(new FakeShillProvider());
+#endif  // USE_SHILL
+  unique_ptr<RealRandomProvider> random_provider(new RealRandomProvider());
+  unique_ptr<RealSystemProvider> system_provider(new RealSystemProvider(
+      system_state->hardware(), system_state->boot_control(), libcros_proxy));
   unique_ptr<RealTimeProvider> time_provider(new RealTimeProvider(clock));
   unique_ptr<RealUpdaterProvider> updater_provider(
       new RealUpdaterProvider(system_state));
@@ -59,7 +80,9 @@
   if (!(config_provider->Init() &&
         device_policy_provider->Init() &&
         random_provider->Init() &&
+#if USE_SHILL
         shill_provider->Init() &&
+#endif  // USE_SHILL
         system_provider->Init() &&
         time_provider->Init() &&
         updater_provider->Init())) {
diff --git a/update_manager/state_factory.h b/update_manager/state_factory.h
index c8db776..689684a 100644
--- a/update_manager/state_factory.h
+++ b/update_manager/state_factory.h
@@ -17,9 +17,6 @@
 #ifndef UPDATE_ENGINE_UPDATE_MANAGER_STATE_FACTORY_H_
 #define UPDATE_ENGINE_UPDATE_MANAGER_STATE_FACTORY_H_
 
-#include <session_manager/dbus-proxies.h>
-
-#include "update_engine/shill_proxy.h"
 #include "update_engine/system_state.h"
 #include "update_engine/update_manager/state.h"
 
@@ -38,8 +35,6 @@
 // to initialize.
 State* DefaultStateFactory(
     policy::PolicyProvider* policy_provider,
-    chromeos_update_engine::ShillProxy* shill_proxy,
-    org::chromium::SessionManagerInterfaceProxyInterface* session_manager_proxy,
     org::chromium::LibCrosServiceInterfaceProxyInterface* libcros_proxy,
     chromeos_update_engine::SystemState* system_state);
 
diff --git a/update_metadata.proto b/update_metadata.proto
index 222542f..454c736 100644
--- a/update_metadata.proto
+++ b/update_metadata.proto
@@ -235,6 +235,10 @@
   // associated operation blobs (in operations[i].data_offset, data_length)
   // should be stored contiguously and in the same order.
   repeated InstallOperation operations = 8;
+
+  // Whether a failure in the postinstall step for this partition should be
+  // ignored.
+  optional bool postinstall_optional = 9;
 }
 
 message DeltaArchiveManifest {
diff --git a/update_status_utils.cc b/update_status_utils.cc
index 1b2dfbc..5de3381 100644
--- a/update_status_utils.cc
+++ b/update_status_utils.cc
@@ -20,22 +20,6 @@
 
 using update_engine::UpdateStatus;
 
-namespace {
-
-const char kWeaveStatusIdle[] = "idle";
-const char kWeaveStatusCheckingForUpdate[] = "checkingForUpdate";
-const char kWeaveStatusUpdateAvailable[] = "updateAvailable";
-const char kWeaveStatusNeedPermissionToUpdate[] = "needPermissionToUpdate";
-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) {
@@ -68,36 +52,6 @@
   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::NEED_PERMISSION_TO_UPDATE:
-      return kWeaveStatusNeedPermissionToUpdate;
-    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 9d85144..30ae53b 100644
--- a/update_status_utils.h
+++ b/update_status_utils.h
@@ -25,10 +25,6 @@
 
 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/utils_android.cc b/utils_android.cc
new file mode 100644
index 0000000..38d62ea
--- /dev/null
+++ b/utils_android.cc
@@ -0,0 +1,66 @@
+//
+// 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/utils_android.h"
+
+#include <cutils/properties.h>
+#include <fs_mgr.h>
+
+using std::string;
+
+namespace chromeos_update_engine {
+
+namespace {
+
+// Open the appropriate fstab file and fallback to /fstab.device if
+// that's what's being used.
+static struct fstab* OpenFSTab() {
+  struct fstab* fstab = fs_mgr_read_fstab_default();
+  if (fstab != nullptr)
+    return fstab;
+
+  fstab = fs_mgr_read_fstab("/fstab.device");
+  return fstab;
+}
+
+}  // namespace
+
+namespace utils {
+
+bool DeviceForMountPoint(const string& mount_point, base::FilePath* device) {
+  struct fstab* fstab;
+  struct fstab_rec* record;
+
+  fstab = OpenFSTab();
+  if (fstab == nullptr) {
+    LOG(ERROR) << "Error opening fstab file.";
+    return false;
+  }
+  record = fs_mgr_get_entry_for_mount_point(fstab, mount_point.c_str());
+  if (record == nullptr) {
+    LOG(ERROR) << "Error finding " << mount_point << " entry in fstab file.";
+    fs_mgr_free_fstab(fstab);
+    return false;
+  }
+
+  *device = base::FilePath(record->blk_device);
+  fs_mgr_free_fstab(fstab);
+  return true;
+}
+
+}  // namespace utils
+
+}  // namespace chromeos_update_engine
diff --git a/utils_android.h b/utils_android.h
new file mode 100644
index 0000000..18dd8ab
--- /dev/null
+++ b/utils_android.h
@@ -0,0 +1,37 @@
+//
+// 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_UTILS_ANDROID_H_
+#define UPDATE_ENGINE_UTILS_ANDROID_H_
+
+#include <string>
+
+#include <base/files/file_util.h>
+
+namespace chromeos_update_engine {
+
+namespace utils {
+
+// Find the block device that should be mounted in the |mount_point| path and
+// store it in |device|. Returns whether a device was found on the fstab.
+bool DeviceForMountPoint(const std::string& mount_point,
+                         base::FilePath* device);
+
+}  // namespace utils
+
+}  // namespace chromeos_update_engine
+
+#endif  // UPDATE_ENGINE_UTILS_ANDROID_H_
diff --git a/weave_service.cc b/weave_service.cc
deleted file mode 100644
index 0a145e4..0000000
--- a/weave_service.cc
+++ /dev/null
@@ -1,133 +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/weave_service.h"
-
-#include <cmath>
-#include <string>
-
-#include <base/bind.h>
-#include <brillo/errors/error.h>
-#include <brillo/message_loops/message_loop.h>
-
-#include "update_engine/update_status_utils.h"
-
-using std::string;
-
-namespace {
-
-const char kWeaveComponent[] = "updater";
-const char kWeaveTrait[] = "_updater";
-
-}  // namespace
-
-namespace chromeos_update_engine {
-
-bool WeaveService::Init(DelegateInterface* delegate) {
-  delegate_ = delegate;
-  weave_service_subscription_ = weaved::Service::Connect(
-      brillo::MessageLoop::current(),
-      base::Bind(&WeaveService::OnWeaveServiceConnected,
-                 base::Unretained(this)));
-  return true;
-}
-
-void WeaveService::OnWeaveServiceConnected(
-    const std::weak_ptr<weaved::Service>& service) {
-  weave_service_ = service;
-  auto weave_service = weave_service_.lock();
-  if (!weave_service)
-    return;
-
-  weave_service->AddComponent(kWeaveComponent, {kWeaveTrait}, nullptr);
-  weave_service->AddCommandHandler(
-      kWeaveComponent, kWeaveTrait, "checkForUpdates",
-      base::Bind(&WeaveService::OnCheckForUpdates, base::Unretained(this)));
-  weave_service->AddCommandHandler(
-      kWeaveComponent, kWeaveTrait, "trackChannel",
-      base::Bind(&WeaveService::OnTrackChannel, base::Unretained(this)));
-  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_)
-    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.;
-
-  base::DictionaryValue state;
-  state.SetString("_updater.currentChannel", current_channel);
-  state.SetString("_updater.trackingChannel", tracking_channel);
-  state.SetString("_updater.status", UpdateStatusToWeaveStatus(update_status));
-  state.SetDouble("_updater.progress", progress);
-  state.SetDouble("_updater.lastUpdateCheckTimestamp",
-                  static_cast<double>(last_checked_time));
-
-  if (!weave_service->SetStateProperties(kWeaveComponent, state, nullptr)) {
-    LOG(ERROR) << "Failed to update _updater state.";
-  }
-}
-
-void WeaveService::OnCheckForUpdates(std::unique_ptr<weaved::Command> command) {
-  brillo::ErrorPtr error;
-  if (!delegate_->OnCheckForUpdates(&error)) {
-    command->AbortWithCustomError(error.get(), nullptr);
-    return;
-  }
-  command->Complete({}, nullptr);
-}
-
-void WeaveService::OnTrackChannel(std::unique_ptr<weaved::Command> command) {
-  string channel = command->GetParameter<string>("channel");
-  brillo::ErrorPtr error;
-  if (!delegate_->OnTrackChannel(channel, &error)) {
-    command->AbortWithCustomError(error.get(), nullptr);
-    return;
-  }
-  command->Complete({}, nullptr);
-}
-
-}  // namespace chromeos_update_engine
diff --git a/weave_service.h b/weave_service.h
deleted file mode 100644
index 5a3aff3..0000000
--- a/weave_service.h
+++ /dev/null
@@ -1,66 +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.
-//
-
-#ifndef UPDATE_ENGINE_WEAVE_SERVICE_H_
-#define UPDATE_ENGINE_WEAVE_SERVICE_H_
-
-#include <memory>
-#include <string>
-
-#include <base/memory/weak_ptr.h>
-#include <libweaved/command.h>
-#include <libweaved/service.h>
-
-#include "update_engine/weave_service_interface.h"
-
-namespace chromeos_update_engine {
-
-class WeaveService : public WeaveServiceInterface {
- public:
-  WeaveService() = default;
-  ~WeaveService() override = default;
-
-  bool Init(DelegateInterface* delegate);
-
-  // 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;
-  void SendPayloadApplicationComplete(ErrorCode error_code) 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
-  // command is received and dispatch the synchronous call to the |delegate_|.
-  void OnCheckForUpdates(std::unique_ptr<weaved::Command> cmd);
-  void OnTrackChannel(std::unique_ptr<weaved::Command> cmd);
-
-  WeaveServiceInterface::DelegateInterface* delegate_{nullptr};
-
-  std::unique_ptr<weaved::Service::Subscription> weave_service_subscription_;
-  std::weak_ptr<weaved::Service> weave_service_;
-};
-
-}  // namespace chromeos_update_engine
-
-#endif  // UPDATE_ENGINE_WEAVE_SERVICE_H_
diff --git a/weave_service_factory.cc b/weave_service_factory.cc
deleted file mode 100644
index 24b9b79..0000000
--- a/weave_service_factory.cc
+++ /dev/null
@@ -1,40 +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/weave_service_factory.h"
-
-#if USE_WEAVE
-#include "update_engine/weave_service.h"
-#endif
-
-namespace chromeos_update_engine {
-
-std::unique_ptr<WeaveServiceInterface> ConstructWeaveService(
-    WeaveServiceInterface::DelegateInterface* delegate) {
-  std::unique_ptr<WeaveServiceInterface> result;
-  if (!delegate)
-    return result;
-
-#if USE_WEAVE
-  WeaveService* weave_service = new WeaveService();
-  result.reset(weave_service);
-  if (!weave_service->Init(delegate))
-    result.reset();
-#endif
-  return result;
-}
-
-}  // namespace chromeos_update_engine
diff --git a/weave_service_factory.h b/weave_service_factory.h
deleted file mode 100644
index 7b129ab..0000000
--- a/weave_service_factory.h
+++ /dev/null
@@ -1,35 +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.
-//
-
-#ifndef UPDATE_ENGINE_WEAVE_SERVICE_FACTORY_H_
-#define UPDATE_ENGINE_WEAVE_SERVICE_FACTORY_H_
-
-#include <memory>
-
-#include <base/memory/ref_counted.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(
-    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
deleted file mode 100644
index a7e603e..0000000
--- a/weave_service_interface.h
+++ /dev/null
@@ -1,62 +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.
-//
-
-#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"
-#include "update_engine/service_observer_interface.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 ServiceObserverInterface {
- 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;
-
- 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
deleted file mode 100644
index 52b1a55..0000000
--- a/weaved/traits/updater.json
+++ /dev/null
@@ -1,52 +0,0 @@
-{
-  "_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"
-      }
-    }
-  }
-}