diff options
-rw-r--r-- | Android.bp | 20 | ||||
-rw-r--r-- | Android.mk | 2 | ||||
-rw-r--r-- | recovery.cpp | 65 | ||||
-rw-r--r-- | tests/Android.mk | 23 | ||||
-rw-r--r-- | tests/unit/commands_test.cpp | 20 | ||||
-rw-r--r-- | updater/Android.bp | 71 | ||||
-rw-r--r-- | updater/Android.mk | 35 | ||||
-rw-r--r-- | updater/commands.cpp | 42 | ||||
-rw-r--r-- | updater/include/private/commands.h | 52 |
9 files changed, 227 insertions, 103 deletions
diff --git a/Android.bp b/Android.bp index 5677b6c2a..e97f71d70 100644 --- a/Android.bp +++ b/Android.bp @@ -127,19 +127,20 @@ cc_defaults { ], shared_libs: [ + "android.hardware.health@2.0", "libbase", "libbootloader_message", "libcrypto", - "libcrypto_utils", "libcutils", "libext4_utils", "libfs_mgr", "libfusesideload", "libhidl-gen-utils", + "libhidlbase", + "libhidltransport", "liblog", "libpng", "libselinux", - "libsparse", "libtinyxml2", "libutils", "libz", @@ -151,20 +152,11 @@ cc_defaults { "libminui", "libverifier", "libotautil", + + // external dependencies + "libhealthhalutils", "libvintf_recovery", "libvintf", - - // TODO(b/80132328): Remove the dependency on static health HAL. - "libhealthd.default", - "android.hardware.health@2.0-impl", - "android.hardware.health@2.0", - "android.hardware.health@1.0", - "android.hardware.health@1.0-convert", - "libhealthstoragedefault", - "libhidltransport", - "libhidlbase", - "libhwbinder_noltopgo", - "libbatterymonitor", ], } diff --git a/Android.mk b/Android.mk index 9888f8616..7d13f4cc4 100644 --- a/Android.mk +++ b/Android.mk @@ -14,7 +14,7 @@ LOCAL_PATH := $(call my-dir) -# Needed by build/make/core/Makefile. +# Needed by build/make/core/Makefile. Must be consistent with the value in Android.bp. RECOVERY_API_VERSION := 3 RECOVERY_FSTAB_VERSION := 2 diff --git a/recovery.cpp b/recovery.cpp index 24f105da0..01bd83b5e 100644 --- a/recovery.cpp +++ b/recovery.cpp @@ -49,7 +49,7 @@ #include <android-base/unique_fd.h> #include <bootloader_message/bootloader_message.h> #include <cutils/properties.h> /* for property_list */ -#include <health2/Health.h> +#include <healthhalutils/HealthHalUtils.h> #include <ziparchive/zip_archive.h> #include "adb_install.h" @@ -879,42 +879,29 @@ void ui_print(const char* format, ...) { static bool is_battery_ok(int* required_battery_level) { using android::hardware::health::V1_0::BatteryStatus; + using android::hardware::health::V2_0::get_health_service; + using android::hardware::health::V2_0::IHealth; using android::hardware::health::V2_0::Result; using android::hardware::health::V2_0::toString; - using android::hardware::health::V2_0::implementation::Health; - - struct healthd_config healthd_config = { - .batteryStatusPath = android::String8(android::String8::kEmptyString), - .batteryHealthPath = android::String8(android::String8::kEmptyString), - .batteryPresentPath = android::String8(android::String8::kEmptyString), - .batteryCapacityPath = android::String8(android::String8::kEmptyString), - .batteryVoltagePath = android::String8(android::String8::kEmptyString), - .batteryTemperaturePath = android::String8(android::String8::kEmptyString), - .batteryTechnologyPath = android::String8(android::String8::kEmptyString), - .batteryCurrentNowPath = android::String8(android::String8::kEmptyString), - .batteryCurrentAvgPath = android::String8(android::String8::kEmptyString), - .batteryChargeCounterPath = android::String8(android::String8::kEmptyString), - .batteryFullChargePath = android::String8(android::String8::kEmptyString), - .batteryCycleCountPath = android::String8(android::String8::kEmptyString), - .energyCounter = nullptr, - .boot_min_cap = 0, - .screen_on = nullptr - }; - auto health = - android::hardware::health::V2_0::implementation::Health::initInstance(&healthd_config); + android::sp<IHealth> health = get_health_service(); static constexpr int BATTERY_READ_TIMEOUT_IN_SEC = 10; int wait_second = 0; while (true) { auto charge_status = BatteryStatus::UNKNOWN; - health - ->getChargeStatus([&charge_status](auto res, auto out_status) { - if (res == Result::SUCCESS) { - charge_status = out_status; - } - }) - .isOk(); // should not have transport error + + if (health == nullptr) { + LOG(WARNING) << "no health implementation is found, assuming defaults"; + } else { + health + ->getChargeStatus([&charge_status](auto res, auto out_status) { + if (res == Result::SUCCESS) { + charge_status = out_status; + } + }) + .isOk(); // should not have transport error + } // Treat unknown status as charged. bool charged = (charge_status != BatteryStatus::DISCHARGING && @@ -922,15 +909,17 @@ static bool is_battery_ok(int* required_battery_level) { Result res = Result::UNKNOWN; int32_t capacity = INT32_MIN; - health - ->getCapacity([&res, &capacity](auto out_res, auto out_capacity) { - res = out_res; - capacity = out_capacity; - }) - .isOk(); // should not have transport error - - ui_print("charge_status %d, charged %d, status %s, capacity %" PRId32 "\n", charge_status, - charged, toString(res).c_str(), capacity); + if (health != nullptr) { + health + ->getCapacity([&res, &capacity](auto out_res, auto out_capacity) { + res = out_res; + capacity = out_capacity; + }) + .isOk(); // should not have transport error + } + + LOG(INFO) << "charge_status " << toString(charge_status) << ", charged " << charged + << ", status " << toString(res) << ", capacity " << capacity; // At startup, the battery drivers in devices like N5X/N6P take some time to load // the battery profile. Before the load finishes, it reports value 50 as a fake // capacity. BATTERY_READ_TIMEOUT_IN_SEC is set that the battery drivers are expected diff --git a/tests/Android.mk b/tests/Android.mk index b6f5b451f..b59da8045 100644 --- a/tests/Android.mk +++ b/tests/Android.mk @@ -127,13 +127,11 @@ tune2fs_static_libraries := \ libupdater_static_libraries := \ libupdater \ libapplypatch \ + libbootloader_message \ libbspatch \ libedify \ - libziparchive \ - libotautil \ - libbootloader_message \ - libutils \ libotafault \ + libotautil \ libext4_utils \ libfec \ libfec_rs \ @@ -144,28 +142,18 @@ libupdater_static_libraries := \ libselinux \ libsparse \ libsquashfs_utils \ + libbrotli \ libbz \ + libziparchive \ libz \ libbase \ libcrypto \ libcrypto_utils \ libcutils \ + libutils \ libtune2fs \ - libbrotli \ $(tune2fs_static_libraries) -health_hal_static_libraries := \ - android.hardware.health@2.0-impl \ - android.hardware.health@2.0 \ - android.hardware.health@1.0 \ - android.hardware.health@1.0-convert \ - libhealthstoragedefault \ - libhidltransport \ - libhidlbase \ - libhwbinder_noltopgo \ - libvndksupport \ - libbatterymonitor - librecovery_static_libraries := \ librecovery \ libbootloader_message \ @@ -175,7 +163,6 @@ librecovery_static_libraries := \ libminui \ libverifier \ libotautil \ - $(health_hal_static_libraries) \ libcrypto_utils \ libcrypto \ libext4_utils \ diff --git a/tests/unit/commands_test.cpp b/tests/unit/commands_test.cpp index 9679a9e73..19841d676 100644 --- a/tests/unit/commands_test.cpp +++ b/tests/unit/commands_test.cpp @@ -333,6 +333,25 @@ TEST(CommandsTest, Parse_ZERO) { ASSERT_EQ(PatchInfo(), command.patch()); } +TEST(CommandsTest, Parse_COMPUTE_HASH_TREE) { + const std::string input{ "compute_hash_tree 2,0,1 2,3,4 sha1 unknown-salt unknown-root-hash" }; + std::string err; + Command command = Command::Parse(input, 9, &err); + ASSERT_TRUE(command); + + ASSERT_EQ(Command::Type::COMPUTE_HASH_TREE, command.type()); + ASSERT_EQ(9, command.index()); + ASSERT_EQ(input, command.cmdline()); + + HashTreeInfo expected_info(RangeSet({ { 0, 1 } }), RangeSet({ { 3, 4 } }), "sha1", "unknown-salt", + "unknown-root-hash"); + ASSERT_EQ(expected_info, command.hash_tree_info()); + ASSERT_EQ(TargetInfo(), command.target()); + ASSERT_EQ(SourceInfo(), command.source()); + ASSERT_EQ(StashInfo(), command.stash()); + ASSERT_EQ(PatchInfo(), command.patch()); +} + TEST(CommandsTest, Parse_InvalidNumberOfArgs) { Command::abort_allowed_ = true; @@ -341,6 +360,7 @@ TEST(CommandsTest, Parse_InvalidNumberOfArgs) { std::vector<std::string> inputs{ "abort foo", "bsdiff", + "compute_hash_tree, 2,0,1 2,0,1 unknown-algorithm unknown-salt", "erase", "erase 4,3,5,10,12 hash1", "free", diff --git a/updater/Android.bp b/updater/Android.bp new file mode 100644 index 000000000..9a36ebbb7 --- /dev/null +++ b/updater/Android.bp @@ -0,0 +1,71 @@ +// Copyright (C) 2018 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. + +cc_library_static { + name: "libupdater", + + defaults: [ + "recovery_defaults", + ], + + srcs: [ + "blockimg.cpp", + "commands.cpp", + "install.cpp", + ], + + include_dirs: [ + "external/e2fsprogs/misc", + ], + + export_include_dirs: [ + "include", + ], + + static_libs: [ + "libapplypatch", + "libbootloader_message", + "libbspatch", + "libedify", + "libotafault", + "libotautil", + "libext4_utils", + "libfec", + "libfec_rs", + "libverity_tree", + "libfs_mgr", + "libgtest_prod", + "liblog", + "libselinux", + "libsparse", + "libsquashfs_utils", + "libbrotli", + "libbz", + "libziparchive", + "libz", + "libbase", + "libcrypto", + "libcrypto_utils", + "libcutils", + "libutils", + "libtune2fs", + + "libext2_com_err", + "libext2_blkid", + "libext2_quota", + "libext2_uuid", + "libext2_e2p", + "libext2fs", + ], +} diff --git a/updater/Android.mk b/updater/Android.mk index 78d0bd451..5478a7df6 100644 --- a/updater/Android.mk +++ b/updater/Android.mk @@ -25,12 +25,10 @@ tune2fs_static_libraries := \ updater_common_static_libraries := \ libapplypatch \ libbootloader_message \ + libbspatch \ libedify \ libotafault \ libotautil \ - libbspatch \ - libziparchive \ - libutils \ libext4_utils \ libfec \ libfec_rs \ @@ -41,43 +39,18 @@ updater_common_static_libraries := \ libselinux \ libsparse \ libsquashfs_utils \ + libbrotli \ libbz \ + libziparchive \ libz \ libbase \ libcrypto \ libcrypto_utils \ libcutils \ + libutils \ libtune2fs \ - libbrotli \ $(tune2fs_static_libraries) -# libupdater (static library) -# =============================== -include $(CLEAR_VARS) - -LOCAL_MODULE := libupdater - -LOCAL_SRC_FILES := \ - commands.cpp \ - install.cpp \ - blockimg.cpp - -LOCAL_C_INCLUDES := \ - $(LOCAL_PATH)/include \ - external/e2fsprogs/misc - -LOCAL_CFLAGS := \ - -Wall \ - -Werror - -LOCAL_EXPORT_C_INCLUDE_DIRS := \ - $(LOCAL_PATH)/include - -LOCAL_STATIC_LIBRARIES := \ - $(updater_common_static_libraries) - -include $(BUILD_STATIC_LIBRARY) - # updater (static executable) # =============================== include $(CLEAR_VARS) diff --git a/updater/commands.cpp b/updater/commands.cpp index 15a787c51..4a90ea873 100644 --- a/updater/commands.cpp +++ b/updater/commands.cpp @@ -31,6 +31,14 @@ using namespace std::string_literals; bool Command::abort_allowed_ = false; +Command::Command(Type type, size_t index, std::string cmdline, HashTreeInfo hash_tree_info) + : type_(type), + index_(index), + cmdline_(std::move(cmdline)), + hash_tree_info_(std::move(hash_tree_info)) { + CHECK(type == Type::COMPUTE_HASH_TREE); +} + Command::Type Command::ParseType(const std::string& type_str) { if (type_str == "abort") { if (!abort_allowed_) { @@ -177,7 +185,6 @@ Command Command::Parse(const std::string& line, size_t index, std::string* err) SourceInfo source_info; StashInfo stash_info; - // TODO(xunchang) add the parse code of compute_hash_tree if (op == Type::ZERO || op == Type::NEW || op == Type::ERASE) { // zero/new/erase <rangeset> if (pos + 1 != tokens.size()) { @@ -255,6 +262,39 @@ Command Command::Parse(const std::string& line, size_t index, std::string* err) tokens.size() - pos); return {}; } + } else if (op == Type::COMPUTE_HASH_TREE) { + // <hash_tree_ranges> <source_ranges> <hash_algorithm> <salt_hex> <root_hash> + if (pos + 5 != tokens.size()) { + *err = android::base::StringPrintf("invalid number of args: %zu (expected 5)", + tokens.size() - pos); + return {}; + } + + // Expects the hash_tree data to be contiguous. + RangeSet hash_tree_ranges = RangeSet::Parse(tokens[pos++]); + if (!hash_tree_ranges || hash_tree_ranges.size() != 1) { + *err = "invalid hash tree ranges in: " + line; + return {}; + } + + RangeSet source_ranges = RangeSet::Parse(tokens[pos++]); + if (!source_ranges) { + *err = "invalid source ranges in: " + line; + return {}; + } + + std::string hash_algorithm = tokens[pos++]; + std::string salt_hex = tokens[pos++]; + std::string root_hash = tokens[pos++]; + if (hash_algorithm.empty() || salt_hex.empty() || root_hash.empty()) { + *err = "invalid hash tree arguments in " + line; + return {}; + } + + HashTreeInfo hash_tree_info(std::move(hash_tree_ranges), std::move(source_ranges), + std::move(hash_algorithm), std::move(salt_hex), + std::move(root_hash)); + return Command(op, index, line, std::move(hash_tree_info)); } else { *err = "invalid op"; return {}; diff --git a/updater/include/private/commands.h b/updater/include/private/commands.h index 7f9dc79f4..85b52883b 100644 --- a/updater/include/private/commands.h +++ b/updater/include/private/commands.h @@ -166,6 +166,50 @@ class PatchInfo { size_t length_{ 0 }; }; +// The arguments to build a hash tree from blocks on the block device. +class HashTreeInfo { + public: + HashTreeInfo() = default; + + HashTreeInfo(RangeSet hash_tree_ranges, RangeSet source_ranges, std::string hash_algorithm, + std::string salt_hex, std::string root_hash) + : hash_tree_ranges_(std::move(hash_tree_ranges)), + source_ranges_(std::move(source_ranges)), + hash_algorithm_(std::move(hash_algorithm)), + salt_hex_(std::move(salt_hex)), + root_hash_(std::move(root_hash)) {} + + const RangeSet& hash_tree_ranges() const { + return hash_tree_ranges_; + } + const RangeSet& source_ranges() const { + return source_ranges_; + } + + const std::string& hash_algorithm() const { + return hash_algorithm_; + } + const std::string& salt_hex() const { + return salt_hex_; + } + const std::string& root_hash() const { + return root_hash_; + } + + bool operator==(const HashTreeInfo& other) const { + return hash_tree_ranges_ == other.hash_tree_ranges_ && source_ranges_ == other.source_ranges_ && + hash_algorithm_ == other.hash_algorithm_ && salt_hex_ == other.salt_hex_ && + root_hash_ == other.root_hash_; + } + + private: + RangeSet hash_tree_ranges_; + RangeSet source_ranges_; + std::string hash_algorithm_; + std::string salt_hex_; + std::string root_hash_; +}; + // Command class holds the info for an update command that performs block-based OTA (BBOTA). Each // command consists of one or several args, namely TargetInfo, SourceInfo, StashInfo and PatchInfo. // The currently used BBOTA version is v4. @@ -248,6 +292,8 @@ class Command { source_(std::move(source)), stash_(std::move(stash)) {} + Command(Type type, size_t index, std::string cmdline, HashTreeInfo hash_tree_info); + // Parses the given command 'line' into a Command object and returns it. The 'index' is specified // by the caller to index the object. On parsing error, it returns an empty Command object that // evaluates to false, and the specific error message will be set in 'err'. @@ -284,6 +330,10 @@ class Command { return stash_; } + const HashTreeInfo& hash_tree_info() const { + return hash_tree_info_; + } + constexpr explicit operator bool() const { return type_ != Type::LAST; } @@ -325,6 +375,8 @@ class Command { // The stash info. Only meaningful for STASH and FREE commands. Note that although SourceInfo may // also load data from stash, such info will be owned and managed by SourceInfo (i.e. in source_). StashInfo stash_; + // The hash_tree info. Only meaningful for COMPUTE_HASH_TREE. + HashTreeInfo hash_tree_info_; }; std::ostream& operator<<(std::ostream& os, const Command& command); |