Merge "Revert "Temporarily disable init_kill_services_test.""
diff --git a/adb/client/adb_install.cpp b/adb/client/adb_install.cpp
index d6f536e..ea50f59 100644
--- a/adb/client/adb_install.cpp
+++ b/adb/client/adb_install.cpp
@@ -876,7 +876,7 @@
"-S",
std::to_string(sb.st_size),
session_id_str,
- android::base::StringPrintf("%d_%s", i, android::base::Basename(file).c_str()),
+ android::base::StringPrintf("%d_%s", i, android::base::Basename(split).c_str()),
"-",
};
diff --git a/adb/client/auth.cpp b/adb/client/auth.cpp
index b674a81..db4c479 100644
--- a/adb/client/auth.cpp
+++ b/adb/client/auth.cpp
@@ -400,12 +400,12 @@
for (const std::string& path : paths) {
int wd = inotify_add_watch(infd, path.c_str(), IN_CREATE | IN_MOVED_TO);
if (wd < 0) {
- PLOG(ERROR) << "failed to inotify_add_watch on path '" << path;
+ PLOG(ERROR) << "failed to inotify_add_watch on path '" << path << "'";
continue;
}
g_monitored_paths[wd] = path;
- LOG(INFO) << "watch descriptor " << wd << " registered for " << path;
+ LOG(INFO) << "watch descriptor " << wd << " registered for '" << path << "'";
}
fdevent* event = fdevent_create(infd, adb_auth_inotify_update, nullptr);
diff --git a/code_coverage/seccomp_policy/code_coverage.arm.policy b/code_coverage/seccomp_policy/code_coverage.arm.policy
index d6784e3..b80910f 100644
--- a/code_coverage/seccomp_policy/code_coverage.arm.policy
+++ b/code_coverage/seccomp_policy/code_coverage.arm.policy
@@ -6,6 +6,7 @@
write: 1
fcntl64: 1
fstat64: 1
+ftruncate64: 1
geteuid32: 1
_llseek: 1
mmap2: 1
diff --git a/code_coverage/seccomp_policy/code_coverage.arm64.policy b/code_coverage/seccomp_policy/code_coverage.arm64.policy
index 4c3dd26..7040ea2 100644
--- a/code_coverage/seccomp_policy/code_coverage.arm64.policy
+++ b/code_coverage/seccomp_policy/code_coverage.arm64.policy
@@ -6,6 +6,7 @@
write: 1
fcntl: 1
fstat: 1
+ftruncate: 1
geteuid: 1
lseek: 1
mmap: 1
diff --git a/code_coverage/seccomp_policy/code_coverage.policy.def b/code_coverage/seccomp_policy/code_coverage.policy.def
index f136084..599c4a4 100644
--- a/code_coverage/seccomp_policy/code_coverage.policy.def
+++ b/code_coverage/seccomp_policy/code_coverage.policy.def
@@ -22,6 +22,7 @@
#if defined(__LP64__)
fcntl: 1
fstat: 1
+ftruncate: 1
geteuid: 1
lseek: 1
mmap: 1
@@ -29,6 +30,7 @@
#else
fcntl64: 1
fstat64: 1
+ftruncate64: 1
geteuid32: 1
_llseek: 1
mmap2: 1
diff --git a/code_coverage/seccomp_policy/code_coverage.x86.policy b/code_coverage/seccomp_policy/code_coverage.x86.policy
index 24ff8b9..f8e0cc0 100644
--- a/code_coverage/seccomp_policy/code_coverage.x86.policy
+++ b/code_coverage/seccomp_policy/code_coverage.x86.policy
@@ -6,6 +6,7 @@
write: 1
fcntl64: 1
fstat64: 1
+ftruncate64: 1
geteuid32: 1
_llseek: 1
mmap2: 1
diff --git a/code_coverage/seccomp_policy/code_coverage.x86_64.policy b/code_coverage/seccomp_policy/code_coverage.x86_64.policy
index 3081036..dcf2f9a 100644
--- a/code_coverage/seccomp_policy/code_coverage.x86_64.policy
+++ b/code_coverage/seccomp_policy/code_coverage.x86_64.policy
@@ -6,6 +6,7 @@
write: 1
fcntl: 1
fstat: 1
+ftruncate: 1
geteuid: 1
lseek: 1
mmap: 1
diff --git a/fastboot/fastboot.bash b/fastboot/fastboot.bash
index cb1d354..cc1366c 100644
--- a/fastboot/fastboot.bash
+++ b/fastboot/fastboot.bash
@@ -109,7 +109,7 @@
cur="${COMP_WORDS[COMP_CWORD]}"
if [[ $i -eq $COMP_CWORD ]]; then
- partitions="boot bootloader dtbo modem odm oem product radio recovery system vbmeta vendor"
+ partitions="boot bootloader dtbo modem odm oem product radio recovery system vbmeta vendor vendor_dlkm"
COMPREPLY=( $(compgen -W "$partitions" -- $cur) )
else
_fastboot_util_complete_local_file "${cur}" '!*.img'
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index 86cf30d..4ca6a6a 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -166,6 +166,10 @@
"vendor_boot.img", "vendor_boot.sig",
"vendor_boot",
true, ImageType::BootCritical },
+ { "vendor_dlkm",
+ "vendor_dlkm.img", "vendor_dlkm.sig",
+ "vendor_dlkm",
+ true, ImageType::Normal },
{ nullptr, "vendor_other.img", "vendor.sig", "vendor", true, ImageType::Normal },
// clang-format on
};
diff --git a/init/README.md b/init/README.md
index 188f19b..c3b64f6 100644
--- a/init/README.md
+++ b/init/README.md
@@ -197,11 +197,14 @@
Currently defaults to root. (??? probably should default to nobody)
`interface <interface name> <instance name>`
-> Associates this service with a list of the HIDL services that it provides. The interface name
- must be a fully-qualified name and not a value name. For instance, this is used to allow
- hwservicemanager to lazily start services. When multiple interfaces are served, this tag should
- be used multiple times.
- For example: interface vendor.foo.bar@1.0::IBaz default
+> Associates this service with a list of the AIDL or HIDL services that it provides. The interface
+ name must be a fully-qualified name and not a value name. For instance, this is used to allow
+ servicemanager or hwservicemanager to lazily start services. When multiple interfaces are served,
+ this tag should be used multiple times. An example of an entry for a HIDL
+ interface is `interface vendor.foo.bar@1.0::IBaz default`. For an AIDL interface, use
+ `interface aidl <instance name>`. The instance name for an AIDL interface is
+ whatever is registered with servicemanager, and these can be listed with `adb
+ shell dumpsys -l`.
`ioprio <class> <priority>`
> Sets the IO priority and IO priority class for this service via the SYS_ioprio_set syscall.
diff --git a/init/property_service.cpp b/init/property_service.cpp
index b593b62..0c4a3c4 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -632,9 +632,10 @@
char *key, *value, *eol, *sol, *tmp, *fn;
size_t flen = 0;
- static constexpr const char* const kVendorPathPrefixes[2] = {
+ static constexpr const char* const kVendorPathPrefixes[3] = {
"/vendor",
"/odm",
+ "/vendor_dlkm",
};
const char* context = kInitContext;
@@ -939,6 +940,7 @@
load_properties_from_file("/vendor/default.prop", nullptr, &properties);
// }
load_properties_from_file("/vendor/build.prop", nullptr, &properties);
+ load_properties_from_file("/vendor_dlkm/etc/build.prop", nullptr, &properties);
load_properties_from_partition("odm", /* support_legacy_path_until */ 28);
load_properties_from_partition("product", /* support_legacy_path_until */ 30);
diff --git a/liblog/properties.cpp b/liblog/properties.cpp
index f5e060c..2392112 100644
--- a/liblog/properties.cpp
+++ b/liblog/properties.cpp
@@ -474,36 +474,7 @@
}
bool __android_logger_valid_buffer_size(unsigned long value) {
- static long pages, pagesize;
- unsigned long maximum;
-
- if ((value < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < value)) {
- return false;
- }
-
- if (!pages) {
- pages = sysconf(_SC_PHYS_PAGES);
- }
- if (pages < 1) {
- return true;
- }
-
- if (!pagesize) {
- pagesize = sysconf(_SC_PAGESIZE);
- if (pagesize <= 1) {
- pagesize = PAGE_SIZE;
- }
- }
-
- /* maximum memory impact a somewhat arbitrary ~3% */
- pages = (pages + 31) / 32;
- maximum = pages * pagesize;
-
- if ((maximum < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < maximum)) {
- return true;
- }
-
- return value <= maximum;
+ return LOG_BUFFER_MIN_SIZE <= value && value <= LOG_BUFFER_MAX_SIZE;
}
struct cache2_property_size {
diff --git a/libpixelflinger/include/pixelflinger/format.h b/libpixelflinger/include/pixelflinger/format.h
index 82eeca4..d429477 100644
--- a/libpixelflinger/include/pixelflinger/format.h
+++ b/libpixelflinger/include/pixelflinger/format.h
@@ -82,7 +82,7 @@
GGL_INDEX_CR = 2,
};
-typedef struct {
+typedef struct GGLFormat {
#ifdef __cplusplus
enum {
ALPHA = GGL_INDEX_ALPHA,
diff --git a/libutils/Android.bp b/libutils/Android.bp
index 9bd15c6..022dedf 100644
--- a/libutils/Android.bp
+++ b/libutils/Android.bp
@@ -248,6 +248,7 @@
"LruCache_test.cpp",
"Mutex_test.cpp",
"SharedBuffer_test.cpp",
+ "Singleton_test.cpp",
"String8_test.cpp",
"String16_test.cpp",
"StrongPointer_test.cpp",
@@ -284,6 +285,11 @@
},
},
+ data_libs: [
+ "libutils_test_singleton1",
+ "libutils_test_singleton2",
+ ],
+
cflags: [
"-Wall",
"-Wextra",
@@ -294,29 +300,10 @@
test_suites: ["device-tests"],
}
-// TODO: the test infrastructure isn't yet capable of running this,
-// so it's broken out into its own test so that the main libutils_tests
-// can be in presubmit even if this can't.
-
-cc_test {
- name: "libutils_singleton_test",
- srcs: ["Singleton_test.cpp"],
- cflags: [
- "-Wall",
- "-Werror",
- ],
- shared_libs: ["libbase"],
-
- required: [
- ":libutils_test_singleton1",
- ":libutils_test_singleton2",
- ],
-}
-
cc_test_library {
name: "libutils_test_singleton1",
host_supported: true,
- relative_install_path: "libutils_test",
+ installable: false,
srcs: ["Singleton_test1.cpp"],
cflags: [
"-Wall",
@@ -327,7 +314,7 @@
cc_test_library {
name: "libutils_test_singleton2",
host_supported: true,
- relative_install_path: "libutils_test",
+ installable: false,
srcs: ["Singleton_test2.cpp"],
cflags: [
"-Wall",
diff --git a/libutils/String8.cpp b/libutils/String8.cpp
index d00e39c..c837891 100644
--- a/libutils/String8.cpp
+++ b/libutils/String8.cpp
@@ -424,7 +424,7 @@
char* buf = lockBuffer(len);
buf += start;
while (length > 0) {
- *buf = tolower(*buf);
+ *buf = static_cast<char>(tolower(*buf));
buf++;
length--;
}
@@ -448,7 +448,7 @@
char* buf = lockBuffer(len);
buf += start;
while (length > 0) {
- *buf = toupper(*buf);
+ *buf = static_cast<char>(toupper(*buf));
buf++;
length--;
}
diff --git a/libutils/include/utils/BitSet.h b/libutils/include/utils/BitSet.h
index 8abfb1a..0fb1a6a 100644
--- a/libutils/include/utils/BitSet.h
+++ b/libutils/include/utils/BitSet.h
@@ -21,9 +21,12 @@
#include <utils/TypeHelpers.h>
/*
- * Contains some bit manipulation helpers.
+ * A class to provide efficient manipulation of bitsets.
*
- * DO NOT USE: std::bitset<32> or std::bitset<64> preferred
+ * Consider using std::bitset<32> or std::bitset<64> if all you want is a class to do basic bit
+ * manipulation (i.e. AND / OR / XOR / flip / etc). These classes are only needed if you want to
+ * efficiently perform operations like finding the first set bit in a bitset and you want to
+ * avoid using the built-in functions (e.g. __builtin_clz) on std::bitset::to_ulong.
*/
namespace android {
@@ -46,7 +49,9 @@
// Returns the number of marked bits in the set.
inline uint32_t count() const { return count(value); }
- static inline uint32_t count(uint32_t value) { return __builtin_popcountl(value); }
+ static inline uint32_t count(uint32_t value) {
+ return static_cast<uint32_t>(__builtin_popcountl(value));
+ }
// Returns true if the bit set does not contain any marked bits.
inline bool isEmpty() const { return isEmpty(value); }
@@ -128,7 +133,7 @@
}
static inline uint32_t getIndexOfBit(uint32_t value, uint32_t n) {
- return __builtin_popcountl(value & ~(0xffffffffUL >> n));
+ return static_cast<uint32_t>(__builtin_popcountl(value & ~(0xffffffffUL >> n)));
}
inline bool operator== (const BitSet32& other) const { return value == other.value; }
@@ -153,17 +158,17 @@
// input, which is only guaranteed to be 16b, not 32. The compiler should optimize this away.
static inline uint32_t clz_checked(uint32_t value) {
if (sizeof(unsigned int) == sizeof(uint32_t)) {
- return __builtin_clz(value);
+ return static_cast<uint32_t>(__builtin_clz(value));
} else {
- return __builtin_clzl(value);
+ return static_cast<uint32_t>(__builtin_clzl(value));
}
}
static inline uint32_t ctz_checked(uint32_t value) {
if (sizeof(unsigned int) == sizeof(uint32_t)) {
- return __builtin_ctz(value);
+ return static_cast<uint32_t>(__builtin_ctz(value));
} else {
- return __builtin_ctzl(value);
+ return static_cast<uint32_t>(__builtin_ctzl(value));
}
}
};
@@ -188,7 +193,9 @@
// Returns the number of marked bits in the set.
inline uint32_t count() const { return count(value); }
- static inline uint32_t count(uint64_t value) { return __builtin_popcountll(value); }
+ static inline uint32_t count(uint64_t value) {
+ return static_cast<uint32_t>(__builtin_popcountll(value));
+ }
// Returns true if the bit set does not contain any marked bits.
inline bool isEmpty() const { return isEmpty(value); }
@@ -219,26 +226,32 @@
// Result is undefined if all bits are unmarked.
inline uint32_t firstMarkedBit() const { return firstMarkedBit(value); }
- static inline uint32_t firstMarkedBit(uint64_t value) { return __builtin_clzll(value); }
+ static inline uint32_t firstMarkedBit(uint64_t value) {
+ return static_cast<uint32_t>(__builtin_clzll(value));
+ }
// Finds the first unmarked bit in the set.
// Result is undefined if all bits are marked.
inline uint32_t firstUnmarkedBit() const { return firstUnmarkedBit(value); }
- static inline uint32_t firstUnmarkedBit(uint64_t value) { return __builtin_clzll(~ value); }
+ static inline uint32_t firstUnmarkedBit(uint64_t value) {
+ return static_cast<uint32_t>(__builtin_clzll(~value));
+ }
// Finds the last marked bit in the set.
// Result is undefined if all bits are unmarked.
inline uint32_t lastMarkedBit() const { return lastMarkedBit(value); }
- static inline uint32_t lastMarkedBit(uint64_t value) { return 63 - __builtin_ctzll(value); }
+ static inline uint32_t lastMarkedBit(uint64_t value) {
+ return static_cast<uint32_t>(63 - __builtin_ctzll(value));
+ }
// Finds the first marked bit in the set and clears it. Returns the bit index.
// Result is undefined if all bits are unmarked.
inline uint32_t clearFirstMarkedBit() { return clearFirstMarkedBit(value); }
static inline uint32_t clearFirstMarkedBit(uint64_t& value) {
- uint64_t n = firstMarkedBit(value);
+ uint32_t n = firstMarkedBit(value);
clearBit(value, n);
return n;
}
@@ -248,7 +261,7 @@
inline uint32_t markFirstUnmarkedBit() { return markFirstUnmarkedBit(value); }
static inline uint32_t markFirstUnmarkedBit(uint64_t& value) {
- uint64_t n = firstUnmarkedBit(value);
+ uint32_t n = firstUnmarkedBit(value);
markBit(value, n);
return n;
}
@@ -258,7 +271,7 @@
inline uint32_t clearLastMarkedBit() { return clearLastMarkedBit(value); }
static inline uint32_t clearLastMarkedBit(uint64_t& value) {
- uint64_t n = lastMarkedBit(value);
+ uint32_t n = lastMarkedBit(value);
clearBit(value, n);
return n;
}
@@ -268,7 +281,7 @@
inline uint32_t getIndexOfBit(uint32_t n) const { return getIndexOfBit(value, n); }
static inline uint32_t getIndexOfBit(uint64_t value, uint32_t n) {
- return __builtin_popcountll(value & ~(0xffffffffffffffffULL >> n));
+ return static_cast<uint32_t>(__builtin_popcountll(value & ~(0xffffffffffffffffULL >> n)));
}
inline bool operator== (const BitSet64& other) const { return value == other.value; }
diff --git a/logd/LogBufferElement.cpp b/logd/LogBufferElement.cpp
index dd779f9..26affa8 100644
--- a/logd/LogBufferElement.cpp
+++ b/logd/LogBufferElement.cpp
@@ -99,6 +99,10 @@
}
LogStatisticsElement LogBufferElement::ToLogStatisticsElement() const {
+ // Estimate the size of this element in the parent std::list<> by adding two void*'s
+ // corresponding to the next/prev pointers and aligning to 64 bit.
+ uint16_t element_in_list_size =
+ (sizeof(*this) + 2 * sizeof(void*) + sizeof(uint64_t) - 1) & -sizeof(uint64_t);
return LogStatisticsElement{
.uid = uid(),
.pid = pid(),
@@ -109,6 +113,7 @@
.msg_len = msg_len(),
.dropped_count = dropped_count(),
.log_id = log_id(),
+ .total_len = static_cast<uint16_t>(element_in_list_size + msg_len()),
};
}
diff --git a/logd/LogBufferTest.h b/logd/LogBufferTest.h
index 5d57ad1..1fd22c2 100644
--- a/logd/LogBufferTest.h
+++ b/logd/LogBufferTest.h
@@ -87,6 +87,6 @@
LogReaderList reader_list_;
LogTags tags_;
PruneList prune_;
- LogStatistics stats_{false};
+ LogStatistics stats_{false, true};
std::unique_ptr<LogBuffer> log_buffer_;
};
diff --git a/logd/LogStatistics.cpp b/logd/LogStatistics.cpp
index 3cd8fde..1705d48 100644
--- a/logd/LogStatistics.cpp
+++ b/logd/LogStatistics.cpp
@@ -27,6 +27,7 @@
#include <list>
+#include <android-base/logging.h>
#include <private/android_logger.h>
#include "LogBufferElement.h"
@@ -60,7 +61,8 @@
return std::string(msg, len);
}
-LogStatistics::LogStatistics(bool enable_statistics) : enable(enable_statistics) {
+LogStatistics::LogStatistics(bool enable_statistics, bool track_total_size)
+ : enable(enable_statistics), track_total_size_(track_total_size) {
log_time now(CLOCK_REALTIME);
log_id_for_each(id) {
mSizes[id] = 0;
@@ -113,10 +115,15 @@
++mElementsTotal[log_id];
}
-void LogStatistics::Add(const LogStatisticsElement& element) {
+void LogStatistics::Add(LogStatisticsElement element) {
auto lock = std::lock_guard{lock_};
+
+ if (!track_total_size_) {
+ element.total_len = element.msg_len;
+ }
+
log_id_t log_id = element.log_id;
- uint16_t size = element.msg_len;
+ uint16_t size = element.total_len;
mSizes[log_id] += size;
++mElements[log_id];
@@ -184,10 +191,15 @@
}
}
-void LogStatistics::Subtract(const LogStatisticsElement& element) {
+void LogStatistics::Subtract(LogStatisticsElement element) {
auto lock = std::lock_guard{lock_};
+
+ if (!track_total_size_) {
+ element.total_len = element.msg_len;
+ }
+
log_id_t log_id = element.log_id;
- uint16_t size = element.msg_len;
+ uint16_t size = element.total_len;
mSizes[log_id] -= size;
--mElements[log_id];
if (element.dropped_count) {
@@ -230,7 +242,9 @@
// Atomically set an entry to drop
// entry->setDropped(1) must follow this call, caller should do this explicitly.
-void LogStatistics::Drop(const LogStatisticsElement& element) {
+void LogStatistics::Drop(LogStatisticsElement element) {
+ CHECK_EQ(element.dropped_count, 0U);
+
auto lock = std::lock_guard{lock_};
log_id_t log_id = element.log_id;
uint16_t size = element.msg_len;
@@ -265,6 +279,43 @@
tagNameTable.Subtract(TagNameKey(element), element);
}
+void LogStatistics::Erase(LogStatisticsElement element) {
+ CHECK_GT(element.dropped_count, 0U);
+ CHECK_EQ(element.msg_len, 0U);
+
+ auto lock = std::lock_guard{lock_};
+
+ if (!track_total_size_) {
+ element.total_len = 0;
+ }
+
+ log_id_t log_id = element.log_id;
+ --mElements[log_id];
+ --mDroppedElements[log_id];
+ mSizes[log_id] -= element.total_len;
+
+ uidTable[log_id].Erase(element.uid, element);
+ if (element.uid == AID_SYSTEM) {
+ pidSystemTable[log_id].Erase(element.pid, element);
+ }
+
+ if (!enable) {
+ return;
+ }
+
+ pidTable.Erase(element.pid, element);
+ tidTable.Erase(element.tid, element);
+
+ uint32_t tag = element.tag;
+ if (tag) {
+ if (log_id == LOG_ID_SECURITY) {
+ securityTagTable.Erase(tag, element);
+ } else {
+ tagTable.Erase(tag, element);
+ }
+ }
+}
+
const char* LogStatistics::UidToName(uid_t uid) const {
auto lock = std::lock_guard{lock_};
return UidToNameLocked(uid);
@@ -876,12 +927,20 @@
if (els) {
oldLength = output.length();
if (spaces < 0) spaces = 0;
- // estimate the std::list overhead.
- static const size_t overhead =
- ((sizeof(LogBufferElement) + sizeof(uint64_t) - 1) &
- -sizeof(uint64_t)) +
- sizeof(std::list<LogBufferElement*>);
- size_t szs = mSizes[id] + els * overhead;
+ size_t szs = 0;
+ if (overhead_[id]) {
+ szs = *overhead_[id];
+ } else if (track_total_size_) {
+ szs = mSizes[id];
+ } else {
+ // Legacy fallback for Chatty without track_total_size_
+ // Estimate the size of this element in the parent std::list<> by adding two void*'s
+ // corresponding to the next/prev pointers and aligning to 64 bit.
+ static const size_t overhead =
+ (sizeof(LogBufferElement) + 2 * sizeof(void*) + sizeof(uint64_t) - 1) &
+ -sizeof(uint64_t);
+ szs = mSizes[id] + els * overhead;
+ }
totalSize += szs;
output += android::base::StringPrintf("%*s%zu", spaces, "", szs);
spaces -= output.length() - oldLength;
diff --git a/logd/LogStatistics.h b/logd/LogStatistics.h
index 5f55802..d440a8c 100644
--- a/logd/LogStatistics.h
+++ b/logd/LogStatistics.h
@@ -57,6 +57,7 @@
uint16_t msg_len;
uint16_t dropped_count;
log_id_t log_id;
+ uint16_t total_len;
};
template <typename TKey, typename TEntry>
@@ -172,6 +173,13 @@
}
}
+ void Erase(const TKey& key, const LogStatisticsElement& element) {
+ iterator it = map.find(key);
+ if (it != map.end()) {
+ it->second.Erase(element);
+ }
+ }
+
iterator begin() { return map.begin(); }
const_iterator begin() const { return map.begin(); }
iterator end() { return map.end(); }
@@ -181,15 +189,17 @@
class EntryBase {
public:
EntryBase() : size_(0) {}
- explicit EntryBase(const LogStatisticsElement& element) : size_(element.msg_len) {}
+ explicit EntryBase(const LogStatisticsElement& element) : size_(element.total_len) {}
size_t getSizes() const { return size_; }
- void Add(const LogStatisticsElement& element) { size_ += element.msg_len; }
+ void Add(const LogStatisticsElement& element) { size_ += element.total_len; }
bool Subtract(const LogStatisticsElement& element) {
- size_ -= element.msg_len;
- return !size_;
+ size_ -= element.total_len;
+ return size_ == 0;
}
+ void Drop(const LogStatisticsElement& element) { size_ -= element.msg_len; }
+ void Erase(const LogStatisticsElement& element) { size_ -= element.total_len; }
static constexpr size_t PRUNED_LEN = 14;
static constexpr size_t TOTAL_LEN = 80;
@@ -229,11 +239,11 @@
}
bool Subtract(const LogStatisticsElement& element) {
dropped_ -= element.dropped_count;
- return EntryBase::Subtract(element) && !dropped_;
+ return EntryBase::Subtract(element) && dropped_ == 0;
}
void Drop(const LogStatisticsElement& element) {
dropped_ += 1;
- EntryBase::Subtract(element);
+ EntryBase::Drop(element);
}
private:
@@ -505,20 +515,23 @@
}
public:
- explicit LogStatistics(bool enable_statistics);
+ LogStatistics(bool enable_statistics, bool track_total_size);
void AddTotal(log_id_t log_id, uint16_t size) 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 LogStatisticsElement& entry) EXCLUDES(lock_);
- // Correct for coalescing two entries referencing dropped content
- void Erase(const LogStatisticsElement& element) EXCLUDES(lock_) {
- auto lock = std::lock_guard{lock_};
- log_id_t log_id = element.log_id;
- --mElements[log_id];
- --mDroppedElements[log_id];
- }
+
+ // Add is for adding an element to the log buffer. It may be a chatty element in the case of
+ // log deduplication. Add the total size of the element to statistics.
+ void Add(LogStatisticsElement entry) EXCLUDES(lock_);
+ // Subtract is for removing an element from the log buffer. It may be a chatty element.
+ // Subtract the total size of the element from statistics.
+ void Subtract(LogStatisticsElement entry) EXCLUDES(lock_);
+ // Drop is for converting a normal element into a chatty element. entry->setDropped(1) must
+ // follow this call. Subtract only msg_len from statistics, since a chatty element will remain.
+ void Drop(LogStatisticsElement entry) EXCLUDES(lock_);
+ // Erase is for coalescing two chatty elements into one. Erase() is called on the element that
+ // is removed from the log buffer. Subtract the total size of the element, which is by
+ // definition only the size of the LogBufferElement + list overhead for chatty elements.
+ void Erase(LogStatisticsElement element) EXCLUDES(lock_);
void WorstTwoUids(log_id id, size_t threshold, int* worst, size_t* worst_sizes,
size_t* second_worst_sizes) const EXCLUDES(lock_);
@@ -533,6 +546,9 @@
// Snapshot of the sizes for a given log buffer.
size_t Sizes(log_id_t id) const EXCLUDES(lock_) {
auto lock = std::lock_guard{lock_};
+ if (overhead_[id]) {
+ return *overhead_[id];
+ }
return mSizes[id];
}
// TODO: Get rid of this entirely.
@@ -546,6 +562,11 @@
uid_t PidToUid(pid_t pid) EXCLUDES(lock_);
const char* UidToName(uid_t uid) const EXCLUDES(lock_);
+ void set_overhead(log_id_t id, size_t size) {
+ auto lock = std::lock_guard{lock_};
+ overhead_[id] = size;
+ }
+
private:
template <typename TKey, typename TEntry>
void WorstTwoWithThreshold(const LogHashtable<TKey, TEntry>& table, size_t threshold,
@@ -559,4 +580,7 @@
const char* UidToNameLocked(uid_t uid) const REQUIRES(lock_);
mutable std::mutex lock_;
+ bool track_total_size_;
+
+ std::optional<size_t> overhead_[LOG_ID_MAX] GUARDED_BY(lock_);
};
diff --git a/logd/README.property b/logd/README.property
index ab9c4d4..1d7d990 100644
--- a/logd/README.property
+++ b/logd/README.property
@@ -52,6 +52,9 @@
log.tag.<tag> string persist The <tag> specific logging level.
persist.log.tag.<tag> string build default for log.tag.<tag>
+logd.buffer_type string (empty) Set the log buffer type. Current choices are 'simple',
+ 'chatty', or 'serialized'. Defaults to 'chatty' if empty.
+
NB:
- auto - managed by /init
- bool+ - "true", "false" and comma separated list of "eng" (forced false if
diff --git a/logd/SerializedLogBuffer.cpp b/logd/SerializedLogBuffer.cpp
index 0f30794..a626d30 100644
--- a/logd/SerializedLogBuffer.cpp
+++ b/logd/SerializedLogBuffer.cpp
@@ -32,12 +32,6 @@
Init();
}
-SerializedLogBuffer::~SerializedLogBuffer() {
- if (deleter_thread_.joinable()) {
- deleter_thread_.join();
- }
-}
-
void SerializedLogBuffer::Init() {
log_id_for_each(i) {
if (SetSize(i, __android_logger_get_buffer_size(i))) {
@@ -109,69 +103,27 @@
}
void SerializedLogBuffer::MaybePrune(log_id_t log_id) {
- auto get_total_size = [](const auto& buffer) {
- size_t total_size = 0;
- for (const auto& chunk : buffer) {
- total_size += chunk.PruneSize();
- }
- return total_size;
- };
- size_t total_size = get_total_size(logs_[log_id]);
+ size_t total_size = GetSizeUsed(log_id);
+ size_t after_size = total_size;
if (total_size > max_size_[log_id]) {
Prune(log_id, total_size - max_size_[log_id], 0);
+ after_size = GetSizeUsed(log_id);
LOG(INFO) << "Pruned Logs from log_id: " << log_id << ", previous size: " << total_size
- << " after size: " << get_total_size(logs_[log_id]);
+ << " after size: " << after_size;
}
+
+ stats_->set_overhead(log_id, after_size);
}
-void SerializedLogBuffer::StartDeleterThread() {
- if (deleter_thread_running_) {
- return;
+void SerializedLogBuffer::RemoveChunkFromStats(log_id_t log_id, SerializedLogChunk& chunk) {
+ chunk.IncReaderRefCount();
+ int read_offset = 0;
+ while (read_offset < chunk.write_offset()) {
+ auto* entry = chunk.log_entry(read_offset);
+ stats_->Subtract(entry->ToLogStatisticsElement(log_id));
+ read_offset += entry->total_len();
}
- if (deleter_thread_.joinable()) {
- deleter_thread_.join();
- }
- auto new_thread = std::thread([this] { DeleterThread(); });
- deleter_thread_.swap(new_thread);
- deleter_thread_running_ = true;
-}
-
-// Decompresses the chunks, call LogStatistics::Subtract() on each entry, then delete the chunks and
-// the list. Note that the SerializedLogChunk objects have been removed from logs_ and their
-// references have been deleted from any SerializedFlushToState objects, so this can be safely done
-// without holding lock_. It is done in a separate thread to avoid delaying the writer thread.
-void SerializedLogBuffer::DeleterThread() {
- prctl(PR_SET_NAME, "logd.deleter");
- while (true) {
- std::list<SerializedLogChunk> local_chunks_to_delete;
- log_id_t log_id;
- {
- auto lock = std::lock_guard{lock_};
- log_id_for_each(i) {
- if (!chunks_to_delete_[i].empty()) {
- local_chunks_to_delete = std::move(chunks_to_delete_[i]);
- chunks_to_delete_[i].clear();
- log_id = i;
- break;
- }
- }
- if (local_chunks_to_delete.empty()) {
- deleter_thread_running_ = false;
- return;
- }
- }
-
- for (auto& chunk : local_chunks_to_delete) {
- chunk.IncReaderRefCount();
- int read_offset = 0;
- while (read_offset < chunk.write_offset()) {
- auto* entry = chunk.log_entry(read_offset);
- stats_->Subtract(entry->ToLogStatisticsElement(log_id));
- read_offset += entry->total_len();
- }
- chunk.DecReaderRefCount(false);
- }
- }
+ chunk.DecReaderRefCount(false);
}
void SerializedLogBuffer::NotifyReadersOfPrune(
@@ -197,8 +149,6 @@
}
}
- StartDeleterThread();
-
auto& log_buffer = logs_[log_id];
auto it = log_buffer.begin();
while (it != log_buffer.end()) {
@@ -206,7 +156,7 @@
break;
}
- // Increment ahead of time since we're going to splice this iterator from the list.
+ // Increment ahead of time since we're going to erase this iterator from the list.
auto it_to_prune = it++;
// The sequence number check ensures that all readers have read all logs in this chunk, but
@@ -222,8 +172,8 @@
}
} else {
size_t buffer_size = it_to_prune->PruneSize();
- chunks_to_delete_[log_id].splice(chunks_to_delete_[log_id].end(), log_buffer,
- it_to_prune);
+ RemoveChunkFromStats(log_id, *it_to_prune);
+ log_buffer.erase(it_to_prune);
if (buffer_size >= bytes_to_free) {
return true;
}
@@ -349,19 +299,22 @@
return Prune(id, ULONG_MAX, uid);
}
+unsigned long SerializedLogBuffer::GetSizeUsed(log_id_t id) {
+ size_t total_size = 0;
+ for (const auto& chunk : logs_[id]) {
+ total_size += chunk.PruneSize();
+ }
+ return total_size;
+}
+
unsigned long SerializedLogBuffer::GetSize(log_id_t id) {
auto lock = std::lock_guard{lock_};
- size_t retval = 2 * max_size_[id] / 3; // See the comment in SetSize().
- return retval;
+ return max_size_[id];
}
// New SerializedLogChunk objects will be allocated according to the new size, but older one are
// unchanged. MaybePrune() is called on the log buffer to reduce it to an appropriate size if the
// new size is lower.
-// ChattyLogBuffer/SimpleLogBuffer don't consider the 'Overhead' of LogBufferElement or the
-// std::list<> overhead as part of the log size. SerializedLogBuffer does by its very nature, so
-// the 'size' metric is not compatible between them. Their actual memory usage is between 1.5x and
-// 2x of what they claim to use, so we conservatively set our internal size as size + size / 2.
int SerializedLogBuffer::SetSize(log_id_t id, unsigned long size) {
// Reasonable limits ...
if (!__android_logger_valid_buffer_size(size)) {
@@ -369,7 +322,7 @@
}
auto lock = std::lock_guard{lock_};
- max_size_[id] = size + size / 2;
+ max_size_[id] = size;
MaybePrune(id);
diff --git a/logd/SerializedLogBuffer.h b/logd/SerializedLogBuffer.h
index 421d419..a03050e 100644
--- a/logd/SerializedLogBuffer.h
+++ b/logd/SerializedLogBuffer.h
@@ -37,7 +37,6 @@
class SerializedLogBuffer final : public LogBuffer {
public:
SerializedLogBuffer(LogReaderList* reader_list, LogTags* tags, LogStatistics* stats);
- ~SerializedLogBuffer();
void Init() override;
int Log(log_id_t log_id, log_time realtime, uid_t uid, pid_t pid, pid_t tid, const char* msg,
@@ -61,9 +60,8 @@
REQUIRES_SHARED(lock_);
void NotifyReadersOfPrune(log_id_t log_id, const std::list<SerializedLogChunk>::iterator& chunk)
REQUIRES(reader_list_->reader_threads_lock());
-
- void StartDeleterThread() REQUIRES(lock_);
- void DeleterThread();
+ void RemoveChunkFromStats(log_id_t log_id, SerializedLogChunk& chunk);
+ unsigned long GetSizeUsed(log_id_t id) REQUIRES(lock_);
LogReaderList* reader_list_;
LogTags* tags_;
@@ -73,9 +71,5 @@
std::list<SerializedLogChunk> logs_[LOG_ID_MAX] GUARDED_BY(lock_);
RwLock lock_;
- std::list<SerializedLogChunk> chunks_to_delete_[LOG_ID_MAX] GUARDED_BY(lock_);
- std::thread deleter_thread_ GUARDED_BY(lock_);
- bool deleter_thread_running_ GUARDED_BY(lock_) = false;
-
std::atomic<uint64_t> sequence_ = 1;
};
diff --git a/logd/SerializedLogChunk.h b/logd/SerializedLogChunk.h
index 65a1e86..50bae63 100644
--- a/logd/SerializedLogChunk.h
+++ b/logd/SerializedLogChunk.h
@@ -44,7 +44,9 @@
// If this buffer has been compressed, we only consider its compressed size when accounting for
// memory consumption for pruning. This is since the uncompressed log is only by used by
// readers, and thus not a representation of how much these logs cost to keep in memory.
- size_t PruneSize() const { return compressed_log_.size() ?: contents_.size(); }
+ size_t PruneSize() const {
+ return sizeof(*this) + (compressed_log_.size() ?: contents_.size());
+ }
void FinishWriting() {
writer_active_ = false;
diff --git a/logd/SerializedLogChunkTest.cpp b/logd/SerializedLogChunkTest.cpp
index 6572503..2b478a3 100644
--- a/logd/SerializedLogChunkTest.cpp
+++ b/logd/SerializedLogChunkTest.cpp
@@ -27,7 +27,7 @@
TEST(SerializedLogChunk, smoke) {
size_t chunk_size = 10 * 4096;
auto chunk = SerializedLogChunk{chunk_size};
- EXPECT_EQ(chunk_size, chunk.PruneSize());
+ EXPECT_EQ(chunk_size + sizeof(SerializedLogChunk), chunk.PruneSize());
static const char log_message[] = "log message";
size_t expected_total_len = sizeof(SerializedLogEntry) + sizeof(log_message);
@@ -58,7 +58,7 @@
size_t individual_message_size = sizeof(SerializedLogEntry) + sizeof(log_message);
size_t chunk_size = individual_message_size * 3;
auto chunk = SerializedLogChunk{chunk_size};
- EXPECT_EQ(chunk_size, chunk.PruneSize());
+ EXPECT_EQ(chunk_size + sizeof(SerializedLogChunk), chunk.PruneSize());
ASSERT_TRUE(chunk.CanLog(individual_message_size));
EXPECT_NE(nullptr, chunk.Log(1, log_time(), 1000, 1, 1, log_message, sizeof(log_message)));
diff --git a/logd/SerializedLogEntry.h b/logd/SerializedLogEntry.h
index f599abe..2f2c244 100644
--- a/logd/SerializedLogEntry.h
+++ b/logd/SerializedLogEntry.h
@@ -59,6 +59,7 @@
.msg_len = msg_len(),
.dropped_count = 0,
.log_id = log_id,
+ .total_len = total_len(),
};
}
diff --git a/logd/fuzz/log_buffer_log_fuzzer.cpp b/logd/fuzz/log_buffer_log_fuzzer.cpp
index 1dc996c..8309f95 100644
--- a/logd/fuzz/log_buffer_log_fuzzer.cpp
+++ b/logd/fuzz/log_buffer_log_fuzzer.cpp
@@ -114,7 +114,7 @@
LogReaderList reader_list;
LogTags tags;
PruneList prune_list;
- LogStatistics stats(true);
+ LogStatistics stats(true, true);
std::unique_ptr<LogBuffer> log_buffer;
#ifdef FUZZ_SERIALIZED
log_buffer.reset(new SerializedLogBuffer(&reader_list, &tags, &stats));
diff --git a/logd/main.cpp b/logd/main.cpp
index e1ec52b..897e11e 100644
--- a/logd/main.cpp
+++ b/logd/main.cpp
@@ -38,6 +38,7 @@
#include <android-base/logging.h>
#include <android-base/macros.h>
+#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <cutils/android_get_control_file.h>
#include <cutils/sockets.h>
@@ -61,6 +62,8 @@
#include "SerializedLogBuffer.h"
#include "SimpleLogBuffer.h"
+using android::base::GetProperty;
+
#define KMSG_PRIORITY(PRI) \
'<', '0' + LOG_MAKEPRI(LOG_DAEMON, LOG_PRI(PRI)) / 10, \
'0' + LOG_MAKEPRI(LOG_DAEMON, LOG_PRI(PRI)) % 10, '>'
@@ -255,28 +258,33 @@
// Pruning configuration.
PruneList prune_list;
+ std::string buffer_type = GetProperty("logd.buffer_type", "chatty");
+
// Partial (required for chatty) or full logging statistics.
bool enable_full_log_statistics = __android_logger_property_get_bool(
"logd.statistics", BOOL_DEFAULT_TRUE | BOOL_DEFAULT_FLAG_PERSIST |
BOOL_DEFAULT_FLAG_ENG | BOOL_DEFAULT_FLAG_SVELTE);
- LogStatistics log_statistics(enable_full_log_statistics);
+ LogStatistics log_statistics(enable_full_log_statistics, buffer_type == "serialized");
- // Serves the purpose of managing the last logs times read on a
- // socket connection, and as a reader lock on a range of log
- // entries.
+ // Serves the purpose of managing the last logs times read on a socket connection, and as a
+ // reader lock on a range of log entries.
LogReaderList reader_list;
// LogBuffer is the object which is responsible for holding all log entries.
- LogBuffer* logBuf;
- if (true) {
- logBuf = new ChattyLogBuffer(&reader_list, &log_tags, &prune_list, &log_statistics);
+ LogBuffer* log_buffer = nullptr;
+ if (buffer_type == "chatty") {
+ log_buffer = new ChattyLogBuffer(&reader_list, &log_tags, &prune_list, &log_statistics);
+ } else if (buffer_type == "serialized") {
+ log_buffer = new SerializedLogBuffer(&reader_list, &log_tags, &log_statistics);
+ } else if (buffer_type == "simple") {
+ log_buffer = new SimpleLogBuffer(&reader_list, &log_tags, &log_statistics);
} else {
- logBuf = new SimpleLogBuffer(&reader_list, &log_tags, &log_statistics);
+ LOG(FATAL) << "buffer_type must be one of 'chatty', 'serialized', or 'simple'";
}
// LogReader listens on /dev/socket/logdr. When a client
// connects, log entries in the LogBuffer are written to the client.
- LogReader* reader = new LogReader(logBuf, &reader_list);
+ LogReader* reader = new LogReader(log_buffer, &reader_list);
if (reader->startListener()) {
return EXIT_FAILURE;
}
@@ -284,14 +292,14 @@
// LogListener listens on /dev/socket/logdw for client
// initiated log messages. New log entries are added to LogBuffer
// and LogReader is notified to send updates to connected clients.
- LogListener* swl = new LogListener(logBuf);
+ LogListener* swl = new LogListener(log_buffer);
if (!swl->StartListener()) {
return EXIT_FAILURE;
}
// Command listener listens on /dev/socket/logd for incoming logd
// administrative commands.
- CommandListener* cl = new CommandListener(logBuf, &log_tags, &prune_list, &log_statistics);
+ CommandListener* cl = new CommandListener(log_buffer, &log_tags, &prune_list, &log_statistics);
if (cl->startListener()) {
return EXIT_FAILURE;
}
@@ -304,12 +312,12 @@
int dmesg_fd = __android_logger_property_get_bool("ro.logd.auditd.dmesg", BOOL_DEFAULT_TRUE)
? fdDmesg
: -1;
- al = new LogAudit(logBuf, dmesg_fd, &log_statistics);
+ al = new LogAudit(log_buffer, dmesg_fd, &log_statistics);
}
LogKlog* kl = nullptr;
if (klogd) {
- kl = new LogKlog(logBuf, fdDmesg, fdPmesg, al != nullptr, &log_statistics);
+ kl = new LogKlog(log_buffer, fdDmesg, fdPmesg, al != nullptr, &log_statistics);
}
readDmesg(al, kl);
diff --git a/rootdir/Android.mk b/rootdir/Android.mk
index a9d0ed0..ac8e847 100644
--- a/rootdir/Android.mk
+++ b/rootdir/Android.mk
@@ -120,6 +120,17 @@
LOCAL_POST_INSTALL_CMD += ; ln -sf /vendor/odm/priv-app $(TARGET_ROOT_OUT)/odm/priv-app
LOCAL_POST_INSTALL_CMD += ; ln -sf /vendor/odm/usr $(TARGET_ROOT_OUT)/odm/usr
+
+# For /vendor_dlkm partition.
+LOCAL_POST_INSTALL_CMD += ; mkdir -p $(TARGET_ROOT_OUT)/vendor_dlkm
+# For Treble Generic System Image (GSI), system-as-root GSI needs to work on
+# both devices with and without /vendor_dlkm partition. Those symlinks are for
+# devices without /vendor_dlkm partition. For devices with /vendor_dlkm
+# partition, mount vendor_dlkm.img under /vendor_dlkm will hide those symlinks.
+# Note that /vendor_dlkm/lib is omitted because vendor DLKMs should be accessed
+# via /vendor/lib/modules directly.
+LOCAL_POST_INSTALL_CMD += ; ln -sf /vendor/vendor_dlkm/etc $(TARGET_ROOT_OUT)/vendor_dlkm/etc
+
ifdef BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE
LOCAL_POST_INSTALL_CMD += ; mkdir -p $(TARGET_ROOT_OUT)/cache
else
diff --git a/toolbox/OWNERS b/toolbox/OWNERS
index 682a067..7529cb9 100644
--- a/toolbox/OWNERS
+++ b/toolbox/OWNERS
@@ -1 +1 @@
-enh@google.com
+include platform/system/core:/janitors/OWNERS
diff --git a/trusty/utils/rpmb_dev/rpmb_dev.c b/trusty/utils/rpmb_dev/rpmb_dev.c
index af97eba..5de1efa 100644
--- a/trusty/utils/rpmb_dev/rpmb_dev.c
+++ b/trusty/utils/rpmb_dev/rpmb_dev.c
@@ -591,7 +591,7 @@
return EXIT_SUCCESS;
}
- open_flags = O_RDWR;
+ open_flags = O_RDWR | O_SYNC;
if (init) {
open_flags |= O_CREAT | O_TRUNC;
}