libbase: update from upstream

Followed instructions from go/nnapi-dep-instructions.

No manual changes / interventions have been made.

$ git merge cros/upstream/master --no-ff
$ repo upload --cbr . --no-verify

BUG=b:197814725
TEST=cq passes

Change-Id: Idd0474acff423a60ebad4cbcc2b0443ce7cf612f
diff --git a/Android.bp b/Android.bp
index 524ff65..0d32885 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: [
@@ -64,7 +80,7 @@
         "chrono_utils.cpp",
         "cmsg.cpp",
         "file.cpp",
-        "liblog_symbols.cpp",
+        "hex.cpp",
         "logging.cpp",
         "mapped_file.cpp",
         "parsebool.cpp",
@@ -164,6 +180,8 @@
         "errors_test.cpp",
         "expected_test.cpp",
         "file_test.cpp",
+        "function_ref_test.cpp",
+        "hex_test.cpp",
         "logging_splitters_test.cpp",
         "logging_test.cpp",
         "macros_test.cpp",
@@ -199,6 +217,7 @@
     },
     local_include_dirs: ["."],
     shared_libs: ["libbase"],
+    static_libs: ["libgmock"],
     compile_multilib: "both",
     multilib: {
         lib32: {
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/hex.cpp b/hex.cpp
new file mode 100644
index 0000000..a4b7715
--- /dev/null
+++ b/hex.cpp
@@ -0,0 +1,42 @@
+/*
+ * 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/hex.h"
+
+#include "android-base/logging.h"
+
+namespace android {
+namespace base {
+
+std::string HexString(const void* bytes, size_t len) {
+  CHECK(bytes != nullptr || len == 0) << bytes << " " << len;
+
+  // b/132916539: Doing this the 'C way', std::setfill triggers ubsan implicit conversion
+  const uint8_t* bytes8 = static_cast<const uint8_t*>(bytes);
+  const char chars[] = "0123456789abcdef";
+  std::string result;
+  result.resize(len * 2);
+
+  for (size_t i = 0; i < len; i++) {
+    result[2 * i] = chars[bytes8[i] >> 4];
+    result[2 * i + 1] = chars[bytes8[i] & 0xf];
+  }
+
+  return result;
+}
+
+}  // namespace base
+}  // namespace android
diff --git a/hex_test.cpp b/hex_test.cpp
new file mode 100644
index 0000000..ebf798c
--- /dev/null
+++ b/hex_test.cpp
@@ -0,0 +1,49 @@
+/*
+ * 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/hex.h"
+
+#include <gtest/gtest.h>
+
+TEST(hex, empty) {
+  ASSERT_EQ("", android::base::HexString(nullptr, 0));
+  ASSERT_EQ("", android::base::HexString(reinterpret_cast<void*>(int32_t(0)), 0));
+}
+
+TEST(hex, short) {
+  const int32_t kShortData = 0xDEADBEEF;
+  ASSERT_EQ("ef", android::base::HexString(&kShortData, 1));
+  ASSERT_EQ("efbe", android::base::HexString(&kShortData, 2));
+  ASSERT_EQ("efbead", android::base::HexString(&kShortData, 3));
+  ASSERT_EQ("efbeadde", android::base::HexString(&kShortData, 4));
+}
+
+TEST(hex, all) {
+  constexpr size_t kSize = 256;
+  uint8_t kLongData[kSize];
+  for (size_t i = 0; i < kSize; i++) {
+    kLongData[i] = i;
+  }
+
+  ASSERT_EQ(
+      "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d"
+      "2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b"
+      "5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f80818283848586878889"
+      "8a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7"
+      "b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5"
+      "e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff",
+      android::base::HexString(&kLongData, kSize));
+}
diff --git a/include/android-base/endian.h b/include/android-base/endian.h
index 8fa6365..b47494b 100644
--- a/include/android-base/endian.h
+++ b/include/android-base/endian.h
@@ -25,18 +25,19 @@
 
 #include <sys/endian.h>
 
-#elif defined(__GLIBC__)
+#elif defined(__GLIBC__) || defined(ANDROID_HOST_MUSL)
 
-/* glibc's <endian.h> is like bionic's <sys/endian.h>. */
+/* glibc and musl's <endian.h> are like bionic's <sys/endian.h>. */
 #include <endian.h>
 
-/* glibc keeps htons and htonl in <netinet/in.h>. */
+/* glibc and musl keep htons and htonl in <netinet/in.h>. */
 #include <netinet/in.h>
 
-/* glibc doesn't have the 64-bit variants. */
+/* glibc and musl don't have the 64-bit variants. */
 #define htonq(x) htobe64(x)
 #define ntohq(x) be64toh(x)
 
+#if defined(__GLIBC__)
 /* glibc has different names to BSD for these. */
 #define betoh16(x) be16toh(x)
 #define betoh32(x) be32toh(x)
@@ -44,6 +45,7 @@
 #define letoh16(x) le16toh(x)
 #define letoh32(x) le32toh(x)
 #define letoh64(x) le64toh(x)
+#endif
 
 #else
 
diff --git a/include/android-base/expected.h b/include/android-base/expected.h
index 11cf1ac..3b9d45f 100644
--- a/include/android-base/expected.h
+++ b/include/android-base/expected.h
@@ -37,7 +37,7 @@
 //
 // void test() {
 //   auto q = safe_divide(10, 0);
-//   if (q) { printf("%f\n", q.value()); }
+//   if (q.ok()) { printf("%f\n", q.value()); }
 //   else { printf("%s\n", q.error().c_str()); }
 // }
 //
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/hex.h b/include/android-base/hex.h
new file mode 100644
index 0000000..cbb26a8
--- /dev/null
+++ b/include/android-base/hex.h
@@ -0,0 +1,31 @@
+/*
+ * 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 <string>
+
+namespace android {
+namespace base {
+
+// Converts binary data into a hexString.
+//
+// Hex values are printed in order, e.g. 0xDEAD will result in 'adde' because
+// Android is little-endian.
+std::string HexString(const void* bytes, size_t len);
+
+}  // namespace base
+}  // namespace android
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 8b34573..021f466 100644
--- a/include/android-base/properties.h
+++ b/include/android-base/properties.h
@@ -97,6 +97,10 @@
 };
 #endif
 
+static inline int HwTimeoutMultiplier() {
+  return android::base::GetIntProperty("ro.hw_timeout_multiplier", 1);
+}
+
 } // namespace base
 } // namespace android
 
diff --git a/include/android-base/result-gmock.h b/include/android-base/result-gmock.h
new file mode 100644
index 0000000..1fd9f00
--- /dev/null
+++ b/include/android-base/result-gmock.h
@@ -0,0 +1,101 @@
+/*
+ * 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 <android-base/result.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+/*
+ * Matchers for android::base::Result<T> that produces human-readable test results.
+ *
+ * Example:
+ *
+ * Result<int> result = ...
+ *
+ * using namespace ::android::base::testing;
+ * using namespace ::testing;
+ *
+ * EXPECT_THAT(result, Ok());
+ * EXPECT_THAT(result, Not(Ok()));
+ * EXPECT_THAT(result, HasValue(5));
+ * EXPECT_THAT(result, HasError(WithCode(EBADF)));
+ * EXPECT_THAT(result, HasError(WithMessageMessage("expected error message")));
+ *
+ * // Advance usage
+ * EXPECT_THAT(result, AnyOf(Ok(), HasError(WithCode(EACCES)));
+ * EXPECT_THAT(result, HasError(WithCode(AnyOf(EBADF, EACCES))) << "Unexpected code from library";
+ */
+
+namespace android::base {
+
+template <typename T>
+inline void PrintTo(const Result<T>& result, std::ostream* os) {
+  if (result.ok()) {
+    *os << "OK: " << ::testing::PrintToString(result.value());
+  } else {
+    *os << "Error: " << result.error();
+  }
+}
+
+template <>
+inline void PrintTo(const Result<void>& result, std::ostream* os) {
+  if (result.ok()) {
+    *os << "OK";
+  } else {
+    *os << "Error: " << result.error();
+  }
+}
+
+namespace testing {
+
+MATCHER(Ok, "") {
+  if (arg.ok()) {
+    *result_listener << "result is OK";
+    return true;
+  }
+  *result_listener << "error is " << arg.error();
+  return false;
+}
+
+MATCHER_P(HasValue, value_matcher, "") {
+  if (arg.ok()) {
+    return ::testing::ExplainMatchResult(value_matcher, arg.value(), result_listener);
+  }
+  *result_listener << "error is " << arg.error();
+  return false;
+}
+
+MATCHER_P(HasError, error_matcher, "") {
+  if (!arg.ok()) {
+    return ::testing::ExplainMatchResult(error_matcher, arg.error(), result_listener);
+  }
+  *result_listener << "result is OK";
+  return false;
+}
+
+MATCHER_P(WithCode, code_matcher, "") {
+  *result_listener << "actual error is " << arg;
+  return ::testing::ExplainMatchResult(code_matcher, arg.code(), result_listener);
+}
+
+MATCHER_P(WithMessage, message_matcher, "") {
+  *result_listener << "actual error is " << arg;
+  return ::testing::ExplainMatchResult(message_matcher, arg.message(), result_listener);
+}
+
+}  // namespace testing
+}  // namespace android::base
diff --git a/include/android-base/result.h b/include/android-base/result.h
index 56a4f3e..acec791 100644
--- a/include/android-base/result.h
+++ b/include/android-base/result.h
@@ -210,6 +210,7 @@
 
 // Macros for testing the results of functions that return android::base::Result.
 // These also work with base::android::expected.
+// For advanced matchers and customized error messages, see result-gtest.h.
 
 #define CHECK_RESULT_OK(stmt)       \
   do {                              \
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/include/android-base/unique_fd.h b/include/android-base/unique_fd.h
index 9ceb5db..e929e4c 100644
--- a/include/android-base/unique_fd.h
+++ b/include/android-base/unique_fd.h
@@ -20,19 +20,25 @@
 #include <errno.h>
 #include <fcntl.h>
 
-#if !defined(_WIN32)
-#include <sys/socket.h>
-#endif
-
 #include <stdio.h>
 #include <sys/types.h>
 #include <unistd.h>
 
-// DO NOT INCLUDE OTHER LIBBASE HEADERS!
+// DO NOT INCLUDE OTHER LIBBASE HEADERS HERE!
 // This file gets used in libbinder, and libbinder is used everywhere.
 // Including other headers from libbase frequently results in inclusion of
 // android-base/macros.h, which causes macro collisions.
 
+#if defined(__BIONIC__)
+#include <android/fdsan.h>
+#endif
+#if !defined(_WIN32)
+#include <sys/socket.h>
+#endif
+
+namespace android {
+namespace base {
+
 // Container for a file descriptor that automatically closes the descriptor as
 // it goes out of scope.
 //
@@ -43,47 +49,14 @@
 //
 //      return 0; // Descriptor is closed for you.
 //
+// See also the Pipe()/Socketpair()/Fdopen()/Fdopendir() functions in this file
+// that provide interoperability with the libc functions with the same (but
+// lowercase) names.
+//
 // unique_fd is also known as ScopedFd/ScopedFD/scoped_fd; mentioned here to help
 // you find this class if you're searching for one of those names.
-
-#if defined(__BIONIC__)
-#include <android/fdsan.h>
-#endif
-
-namespace android {
-namespace base {
-
-struct DefaultCloser {
-#if defined(__BIONIC__)
-  static void Tag(int fd, void* old_addr, void* new_addr) {
-    if (android_fdsan_exchange_owner_tag) {
-      uint64_t old_tag = android_fdsan_create_owner_tag(ANDROID_FDSAN_OWNER_TYPE_UNIQUE_FD,
-                                                        reinterpret_cast<uint64_t>(old_addr));
-      uint64_t new_tag = android_fdsan_create_owner_tag(ANDROID_FDSAN_OWNER_TYPE_UNIQUE_FD,
-                                                        reinterpret_cast<uint64_t>(new_addr));
-      android_fdsan_exchange_owner_tag(fd, old_tag, new_tag);
-    }
-  }
-  static void Close(int fd, void* addr) {
-    if (android_fdsan_close_with_tag) {
-      uint64_t tag = android_fdsan_create_owner_tag(ANDROID_FDSAN_OWNER_TYPE_UNIQUE_FD,
-                                                    reinterpret_cast<uint64_t>(addr));
-      android_fdsan_close_with_tag(fd, tag);
-    } else {
-      close(fd);
-    }
-  }
-#else
-  static void Close(int fd) {
-    // Even if close(2) fails with EINTR, the fd will have been closed.
-    // Using TEMP_FAILURE_RETRY will either lead to EBADF or closing someone
-    // else's fd.
-    // http://lkml.indiana.edu/hypermail/linux/kernel/0509.1/0877.html
-    ::close(fd);
-  }
-#endif
-};
-
+//
+// unique_fd itself is a specialization of unique_fd_impl with a default closer.
 template <typename Closer>
 class unique_fd_impl final {
  public:
@@ -175,11 +148,48 @@
   }
 };
 
+// The actual details of closing are factored out to support unusual cases.
+// Almost everyone will want this DefaultCloser, which handles fdsan on bionic.
+struct DefaultCloser {
+#if defined(__BIONIC__)
+  static void Tag(int fd, void* old_addr, void* new_addr) {
+    if (android_fdsan_exchange_owner_tag) {
+      uint64_t old_tag = android_fdsan_create_owner_tag(ANDROID_FDSAN_OWNER_TYPE_UNIQUE_FD,
+                                                        reinterpret_cast<uint64_t>(old_addr));
+      uint64_t new_tag = android_fdsan_create_owner_tag(ANDROID_FDSAN_OWNER_TYPE_UNIQUE_FD,
+                                                        reinterpret_cast<uint64_t>(new_addr));
+      android_fdsan_exchange_owner_tag(fd, old_tag, new_tag);
+    }
+  }
+  static void Close(int fd, void* addr) {
+    if (android_fdsan_close_with_tag) {
+      uint64_t tag = android_fdsan_create_owner_tag(ANDROID_FDSAN_OWNER_TYPE_UNIQUE_FD,
+                                                    reinterpret_cast<uint64_t>(addr));
+      android_fdsan_close_with_tag(fd, tag);
+    } else {
+      close(fd);
+    }
+  }
+#else
+  static void Close(int fd) {
+    // Even if close(2) fails with EINTR, the fd will have been closed.
+    // Using TEMP_FAILURE_RETRY will either lead to EBADF or closing someone
+    // else's fd.
+    // http://lkml.indiana.edu/hypermail/linux/kernel/0509.1/0877.html
+    ::close(fd);
+  }
+#endif
+};
+
 using unique_fd = unique_fd_impl<DefaultCloser>;
 
 #if !defined(_WIN32)
 
 // Inline functions, so that they can be used header-only.
+
+// See pipe(2).
+// This helper hides the details of converting to unique_fd, and also hides the
+// fact that macOS doesn't support O_CLOEXEC or O_NONBLOCK directly.
 template <typename Closer>
 inline bool Pipe(unique_fd_impl<Closer>* read, unique_fd_impl<Closer>* write,
                  int flags = O_CLOEXEC) {
@@ -218,6 +228,8 @@
   return true;
 }
 
+// See socketpair(2).
+// This helper hides the details of converting to unique_fd.
 template <typename Closer>
 inline bool Socketpair(int domain, int type, int protocol, unique_fd_impl<Closer>* left,
                        unique_fd_impl<Closer>* right) {
@@ -230,11 +242,14 @@
   return true;
 }
 
+// See socketpair(2).
+// This helper hides the details of converting to unique_fd.
 template <typename Closer>
 inline bool Socketpair(int type, unique_fd_impl<Closer>* left, unique_fd_impl<Closer>* right) {
   return Socketpair(AF_UNIX, type, 0, left, right);
 }
 
+// See fdopen(3).
 // Using fdopen with unique_fd correctly is more annoying than it should be,
 // because fdopen doesn't close the file descriptor received upon failure.
 inline FILE* Fdopen(unique_fd&& ufd, const char* mode) {
@@ -246,6 +261,7 @@
   return file;
 }
 
+// See fdopendir(3).
 // Using fdopendir with unique_fd correctly is more annoying than it should be,
 // because fdopen doesn't close the file descriptor received upon failure.
 inline DIR* Fdopendir(unique_fd&& ufd) {
@@ -259,7 +275,20 @@
 
 #endif  // !defined(_WIN32)
 
-// A wrapper type that can be implicitly constructed from either int or unique_fd.
+// A wrapper type that can be implicitly constructed from either int or
+// unique_fd. This supports cases where you don't actually own the file
+// descriptor, and can't take ownership, but are temporarily acting as if
+// you're the owner.
+//
+// One example would be a function that needs to also allow
+// STDERR_FILENO, not just a newly-opened fd. Another example would be JNI code
+// that's using a file descriptor that's actually owned by a
+// ParcelFileDescriptor or whatever on the Java side, but where the JNI code
+// would like to enforce this weaker sense of "temporary ownership".
+//
+// If you think of unique_fd as being like std::string in that represents
+// ownership, borrowed_fd is like std::string_view (and int is like const
+// char*).
 struct borrowed_fd {
   /* implicit */ borrowed_fd(int fd) : fd_(fd) {}  // NOLINT
   template <typename T>
diff --git a/liblog_symbols.cpp b/liblog_symbols.cpp
deleted file mode 100644
index 2e4ab3e..0000000
--- a/liblog_symbols.cpp
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (C) 2020 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 "liblog_symbols.h"
-
-// __ANDROID_APEX_MIN_SDK_VERSION__ is the max of all the minSdkVersions that
-// this module shares an APEX with. In other words, this is the lowest OS
-// version that this code could possibly run on.
-#if defined(__ANDROID_APEX_MIN_SDK_VERSION__) && (__ANDROID_APEX_MIN_SDK_VERSION__ <= 29)
-#define USE_DLSYM
-#endif
-
-// __ANDROID_API__ is the historical name for __ANDROID_MIN_SDK_VERSION__. The
-// latter is not set by the Clang we're currently using. This path will be used
-// when this code is built by NDK modules rather than APEX modules.
-#if defined(__ANDROID_API__) && (__ANDROID_API__ <= 29)
-#define USE_DLSYM
-#endif
-
-#ifdef USE_DLSYM
-#include <dlfcn.h>
-#endif
-
-namespace android {
-namespace base {
-
-#ifdef USE_DLSYM
-
-const std::optional<LibLogFunctions>& GetLibLogFunctions() {
-  static std::optional<LibLogFunctions> liblog_functions = []() -> std::optional<LibLogFunctions> {
-    void* liblog_handle = dlopen("liblog.so", RTLD_NOW);
-    if (liblog_handle == nullptr) {
-      return {};
-    }
-
-    LibLogFunctions real_liblog_functions = {};
-
-#define DLSYM(name)                                                                   \
-  real_liblog_functions.name =                                                        \
-      reinterpret_cast<decltype(LibLogFunctions::name)>(dlsym(liblog_handle, #name)); \
-  if (real_liblog_functions.name == nullptr) {                                        \
-    return {};                                                                        \
-  }
-
-    DLSYM(__android_log_set_logger)
-    DLSYM(__android_log_write_log_message)
-    DLSYM(__android_log_logd_logger)
-    DLSYM(__android_log_stderr_logger)
-    DLSYM(__android_log_set_aborter)
-    DLSYM(__android_log_call_aborter)
-    DLSYM(__android_log_default_aborter)
-    DLSYM(__android_log_set_minimum_priority);
-    DLSYM(__android_log_get_minimum_priority);
-    DLSYM(__android_log_set_default_tag);
-#undef DLSYM
-
-    return real_liblog_functions;
-  }();
-
-  return liblog_functions;
-}
-
-#else
-
-const std::optional<LibLogFunctions>& GetLibLogFunctions() {
-  static std::optional<LibLogFunctions> liblog_functions = []() -> std::optional<LibLogFunctions> {
-    return LibLogFunctions{
-        .__android_log_set_logger = __android_log_set_logger,
-        .__android_log_write_log_message = __android_log_write_log_message,
-        .__android_log_logd_logger = __android_log_logd_logger,
-        .__android_log_stderr_logger = __android_log_stderr_logger,
-        .__android_log_set_aborter = __android_log_set_aborter,
-        .__android_log_call_aborter = __android_log_call_aborter,
-        .__android_log_default_aborter = __android_log_default_aborter,
-        .__android_log_set_minimum_priority = __android_log_set_minimum_priority,
-        .__android_log_get_minimum_priority = __android_log_get_minimum_priority,
-        .__android_log_set_default_tag = __android_log_set_default_tag,
-    };
-  }();
-  return liblog_functions;
-}
-
-#endif
-
-}  // namespace base
-}  // namespace android
diff --git a/liblog_symbols.h b/liblog_symbols.h
deleted file mode 100644
index 2e6b47f..0000000
--- a/liblog_symbols.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2020 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 <optional>
-
-#include <android/log.h>
-
-namespace android {
-namespace base {
-
-struct LibLogFunctions {
-  void (*__android_log_set_logger)(__android_logger_function logger);
-  void (*__android_log_write_log_message)(struct __android_log_message* log_message);
-
-  void (*__android_log_logd_logger)(const struct __android_log_message* log_message);
-  void (*__android_log_stderr_logger)(const struct __android_log_message* log_message);
-
-  void (*__android_log_set_aborter)(__android_aborter_function aborter);
-  void (*__android_log_call_aborter)(const char* abort_message);
-  void (*__android_log_default_aborter)(const char* abort_message);
-  int32_t (*__android_log_set_minimum_priority)(int32_t priority);
-  int32_t (*__android_log_get_minimum_priority)();
-  void (*__android_log_set_default_tag)(const char* tag);
-};
-
-const std::optional<LibLogFunctions>& GetLibLogFunctions();
-
-}  // namespace base
-}  // namespace android
diff --git a/logging.cpp b/logging.cpp
index d6ecc78..d36126a 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>
@@ -60,18 +56,15 @@
 #include <android-base/strings.h>
 #include <android-base/threads.h>
 
-#include "liblog_symbols.h"
 #include "logging_splitters.h"
 
 namespace android {
 namespace base {
 
 // BSD-based systems like Android/macOS have getprogname(). Others need us to provide one.
-#if defined(__GLIBC__) || defined(_WIN32)
+#if !defined(__APPLE__) && !defined(__BIONIC__)
 static const char* getprogname() {
-#if defined(__GLIBC__)
-  return program_invocation_short_name;
-#elif defined(_WIN32)
+#ifdef _WIN32
   static bool first = true;
   static char progname[MAX_PATH] = {};
 
@@ -82,6 +75,8 @@
   }
 
   return progname;
+#else
+  return program_invocation_short_name;
 #endif
 }
 #endif
@@ -214,9 +209,8 @@
 static std::string* gDefaultTag;
 
 void SetDefaultTag(const std::string& tag) {
-  static auto& liblog_functions = GetLibLogFunctions();
-  if (liblog_functions) {
-    liblog_functions->__android_log_set_default_tag(tag.c_str());
+  if (__builtin_available(android 30, *)) {
+    __android_log_set_default_tag(tag.c_str());
   } else {
     std::lock_guard<std::recursive_mutex> lock(TagLock());
     if (gDefaultTag != nullptr) {
@@ -257,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,
@@ -318,11 +314,10 @@
   int32_t lg_id = LogIdTolog_id_t(id);
   int32_t priority = LogSeverityToPriority(severity);
 
-  static auto& liblog_functions = GetLibLogFunctions();
-  if (liblog_functions) {
+  if (__builtin_available(android 30, *)) {
     __android_log_message log_message = {sizeof(__android_log_message),     lg_id, priority, tag,
                                          static_cast<const char*>(nullptr), 0,     message};
-    liblog_functions->__android_log_logd_logger(&log_message);
+    __android_log_logd_logger(&log_message);
   } else {
     __android_log_buf_print(lg_id, priority, tag, "%s", message);
   }
@@ -401,9 +396,8 @@
   LogFunction old_logger = std::move(Logger());
   Logger() = std::move(logger);
 
-  static auto& liblog_functions = GetLibLogFunctions();
-  if (liblog_functions) {
-    liblog_functions->__android_log_set_logger([](const struct __android_log_message* log_message) {
+  if (__builtin_available(android 30, *)) {
+    __android_log_set_logger([](const struct __android_log_message* log_message) {
       auto log_id = log_id_tToLogId(log_message->buffer_id);
       auto severity = PriorityToLogSeverity(log_message->priority);
 
@@ -418,10 +412,8 @@
   AbortFunction old_aborter = std::move(Aborter());
   Aborter() = std::move(aborter);
 
-  static auto& liblog_functions = GetLibLogFunctions();
-  if (liblog_functions) {
-    liblog_functions->__android_log_set_aborter(
-        [](const char* abort_message) { Aborter()(abort_message); });
+  if (__builtin_available(android 30, *)) {
+    __android_log_set_aborter([](const char* abort_message) { Aborter()(abort_message); });
   }
   return old_aborter;
 }
@@ -508,9 +500,8 @@
 
   // Abort if necessary.
   if (data_->GetSeverity() == FATAL) {
-    static auto& liblog_functions = GetLibLogFunctions();
-    if (liblog_functions) {
-      liblog_functions->__android_log_call_aborter(msg.c_str());
+    if (__builtin_available(android 30, *)) {
+      __android_log_call_aborter(msg.c_str());
     } else {
       Aborter()(msg.c_str());
     }
@@ -523,12 +514,11 @@
 
 void LogMessage::LogLine(const char* file, unsigned int line, LogSeverity severity, const char* tag,
                          const char* message) {
-  static auto& liblog_functions = GetLibLogFunctions();
   int32_t priority = LogSeverityToPriority(severity);
-  if (liblog_functions) {
+  if (__builtin_available(android 30, *)) {
     __android_log_message log_message = {
         sizeof(__android_log_message), LOG_ID_DEFAULT, priority, tag, file, line, message};
-    liblog_functions->__android_log_write_log_message(&log_message);
+    __android_log_write_log_message(&log_message);
   } else {
     if (tag == nullptr) {
       std::lock_guard<std::recursive_mutex> lock(TagLock());
@@ -544,20 +534,18 @@
 }
 
 LogSeverity GetMinimumLogSeverity() {
-  static auto& liblog_functions = GetLibLogFunctions();
-  if (liblog_functions) {
-    return PriorityToLogSeverity(liblog_functions->__android_log_get_minimum_priority());
+  if (__builtin_available(android 30, *)) {
+    return PriorityToLogSeverity(__android_log_get_minimum_priority());
   } else {
     return gMinimumLogSeverity;
   }
 }
 
 bool ShouldLog(LogSeverity severity, const char* tag) {
-  static auto& liblog_functions = GetLibLogFunctions();
   // Even though we're not using the R liblog functions in this function, if we're running on Q,
   // we need to fall back to using gMinimumLogSeverity, since __android_log_is_loggable() will not
   // take into consideration the value from SetMinimumLogSeverity().
-  if (liblog_functions) {
+  if (__builtin_available(android 30, *)) {
     int32_t priority = LogSeverityToPriority(severity);
     return __android_log_is_loggable(priority, tag, ANDROID_LOG_INFO);
   } else {
@@ -566,10 +554,9 @@
 }
 
 LogSeverity SetMinimumLogSeverity(LogSeverity new_severity) {
-  static auto& liblog_functions = GetLibLogFunctions();
-  if (liblog_functions) {
+  if (__builtin_available(android 30, *)) {
     int32_t priority = LogSeverityToPriority(new_severity);
-    return PriorityToLogSeverity(liblog_functions->__android_log_set_minimum_priority(priority));
+    return PriorityToLogSeverity(__android_log_set_minimum_priority(priority));
   } else {
     LogSeverity old_severity = gMinimumLogSeverity;
     gMinimumLogSeverity = new_severity;
diff --git a/result_test.cpp b/result_test.cpp
index c0ac0fd..88eb658 100644
--- a/result_test.cpp
+++ b/result_test.cpp
@@ -21,9 +21,17 @@
 #include <istream>
 #include <string>
 
+#include <gmock/gmock.h>
 #include <gtest/gtest.h>
 
+#include "android-base/result-gmock.h"
+
 using namespace std::string_literals;
+using ::testing::Eq;
+using ::testing::ExplainMatchResult;
+using ::testing::HasSubstr;
+using ::testing::Not;
+using ::testing::StartsWith;
 
 namespace android {
 namespace base {
@@ -418,5 +426,99 @@
             outer.error().message());
 }
 
+namespace testing {
+
+class Listener : public ::testing::MatchResultListener {
+ public:
+  Listener() : MatchResultListener(&ss_) {}
+  ~Listener() = default;
+  std::string message() const { return ss_.str(); }
+
+ private:
+  std::stringstream ss_;
+};
+
+class ResultMatchers : public ::testing::Test {
+ public:
+  Result<int> result = 1;
+  Result<int> error = Error(EBADF) << "error message";
+  Listener listener;
+};
+
+TEST_F(ResultMatchers, ok_result) {
+  EXPECT_TRUE(ExplainMatchResult(Ok(), result, &listener));
+  EXPECT_THAT(listener.message(), Eq("result is OK"));
+}
+
+TEST_F(ResultMatchers, ok_error) {
+  EXPECT_FALSE(ExplainMatchResult(Ok(), error, &listener));
+  EXPECT_THAT(listener.message(), StartsWith("error is"));
+  EXPECT_THAT(listener.message(), HasSubstr(error.error().message()));
+  EXPECT_THAT(listener.message(), HasSubstr(strerror(error.error().code())));
+}
+
+TEST_F(ResultMatchers, not_ok_result) {
+  EXPECT_FALSE(ExplainMatchResult(Not(Ok()), result, &listener));
+  EXPECT_THAT(listener.message(), Eq("result is OK"));
+}
+
+TEST_F(ResultMatchers, not_ok_error) {
+  EXPECT_TRUE(ExplainMatchResult(Not(Ok()), error, &listener));
+  EXPECT_THAT(listener.message(), StartsWith("error is"));
+  EXPECT_THAT(listener.message(), HasSubstr(error.error().message()));
+  EXPECT_THAT(listener.message(), HasSubstr(strerror(error.error().code())));
+}
+
+TEST_F(ResultMatchers, has_value_result) {
+  EXPECT_TRUE(ExplainMatchResult(HasValue(*result), result, &listener));
+}
+
+TEST_F(ResultMatchers, has_value_wrong_result) {
+  EXPECT_FALSE(ExplainMatchResult(HasValue(*result + 1), result, &listener));
+}
+
+TEST_F(ResultMatchers, has_value_error) {
+  EXPECT_FALSE(ExplainMatchResult(HasValue(*result), error, &listener));
+  EXPECT_THAT(listener.message(), StartsWith("error is"));
+  EXPECT_THAT(listener.message(), HasSubstr(error.error().message()));
+  EXPECT_THAT(listener.message(), HasSubstr(strerror(error.error().code())));
+}
+
+TEST_F(ResultMatchers, has_error_code_result) {
+  EXPECT_FALSE(ExplainMatchResult(HasError(WithCode(error.error().code())), result, &listener));
+  EXPECT_THAT(listener.message(), Eq("result is OK"));
+}
+
+TEST_F(ResultMatchers, has_error_code_wrong_code) {
+  EXPECT_FALSE(ExplainMatchResult(HasError(WithCode(error.error().code() + 1)), error, &listener));
+  EXPECT_THAT(listener.message(), StartsWith("actual error is"));
+  EXPECT_THAT(listener.message(), HasSubstr(strerror(error.error().code())));
+}
+
+TEST_F(ResultMatchers, has_error_code_correct_code) {
+  EXPECT_TRUE(ExplainMatchResult(HasError(WithCode(error.error().code())), error, &listener));
+  EXPECT_THAT(listener.message(), StartsWith("actual error is"));
+  EXPECT_THAT(listener.message(), HasSubstr(strerror(error.error().code())));
+}
+
+TEST_F(ResultMatchers, has_error_message_result) {
+  EXPECT_FALSE(
+      ExplainMatchResult(HasError(WithMessage(error.error().message())), result, &listener));
+  EXPECT_THAT(listener.message(), Eq("result is OK"));
+}
+
+TEST_F(ResultMatchers, has_error_message_wrong_message) {
+  EXPECT_FALSE(ExplainMatchResult(HasError(WithMessage("foo")), error, &listener));
+  EXPECT_THAT(listener.message(), StartsWith("actual error is"));
+  EXPECT_THAT(listener.message(), HasSubstr(error.error().message()));
+}
+
+TEST_F(ResultMatchers, has_error_message_correct_message) {
+  EXPECT_TRUE(ExplainMatchResult(HasError(WithMessage(error.error().message())), error, &listener));
+  EXPECT_THAT(listener.message(), StartsWith("actual error is"));
+  EXPECT_THAT(listener.message(), HasSubstr(error.error().message()));
+}
+
+}  // namespace testing
 }  // namespace base
 }  // namespace android