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(
- ¶ms,
- 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(¶ms,
+ 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, ×tamp));
- 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(¶ms,
- fake_update_response_.GetUpdateResponse(),
- -1,
- false, // ping_only
- ErrorCode::kSuccess,
- metrics::CheckResult::kUpdateAvailable,
- metrics::CheckReaction::kUpdating,
- metrics::DownloadErrorCode::kUnset,
- &response,
- nullptr));
+ ASSERT_TRUE(TestUpdateCheck(¶ms,
+ 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(
- ¶ms,
- 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(¶ms,
+ 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,
- ¤t_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"
- }
- }
- }
-}