Merge "first_stage_init: support kernel module directories"
diff --git a/adb/Android.bp b/adb/Android.bp
index 9db151d..8747182 100644
--- a/adb/Android.bp
+++ b/adb/Android.bp
@@ -124,11 +124,12 @@
"libadbd_core",
"libadbconnection_server",
"libasyncio",
+ "libbase",
"libbrotli",
"libcutils_sockets",
"libdiagnose_usb",
"libmdnssd",
- "libbase",
+ "libzstd",
"libadb_protos",
"libapp_processes_protos_lite",
@@ -351,6 +352,7 @@
"liblog",
"libziparchive",
"libz",
+ "libzstd",
],
// Don't add anything here, we don't want additional shared dependencies
@@ -483,6 +485,7 @@
"libbrotli",
"libdiagnose_usb",
"liblz4",
+ "libzstd",
],
shared_libs: [
@@ -586,6 +589,7 @@
"libdiagnose_usb",
"liblz4",
"libmdnssd",
+ "libzstd",
],
visibility: [
diff --git a/adb/client/commandline.cpp b/adb/client/commandline.cpp
index eaa32e5..43772ba 100644
--- a/adb/client/commandline.cpp
+++ b/adb/client/commandline.cpp
@@ -1336,6 +1336,8 @@
return CompressionType::Brotli;
} else if (str == "lz4") {
return CompressionType::LZ4;
+ } else if (str == "zstd") {
+ return CompressionType::Zstd;
}
error_exit("unexpected compression type %s", str.c_str());
diff --git a/adb/client/file_sync_client.cpp b/adb/client/file_sync_client.cpp
index 7185939..8bbe2a8 100644
--- a/adb/client/file_sync_client.cpp
+++ b/adb/client/file_sync_client.cpp
@@ -240,6 +240,7 @@
have_sendrecv_v2_ = CanUseFeature(*features, kFeatureSendRecv2);
have_sendrecv_v2_brotli_ = CanUseFeature(*features, kFeatureSendRecv2Brotli);
have_sendrecv_v2_lz4_ = CanUseFeature(*features, kFeatureSendRecv2LZ4);
+ have_sendrecv_v2_zstd_ = CanUseFeature(*features, kFeatureSendRecv2Zstd);
have_sendrecv_v2_dry_run_send_ = CanUseFeature(*features, kFeatureSendRecv2DryRunSend);
std::string error;
fd.reset(adb_connect("sync:", &error));
@@ -268,13 +269,16 @@
bool HaveSendRecv2() const { return have_sendrecv_v2_; }
bool HaveSendRecv2Brotli() const { return have_sendrecv_v2_brotli_; }
bool HaveSendRecv2LZ4() const { return have_sendrecv_v2_lz4_; }
+ bool HaveSendRecv2Zstd() const { return have_sendrecv_v2_zstd_; }
bool HaveSendRecv2DryRunSend() const { return have_sendrecv_v2_dry_run_send_; }
// Resolve a compression type which might be CompressionType::Any to a specific compression
// algorithm.
CompressionType ResolveCompressionType(CompressionType compression) const {
if (compression == CompressionType::Any) {
- if (HaveSendRecv2LZ4()) {
+ if (HaveSendRecv2Zstd()) {
+ return CompressionType::Zstd;
+ } else if (HaveSendRecv2LZ4()) {
return CompressionType::LZ4;
} else if (HaveSendRecv2Brotli()) {
return CompressionType::Brotli;
@@ -374,6 +378,10 @@
msg.send_v2_setup.flags = kSyncFlagLZ4;
break;
+ case CompressionType::Zstd:
+ msg.send_v2_setup.flags = kSyncFlagZstd;
+ break;
+
case CompressionType::Any:
LOG(FATAL) << "unexpected CompressionType::Any";
}
@@ -421,6 +429,10 @@
msg.recv_v2_setup.flags |= kSyncFlagLZ4;
break;
+ case CompressionType::Zstd:
+ msg.recv_v2_setup.flags |= kSyncFlagZstd;
+ break;
+
case CompressionType::Any:
LOG(FATAL) << "unexpected CompressionType::Any";
}
@@ -631,7 +643,8 @@
syncsendbuf sbuf;
sbuf.id = ID_DATA;
- std::variant<std::monostate, NullEncoder, BrotliEncoder, LZ4Encoder> encoder_storage;
+ std::variant<std::monostate, NullEncoder, BrotliEncoder, LZ4Encoder, ZstdEncoder>
+ encoder_storage;
Encoder* encoder = nullptr;
switch (compression) {
case CompressionType::None:
@@ -646,6 +659,10 @@
encoder = &encoder_storage.emplace<LZ4Encoder>(SYNC_DATA_MAX);
break;
+ case CompressionType::Zstd:
+ encoder = &encoder_storage.emplace<ZstdEncoder>(SYNC_DATA_MAX);
+ break;
+
case CompressionType::Any:
LOG(FATAL) << "unexpected CompressionType::Any";
}
@@ -928,6 +945,7 @@
bool have_sendrecv_v2_;
bool have_sendrecv_v2_brotli_;
bool have_sendrecv_v2_lz4_;
+ bool have_sendrecv_v2_zstd_;
bool have_sendrecv_v2_dry_run_send_;
TransferLedger global_ledger_;
@@ -1133,7 +1151,8 @@
uint64_t bytes_copied = 0;
Block buffer(SYNC_DATA_MAX);
- std::variant<std::monostate, NullDecoder, BrotliDecoder, LZ4Decoder> decoder_storage;
+ std::variant<std::monostate, NullDecoder, BrotliDecoder, LZ4Decoder, ZstdDecoder>
+ decoder_storage;
Decoder* decoder = nullptr;
std::span buffer_span(buffer.data(), buffer.size());
@@ -1150,6 +1169,10 @@
decoder = &decoder_storage.emplace<LZ4Decoder>(buffer_span);
break;
+ case CompressionType::Zstd:
+ decoder = &decoder_storage.emplace<ZstdDecoder>(buffer_span);
+ break;
+
case CompressionType::Any:
LOG(FATAL) << "unexpected CompressionType::Any";
}
diff --git a/adb/client/incremental.cpp b/adb/client/incremental.cpp
index a8b0ab3..1e985ed 100644
--- a/adb/client/incremental.cpp
+++ b/adb/client/incremental.cpp
@@ -42,7 +42,7 @@
struct stat st;
if (stat(signature_file.c_str(), &st)) {
if (!silent) {
- fprintf(stderr, "Failed to stat signature file %s. Abort.\n", signature_file.c_str());
+ fprintf(stderr, "Failed to stat signature file %s.\n", signature_file.c_str());
}
return {};
}
@@ -50,11 +50,21 @@
unique_fd fd(adb_open(signature_file.c_str(), O_RDONLY));
if (fd < 0) {
if (!silent) {
- fprintf(stderr, "Failed to open signature file: %s. Abort.\n", signature_file.c_str());
+ fprintf(stderr, "Failed to open signature file: %s.\n", signature_file.c_str());
}
return {};
}
+ std::vector<char> invalid_signature;
+
+ if (st.st_size > kMaxSignatureSize) {
+ if (!silent) {
+ fprintf(stderr, "Signature is too long. Max allowed is %d. Abort.\n",
+ kMaxSignatureSize);
+ }
+ return {std::move(fd), std::move(invalid_signature)};
+ }
+
auto [signature, tree_size] = read_id_sig_headers(fd);
if (auto expected = verity_tree_size_for_file(file_size); tree_size != expected) {
if (!silent) {
@@ -62,7 +72,7 @@
"Verity tree size mismatch in signature file: %s [was %lld, expected %lld].\n",
signature_file.c_str(), (long long)tree_size, (long long)expected);
}
- return {};
+ return {std::move(fd), std::move(invalid_signature)};
}
return {std::move(fd), std::move(signature)};
@@ -72,9 +82,11 @@
static std::pair<unique_fd, std::string> read_and_encode_signature(Size file_size,
std::string signature_file,
bool silent) {
+ std::string encoded_signature;
+
auto [fd, signature] = read_signature(file_size, std::move(signature_file), silent);
- if (!fd.ok()) {
- return {};
+ if (!fd.ok() || signature.empty()) {
+ return {std::move(fd), std::move(encoded_signature)};
}
size_t base64_len = 0;
@@ -82,9 +94,10 @@
if (!silent) {
fprintf(stderr, "Fail to estimate base64 encoded length. Abort.\n");
}
- return {};
+ return {std::move(fd), std::move(encoded_signature)};
}
- std::string encoded_signature(base64_len, '\0');
+
+ encoded_signature.resize(base64_len, '\0');
encoded_signature.resize(EVP_EncodeBlock((uint8_t*)encoded_signature.data(),
(const uint8_t*)signature.data(), signature.size()));
@@ -109,7 +122,7 @@
}
auto [signature_fd, signature] = read_and_encode_signature(st.st_size, file, silent);
- if (!signature_fd.ok()) {
+ if (signature_fd.ok() && signature.empty()) {
return {};
}
@@ -138,9 +151,12 @@
return false;
}
- auto [fd, _] = read_signature(st.st_size, file, true);
- if (!fd.ok()) {
- return false;
+ if (android::base::EndsWithIgnoreCase(file, ".apk")) {
+ // Signature has to be present for APKs.
+ auto [fd, _] = read_signature(st.st_size, file, /*silent=*/true);
+ if (!fd.ok()) {
+ return false;
+ }
}
}
return true;
diff --git a/adb/client/incremental_server.cpp b/adb/client/incremental_server.cpp
index bfe18c0..0654a11 100644
--- a/adb/client/incremental_server.cpp
+++ b/adb/client/incremental_server.cpp
@@ -171,6 +171,8 @@
const std::vector<BlockIdx>& PriorityBlocks() const { return priority_blocks_; }
+ bool hasTree() const { return tree_fd_.ok(); }
+
std::vector<bool> sentBlocks;
NumBlocks sentBlocksCount = 0;
@@ -349,6 +351,9 @@
bool IncrementalServer::SendTreeBlocksForDataBlock(const FileId fileId, const BlockIdx blockIdx) {
auto& file = files_[fileId];
+ if (!file.hasTree()) {
+ return true;
+ }
const int32_t data_block_count = numBytesToNumBlocks(file.size);
const int32_t total_nodes_count(file.sentTreeBlocks.size());
@@ -670,7 +675,8 @@
unique_fd fd(adb_open(signature_file.c_str(), O_RDONLY));
if (fd < 0) {
- error_exit("inc-server: failed to open file '%s'.", signature_file.c_str());
+ D("No signature file found for '%s'('%s')", filepath, signature_file.c_str());
+ return {};
}
auto [tree_offset, tree_size] = skip_id_sig_headers(fd);
diff --git a/adb/client/incremental_utils.h b/adb/client/incremental_utils.h
index fe2914d..4ad60dd 100644
--- a/adb/client/incremental_utils.h
+++ b/adb/client/incremental_utils.h
@@ -33,6 +33,7 @@
constexpr int kBlockSize = 4096;
constexpr int kSha256DigestSize = 32;
constexpr int kDigestSize = kSha256DigestSize;
+constexpr int kMaxSignatureSize = 8096; // incrementalfs.h
constexpr std::string_view IDSIG = ".idsig";
diff --git a/adb/compression_utils.h b/adb/compression_utils.h
index a0c48a2..a747108 100644
--- a/adb/compression_utils.h
+++ b/adb/compression_utils.h
@@ -25,6 +25,7 @@
#include <brotli/decode.h>
#include <brotli/encode.h>
#include <lz4frame.h>
+#include <zstd.h>
#include "types.h"
@@ -381,3 +382,105 @@
std::unique_ptr<LZ4F_cctx, LZ4F_errorCode_t (*)(LZ4F_cctx*)> encoder_;
IOVector output_buffer_;
};
+
+struct ZstdDecoder final : public Decoder {
+ explicit ZstdDecoder(std::span<char> output_buffer)
+ : Decoder(output_buffer), decoder_(ZSTD_createDStream(), ZSTD_freeDStream) {
+ if (!decoder_) {
+ LOG(FATAL) << "failed to initialize Zstd decompression context";
+ }
+ }
+
+ DecodeResult Decode(std::span<char>* output) final {
+ ZSTD_inBuffer in;
+ in.src = input_buffer_.front_data();
+ in.size = input_buffer_.front_size();
+ in.pos = 0;
+
+ ZSTD_outBuffer out;
+ out.dst = output_buffer_.data();
+ // The standard specifies size() as returning size_t, but our current version of
+ // libc++ returns a signed value instead.
+ out.size = static_cast<size_t>(output_buffer_.size());
+ out.pos = 0;
+
+ size_t rc = ZSTD_decompressStream(decoder_.get(), &out, &in);
+ if (ZSTD_isError(rc)) {
+ LOG(ERROR) << "ZSTD_decompressStream failed: " << ZSTD_getErrorName(rc);
+ return DecodeResult::Error;
+ }
+
+ input_buffer_.drop_front(in.pos);
+ if (rc == 0) {
+ if (!input_buffer_.empty()) {
+ LOG(ERROR) << "Zstd stream hit end before reading all data";
+ return DecodeResult::Error;
+ }
+ zstd_done_ = true;
+ }
+
+ *output = std::span<char>(output_buffer_.data(), out.pos);
+
+ if (finished_) {
+ return input_buffer_.empty() && zstd_done_ ? DecodeResult::Done
+ : DecodeResult::MoreOutput;
+ }
+ return DecodeResult::NeedInput;
+ }
+
+ private:
+ bool zstd_done_ = false;
+ std::unique_ptr<ZSTD_DStream, size_t (*)(ZSTD_DStream*)> decoder_;
+};
+
+struct ZstdEncoder final : public Encoder {
+ explicit ZstdEncoder(size_t output_block_size)
+ : Encoder(output_block_size), encoder_(ZSTD_createCStream(), ZSTD_freeCStream) {
+ if (!encoder_) {
+ LOG(FATAL) << "failed to initialize Zstd compression context";
+ }
+ ZSTD_CCtx_setParameter(encoder_.get(), ZSTD_c_compressionLevel, 1);
+ }
+
+ EncodeResult Encode(Block* output) final {
+ ZSTD_inBuffer in;
+ in.src = input_buffer_.front_data();
+ in.size = input_buffer_.front_size();
+ in.pos = 0;
+
+ output->resize(output_block_size_);
+
+ ZSTD_outBuffer out;
+ out.dst = output->data();
+ out.size = static_cast<size_t>(output->size());
+ out.pos = 0;
+
+ ZSTD_EndDirective end_directive = finished_ ? ZSTD_e_end : ZSTD_e_continue;
+ size_t rc = ZSTD_compressStream2(encoder_.get(), &out, &in, end_directive);
+ if (ZSTD_isError(rc)) {
+ LOG(ERROR) << "ZSTD_compressStream2 failed: " << ZSTD_getErrorName(rc);
+ return EncodeResult::Error;
+ }
+
+ input_buffer_.drop_front(in.pos);
+ output->resize(out.pos);
+
+ if (rc == 0) {
+ // Zstd finished flushing its data.
+ if (finished_) {
+ if (!input_buffer_.empty()) {
+ LOG(ERROR) << "ZSTD_compressStream2 finished early";
+ return EncodeResult::Error;
+ }
+ return EncodeResult::Done;
+ } else {
+ return input_buffer_.empty() ? EncodeResult::NeedInput : EncodeResult::MoreOutput;
+ }
+ } else {
+ return EncodeResult::MoreOutput;
+ }
+ }
+
+ private:
+ std::unique_ptr<ZSTD_CStream, size_t (*)(ZSTD_CStream*)> encoder_;
+};
diff --git a/adb/daemon/file_sync_service.cpp b/adb/daemon/file_sync_service.cpp
index d58131e..513b8dd 100644
--- a/adb/daemon/file_sync_service.cpp
+++ b/adb/daemon/file_sync_service.cpp
@@ -272,7 +272,8 @@
syncmsg msg;
Block buffer(SYNC_DATA_MAX);
std::span<char> buffer_span(buffer.data(), buffer.size());
- std::variant<std::monostate, NullDecoder, BrotliDecoder, LZ4Decoder> decoder_storage;
+ std::variant<std::monostate, NullDecoder, BrotliDecoder, LZ4Decoder, ZstdDecoder>
+ decoder_storage;
Decoder* decoder = nullptr;
switch (compression) {
@@ -288,6 +289,10 @@
decoder = &decoder_storage.emplace<LZ4Decoder>(buffer_span);
break;
+ case CompressionType::Zstd:
+ decoder = &decoder_storage.emplace<ZstdDecoder>(buffer_span);
+ break;
+
case CompressionType::Any:
LOG(FATAL) << "unexpected CompressionType::Any";
}
@@ -590,6 +595,15 @@
}
compression = CompressionType::LZ4;
}
+ if (msg.send_v2_setup.flags & kSyncFlagZstd) {
+ msg.send_v2_setup.flags &= ~kSyncFlagZstd;
+ if (compression) {
+ SendSyncFail(s, android::base::StringPrintf("multiple compression flags received: %d",
+ orig_flags));
+ return false;
+ }
+ compression = CompressionType::Zstd;
+ }
if (msg.send_v2_setup.flags & kSyncFlagDryRun) {
msg.send_v2_setup.flags &= ~kSyncFlagDryRun;
dry_run = true;
@@ -623,7 +637,8 @@
syncmsg msg;
msg.data.id = ID_DATA;
- std::variant<std::monostate, NullEncoder, BrotliEncoder, LZ4Encoder> encoder_storage;
+ std::variant<std::monostate, NullEncoder, BrotliEncoder, LZ4Encoder, ZstdEncoder>
+ encoder_storage;
Encoder* encoder;
switch (compression) {
@@ -639,6 +654,10 @@
encoder = &encoder_storage.emplace<LZ4Encoder>(SYNC_DATA_MAX);
break;
+ case CompressionType::Zstd:
+ encoder = &encoder_storage.emplace<ZstdEncoder>(SYNC_DATA_MAX);
+ break;
+
case CompressionType::Any:
LOG(FATAL) << "unexpected CompressionType::Any";
}
@@ -726,6 +745,15 @@
}
compression = CompressionType::LZ4;
}
+ if (msg.recv_v2_setup.flags & kSyncFlagZstd) {
+ msg.recv_v2_setup.flags &= ~kSyncFlagZstd;
+ if (compression) {
+ SendSyncFail(s, android::base::StringPrintf("multiple compression flags received: %d",
+ orig_flags));
+ return false;
+ }
+ compression = CompressionType::Zstd;
+ }
if (msg.recv_v2_setup.flags) {
SendSyncFail(s, android::base::StringPrintf("unknown flags: %d", msg.recv_v2_setup.flags));
diff --git a/adb/file_sync_protocol.h b/adb/file_sync_protocol.h
index 8f8f85f..5234c20 100644
--- a/adb/file_sync_protocol.h
+++ b/adb/file_sync_protocol.h
@@ -93,6 +93,7 @@
kSyncFlagNone = 0,
kSyncFlagBrotli = 1,
kSyncFlagLZ4 = 2,
+ kSyncFlagZstd = 4,
kSyncFlagDryRun = 0x8000'0000U,
};
@@ -101,6 +102,7 @@
Any,
Brotli,
LZ4,
+ Zstd,
};
// send_v1 sent the path in a buffer, followed by a comma and the mode as a string.
diff --git a/adb/test_device.py b/adb/test_device.py
index 9f1f403..c1caafc 100755
--- a/adb/test_device.py
+++ b/adb/test_device.py
@@ -1362,6 +1362,10 @@
compression = "lz4"
+class FileOperationsTestZstd(FileOperationsTest.Base):
+ compression = "zstd"
+
+
class DeviceOfflineTest(DeviceTest):
def _get_device_state(self, serialno):
output = subprocess.check_output(self.device.adb_cmd + ['devices'])
diff --git a/adb/tools/check_ms_os_desc.cpp b/adb/tools/check_ms_os_desc.cpp
index 8743ff7..8e85809 100644
--- a/adb/tools/check_ms_os_desc.cpp
+++ b/adb/tools/check_ms_os_desc.cpp
@@ -131,8 +131,6 @@
errx(1, "failed to retrieve MS OS v1 compat descriptor: %s", libusb_error_name(rc));
}
- memcpy(&hdr, data.data(), data.size());
-
struct __attribute__((packed)) ms_os_desc_v1_function {
uint8_t bFirstInterfaceNumber;
uint8_t reserved1;
diff --git a/adb/transport.cpp b/adb/transport.cpp
index 1667011..b6b6984 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -85,6 +85,7 @@
const char* const kFeatureSendRecv2 = "sendrecv_v2";
const char* const kFeatureSendRecv2Brotli = "sendrecv_v2_brotli";
const char* const kFeatureSendRecv2LZ4 = "sendrecv_v2_lz4";
+const char* const kFeatureSendRecv2Zstd = "sendrecv_v2_zstd";
const char* const kFeatureSendRecv2DryRunSend = "sendrecv_v2_dry_run_send";
namespace {
@@ -1189,6 +1190,7 @@
kFeatureSendRecv2,
kFeatureSendRecv2Brotli,
kFeatureSendRecv2LZ4,
+ kFeatureSendRecv2Zstd,
kFeatureSendRecv2DryRunSend,
// Increment ADB_SERVER_VERSION when adding a feature that adbd needs
// to know about. Otherwise, the client can be stuck running an old
diff --git a/adb/transport.h b/adb/transport.h
index 2ac21cf..b1f2744 100644
--- a/adb/transport.h
+++ b/adb/transport.h
@@ -93,6 +93,8 @@
extern const char* const kFeatureSendRecv2Brotli;
// adbd supports LZ4 for send/recv v2.
extern const char* const kFeatureSendRecv2LZ4;
+// adbd supports Zstd for send/recv v2.
+extern const char* const kFeatureSendRecv2Zstd;
// adbd supports dry-run send for send/recv v2.
extern const char* const kFeatureSendRecv2DryRunSend;
diff --git a/logd/ChattyLogBuffer.cpp b/logd/ChattyLogBuffer.cpp
index c2e89fc..62c8629 100644
--- a/logd/ChattyLogBuffer.cpp
+++ b/logd/ChattyLogBuffer.cpp
@@ -74,7 +74,8 @@
}
// audit message (except sequence number) identical?
- if (last.IsBinary() && lenl > static_cast<ssize_t>(sizeof(android_log_event_string_t)) &&
+ if (IsBinary(last.log_id()) &&
+ lenl > static_cast<ssize_t>(sizeof(android_log_event_string_t)) &&
lenr > static_cast<ssize_t>(sizeof(android_log_event_string_t))) {
if (fastcmp<memcmp>(msgl, msgr, sizeof(android_log_event_string_t) - sizeof(int32_t))) {
return DIFFERENT;
@@ -205,9 +206,9 @@
#endif
if (coalesce) {
- stats()->Erase(element);
+ stats()->Erase(element.ToLogStatisticsElement());
} else {
- stats()->Subtract(element);
+ stats()->Subtract(element.ToLogStatisticsElement());
}
it = SimpleLogBuffer::Erase(it);
@@ -533,7 +534,7 @@
if (leading) {
it = Erase(it);
} else {
- stats()->Drop(element);
+ stats()->Drop(element.ToLogStatisticsElement());
element.SetDropped(1);
if (last.coalesce(&element, 1)) {
it = Erase(it, true);
diff --git a/logd/LogBufferElement.cpp b/logd/LogBufferElement.cpp
index 172a757..ef9f1cf 100644
--- a/logd/LogBufferElement.cpp
+++ b/logd/LogBufferElement.cpp
@@ -86,7 +86,7 @@
uint32_t LogBufferElement::GetTag() const {
// Binary buffers have no tag.
- if (!IsBinary()) {
+ if (!IsBinary(log_id())) {
return 0;
}
@@ -95,12 +95,21 @@
return tag_;
}
- // For non-dropped messages, we get the tag from the message header itself.
- if (msg_len_ < sizeof(android_event_header_t)) {
- return 0;
- }
+ return MsgToTag(msg(), msg_len());
+}
- return reinterpret_cast<const android_event_header_t*>(msg_)->tag;
+LogStatisticsElement LogBufferElement::ToLogStatisticsElement() const {
+ return LogStatisticsElement{
+ .uid = uid(),
+ .pid = pid(),
+ .tid = tid(),
+ .tag = GetTag(),
+ .realtime = realtime(),
+ .msg = msg(),
+ .msg_len = msg_len(),
+ .dropped_count = dropped_count(),
+ .log_id = log_id(),
+ };
}
uint16_t LogBufferElement::SetDropped(uint16_t value) {
@@ -218,7 +227,7 @@
type, dropped_count(), (dropped_count() > 1) ? "s" : "");
size_t hdrLen;
- if (IsBinary()) {
+ if (IsBinary(log_id())) {
hdrLen = sizeof(android_log_event_string_t);
} else {
hdrLen = 1 + sizeof(tag);
@@ -232,7 +241,7 @@
}
size_t retval = hdrLen + len;
- if (IsBinary()) {
+ if (IsBinary(log_id())) {
android_log_event_string_t* event =
reinterpret_cast<android_log_event_string_t*>(buffer);
diff --git a/logd/LogBufferElement.h b/logd/LogBufferElement.h
index 5b13e32..fd5d88f 100644
--- a/logd/LogBufferElement.h
+++ b/logd/LogBufferElement.h
@@ -24,7 +24,7 @@
#include "LogWriter.h"
-class LogStatistics;
+#include "LogStatistics.h"
#define EXPIRE_HOUR_THRESHOLD 24 // Only expire chatty UID logs to preserve
// non-chatty UIDs less than this age in hours
@@ -40,13 +40,13 @@
LogBufferElement(LogBufferElement&& elem);
~LogBufferElement();
- bool IsBinary() const { return (log_id_ == LOG_ID_EVENTS) || (log_id_ == LOG_ID_SECURITY); }
-
uint32_t GetTag() const;
uint16_t SetDropped(uint16_t value);
bool FlushTo(LogWriter* writer, LogStatistics* parent, bool lastSame);
+ LogStatisticsElement ToLogStatisticsElement() const;
+
log_id_t log_id() const { return static_cast<log_id_t>(log_id_); }
uid_t uid() const { return uid_; }
pid_t pid() const { return pid_; }
diff --git a/logd/LogStatistics.cpp b/logd/LogStatistics.cpp
index a2acab7..04fd59d 100644
--- a/logd/LogStatistics.cpp
+++ b/logd/LogStatistics.cpp
@@ -29,6 +29,8 @@
#include <private/android_logger.h>
+#include "LogBufferElement.h"
+
static const uint64_t hourSec = 60 * 60;
static const uint64_t monthSec = 31 * 24 * hourSec;
@@ -87,10 +89,10 @@
++mElementsTotal[log_id];
}
-void LogStatistics::Add(const LogBufferElement& element) {
+void LogStatistics::Add(const LogStatisticsElement& element) {
auto lock = std::lock_guard{lock_};
- log_id_t log_id = element.log_id();
- uint16_t size = element.msg_len();
+ log_id_t log_id = element.log_id;
+ uint16_t size = element.msg_len;
mSizes[log_id] += size;
++mElements[log_id];
@@ -99,7 +101,7 @@
// evaluated and trimmed, thus recording size and number of
// elements, but we must recognize the manufactured dropped
// entry as not contributing to the lifetime totals.
- if (element.dropped_count()) {
+ if (element.dropped_count) {
++mDroppedElements[log_id];
} else {
mSizesTotal[log_id] += size;
@@ -107,7 +109,7 @@
++mElementsTotal[log_id];
}
- log_time stamp(element.realtime());
+ log_time stamp(element.realtime);
if (mNewest[log_id] < stamp) {
// A major time update invalidates the statistics :-(
log_time diff = stamp - mNewest[log_id];
@@ -132,19 +134,19 @@
return;
}
- uidTable[log_id].Add(element.uid(), element);
- if (element.uid() == AID_SYSTEM) {
- pidSystemTable[log_id].Add(element.pid(), element);
+ uidTable[log_id].Add(element.uid, element);
+ if (element.uid == AID_SYSTEM) {
+ pidSystemTable[log_id].Add(element.pid, element);
}
if (!enable) {
return;
}
- pidTable.Add(element.pid(), element);
- tidTable.Add(element.tid(), element);
+ pidTable.Add(element.pid, element);
+ tidTable.Add(element.tid, element);
- uint32_t tag = element.GetTag();
+ uint32_t tag = element.tag;
if (tag) {
if (log_id == LOG_ID_SECURITY) {
securityTagTable.Add(tag, element);
@@ -153,42 +155,42 @@
}
}
- if (!element.dropped_count()) {
+ if (!element.dropped_count) {
tagNameTable.Add(TagNameKey(element), element);
}
}
-void LogStatistics::Subtract(const LogBufferElement& element) {
+void LogStatistics::Subtract(const LogStatisticsElement& element) {
auto lock = std::lock_guard{lock_};
- log_id_t log_id = element.log_id();
- uint16_t size = element.msg_len();
+ log_id_t log_id = element.log_id;
+ uint16_t size = element.msg_len;
mSizes[log_id] -= size;
--mElements[log_id];
- if (element.dropped_count()) {
+ if (element.dropped_count) {
--mDroppedElements[log_id];
}
- if (mOldest[log_id] < element.realtime()) {
- mOldest[log_id] = element.realtime();
+ if (mOldest[log_id] < element.realtime) {
+ mOldest[log_id] = element.realtime;
}
if (log_id == LOG_ID_KERNEL) {
return;
}
- uidTable[log_id].Subtract(element.uid(), element);
- if (element.uid() == AID_SYSTEM) {
- pidSystemTable[log_id].Subtract(element.pid(), element);
+ uidTable[log_id].Subtract(element.uid, element);
+ if (element.uid == AID_SYSTEM) {
+ pidSystemTable[log_id].Subtract(element.pid, element);
}
if (!enable) {
return;
}
- pidTable.Subtract(element.pid(), element);
- tidTable.Subtract(element.tid(), element);
+ pidTable.Subtract(element.pid, element);
+ tidTable.Subtract(element.tid, element);
- uint32_t tag = element.GetTag();
+ uint32_t tag = element.tag;
if (tag) {
if (log_id == LOG_ID_SECURITY) {
securityTagTable.Subtract(tag, element);
@@ -197,37 +199,37 @@
}
}
- if (!element.dropped_count()) {
+ if (!element.dropped_count) {
tagNameTable.Subtract(TagNameKey(element), element);
}
}
// Atomically set an entry to drop
// entry->setDropped(1) must follow this call, caller should do this explicitly.
-void LogStatistics::Drop(const LogBufferElement& element) {
+void LogStatistics::Drop(const LogStatisticsElement& element) {
auto lock = std::lock_guard{lock_};
- log_id_t log_id = element.log_id();
- uint16_t size = element.msg_len();
+ log_id_t log_id = element.log_id;
+ uint16_t size = element.msg_len;
mSizes[log_id] -= size;
++mDroppedElements[log_id];
- if (mNewestDropped[log_id] < element.realtime()) {
- mNewestDropped[log_id] = element.realtime();
+ if (mNewestDropped[log_id] < element.realtime) {
+ mNewestDropped[log_id] = element.realtime;
}
- uidTable[log_id].Drop(element.uid(), element);
- if (element.uid() == AID_SYSTEM) {
- pidSystemTable[log_id].Drop(element.pid(), element);
+ uidTable[log_id].Drop(element.uid, element);
+ if (element.uid == AID_SYSTEM) {
+ pidSystemTable[log_id].Drop(element.pid, element);
}
if (!enable) {
return;
}
- pidTable.Drop(element.pid(), element);
- tidTable.Drop(element.tid(), element);
+ pidTable.Drop(element.pid, element);
+ tidTable.Drop(element.tid, element);
- uint32_t tag = element.GetTag();
+ uint32_t tag = element.tag;
if (tag) {
if (log_id == LOG_ID_SECURITY) {
securityTagTable.Drop(tag, element);
diff --git a/logd/LogStatistics.h b/logd/LogStatistics.h
index 6a46adb..33a4d63 100644
--- a/logd/LogStatistics.h
+++ b/logd/LogStatistics.h
@@ -38,7 +38,6 @@
#include <private/android_filesystem_config.h>
#include <utils/FastStrcmp.h>
-#include "LogBufferElement.h"
#include "LogUtils.h"
#define log_id_for_each(i) \
@@ -46,6 +45,18 @@
class LogStatistics;
+struct LogStatisticsElement {
+ uid_t uid;
+ pid_t pid;
+ pid_t tid;
+ uint32_t tag;
+ log_time realtime;
+ const char* msg;
+ uint16_t msg_len;
+ uint16_t dropped_count;
+ log_id_t log_id;
+};
+
template <typename TKey, typename TEntry>
class LogHashtable {
std::unordered_map<TKey, TEntry> map;
@@ -113,7 +124,7 @@
}
}
- iterator Add(const TKey& key, const LogBufferElement& element) {
+ iterator Add(const TKey& key, const LogStatisticsElement& element) {
iterator it = map.find(key);
if (it == map.end()) {
it = map.insert(std::make_pair(key, TEntry(element))).first;
@@ -133,14 +144,14 @@
return it;
}
- void Subtract(const TKey& key, const LogBufferElement& element) {
+ void Subtract(const TKey& key, const LogStatisticsElement& element) {
iterator it = map.find(key);
if (it != map.end() && it->second.Subtract(element)) {
map.erase(it);
}
}
- void Drop(const TKey& key, const LogBufferElement& element) {
+ void Drop(const TKey& key, const LogStatisticsElement& element) {
iterator it = map.find(key);
if (it != map.end()) {
it->second.Drop(element);
@@ -156,13 +167,13 @@
class EntryBase {
public:
EntryBase() : size_(0) {}
- explicit EntryBase(const LogBufferElement& element) : size_(element.msg_len()) {}
+ explicit EntryBase(const LogStatisticsElement& element) : size_(element.msg_len) {}
size_t getSizes() const { return size_; }
- void Add(const LogBufferElement& element) { size_ += element.msg_len(); }
- bool Subtract(const LogBufferElement& element) {
- size_ -= element.msg_len();
+ void Add(const LogStatisticsElement& element) { size_ += element.msg_len; }
+ bool Subtract(const LogStatisticsElement& element) {
+ size_ -= element.msg_len;
return !size_;
}
@@ -193,20 +204,20 @@
class EntryBaseDropped : public EntryBase {
public:
EntryBaseDropped() : dropped_(0) {}
- explicit EntryBaseDropped(const LogBufferElement& element)
- : EntryBase(element), dropped_(element.dropped_count()) {}
+ explicit EntryBaseDropped(const LogStatisticsElement& element)
+ : EntryBase(element), dropped_(element.dropped_count) {}
size_t dropped_count() const { return dropped_; }
- void Add(const LogBufferElement& element) {
- dropped_ += element.dropped_count();
+ void Add(const LogStatisticsElement& element) {
+ dropped_ += element.dropped_count;
EntryBase::Add(element);
}
- bool Subtract(const LogBufferElement& element) {
- dropped_ -= element.dropped_count();
+ bool Subtract(const LogStatisticsElement& element) {
+ dropped_ -= element.dropped_count;
return EntryBase::Subtract(element) && !dropped_;
}
- void Drop(const LogBufferElement& element) {
+ void Drop(const LogStatisticsElement& element) {
dropped_ += 1;
EntryBase::Subtract(element);
}
@@ -217,15 +228,15 @@
class UidEntry : public EntryBaseDropped {
public:
- explicit UidEntry(const LogBufferElement& element)
- : EntryBaseDropped(element), uid_(element.uid()), pid_(element.pid()) {}
+ explicit UidEntry(const LogStatisticsElement& element)
+ : EntryBaseDropped(element), uid_(element.uid), pid_(element.pid) {}
uid_t key() const { return uid_; }
uid_t uid() const { return key(); }
pid_t pid() const { return pid_; }
- void Add(const LogBufferElement& element) {
- if (pid_ != element.pid()) {
+ void Add(const LogStatisticsElement& element) {
+ if (pid_ != element.pid) {
pid_ = -1;
}
EntryBaseDropped::Add(element);
@@ -250,10 +261,10 @@
pid_(pid),
uid_(android::pidToUid(pid)),
name_(android::pidToName(pid)) {}
- explicit PidEntry(const LogBufferElement& element)
+ explicit PidEntry(const LogStatisticsElement& element)
: EntryBaseDropped(element),
- pid_(element.pid()),
- uid_(element.uid()),
+ pid_(element.pid),
+ uid_(element.uid),
name_(android::pidToName(pid_)) {}
PidEntry(const PidEntry& element)
: EntryBaseDropped(element),
@@ -277,14 +288,14 @@
}
}
- void Add(const LogBufferElement& element) {
- uid_t incoming_uid = element.uid();
+ void Add(const LogStatisticsElement& element) {
+ uid_t incoming_uid = element.uid;
if (uid() != incoming_uid) {
uid_ = incoming_uid;
free(name_);
- name_ = android::pidToName(element.pid());
+ name_ = android::pidToName(element.pid);
} else {
- Add(element.pid());
+ Add(element.pid);
}
EntryBaseDropped::Add(element);
}
@@ -306,11 +317,11 @@
pid_(pid),
uid_(android::pidToUid(tid)),
name_(android::tidToName(tid)) {}
- explicit TidEntry(const LogBufferElement& element)
+ explicit TidEntry(const LogStatisticsElement& element)
: EntryBaseDropped(element),
- tid_(element.tid()),
- pid_(element.pid()),
- uid_(element.uid()),
+ tid_(element.tid),
+ pid_(element.pid),
+ uid_(element.uid),
name_(android::tidToName(tid_)) {}
TidEntry(const TidEntry& element)
: EntryBaseDropped(element),
@@ -336,16 +347,16 @@
}
}
- void Add(const LogBufferElement& element) {
- uid_t incoming_uid = element.uid();
- pid_t incoming_pid = element.pid();
+ void Add(const LogStatisticsElement& element) {
+ uid_t incoming_uid = element.uid;
+ pid_t incoming_pid = element.pid;
if (uid() != incoming_uid || pid() != incoming_pid) {
uid_ = incoming_uid;
pid_ = incoming_pid;
free(name_);
- name_ = android::tidToName(element.tid());
+ name_ = android::tidToName(element.tid);
} else {
- Add(element.tid());
+ Add(element.tid);
}
EntryBaseDropped::Add(element);
}
@@ -362,22 +373,19 @@
class TagEntry : public EntryBaseDropped {
public:
- explicit TagEntry(const LogBufferElement& element)
- : EntryBaseDropped(element),
- tag_(element.GetTag()),
- pid_(element.pid()),
- uid_(element.uid()) {}
+ explicit TagEntry(const LogStatisticsElement& element)
+ : EntryBaseDropped(element), tag_(element.tag), pid_(element.pid), uid_(element.uid) {}
uint32_t key() const { return tag_; }
pid_t pid() const { return pid_; }
uid_t uid() const { return uid_; }
const char* name() const { return android::tagToName(tag_); }
- void Add(const LogBufferElement& element) {
- if (uid_ != element.uid()) {
+ void Add(const LogStatisticsElement& element) {
+ if (uid_ != element.uid) {
uid_ = -1;
}
- if (pid_ != element.pid()) {
+ if (pid_ != element.pid) {
pid_ = -1;
}
EntryBaseDropped::Add(element);
@@ -396,9 +404,10 @@
std::string* alloc;
std::string_view name; // Saves space if const char*
- explicit TagNameKey(const LogBufferElement& element) : alloc(nullptr), name("", strlen("")) {
- if (element.IsBinary()) {
- uint32_t tag = element.GetTag();
+ explicit TagNameKey(const LogStatisticsElement& element)
+ : alloc(nullptr), name("", strlen("")) {
+ if (IsBinary(element.log_id)) {
+ uint32_t tag = element.tag;
if (tag) {
const char* cp = android::tagToName(tag);
if (cp) {
@@ -412,13 +421,13 @@
name = std::string_view(alloc->c_str(), alloc->size());
return;
}
- const char* msg = element.msg();
+ const char* msg = element.msg;
if (!msg) {
name = std::string_view("chatty", strlen("chatty"));
return;
}
++msg;
- uint16_t len = element.msg_len();
+ uint16_t len = element.msg_len;
len = (len <= 1) ? 0 : strnlen(msg, len - 1);
if (!len) {
name = std::string_view("<NULL>", strlen("<NULL>"));
@@ -480,11 +489,11 @@
class TagNameEntry : public EntryBase {
public:
- explicit TagNameEntry(const LogBufferElement& element)
+ explicit TagNameEntry(const LogStatisticsElement& element)
: EntryBase(element),
- tid_(element.tid()),
- pid_(element.pid()),
- uid_(element.uid()),
+ tid_(element.tid),
+ pid_(element.pid),
+ uid_(element.uid),
name_(element) {}
const TagNameKey& key() const { return name_; }
@@ -494,14 +503,14 @@
const char* name() const { return name_.data(); }
size_t getNameAllocLength() const { return name_.getAllocLength(); }
- void Add(const LogBufferElement& element) {
- if (uid_ != element.uid()) {
+ void Add(const LogStatisticsElement& element) {
+ if (uid_ != element.uid) {
uid_ = -1;
}
- if (pid_ != element.pid()) {
+ if (pid_ != element.pid) {
pid_ = -1;
}
- if (tid_ != element.tid()) {
+ if (tid_ != element.tid) {
tid_ = -1;
}
EntryBase::Add(element);
@@ -590,14 +599,14 @@
LogStatistics(bool enable_statistics);
void AddTotal(log_id_t log_id, uint16_t size) EXCLUDES(lock_);
- void Add(const LogBufferElement& entry) EXCLUDES(lock_);
- void Subtract(const LogBufferElement& entry) EXCLUDES(lock_);
+ void Add(const LogStatisticsElement& entry) EXCLUDES(lock_);
+ void Subtract(const LogStatisticsElement& entry) EXCLUDES(lock_);
// entry->setDropped(1) must follow this call
- void Drop(const LogBufferElement& entry) EXCLUDES(lock_);
+ void Drop(const LogStatisticsElement& entry) EXCLUDES(lock_);
// Correct for coalescing two entries referencing dropped content
- void Erase(const LogBufferElement& element) EXCLUDES(lock_) {
+ void Erase(const LogStatisticsElement& element) EXCLUDES(lock_) {
auto lock = std::lock_guard{lock_};
- log_id_t log_id = element.log_id();
+ log_id_t log_id = element.log_id;
--mElements[log_id];
--mDroppedElements[log_id];
}
diff --git a/logd/LogUtils.h b/logd/LogUtils.h
index c472167..96aa1d3 100644
--- a/logd/LogUtils.h
+++ b/logd/LogUtils.h
@@ -60,6 +60,20 @@
}
}
+// Returns true if the log buffer is meant for binary logs.
+static inline bool IsBinary(log_id_t log_id) {
+ return log_id == LOG_ID_EVENTS || log_id == LOG_ID_STATS || log_id == LOG_ID_SECURITY;
+}
+
+// Returns the numeric log tag for binary log messages.
+static inline uint32_t MsgToTag(const char* msg, uint16_t msg_len) {
+ if (msg_len < sizeof(android_event_header_t)) {
+ return 0;
+ }
+
+ return reinterpret_cast<const android_event_header_t*>(msg)->tag;
+}
+
static inline bool worstUidEnabledForLogid(log_id_t id) {
return (id == LOG_ID_MAIN) || (id == LOG_ID_SYSTEM) ||
(id == LOG_ID_RADIO) || (id == LOG_ID_EVENTS);
diff --git a/logd/SimpleLogBuffer.cpp b/logd/SimpleLogBuffer.cpp
index 5ab8e09..b4b3546 100644
--- a/logd/SimpleLogBuffer.cpp
+++ b/logd/SimpleLogBuffer.cpp
@@ -61,11 +61,8 @@
int prio = ANDROID_LOG_INFO;
const char* tag = nullptr;
size_t tag_len = 0;
- if (log_id == LOG_ID_EVENTS || log_id == LOG_ID_STATS) {
- if (len < sizeof(android_event_header_t)) {
- return false;
- }
- int32_t numeric_tag = reinterpret_cast<const android_event_header_t*>(msg)->tag;
+ if (IsBinary(log_id)) {
+ int32_t numeric_tag = MsgToTag(msg, len);
tag = tags_->tagToName(numeric_tag);
if (tag) {
tag_len = strlen(tag);
@@ -105,7 +102,7 @@
log_id_t log_id = elem.log_id();
logs_.emplace_back(std::move(elem));
- stats_->Add(logs_.back());
+ stats_->Add(logs_.back().ToLogStatisticsElement());
MaybePrune(log_id);
reader_list_->NotifyNewLog(1 << log_id);
}
@@ -317,7 +314,7 @@
return true;
}
- stats_->Subtract(element);
+ stats_->Subtract(element.ToLogStatisticsElement());
it = Erase(it);
if (--prune_rows == 0) {
return false;