Merge changes from topic "health-v3" into main
* changes:
fastboot: Add getvar commands to query battery part info.
Update fastbootd to use Health AIDL HAL V3.
Update healthd to use Health AIDL HAL V3.
Update storaged to use Health AIDL HAL V3.
diff --git a/debuggerd/crash_dump.cpp b/debuggerd/crash_dump.cpp
index 3563436..0899111 100644
--- a/debuggerd/crash_dump.cpp
+++ b/debuggerd/crash_dump.cpp
@@ -317,6 +317,7 @@
process_info->gwp_asan_state = crash_info->data.d.gwp_asan_state;
process_info->gwp_asan_metadata = crash_info->data.d.gwp_asan_metadata;
process_info->scudo_stack_depot = crash_info->data.d.scudo_stack_depot;
+ process_info->scudo_stack_depot_size = crash_info->data.d.scudo_stack_depot_size;
process_info->scudo_region_info = crash_info->data.d.scudo_region_info;
process_info->scudo_ring_buffer = crash_info->data.d.scudo_ring_buffer;
process_info->scudo_ring_buffer_size = crash_info->data.d.scudo_ring_buffer_size;
diff --git a/debuggerd/handler/debuggerd_handler.cpp b/debuggerd/handler/debuggerd_handler.cpp
index 01365f2..ea07ce2 100644
--- a/debuggerd/handler/debuggerd_handler.cpp
+++ b/debuggerd/handler/debuggerd_handler.cpp
@@ -395,6 +395,7 @@
ASSERT_SAME_OFFSET(scudo_region_info, scudo_region_info);
ASSERT_SAME_OFFSET(scudo_ring_buffer, scudo_ring_buffer);
ASSERT_SAME_OFFSET(scudo_ring_buffer_size, scudo_ring_buffer_size);
+ ASSERT_SAME_OFFSET(scudo_stack_depot_size, scudo_stack_depot_size);
ASSERT_SAME_OFFSET(recoverable_gwp_asan_crash, recoverable_gwp_asan_crash);
#undef ASSERT_SAME_OFFSET
diff --git a/debuggerd/include/debuggerd/handler.h b/debuggerd/include/debuggerd/handler.h
index ebb5372..de12fc6 100644
--- a/debuggerd/include/debuggerd/handler.h
+++ b/debuggerd/include/debuggerd/handler.h
@@ -44,6 +44,7 @@
const char* scudo_region_info;
const char* scudo_ring_buffer;
size_t scudo_ring_buffer_size;
+ size_t scudo_stack_depot_size;
bool recoverable_gwp_asan_crash;
};
diff --git a/debuggerd/libdebuggerd/include/libdebuggerd/types.h b/debuggerd/libdebuggerd/include/libdebuggerd/types.h
index 5a2a7ab..075b12c 100644
--- a/debuggerd/libdebuggerd/include/libdebuggerd/types.h
+++ b/debuggerd/libdebuggerd/include/libdebuggerd/types.h
@@ -51,6 +51,7 @@
uintptr_t scudo_region_info = 0;
uintptr_t scudo_ring_buffer = 0;
size_t scudo_ring_buffer_size = 0;
+ size_t scudo_stack_depot_size = 0;
bool has_fault_address = false;
uintptr_t untagged_fault_address = 0;
diff --git a/debuggerd/libdebuggerd/scudo.cpp b/debuggerd/libdebuggerd/scudo.cpp
index ea8dff4..cff43f8 100644
--- a/debuggerd/libdebuggerd/scudo.cpp
+++ b/debuggerd/libdebuggerd/scudo.cpp
@@ -41,8 +41,6 @@
return;
}
- auto stack_depot = AllocAndReadFully(process_memory, process_info.scudo_stack_depot,
- __scudo_get_stack_depot_size());
auto region_info = AllocAndReadFully(process_memory, process_info.scudo_region_info,
__scudo_get_region_info_size());
std::unique_ptr<char[]> ring_buffer;
@@ -50,7 +48,12 @@
ring_buffer = AllocAndReadFully(process_memory, process_info.scudo_ring_buffer,
process_info.scudo_ring_buffer_size);
}
- if (!stack_depot || !region_info) {
+ std::unique_ptr<char[]> stack_depot;
+ if (process_info.scudo_stack_depot_size != 0) {
+ stack_depot = AllocAndReadFully(process_memory, process_info.scudo_stack_depot,
+ process_info.scudo_stack_depot_size);
+ }
+ if (!region_info) {
return;
}
diff --git a/debuggerd/protocol.h b/debuggerd/protocol.h
index 212d6dc..793428a 100644
--- a/debuggerd/protocol.h
+++ b/debuggerd/protocol.h
@@ -99,6 +99,7 @@
uintptr_t scudo_region_info;
uintptr_t scudo_ring_buffer;
size_t scudo_ring_buffer_size;
+ size_t scudo_stack_depot_size;
bool recoverable_gwp_asan_crash;
};
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index ac2a20f..1bc7b75 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -402,7 +402,7 @@
transport = open_device(device.c_str(), false, false);
if (print) {
- PrintDevice(device.c_str(), transport ? "offline" : "fastboot");
+ PrintDevice(device.c_str(), transport ? "fastboot" : "offline");
}
if (transport) {
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/cow_format.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/cow_format.cpp
index 2c4d40f..b0eb723 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/cow_format.cpp
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/cow_format.cpp
@@ -14,7 +14,6 @@
// limitations under the License.
//
-#include <inttypes.h>
#include <libsnapshot/cow_format.h>
#include <sys/types.h>
#include <unistd.h>
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/test_v3.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/test_v3.cpp
index 27accdc..44b7344 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/test_v3.cpp
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/test_v3.cpp
@@ -97,7 +97,7 @@
options.op_count_max = 20;
auto writer = CreateCowWriter(3, options, GetCowFd());
ASSERT_FALSE(writer->AddZeroBlocks(1, 21));
- ASSERT_FALSE(writer->AddZeroBlocks(1, 1));
+ ASSERT_TRUE(writer->AddZeroBlocks(1, 20));
std::string data = "This is some data, believe it";
data.resize(options.block_size, '\0');
@@ -184,7 +184,7 @@
std::string data;
data.resize(options.block_size * 5);
for (int i = 0; i < data.size(); i++) {
- data[i] = char(rand() % 256);
+ data[i] = static_cast<char>('A' + i / options.block_size);
}
ASSERT_TRUE(writer->AddRawBlocks(5, data.data(), data.size()));
@@ -205,19 +205,20 @@
ASSERT_FALSE(iter->AtEnd());
size_t i = 0;
- std::string sink(data.size(), '\0');
while (!iter->AtEnd()) {
auto op = iter->Get();
+ std::string sink(options.block_size, '\0');
ASSERT_EQ(op->type(), kCowReplaceOp);
ASSERT_EQ(op->data_length, options.block_size);
ASSERT_EQ(op->new_block, 5 + i);
- ASSERT_TRUE(
- ReadData(reader, op, sink.data() + (i * options.block_size), options.block_size));
+ ASSERT_TRUE(ReadData(reader, op, sink.data(), options.block_size));
+ ASSERT_EQ(std::string_view(sink),
+ std::string_view(data).substr(i * options.block_size, options.block_size))
+ << " readback data for " << i << "th block does not match";
iter->Next();
i++;
}
- ASSERT_EQ(sink, data);
ASSERT_EQ(i, 5);
}
@@ -372,41 +373,33 @@
ASSERT_NE(iter, nullptr);
ASSERT_FALSE(iter->AtEnd());
- size_t i = 0;
-
- while (i < 5) {
+ for (size_t i = 0; i < 5; i++) {
auto op = iter->Get();
ASSERT_EQ(op->type(), kCowZeroOp);
ASSERT_EQ(op->new_block, 10 + i);
iter->Next();
- i++;
}
- i = 0;
- while (i < 5) {
+ for (size_t i = 0; i < 5; i++) {
auto op = iter->Get();
ASSERT_EQ(op->type(), kCowCopyOp);
ASSERT_EQ(op->new_block, 15 + i);
ASSERT_EQ(op->source(), 3 + i);
iter->Next();
- i++;
}
- i = 0;
std::string sink(data.size(), '\0');
- while (i < 5) {
+ for (size_t i = 0; i < 5; i++) {
auto op = iter->Get();
ASSERT_EQ(op->type(), kCowReplaceOp);
ASSERT_EQ(op->new_block, 18 + i);
- ASSERT_TRUE(
- ReadData(reader, op, sink.data() + (i * options.block_size), options.block_size));
+ ASSERT_EQ(reader.ReadData(op, sink.data() + (i * options.block_size), options.block_size),
+ options.block_size);
iter->Next();
- i++;
}
ASSERT_EQ(sink, data);
- i = 0;
std::fill(sink.begin(), sink.end(), '\0');
- while (i < 5) {
+ for (size_t i = 0; i < 5; i++) {
auto op = iter->Get();
ASSERT_EQ(op->type(), kCowXorOp);
ASSERT_EQ(op->new_block, 50 + i);
@@ -414,7 +407,6 @@
ASSERT_TRUE(
ReadData(reader, op, sink.data() + (i * options.block_size), options.block_size));
iter->Next();
- i++;
}
ASSERT_EQ(sink, data);
}
@@ -671,5 +663,25 @@
ASSERT_LE(writer.GetCowSize(), cow_size);
}
+TEST_F(CowTestV3, CopyOpMany) {
+ CowOptions options;
+ options.op_count_max = 100;
+ CowWriterV3 writer(options, GetCowFd());
+ writer.Initialize();
+ ASSERT_TRUE(writer.AddCopy(100, 50, 50));
+ ASSERT_TRUE(writer.AddCopy(150, 100, 50));
+ ASSERT_TRUE(writer.Finalize());
+ CowReader reader;
+ ASSERT_TRUE(reader.Parse(GetCowFd()));
+ auto it = reader.GetOpIter();
+ for (size_t i = 0; i < 100; i++) {
+ ASSERT_FALSE(it->AtEnd()) << " op iterator ended at " << i;
+ const auto op = *it->Get();
+ ASSERT_EQ(op.type(), kCowCopyOp);
+ ASSERT_EQ(op.new_block, 100 + i);
+ it->Next();
+ }
+}
+
} // namespace snapshot
} // namespace android
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.cpp
index 07f6f00..4df0e76 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.cpp
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.cpp
@@ -113,7 +113,13 @@
}
compression_.algorithm = *algorithm;
- compressor_ = ICompressor::Create(compression_, header_.block_size);
+ if (compression_.algorithm != kCowCompressNone) {
+ compressor_ = ICompressor::Create(compression_, header_.block_size);
+ if (compressor_ == nullptr) {
+ LOG(ERROR) << "Failed to create compressor for " << compression_.algorithm;
+ return false;
+ }
+ }
return true;
}
@@ -207,14 +213,15 @@
}
bool CowWriterV3::EmitCopy(uint64_t new_block, uint64_t old_block, uint64_t num_blocks) {
+ std::vector<CowOperationV3> ops(num_blocks);
for (size_t i = 0; i < num_blocks; i++) {
- CowOperationV3 op{};
+ CowOperationV3& op = ops[i];
op.set_type(kCowCopyOp);
op.new_block = new_block + i;
op.set_source(old_block + i);
- if (!WriteOperation(op)) {
- return false;
- }
+ }
+ if (!WriteOperation({ops.data(), ops.size()}, {})) {
+ return false;
}
return true;
@@ -231,12 +238,37 @@
bool CowWriterV3::EmitBlocks(uint64_t new_block_start, const void* data, size_t size,
uint64_t old_block, uint16_t offset, CowOperationType type) {
+ if (compression_.algorithm != kCowCompressNone && compressor_ == nullptr) {
+ LOG(ERROR) << "Compression algorithm is " << compression_.algorithm
+ << " but compressor is uninitialized.";
+ return false;
+ }
const size_t num_blocks = (size / header_.block_size);
+ if (compression_.algorithm == kCowCompressNone) {
+ std::vector<CowOperationV3> ops(num_blocks);
+ for (size_t i = 0; i < num_blocks; i++) {
+ CowOperation& op = ops[i];
+ op.new_block = new_block_start + i;
+
+ op.set_type(type);
+ if (type == kCowXorOp) {
+ op.set_source((old_block + i) * header_.block_size + offset);
+ } else {
+ op.set_source(next_data_pos_ + header_.block_size * i);
+ }
+ op.data_length = header_.block_size;
+ }
+ return WriteOperation({ops.data(), ops.size()},
+ {reinterpret_cast<const uint8_t*>(data), size});
+ }
+
+ const auto saved_op_count = header_.op_count;
+ const auto saved_data_pos = next_data_pos_;
for (size_t i = 0; i < num_blocks; i++) {
const uint8_t* const iter =
reinterpret_cast<const uint8_t*>(data) + (header_.block_size * i);
- CowOperation op = {};
+ CowOperation op{};
op.new_block = new_block_start + i;
op.set_type(type);
@@ -245,25 +277,21 @@
} else {
op.set_source(next_data_pos_);
}
- std::basic_string<uint8_t> compressed_data;
const void* out_data = iter;
op.data_length = header_.block_size;
- if (compression_.algorithm) {
- if (!compressor_) {
- PLOG(ERROR) << "Compressor not initialized";
- return false;
- }
- compressed_data = compressor_->Compress(out_data, header_.block_size);
- if (compressed_data.size() < op.data_length) {
- out_data = compressed_data.data();
- op.data_length = compressed_data.size();
- }
+ const std::basic_string<uint8_t> compressed_data =
+ compressor_->Compress(out_data, header_.block_size);
+ if (compressed_data.size() < op.data_length) {
+ out_data = compressed_data.data();
+ op.data_length = compressed_data.size();
}
if (!WriteOperation(op, out_data, op.data_length)) {
PLOG(ERROR) << "AddRawBlocks with compression: write failed. new block: "
<< new_block_start << " compression: " << compression_.algorithm;
+ header_.op_count = saved_op_count;
+ next_data_pos_ = saved_data_pos;
return false;
}
}
@@ -272,13 +300,14 @@
}
bool CowWriterV3::EmitZeroBlocks(uint64_t new_block_start, uint64_t num_blocks) {
+ std::vector<CowOperationV3> ops(num_blocks);
for (uint64_t i = 0; i < num_blocks; i++) {
- CowOperationV3 op{};
+ CowOperationV3& op = ops[i];
op.set_type(kCowZeroOp);
op.new_block = new_block_start + i;
- if (!WriteOperation(op)) {
- return false;
- }
+ }
+ if (!WriteOperation({ops.data(), ops.size()}, {})) {
+ return false;
}
return true;
}
@@ -324,43 +353,48 @@
return true;
}
-bool CowWriterV3::WriteOperation(const CowOperationV3& op, const void* data, size_t size) {
+bool CowWriterV3::WriteOperation(std::basic_string_view<CowOperationV3> ops,
+ std::basic_string_view<uint8_t> data) {
if (IsEstimating()) {
- header_.op_count++;
+ header_.op_count += ops.size();
if (header_.op_count > header_.op_count_max) {
// If we increment op_count_max, the offset of data section would
// change. So need to update |next_data_pos_|
next_data_pos_ += (header_.op_count - header_.op_count_max) * sizeof(CowOperationV3);
header_.op_count_max = header_.op_count;
}
- next_data_pos_ += op.data_length;
+ next_data_pos_ += data.size();
return true;
}
- if (header_.op_count + 1 > header_.op_count_max) {
- LOG(ERROR) << "Maximum number of ops reached: " << header_.op_count_max;
+ if (header_.op_count + ops.size() > header_.op_count_max) {
+ LOG(ERROR) << "Current op count " << header_.op_count << ", attempting to write "
+ << ops.size() << " ops will exceed the max of " << header_.op_count_max;
return false;
}
const off_t offset = GetOpOffset(header_.op_count, header_);
- if (!android::base::WriteFullyAtOffset(fd_, &op, sizeof(op), offset)) {
- PLOG(ERROR) << "write failed for " << op << " at " << offset;
+ if (!android::base::WriteFullyAtOffset(fd_, ops.data(), ops.size() * sizeof(ops[0]), offset)) {
+ PLOG(ERROR) << "Write failed for " << ops.size() << " ops at " << offset;
return false;
}
- if (data && size > 0) {
- if (!android::base::WriteFullyAtOffset(fd_, data, size, next_data_pos_)) {
- PLOG(ERROR) << "write failed for data of size: " << size
+ if (!data.empty()) {
+ if (!android::base::WriteFullyAtOffset(fd_, data.data(), data.size(), next_data_pos_)) {
+ PLOG(ERROR) << "write failed for data of size: " << data.size()
<< " at offset: " << next_data_pos_;
return false;
}
}
- header_.op_count++;
- next_data_pos_ += op.data_length;
- next_op_pos_ += sizeof(CowOperationV3);
+ header_.op_count += ops.size();
+ next_data_pos_ += data.size();
return true;
}
+bool CowWriterV3::WriteOperation(const CowOperationV3& op, const void* data, size_t size) {
+ return WriteOperation({&op, 1}, {reinterpret_cast<const uint8_t*>(data), size});
+}
+
bool CowWriterV3::Finalize() {
CHECK_GE(header_.prefix.header_size, sizeof(CowHeaderV3));
CHECK_LE(header_.prefix.header_size, sizeof(header_));
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.h b/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.h
index 340218f..02b4e61 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.h
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.h
@@ -15,6 +15,7 @@
#pragma once
#include <android-base/logging.h>
+#include <string_view>
#include "writer_base.h"
@@ -44,6 +45,8 @@
bool ParseOptions();
bool OpenForWrite();
bool OpenForAppend(uint64_t label);
+ bool WriteOperation(std::basic_string_view<CowOperationV3> op,
+ std::basic_string_view<uint8_t> data);
bool WriteOperation(const CowOperationV3& op, const void* data = nullptr, size_t size = 0);
bool EmitBlocks(uint64_t new_block_start, const void* data, size_t size, uint64_t old_block,
uint16_t offset, CowOperationType type);
@@ -59,7 +62,6 @@
// Resume points contain a laebl + cow_op_index.
std::shared_ptr<std::vector<ResumePoint>> resume_points_;
- uint64_t next_op_pos_ = 0;
uint64_t next_data_pos_ = 0;
std::vector<std::basic_string<uint8_t>> compressed_buf_;