Merge "better document ifc_{add,del}_address return code"
diff --git a/adb/Android.bp b/adb/Android.bp
index 2f9c8fc..170053b 100644
--- a/adb/Android.bp
+++ b/adb/Android.bp
@@ -422,14 +422,6 @@
"liblog",
],
- product_variables: {
- debuggable: {
- required: [
- "remount",
- ],
- },
- },
-
target: {
android: {
srcs: [
@@ -437,7 +429,6 @@
"daemon/framebuffer_service.cpp",
"daemon/mdns.cpp",
"daemon/reboot_service.cpp",
- "daemon/remount_service.cpp",
"daemon/restart_service.cpp",
"daemon/set_verity_enable_state_service.cpp",
],
diff --git a/adb/daemon/main.cpp b/adb/daemon/main.cpp
index e5a4917..9ebab74 100644
--- a/adb/daemon/main.cpp
+++ b/adb/daemon/main.cpp
@@ -248,6 +248,12 @@
prop_port = android::base::GetProperty("persist.adb.tcp.port", "");
}
+#if !defined(__ANDROID__)
+ if (prop_port.empty() && getenv("ADBD_PORT")) {
+ prop_port = getenv("ADBD_PORT");
+ }
+#endif
+
int port;
if (sscanf(prop_port.c_str(), "%d", &port) == 1 && port > 0) {
D("using port=%d", port);
diff --git a/adb/daemon/remount_service.cpp b/adb/daemon/remount_service.cpp
deleted file mode 100644
index 6bd7855..0000000
--- a/adb/daemon/remount_service.cpp
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2008 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 <errno.h>
-#include <fcntl.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <unistd.h>
-
-#include <string>
-
-#include "adb.h"
-#include "adb_io.h"
-#include "adb_unique_fd.h"
-
-static constexpr char kRemountCmd[] = "/system/bin/remount";
-
-static bool do_remount(int fd, const std::string& cmd) {
- if (getuid() != 0) {
- WriteFdExactly(fd, "Not running as root. Try \"adb root\" first.\n");
- return false;
- }
-
- auto pid = fork();
- if (pid < 0) {
- WriteFdFmt(fd, "Failed to fork to %s: %s\n", kRemountCmd, strerror(errno));
- return false;
- }
-
- if (pid == 0) {
- // child side of the fork
- dup2(fd, STDIN_FILENO);
- dup2(fd, STDOUT_FILENO);
- dup2(fd, STDERR_FILENO);
-
- execl(kRemountCmd, kRemountCmd, cmd.empty() ? nullptr : cmd.c_str(), nullptr);
- const char* msg = "failed to exec remount\n";
- write(STDERR_FILENO, msg, strlen(msg));
- _exit(errno);
- }
-
- int wstatus = 0;
- auto ret = waitpid(pid, &wstatus, 0);
-
- if (ret == -1) {
- WriteFdFmt(fd, "Failed to wait for %s: %s\n", kRemountCmd, strerror(errno));
- return false;
- } else if (ret != pid) {
- WriteFdFmt(fd, "pid %d and waitpid return %d do not match for %s\n",
- static_cast<int>(pid), static_cast<int>(ret), kRemountCmd);
- return false;
- }
-
- if (WIFSIGNALED(wstatus)) {
- WriteFdFmt(fd, "%s terminated with signal %s\n", kRemountCmd,
- strsignal(WTERMSIG(wstatus)));
- return false;
- }
-
- if (!WIFEXITED(wstatus)) {
- WriteFdFmt(fd, "%s stopped with status 0x%x\n", kRemountCmd, wstatus);
- return false;
- }
-
- if (WEXITSTATUS(wstatus)) {
- WriteFdFmt(fd, "%s exited with status %d\n", kRemountCmd, WEXITSTATUS(wstatus));
- return false;
- }
-
- return true;
-}
-
-void remount_service(unique_fd fd, const std::string& cmd) {
- do_remount(fd.get(), cmd);
- // The remount command will print success or failure for us.
-}
diff --git a/adb/daemon/remount_service.h b/adb/daemon/remount_service.h
deleted file mode 100644
index 522a5da..0000000
--- a/adb/daemon/remount_service.h
+++ /dev/null
@@ -1,25 +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.
- */
-
-#pragma once
-
-#include <string>
-
-#include "adb_unique_fd.h"
-
-#if defined(__ANDROID__)
-void remount_service(unique_fd, const std::string&);
-#endif
diff --git a/adb/daemon/services.cpp b/adb/daemon/services.cpp
index e6f4499..181a8c5 100644
--- a/adb/daemon/services.cpp
+++ b/adb/daemon/services.cpp
@@ -54,7 +54,6 @@
#include "daemon/file_sync_service.h"
#include "daemon/framebuffer_service.h"
#include "daemon/reboot_service.h"
-#include "daemon/remount_service.h"
#include "daemon/restart_service.h"
#include "daemon/set_verity_enable_state_service.h"
#include "daemon/shell_service.h"
@@ -251,9 +250,9 @@
if (name.starts_with("framebuffer:")) {
return create_service_thread("fb", framebuffer_service);
} else if (android::base::ConsumePrefix(&name, "remount:")) {
- std::string arg(name);
- return create_service_thread("remount",
- std::bind(remount_service, std::placeholders::_1, arg));
+ std::string cmd = "/system/bin/remount ";
+ cmd += name;
+ return StartSubprocess(cmd, nullptr, SubprocessType::kRaw, SubprocessProtocol::kNone);
} else if (android::base::ConsumePrefix(&name, "reboot:")) {
std::string arg(name);
return create_service_thread("reboot",
diff --git a/debuggerd/client/debuggerd_client_test.cpp b/debuggerd/client/debuggerd_client_test.cpp
index 9c2f0d6..2545cd6 100644
--- a/debuggerd/client/debuggerd_client_test.cpp
+++ b/debuggerd/client/debuggerd_client_test.cpp
@@ -73,15 +73,15 @@
unique_fd pipe_read, pipe_write;
ASSERT_TRUE(Pipe(&pipe_read, &pipe_write));
- // 64 kB should be enough for everyone.
+ // 64 MiB should be enough for everyone.
constexpr int PIPE_SIZE = 64 * 1024 * 1024;
ASSERT_EQ(PIPE_SIZE, fcntl(pipe_read.get(), F_SETPIPE_SZ, PIPE_SIZE));
// Wait for a bit to let the child spawn all of its threads.
- std::this_thread::sleep_for(250ms);
+ std::this_thread::sleep_for(1s);
ASSERT_TRUE(
- debuggerd_trigger_dump(forkpid, kDebuggerdNativeBacktrace, 10000, std::move(pipe_write)));
+ debuggerd_trigger_dump(forkpid, kDebuggerdNativeBacktrace, 60000, std::move(pipe_write)));
// Immediately kill the forked child, to make sure that the dump didn't return early.
ASSERT_EQ(0, kill(forkpid, SIGKILL)) << strerror(errno);
diff --git a/fs_mgr/liblp/Android.bp b/fs_mgr/liblp/Android.bp
index a7c77b8..ea0fca8 100644
--- a/fs_mgr/liblp/Android.bp
+++ b/fs_mgr/liblp/Android.bp
@@ -100,6 +100,7 @@
test_suites: ["vts-core"],
auto_gen_config: true,
test_min_api_level: 29,
+ require_root: true,
}
cc_test {
diff --git a/fs_mgr/liblp/builder.cpp b/fs_mgr/liblp/builder.cpp
index 7405039..54350a5 100644
--- a/fs_mgr/liblp/builder.cpp
+++ b/fs_mgr/liblp/builder.cpp
@@ -171,7 +171,8 @@
std::unique_ptr<MetadataBuilder> MetadataBuilder::NewForUpdate(const IPartitionOpener& opener,
const std::string& source_partition,
uint32_t source_slot_number,
- uint32_t target_slot_number) {
+ uint32_t target_slot_number,
+ bool always_keep_source_slot) {
auto metadata = ReadMetadata(opener, source_partition, source_slot_number);
if (!metadata) {
return nullptr;
@@ -189,7 +190,8 @@
}
}
- if (IPropertyFetcher::GetInstance()->GetBoolProperty("ro.virtual_ab.enabled", false)) {
+ if (IPropertyFetcher::GetInstance()->GetBoolProperty("ro.virtual_ab.enabled", false) &&
+ !always_keep_source_slot) {
if (!UpdateMetadataForInPlaceSnapshot(metadata.get(), source_slot_number,
target_slot_number)) {
return nullptr;
diff --git a/fs_mgr/liblp/include/liblp/builder.h b/fs_mgr/liblp/include/liblp/builder.h
index b43ccf0..1e9d636 100644
--- a/fs_mgr/liblp/include/liblp/builder.h
+++ b/fs_mgr/liblp/include/liblp/builder.h
@@ -209,10 +209,13 @@
// metadata may not have the target slot's devices listed yet, in which
// case, it is automatically upgraded to include all available block
// devices.
+ // If |always_keep_source_slot| is set, on a Virtual A/B device, source slot
+ // partitions are kept. This is useful when applying a downgrade package.
static std::unique_ptr<MetadataBuilder> NewForUpdate(const IPartitionOpener& opener,
const std::string& source_partition,
uint32_t source_slot_number,
- uint32_t target_slot_number);
+ uint32_t target_slot_number,
+ bool always_keep_source_slot = false);
// Import an existing table for modification. If the table is not valid, for
// example it contains duplicate partition names, then nullptr is returned.
diff --git a/fs_mgr/libsnapshot/Android.bp b/fs_mgr/libsnapshot/Android.bp
index 8cf0f3b..ba43949 100644
--- a/fs_mgr/libsnapshot/Android.bp
+++ b/fs_mgr/libsnapshot/Android.bp
@@ -28,6 +28,7 @@
"liblp",
],
static_libs: [
+ "libcutils",
"libdm",
"libfs_mgr",
"libfstab",
@@ -56,6 +57,17 @@
},
}
+cc_defaults {
+ name: "libsnapshot_hal_deps",
+ cflags: [
+ "-DLIBSNAPSHOT_USE_HAL",
+ ],
+ shared_libs: [
+ "android.hardware.boot@1.0",
+ "android.hardware.boot@1.1",
+ ],
+}
+
filegroup {
name: "libsnapshot_sources",
srcs: [
@@ -75,7 +87,10 @@
cc_library_static {
name: "libsnapshot",
- defaults: ["libsnapshot_defaults"],
+ defaults: [
+ "libsnapshot_defaults",
+ "libsnapshot_hal_deps",
+ ],
srcs: [":libsnapshot_sources"],
whole_static_libs: [
"libfiemap_binder",
@@ -83,7 +98,7 @@
}
cc_library_static {
- name: "libsnapshot_nobinder",
+ name: "libsnapshot_init",
defaults: ["libsnapshot_defaults"],
srcs: [":libsnapshot_sources"],
recovery_available: true,
@@ -92,6 +107,19 @@
],
}
+cc_library_static {
+ name: "libsnapshot_nobinder",
+ defaults: [
+ "libsnapshot_defaults",
+ "libsnapshot_hal_deps",
+ ],
+ srcs: [":libsnapshot_sources"],
+ recovery_available: true,
+ whole_static_libs: [
+ "libfiemap_passthrough",
+ ],
+}
+
cc_test {
name: "libsnapshot_test",
defaults: ["libsnapshot_defaults"],
@@ -103,11 +131,13 @@
],
shared_libs: [
"libbinder",
+ "libhidlbase",
"libprotobuf-cpp-lite",
"libutils",
],
static_libs: [
- "libcutils",
+ "android.hardware.boot@1.0",
+ "android.hardware.boot@1.1",
"libcrypto_static",
"libfs_mgr",
"libgmock",
@@ -134,10 +164,14 @@
"libsnapshot",
],
shared_libs: [
+ "android.hardware.boot@1.0",
+ "android.hardware.boot@1.1",
"libbase",
"libbinder",
+ "libbinderthreadstate",
"libext4_utils",
"libfs_mgr",
+ "libhidlbase",
"liblog",
"liblp",
"libprotobuf-cpp-lite",
diff --git a/fs_mgr/libsnapshot/dm_snapshot_internals.h b/fs_mgr/libsnapshot/dm_snapshot_internals.h
new file mode 100644
index 0000000..4903de1
--- /dev/null
+++ b/fs_mgr/libsnapshot/dm_snapshot_internals.h
@@ -0,0 +1,133 @@
+// Copyright (C) 2019 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 <stdint.h>
+
+#include <vector>
+
+namespace android {
+namespace snapshot {
+
+class DmSnapCowSizeCalculator {
+ public:
+ DmSnapCowSizeCalculator(unsigned int sector_bytes, unsigned int chunk_sectors)
+ : sector_bytes_(sector_bytes),
+ chunk_sectors_(chunk_sectors),
+ exceptions_per_chunk(chunk_sectors_ * sector_bytes_ / (64 * 2 / 8)) {}
+
+ void WriteByte(uint64_t address) { WriteSector(address / sector_bytes_); }
+ void WriteSector(uint64_t sector) { WriteChunk(sector / chunk_sectors_); }
+ void WriteChunk(uint64_t chunk_id) {
+ if (modified_chunks_.size() <= chunk_id) {
+ modified_chunks_.resize(chunk_id + 1, false);
+ }
+ modified_chunks_[chunk_id] = true;
+ }
+
+ uint64_t cow_size_bytes() const { return cow_size_sectors() * sector_bytes_; }
+ uint64_t cow_size_sectors() const { return cow_size_chunks() * chunk_sectors_; }
+
+ /*
+ * The COW device has a precise internal structure as follows:
+ *
+ * - header (1 chunk)
+ * - #0 map and chunks
+ * - map (1 chunk)
+ * - chunks addressable by previous map (exceptions_per_chunk)
+ * - #1 map and chunks
+ * - map (1 chunk)
+ * - chunks addressable by previous map (exceptions_per_chunk)
+ * ...
+ * - #n: map and chunks
+ * - map (1 chunk)
+ * - chunks addressable by previous map (exceptions_per_chunk)
+ * - 1 extra chunk
+ */
+ uint64_t cow_size_chunks() const {
+ uint64_t modified_chunks_count = 0;
+ uint64_t cow_chunks = 0;
+
+ for (const auto& c : modified_chunks_) {
+ if (c) {
+ ++modified_chunks_count;
+ }
+ }
+
+ /* disk header + padding = 1 chunk */
+ cow_chunks += 1;
+
+ /* snapshot modified chunks */
+ cow_chunks += modified_chunks_count;
+
+ /* snapshot chunks index metadata */
+ cow_chunks += 1 + modified_chunks_count / exceptions_per_chunk;
+
+ return cow_chunks;
+ }
+
+ private:
+ /*
+ * Size of each sector in bytes.
+ */
+ const uint64_t sector_bytes_;
+
+ /*
+ * Size of each chunk in sectors.
+ */
+ const uint64_t chunk_sectors_;
+
+ /*
+ * The COW device stores tables to map the modified chunks. Each table
+ * has the size of exactly 1 chunk.
+ * Each row of the table (also called exception in the kernel) contains two
+ * 64 bit indices to identify the corresponding chunk, and this 128 bit row
+ * size is a constant.
+ * The number of exceptions that each table can contain determines the
+ * number of data chunks that separate two consecutive tables. This value
+ * is then fundamental to compute the space overhead introduced by the
+ * tables in COW devices.
+ */
+ const uint64_t exceptions_per_chunk;
+
+ /*
+ * |modified_chunks_| is a container that keeps trace of the modified
+ * chunks.
+ * Multiple options were considered when choosing the most appropriate data
+ * structure for this container. Here follows a summary of why vector<bool>
+ * has been chosen, taking as a reference a snapshot partition of 4 GiB and
+ * chunk size of 4 KiB.
+ * - std::set<uint64_t> is very space-efficient for a small number of
+ * operations, but if the whole snapshot is changed, it would need to
+ * store
+ * 4 GiB / 4 KiB * (64 bit / 8) = 8 MiB
+ * just for the data, plus the additional data overhead for the red-black
+ * tree used for data sorting (if each rb-tree element stores 3 address
+ * and the word-aligne color, the total size grows to 32 MiB).
+ * - std::bitset<N> is not a good fit because requires a priori knowledge,
+ * at compile time, of the bitset size.
+ * - std::vector<bool> is a special case of vector, which uses a data
+ * compression that allows reducing the space utilization of each element
+ * to 1 bit. In detail, this data structure is composed of a resizable
+ * array of words, each of them representing a bitmap. On a 64 bit
+ * device, modifying the whole 4 GiB snapshot grows this container up to
+ * 4 * GiB / 4 KiB / 64 = 64 KiB
+ * that, even if is the same space requirement to change a single byte at
+ * the highest address of the snapshot, is a very affordable space
+ * requirement.
+ */
+ std::vector<bool> modified_chunks_;
+};
+
+} // namespace snapshot
+} // namespace android
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
index 69f2895..fcaa73a 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
@@ -49,6 +49,16 @@
class IPartitionOpener;
} // namespace fs_mgr
+// Forward declare IBootControl types since we cannot include only the headers
+// with Soong. Note: keep the enum width in sync.
+namespace hardware {
+namespace boot {
+namespace V1_1 {
+enum class MergeStatus : int32_t;
+} // namespace V1_1
+} // namespace boot
+} // namespace hardware
+
namespace snapshot {
struct AutoDeleteCowImage;
@@ -94,6 +104,7 @@
using LpMetadata = android::fs_mgr::LpMetadata;
using MetadataBuilder = android::fs_mgr::MetadataBuilder;
using DeltaArchiveManifest = chromeos_update_engine::DeltaArchiveManifest;
+ using MergeStatus = android::hardware::boot::V1_1::MergeStatus;
public:
// Dependency injection for testing.
@@ -107,6 +118,7 @@
virtual std::string GetSuperDevice(uint32_t slot) const = 0;
virtual const IPartitionOpener& GetPartitionOpener() const = 0;
virtual bool IsOverlayfsSetup() const = 0;
+ virtual bool SetBootControlMergeStatus(MergeStatus status) = 0;
};
~SnapshotManager();
@@ -208,6 +220,7 @@
FRIEND_TEST(SnapshotTest, Merge);
FRIEND_TEST(SnapshotTest, MergeCannotRemoveCow);
FRIEND_TEST(SnapshotTest, NoMergeBeforeReboot);
+ FRIEND_TEST(SnapshotTest, UpdateBootControlHal);
FRIEND_TEST(SnapshotUpdateTest, SnapshotStatusFileWithoutCow);
friend class SnapshotTest;
friend class SnapshotUpdateTest;
diff --git a/fs_mgr/libsnapshot/partition_cow_creator_test.cpp b/fs_mgr/libsnapshot/partition_cow_creator_test.cpp
index cf2d745..f683f5b 100644
--- a/fs_mgr/libsnapshot/partition_cow_creator_test.cpp
+++ b/fs_mgr/libsnapshot/partition_cow_creator_test.cpp
@@ -17,6 +17,7 @@
#include <liblp/builder.h>
#include <liblp/property_fetcher.h>
+#include "dm_snapshot_internals.h"
#include "partition_cow_creator.h"
#include "test_helpers.h"
@@ -99,5 +100,31 @@
ASSERT_TRUE(ret.has_value());
}
+TEST(DmSnapshotInternals, CowSizeCalculator) {
+ DmSnapCowSizeCalculator cc(512, 8);
+ unsigned long int b;
+
+ // Empty COW
+ ASSERT_EQ(cc.cow_size_sectors(), 16);
+
+ // First chunk written
+ for (b = 0; b < 4_KiB; ++b) {
+ cc.WriteByte(b);
+ ASSERT_EQ(cc.cow_size_sectors(), 24);
+ }
+
+ // Second chunk written
+ for (b = 4_KiB; b < 8_KiB; ++b) {
+ cc.WriteByte(b);
+ ASSERT_EQ(cc.cow_size_sectors(), 32);
+ }
+
+ // Leave a hole and write 5th chunk
+ for (b = 16_KiB; b < 20_KiB; ++b) {
+ cc.WriteByte(b);
+ ASSERT_EQ(cc.cow_size_sectors(), 40);
+ }
+}
+
} // namespace snapshot
} // namespace android
diff --git a/fs_mgr/libsnapshot/snapshot.cpp b/fs_mgr/libsnapshot/snapshot.cpp
index 395fb40..48a94e4 100644
--- a/fs_mgr/libsnapshot/snapshot.cpp
+++ b/fs_mgr/libsnapshot/snapshot.cpp
@@ -29,6 +29,9 @@
#include <android-base/parseint.h>
#include <android-base/strings.h>
#include <android-base/unique_fd.h>
+#ifdef LIBSNAPSHOT_USE_HAL
+#include <android/hardware/boot/1.1/IBootControl.h>
+#endif
#include <ext4_utils/ext4_utils.h>
#include <fs_mgr.h>
#include <fs_mgr_dm_linear.h>
@@ -63,6 +66,7 @@
using android::fs_mgr::LpMetadata;
using android::fs_mgr::MetadataBuilder;
using android::fs_mgr::SlotNumberForSlotSuffix;
+using android::hardware::boot::V1_1::MergeStatus;
using chromeos_update_engine::DeltaArchiveManifest;
using chromeos_update_engine::InstallOperation;
template <typename T>
@@ -84,11 +88,39 @@
return fs_mgr_get_super_partition_name(slot);
}
bool IsOverlayfsSetup() const override { return fs_mgr_overlayfs_is_setup(); }
+ bool SetBootControlMergeStatus(MergeStatus status) override;
private:
android::fs_mgr::PartitionOpener opener_;
+#ifdef LIBSNAPSHOT_USE_HAL
+ android::sp<android::hardware::boot::V1_1::IBootControl> boot_control_;
+#endif
};
+bool DeviceInfo::SetBootControlMergeStatus([[maybe_unused]] MergeStatus status) {
+#ifdef LIBSNAPSHOT_USE_HAL
+ if (!boot_control_) {
+ auto hal = android::hardware::boot::V1_0::IBootControl::getService();
+ if (!hal) {
+ LOG(ERROR) << "Could not find IBootControl HAL";
+ return false;
+ }
+ boot_control_ = android::hardware::boot::V1_1::IBootControl::castFrom(hal);
+ if (!boot_control_) {
+ LOG(ERROR) << "Could not find IBootControl 1.1 HAL";
+ return false;
+ }
+ }
+ if (!boot_control_->setSnapshotMergeStatus(status)) {
+ LOG(ERROR) << "Unable to set the snapshot merge status";
+ return false;
+ }
+ return true;
+#else
+ return false;
+#endif
+}
+
// Note: IImageManager is an incomplete type in the header, so the default
// destructor doesn't work.
SnapshotManager::~SnapshotManager() {}
@@ -1590,6 +1622,35 @@
PLOG(ERROR) << "Could not write to state file";
return false;
}
+
+#ifdef LIBSNAPSHOT_USE_HAL
+ auto merge_status = MergeStatus::UNKNOWN;
+ switch (state) {
+ // The needs-reboot and completed cases imply that /data and /metadata
+ // can be safely wiped, so we don't report a merge status.
+ case UpdateState::None:
+ case UpdateState::MergeNeedsReboot:
+ case UpdateState::MergeCompleted:
+ merge_status = MergeStatus::NONE;
+ break;
+ case UpdateState::Initiated:
+ case UpdateState::Unverified:
+ merge_status = MergeStatus::SNAPSHOTTED;
+ break;
+ case UpdateState::Merging:
+ case UpdateState::MergeFailed:
+ merge_status = MergeStatus::MERGING;
+ break;
+ default:
+ // Note that Cancelled flows to here - it is never written, since
+ // it only communicates a transient state to the caller.
+ LOG(ERROR) << "Unexpected update status: " << state;
+ break;
+ }
+ if (!device_->SetBootControlMergeStatus(merge_status)) {
+ return false;
+ }
+#endif
return true;
}
diff --git a/fs_mgr/libsnapshot/snapshot_test.cpp b/fs_mgr/libsnapshot/snapshot_test.cpp
index aea12be..a008294 100644
--- a/fs_mgr/libsnapshot/snapshot_test.cpp
+++ b/fs_mgr/libsnapshot/snapshot_test.cpp
@@ -617,6 +617,31 @@
ASSERT_EQ(sm->GetUpdateState(), UpdateState::None);
}
+TEST_F(SnapshotTest, UpdateBootControlHal) {
+ ASSERT_TRUE(AcquireLock());
+
+ ASSERT_TRUE(sm->WriteUpdateState(lock_.get(), UpdateState::None));
+ ASSERT_EQ(test_device->merge_status(), MergeStatus::NONE);
+
+ ASSERT_TRUE(sm->WriteUpdateState(lock_.get(), UpdateState::Initiated));
+ ASSERT_EQ(test_device->merge_status(), MergeStatus::SNAPSHOTTED);
+
+ ASSERT_TRUE(sm->WriteUpdateState(lock_.get(), UpdateState::Unverified));
+ ASSERT_EQ(test_device->merge_status(), MergeStatus::SNAPSHOTTED);
+
+ ASSERT_TRUE(sm->WriteUpdateState(lock_.get(), UpdateState::Merging));
+ ASSERT_EQ(test_device->merge_status(), MergeStatus::MERGING);
+
+ ASSERT_TRUE(sm->WriteUpdateState(lock_.get(), UpdateState::MergeNeedsReboot));
+ ASSERT_EQ(test_device->merge_status(), MergeStatus::NONE);
+
+ ASSERT_TRUE(sm->WriteUpdateState(lock_.get(), UpdateState::MergeCompleted));
+ ASSERT_EQ(test_device->merge_status(), MergeStatus::NONE);
+
+ ASSERT_TRUE(sm->WriteUpdateState(lock_.get(), UpdateState::MergeFailed));
+ ASSERT_EQ(test_device->merge_status(), MergeStatus::MERGING);
+}
+
class SnapshotUpdateTest : public SnapshotTest {
public:
void SetUp() override {
diff --git a/fs_mgr/libsnapshot/test_helpers.h b/fs_mgr/libsnapshot/test_helpers.h
index 769d21e..ea2c5b6 100644
--- a/fs_mgr/libsnapshot/test_helpers.h
+++ b/fs_mgr/libsnapshot/test_helpers.h
@@ -17,6 +17,7 @@
#include <optional>
#include <string>
+#include <android/hardware/boot/1.1/IBootControl.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <libfiemap/image_manager.h>
@@ -32,6 +33,7 @@
using android::fs_mgr::IPropertyFetcher;
using android::fs_mgr::MetadataBuilder;
using android::fs_mgr::testing::MockPropertyFetcher;
+using android::hardware::boot::V1_1::MergeStatus;
using chromeos_update_engine::DeltaArchiveManifest;
using chromeos_update_engine::PartitionUpdate;
using testing::_;
@@ -81,16 +83,22 @@
const android::fs_mgr::IPartitionOpener& GetPartitionOpener() const override {
return *opener_.get();
}
+ bool SetBootControlMergeStatus(MergeStatus status) override {
+ merge_status_ = status;
+ return true;
+ }
bool IsOverlayfsSetup() const override { return false; }
void set_slot_suffix(const std::string& suffix) { slot_suffix_ = suffix; }
void set_fake_super(const std::string& path) {
opener_ = std::make_unique<TestPartitionOpener>(path);
}
+ MergeStatus merge_status() const { return merge_status_; }
private:
std::string slot_suffix_ = "_a";
std::unique_ptr<TestPartitionOpener> opener_;
+ MergeStatus merge_status_;
};
class SnapshotTestPropertyFetcher : public android::fs_mgr::testing::MockPropertyFetcher {
diff --git a/init/Android.bp b/init/Android.bp
index 9b2ddc0..ce5b12a 100644
--- a/init/Android.bp
+++ b/init/Android.bp
@@ -69,7 +69,7 @@
"libprotobuf-cpp-lite",
"libpropertyinfoserializer",
"libpropertyinfoparser",
- "libsnapshot_nobinder",
+ "libsnapshot_init",
],
shared_libs: [
"libbacktrace",
diff --git a/init/Android.mk b/init/Android.mk
index 8fc44da..4e4c002 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -114,7 +114,7 @@
libmodprobe \
libext2_uuid \
libprotobuf-cpp-lite \
- libsnapshot_nobinder \
+ libsnapshot_init \
LOCAL_SANITIZE := signed-integer-overflow
# First stage init is weird: it may start without stdout/stderr, and no /proc.
diff --git a/liblog/include/android/log.h b/liblog/include/android/log.h
index 935590d..2e6210e 100644
--- a/liblog/include/android/log.h
+++ b/liblog/include/android/log.h
@@ -96,20 +96,14 @@
* [printf(3)](http://man7.org/linux/man-pages/man3/printf.3.html).
*/
int __android_log_print(int prio, const char* tag, const char* fmt, ...)
-#if defined(__GNUC__)
- __attribute__((__format__(printf, 3, 4)))
-#endif
- ;
+ __attribute__((__format__(printf, 3, 4)));
/**
* Equivalent to `__android_log_print`, but taking a `va_list`.
* (If `__android_log_print` is like `printf`, this is like `vprintf`.)
*/
int __android_log_vprint(int prio, const char* tag, const char* fmt, va_list ap)
-#if defined(__GNUC__)
- __attribute__((__format__(printf, 3, 0)))
-#endif
- ;
+ __attribute__((__format__(printf, 3, 0)));
/**
* Writes an assertion failure to the log (as `ANDROID_LOG_FATAL`) and to
@@ -127,13 +121,8 @@
* including the source filename and line number more conveniently than this
* function.
*/
-void __android_log_assert(const char* cond, const char* tag, const char* fmt,
- ...)
-#if defined(__GNUC__)
- __attribute__((__noreturn__))
- __attribute__((__format__(printf, 3, 4)))
-#endif
- ;
+void __android_log_assert(const char* cond, const char* tag, const char* fmt, ...)
+ __attribute__((__noreturn__)) __attribute__((__format__(printf, 3, 4)));
#ifndef log_id_t_defined
#define log_id_t_defined
@@ -171,8 +160,7 @@
*
* Apps should use __android_log_write() instead.
*/
-int __android_log_buf_write(int bufID, int prio, const char* tag,
- const char* text);
+int __android_log_buf_write(int bufID, int prio, const char* tag, const char* text);
/**
* Writes a formatted string to log buffer `id`,
@@ -182,12 +170,8 @@
*
* Apps should use __android_log_print() instead.
*/
-int __android_log_buf_print(int bufID, int prio, const char* tag,
- const char* fmt, ...)
-#if defined(__GNUC__)
- __attribute__((__format__(printf, 4, 5)))
-#endif
- ;
+int __android_log_buf_print(int bufID, int prio, const char* tag, const char* fmt, ...)
+ __attribute__((__format__(printf, 4, 5)));
#ifdef __cplusplus
}
diff --git a/liblog/include/log/log_id.h b/liblog/include/log/log_id.h
index c052a50..4c6d809 100644
--- a/liblog/include/log/log_id.h
+++ b/liblog/include/log/log_id.h
@@ -45,12 +45,8 @@
*/
int __android_log_buf_write(int bufID, int prio, const char* tag,
const char* text);
-int __android_log_buf_print(int bufID, int prio, const char* tag,
- const char* fmt, ...)
-#if defined(__GNUC__)
- __attribute__((__format__(printf, 4, 5)))
-#endif
- ;
+int __android_log_buf_print(int bufID, int prio, const char* tag, const char* fmt, ...)
+ __attribute__((__format__(printf, 4, 5)));
/*
* log_id_t helpers
diff --git a/rootdir/Android.mk b/rootdir/Android.mk
index 5241730..e1bb02f 100644
--- a/rootdir/Android.mk
+++ b/rootdir/Android.mk
@@ -326,7 +326,7 @@
LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)
LOCAL_MODULE_STEM := $(call append_vndk_version,$(LOCAL_MODULE))
include $(BUILD_SYSTEM)/base_rules.mk
-$(LOCAL_BUILT_MODULE): PRIVATE_VNDK_SAMEPROCESS_LIBRARIES := $(call module-installed-files-or-guess,$(VNDK_SAMEPROCESS_LIBRARIES),.com.android.vndk.current)
+$(LOCAL_BUILT_MODULE): PRIVATE_VNDK_SAMEPROCESS_LIBRARIES := $(call module-installed-files-or-guess,$(VNDK_SAMEPROCESS_LIBRARIES),.vendor)
$(LOCAL_BUILT_MODULE):
@echo "Generate: $@"
@mkdir -p $(dir $@)
@@ -342,7 +342,7 @@
LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)
LOCAL_MODULE_STEM := $(call append_vndk_version,$(LOCAL_MODULE))
include $(BUILD_SYSTEM)/base_rules.mk
-$(LOCAL_BUILT_MODULE): PRIVATE_VNDK_CORE_LIBRARIES := $(call module-installed-files-or-guess,$(VNDK_CORE_LIBRARIES),.com.android.vndk.current)
+$(LOCAL_BUILT_MODULE): PRIVATE_VNDK_CORE_LIBRARIES := $(call module-installed-files-or-guess,$(VNDK_CORE_LIBRARIES),.vendor)
$(LOCAL_BUILT_MODULE):
@echo "Generate: $@"
@mkdir -p $(dir $@)
@@ -358,7 +358,7 @@
LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)
LOCAL_MODULE_STEM := $(call append_vndk_version,$(LOCAL_MODULE))
include $(BUILD_SYSTEM)/base_rules.mk
-$(LOCAL_BUILT_MODULE): PRIVATE_VNDK_PRIVATE_LIBRARIES := $(call module-installed-files-or-guess,$(VNDK_PRIVATE_LIBRARIES),.com.android.vndk.current)
+$(LOCAL_BUILT_MODULE): PRIVATE_VNDK_PRIVATE_LIBRARIES := $(call module-installed-files-or-guess,$(VNDK_PRIVATE_LIBRARIES),.vendor)
$(LOCAL_BUILT_MODULE):
@echo "Generate: $@"
@mkdir -p $(dir $@)