Merge "Revert "unique_fd: easier to forward declare""
diff --git a/Android.bp b/Android.bp
index 7167bb3..461f1db 100644
--- a/Android.bp
+++ b/Android.bp
@@ -14,6 +14,22 @@
// limitations under the License.
//
+package {
+ default_applicable_licenses: ["system_libbase_license"],
+}
+
+license {
+ name: "system_libbase_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ "SPDX-license-identifier-BSD",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_defaults {
name: "libbase_cflags_defaults",
cflags: [
@@ -163,6 +179,7 @@
"errors_test.cpp",
"expected_test.cpp",
"file_test.cpp",
+ "function_ref_test.cpp",
"logging_splitters_test.cpp",
"logging_test.cpp",
"macros_test.cpp",
diff --git a/function_ref_test.cpp b/function_ref_test.cpp
new file mode 100644
index 0000000..44194f7
--- /dev/null
+++ b/function_ref_test.cpp
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2021 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 "android-base/function_ref.h"
+
+#include <gtest/gtest.h>
+
+#include <functional>
+#include <string>
+
+namespace android::base {
+
+TEST(function_ref, Ctor) {
+ // Making sure it can be constructed in all meaningful ways
+
+ using EmptyFunc = function_ref<void()>;
+
+ EmptyFunc f1([] {});
+
+ struct Functor {
+ void operator()() const {}
+ };
+ EmptyFunc f2(Functor{});
+ Functor fctr;
+ EmptyFunc f3(fctr);
+
+ EmptyFunc f4(std::function<void()>([f1, f2, f3] {
+ (void)f1;
+ (void)f2;
+ (void)f3;
+ }));
+
+ const std::function<void()> func = [] {};
+ EmptyFunc f5(func);
+
+ static_assert(sizeof(f1) <= 2 * sizeof(void*), "Too big function_ref");
+ static_assert(sizeof(f2) <= 2 * sizeof(void*), "Too big function_ref");
+ static_assert(sizeof(f3) <= 2 * sizeof(void*), "Too big function_ref");
+ static_assert(sizeof(f4) <= 2 * sizeof(void*), "Too big function_ref");
+ static_assert(sizeof(f5) <= 2 * sizeof(void*), "Too big function_ref");
+}
+
+TEST(function_ref, Call) {
+ function_ref<int(int)> view = [](int i) { return i + 1; };
+ EXPECT_EQ(1, view(0));
+ EXPECT_EQ(-1, view(-2));
+
+ function_ref<std::string(std::string)> fs = [](const std::string& s) { return s + "1"; };
+ EXPECT_STREQ("s1", fs("s").c_str());
+ EXPECT_STREQ("ssss1", fs("ssss").c_str());
+
+ std::string base;
+ auto lambda = [&base]() { return base + "1"; };
+ function_ref<std::string()> fs2 = lambda;
+ base = "one";
+ EXPECT_STREQ("one1", fs2().c_str());
+ base = "forty two";
+ EXPECT_STREQ("forty two1", fs2().c_str());
+}
+
+TEST(function_ref, CopyAndAssign) {
+ function_ref<int(int)> view = [](int i) { return i + 1; };
+ EXPECT_EQ(1, view(0));
+ view = [](int i) { return i - 1; };
+ EXPECT_EQ(0, view(1));
+
+ function_ref<int(int)> view2 = view;
+ EXPECT_EQ(view(10), view2(10));
+
+ view = view2;
+ EXPECT_EQ(view(10), view2(10));
+}
+
+} // namespace android::base
diff --git a/include/android-base/function_ref.h b/include/android-base/function_ref.h
new file mode 100644
index 0000000..2de14e3
--- /dev/null
+++ b/include/android-base/function_ref.h
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2021 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 <stdint.h>
+#include <type_traits>
+#include <utility>
+
+namespace android::base {
+
+//
+// function_ref<> - a class that stores a reference to a callable object,
+// similar to string_view for strings.
+//
+// We need to pass around lots of callbacks. The standard way of doing it
+// is via std::function<> class, and it usually works OK. But there are some
+// noticeable drawbacks:
+//
+// 1. std::function<> in most STLs performs heap allocation for all callables
+// bigger than a single poiner to a function.
+// 2. std::function<> goes through at least two pointers + a vptr call to call
+// the stored function.
+// 3. std::function<> copies the passed object inside at least once; this also
+// means it can't work with non-copyable functors.
+//
+// function_ref is an alternative way of passing functors around. Instead of
+// storing a copy of the functor inside, it follows the path of string_view and
+// merely captures a pointer to the object to call. This allows for a simple,
+// fast and lightweight wrapper design; it also dictates the limitations:
+//
+// 1. function_ref<> stores a pointer to outside functor. That functor _must_
+// outlive the ref.
+// 2. function_ref<> has two calls through a function pointer in its call
+// operator. That's still better than std::function<>, but slower compared
+// to a raw function pointer call with a "void* opaque" context parameter.
+//
+// Limitation #1 dictates the best use case: a function parameter type for some
+// generic callback which doesn't get stored inside an object field but only
+// gets called in this call. E.g.:
+//
+// void someLongOperation(function_ref<void(int progress)> onProgress) {
+// firstStep(onProgress);
+// ...
+// onProgress(50);
+// ...
+// lastStep(onProgress);
+// onProgress(100);
+// }
+//
+// In this code std::function<> is an overkill as the whole use of |onProgresss|
+// callback is scoped and easy to track. An alternative design - making it a
+// template parameter (template <class Callback> ... (Callback onProgress))
+// forces one to put someLongOperation() + some private functions into the
+// header. function_ref<> is the choice then.
+//
+// NOTE: Beware of passing temporary functions via function_ref<>! Temporaries
+// live until the end of full expression (usually till the next semicolon), and
+// having a function_ref<> that refers to a dangling pointer is a bug that's
+// hard to debug. E.g.:
+// function_ref<...> v = [](){}; // this is fine
+// function_ref<...> v = std::function<...>([](){}); // this will kill you
+//
+// NOTE2: function_ref<> should not have an empty state, but it doesn't have a
+// runtime check against that. Don't construct it from a null function!
+
+template <class Signature>
+class function_ref;
+
+template <class Ret, class... Args>
+class function_ref<Ret(Args...)> final {
+ public:
+ constexpr function_ref() noexcept = delete;
+ constexpr function_ref(const function_ref& other) noexcept = default;
+ constexpr function_ref& operator=(const function_ref&) noexcept = default;
+
+ template <class Callable, class = std::enable_if_t<
+ std::is_invocable_r<Ret, Callable, Args...>::value &&
+ !std::is_same_v<function_ref, std::remove_reference_t<Callable>>>>
+ function_ref(Callable&& c) noexcept
+ : mTypeErasedFunction([](const function_ref* self, Args... args) -> Ret {
+ // Generate a lambda that remembers the type of the passed
+ // |Callable|.
+ return (*reinterpret_cast<std::remove_reference_t<Callable>*>(self->mCallable))(
+ std::forward<Args>(args)...);
+ }),
+ mCallable(reinterpret_cast<intptr_t>(&c)) {}
+
+ template <class Callable, class = std::enable_if_t<
+ std::is_invocable_r<Ret, Callable, Args...>::value &&
+ !std::is_same_v<function_ref, std::remove_reference_t<Callable>>>>
+ function_ref& operator=(Callable&& c) noexcept {
+ mTypeErasedFunction = [](const function_ref* self, Args... args) -> Ret {
+ // Generate a lambda that remembers the type of the passed
+ // |Callable|.
+ return (*reinterpret_cast<std::remove_reference_t<Callable>*>(self->mCallable))(
+ std::forward<Args>(args)...);
+ };
+ mCallable = reinterpret_cast<intptr_t>(&c);
+ return *this;
+ }
+
+ Ret operator()(Args... args) const {
+ return mTypeErasedFunction(this, std::forward<Args>(args)...);
+ }
+
+ private:
+ using TypeErasedFunc = Ret(const function_ref*, Args...);
+ TypeErasedFunc* mTypeErasedFunction;
+ intptr_t mCallable;
+};
+
+} // namespace android::base
diff --git a/include/android-base/logging.h b/include/android-base/logging.h
index 9064075..179ddf0 100644
--- a/include/android-base/logging.h
+++ b/include/android-base/logging.h
@@ -27,6 +27,8 @@
// LOG(INFO) << "Some text; " << some_value;
//
// Replace `INFO` with any severity from `enum LogSeverity`.
+// Most devices filter out VERBOSE logs by default, run
+// `adb shell setprop log.tag.<TAG> V` to see them in adb logcat.
//
// To log the result of a failed function and include the string
// representation of `errno` at the end:
diff --git a/include/android-base/properties.h b/include/android-base/properties.h
index 0f208ec..021f466 100644
--- a/include/android-base/properties.h
+++ b/include/android-base/properties.h
@@ -97,8 +97,8 @@
};
#endif
-static inline int TimeoutMultiplier() {
- return android::base::GetIntProperty("ro.timeout_multiplier", 1);
+static inline int HwTimeoutMultiplier() {
+ return android::base::GetIntProperty("ro.hw_timeout_multiplier", 1);
}
} // namespace base
diff --git a/include/android-base/silent_death_test.h b/include/android-base/silent_death_test.h
new file mode 100644
index 0000000..2aec890
--- /dev/null
+++ b/include/android-base/silent_death_test.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2014 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 <signal.h>
+
+#include <gtest/gtest.h>
+
+#if !defined(__BIONIC__)
+#define sigaction64 sigaction
+#endif
+
+// Disables debuggerd stack traces to speed up death tests and make them less
+// noisy in logcat.
+//
+// Use `using my_DeathTest = SilentDeathTest;` instead of inheriting from
+// testing::Test yourself.
+class SilentDeathTest : public testing::Test {
+ protected:
+ virtual void SetUp() {
+ // Suppress debuggerd stack traces. Too slow.
+ for (int signo : {SIGABRT, SIGBUS, SIGSEGV, SIGSYS}) {
+ struct sigaction64 action = {.sa_handler = SIG_DFL};
+ sigaction64(signo, &action, &previous_);
+ }
+ }
+
+ virtual void TearDown() {
+ for (int signo : {SIGABRT, SIGBUS, SIGSEGV, SIGSYS}) {
+ sigaction64(signo, &previous_, nullptr);
+ }
+ }
+
+ private:
+ struct sigaction64 previous_;
+};
diff --git a/logging.cpp b/logging.cpp
index 54f3fcc..4942e2f 100644
--- a/logging.cpp
+++ b/logging.cpp
@@ -32,10 +32,6 @@
#include <errno.h>
#endif
-#if defined(__linux__)
-#include <sys/uio.h>
-#endif
-
#include <atomic>
#include <iostream>
#include <limits>
@@ -255,20 +251,22 @@
int level = kLogSeverityToKernelLogLevel[severity];
- // The kernel's printk buffer is only 1024 bytes.
- // TODO: should we automatically break up long lines into multiple lines?
- // Or we could log but with something like "..." at the end?
- char buf[1024] __attribute__((__uninitialized__));
+ // The kernel's printk buffer is only |1024 - PREFIX_MAX| bytes, where
+ // PREFIX_MAX could be 48 or 32.
+ // Reference: kernel/printk/printk.c
+ static constexpr int LOG_LINE_MAX = 1024 - 48;
+ char buf[LOG_LINE_MAX] __attribute__((__uninitialized__));
size_t size = snprintf(buf, sizeof(buf), "<%d>%s: %.*s\n", level, tag, length, msg);
- if (size > sizeof(buf)) {
- size = snprintf(buf, sizeof(buf), "<%d>%s: %zu-byte message too long for printk\n",
- level, tag, size);
- }
+ TEMP_FAILURE_RETRY(write(klog_fd, buf, std::min(size, sizeof(buf))));
- iovec iov[1];
- iov[0].iov_base = buf;
- iov[0].iov_len = size;
- TEMP_FAILURE_RETRY(writev(klog_fd, iov, 1));
+ if (size > sizeof(buf)) {
+ size_t truncated = size - sizeof(buf);
+ size = snprintf(
+ buf, sizeof(buf),
+ "<%d>%s: **previous message missing %zu bytes** %zu-byte message too long for printk\n",
+ level, tag, truncated, size);
+ TEMP_FAILURE_RETRY(write(klog_fd, buf, std::min(size, sizeof(buf))));
+ }
}
void KernelLogger(android::base::LogId, android::base::LogSeverity severity, const char* tag,